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
4a0540b8
Commit
4a0540b8
authored
Jun 06, 2002
by
Kai Germaschewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ISDN: Add support for Formula-n enter:now, a.k.a. Gerdes Power ISDN
(by Christoph Ersfeld/Karsten Keil)
parent
db72b2ad
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1382 additions
and
2 deletions
+1382
-2
Documentation/isdn/README.HiSax
Documentation/isdn/README.HiSax
+7
-1
drivers/isdn/hisax/Config.in
drivers/isdn/hisax/Config.in
+1
-0
drivers/isdn/hisax/Makefile
drivers/isdn/hisax/Makefile
+1
-0
drivers/isdn/hisax/amd7930_fn.c
drivers/isdn/hisax/amd7930_fn.c
+761
-0
drivers/isdn/hisax/amd7930_fn.h
drivers/isdn/hisax/amd7930_fn.h
+69
-0
drivers/isdn/hisax/config.c
drivers/isdn/hisax/config.c
+12
-0
drivers/isdn/hisax/enternow.h
drivers/isdn/hisax/enternow.h
+51
-0
drivers/isdn/hisax/enternow_pci.c
drivers/isdn/hisax/enternow_pci.c
+447
-0
drivers/isdn/hisax/hisax.h
drivers/isdn/hisax/hisax.h
+21
-1
drivers/isdn/hisax/netjet.c
drivers/isdn/hisax/netjet.c
+4
-0
drivers/isdn/hisax/nj_s.c
drivers/isdn/hisax/nj_s.c
+8
-0
No files found.
Documentation/isdn/README.HiSax
View file @
4a0540b8
...
...
@@ -68,6 +68,8 @@ Gazel ISDN cards
HFC-PCI based cards
Winbond W6692 based cards
HFC-S+, HFC-SP/PCMCIA cards
formula-n enternow
Gerdes Power ISDN
Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
PCC-8: not tested yet
...
...
@@ -192,6 +194,8 @@ Card types:
37 HFC 2BDS0 S+, SP irq,io
38 NETspider U PCI card none
39 HFC 2BDS0 SP/PCMCIA irq,io (set with cardmgr)
40 hotplug interface
41 Formula-n enter:now PCI none
At the moment IRQ sharing is only possible with PCI cards. Please make sure
that your IRQ is free and enabled for ISA use.
...
...
@@ -297,7 +301,9 @@ type
36 W6692 based PCI cards none
37 HFC 2BDS0 S+,SP/PCMCIA ONLY WORKS AS A MODULE !
38 NETspider U PCI card none
39 HFC 2BDS0 SP/PCMCIA ONLY WORKS AS A MODULE !
40 hotplug interface ONLY WORKS AS A MODULE !
41 Formula-n enter:now PCI none
Running the driver
------------------
...
...
drivers/isdn/hisax/Config.in
View file @
4a0540b8
...
...
@@ -43,6 +43,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
bool ' HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
# bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
bool ' Formula-n enter:now PCI card' CONFIG_HISAX_ENTERNOW_PCI
if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
bool ' Am7930' CONFIG_HISAX_AMD7930
fi
...
...
drivers/isdn/hisax/Makefile
View file @
4a0540b8
...
...
@@ -57,6 +57,7 @@ hisax-objs-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o
hisax-objs-$(CONFIG_HISAX_SCT_QUADRO)
+=
bkm_a8.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_GAZEL)
+=
gazel.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_W6692)
+=
w6692.o
hisax-objs-$(CONFIG_HISAX_ENTERNOW_PCI)
+=
enternow_pci.o amd7930_fn.o
#hisax-objs-$(CONFIG_HISAX_TESTEMU) += testemu.o
hisax-objs
+=
$
(
hisax-objs-y
)
...
...
drivers/isdn/hisax/amd7930_fn.c
0 → 100644
View file @
4a0540b8
/* gerdes_amd7930.c,v 0.99 2001/10/02
*
* gerdes_amd7930.c Amd 79C30A and 79C32A specific routines
* (based on HiSax driver by Karsten Keil)
*
* Author Christoph Ersfeld <info@formula-n.de>
* Formula-n Europe AG (www.formula-n.com)
* previously Gerdes AG
*
*
* This file is (c) under GNU PUBLIC LICENSE
*
*
* Notes:
* Version 0.99 is the first release of this driver and there are
* certainly a few bugs.
*
* Please don't report any malfunction to me without sending
* (compressed) debug-logs.
* It would be nearly impossible to retrace it.
*
* Log D-channel-processing as follows:
*
* 1. Load hisax with card-specific parameters, this example ist for
* Formula-n enter:now ISDN PCI and compatible
* (f.e. Gerdes Power ISDN PCI)
*
* modprobe hisax type=41 protocol=2 id=gerdes
*
* if you chose an other value for id, you need to modify the
* code below, too.
*
* 2. set debug-level
*
* hisaxctrl gerdes 1 0x3ff
* hisaxctrl gerdes 11 0x4f
* cat /dev/isdnctrl >> ~/log &
*
* Please take also a look into /var/log/messages if there is
* anything importand concerning HISAX.
*
*
* Credits:
* Programming the driver for Formula-n enter:now ISDN PCI and
* neccessary this driver for the used Amd 7930 D-channel-controller
* was spnsored by Formula-n Europe AG.
* Thanks to Karsten Keil and Petr Novak, who gave me support in
* Hisax-specific questions.
* I want so say special thanks to Carl-Friedrich Braun, who had to
* answer a lot of questions about generally ISDN and about handling
* of the Amd-Chip.
*
*/
#define __NO_VERSION__
#include "hisax.h"
#include "isdnl1.h"
#include "isac.h"
#include "amd7930_fn.h"
#include <linux/interrupt.h>
#include <linux/init.h>
static
void
Amd7930_new_ph
(
struct
IsdnCardState
*
cs
);
void
/* macro wWordAMD */
WriteWordAmd7930
(
struct
IsdnCardState
*
cs
,
BYTE
reg
,
WORD
val
)
{
wByteAMD
(
cs
,
0x00
,
reg
);
wByteAMD
(
cs
,
0x01
,
LOBYTE
(
val
));
wByteAMD
(
cs
,
0x01
,
HIBYTE
(
val
));
}
WORD
/* macro rWordAMD */
ReadWordAmd7930
(
struct
IsdnCardState
*
cs
,
BYTE
reg
)
{
WORD
res
;
/* direct access register */
if
(
reg
<
8
)
{
res
=
rByteAMD
(
cs
,
reg
);
res
+=
256
*
rByteAMD
(
cs
,
reg
);
}
/* indirect access register */
else
{
wByteAMD
(
cs
,
0x00
,
reg
);
res
=
rByteAMD
(
cs
,
0x01
);
res
+=
256
*
rByteAMD
(
cs
,
0x01
);
}
return
(
res
);
}
static
void
Amd7930_ph_command
(
struct
IsdnCardState
*
cs
,
u_char
command
,
char
*
s
)
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"AMD7930: %s: ph_command 0x%02X"
,
s
,
command
);
cs
->
dc
.
amd7930
.
lmr1
=
command
;
wByteAMD
(
cs
,
0xA3
,
command
);
}
static
BYTE
i430States
[]
=
{
// to reset F3 F4 F5 F6 F7 F8 AR from
0x01
,
0x02
,
0x00
,
0x00
,
0x00
,
0x07
,
0x05
,
0x00
,
// init
0x01
,
0x02
,
0x00
,
0x00
,
0x00
,
0x07
,
0x05
,
0x00
,
// reset
0x01
,
0x02
,
0x00
,
0x00
,
0x00
,
0x09
,
0x05
,
0x04
,
// F3
0x01
,
0x02
,
0x00
,
0x00
,
0x1B
,
0x00
,
0x00
,
0x00
,
// F4
0x01
,
0x02
,
0x00
,
0x00
,
0x1B
,
0x00
,
0x00
,
0x00
,
// F5
0x01
,
0x03
,
0x00
,
0x00
,
0x00
,
0x06
,
0x05
,
0x00
,
// F6
0x11
,
0x13
,
0x00
,
0x00
,
0x1B
,
0x00
,
0x15
,
0x00
,
// F7
0x01
,
0x03
,
0x00
,
0x00
,
0x00
,
0x06
,
0x00
,
0x00
,
// F8
0x01
,
0x03
,
0x00
,
0x00
,
0x00
,
0x09
,
0x00
,
0x0A
};
// AR
/* Row init - reset F3 F4 F5 F6 F7 F8 AR */
static
BYTE
stateHelper
[]
=
{
0x00
,
0x00
,
0x01
,
0x02
,
0x03
,
0x04
,
0x05
,
0x06
,
0x07
,
0x08
};
static
void
Amd7930_get_state
(
struct
IsdnCardState
*
cs
)
{
BYTE
lsr
=
rByteAMD
(
cs
,
0xA1
);
cs
->
dc
.
amd7930
.
ph_state
=
(
lsr
&
0x7
)
+
2
;
Amd7930_new_ph
(
cs
);
}
static
void
Amd7930_new_ph
(
struct
IsdnCardState
*
cs
)
{
u_char
index
=
stateHelper
[
cs
->
dc
.
amd7930
.
old_state
]
*
8
+
stateHelper
[
cs
->
dc
.
amd7930
.
ph_state
]
-
1
;
u_char
message
=
i430States
[
index
];
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"AMD7930: new_ph %d, old_ph %d, message %d, index %d"
,
cs
->
dc
.
amd7930
.
ph_state
,
cs
->
dc
.
amd7930
.
old_state
,
message
&
0x0f
,
index
);
cs
->
dc
.
amd7930
.
old_state
=
cs
->
dc
.
amd7930
.
ph_state
;
/* abort transmit if nessesary */
if
((
message
&
0xf0
)
&&
(
cs
->
tx_skb
))
{
wByteAMD
(
cs
,
0x21
,
0xC2
);
wByteAMD
(
cs
,
0x21
,
0x02
);
}
switch
(
message
&
0x0f
)
{
case
(
1
):
l1_msg
(
cs
,
HW_RESET
|
INDICATION
,
NULL
);
Amd7930_get_state
(
cs
);
break
;
case
(
2
):
/* init, Card starts in F3 */
l1_msg
(
cs
,
HW_DEACTIVATE
|
CONFIRM
,
NULL
);
break
;
case
(
3
):
l1_msg
(
cs
,
HW_DEACTIVATE
|
INDICATION
,
NULL
);
break
;
case
(
4
):
l1_msg
(
cs
,
HW_POWERUP
|
CONFIRM
,
NULL
);
Amd7930_ph_command
(
cs
,
0x50
,
"HW_ENABLE REQUEST"
);
break
;
case
(
5
):
l1_msg
(
cs
,
HW_RSYNC
|
INDICATION
,
NULL
);
break
;
case
(
6
):
l1_msg
(
cs
,
HW_INFO4_P8
|
INDICATION
,
NULL
);
break
;
case
(
7
):
/* init, Card starts in F7 */
l1_msg
(
cs
,
HW_RSYNC
|
INDICATION
,
NULL
);
l1_msg
(
cs
,
HW_INFO4_P8
|
INDICATION
,
NULL
);
break
;
case
(
8
):
l1_msg
(
cs
,
HW_POWERUP
|
CONFIRM
,
NULL
);
/* fall through */
case
(
9
):
Amd7930_ph_command
(
cs
,
0x40
,
"HW_ENABLE REQ cleared if set"
);
l1_msg
(
cs
,
HW_RSYNC
|
INDICATION
,
NULL
);
l1_msg
(
cs
,
HW_INFO2
|
INDICATION
,
NULL
);
l1_msg
(
cs
,
HW_INFO4_P8
|
INDICATION
,
NULL
);
break
;
case
(
10
):
Amd7930_ph_command
(
cs
,
0x40
,
"T3 expired, HW_ENABLE REQ cleared"
);
cs
->
dc
.
amd7930
.
old_state
=
3
;
break
;
case
(
11
):
l1_msg
(
cs
,
HW_INFO2
|
INDICATION
,
NULL
);
break
;
default:
break
;
}
}
static
void
Amd7930_bh
(
struct
IsdnCardState
*
cs
)
{
struct
PStack
*
stptr
;
if
(
!
cs
)
return
;
if
(
test_and_clear_bit
(
D_CLEARBUSY
,
&
cs
->
event
))
{
if
(
cs
->
debug
)
debugl1
(
cs
,
"Amd7930: bh, D-Channel Busy cleared"
);
stptr
=
cs
->
stlist
;
while
(
stptr
!=
NULL
)
{
stptr
->
l2
.
l1l2
(
stptr
,
PH_PAUSE
|
CONFIRM
,
NULL
);
stptr
=
stptr
->
next
;
}
}
if
(
test_and_clear_bit
(
D_L1STATECHANGE
,
&
cs
->
event
))
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"AMD7930: bh, D_L1STATECHANGE"
);
Amd7930_new_ph
(
cs
);
}
if
(
test_and_clear_bit
(
D_RCVBUFREADY
,
&
cs
->
event
))
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"AMD7930: bh, D_RCVBUFREADY"
);
DChannel_proc_rcv
(
cs
);
}
if
(
test_and_clear_bit
(
D_XMTBUFREADY
,
&
cs
->
event
))
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"AMD7930: bh, D_XMTBUFREADY"
);
DChannel_proc_xmt
(
cs
);
}
}
void
Amd7930_sched_event
(
struct
IsdnCardState
*
cs
,
int
event
)
// ok
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
{
debugl1
(
cs
,
"AMD7930: sched_event 0x%X"
,
event
);
}
test_and_set_bit
(
event
,
&
cs
->
event
);
queue_task
(
&
cs
->
tqueue
,
&
tq_immediate
);
mark_bh
(
IMMEDIATE_BH
);
}
static
void
Amd7930_empty_Dfifo
(
struct
IsdnCardState
*
cs
,
int
flag
)
{
BYTE
stat
,
der
;
BYTE
*
ptr
;
struct
sk_buff
*
skb
;
if
((
cs
->
debug
&
L1_DEB_ISAC
)
&&
!
(
cs
->
debug
&
L1_DEB_ISAC_FIFO
))
debugl1
(
cs
,
"Amd7930: empty_Dfifo"
);
ptr
=
cs
->
rcvbuf
+
cs
->
rcvidx
;
/* AMD interrupts off */
AmdIrqOff
(
cs
);
/* read D-Channel-Fifo*/
stat
=
rByteAMD
(
cs
,
0x07
);
// DSR2
/* while Data in Fifo ... */
while
(
(
stat
&
2
)
&&
((
ptr
-
cs
->
rcvbuf
)
<
MAX_DFRAME_LEN_L1
)
)
{
*
ptr
=
rByteAMD
(
cs
,
0x04
);
// DCRB
ptr
++
;
stat
=
rByteAMD
(
cs
,
0x07
);
// DSR2
cs
->
rcvidx
=
ptr
-
cs
->
rcvbuf
;
/* Paket ready? */
if
(
stat
&
1
)
{
der
=
rWordAMD
(
cs
,
0x03
);
/* no errors, packet ok */
if
(
!
der
&&
!
flag
)
{
rWordAMD
(
cs
,
0x89
);
// clear DRCR
if
((
cs
->
rcvidx
)
>
0
)
{
if
(
!
(
skb
=
alloc_skb
(
cs
->
rcvidx
,
GFP_ATOMIC
)))
printk
(
KERN_WARNING
"HiSax: Amd7930: empty_Dfifo, D receive out of memory!
\n
"
);
else
{
/* Debugging */
if
(
cs
->
debug
&
L1_DEB_ISAC_FIFO
)
{
char
*
t
=
cs
->
dlog
;
t
+=
sprintf
(
t
,
"Amd7930: empty_Dfifo cnt: %d |"
,
cs
->
rcvidx
);
QuickHex
(
t
,
cs
->
rcvbuf
,
cs
->
rcvidx
);
debugl1
(
cs
,
cs
->
dlog
);
}
/* moves recieved data in sk-buffer */
memcpy
(
skb_put
(
skb
,
cs
->
rcvidx
),
cs
->
rcvbuf
,
cs
->
rcvidx
);
skb_queue_tail
(
&
cs
->
rq
,
skb
);
}
}
}
/* throw damaged packets away, reset recieve-buffer, indicate RX */
ptr
=
cs
->
rcvbuf
;
cs
->
rcvidx
=
0
;
Amd7930_sched_event
(
cs
,
D_RCVBUFREADY
);
}
}
/* Packet to long, overflow */
if
(
cs
->
rcvidx
>=
MAX_DFRAME_LEN_L1
)
{
if
(
cs
->
debug
&
L1_DEB_WARN
)
debugl1
(
cs
,
"AMD7930: empty_Dfifo L2-Framelength overrun"
);
cs
->
rcvidx
=
0
;
return
;
}
/* AMD interrupts on */
AmdIrqOn
(
cs
);
}
static
void
Amd7930_fill_Dfifo
(
struct
IsdnCardState
*
cs
)
{
WORD
dtcrr
,
dtcrw
,
len
,
count
;
BYTE
txstat
,
dmr3
;
BYTE
*
ptr
,
*
deb_ptr
;
if
((
cs
->
debug
&
L1_DEB_ISAC
)
&&
!
(
cs
->
debug
&
L1_DEB_ISAC_FIFO
))
debugl1
(
cs
,
"Amd7930: fill_Dfifo"
);
if
((
!
cs
->
tx_skb
)
||
(
cs
->
tx_skb
->
len
<=
0
))
return
;
dtcrw
=
0
;
if
(
!
cs
->
dc
.
amd7930
.
tx_xmtlen
)
/* new Frame */
len
=
dtcrw
=
cs
->
tx_skb
->
len
;
/* continue frame */
else
len
=
cs
->
dc
.
amd7930
.
tx_xmtlen
;
/* AMD interrupts off */
AmdIrqOff
(
cs
);
deb_ptr
=
ptr
=
cs
->
tx_skb
->
data
;
/* while free place in tx-fifo available and data in sk-buffer */
txstat
=
0x10
;
while
((
txstat
&
0x10
)
&&
(
cs
->
tx_cnt
<
len
))
{
wByteAMD
(
cs
,
0x04
,
*
ptr
);
ptr
++
;
cs
->
tx_cnt
++
;
txstat
=
rByteAMD
(
cs
,
0x07
);
}
count
=
ptr
-
cs
->
tx_skb
->
data
;
skb_pull
(
cs
->
tx_skb
,
count
);
dtcrr
=
rWordAMD
(
cs
,
0x85
);
// DTCR
dmr3
=
rByteAMD
(
cs
,
0x8E
);
if
(
cs
->
debug
&
L1_DEB_ISAC
)
{
debugl1
(
cs
,
"Amd7930: fill_Dfifo, DMR3: 0x%02X, DTCR read: 0x%04X write: 0x%02X 0x%02X"
,
dmr3
,
dtcrr
,
LOBYTE
(
dtcrw
),
HIBYTE
(
dtcrw
));
}
/* writeing of dtcrw starts transmit */
if
(
!
cs
->
dc
.
amd7930
.
tx_xmtlen
)
{
wWordAMD
(
cs
,
0x85
,
dtcrw
);
cs
->
dc
.
amd7930
.
tx_xmtlen
=
dtcrw
;
}
if
(
test_and_set_bit
(
FLG_DBUSY_TIMER
,
&
cs
->
HW_Flags
))
{
debugl1
(
cs
,
"Amd7930: fill_Dfifo dbusytimer running"
);
del_timer
(
&
cs
->
dbusytimer
);
}
init_timer
(
&
cs
->
dbusytimer
);
cs
->
dbusytimer
.
expires
=
jiffies
+
((
DBUSY_TIMER_VALUE
*
HZ
)
/
1000
);
add_timer
(
&
cs
->
dbusytimer
);
if
(
cs
->
debug
&
L1_DEB_ISAC_FIFO
)
{
char
*
t
=
cs
->
dlog
;
t
+=
sprintf
(
t
,
"Amd7930: fill_Dfifo cnt: %d |"
,
count
);
QuickHex
(
t
,
deb_ptr
,
count
);
debugl1
(
cs
,
cs
->
dlog
);
}
/* AMD interrupts on */
AmdIrqOn
(
cs
);
}
void
Amd7930_interrupt
(
struct
IsdnCardState
*
cs
,
BYTE
irflags
)
{
BYTE
dsr1
,
dsr2
,
lsr
;
WORD
der
;
while
(
irflags
)
{
dsr1
=
rByteAMD
(
cs
,
0x02
);
der
=
rWordAMD
(
cs
,
0x03
);
dsr2
=
rByteAMD
(
cs
,
0x07
);
lsr
=
rByteAMD
(
cs
,
0xA1
);
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: interrupt: flags: 0x%02X, DSR1: 0x%02X, DSR2: 0x%02X, LSR: 0x%02X, DER=0x%04X"
,
irflags
,
dsr1
,
dsr2
,
lsr
,
der
);
/* D error -> read DER and DSR2 bit 2 */
if
(
der
||
(
dsr2
&
4
))
{
if
(
cs
->
debug
&
L1_DEB_WARN
)
debugl1
(
cs
,
"Amd7930: interrupt: D error DER=0x%04X"
,
der
);
/* RX, TX abort if collision detected */
if
(
der
&
2
)
{
wByteAMD
(
cs
,
0x21
,
0xC2
);
wByteAMD
(
cs
,
0x21
,
0x02
);
if
(
test_and_clear_bit
(
FLG_DBUSY_TIMER
,
&
cs
->
HW_Flags
))
del_timer
(
&
cs
->
dbusytimer
);
if
(
test_and_clear_bit
(
FLG_L1_DBUSY
,
&
cs
->
HW_Flags
))
Amd7930_sched_event
(
cs
,
D_CLEARBUSY
);
/* restart frame */
if
(
cs
->
tx_skb
)
{
skb_push
(
cs
->
tx_skb
,
cs
->
tx_cnt
);
cs
->
tx_cnt
=
0
;
cs
->
dc
.
amd7930
.
tx_xmtlen
=
0
;
Amd7930_fill_Dfifo
(
cs
);
}
else
{
printk
(
KERN_WARNING
"HiSax: Amd7930 D-Collision, no skb
\n
"
);
debugl1
(
cs
,
"Amd7930: interrupt: D-Collision, no skb"
);
}
}
/* remove damaged data from fifo */
Amd7930_empty_Dfifo
(
cs
,
1
);
if
(
test_and_clear_bit
(
FLG_DBUSY_TIMER
,
&
cs
->
HW_Flags
))
del_timer
(
&
cs
->
dbusytimer
);
if
(
test_and_clear_bit
(
FLG_L1_DBUSY
,
&
cs
->
HW_Flags
))
Amd7930_sched_event
(
cs
,
D_CLEARBUSY
);
/* restart TX-Frame */
if
(
cs
->
tx_skb
)
{
skb_push
(
cs
->
tx_skb
,
cs
->
tx_cnt
);
cs
->
tx_cnt
=
0
;
cs
->
dc
.
amd7930
.
tx_xmtlen
=
0
;
Amd7930_fill_Dfifo
(
cs
);
}
}
/* D TX FIFO empty -> fill */
if
(
irflags
&
1
)
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: interrupt: clear Timer and fill D-TX-FIFO if data"
);
/* AMD interrupts off */
AmdIrqOff
(
cs
);
if
(
test_and_clear_bit
(
FLG_DBUSY_TIMER
,
&
cs
->
HW_Flags
))
del_timer
(
&
cs
->
dbusytimer
);
if
(
test_and_clear_bit
(
FLG_L1_DBUSY
,
&
cs
->
HW_Flags
))
Amd7930_sched_event
(
cs
,
D_CLEARBUSY
);
if
(
cs
->
tx_skb
)
{
if
(
cs
->
tx_skb
->
len
)
Amd7930_fill_Dfifo
(
cs
);
}
/* AMD interrupts on */
AmdIrqOn
(
cs
);
}
/* D RX FIFO full or tiny packet in Fifo -> empty */
if
((
irflags
&
2
)
||
(
dsr1
&
2
))
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: interrupt: empty D-FIFO"
);
Amd7930_empty_Dfifo
(
cs
,
0
);
}
/* D-Frame transmit complete */
if
(
dsr1
&
64
)
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
{
debugl1
(
cs
,
"Amd7930: interrupt: transmit packet ready"
);
}
/* AMD interrupts off */
AmdIrqOff
(
cs
);
if
(
test_and_clear_bit
(
FLG_DBUSY_TIMER
,
&
cs
->
HW_Flags
))
del_timer
(
&
cs
->
dbusytimer
);
if
(
test_and_clear_bit
(
FLG_L1_DBUSY
,
&
cs
->
HW_Flags
))
Amd7930_sched_event
(
cs
,
D_CLEARBUSY
);
if
(
cs
->
tx_skb
)
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: interrupt: TX-Packet ready, freeing skb"
);
dev_kfree_skb_irq
(
cs
->
tx_skb
);
cs
->
tx_cnt
=
0
;
cs
->
dc
.
amd7930
.
tx_xmtlen
=
0
;
cs
->
tx_skb
=
NULL
;
}
if
((
cs
->
tx_skb
=
skb_dequeue
(
&
cs
->
sq
)))
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: interrupt: TX-Packet ready, next packet dequeued"
);
cs
->
tx_cnt
=
0
;
cs
->
dc
.
amd7930
.
tx_xmtlen
=
0
;
Amd7930_fill_Dfifo
(
cs
);
}
else
Amd7930_sched_event
(
cs
,
D_XMTBUFREADY
);
/* AMD interrupts on */
AmdIrqOn
(
cs
);
}
/* LIU status interrupt -> read LSR, check statechanges */
if
(
lsr
&
0x38
)
{
/* AMD interrupts off */
AmdIrqOff
(
cs
);
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd: interrupt: LSR=0x%02X, LIU is in state %d"
,
lsr
,
((
lsr
&
0x7
)
+
2
));
cs
->
dc
.
amd7930
.
ph_state
=
(
lsr
&
0x7
)
+
2
;
Amd7930_sched_event
(
cs
,
D_L1STATECHANGE
);
/* AMD interrupts on */
AmdIrqOn
(
cs
);
}
/* reads Interrupt-Register again. If there is a new interrupt-flag: restart handler */
irflags
=
rByteAMD
(
cs
,
0x00
);
}
}
static
void
Amd7930_l1hw
(
struct
PStack
*
st
,
int
pr
,
void
*
arg
)
{
struct
IsdnCardState
*
cs
=
(
struct
IsdnCardState
*
)
st
->
l1
.
hardware
;
struct
sk_buff
*
skb
=
arg
;
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: l1hw called, pr: 0x%04X"
,
pr
);
switch
(
pr
)
{
case
(
PH_DATA
|
REQUEST
):
if
(
cs
->
debug
&
DEB_DLOG_HEX
)
LogFrame
(
cs
,
skb
->
data
,
skb
->
len
);
if
(
cs
->
debug
&
DEB_DLOG_VERBOSE
)
dlogframe
(
cs
,
skb
,
0
);
if
(
cs
->
tx_skb
)
{
skb_queue_tail
(
&
cs
->
sq
,
skb
);
#ifdef L2FRAME_DEBUG
/* psa */
if
(
cs
->
debug
&
L1_DEB_LAPD
)
Logl2Frame
(
cs
,
skb
,
"Amd7930: l1hw: PH_DATA Queued"
,
0
);
#endif
}
else
{
cs
->
tx_skb
=
skb
;
cs
->
tx_cnt
=
0
;
cs
->
dc
.
amd7930
.
tx_xmtlen
=
0
;
#ifdef L2FRAME_DEBUG
/* psa */
if
(
cs
->
debug
&
L1_DEB_LAPD
)
Logl2Frame
(
cs
,
skb
,
"Amd7930: l1hw: PH_DATA"
,
0
);
#endif
Amd7930_fill_Dfifo
(
cs
);
}
break
;
case
(
PH_PULL
|
INDICATION
):
if
(
cs
->
tx_skb
)
{
if
(
cs
->
debug
&
L1_DEB_WARN
)
debugl1
(
cs
,
"Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen"
);
skb_queue_tail
(
&
cs
->
sq
,
skb
);
break
;
}
if
(
cs
->
debug
&
DEB_DLOG_HEX
)
LogFrame
(
cs
,
skb
->
data
,
skb
->
len
);
if
(
cs
->
debug
&
DEB_DLOG_VERBOSE
)
dlogframe
(
cs
,
skb
,
0
);
cs
->
tx_skb
=
skb
;
cs
->
tx_cnt
=
0
;
cs
->
dc
.
amd7930
.
tx_xmtlen
=
0
;
#ifdef L2FRAME_DEBUG
/* psa */
if
(
cs
->
debug
&
L1_DEB_LAPD
)
Logl2Frame
(
cs
,
skb
,
"Amd7930: l1hw: PH_DATA_PULLED"
,
0
);
#endif
Amd7930_fill_Dfifo
(
cs
);
break
;
case
(
PH_PULL
|
REQUEST
):
#ifdef L2FRAME_DEBUG
/* psa */
if
(
cs
->
debug
&
L1_DEB_LAPD
)
debugl1
(
cs
,
"Amd7930: l1hw: -> PH_REQUEST_PULL, skb: %s"
,
(
cs
->
tx_skb
)
?
"yes"
:
"no"
);
#endif
if
(
!
cs
->
tx_skb
)
{
test_and_clear_bit
(
FLG_L1_PULL_REQ
,
&
st
->
l1
.
Flags
);
st
->
l2
.
l1l2
(
st
,
PH_PULL
|
CONFIRM
,
NULL
);
}
else
test_and_set_bit
(
FLG_L1_PULL_REQ
,
&
st
->
l1
.
Flags
);
break
;
case
(
HW_RESET
|
REQUEST
):
if
((
cs
->
dc
.
amd7930
.
ph_state
==
8
))
/* b-channels off, PH-AR cleared
* change to F3 */
Amd7930_ph_command
(
cs
,
0x20
,
"HW_RESET REQEST"
);
//LMR1 bit 5
else
{
Amd7930_ph_command
(
cs
,
0x40
,
"HW_RESET REQUEST"
);
cs
->
dc
.
amd7930
.
ph_state
=
2
;
Amd7930_new_ph
(
cs
);
}
break
;
case
(
HW_ENABLE
|
REQUEST
):
cs
->
dc
.
amd7930
.
ph_state
=
9
;
Amd7930_new_ph
(
cs
);
break
;
case
(
HW_INFO3
|
REQUEST
):
// automatic
break
;
case
(
HW_TESTLOOP
|
REQUEST
):
/* not implemented yet */
break
;
case
(
HW_DEACTIVATE
|
RESPONSE
):
skb_queue_purge
(
&
cs
->
rq
);
skb_queue_purge
(
&
cs
->
sq
);
if
(
cs
->
tx_skb
)
{
dev_kfree_skb
(
cs
->
tx_skb
);
cs
->
tx_skb
=
NULL
;
}
if
(
test_and_clear_bit
(
FLG_DBUSY_TIMER
,
&
cs
->
HW_Flags
))
del_timer
(
&
cs
->
dbusytimer
);
if
(
test_and_clear_bit
(
FLG_L1_DBUSY
,
&
cs
->
HW_Flags
))
Amd7930_sched_event
(
cs
,
D_CLEARBUSY
);
break
;
default:
if
(
cs
->
debug
&
L1_DEB_WARN
)
debugl1
(
cs
,
"Amd7930: l1hw: unknown %04x"
,
pr
);
break
;
}
}
void
setstack_Amd7930
(
struct
PStack
*
st
,
struct
IsdnCardState
*
cs
)
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: setstack called"
);
st
->
l1
.
l1hw
=
Amd7930_l1hw
;
}
void
DC_Close_Amd7930
(
struct
IsdnCardState
*
cs
)
{
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: DC_Close called"
);
}
static
void
dbusy_timer_handler
(
struct
IsdnCardState
*
cs
)
{
struct
PStack
*
stptr
;
WORD
dtcr
,
der
;
BYTE
dsr1
,
dsr2
;
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: dbusy_timer expired!"
);
if
(
test_bit
(
FLG_DBUSY_TIMER
,
&
cs
->
HW_Flags
))
{
/* D Transmit Byte Count Register:
* Counts down packet's number of Bytes, 0 if packet ready */
dtcr
=
rWordAMD
(
cs
,
0x85
);
dsr1
=
rByteAMD
(
cs
,
0x02
);
dsr2
=
rByteAMD
(
cs
,
0x07
);
der
=
rWordAMD
(
cs
,
0x03
);
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u"
,
dsr1
,
dsr2
,
der
,
cs
->
tx_skb
->
len
,
cs
->
dc
.
amd7930
.
tx_xmtlen
,
dtcr
,
cs
->
tx_cnt
);
if
((
cs
->
dc
.
amd7930
.
tx_xmtlen
-
dtcr
)
<
cs
->
tx_cnt
)
{
/* D-Channel Busy */
test_and_set_bit
(
FLG_L1_DBUSY
,
&
cs
->
HW_Flags
);
stptr
=
cs
->
stlist
;
while
(
stptr
!=
NULL
)
{
stptr
->
l2
.
l1l2
(
stptr
,
PH_PAUSE
|
INDICATION
,
NULL
);
stptr
=
stptr
->
next
;
}
}
else
{
/* discard frame; reset transceiver */
test_and_clear_bit
(
FLG_DBUSY_TIMER
,
&
cs
->
HW_Flags
);
if
(
cs
->
tx_skb
)
{
dev_kfree_skb_any
(
cs
->
tx_skb
);
cs
->
tx_cnt
=
0
;
cs
->
tx_skb
=
NULL
;
cs
->
dc
.
amd7930
.
tx_xmtlen
=
0
;
}
else
{
printk
(
KERN_WARNING
"HiSax: Amd7930: D-Channel Busy no skb
\n
"
);
debugl1
(
cs
,
"Amd7930: D-Channel Busy no skb"
);
}
/* Transmitter reset, abort transmit */
wByteAMD
(
cs
,
0x21
,
0x82
);
wByteAMD
(
cs
,
0x21
,
0x02
);
cs
->
irq_func
(
cs
->
irq
,
cs
,
NULL
);
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: dbusy_timer_handler: Transmitter reset"
);
}
}
}
void
__devinit
Amd7930_init
(
struct
IsdnCardState
*
cs
)
{
WORD
*
ptr
;
BYTE
cmd
,
cnt
;
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"Amd7930: initamd called"
);
cs
->
dc
.
amd7930
.
tx_xmtlen
=
0
;
cs
->
dc
.
amd7930
.
old_state
=
0
;
cs
->
dc
.
amd7930
.
lmr1
=
0x40
;
cs
->
dc
.
amd7930
.
ph_command
=
Amd7930_ph_command
;
cs
->
tqueue
.
routine
=
(
void
*
)
(
void
*
)
Amd7930_bh
;
cs
->
setstack_d
=
setstack_Amd7930
;
cs
->
DC_Close
=
DC_Close_Amd7930
;
cs
->
dbusytimer
.
function
=
(
void
*
)
dbusy_timer_handler
;
cs
->
dbusytimer
.
data
=
(
long
)
cs
;
init_timer
(
&
cs
->
dbusytimer
);
/* AMD Initialisation */
for
(
ptr
=
initAMD
;
*
ptr
!=
0xFFFF
;
)
{
cmd
=
LOBYTE
(
*
ptr
);
/* read */
if
(
*
ptr
++
>=
0x100
)
{
if
(
cmd
<
8
)
/* setzt Register zurck */
rByteAMD
(
cs
,
cmd
);
else
{
wByteAMD
(
cs
,
0x00
,
cmd
);
for
(
cnt
=
*
ptr
++
;
cnt
>
0
;
cnt
--
)
rByteAMD
(
cs
,
0x01
);
}
}
/* write */
else
if
(
cmd
<
8
)
wByteAMD
(
cs
,
cmd
,
LOBYTE
(
*
ptr
++
));
else
{
wByteAMD
(
cs
,
0x00
,
cmd
);
for
(
cnt
=
*
ptr
++
;
cnt
>
0
;
cnt
--
)
wByteAMD
(
cs
,
0x01
,
LOBYTE
(
*
ptr
++
));
}
}
}
drivers/isdn/hisax/amd7930_fn.h
0 → 100644
View file @
4a0540b8
/* 2001/10/02
*
* gerdes_amd7930.h Header-file included by
* gerdes_amd7930.c
*
* Author Christoph Ersfeld <info@formula-n.de>
* Formula-n Europe AG (www.formula-n.com)
* previously Gerdes AG
*
*
* This file is (c) under GNU PUBLIC LICENSE
*/
#define BYTE unsigned char
#define WORD unsigned int
#define rByteAMD(cs, reg) cs->readisac(cs, reg)
#define wByteAMD(cs, reg, val) cs->writeisac(cs, reg, val)
#define rWordAMD(cs, reg) ReadWordAmd7930(cs, reg)
#define wWordAMD(cs, reg, val) WriteWordAmd7930(cs, reg, val)
#define HIBYTE(w) ((unsigned char)((w & 0xff00) / 256))
#define LOBYTE(w) ((unsigned char)(w & 0x00ff))
#define AmdIrqOff(cs) cs->dc.amd7930.setIrqMask(cs, 0)
#define AmdIrqOn(cs) cs->dc.amd7930.setIrqMask(cs, 1)
#define AMD_CR 0x00
#define AMD_DR 0x01
#define DBUSY_TIMER_VALUE 80
static
WORD
initAMD
[]
=
{
0x0100
,
0x00A5
,
3
,
0x01
,
0x40
,
0x58
,
// LPR, LMR1, LMR2
0x0086
,
1
,
0x0B
,
// DMR1 (D-Buffer TH-Interrupts on)
0x0087
,
1
,
0xFF
,
// DMR2
0x0092
,
1
,
0x03
,
// EFCR (extended mode d-channel-fifo on)
0x0090
,
4
,
0xFE
,
0xFF
,
0x02
,
0x0F
,
// FRAR4, SRAR4, DMR3, DMR4 (address recognition )
0x0084
,
2
,
0x80
,
0x00
,
// DRLR
0x00C0
,
1
,
0x47
,
// PPCR1
0x00C8
,
1
,
0x01
,
// PPCR2
0x0102
,
0x0107
,
0x01A1
,
1
,
0x0121
,
1
,
0x0189
,
2
,
0x0045
,
4
,
0x61
,
0x72
,
0x00
,
0x00
,
// MCR1, MCR2, MCR3, MCR4
0x0063
,
2
,
0x08
,
0x08
,
// GX
0x0064
,
2
,
0x08
,
0x08
,
// GR
0x0065
,
2
,
0x99
,
0x00
,
// GER
0x0066
,
2
,
0x7C
,
0x8B
,
// STG
0x0067
,
2
,
0x00
,
0x00
,
// FTGR1, FTGR2
0x0068
,
2
,
0x20
,
0x20
,
// ATGR1, ATGR2
0x0069
,
1
,
0x4F
,
// MMR1
0x006A
,
1
,
0x00
,
// MMR2
0x006C
,
1
,
0x40
,
// MMR3
0x0021
,
1
,
0x02
,
// INIT
0x00A3
,
1
,
0x40
,
// LMR1
0xFFFF
};
extern
void
Amd7930_interrupt
(
struct
IsdnCardState
*
cs
,
unsigned
char
irflags
);
extern
void
Amd7930_init
(
struct
IsdnCardState
*
cs
);
drivers/isdn/hisax/config.c
View file @
4a0540b8
...
...
@@ -75,6 +75,8 @@
* 37 HFC 2BDS0 S+/SP p0=irq p1=iobase
* 38 Travers Technologies NETspider-U PCI card
* 39 HFC 2BDS0-SP PCMCIA p0=irq p1=iobase
* 40 hotplug interface
* 41 Formula-n enter:now ISDN PCI a/b none
*
* protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
*
...
...
@@ -93,6 +95,7 @@ const char *CardType[] = {
"Siemens I-Surf"
,
"Acer P10"
,
"HST Saphir"
,
"Telekom A4T"
,
"Scitel Quadro"
,
"Gazel"
,
"HFC 2BDS0 PCI"
,
"Winbond 6692"
,
"HFC 2BDS0 SX"
,
"NETspider-U"
,
"HFC-2BDS0-SP PCMCIA"
,
"Hotplug"
,
"Formula-n enter:now PCI a/b"
,
};
void
HiSax_closecard
(
int
cardnr
);
...
...
@@ -601,6 +604,10 @@ extern int setup_w6692(struct IsdnCard *card);
extern
int
setup_netjet_u
(
struct
IsdnCard
*
card
);
#endif
#if CARD_FN_ENTERNOW_PCI
extern
int
setup_enternow_pci
(
struct
IsdnCard
*
card
);
#endif
/*
* Find card with given driverId
*/
...
...
@@ -1137,6 +1144,11 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
case
ISDN_CTYPE_NETJET_U
:
ret
=
setup_netjet_u
(
card
);
break
;
#endif
#if CARD_FN_ENTERNOW_PCI
case
ISDN_CTYPE_ENTERNOW
:
ret
=
setup_enternow_pci
(
card
);
break
;
#endif
case
ISDN_CTYPE_DYNAMIC
:
ret
=
2
;
...
...
drivers/isdn/hisax/enternow.h
0 → 100644
View file @
4a0540b8
/* 2001/10/02
*
* enternow.h Header-file included by
* enternow_pci.c
*
* Author Christoph Ersfeld <info@formula-n.de>
* Formula-n Europe AG (www.formula-n.com)
* previously Gerdes AG
*
*
* This file is (c) under GNU PUBLIC LICENSE
*/
/* ***************************************************************************************** *
* ****************************** datatypes and macros ************************************* *
* ***************************************************************************************** */
#define BYTE unsigned char
#define WORD unsigned int
#define HIBYTE(w) ((unsigned char)((w & 0xff00) / 256))
#define LOBYTE(w) ((unsigned char)(w & 0x00ff))
#define InByte(addr) inb(addr)
#define OutByte(addr,val) outb(val,addr)
/* ***************************************************************************************** *
* *********************************** card-specific *************************************** *
* ***************************************************************************************** */
/* fr PowerISDN PCI */
#define TJ_AMD_IRQ 0x20
#define TJ_LED1 0x40
#define TJ_LED2 0x80
/* Das Fenster zum AMD...
* Ab Adresse hw.njet.base + TJ_AMD_PORT werden vom AMD jeweils 8 Bit in
* den TigerJet i/o-Raum gemappt
* -> 0x01 des AMD bei hw.njet.base + 0C4 */
#define TJ_AMD_PORT 0xC0
/* ***************************************************************************************** *
* *************************************** Prototypen ************************************** *
* ***************************************************************************************** */
BYTE
ReadByteAmd7930
(
struct
IsdnCardState
*
cs
,
BYTE
offset
);
void
WriteByteAmd7930
(
struct
IsdnCardState
*
cs
,
BYTE
offset
,
BYTE
value
);
drivers/isdn/hisax/enternow_pci.c
0 → 100644
View file @
4a0540b8
/* enternow_pci.c,v 0.99 2001/10/02
*
* enternow_pci.c Card-specific routines for
* Formula-n enter:now ISDN PCI ab
* Gerdes AG Power ISDN PCI
* Woerltronic SA 16 PCI
* (based on HiSax driver by Karsten Keil)
*
* Author Christoph Ersfeld <info@formula-n.de>
* Formula-n Europe AG (www.formula-n.com)
* previously Gerdes AG
*
*
* This file is (c) under GNU PUBLIC LICENSE
*
* Notes:
* This driver interfaces to netjet.c which performs B-channel
* processing.
*
* Version 0.99 is the first release of this driver and there are
* certainly a few bugs.
* It isn't testet on linux 2.4 yet, so consider this code to be
* beta.
*
* Please don't report me any malfunction without sending
* (compressed) debug-logs.
* It would be nearly impossible to retrace it.
*
* Log D-channel-processing as follows:
*
* 1. Load hisax with card-specific parameters, this example ist for
* Formula-n enter:now ISDN PCI and compatible
* (f.e. Gerdes Power ISDN PCI)
*
* modprobe hisax type=41 protocol=2 id=gerdes
*
* if you chose an other value for id, you need to modify the
* code below, too.
*
* 2. set debug-level
*
* hisaxctrl gerdes 1 0x3ff
* hisaxctrl gerdes 11 0x4f
* cat /dev/isdnctrl >> ~/log &
*
* Please take also a look into /var/log/messages if there is
* anything importand concerning HISAX.
*
*
* Credits:
* Programming the driver for Formula-n enter:now ISDN PCI and
* neccessary the driver for the used Amd 7930 D-channel-controller
* was spnsored by Formula-n Europe AG.
* Thanks to Karsten Keil and Petr Novak, who gave me support in
* Hisax-specific questions.
* I want so say special thanks to Carl-Friedrich Braun, who had to
* answer a lot of questions about generally ISDN and about handling
* of the Amd-Chip.
*
*/
#define __NO_VERSION__
#include <linux/config.h>
#include "hisax.h"
#include "isac.h"
#include "isdnl1.h"
#include "amd7930_fn.h"
#include "enternow.h"
#include <linux/interrupt.h>
#include <linux/ppp_defs.h>
#include <linux/pci.h>
#include <linux/init.h>
#include "netjet.h"
const
char
*
enternow_pci_rev
=
"$Revision: 1.1.2.1 $"
;
/* *************************** I/O-Interface functions ************************************* */
/* cs->readisac, macro rByteAMD */
BYTE
ReadByteAmd7930
(
struct
IsdnCardState
*
cs
,
BYTE
offset
)
{
/* direktes Register */
if
(
offset
<
8
)
return
(
InByte
(
cs
->
hw
.
njet
.
isac
+
4
*
offset
));
/* indirektes Register */
else
{
OutByte
(
cs
->
hw
.
njet
.
isac
+
4
*
AMD_CR
,
offset
);
return
(
InByte
(
cs
->
hw
.
njet
.
isac
+
4
*
AMD_DR
));
}
}
/* cs->writeisac, macro wByteAMD */
void
WriteByteAmd7930
(
struct
IsdnCardState
*
cs
,
BYTE
offset
,
BYTE
value
)
{
/* direktes Register */
if
(
offset
<
8
)
OutByte
(
cs
->
hw
.
njet
.
isac
+
4
*
offset
,
value
);
/* indirektes Register */
else
{
OutByte
(
cs
->
hw
.
njet
.
isac
+
4
*
AMD_CR
,
offset
);
OutByte
(
cs
->
hw
.
njet
.
isac
+
4
*
AMD_DR
,
value
);
}
}
void
enpci_setIrqMask
(
struct
IsdnCardState
*
cs
,
BYTE
val
)
{
if
(
!
val
)
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_IRQMASK1
,
0x00
);
else
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_IRQMASK1
,
TJ_AMD_IRQ
);
}
static
BYTE
dummyrr
(
struct
IsdnCardState
*
cs
,
int
chan
,
BYTE
off
)
{
return
(
5
);
}
static
void
dummywr
(
struct
IsdnCardState
*
cs
,
int
chan
,
BYTE
off
,
BYTE
value
)
{
}
/* ******************************************************************************** */
static
void
reset_enpci
(
struct
IsdnCardState
*
cs
)
{
long
flags
;
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"enter:now PCI: reset"
);
save_flags
(
flags
);
sti
();
/* Reset on, (also for AMD) */
cs
->
hw
.
njet
.
ctrl_reg
=
0x07
;
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_CTRL
,
cs
->
hw
.
njet
.
ctrl_reg
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
/* 80 ms delay */
schedule_timeout
((
80
*
HZ
)
/
1000
);
/* Reset off */
cs
->
hw
.
njet
.
ctrl_reg
=
0x70
;
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_CTRL
,
cs
->
hw
.
njet
.
ctrl_reg
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
/* 80ms delay */
schedule_timeout
((
80
*
HZ
)
/
1000
);
restore_flags
(
flags
);
cs
->
hw
.
njet
.
auxd
=
0
;
// LED-status
cs
->
hw
.
njet
.
dmactrl
=
0
;
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_AUXCTRL
,
~
TJ_AMD_IRQ
);
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_IRQMASK1
,
TJ_AMD_IRQ
);
OutByte
(
cs
->
hw
.
njet
.
auxa
,
cs
->
hw
.
njet
.
auxd
);
// LED off
}
static
int
enpci_card_msg
(
struct
IsdnCardState
*
cs
,
int
mt
,
void
*
arg
)
{
BYTE
*
chan
;
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"enter:now PCI: card_msg: 0x%04X"
,
mt
);
switch
(
mt
)
{
case
CARD_RESET
:
reset_enpci
(
cs
);
Amd7930_init
(
cs
);
break
;
case
CARD_RELEASE
:
release_io_netjet
(
cs
);
break
;
case
CARD_INIT
:
inittiger
(
cs
);
Amd7930_init
(
cs
);
break
;
case
CARD_TEST
:
break
;
case
MDL_ASSIGN
:
/* TEI assigned, LED1 on */
cs
->
hw
.
njet
.
auxd
=
TJ_AMD_IRQ
<<
1
;
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_AUXDATA
,
cs
->
hw
.
njet
.
auxd
);
break
;
case
MDL_REMOVE
:
/* TEI removed, LEDs off */
cs
->
hw
.
njet
.
auxd
=
0
;
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_AUXDATA
,
0x00
);
break
;
case
MDL_BC_ASSIGN
:
/* activate B-channel */
chan
=
(
BYTE
*
)
arg
;
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"enter:now PCI: assign phys. BC %d in AMD LMR1"
,
*
chan
);
cs
->
dc
.
amd7930
.
ph_command
(
cs
,
(
cs
->
dc
.
amd7930
.
lmr1
|
(
*
chan
+
1
)),
"MDL_BC_ASSIGN"
);
/* at least one b-channel in use, LED 2 on */
cs
->
hw
.
njet
.
auxd
|=
TJ_AMD_IRQ
<<
2
;
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_AUXDATA
,
cs
->
hw
.
njet
.
auxd
);
break
;
case
MDL_BC_RELEASE
:
/* deactivate B-channel */
chan
=
(
BYTE
*
)
arg
;
if
(
cs
->
debug
&
L1_DEB_ISAC
)
debugl1
(
cs
,
"enter:now PCI: release phys. BC %d in Amd LMR1"
,
*
chan
);
cs
->
dc
.
amd7930
.
ph_command
(
cs
,
(
cs
->
dc
.
amd7930
.
lmr1
&
~
(
*
chan
+
1
)),
"MDL_BC_RELEASE"
);
/* no b-channel active -> LED2 off */
if
(
!
(
cs
->
dc
.
amd7930
.
lmr1
&
3
))
{
cs
->
hw
.
njet
.
auxd
&=
~
(
TJ_AMD_IRQ
<<
2
);
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_AUXDATA
,
cs
->
hw
.
njet
.
auxd
);
}
break
;
default:
break
;
}
return
(
0
);
}
static
void
enpci_interrupt
(
int
intno
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
IsdnCardState
*
cs
=
dev_id
;
BYTE
sval
,
ir
;
long
flags
;
if
(
!
cs
)
{
printk
(
KERN_WARNING
"enter:now PCI: Spurious interrupt!
\n
"
);
return
;
}
sval
=
InByte
(
cs
->
hw
.
njet
.
base
+
NETJET_IRQSTAT1
);
/* AMD threw an interrupt */
if
(
!
(
sval
&
TJ_AMD_IRQ
))
{
/* read and clear interrupt-register */
ir
=
ReadByteAmd7930
(
cs
,
0x00
);
Amd7930_interrupt
(
cs
,
ir
);
}
/* DMA-Interrupt: B-channel-stuff */
/* set bits in sval to indicate which page is free */
save_flags
(
flags
);
cli
();
/* set bits in sval to indicate which page is free */
if
(
inl
(
cs
->
hw
.
njet
.
base
+
NETJET_DMA_WRITE_ADR
)
<
inl
(
cs
->
hw
.
njet
.
base
+
NETJET_DMA_WRITE_IRQ
))
/* the 2nd write page is free */
sval
=
0x08
;
else
/* the 1st write page is free */
sval
=
0x04
;
if
(
inl
(
cs
->
hw
.
njet
.
base
+
NETJET_DMA_READ_ADR
)
<
inl
(
cs
->
hw
.
njet
.
base
+
NETJET_DMA_READ_IRQ
))
/* the 2nd read page is free */
sval
=
sval
|
0x02
;
else
/* the 1st read page is free */
sval
=
sval
|
0x01
;
if
(
sval
!=
cs
->
hw
.
njet
.
last_is0
)
/* we have a DMA interrupt */
{
if
(
test_and_set_bit
(
FLG_LOCK_ATOMIC
,
&
cs
->
HW_Flags
))
{
restore_flags
(
flags
);
return
;
}
cs
->
hw
.
njet
.
irqstat0
=
sval
;
restore_flags
(
flags
);
if
((
cs
->
hw
.
njet
.
irqstat0
&
NETJET_IRQM0_READ
)
!=
(
cs
->
hw
.
njet
.
last_is0
&
NETJET_IRQM0_READ
))
/* we have a read dma int */
read_tiger
(
cs
);
if
((
cs
->
hw
.
njet
.
irqstat0
&
NETJET_IRQM0_WRITE
)
!=
(
cs
->
hw
.
njet
.
last_is0
&
NETJET_IRQM0_WRITE
))
/* we have a write dma int */
write_tiger
(
cs
);
test_and_clear_bit
(
FLG_LOCK_ATOMIC
,
&
cs
->
HW_Flags
);
}
else
restore_flags
(
flags
);
}
static
struct
pci_dev
*
dev_netjet
__initdata
=
NULL
;
/* called by config.c */
int
__init
setup_enternow_pci
(
struct
IsdnCard
*
card
)
{
int
bytecnt
;
struct
IsdnCardState
*
cs
=
card
->
cs
;
char
tmp
[
64
];
long
flags
;
#if CONFIG_PCI
#ifdef __BIG_ENDIAN
#error "not running on big endian machines now"
#endif
strcpy
(
tmp
,
enternow_pci_rev
);
printk
(
KERN_INFO
"HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s
\n
"
,
HiSax_getrev
(
tmp
));
if
(
cs
->
typ
!=
ISDN_CTYPE_ENTERNOW
)
return
(
0
);
test_and_clear_bit
(
FLG_LOCK_ATOMIC
,
&
cs
->
HW_Flags
);
for
(
;;
)
{
if
(
!
pci_present
())
{
printk
(
KERN_ERR
"enter:now PCI: no PCI bus present
\n
"
);
return
(
0
);
}
if
((
dev_netjet
=
pci_find_device
(
PCI_VENDOR_ID_TIGERJET
,
PCI_DEVICE_ID_TIGERJET_300
,
dev_netjet
)))
{
if
(
pci_enable_device
(
dev_netjet
))
return
(
0
);
cs
->
irq
=
dev_netjet
->
irq
;
if
(
!
cs
->
irq
)
{
printk
(
KERN_WARNING
"enter:now PCI: No IRQ for PCI card found
\n
"
);
return
(
0
);
}
cs
->
hw
.
njet
.
base
=
pci_resource_start
(
dev_netjet
,
0
);
if
(
!
cs
->
hw
.
njet
.
base
)
{
printk
(
KERN_WARNING
"enter:now PCI: No IO-Adr for PCI card found
\n
"
);
return
(
0
);
}
/* checks Sub-Vendor ID because system crashes with Traverse-Card */
if
((
dev_netjet
->
subsystem_vendor
!=
0x55
)
||
(
dev_netjet
->
subsystem_device
!=
0x02
))
{
printk
(
KERN_WARNING
"enter:now: You tried to load this driver with an incompatible TigerJet-card
\n
"
);
printk
(
KERN_WARNING
"Use type=20 for Traverse NetJet PCI Card.
\n
"
);
return
(
0
);
}
}
else
{
printk
(
KERN_WARNING
"enter:now PCI: No PCI card found
\n
"
);
return
(
0
);
}
cs
->
hw
.
njet
.
auxa
=
cs
->
hw
.
njet
.
base
+
NETJET_AUXDATA
;
cs
->
hw
.
njet
.
isac
=
cs
->
hw
.
njet
.
base
+
0xC0
;
// Fenster zum AMD
save_flags
(
flags
);
sti
();
/* Reset an */
cs
->
hw
.
njet
.
ctrl_reg
=
0x07
;
// gendert von 0xff
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_CTRL
,
cs
->
hw
.
njet
.
ctrl_reg
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
/* 50 ms Pause */
schedule_timeout
((
50
*
HZ
)
/
1000
);
cs
->
hw
.
njet
.
ctrl_reg
=
0x30
;
/* Reset Off and status read clear */
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_CTRL
,
cs
->
hw
.
njet
.
ctrl_reg
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
((
10
*
HZ
)
/
1000
);
/* Timeout 10ms */
restore_flags
(
flags
);
cs
->
hw
.
njet
.
auxd
=
0x00
;
// war 0xc0
cs
->
hw
.
njet
.
dmactrl
=
0
;
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_AUXCTRL
,
~
TJ_AMD_IRQ
);
OutByte
(
cs
->
hw
.
njet
.
base
+
NETJET_IRQMASK1
,
TJ_AMD_IRQ
);
OutByte
(
cs
->
hw
.
njet
.
auxa
,
cs
->
hw
.
njet
.
auxd
);
break
;
}
#else
printk
(
KERN_WARNING
"enter:now PCI: NO_PCI_BIOS
\n
"
);
printk
(
KERN_WARNING
"enter:now PCI: unable to config Formula-n enter:now ISDN PCI ab
\n
"
);
return
(
0
);
#endif
/* CONFIG_PCI */
bytecnt
=
256
;
printk
(
KERN_INFO
"enter:now PCI: PCI card configured at 0x%lx IRQ %d
\n
"
,
cs
->
hw
.
njet
.
base
,
cs
->
irq
);
if
(
check_region
(
cs
->
hw
.
njet
.
base
,
bytecnt
))
{
printk
(
KERN_WARNING
"HiSax: %s config port %lx-%lx already in use
\n
"
,
CardType
[
card
->
typ
],
cs
->
hw
.
njet
.
base
,
cs
->
hw
.
njet
.
base
+
bytecnt
);
return
(
0
);
}
else
{
request_region
(
cs
->
hw
.
njet
.
base
,
bytecnt
,
"Fn_ISDN"
);
}
reset_enpci
(
cs
);
cs
->
hw
.
njet
.
last_is0
=
0
;
/* macro rByteAMD */
cs
->
readisac
=
&
ReadByteAmd7930
;
/* macro wByteAMD */
cs
->
writeisac
=
&
WriteByteAmd7930
;
cs
->
dc
.
amd7930
.
setIrqMask
=
&
enpci_setIrqMask
;
cs
->
BC_Read_Reg
=
&
dummyrr
;
cs
->
BC_Write_Reg
=
&
dummywr
;
cs
->
BC_Send_Data
=
&
netjet_fill_dma
;
cs
->
cardmsg
=
&
enpci_card_msg
;
cs
->
irq_func
=
&
enpci_interrupt
;
cs
->
irq_flags
|=
SA_SHIRQ
;
return
(
1
);
}
drivers/isdn/hisax/hisax.h
View file @
4a0540b8
...
...
@@ -67,6 +67,9 @@
#define DL_DATA 0x0220
#define DL_FLUSH 0x0224
#define DL_UNIT_DATA 0x0230
#define MDL_BC_RELEASE 0x0278 // Formula-n enter:now
#define MDL_BC_ASSIGN 0x027C // Formula-n enter:now
#define MDL_ASSIGN 0x0280
#define MDL_REMOVE 0x0284
#define MDL_ERROR 0x0288
...
...
@@ -835,6 +838,17 @@ struct w6692_chip {
int
ph_state
;
};
struct
amd7930_chip
{
u_char
lmr1
;
u_char
ph_state
;
u_char
old_state
;
u_char
flg_t3
;
unsigned
int
tx_xmtlen
;
struct
timer_list
timer3
;
void
(
*
ph_command
)
(
struct
IsdnCardState
*
,
u_char
,
char
*
);
void
(
*
setIrqMask
)
(
struct
IsdnCardState
*
,
u_char
);
};
struct
icc_chip
{
int
ph_state
;
u_char
*
mon_tx
;
...
...
@@ -932,6 +946,7 @@ struct IsdnCardState {
struct
hfcpci_chip
hfcpci
;
struct
hfcsx_chip
hfcsx
;
struct
w6692_chip
w6692
;
struct
amd7930_chip
amd7930
;
struct
icc_chip
icc
;
}
dc
;
u_char
*
rcvbuf
;
...
...
@@ -993,7 +1008,8 @@ struct IsdnCardState {
#define ISDN_CTYPE_NETJET_U 38
#define ISDN_CTYPE_HFC_SP_PCMCIA 39
#define ISDN_CTYPE_DYNAMIC 40
#define ISDN_CTYPE_COUNT 40
#define ISDN_CTYPE_ENTERNOW 41
#define ISDN_CTYPE_COUNT 41
#ifdef ISDN_CHIP_ISAC
...
...
@@ -1252,6 +1268,10 @@ struct IsdnCardState {
#define CARD_NETJET_U 0
#endif
#ifdef CONFIG_HISAX_ENTERNOW_PCI
#define CARD_FN_ENTERNOW_PCI 1
#endif
#define TEI_PER_CARD 1
/* L1 Debug */
...
...
drivers/isdn/hisax/netjet.c
View file @
4a0540b8
...
...
@@ -858,9 +858,13 @@ tiger_l2l1(struct PStack *st, int pr, void *arg)
case
(
PH_ACTIVATE
|
REQUEST
):
test_and_set_bit
(
BC_FLG_ACTIV
,
&
st
->
l1
.
bcs
->
Flag
);
mode_tiger
(
st
->
l1
.
bcs
,
st
->
l1
.
mode
,
st
->
l1
.
bc
);
/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
st
->
l1
.
bcs
->
cs
->
cardmsg
(
st
->
l1
.
bcs
->
cs
,
MDL_BC_ASSIGN
,
(
void
*
)(
&
st
->
l1
.
bc
));
l1_msg_b
(
st
,
pr
,
arg
);
break
;
case
(
PH_DEACTIVATE
|
REQUEST
):
/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
st
->
l1
.
bcs
->
cs
->
cardmsg
(
st
->
l1
.
bcs
->
cs
,
MDL_BC_RELEASE
,
(
void
*
)(
&
st
->
l1
.
bc
));
l1_msg_b
(
st
,
pr
,
arg
);
break
;
case
(
PH_DEACTIVATE
|
CONFIRM
):
...
...
drivers/isdn/hisax/nj_s.c
View file @
4a0540b8
...
...
@@ -184,6 +184,14 @@ setup_netjet_s(struct IsdnCard *card)
printk
(
KERN_WARNING
"NETjet-S: No IO-Adr for PCI card found
\n
"
);
return
(
0
);
}
/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
if
((
dev_netjet
->
subsystem_vendor
==
0x55
)
&&
(
dev_netjet
->
subsystem_device
==
0x02
))
{
printk
(
KERN_WARNING
"Netjet: You tried to load this driver with an incompatible TigerJet-card
\n
"
);
printk
(
KERN_WARNING
"Use type=41 for Formula-n enter:now ISDN PCI and compatible
\n
"
);
return
(
0
);
}
/* end new code */
cs
->
hw
.
njet
.
pdev
=
dev_netjet
;
}
else
{
printk
(
KERN_WARNING
"NETjet-S: No PCI card found
\n
"
);
...
...
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