- new locking, relaxed irq

- dchannel and bchannel helper routines
- dchannel and bchannel hardware module
This commit is contained in:
Karsten Keil 2003-06-21 21:39:54 +00:00
parent fbba4429c5
commit 458ed3d264
20 changed files with 1163 additions and 1233 deletions

View File

@ -34,9 +34,9 @@ include: $(KDIR)/include
ln -s $(KDIR)/include
clean:
rm -f $(TARGETS) $(TARGETDIR)/.*.flags $(TARGETDIR)/*.o
rm -f $(TARGETS) $(TARGETDIR)/.*.flags $(TARGETDIR)/*.o $(TARGETDIR)/.depend
rm -f $(TARGETDIR)/*~ newinclude/linux/*~ *~ .kversion
rm -f -r modules
rm -f -r modules .depend .hdepend
$(TARGET):
$(MAKE) -f Makefile KDIR=$(KDIR) TARGETDIR=$(TARGETDIR) $(TARGET)

View File

@ -17,7 +17,7 @@ TOPDIR := $(KDIR)
include $(KDIR)/.config
include $(KDIR)/Makefile
CFLAGS := -I. -I $(KDIR)/drivers/isdn/avmb1 $(CFLAGS) -DLINUX
CFLAGS := -I. -I $(KDIR)/drivers/isdn/avmb1 $(CFLAGS) -I $(MYDIR)/newinclude -DLINUX
CC := $(filter-out -I$(HPATH), $(CC)) -I $(MYDIR)/newinclude -I $(HPATH)
ifdef CONFIG_MODVERSIONS
@ -26,12 +26,22 @@ else
CFLAGS := -DMODULE $(CFLAGS)
endif
FINDHPATH += $(MYDIR)/newinclude/linux
MODLIB := $(DESTDIR)$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
newhisax: $(TARGETDIR) newhisax_mod
newhisax: $(TARGETDIR) depend newhisax_mod
$(MAKE) -C $(TARGETDIR) CFLAGS="$(CFLAGS)" MAKING_MODULES=1 modules
dep-files: scripts/mkdep archdep include/linux/version.h
scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend
$(MAKE) $(patsubst %,_sfdep_%,$(TARGETDIR)) _FASTDEP_ALL_SUB_DIRS="$(TARGETDIR)"
ifdef CONFIG_MODVERSIONS
$(MAKE) update-modverfile
endif
depend dep: dep-files
ifeq ($(PATCHLEVEL), 2)
TARGETMODDIR = misc

View File

@ -11,11 +11,11 @@ O_TARGET := vmlinux-obj.o
# multi objects
SEDLFAXOBJ := sedl_fax.o debug.o helper.o fsm.o isar.o
SEDLFAXOBJ := sedl_fax.o debug.o helper.o fsm.o isar.o hisax_dch.o
FRITZOBJ := fritz_pci.o debug.o helper.o fsm.o
FRITZOBJ := fritz_pci.o debug.o helper.o fsm.o hisax_dch.o
HFC_PCIOBJ := hfc_pci.o debug.o helper.o
HFC_PCIOBJ := hfc_pci.o debug.o helper.o hisax_dch.o
hisaxisac-objs := isac.o arcofi.o debug.o

View File

@ -9,7 +9,7 @@
*/
#define __NO_VERSION__
#include "hisax_hw.h"
#include "hisax_dch.h"
#include "hisaxl1.h"
#include "isac.h"
#include "arcofi.h"

View File

@ -20,6 +20,13 @@
#define ARCOFI_RX_END 3
#define ARCOFI_TIMEOUT 4
struct arcofi_msg {
struct arcofi_msg *next;
u_char receive;
u_char len;
u_char msg[10];
};
extern int arcofi_fsm(dchannel_t *, int, void *);
extern void init_arcofi(dchannel_t *);
extern void clear_arcofi(dchannel_t *);

View File

@ -12,12 +12,18 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel_stat.h>
#include "hisax_hw.h"
#include <linux/delay.h>
#include "hisax_dch.h"
#include "hisax_bch.h"
#include "isac.h"
#include "hisaxl1.h"
#include "helper.h"
#include "debug.h"
#define SPIN_DEBUG
#define LOCK_STATISTIC
#include "hw_lock.h"
static const char *avm_pci_rev = "$Revision$";
#define ISDN_CTYPE_FRITZPCI 1
@ -80,17 +86,38 @@ static const char *avm_pci_rev = "$Revision$";
/* data struct */
struct hdlc_stat_reg {
#ifdef __BIG_ENDIAN
u_char fill __attribute__((packed));
u_char mode __attribute__((packed));
u_char xml __attribute__((packed));
u_char cmd __attribute__((packed));
#else
u_char cmd __attribute__((packed));
u_char xml __attribute__((packed));
u_char mode __attribute__((packed));
u_char fill __attribute__((packed));
#endif
};
typedef struct hdlc_hw {
union {
u_int ctrl;
struct hdlc_stat_reg sr;
} ctrl;
u_int stat;
} hdlc_hw_t;
typedef struct _fritzpnppci {
struct _fritzpnppci *prev;
struct _fritzpnppci *next;
u_char subtyp;
u_int irq;
u_int addr;
spinlock_t devlock;
u_long flags;
#ifdef SPIN_DEBUG
void *lock_adr;
#endif
hisax_HWlock_t lock;
isac_chip_t isac;
hdlc_hw_t hdlc[2];
dchannel_t dch;
bchannel_t bch[2];
} fritzpnppci;
@ -98,24 +125,18 @@ typedef struct _fritzpnppci {
static void lock_dev(void *data)
{
register u_long flags;
register fritzpnppci *card = data;
spin_lock_irqsave(&card->devlock, flags);
card->flags = flags;
#ifdef SPIN_DEBUG
card->lock_adr = __builtin_return_address(0);
#endif
fritzpnppci *card = data;
register hisax_HWlock_t *lock = &card->lock;
lock_HW(lock);
}
static void unlock_dev(void *data)
{
register fritzpnppci *card = data;
spin_unlock_irqrestore(&card->devlock, card->flags);
#ifdef SPIN_DEBUG
card->lock_adr = NULL;
#endif
fritzpnppci *card = data;
register hisax_HWlock_t *lock = &card->lock;
unlock_HW(lock);
}
/* Interface functions */
@ -227,45 +248,39 @@ bchannel_t *Sel_BCS(fritzpnppci *fc, int channel)
return(NULL);
}
void inline
hdlc_sched_event(bchannel_t *bch, int event)
{
bch->event |= 1 << event;
queue_task(&bch->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
void
write_ctrl(bchannel_t *bch, int which) {
fritzpnppci *fc = bch->inst.data;
fritzpnppci *fc = bch->inst.data;
hdlc_hw_t *hdlc = bch->hw;
if (fc->dch.debug & L1_DEB_HSCX)
debugprint(&bch->inst, "hdlc %c wr%x ctrl %x",
'A' + bch->channel, which, bch->hw.hdlc.ctrl.ctrl);
'A' + bch->channel, which, hdlc->ctrl.ctrl);
if (fc->subtyp == AVM_FRITZ_PCI) {
WriteHDLCPCI(fc, bch->channel, HDLC_STATUS, bch->hw.hdlc.ctrl.ctrl);
WriteHDLCPCI(fc, bch->channel, HDLC_STATUS, hdlc->ctrl.ctrl);
} else {
if (which & 4)
WriteHDLCPnP(fc, bch->channel, HDLC_STATUS + 2,
bch->hw.hdlc.ctrl.sr.mode);
hdlc->ctrl.sr.mode);
if (which & 2)
WriteHDLCPnP(fc, bch->channel, HDLC_STATUS + 1,
bch->hw.hdlc.ctrl.sr.xml);
hdlc->ctrl.sr.xml);
if (which & 1)
WriteHDLCPnP(fc, bch->channel, HDLC_STATUS,
bch->hw.hdlc.ctrl.sr.cmd);
hdlc->ctrl.sr.cmd);
}
}
static int
modehdlc(bchannel_t *bch, int bc, int protocol)
{
int hdlc = bch->channel;
int hdlc_ch = bch->channel;
hdlc_hw_t *hdlc = bch->hw;
if (bch->debug & L1_DEB_HSCX)
debugprint(&bch->inst, "hdlc %c protocol %x-->%x ch %d-->%d",
'A' + hdlc, bch->protocol, protocol, hdlc, bc);
bch->hw.hdlc.ctrl.ctrl = 0;
'A' + hdlc_ch, bch->protocol, protocol, hdlc_ch, bc);
hdlc->ctrl.ctrl = 0;
switch (protocol) {
case (-1): /* used for init */
bch->protocol = -1;
@ -274,8 +289,8 @@ modehdlc(bchannel_t *bch, int bc, int protocol)
case (ISDN_PID_NONE):
if (bch->protocol == ISDN_PID_NONE)
break;
bch->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
bch->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
write_ctrl(bch, 5);
bch->protocol = ISDN_PID_NONE;
bch->channel = bc;
@ -283,24 +298,24 @@ modehdlc(bchannel_t *bch, int bc, int protocol)
case (ISDN_PID_L1_B_64TRANS):
bch->protocol = protocol;
bch->channel = bc;
bch->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
bch->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
write_ctrl(bch, 5);
bch->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
write_ctrl(bch, 1);
bch->hw.hdlc.ctrl.sr.cmd = 0;
hdlc_sched_event(bch, B_XMTBUFREADY);
hdlc->ctrl.sr.cmd = 0;
bch_sched_event(bch, B_XMTBUFREADY);
break;
case (ISDN_PID_L1_B_64HDLC):
bch->protocol = protocol;
bch->channel = bc;
bch->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
bch->hw.hdlc.ctrl.sr.mode = HDLC_MODE_ITF_FLG;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
write_ctrl(bch, 5);
bch->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
write_ctrl(bch, 1);
bch->hw.hdlc.ctrl.sr.cmd = 0;
hdlc_sched_event(bch, B_XMTBUFREADY);
hdlc->ctrl.sr.cmd = 0;
bch_sched_event(bch, B_XMTBUFREADY);
break;
default:
debugprint(&bch->inst, "prot not known %x", protocol);
@ -365,10 +380,11 @@ hdlc_empty_fifo(bchannel_t *bch, int count)
static void
hdlc_fill_fifo(bchannel_t *bch)
{
fritzpnppci *fc = bch->inst.data;
int count, cnt =0;
u_char *p;
u_int *ptr;
fritzpnppci *fc = bch->inst.data;
hdlc_hw_t *hdlc = bch->hw;
int count, cnt =0;
u_char *p;
u_int *ptr;
if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
debugprint(&bch->inst, __FUNCTION__);
@ -376,19 +392,19 @@ hdlc_fill_fifo(bchannel_t *bch)
if (count <= 0)
return;
p = bch->tx_buf + bch->tx_idx;
bch->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME;
hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
if (count > HDLC_FIFO_SIZE) {
count = HDLC_FIFO_SIZE;
} else {
if (bch->protocol != ISDN_PID_L1_B_64TRANS)
bch->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
}
if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
debugprint(&bch->inst, "%s: %d/%d", __FUNCTION__,
count, bch->tx_idx);
ptr = (u_int *) p;
bch->tx_idx += count;
bch->hw.hdlc.ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count);
hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count);
write_ctrl(bch, 3); /* sets the correct index too */
if (fc->subtyp == AVM_FRITZ_PCI) {
while (cnt<count) {
@ -423,8 +439,9 @@ hdlc_fill_fifo(bchannel_t *bch)
static void
HDLC_irq(bchannel_t *bch, u_int stat) {
int len;
struct sk_buff *skb;
int len;
struct sk_buff *skb;
hdlc_hw_t *hdlc = bch->hw;
if (bch->debug & L1_DEB_HSCX)
debugprint(&bch->inst, "ch%d stat %#x", bch->channel, stat);
@ -434,10 +451,10 @@ HDLC_irq(bchannel_t *bch, u_int stat) {
debugprint(&bch->inst, "RDO");
else
debugprint(&bch->inst, "ch%d stat %#x", bch->channel, stat);
bch->hw.hdlc.ctrl.sr.xml = 0;
bch->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_RRS;
hdlc->ctrl.sr.xml = 0;
hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;
write_ctrl(bch, 1);
bch->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS;
hdlc->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
write_ctrl(bch, 1);
bch->rx_idx = 0;
} else {
@ -455,7 +472,7 @@ HDLC_irq(bchannel_t *bch, u_int stat) {
skb_queue_tail(&bch->rqueue, skb);
}
bch->rx_idx = 0;
hdlc_sched_event(bch, B_RCVBUFREADY);
bch_sched_event(bch, B_RCVBUFREADY);
} else {
if (bch->debug & L1_DEB_HSCX)
debugprint(&bch->inst, "invalid frame");
@ -476,10 +493,10 @@ HDLC_irq(bchannel_t *bch, u_int stat) {
debugprint(&bch->inst, "ch%d XDU", bch->channel);
} else if (bch->debug & L1_DEB_WARN)
debugprint(&bch->inst, "ch%d XDU without data", bch->channel);
bch->hw.hdlc.ctrl.sr.xml = 0;
bch->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
hdlc->ctrl.sr.xml = 0;
hdlc->ctrl.sr.cmd |= HDLC_CMD_XRS;
write_ctrl(bch, 1);
bch->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
write_ctrl(bch, 1);
hdlc_fill_fifo(bch);
} else if (stat & HDLC_INT_XPR) {
@ -487,20 +504,20 @@ HDLC_irq(bchannel_t *bch, u_int stat) {
hdlc_fill_fifo(bch);
} else {
bch->tx_idx = 0;
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flag)) {
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
if (bch->next_skb) {
bch->tx_len = bch->next_skb->len;
memcpy(bch->tx_buf,
bch->next_skb->data, bch->tx_len);
hdlc_fill_fifo(bch);
hdlc_sched_event(bch, B_XMTBUFREADY);
bch_sched_event(bch, B_XMTBUFREADY);
} else {
printk(KERN_WARNING "hdlc tx irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
}
} else {
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
hdlc_sched_event(bch, B_XMTBUFREADY);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch_sched_event(bch, B_XMTBUFREADY);
}
}
}
@ -545,21 +562,48 @@ HDLC_irq_main(fritzpnppci *fc)
static void
avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
fritzpnppci *fc = dev_id;
fritzpnppci *fc = dev_id;
u_long flags;
u_char val;
u_char sval;
if (!fc) {
printk(KERN_WARNING "AVM PCI: Spurious interrupt!\n");
return;
}
lock_dev(fc);
spin_lock_irqsave(&fc->lock.lock, flags);
#ifdef SPIN_DEBUG
fc->lock.spin_adr = (void *)0x2001;
#endif
sval = inb(fc->addr + 2);
if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) {
/* possible a shared IRQ reqest */
unlock_dev(fc);
#ifdef SPIN_DEBUG
fc->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&fc->lock.lock, flags);
return;
}
if (test_and_set_bit(STATE_FLAG_BUSY, &fc->lock.state)) {
printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%x\n",
__FUNCTION__, fc->lock.state);
#ifdef SPIN_DEBUG
printk(KERN_ERR "%s: previous lock:%p\n",
__FUNCTION__, fc->lock.busy_adr);
#endif
#ifdef LOCK_STATISTIC
fc->lock.irq_fail++;
#endif
} else {
#ifdef LOCK_STATISTIC
fc->lock.irq_ok++;
#endif
#ifdef SPIN_DEBUG
fc->lock.busy_adr = avm_pcipnp_interrupt;
#endif
}
test_and_set_bit(STATE_FLAG_INIRQ, &fc->lock.state);
#ifdef SPIN_DEBUG
fc->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&fc->lock.lock, flags);
if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
val = ReadISAC(fc, ISAC_ISTA);
ISAC_interrupt(&fc->dch, val);
@ -569,7 +613,21 @@ avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
WriteISAC(fc, ISAC_MASK, 0xFF);
WriteISAC(fc, ISAC_MASK, 0x0);
unlock_dev(fc);
spin_lock_irqsave(&fc->lock.lock, flags);
#ifdef SPIN_DEBUG
fc->lock.spin_adr = (void *)0x2002;
#endif
if (!test_and_clear_bit(STATE_FLAG_INIRQ, &fc->lock.state)) {
}
if (!test_and_clear_bit(STATE_FLAG_BUSY, &fc->lock.state)) {
printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%x)\n",
__FUNCTION__, fc->lock.state);
}
#ifdef SPIN_DEBUG
fc->lock.busy_adr = NULL;
fc->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&fc->lock.lock, flags);
}
static int
@ -590,8 +648,8 @@ hdlc_down(hisaxif_t *hif, struct sk_buff *skb)
return(-EBUSY);
}
bch->inst.lock(bch->inst.data);
if (test_and_set_bit(FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(FLG_TX_NEXT, &bch->Flag);
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
bch->next_skb = skb;
bch->inst.unlock(bch->inst.data);
return(0);
@ -621,11 +679,11 @@ hdlc_down(hisaxif_t *hif, struct sk_buff *skb)
(hh->prim == (DL_RELEASE | REQUEST)) ||
(hh->prim == (MGR_DISCONNECT | REQUEST))) {
bch->inst.lock(bch->inst.data);
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flag)) {
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL;
}
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
modehdlc(bch, bch->channel, 0);
test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
bch->inst.unlock(bch->inst.data);
@ -899,20 +957,20 @@ setup_fritz(fritzpnppci *fc, u_int io_cfg, u_int irq_cfg)
printk(KERN_INFO "AVM PCI: stat %#x\n", val);
printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
val & 0xff, (val>>8) & 0xff);
fc->bch[0].BC_Read_Reg = &ReadHDLC_s;
fc->bch[0].BC_Write_Reg = &WriteHDLC_s;
fc->bch[1].BC_Read_Reg = &ReadHDLC_s;
fc->bch[1].BC_Write_Reg = &WriteHDLC_s;
fc->bch[0].Read_Reg = &ReadHDLC_s;
fc->bch[0].Write_Reg = &WriteHDLC_s;
fc->bch[1].Read_Reg = &ReadHDLC_s;
fc->bch[1].Write_Reg = &WriteHDLC_s;
break;
case AVM_FRITZ_PNP:
val = inb(fc->addr);
ver = inb(fc->addr + 1);
printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
reset_avmpcipnp(fc);
fc->bch[0].BC_Read_Reg = &ReadHDLCPnP;
fc->bch[0].BC_Write_Reg = &WriteHDLCPnP;
fc->bch[1].BC_Read_Reg = &ReadHDLCPnP;
fc->bch[1].BC_Write_Reg = &WriteHDLCPnP;
fc->bch[0].Read_Reg = &ReadHDLCPnP;
fc->bch[0].Write_Reg = &WriteHDLCPnP;
fc->bch[1].Read_Reg = &ReadHDLCPnP;
fc->bch[1].Write_Reg = &WriteHDLCPnP;
break;
default:
printk(KERN_WARNING "AVM unknown subtype %d\n", fc->subtyp);
@ -926,9 +984,11 @@ setup_fritz(fritzpnppci *fc, u_int io_cfg, u_int irq_cfg)
fc->dch.write_reg = &WriteISAC;
fc->dch.read_fifo = &ReadISACfifo;
fc->dch.write_fifo = &WriteISACfifo;
fc->dch.hw = &fc->isac;
lock_dev(fc);
#ifdef SPIN_DEBUG
printk(KERN_ERR "lock_adr=%p now(%p)\n", &fc->lock_adr, fc->lock_adr);
printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &fc->lock.busy_adr, fc->lock.busy_adr);
printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &fc->lock.busy_adr, fc->lock.busy_adr);
#endif
unlock_dev(fc);
return(0);
@ -1120,7 +1180,7 @@ Fritz_init(void)
APPEND_TO_LIST(card, ((fritzpnppci *)fritz.ilist));
card->dch.debug = debug;
card->dch.inst.obj = &fritz;
spin_lock_init(&card->devlock);
lock_HW_init(&card->lock);
card->dch.inst.lock = lock_dev;
card->dch.inst.unlock = unlock_dev;
card->dch.inst.data = card;
@ -1149,6 +1209,7 @@ Fritz_init(void)
sprintf(card->bch[i].inst.name, "%s B%d",
card->dch.inst.name, i+1);
init_bchannel(&card->bch[i]);
card->bch[i].hw = &card->hdlc[i];
}
printk(KERN_DEBUG "fritz card %p dch %p bch1 %p bch2 %p\n",
card, &card->dch, &card->bch[0], &card->bch[1]);

View File

@ -0,0 +1,79 @@
/* $Id$
*
* Basic declarations, defines for Bchannel hardware
*
* This file is (c) under GNU PUBLIC LICENSE
*
*/
#include <linux/hisaxif.h>
#include <linux/tqueue.h>
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/skbuff.h>
#ifdef MEMDBG
#include "memdbg.h"
#endif
#define MAX_BLOG_SPACE 256
#define BC_FLG_INIT 1
#define BC_FLG_ACTIV 2
#define BC_FLG_TX_BUSY 3
#define BC_FLG_NOFRAME 4
#define BC_FLG_HALF 5
#define BC_FLG_EMPTY 6
#define BC_FLG_ORIG 7
#define BC_FLG_DLEETX 8
#define BC_FLG_LASTDLE 9
#define BC_FLG_FIRST 10
#define BC_FLG_LASTDATA 11
#define BC_FLG_NMD_DATA 12
#define BC_FLG_FTI_RUN 13
#define BC_FLG_LL_OK 14
#define BC_FLG_LL_CONN 15
#define BC_FLG_TX_NEXT 16
typedef struct _bchannel_t {
int channel;
int protocol;
int Flag;
int debug;
hisaxstack_t *st;
hisaxinstance_t inst;
hisaxdevice_t *dev;
void *hw;
u_char (*Read_Reg)(void *, int, u_char);
void (*Write_Reg)(void *, int, u_char, u_char);
struct sk_buff *next_skb;
u_char *tx_buf;
int tx_idx;
int tx_len;
u_char *rx_buf;
int rx_idx;
struct sk_buff_head rqueue; /* B-Channel receive Queue */
u_char *blog;
u_char *conmsg;
struct timer_list transbusy;
struct tq_struct tqueue;
int event;
int err_crc;
int err_tx;
int err_rdo;
int err_inv;
} bchannel_t;
extern int init_bchannel(bchannel_t *);
extern int free_bchannel(bchannel_t *);
static inline void
bch_sched_event(bchannel_t *bch, int event)
{
test_and_set_bit(event, &bch->event);
queue_task(&bch->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}

View File

@ -0,0 +1,99 @@
/* $Id$
*
* Basic declarations for dchannel HW
*
* This file is (c) under GNU PUBLIC LICENSE
*
*/
#include <linux/hisaxif.h>
#include <linux/tqueue.h>
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/skbuff.h>
#ifdef MEMDBG
#include "memdbg.h"
#endif
#define MAX_DFRAME_LEN_L1 300
#define MAX_MON_FRAME 32
#define MAX_DLOG_SPACE 2048
#define HW_IOM1 0
#define HW_IPAC 1
#define HW_ISAR 2
#define HW_ARCOFI 3
#define FLG_TWO_DCHAN 4
#define FLG_TX_BUSY 5
#define FLG_TX_NEXT 6
#define FLG_L1_DBUSY 7
#define FLG_DBUSY_TIMER 8
#define FLG_LOCK_ATOMIC 9
#define FLG_ARCOFI_TIMER 10
#define FLG_ARCOFI_ERROR 11
#define FLG_HW_L1_UINT 12
#define FLG_HW_INIT 13
typedef struct _dchannel_t {
hisaxinstance_t inst;
u_int DFlags;
u_int type;
u_int ph_state;
u_char (*read_reg) (void *, u_char);
void (*write_reg) (void *, u_char, u_char);
void (*read_fifo) (void *, u_char *, int);
void (*write_fifo) (void *, u_char *, int);
char *dlog;
int debug;
struct sk_buff *rx_skb;
struct sk_buff *next_skb;
u_char *tx_buf;
int tx_idx;
int tx_len;
int err_crc;
int err_tx;
int err_rx;
void *hw;
struct timer_list dbusytimer;
u_int event;
struct sk_buff_head rqueue; /* D-channel receive queue */
struct tq_struct tqueue;
void (*hw_bh) (struct _dchannel_t *);
} dchannel_t;
#define MON0_RX 1
#define MON1_RX 2
#define MON0_TX 4
#define MON1_TX 8
extern int init_dchannel(dchannel_t *);
extern int free_dchannel(dchannel_t *);
void set_dchannel_pid(hisax_pid_t *, int, int);
static inline void
dchannel_sched_event(dchannel_t *dch, int event)
{
test_and_set_bit(event, &dch->event);
queue_task(&dch->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
#ifdef __powerpc__
#include <linux/pci.h>
static inline int pci_enable_device(struct pci_dev *dev)
{
u16 cmd;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_SERR;
cmd &= ~PCI_COMMAND_FAST_BACK;
pci_write_config_word(dev, PCI_COMMAND, cmd);
return(0);
}
#else
#define pci_enable_device(dev) !dev
#endif /* __powerpc__ */

View File

@ -9,56 +9,7 @@
#define __NO_VERSION__
#include <linux/hisaxif.h>
#include "helper.h"
#include "hisax_hw.h"
int
init_dchannel(dchannel_t *dch) {
if (!(dch->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for dlog\n");
return(-ENOMEM);
}
if (!(dch->tx_buf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for dchannel tx_buf\n");
kfree(dch->dlog);
dch->dlog = NULL;
return(-ENOMEM);
}
dch->hw = NULL;
dch->rx_skb = NULL;
dch->tx_idx = 0;
dch->next_skb = NULL;
dch->event = 0;
dch->tqueue.data = dch;
skb_queue_head_init(&dch->rqueue);
return(0);
}
int
free_dchannel(dchannel_t *dch) {
if (dch->tqueue.sync)
printk(KERN_ERR"free_dchannel tqueue.sync\n");
discard_queue(&dch->rqueue);
if (dch->rx_skb) {
dev_kfree_skb(dch->rx_skb);
dch->rx_skb = NULL;
}
if (dch->tx_buf) {
kfree(dch->tx_buf);
dch->tx_buf = NULL;
}
if (dch->next_skb) {
dev_kfree_skb(dch->next_skb);
dch->next_skb = NULL;
}
if (dch->dlog) {
kfree(dch->dlog);
dch->dlog = NULL;
}
return(0);
}
#include "hisax_bch.h"
int
init_bchannel(bchannel_t *bch) {
@ -164,29 +115,6 @@ int bprotocol2pid(void *bp, hisax_pid_t *pid) {
return(0);
}
void
set_dchannel_pid(hisax_pid_t *pid, int protocol, int layermask) {
if (!layermask)
layermask = ISDN_LAYER(0)| ISDN_LAYER(1) | ISDN_LAYER(2) |
ISDN_LAYER(3) | ISDN_LAYER(4);
memset(pid, 0, sizeof(hisax_pid_t));
pid->layermask = layermask;
if (layermask & ISDN_LAYER(0))
pid->protocol[0] = ISDN_PID_L0_TE_S0;
if (layermask & ISDN_LAYER(1))
pid->protocol[1] = ISDN_PID_L1_TE_S0;
if (layermask & ISDN_LAYER(2))
pid->protocol[2] = ISDN_PID_L2_LAPD;
if (layermask & ISDN_LAYER(3)) {
if (protocol == 2)
pid->protocol[3] = ISDN_PID_L3_DSS1USER;
}
if (layermask & ISDN_LAYER(4))
pid->protocol[4] = ISDN_PID_L4_CAPI20;
}
int
HasProtocol(hisaxobject_t *obj, int protocol)
{

View File

@ -31,13 +31,18 @@
#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include "hisax_hw.h"
#include "hisax_dch.h"
#include "hisax_bch.h"
#include "hfc_pci.h"
#include "hisaxl1.h"
#include "helper.h"
#include "debug.h"
#include <linux/isdn_compat.h>
#define SPIN_DEBUG
#define LOCK_STATISTIC
#include "hw_lock.h"
#define HFC_INFO(txt) printk(KERN_DEBUG txt)
extern const char *CardType[];
@ -126,7 +131,6 @@ struct hfcPCI_hw {
unsigned char mst_m;
unsigned char int_m1;
unsigned char int_m2;
unsigned char int_s1;
unsigned char sctrl;
unsigned char sctrl_r;
unsigned char sctrl_e;
@ -163,11 +167,7 @@ typedef struct _hfc_pci {
u_int cfg;
u_int irq;
hfcPCI_hw_t hw;
spinlock_t devlock;
u_long flags;
#ifdef SPIN_DEBUG
void *lock_adr;
#endif
hisax_HWlock_t lock;
dchannel_t dch;
bchannel_t bch[2];
} hfc_pci_t;
@ -175,24 +175,16 @@ typedef struct _hfc_pci {
static void lock_dev(void *data)
{
register u_long flags;
register hfc_pci_t *card = data;
spin_lock_irqsave(&card->devlock, flags);
card->flags = flags;
#ifdef SPIN_DEBUG
card->lock_adr = __builtin_return_address(0);
#endif
register hisax_HWlock_t *lock = &((hfc_pci_t *)data)->lock;
lock_HW(lock);
}
static void unlock_dev(void *data)
{
register hfc_pci_t *card = data;
register hisax_HWlock_t *lock = &((hfc_pci_t *)data)->lock;
spin_unlock_irqrestore(&card->devlock, card->flags);
#ifdef SPIN_DEBUG
card->lock_adr = NULL;
#endif
unlock_HW(lock);
}
/* Interface functions */
@ -203,13 +195,8 @@ static void unlock_dev(void *data)
void
release_io_hfcpci(hfc_pci_t *hc)
{
int flags;
save_flags(flags);
cli();
hc->hw.int_m2 = 0; /* interrupt output off ! */
Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
restore_flags(flags);
Write_hfc(hc, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
@ -230,15 +217,12 @@ release_io_hfcpci(hfc_pci_t *hc)
static void
reset_hfcpci(hfc_pci_t *hc)
{
long flags;
u_char val;
int cnt = 0;
HFC_INFO("reset_hfcpci: entered\n");
val = Read_hfc(hc, HFCPCI_CHIP_ID);
printk(KERN_INFO "HFC_PCI: resetting HFC ChipId(%x)\n", val);
save_flags(flags);
cli();
pcibios_write_config_word(hc->hw.pci_bus, hc->hw.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */
hc->hw.int_m2 = 0; /* interrupt output off ! */
Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
@ -247,11 +231,8 @@ reset_hfcpci(hfc_pci_t *hc)
printk(KERN_DEBUG "HFC-PCI status(%x) before reset\n", val);
hc->hw.cirm = HFCPCI_RESET; /* Reset On */
Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
restore_flags(flags);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
save_flags(flags);
cli();
hc->hw.cirm = 0; /* Reset Off */
Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
val = Read_hfc(hc, HFCPCI_STATUS);
@ -333,7 +314,6 @@ reset_hfcpci(hfc_pci_t *hc)
}
Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
val = Read_hfc(hc, HFCPCI_INT_S2);
restore_flags(flags);
}
/***************************************************/
@ -350,28 +330,6 @@ hfcpci_Timer(hfc_pci_t *hc)
}
/*********************************/
/* schedule a new D-channel task */
/*********************************/
static void
sched_event_D_pci(hfc_pci_t *hc, int event)
{
test_and_set_bit(event, &hc->dch.event);
queue_task(&hc->dch.tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
/*********************************/
/* schedule a new b_channel task */
/*********************************/
static void
hfcpci_sched_event(bchannel_t *bch, int event)
{
bch->event |= 1 << event;
queue_task(&bch->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
/************************************************/
/* select a b-channel entry matching and active */
/************************************************/
@ -520,10 +478,6 @@ receive_dmsg(hfc_pci_t *hc)
z_type *zp;
df = &((fifo_area *) (hc->hw.fifos))->d_chan.d_rx;
if (test_and_set_bit(FLG_LOCK_ATOMIC, &dch->DFlags)) {
debugprint(&dch->inst, "rec_dmsg blocked");
return (1);
}
while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) {
zp = &df->za[df->f2 & D_FREG_MASK];
rcnt = zp->z1 - zp->z2;
@ -575,11 +529,10 @@ receive_dmsg(hfc_pci_t *hc)
debugprint(&dch->inst, dch->dlog);
}
skb_queue_tail(&dch->rqueue, skb);
sched_event_D_pci(hc, D_RCVBUFREADY);
dchannel_sched_event(dch, D_RCVBUFREADY);
} else
printk(KERN_WARNING "HFC-PCI: D receive out of memory\n");
}
test_and_clear_bit(FLG_LOCK_ATOMIC, &dch->DFlags);
return (1);
}
@ -628,7 +581,7 @@ hfcpci_empty_fifo_trans(bchannel_t *bch, bzfifo_type * bz, u_char * bdata)
memcpy(ptr, ptr1, fcnt); /* rest */
}
skb_queue_tail(&bch->rqueue, skb);
hfcpci_sched_event(bch, B_RCVBUFREADY);
bch_sched_event(bch, B_RCVBUFREADY);
}
*z2r = new_z2; /* new position */
@ -641,7 +594,6 @@ hfcpci_empty_fifo_trans(bchannel_t *bch, bzfifo_type * bz, u_char * bdata)
void
main_rec_hfcpci(bchannel_t *bch)
{
long flags;
hfc_pci_t *hc = bch->inst.data;
int rcnt, real_fifo;
int receive, count = 5;
@ -662,14 +614,6 @@ main_rec_hfcpci(bchannel_t *bch)
}
Begin:
count--;
save_flags(flags);
cli();
if (test_and_set_bit(FLG_LOCK_ATOMIC, &hc->dch.DFlags)) {
restore_flags(flags);
debugprint(&bch->inst, "rec_data ch(%x) blocked", bch->channel);
return;
}
restore_flags(flags);
if (bz->f1 != bz->f2) {
if (bch->debug & L1_DEB_HSCX)
debugprint(&bch->inst, "hfcpci rec ch(%x) f1(%d) f2(%d)",
@ -685,7 +629,7 @@ main_rec_hfcpci(bchannel_t *bch)
bch->channel, zp->z1, zp->z2, rcnt);
if ((skb = hfcpci_empty_fifo(bch, bz, bdata, rcnt))) {
skb_queue_tail(&bch->rqueue, skb);
hfcpci_sched_event(bch, B_RCVBUFREADY);
bch_sched_event(bch, B_RCVBUFREADY);
}
rcnt = bz->f1 - bz->f2;
if (rcnt < 0)
@ -703,7 +647,6 @@ main_rec_hfcpci(bchannel_t *bch)
receive = hfcpci_empty_fifo_trans(bch, bz, bdata);
else
receive = 0;
test_and_clear_bit(FLG_LOCK_ATOMIC, &hc->dch.DFlags);
if (count && receive)
goto Begin;
return;
@ -716,7 +659,6 @@ static void
hfcpci_fill_dfifo(hfc_pci_t *hc)
{
dchannel_t *dch = &hc->dch;
long flags;
int fcnt;
int count, new_z1, maxlen;
dfifo_type *df;
@ -773,12 +715,9 @@ hfcpci_fill_dfifo(hfc_pci_t *hc)
src += maxlen; /* new position */
memcpy(dst, src, count);
}
save_flags(flags);
cli();
df->za[new_f1 & D_FREG_MASK].z1 = new_z1; /* for next buffer */
df->za[df->f1 & D_FREG_MASK].z1 = new_z1; /* new pos actual buffer */
df->f1 = new_f1; /* next frame */
restore_flags(flags);
if (dch->debug & L1_DEB_ISAC_FIFO) {
char *t = dch->dlog;
@ -792,20 +731,6 @@ hfcpci_fill_dfifo(hfc_pci_t *hc)
return;
}
static void
hfcD_send_fifo(dchannel_t *dch)
{
hfc_pci_t *hc = dch->inst.data;
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &dch->DFlags)) {
hfcpci_fill_dfifo(hc);
test_and_clear_bit(FLG_LOCK_ATOMIC, &dch->DFlags);
} else {
debugprint(&dch->inst, "hfcpci_fill_dfifo blocked");
sched_event_D_pci(hc, D_BLOCKEDATOMIC);
}
}
/**************************/
/* B-channel send routine */
/**************************/
@ -813,7 +738,7 @@ static void
hfcpci_fill_fifo(bchannel_t *bch)
{
hfc_pci_t *hc = bch->inst.data;
int flags, maxlen, fcnt;
int maxlen, fcnt;
int count, new_z1;
bzfifo_type *bz;
u_char *bdata;
@ -873,19 +798,19 @@ next_t_frame:
} else if (bch->debug & L1_DEB_HSCX)
debugprint(&bch->inst, "hfcpci_fill_fifo_trans ch(%x) frame length %d discarded",
bch->channel, bch->tx_len);
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flag)) {
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
if (bch->next_skb) {
bch->tx_idx = 0;
bch->tx_len = bch->next_skb->len;
memcpy(bch->tx_buf,
bch->next_skb->data,
bch->tx_len);
hfcpci_sched_event(bch, B_XMTBUFREADY);
bch_sched_event(bch, B_XMTBUFREADY);
goto next_t_frame;
} else
printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
}
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch->tx_idx = bch->tx_len;
}
return;
@ -934,32 +859,13 @@ next_t_frame:
src += maxlen; /* new position */
memcpy(dst, src, count);
}
save_flags(flags);
cli();
bz->za[new_f1].z1 = new_z1; /* for next buffer */
bz->f1 = new_f1; /* next frame */
restore_flags(flags);
bch->tx_idx = bch->tx_len;
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
return;
}
/**************************************/
/* send B-channel data if not blocked */
/**************************************/
static void
hfcpci_send_data(bchannel_t *bch)
{
hfc_pci_t *hc = bch->inst.data;
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &hc->dch.DFlags)) {
hfcpci_fill_fifo(bch);
test_and_clear_bit(FLG_LOCK_ATOMIC, &hc->dch.DFlags);
} else {
debugprint(&bch->inst, "send_data ch(%x) blocked", bch->channel);
hfcpci_sched_event(bch, B_BLOCKEDATOMIC);
}
}
#if 0
/**********************************************/
@ -1003,13 +909,10 @@ dch_nt_l2l1(struct PStack *st, int pr, void *arg)
static int
hfcpci_auxcmd(hfc_pci_t *hc, isdn_ctrl * ic)
{
int flags;
int i = *(unsigned int *) ic->parm.num;
if ((ic->arg == 98) &&
(!(hc->hw.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) {
save_flags(flags);
cli();
hc->hw.clkdel = CLKDEL_NT; /* ST-Bit delay for NT-Mode */
Write_hfc(hc, HFCPCI_CLKDEL, hc->hw.clkdel);
Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* HFC ST G0 */
@ -1024,7 +927,6 @@ hfcpci_auxcmd(hfc_pci_t *hc, isdn_ctrl * ic)
hc->hw.nt_mode = 1;
hc->hw.nt_timer = 0;
cs->stlist->l2.l2l1 = dch_nt_l2l1;
restore_flags(flags);
debugl1(hc, "NT mode activated");
return (0);
}
@ -1032,8 +934,6 @@ hfcpci_auxcmd(hfc_pci_t *hc, isdn_ctrl * ic)
(hc->hw.nt_mode) || (ic->arg != 12))
return (-EINVAL);
save_flags(flags);
cli();
if (i) {
cs->logecho = 1;
hc->hw.trm |= 0x20; /* enable echo chan */
@ -1056,7 +956,6 @@ hfcpci_auxcmd(hfc_pci_t *hc, isdn_ctrl * ic)
Write_hfc(hc, HFCPCI_TRM, hc->hw.trm);
Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
restore_flags(flags);
return (0);
} /* hfcpci_auxcmd */
@ -1066,7 +965,6 @@ hfcpci_auxcmd(hfc_pci_t *hc, isdn_ctrl * ic)
static void
receive_emsg(hfc_pci_t *hc)
{
long flags;
int rcnt;
int receive, count = 5;
bzfifo_type *bz;
@ -1076,18 +974,10 @@ receive_emsg(hfc_pci_t *hc)
int total, maxlen, new_z2;
u_char e_buffer[256];
save_flags(flags);
bz = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b2;
bdata = ((fifo_area *) (hc->hw.fifos))->b_chans.rxdat_b2;
Begin:
count--;
cli();
if (test_and_set_bit(FLG_LOCK_ATOMIC, &dch->DFlags)) {
debugl1(hc, "echo_rec_data blocked");
restore_flags(flags);
return;
}
sti();
if (bz->f1 != bz->f2) {
if (hc->debug & L1_DEB_ISAC)
debugl1(hc, "hfcpci e_rec f1(%d) f2(%d)",
@ -1159,10 +1049,8 @@ receive_emsg(hfc_pci_t *hc)
receive = 0;
} else
receive = 0;
test_and_clear_bit(FLG_LOCK_ATOMIC, &dch->DFlags);
if (count && receive)
goto Begin;
restore_flags(flags);
return;
} /* receive_emsg */
@ -1177,28 +1065,61 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
hfc_pci_t *hc = dev_id;
u_char exval;
bchannel_t *bch;
int count = 15;
long flags;
u_char val, stat;
if (!hc) {
printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n");
return;
}
if (!(hc->hw.int_m2 & 0x08))
spin_lock_irqsave(&hc->lock.lock, flags);
#ifdef SPIN_DEBUG
hc->lock.spin_adr = (void *)0x3001;
#endif
if (!(hc->hw.int_m2 & 0x08)) {
#ifdef SPIN_DEBUG
hc->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&hc->lock.lock, flags);
return; /* not initialised */
}
if (HFCPCI_ANYINT & (stat = Read_hfc(hc, HFCPCI_STATUS))) {
val = Read_hfc(hc, HFCPCI_INT_S1);
if (hc->dch.debug & L1_DEB_ISAC)
debugprint(&hc->dch.inst, "HFC-PCI: stat(%02x) s1(%02x)",
stat, val);
} else
} else {
/* shared */
#ifdef SPIN_DEBUG
hc->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&hc->lock.lock, flags);
return;
}
if (test_and_set_bit(STATE_FLAG_BUSY, &hc->lock.state)) {
printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%x\n",
__FUNCTION__, hc->lock.state);
#ifdef SPIN_DEBUG
printk(KERN_ERR "%s: previous lock:%p\n",
__FUNCTION__, hc->lock.busy_adr);
#endif
#ifdef LOCK_STATISTIC
hc->lock.irq_fail++;
#endif
} else {
#ifdef LOCK_STATISTIC
hc->lock.irq_ok++;
#endif
#ifdef SPIN_DEBUG
hc->lock.busy_adr = hfcpci_interrupt;
#endif
}
test_and_set_bit(STATE_FLAG_INIRQ, &hc->lock.state);
#ifdef SPIN_DEBUG
hc->lock.spin_adr= NULL;
#endif
spin_unlock_irqrestore(&hc->lock.lock, flags);
if (hc->dch.debug & L1_DEB_ISAC)
debugprint(&hc->dch.inst, "HFC-PCI irq %x %s", val,
test_bit(FLG_LOCK_ATOMIC, &hc->dch.DFlags) ?
"locked" : "unlocked");
debugprint(&hc->dch.inst, "HFC-PCI irq %x", val);
val &= hc->hw.int_m1;
if (val & 0x40) { /* state machine irq */
exval = Read_hfc(hc, HFCPCI_STATES) & 0xf;
@ -1206,144 +1127,137 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
debugprint(&hc->dch.inst, "ph_state chg %d->%d",
hc->dch.ph_state, exval);
hc->dch.ph_state = exval;
sched_event_D_pci(hc, D_L1STATECHANGE);
dchannel_sched_event(&hc->dch, D_L1STATECHANGE);
val &= ~0x40;
}
if (val & 0x80) { /* timer irq */
if (hc->hw.nt_mode) {
if ((--hc->hw.nt_timer) < 0)
sched_event_D_pci(hc, D_L1STATECHANGE);
dchannel_sched_event(&hc->dch, D_L1STATECHANGE);
}
val &= ~0x80;
Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
}
while (val) {
save_flags(flags);
cli();
if (test_bit(FLG_LOCK_ATOMIC, &hc->dch.DFlags)) {
hc->hw.int_s1 |= val;
restore_flags(flags);
return;
}
if (hc->hw.int_s1 & 0x18) {
exval = val;
val = hc->hw.int_s1;
hc->hw.int_s1 = exval;
}
if (val & 0x08) {
if (!(bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1))) {
if (hc->dch.debug)
debugprint(&hc->dch.inst, "hfcpci spurious 0x08 IRQ");
} else
main_rec_hfcpci(bch);
}
if (val & 0x10) {
// if (hc->logecho)
// receive_emsg(hc);
// else
if (!(bch = Sel_BCS(hc, 2))) {
if (hc->dch.debug)
debugprint(&hc->dch.inst, "hfcpci spurious 0x10 IRQ");
} else
main_rec_hfcpci(bch);
}
if (val & 0x01) {
if (!(bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1))) {
if (hc->dch.debug)
debugprint(&hc->dch.inst, "hfcpci spurious 0x01 IRQ");
} else {
if (bch->tx_idx < bch->tx_len) {
hfcpci_send_data(bch);
} else {
bch->tx_idx = 0;
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flag)) {
if (bch->next_skb) {
bch->tx_len = bch->next_skb->len;
memcpy(bch->tx_buf,
bch->next_skb->data,
bch->tx_len);
hfcpci_send_data(bch);
hfcpci_sched_event(bch, B_XMTBUFREADY);
} else {
printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
bch->tx_len = 0;
}
} else {
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
hfcpci_sched_event(bch, B_XMTBUFREADY);
bch->tx_len = 0;
}
}
}
}
if (val & 0x02) {
if (!(bch = Sel_BCS(hc, 2))) {
if (hc->dch.debug)
debugprint(&hc->dch.inst, "hfcpci spurious 0x02 IRQ");
} else {
if (bch->tx_idx < bch->tx_len) {
hfcpci_send_data(bch);
} else {
bch->tx_idx = 0;
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flag)) {
if (bch->next_skb) {
bch->tx_len = bch->next_skb->len;
memcpy(bch->tx_buf,
bch->next_skb->data,
bch->tx_len);
hfcpci_send_data(bch);
hfcpci_sched_event(bch, B_XMTBUFREADY);
} else {
printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
bch->tx_len = 0;
}
} else {
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
hfcpci_sched_event(bch, B_XMTBUFREADY);
bch->tx_len = 0;
}
}
}
}
if (val & 0x20) { /* receive dframe */
receive_dmsg(hc);
}
if (val & 0x04) { /* dframe transmitted */
if (test_and_clear_bit(FLG_DBUSY_TIMER, &hc->dch.DFlags))
del_timer(&hc->dch.dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &hc->dch.DFlags))
sched_event_D_pci(hc, D_CLEARBUSY);
if (hc->dch.tx_idx < hc->dch.tx_len) {
hfcD_send_fifo(&hc->dch);
} else {
if (test_and_clear_bit(FLG_TX_NEXT, &hc->dch.DFlags)) {
if (hc->dch.next_skb) {
hc->dch.tx_len = hc->dch.next_skb->len;
memcpy(hc->dch.tx_buf,
hc->dch.next_skb->data,
hc->dch.tx_len);
hc->dch.tx_idx = 0;
hfcD_send_fifo(&hc->dch);
sched_event_D_pci(hc, D_XMTBUFREADY);
} else {
printk(KERN_WARNING "hfcd tx irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags);
}
} else
test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags);
}
}
if (hc->hw.int_s1 && count--) {
val = hc->hw.int_s1;
hc->hw.int_s1 = 0;
if (hc->dch.debug & L1_DEB_ISAC)
debugprint(&hc->dch.inst, "HFC-PCI irq %x loop %d", val, 15 - count);
if (val & 0x08) {
if (!(bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1))) {
if (hc->dch.debug)
debugprint(&hc->dch.inst, "hfcpci spurious 0x08 IRQ");
} else
val = 0;
restore_flags(flags);
main_rec_hfcpci(bch);
}
if (val & 0x10) {
// if (hc->logecho)
// receive_emsg(hc);
// else
if (!(bch = Sel_BCS(hc, 2))) {
if (hc->dch.debug)
debugprint(&hc->dch.inst, "hfcpci spurious 0x10 IRQ");
} else
main_rec_hfcpci(bch);
}
if (val & 0x01) {
if (!(bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1))) {
if (hc->dch.debug)
debugprint(&hc->dch.inst, "hfcpci spurious 0x01 IRQ");
} else {
if (bch->tx_idx < bch->tx_len) {
hfcpci_fill_fifo(bch);
} else {
bch->tx_idx = 0;
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
if (bch->next_skb) {
bch->tx_len = bch->next_skb->len;
memcpy(bch->tx_buf,
bch->next_skb->data,
bch->tx_len);
hfcpci_fill_fifo(bch);
bch_sched_event(bch, B_XMTBUFREADY);
} else {
printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch->tx_len = 0;
}
} else {
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch_sched_event(bch, B_XMTBUFREADY);
bch->tx_len = 0;
}
}
}
}
if (val & 0x02) {
if (!(bch = Sel_BCS(hc, 2))) {
if (hc->dch.debug)
debugprint(&hc->dch.inst, "hfcpci spurious 0x02 IRQ");
} else {
if (bch->tx_idx < bch->tx_len) {
hfcpci_fill_fifo(bch);
} else {
bch->tx_idx = 0;
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
if (bch->next_skb) {
bch->tx_len = bch->next_skb->len;
memcpy(bch->tx_buf,
bch->next_skb->data,
bch->tx_len);
hfcpci_fill_fifo(bch);
bch_sched_event(bch, B_XMTBUFREADY);
} else {
printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch->tx_len = 0;
}
} else {
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch_sched_event(bch, B_XMTBUFREADY);
bch->tx_len = 0;
}
}
}
}
if (val & 0x20) { /* receive dframe */
receive_dmsg(hc);
}
if (val & 0x04) { /* dframe transmitted */
if (test_and_clear_bit(FLG_DBUSY_TIMER, &hc->dch.DFlags))
del_timer(&hc->dch.dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &hc->dch.DFlags))
dchannel_sched_event(&hc->dch, D_CLEARBUSY);
if (hc->dch.tx_idx < hc->dch.tx_len) {
hfcpci_fill_dfifo(hc);
} else {
if (test_and_clear_bit(FLG_TX_NEXT, &hc->dch.DFlags)) {
if (hc->dch.next_skb) {
hc->dch.tx_len = hc->dch.next_skb->len;
memcpy(hc->dch.tx_buf,
hc->dch.next_skb->data,
hc->dch.tx_len);
hc->dch.tx_idx = 0;
hfcpci_fill_dfifo(hc);
dchannel_sched_event(&hc->dch, D_XMTBUFREADY);
} else {
printk(KERN_WARNING "hfcd tx irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags);
}
} else
test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags);
}
}
spin_lock_irqsave(&hc->lock.lock, flags);
#ifdef SPIN_DEBUG
hc->lock.spin_adr = (void *)0x3002;
#endif
if (!test_and_clear_bit(STATE_FLAG_INIRQ, &hc->lock.state)) {
}
if (!test_and_clear_bit(STATE_FLAG_BUSY, &hc->lock.state)) {
printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%x)\n",
__FUNCTION__, hc->lock.state);
}
#ifdef SPIN_DEBUG
hc->lock.busy_adr = NULL;
hc->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&hc->lock.lock, flags);
}
/********************************************************************/
@ -1364,7 +1278,6 @@ HFCD_l1hw(hisaxif_t *hif, struct sk_buff *skb)
hfc_pci_t *hc;
int ret = -EINVAL;
hisax_head_t *hh;
long flags;
if (!hif || !skb)
return(ret);
@ -1387,7 +1300,7 @@ HFCD_l1hw(hisaxif_t *hif, struct sk_buff *skb)
dch->tx_len = skb->len;
memcpy(dch->tx_buf, skb->data, dch->tx_len);
dch->tx_idx = 0;
hfcD_send_fifo(dch);
hfcpci_fill_dfifo(dch->inst.data);
dch->inst.unlock(dch->inst.data);
skb_trim(skb, 0);
return(if_newhead(&dch->inst.up, PH_DATA_CNF,
@ -1426,7 +1339,7 @@ HFCD_l1hw(hisaxif_t *hif, struct sk_buff *skb)
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
sched_event_D_pci(hc, D_CLEARBUSY);
dchannel_sched_event(&hc->dch, D_CLEARBUSY);
} else if (hh->dinfo == HW_POWERUP) {
Write_hfc(hc, HFCPCI_STATES, HFCPCI_DO_ACTION);
} else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
@ -1440,11 +1353,8 @@ HFCD_l1hw(hisaxif_t *hif, struct sk_buff *skb)
__FUNCTION__, slot);
Write_hfc(hc, HFCPCI_B1_SSL, slot);
Write_hfc(hc, HFCPCI_B1_RSL, slot);
save_flags(flags);
cli();
hc->hw.conn = (hc->hw.conn & ~7) | 1;
Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
restore_flags(flags);
}
if (2 & hh->dinfo) {
if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg))
@ -1455,20 +1365,14 @@ HFCD_l1hw(hisaxif_t *hif, struct sk_buff *skb)
__FUNCTION__, slot);
Write_hfc(hc, HFCPCI_B2_SSL, slot);
Write_hfc(hc, HFCPCI_B2_RSL, slot);
save_flags(flags);
cli();
hc->hw.conn = (hc->hw.conn & ~0x38) | 0x08;
Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
restore_flags(flags);
}
save_flags(flags);
cli();
if (3 & hh->dinfo)
hc->hw.trm |= 0x80; /* enable IOM-loop */
else
hc->hw.trm &= 0x7f; /* disable IOM-loop */
Write_hfc(hc, HFCPCI_TRM, hc->hw.trm);
restore_flags(flags);
} else {
if (dch->debug & L1_DEB_WARN)
debugprint(&dch->inst, "%s: unknown ctrl %x",
@ -1510,7 +1414,7 @@ HFCD_l1hw(hisaxif_t *hif, struct sk_buff *skb)
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
sched_event_D_pci(hc, D_CLEARBUSY);
dchannel_sched_event(&hc->dch, D_CLEARBUSY);
dch->inst.unlock(dch->inst.data);
} else {
if (dch->debug & L1_DEB_WARN)
@ -1536,7 +1440,6 @@ static int
mode_hfcpci(bchannel_t *bch, int bc, int protocol)
{
hfc_pci_t *hc = bch->inst.data;
long flags;
int fifo2;
u_char rx_slot = 0, tx_slot = 0, pcm_mode;
@ -1556,8 +1459,6 @@ mode_hfcpci(bchannel_t *bch, int bc, int protocol)
} else if (test_bit(HFC_CFG_PCM, &hc->cfg) && (protocol > ISDN_PID_NONE))
printk(KERN_WARNING "%s: no pcm channel id but HFC_CFG_PCM\n",
__FUNCTION__);
save_flags(flags);
cli();
if (hc->chanlimit > 1) {
hc->hw.bswapped = 0; /* B1 and B2 normal mode */
hc->hw.sctrl_e &= ~0x80;
@ -1582,7 +1483,6 @@ mode_hfcpci(bchannel_t *bch, int bc, int protocol)
bch->channel = bc;
case (ISDN_PID_NONE):
if (bch->protocol == ISDN_PID_NONE) {
restore_flags(flags);
return(0);
}
if (bc & 2) {
@ -1677,7 +1577,6 @@ mode_hfcpci(bchannel_t *bch, int bc, int protocol)
#endif
default:
debugprint(&bch->inst, "prot not known %x", protocol);
restore_flags(flags);
return(-ENOPROTOOPT);
}
if (test_bit(HFC_CFG_PCM, &hc->cfg)) {
@ -1723,8 +1622,7 @@ mode_hfcpci(bchannel_t *bch, int bc, int protocol)
Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
if (bch->protocol)
hfcpci_sched_event(bch, B_XMTBUFREADY);
restore_flags(flags);
bch_sched_event(bch, B_XMTBUFREADY);
return(0);
}
@ -1750,8 +1648,8 @@ hfcpci_l2l1(hisaxif_t *hif, struct sk_buff *skb)
return(-EBUSY);
}
bch->inst.lock(bch->inst.data);
if (test_and_set_bit(FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(FLG_TX_NEXT, &bch->Flag);
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
bch->next_skb = skb;
bch->inst.unlock(bch->inst.data);
return(0);
@ -1759,7 +1657,7 @@ hfcpci_l2l1(hisaxif_t *hif, struct sk_buff *skb)
bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len);
bch->tx_idx = 0;
hfcpci_send_data(bch);
hfcpci_fill_fifo(bch);
bch->inst.unlock(bch->inst.data);
if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
&& bch->dev)
@ -1790,11 +1688,11 @@ hfcpci_l2l1(hisaxif_t *hif, struct sk_buff *skb)
(hh->prim == (DL_RELEASE | REQUEST)) ||
(hh->prim == (MGR_DISCONNECT | REQUEST))) {
bch->inst.lock(bch->inst.data);
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flag)) {
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL;
}
test_and_clear_bit(FLG_TX_BUSY, &bch->Flag);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
mode_hfcpci(bch, bch->channel, ISDN_PID_NONE);
test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
bch->inst.unlock(bch->inst.data);
@ -1933,8 +1831,6 @@ hfcD_bh(dchannel_t *dch)
// printk(KERN_DEBUG "%s: event %x\n", __FUNCTION__, dch->event);
if (test_and_clear_bit(D_L1STATECHANGE, &dch->event))
hfcD_newstate(dch);
if (test_and_clear_bit(D_BLOCKEDATOMIC, &dch->event))
hfcD_send_fifo(dch);
if (test_and_clear_bit(D_XMTBUFREADY, &dch->event)) {
struct sk_buff *skb = dch->next_skb;
hisax_head_t *hh;
@ -1973,8 +1869,6 @@ hfcB_bh(bchannel_t *bch)
printk(KERN_DEBUG "%s: rpflg(%x) wpflg(%x)\n", __FUNCTION__,
bch->dev->rport.Flag, bch->dev->wport.Flag);
#endif
if (test_and_clear_bit(B_BLOCKEDATOMIC, &bch->event))
hfcpci_send_data(bch);
if (test_and_clear_bit(B_XMTBUFREADY, &bch->event)) {
skb = bch->next_skb;
if (skb) {
@ -2243,7 +2137,6 @@ setup_hfcpci(hfc_pci_t *hc)
#endif
strcpy(tmp, hfcpci_revision);
printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
hc->hw.int_s1 = 0;
hc->hw.cirm = 0;
hc->dch.ph_state = 0;
while (id_list[i].vendor_id) {
@ -2307,7 +2200,8 @@ setup_hfcpci(hfc_pci_t *hc)
init_timer(&hc->hw.timer);
lock_dev(hc);
#ifdef SPIN_DEBUG
printk(KERN_ERR "lock_adr=%p now(%p)\n", &hc->lock_adr, hc->lock_adr);
printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &hc->lock.spin_adr, hc->lock.spin_adr);
printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &hc->lock.busy_adr, hc->lock.busy_adr);
#endif
unlock_dev(hc);
reset_hfcpci(hc);
@ -2513,7 +2407,7 @@ HFC_init(void)
APPEND_TO_LIST(card, ((hfc_pci_t *)HFC_obj.ilist));
card->dch.debug = debug;
card->dch.inst.obj = &HFC_obj;
spin_lock_init(&card->devlock);
lock_HW_init(&card->lock);
card->dch.inst.lock = lock_dev;
card->dch.inst.unlock = unlock_dev;
card->dch.inst.data = card;

View File

@ -238,7 +238,6 @@ typedef union {
u_char fill[32768];
} fifo_area;
#define Write_hfc(a,b,c) (*(((u_char *)a->hw.pci_io)+b) = c)
#define Read_hfc(a,b) (*(((u_char *)a->hw.pci_io)+b))

View File

@ -1,214 +0,0 @@
/* $Id$
*
* Basic declarations, defines for HiSax hardware drivers
*
* This file is (c) under GNU PUBLIC LICENSE
*
*/
#include <linux/hisaxif.h>
#include <linux/tqueue.h>
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/skbuff.h>
#ifdef MEMDBG
#include "memdbg.h"
#endif
#define MAX_DFRAME_LEN_L1 300
#define MAX_MON_FRAME 32
#define MAX_DLOG_SPACE 2048
#define MAX_BLOG_SPACE 256
struct hdlc_stat_reg {
#ifdef __BIG_ENDIAN
u_char fill __attribute__((packed));
u_char mode __attribute__((packed));
u_char xml __attribute__((packed));
u_char cmd __attribute__((packed));
#else
u_char cmd __attribute__((packed));
u_char xml __attribute__((packed));
u_char mode __attribute__((packed));
u_char fill __attribute__((packed));
#endif
};
struct isar_reg {
unsigned int Flags;
volatile u_char bstat;
volatile u_char iis;
volatile u_char cmsb;
volatile u_char clsb;
volatile u_char par[8];
};
struct isar_hw {
int dpath;
int mml;
u_char state;
u_char cmd;
u_char mod;
u_char newcmd;
u_char newmod;
char try_mod;
struct timer_list ftimer;
u_char conmsg[16];
struct isar_reg *reg;
};
struct hdlc_hw {
union {
u_int ctrl;
struct hdlc_stat_reg sr;
} ctrl;
u_int stat;
};
struct hfcB_hw {
unsigned int *send;
int f1;
int f2;
};
#define BC_FLG_INIT 1
#define BC_FLG_ACTIV 2
// #define BC_FLG_BUSY 3
#define BC_FLG_NOFRAME 4
#define BC_FLG_HALF 5
#define BC_FLG_EMPTY 6
#define BC_FLG_ORIG 7
#define BC_FLG_DLEETX 8
#define BC_FLG_LASTDLE 9
#define BC_FLG_FIRST 10
#define BC_FLG_LASTDATA 11
#define BC_FLG_NMD_DATA 12
#define BC_FLG_FTI_RUN 13
#define BC_FLG_LL_OK 14
#define BC_FLG_LL_CONN 15
typedef struct _bchannel_t {
int channel;
int protocol;
int Flag;
int debug;
hisaxstack_t *st;
hisaxinstance_t inst;
hisaxdevice_t *dev;
u_char (*BC_Read_Reg)(void *, int, u_char);
void (*BC_Write_Reg)(void *, int, u_char, u_char);
struct sk_buff *next_skb;
u_char *tx_buf;
int tx_idx;
int tx_len;
u_char *rx_buf;
int rx_idx;
struct sk_buff_head rqueue; /* B-Channel receive Queue */
u_char *blog;
u_char *conmsg;
struct timer_list transbusy;
struct tq_struct tqueue;
int event;
int err_crc;
int err_tx;
int err_rdo;
int err_inv;
union {
struct hdlc_hw hdlc;
struct isar_hw isar;
} hw;
} bchannel_t;
struct arcofi_msg {
struct arcofi_msg *next;
u_char receive;
u_char len;
u_char msg[10];
};
#define HW_IOM1 0
#define HW_IPAC 1
#define HW_ISAR 2
#define HW_ARCOFI 3
#define FLG_TWO_DCHAN 4
#define FLG_TX_BUSY 5
#define FLG_TX_NEXT 6
#define FLG_L1_DBUSY 7
#define FLG_DBUSY_TIMER 8
#define FLG_LOCK_ATOMIC 9
#define FLG_ARCOFI_TIMER 10
#define FLG_ARCOFI_ERROR 11
#define FLG_HW_L1_UINT 12
#define FLG_HW_INIT 13
typedef struct _dchannel_t {
hisaxinstance_t inst;
u_int DFlags;
u_int type;
u_int ph_state;
u_char (*read_reg) (void *, u_char);
void (*write_reg) (void *, u_char, u_char);
void (*read_fifo) (void *, u_char *, int);
void (*write_fifo) (void *, u_char *, int);
char *dlog;
int debug;
struct sk_buff *rx_skb;
struct sk_buff *next_skb;
u_char *tx_buf;
int tx_idx;
int tx_len;
int err_crc;
int err_tx;
int err_rx;
void *hw;
struct timer_list dbusytimer;
u_int event;
struct sk_buff_head rqueue; /* D-channel receive queue */
struct tq_struct tqueue;
} dchannel_t;
#define MON0_RX 1
#define MON1_RX 2
#define MON0_TX 4
#define MON1_TX 8
/* L1 Debug */
#define L1_DEB_WARN 0x01
#define L1_DEB_INTSTAT 0x02
#define L1_DEB_ISAC 0x04
#define L1_DEB_ISAC_FIFO 0x08
#define L1_DEB_HSCX 0x10
#define L1_DEB_HSCX_FIFO 0x20
#define L1_DEB_LAPD 0x40
#define L1_DEB_IPAC 0x80
#define L1_DEB_RECEIVE_FRAME 0x100
#define L1_DEB_MONITOR 0x200
#define DEB_DLOG_HEX 0x400
#define DEB_DLOG_VERBOSE 0x800
int init_dchannel(dchannel_t *);
int free_dchannel(dchannel_t *);
int init_bchannel(bchannel_t *);
int free_bchannel(bchannel_t *);
void set_dchannel_pid(hisax_pid_t *, int, int);
#ifdef __powerpc__
#include <linux/pci.h>
static inline int pci_enable_device(struct pci_dev *dev)
{
u16 cmd;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_SERR;
cmd &= ~PCI_COMMAND_FAST_BACK;
pci_write_config_word(dev, PCI_COMMAND, cmd);
return(0);
}
#else
#define pci_enable_device(dev) !dev
#endif /* __powerpc__ */

View File

@ -0,0 +1,118 @@
/* $Id$
*
* hw_lock.h HArdware locking inline routines
*
* Author Karsten Keil (keil@isdn4linux.de)
*
* This file is (c) under GNU PUBLIC LICENSE
*
*/
#ifndef __hw_lock__
#define __hw_lock__
typedef struct _hisax_HWlock {
u_long flags;
spinlock_t lock;
#ifdef SPIN_DEBUG
void *spin_adr;
void *busy_adr;
#endif
volatile u_int state;
#ifdef LOCK_STATISTIC
u_int try_ok;
u_int try_wait;
u_int try_inirq;
u_int try_mult;
u_int irq_ok;
u_int irq_fail;
#endif
} hisax_HWlock_t;
#define STATE_FLAG_BUSY 1
#define STATE_FLAG_INIRQ 2
static inline void lock_HW(hisax_HWlock_t *lock)
{
register u_long flags;
#ifdef LOCK_STATISTIC
int wait = 0;
#endif
spin_lock_irqsave(&lock->lock, flags);
#ifdef SPIN_DEBUG
lock->spin_adr = __builtin_return_address(0);
#endif
while (test_and_set_bit(STATE_FLAG_BUSY, &lock->state)) {
/* allready busy so we delay */
spin_unlock_irqrestore(&lock->lock, flags);
#ifdef SPIN_DEBUG
lock->spin_adr = NULL;
#endif
/* delay 1 jiffie is enought */
if (in_interrupt()) {
#ifdef LOCK_STATISTIC
lock->try_inirq++;
#endif
printk(KERN_ERR "lock_HW: try to schedule in IRQ state(%x)\n",
lock->state);
mdelay(1);
} else {
#ifdef LOCK_STATISTIC
if (wait++)
lock->try_mult++;
else
lock->try_wait++;
#endif
schedule_timeout(1);
}
spin_lock_irqsave(&lock->lock, flags);
#ifdef SPIN_DEBUG
lock->spin_adr = __builtin_return_address(0);
#endif
}
/* get the LOCK */
lock->flags = flags;
#ifdef SPIN_DEBUG
lock->busy_adr = __builtin_return_address(0);
#endif
#ifdef LOCK_STATISTIC
if (!wait)
lock->try_ok++;
#endif
}
static inline void unlock_HW(hisax_HWlock_t *lock)
{
if (!test_and_clear_bit(STATE_FLAG_BUSY, &lock->state)) {
printk(KERN_ERR "lock_HW: STATE_FLAG_BUSY not locked state(%x)\n",
lock->state);
}
#ifdef SPIN_DEBUG
lock->busy_adr = NULL;
lock->spin_adr = NULL;
#endif
spin_unlock_irqrestore(&lock->lock, lock->flags);
}
static inline void lock_HW_init(hisax_HWlock_t *lock)
{
spin_lock_init(&lock->lock);
lock->state = 0;
#ifdef SPIN_DEBUG
lock->busy_adr = NULL;
lock->spin_adr = NULL;
#endif
#ifdef LOCK_STATISTIC
lock->try_ok = 0;
lock->try_wait = 0;
lock->try_inirq = 0;
lock->try_mult = 0;
lock->irq_ok = 0;
lock->irq_fail = 0;
#endif
}
#endif

View File

@ -9,7 +9,7 @@
#define __NO_VERSION__
#include <linux/module.h>
#include "hisax_hw.h"
#include "hisax_dch.h"
#include "isac.h"
#include "arcofi.h"
#include "hisaxl1.h"
@ -95,26 +95,10 @@ isac_new_ph(dchannel_t *dch)
}
static void
isac_rcv(dchannel_t *dch)
isac_hwbh(dchannel_t *dch)
{
struct sk_buff *skb;
int err;
while ((skb = skb_dequeue(&dch->rqueue))) {
err = if_newhead(&dch->inst.up, PH_DATA_IND, DINFO_SKB, skb);
if (err < 0) {
printk(KERN_WARNING "HiSax: isac deliver err %d\n", err);
dev_kfree_skb(skb);
}
}
}
static void
isac_bh(dchannel_t *dch)
{
if (!dch)
return;
printk(KERN_DEBUG "%s: event %x\n", __FUNCTION__, dch->event);
if (dch->debug)
printk(KERN_DEBUG "%s: event %x\n", __FUNCTION__, dch->event);
#if 0
if (test_and_clear_bit(D_CLEARBUSY, &dch->event)) {
if (dch->debug)
@ -128,19 +112,6 @@ isac_bh(dchannel_t *dch)
#endif
if (test_and_clear_bit(D_L1STATECHANGE, &dch->event))
isac_new_ph(dch);
if (test_and_clear_bit(D_XMTBUFREADY, &dch->event)) {
struct sk_buff *skb = dch->next_skb;
if (skb) {
dch->next_skb = NULL;
skb_trim(skb, 0);
if (if_newhead(&dch->inst.up, PH_DATA_CNF, DINFO_SKB,
skb))
dev_kfree_skb(skb);
}
}
if (test_and_clear_bit(D_RCVBUFREADY, &dch->event))
isac_rcv(dch);
#if ARCOFI_USE
if (!test_bit(HW_ARCOFI, &dch->DFlags))
return;
@ -223,14 +194,6 @@ isac_fill_fifo(dchannel_t *dch)
}
}
void
isac_sched_event(dchannel_t *dch, int event)
{
test_and_set_bit(event, &dch->event);
queue_task(&dch->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
void
ISAC_interrupt(dchannel_t *dch, u_char val)
{
@ -269,7 +232,7 @@ ISAC_interrupt(dchannel_t *dch, u_char val)
skb_queue_tail(&dch->rqueue, dch->rx_skb);
}
dch->rx_skb = NULL;
isac_sched_event(dch, D_RCVBUFREADY);
dchannel_sched_event(dch, D_RCVBUFREADY);
}
if (val & 0x40) { /* RPF */
isac_empty_fifo(dch, 32);
@ -283,7 +246,7 @@ ISAC_interrupt(dchannel_t *dch, u_char val)
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
isac_sched_event(dch, D_CLEARBUSY);
dchannel_sched_event(dch, D_CLEARBUSY);
if (dch->tx_idx < dch->tx_len) {
isac_fill_fifo(dch);
} else {
@ -294,7 +257,7 @@ ISAC_interrupt(dchannel_t *dch, u_char val)
dch->next_skb->data, dch->tx_len);
dch->tx_idx = 0;
isac_fill_fifo(dch);
isac_sched_event(dch, D_XMTBUFREADY);
dchannel_sched_event(dch, D_XMTBUFREADY);
} else {
printk(KERN_WARNING "isac tx irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
@ -312,7 +275,7 @@ ISAC_interrupt(dchannel_t *dch, u_char val)
if (dch->debug & L1_DEB_ISAC)
debugprint(&dch->inst, "ph_state change %x", dch->ph_state);
/* unconditional reset procedure */
isac_sched_event(dch, D_L1STATECHANGE);
dchannel_sched_event(dch, D_L1STATECHANGE);
}
if (exval & 1) {
exval = dch->read_reg(dch->inst.data, ISAC_CIR1);
@ -342,7 +305,7 @@ ISAC_interrupt(dchannel_t *dch, u_char val)
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
isac_sched_event(dch, D_CLEARBUSY);
dchannel_sched_event(dch, D_CLEARBUSY);
if (test_bit(FLG_TX_BUSY, &dch->DFlags)) {
/* Restart frame */
dch->tx_idx = 0;
@ -358,7 +321,7 @@ ISAC_interrupt(dchannel_t *dch, u_char val)
dch->tx_len);
dch->tx_idx = 0;
isac_fill_fifo(dch);
isac_sched_event(dch, D_XMTBUFREADY);
dchannel_sched_event(dch, D_XMTBUFREADY);
} else {
printk(KERN_WARNING "isac xdu irq TX_NEXT without skb\n");
}
@ -433,14 +396,14 @@ ISAC_interrupt(dchannel_t *dch, u_char val)
dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
isac->mocr |= 0x0a;
dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
isac_sched_event(dch, D_RX_MON0);
dchannel_sched_event(dch, D_RX_MON0);
}
if (v1 & 0x40) {
isac->mocr &= 0x0f;
dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
isac->mocr |= 0xa0;
dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
isac_sched_event(dch, D_RX_MON1);
dchannel_sched_event(dch, D_RX_MON1);
}
if (v1 & 0x02) {
if ((!isac->mon_tx) || (isac->mon_txc &&
@ -452,11 +415,11 @@ ISAC_interrupt(dchannel_t *dch, u_char val)
dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
if (isac->mon_txc &&
(isac->mon_txp >= isac->mon_txc))
isac_sched_event(dch, D_TX_MON0);
dchannel_sched_event(dch, D_TX_MON0);
goto AfterMOX0;
}
if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
isac_sched_event(dch, D_TX_MON0);
dchannel_sched_event(dch, D_TX_MON0);
goto AfterMOX0;
}
dch->write_reg(dch->inst.data, ISAC_MOX0,
@ -475,11 +438,11 @@ ISAC_interrupt(dchannel_t *dch, u_char val)
dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
if (isac->mon_txc &&
(isac->mon_txp >= isac->mon_txc))
isac_sched_event(dch, D_TX_MON1);
dchannel_sched_event(dch, D_TX_MON1);
goto AfterMOX1;
}
if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
isac_sched_event(dch, D_TX_MON1);
dchannel_sched_event(dch, D_TX_MON1);
goto AfterMOX1;
}
dch->write_reg(dch->inst.data, ISAC_MOX1,
@ -557,7 +520,7 @@ ISAC_l1hw(hisaxif_t *hif, struct sk_buff *skb)
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
isac_sched_event(dch, D_CLEARBUSY);
dchannel_sched_event(dch, D_CLEARBUSY);
} else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
tl = 0;
if (1 & hh->dinfo)
@ -617,8 +580,6 @@ ISAC_free(dchannel_t *dch) {
kfree(isac->mon_tx);
isac->mon_tx = NULL;
}
kfree(isac);
dch->hw = NULL;
}
static void
@ -665,7 +626,7 @@ static char *ISACVer[] =
int
ISAC_init(dchannel_t *dch)
{
isac_chip_t *isac = kmalloc(sizeof(isac_chip_t), GFP_ATOMIC);
isac_chip_t *isac = dch->hw;
u_char val;
dch->write_reg(dch->inst.data, ISAC_MASK, 0xff);
@ -674,8 +635,7 @@ ISAC_init(dchannel_t *dch)
if (!isac)
return(-ENOMEM);
dch->hw = isac;
dch->tqueue.routine = (void *) (void *) isac_bh;
dch->hw_bh = isac_hwbh;
isac->mon_tx = NULL;
isac->mon_rx = NULL;
dch->dbusytimer.function = (void *) dbusy_timer_handler;
@ -701,7 +661,7 @@ ISAC_init(dchannel_t *dch)
dch->write_reg(dch->inst.data, ISAC_TIMR, 0x00);
dch->write_reg(dch->inst.data, ISAC_ADF1, 0x00);
}
isac_sched_event(dch, D_L1STATECHANGE);
dchannel_sched_event(dch, D_L1STATECHANGE);
ph_command(dch, ISAC_CMD_RS);
dch->write_reg(dch->inst.data, ISAC_MASK, 0x0);
return 0;

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,29 @@
*
*/
typedef struct _isar_reg {
unsigned int Flags;
volatile u_char bstat;
volatile u_char iis;
volatile u_char cmsb;
volatile u_char clsb;
volatile u_char par[8];
} isar_reg_t;
typedef struct _isar_hw {
int dpath;
int mml;
u_char state;
u_char cmd;
u_char mod;
u_char newcmd;
u_char newmod;
char try_mod;
struct timer_list ftimer;
u_char conmsg[16];
isar_reg_t *reg;
} isar_hw_t;
#define ISAR_IRQMSK 0x04
#define ISAR_IRQSTA 0x04
#define ISAR_IRQBIT 0x75

View File

@ -34,3 +34,18 @@
#define FLG_L1_PULL_REQ 6
#define FLG_L1_UINT 7
#define FLG_L1_DBLOCKED 8
/* L1 Debug */
#define L1_DEB_WARN 0x01
#define L1_DEB_INTSTAT 0x02
#define L1_DEB_ISAC 0x04
#define L1_DEB_ISAC_FIFO 0x08
#define L1_DEB_HSCX 0x10
#define L1_DEB_HSCX_FIFO 0x20
#define L1_DEB_LAPD 0x40
#define L1_DEB_IPAC 0x80
#define L1_DEB_RECEIVE_FRAME 0x100
#define L1_DEB_MONITOR 0x200
#define DEB_DLOG_HEX 0x400
#define DEB_DLOG_VERBOSE 0x800

View File

@ -32,13 +32,18 @@
#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <asm/semaphore.h>
#include "hisax_hw.h"
#include "hisax_dch.h"
#include "hisax_bch.h"
#include "isac.h"
#include "isar.h"
#include "hisaxl1.h"
#include "helper.h"
#include "debug.h"
#define SPIN_DEBUG
#define LOCK_STATISTIC
#include "hw_lock.h"
extern const char *CardType[];
const char *Sedlfax_revision = "$Revision$";
@ -98,8 +103,6 @@ const char *Sedlbauer_Types[] =
#define SEDL_RESET 0x3 /* same as DOS driver */
/* data struct */
#define SPIN_DEBUG
#define LOCK_STATISTIC
typedef struct _sedl_fax {
struct _sedl_fax *prev;
@ -110,28 +113,27 @@ typedef struct _sedl_fax {
u_int addr;
u_int isac;
u_int isar;
spinlock_t devlock;
#ifdef SPIN_DEBUG
void *spin_lock_adr;
void *sem_lock_adr;
#endif
volatile u_int state;
struct semaphore sem;
#ifdef LOCK_STATISTIC
u_int try_ok;
u_int try_fail;
u_int try_inirq;
u_int try_pend;
u_int irq_ok;
u_int irq_fail;
u_int irq_pend;
#endif
struct isar_reg ir;
hisax_HWlock_t lock;
isar_reg_t ir;
isac_chip_t isac_hw;
isar_hw_t isar_hw[2];
dchannel_t dch;
bchannel_t bch[2];
} sedl_fax;
#define STATE_IRQ_PENDING 1
static void lock_dev(void *data)
{
register hisax_HWlock_t *lock = &((sedl_fax *)data)->lock;
lock_HW(lock);
}
static void unlock_dev(void *data)
{
register hisax_HWlock_t *lock = &((sedl_fax *)data)->lock;
unlock_HW(lock);
}
static inline u_char
readreg(unsigned int ale, unsigned int adr, u_char off)
@ -255,119 +257,56 @@ do_sedl_interrupt(sedl_fax *sf)
writereg(sf->addr, sf->isar, ISAR_IRQBIT, ISAR_IRQMSK);
}
static int lock_dev(void *data)
{
register sedl_fax *sf = (sedl_fax *)data;
if (down_trylock(&sf->sem) != 0) {
/* don't get it */
#ifdef LOCK_STATISTIC
sf->try_fail++;
#endif
if (!in_interrupt()) {
down(&sf->sem);
} else {
#ifdef LOCK_STATISTIC
sf->try_inirq++;
#endif
printk(KERN_ERR "Sedlbauer: try to get device lock in IRQ context\n");
return(1);
}
}
#ifdef LOCK_STATISTIC
else
sf->try_ok++;
#endif
#ifdef SPIN_DEBUG
sf->sem_lock_adr = __builtin_return_address(0);
#endif
return(0);
}
static void unlock_dev(void *data)
{
ulong flags;
register sedl_fax *sf = (sedl_fax *)data;
spin_lock_irqsave(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = (void *)0x1001;
#endif
while(test_and_clear_bit(STATE_IRQ_PENDING, &sf->state)) {
spin_unlock_irqrestore(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = NULL;
#endif
#ifdef LOCK_STATISTIC
sf->try_pend++;
#endif
do_sedl_interrupt(sf);
spin_lock_irqsave(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = (void *)0x1002;
#endif
}
#ifdef SPIN_DEBUG
sf->sem_lock_adr = NULL;
#endif
spin_unlock_irqrestore(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = NULL;
#endif
up(&sf->sem);
}
static void
speedfax_isa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
sedl_fax *sf = dev_id;
u_long flags;
spin_lock_irqsave(&sf->devlock, flags);
spin_lock_irqsave(&sf->lock.lock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = (void *)0x2001;
sf->lock.spin_adr = (void *)0x2001;
#endif
if (0==down_trylock(&sf->sem)) {
if (test_and_set_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%x\n",
__FUNCTION__, sf->lock.state);
#ifdef SPIN_DEBUG
sf->sem_lock_adr = speedfax_isa_interrupt;
printk(KERN_ERR "%s: previous lock:%p\n",
__FUNCTION__, sf->lock.busy_adr);
#endif
#ifdef LOCK_STATISTIC
sf->irq_ok++;
sf->lock.irq_fail++;
#endif
while (1) {
spin_unlock_irqrestore(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = NULL;
#endif
do_sedl_interrupt(sf);
spin_lock_irqsave(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = (void *)0x2002;
#endif
if (!test_and_clear_bit(STATE_IRQ_PENDING, &sf->state))
break;
#ifdef LOCK_STATISTIC
sf->irq_pend++;
#endif
}
#ifdef SPIN_DEBUG
sf->sem_lock_adr = NULL;
#endif
spin_unlock_irqrestore(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = NULL;
#endif
up(&sf->sem);
} else {
test_and_set_bit(STATE_IRQ_PENDING, &sf->state);
spin_unlock_irqrestore(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = NULL;
#endif
#ifdef LOCK_STATISTIC
sf->irq_fail++;
sf->lock.irq_ok++;
#endif
#ifdef SPIN_DEBUG
sf->lock.busy_adr = speedfax_isa_interrupt;
#endif
}
test_and_set_bit(STATE_FLAG_INIRQ, &sf->lock.state);
#ifdef SPIN_DEBUG
sf->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&sf->lock.lock, flags);
do_sedl_interrupt(sf);
spin_lock_irqsave(&sf->lock.lock, flags);
#ifdef SPIN_DEBUG
sf->lock.spin_adr = (void *)0x2002;
#endif
if (!test_and_clear_bit(STATE_FLAG_INIRQ, &sf->lock.state)) {
}
if (!test_and_clear_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%x)\n",
__FUNCTION__, sf->lock.state);
}
#ifdef SPIN_DEBUG
sf->lock.busy_adr = NULL;
sf->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&sf->lock.lock, flags);
}
static void
@ -377,59 +316,58 @@ speedfax_pci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
u_long flags;
u_char val;
spin_lock_irqsave(&sf->devlock, flags);
spin_lock_irqsave(&sf->lock.lock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = (void *)0x3001;
sf->lock.spin_adr = (void *)0x3001;
#endif
val = bytein(sf->cfg + TIGER_AUX_STATUS);
if (val & SEDL_TIGER_IRQ_BIT) { /* for us or shared ? */
spin_unlock_irqrestore(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = NULL;
sf->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&sf->lock.lock, flags);
return; /* shared */
}
if (0==down_trylock(&sf->sem)) {
if (test_and_set_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%x\n",
__FUNCTION__, sf->lock.state);
#ifdef SPIN_DEBUG
sf->sem_lock_adr = speedfax_pci_interrupt;
printk(KERN_ERR "%s: previous lock:%p\n",
__FUNCTION__, sf->lock.busy_adr);
#endif
#ifdef LOCK_STATISTIC
sf->irq_ok++;
sf->lock.irq_fail++;
#endif
while (1) {
spin_unlock_irqrestore(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = NULL;
#endif
do_sedl_interrupt(sf);
spin_lock_irqsave(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = (void *)0x3002;
#endif
if (!test_and_clear_bit(STATE_IRQ_PENDING, &sf->state))
break;
#ifdef LOCK_STATISTIC
sf->irq_pend++;
#endif
}
#ifdef SPIN_DEBUG
sf->sem_lock_adr = NULL;
#endif
spin_unlock_irqrestore(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = NULL;
#endif
up(&sf->sem);
} else {
test_and_set_bit(STATE_IRQ_PENDING, &sf->state);
spin_unlock_irqrestore(&sf->devlock, flags);
#ifdef SPIN_DEBUG
sf->spin_lock_adr = NULL;
#endif
#ifdef LOCK_STATISTIC
sf->irq_fail++;
sf->lock.irq_ok++;
#endif
#ifdef SPIN_DEBUG
sf->lock.busy_adr = speedfax_pci_interrupt;
#endif
}
test_and_set_bit(STATE_FLAG_INIRQ, &sf->lock.state);
#ifdef SPIN_DEBUG
sf->lock.spin_adr= NULL;
#endif
spin_unlock_irqrestore(&sf->lock.lock, flags);
do_sedl_interrupt(sf);
spin_lock_irqsave(&sf->lock.lock, flags);
#ifdef SPIN_DEBUG
sf->lock.spin_adr = (void *)0x3002;
#endif
if (!test_and_clear_bit(STATE_FLAG_INIRQ, &sf->lock.state)) {
}
if (!test_and_clear_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%x)\n",
__FUNCTION__, sf->lock.state);
}
#ifdef SPIN_DEBUG
sf->lock.busy_adr = NULL;
sf->lock.spin_adr = NULL;
#endif
spin_unlock_irqrestore(&sf->lock.lock, flags);
}
void
@ -649,6 +587,7 @@ setup_speedfax(sedl_fax *sf, u_int io_cfg, u_int irq_cfg)
sf->dch.write_reg = &WriteISAC;
sf->dch.read_fifo = &ReadISACfifo;
sf->dch.write_fifo = &WriteISACfifo;
sf->dch.hw = &sf->isac_hw;
if (sf->subtyp != SEDL_SPEEDFAX_ISA) {
sf->addr = sf->cfg + SEDL_PCI_ADR;
sf->isac = sf->cfg + SEDL_PCI_ISAC;
@ -668,16 +607,18 @@ setup_speedfax(sedl_fax *sf, u_int io_cfg, u_int irq_cfg)
sf->isac = sf->cfg + SEDL_ISA_ISAC;
sf->isar = sf->cfg + SEDL_ISA_ISAR;
}
sf->bch[0].hw.isar.reg = &sf->ir;
sf->bch[1].hw.isar.reg = &sf->ir;
sf->bch[0].BC_Read_Reg = &ReadISAR;
sf->bch[0].BC_Write_Reg = &WriteISAR;
sf->bch[1].BC_Read_Reg = &ReadISAR;
sf->bch[1].BC_Write_Reg = &WriteISAR;
sf->isar_hw[0].reg = &sf->ir;
sf->isar_hw[1].reg = &sf->ir;
sf->bch[0].hw = &sf->isar_hw[0];
sf->bch[1].hw = &sf->isar_hw[1];
sf->bch[0].Read_Reg = &ReadISAR;
sf->bch[0].Write_Reg = &WriteISAR;
sf->bch[1].Read_Reg = &ReadISAR;
sf->bch[1].Write_Reg = &WriteISAR;
lock_dev(sf);
#ifdef SPIN_DEBUG
printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &sf->spin_lock_adr, sf->spin_lock_adr);
printk(KERN_ERR "sem_lock_adr=%p now(%p)\n", &sf->sem_lock_adr, sf->sem_lock_adr);
printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &sf->lock.spin_adr, sf->lock.spin_adr);
printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &sf->lock.busy_adr, sf->lock.busy_adr);
#endif
writereg(sf->addr, sf->isar, ISAR_IRQBIT, 0);
writereg(sf->addr, sf->isac, ISAC_MASK, 0xFF);
@ -696,14 +637,12 @@ static void
release_card(sedl_fax *card) {
#ifdef LOCK_STATISTIC
printk(KERN_INFO "try_ok(%d) try_fail(%d) try_pend(%d) try_inirq(%d)\n",
card->try_ok, card->try_fail, card->try_pend, card->try_inirq);
printk(KERN_INFO "irq_ok(%d) irq_fail(%d) irq_pend(%d)\n",
card->irq_ok, card->irq_fail, card->irq_pend);
printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",
card->lock.try_ok, card->lock.try_wait, card->lock.try_mult, card->lock.try_inirq);
printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
card->lock.irq_ok, card->lock.irq_fail);
#endif
while(lock_dev(card)) {
printk(KERN_WARNING "Sedlbauer release_card waiting for lock\n");
}
lock_dev(card);
free_irq(card->irq, card);
free_isar(&card->bch[1]);
free_isar(&card->bch[0]);
@ -718,7 +657,6 @@ release_card(sedl_fax *card) {
free_bchannel(&card->bch[0]);
free_dchannel(&card->dch);
REMOVE_FROM_LISTBASE(card, ((sedl_fax *)speedfax.ilist));
test_and_clear_bit(STATE_IRQ_PENDING, &card->state);
unlock_dev(card);
kfree(card);
sedl_cnt--;
@ -906,8 +844,7 @@ Speedfax_init(void)
APPEND_TO_LIST(card, ((sedl_fax *)speedfax.ilist));
card->dch.debug = debug;
card->dch.inst.obj = &speedfax;
spin_lock_init(&card->devlock);
init_MUTEX(&card->sem);
lock_HW_init(&card->lock);
card->dch.inst.lock = lock_dev;
card->dch.inst.unlock = unlock_dev;
card->dch.inst.data = card;

View File

@ -622,7 +622,7 @@ typedef struct _hisaxinstance {
void *data;
hisaxif_t up;
hisaxif_t down;
int (*lock)(void *);
void (*lock)(void *);
void (*unlock)(void *);
} hisaxinstance_t;

View File

@ -1,7 +1,7 @@
Vendor: SuSE GmbH, Nuernberg, Germany
Distribution: SuSE Linux 7.3 (i386)
Distribution: SuSE Linux 8.2 (i386)
Name: km_newhisax
Release: 16
Release: 17
Packager: feedback@suse.de
Copyright: Karsten Keil GPL