port bkm_a4t hfc_2bds0hfc_sx gazel hfc_2bs0 teleint

This commit is contained in:
Karsten Keil 2004-01-14 16:04:48 +00:00
parent 74d5a9e82d
commit 849a9961ec
14 changed files with 454 additions and 650 deletions

View File

@ -402,13 +402,6 @@ config HISAX_FRITZ_PCIPNP
(the latter also needs you to select "ISA Plug and Play support" (the latter also needs you to select "ISA Plug and Play support"
from the menu "Plug and Play configuration") from the menu "Plug and Play configuration")
config HISAX_FRITZ_CLASSIC
tristate "AVM Fritz!Card classic support (EXPERIMENTAL)"
depends on ISA && EXPERIMENTAL
help
This enables the driver for the AVM Fritz!Card classic, formerly
known as AVM A1.
endif endif
endmenu endmenu

View File

@ -12,8 +12,6 @@ obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o
obj-$(CONFIG_HISAX_AVM_A1_CS) += avma1_cs.o obj-$(CONFIG_HISAX_AVM_A1_CS) += avma1_cs.o
obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o
obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o
obj-$(CONFIG_HISAX_FRITZ_CLASSIC) += hisax_isac.o hisax_hscx.o hisax_fcclassic.o
obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_hfcpci.o
# Multipart objects. # Multipart objects.

View File

@ -30,16 +30,13 @@ static inline u_char
readreg(unsigned int ale, unsigned long adr, u_char off) readreg(unsigned int ale, unsigned long adr, u_char off)
{ {
register u_int ret; register u_int ret;
long flags;
unsigned int *po = (unsigned int *) adr; /* Postoffice */ unsigned int *po = (unsigned int *) adr; /* Postoffice */
save_flags(flags);
cli();
*po = (GCS_2 | PO_WRITE | off); *po = (GCS_2 | PO_WRITE | off);
__WAITI20__(po); __WAITI20__(po);
*po = (ale | PO_READ); *po = (ale | PO_READ);
__WAITI20__(po); __WAITI20__(po);
ret = *po; ret = *po;
restore_flags(flags);
return ((unsigned char) ret); return ((unsigned char) ret);
} }
@ -47,7 +44,6 @@ readreg(unsigned int ale, unsigned long adr, u_char off)
static inline void static inline void
readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size) readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
{ {
/* fifo read without cli because it's allready done */
int i; int i;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
*data++ = readreg(ale, adr, off); *data++ = readreg(ale, adr, off);
@ -57,22 +53,17 @@ readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int siz
static inline void static inline void
writereg(unsigned int ale, unsigned long adr, u_char off, u_char data) writereg(unsigned int ale, unsigned long adr, u_char off, u_char data)
{ {
long flags;
unsigned int *po = (unsigned int *) adr; /* Postoffice */ unsigned int *po = (unsigned int *) adr; /* Postoffice */
save_flags(flags);
cli();
*po = (GCS_2 | PO_WRITE | off); *po = (GCS_2 | PO_WRITE | off);
__WAITI20__(po); __WAITI20__(po);
*po = (ale | PO_WRITE | data); *po = (ale | PO_WRITE | data);
__WAITI20__(po); __WAITI20__(po);
restore_flags(flags);
} }
static inline void static inline void
writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size) writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
{ {
/* fifo write without cli because it's allready done */
int i; int i;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
@ -134,17 +125,15 @@ WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value)
#include "jade_irq.c" #include "jade_irq.c"
static void static irqreturn_t
bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs) bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{ {
struct IsdnCardState *cs = dev_id; struct IsdnCardState *cs = dev_id;
u_char val = 0; u_char val = 0;
u_long flags;
I20_REGISTER_FILE *pI20_Regs; I20_REGISTER_FILE *pI20_Regs;
if (!cs) { spin_lock_irqsave(&cs->lock, flags);
printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!\n");
return;
}
pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
/* ISDN interrupt pending? */ /* ISDN interrupt pending? */
@ -170,6 +159,11 @@ bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
} }
/* Reenable ISDN interrupt */ /* Reenable ISDN interrupt */
pI20_Regs->i20IntCtrl |= intISDN; pI20_Regs->i20IntCtrl |= intISDN;
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_HANDLED;
} else {
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_NONE;
} }
} }
@ -228,25 +222,33 @@ reset_bkm(struct IsdnCardState *cs)
static int static int
BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{ {
u_long flags;
switch (mt) { switch (mt) {
case CARD_RESET: case CARD_RESET:
/* Disable ints */ /* Disable ints */
spin_lock_irqsave(&cs->lock, flags);
enable_bkm_int(cs, 0); enable_bkm_int(cs, 0);
reset_bkm(cs); reset_bkm(cs);
spin_unlock_irqrestore(&cs->lock, flags);
return (0); return (0);
case CARD_RELEASE: case CARD_RELEASE:
/* Sanity */ /* Sanity */
spin_lock_irqsave(&cs->lock, flags);
enable_bkm_int(cs, 0); enable_bkm_int(cs, 0);
reset_bkm(cs); reset_bkm(cs);
spin_unlock_irqrestore(&cs->lock, flags);
release_io_bkm(cs); release_io_bkm(cs);
return (0); return (0);
case CARD_INIT: case CARD_INIT:
spin_lock_irqsave(&cs->lock, flags);
clear_pending_isac_ints(cs); clear_pending_isac_ints(cs);
clear_pending_jade_ints(cs); clear_pending_jade_ints(cs);
initisac(cs); initisac(cs);
initjade(cs); initjade(cs);
/* Enable ints */ /* Enable ints */
enable_bkm_int(cs, 1); enable_bkm_int(cs, 1);
spin_unlock_irqrestore(&cs->lock, flags);
return (0); return (0);
case CARD_TEST: case CARD_TEST:
return (0); return (0);
@ -274,10 +276,6 @@ setup_bkm_a4t(struct IsdnCard *card)
return (0); return (0);
#if CONFIG_PCI #if CONFIG_PCI
if (!pci_present()) {
printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
return (0);
}
while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN, while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
u16 sub_sys; u16 sub_sys;
@ -328,7 +326,7 @@ setup_bkm_a4t(struct IsdnCard *card)
printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n", printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
CardType[card->typ], cs->hw.ax.base, cs->irq); CardType[card->typ], cs->hw.ax.base, cs->irq);
reset_bkm(cs); setup_isac(cs);
cs->readisac = &ReadISAC; cs->readisac = &ReadISAC;
cs->writeisac = &WriteISAC; cs->writeisac = &WriteISAC;
cs->readisacfifo = &ReadISACfifo; cs->readisacfifo = &ReadISACfifo;

View File

@ -72,26 +72,17 @@ static inline u_char
readreg_ipac(unsigned int adr, u_short off) readreg_ipac(unsigned int adr, u_short off)
{ {
register u_char ret; register u_char ret;
long flags;
save_flags(flags);
cli();
byteout(adr, off); byteout(adr, off);
ret = bytein(adr + 4); ret = bytein(adr + 4);
restore_flags(flags);
return ret; return ret;
} }
static inline void static inline void
writereg_ipac(unsigned int adr, u_short off, u_char data) writereg_ipac(unsigned int adr, u_short off, u_char data)
{ {
long flags;
save_flags(flags);
cli();
byteout(adr, off); byteout(adr, off);
byteout(adr + 4, data); byteout(adr + 4, data);
restore_flags(flags);
} }
@ -252,18 +243,16 @@ WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
#include "hscx_irq.c" #include "hscx_irq.c"
static void static irqreturn_t
gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs) gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{ {
#define MAXCOUNT 5 #define MAXCOUNT 5
struct IsdnCardState *cs = dev_id; struct IsdnCardState *cs = dev_id;
u_char valisac, valhscx; u_char valisac, valhscx;
int count = 0; int count = 0;
u_long flags;
if (!cs) { spin_lock_irqsave(&cs->lock, flags);
printk(KERN_WARNING "Gazel: Spurious interrupt!\n");
return;
}
do { do {
valhscx = ReadHSCX(cs, 1, HSCX_ISTA); valhscx = ReadHSCX(cs, 1, HSCX_ISTA);
if (valhscx) if (valhscx)
@ -280,20 +269,20 @@ gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs)
WriteISAC(cs, ISAC_MASK, 0x0); WriteISAC(cs, ISAC_MASK, 0x0);
WriteHSCX(cs, 0, HSCX_MASK, 0x0); WriteHSCX(cs, 0, HSCX_MASK, 0x0);
WriteHSCX(cs, 1, HSCX_MASK, 0x0); WriteHSCX(cs, 1, HSCX_MASK, 0x0);
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_HANDLED;
} }
static void static irqreturn_t
gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
{ {
struct IsdnCardState *cs = dev_id; struct IsdnCardState *cs = dev_id;
u_char ista, val; u_char ista, val;
int count = 0; int count = 0;
u_long flags;
if (!cs) {
printk(KERN_WARNING "Gazel: Spurious interrupt!\n"); spin_lock_irqsave(&cs->lock, flags);
return;
}
ista = ReadISAC(cs, IPAC_ISTA - 0x80); ista = ReadISAC(cs, IPAC_ISTA - 0x80);
do { do {
if (ista & 0x0f) { if (ista & 0x0f) {
@ -325,6 +314,8 @@ gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
WriteISAC(cs, IPAC_MASK - 0x80, 0xFF); WriteISAC(cs, IPAC_MASK - 0x80, 0xFF);
WriteISAC(cs, IPAC_MASK - 0x80, 0xC0); WriteISAC(cs, IPAC_MASK - 0x80, 0xC0);
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_HANDLED;
} }
void void
release_io_gazel(struct IsdnCardState *cs) release_io_gazel(struct IsdnCardState *cs)
@ -357,18 +348,14 @@ release_io_gazel(struct IsdnCardState *cs)
static int static int
reset_gazel(struct IsdnCardState *cs) reset_gazel(struct IsdnCardState *cs)
{ {
long flags;
unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg; unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
switch (cs->subtyp) { switch (cs->subtyp) {
case R647: case R647:
save_flags(flags);
cli();
writereg(addr, 0, 0); writereg(addr, 0, 0);
HZDELAY(10); HZDELAY(10);
writereg(addr, 0, 1); writereg(addr, 0, 1);
HZDELAY(2); HZDELAY(2);
restore_flags(flags);
break; break;
case R685: case R685:
plxcntrl = inl(addr + PLX_CNTRL); plxcntrl = inl(addr + PLX_CNTRL);
@ -414,14 +401,19 @@ reset_gazel(struct IsdnCardState *cs)
static int static int
Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg) Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{ {
u_long flags;
switch (mt) { switch (mt) {
case CARD_RESET: case CARD_RESET:
spin_lock_irqsave(&cs->lock, flags);
reset_gazel(cs); reset_gazel(cs);
spin_unlock_irqrestore(&cs->lock, flags);
return (0); return (0);
case CARD_RELEASE: case CARD_RELEASE:
release_io_gazel(cs); release_io_gazel(cs);
return (0); return (0);
case CARD_INIT: case CARD_INIT:
spin_lock_irqsave(&cs->lock, flags);
inithscxisac(cs, 1); inithscxisac(cs, 1);
if ((cs->subtyp==R647)||(cs->subtyp==R685)) { if ((cs->subtyp==R647)||(cs->subtyp==R685)) {
int i; int i;
@ -430,6 +422,7 @@ Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg)
cs->bcs[i].hw.hscx.tsaxr1 = 0x23; cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
} }
} }
spin_unlock_irqrestore(&cs->lock, flags);
return (0); return (0);
case CARD_TEST: case CARD_TEST:
return (0); return (0);
@ -440,48 +433,46 @@ Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg)
static int static int
reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs) reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
{ {
unsigned int i, base = 0, adr = 0, len = 0; unsigned int i, j, base = 0, adr = 0, len = 0;
switch (cs->subtyp) { switch (cs->subtyp) {
case R647: case R647:
base = cs->hw.gazel.hscx[0]; base = cs->hw.gazel.hscx[0];
if (!request_region(adr = (0xC000 + base), len = 1, "gazel"))
goto error;
for (i = 0x0000; i < 0xC000; i += 0x1000) { for (i = 0x0000; i < 0xC000; i += 0x1000) {
if (check_region(adr = (i + base), len = 16)) if (!request_region(adr = (i + base), len = 16, "gazel"))
goto error; goto error;
} }
if (check_region(adr = (0xC000 + base), len = 1)) if (i != 0xC000) {
for (j = 0; j < i; j+= 0x1000)
release_region(j + base, 16);
release_region(0xC000 + base, 1);
goto error; goto error;
}
for (i = 0x0000; i < 0xC000; i += 0x1000)
request_region(i + base, 16, "gazel");
request_region(0xC000 + base, 1, "gazel");
break; break;
case R685: case R685:
if (check_region(adr = cs->hw.gazel.hscx[0], len = 0x100)) if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel"))
goto error; goto error;
if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80)) if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
release_region(cs->hw.gazel.hscx[0],0x100);
goto error; goto error;
}
request_region(cs->hw.gazel.hscx[0], 0x100, "gazel");
request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
break; break;
case R753: case R753:
if (check_region(adr = cs->hw.gazel.ipac, len = 0x8)) if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
goto error; goto error;
if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80)) if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
release_region(cs->hw.gazel.ipac, 8);
goto error; goto error;
}
request_region(cs->hw.gazel.ipac, 0x8, "gazel");
request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
break; break;
case R742: case R742:
if (check_region(adr = cs->hw.gazel.ipac, len = 0x8)) if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
goto error; goto error;
request_region(cs->hw.gazel.ipac, 0x8, "gazel");
break; break;
} }
@ -506,6 +497,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
else else
cs->subtyp = R647; cs->subtyp = R647;
setup_isac(cs);
cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
cs->hw.gazel.ipac = card->para[1]; cs->hw.gazel.ipac = card->para[1];
cs->hw.gazel.isac = card->para[1] + 0x8000; cs->hw.gazel.isac = card->para[1] + 0x8000;
@ -552,10 +544,6 @@ setup_gazelpci(struct IsdnCardState *cs)
printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
found = 0; found = 0;
if (!pci_present()) {
printk(KERN_WARNING "Gazel: No PCI bus present\n");
return 1;
}
seekcard = PCI_DEVICE_ID_PLX_R685; seekcard = PCI_DEVICE_ID_PLX_R685;
for (nbseek = 0; nbseek < 3; nbseek++) { for (nbseek = 0; nbseek < 3; nbseek++) {
if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) { if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) {
@ -589,7 +577,7 @@ setup_gazelpci(struct IsdnCardState *cs)
} }
cs->hw.gazel.pciaddr[0] = pci_ioaddr0; cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
cs->hw.gazel.pciaddr[1] = pci_ioaddr1; cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
setup_isac(cs);
pci_ioaddr1 &= 0xfffe; pci_ioaddr1 &= 0xfffe;
cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe; cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
cs->hw.gazel.ipac = pci_ioaddr1; cs->hw.gazel.ipac = pci_ioaddr1;

View File

@ -78,17 +78,6 @@ writereghfcd(struct IsdnCardState *cs, u_char offset, u_char value)
WriteReg(cs, HFCD_DATA, offset, value); WriteReg(cs, HFCD_DATA, offset, value);
} }
void
set_cs_func(struct IsdnCardState *cs)
{
cs->readisac = &readreghfcd;
cs->writeisac = &writereghfcd;
cs->readisacfifo = &dummyf;
cs->writeisacfifo = &dummyf;
cs->BC_Read_Reg = &ReadReg;
cs->BC_Write_Reg = &WriteReg;
}
static inline int static inline int
WaitForBusy(struct IsdnCardState *cs) WaitForBusy(struct IsdnCardState *cs)
{ {
@ -106,15 +95,11 @@ WaitForBusy(struct IsdnCardState *cs)
static inline int static inline int
WaitNoBusy(struct IsdnCardState *cs) WaitNoBusy(struct IsdnCardState *cs)
{ {
long flags;
int to = 130; int to = 130;
while ((ReadReg(cs, HFCD_STATUS, HFCD_STATUS) & HFCD_BUSY) && to) { while ((ReadReg(cs, HFCD_STATUS, HFCD_STATUS) & HFCD_BUSY) && to) {
save_flags(flags);
sti();
udelay(1); udelay(1);
to--; to--;
restore_flags(flags);
} }
if (!to) if (!to)
printk(KERN_WARNING "HiSax: WaitNoBusy timeout\n"); printk(KERN_WARNING "HiSax: WaitNoBusy timeout\n");
@ -125,13 +110,9 @@ static int
SelFiFo(struct IsdnCardState *cs, u_char FiFo) SelFiFo(struct IsdnCardState *cs, u_char FiFo)
{ {
u_char cip; u_char cip;
long flags;
if (cs->hw.hfcD.fifo == FiFo) if (cs->hw.hfcD.fifo == FiFo)
return(1); return(1);
save_flags(flags);
cli();
switch(FiFo) { switch(FiFo) {
case 0: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B1; case 0: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B1;
break; break;
@ -146,18 +127,16 @@ SelFiFo(struct IsdnCardState *cs, u_char FiFo)
case 5: cip = HFCD_FIFO | HFCD_Z1 | HFCD_REC; case 5: cip = HFCD_FIFO | HFCD_Z1 | HFCD_REC;
break; break;
default: default:
restore_flags(flags);
debugl1(cs, "SelFiFo Error"); debugl1(cs, "SelFiFo Error");
return(0); return(0);
} }
cs->hw.hfcD.fifo = FiFo; cs->hw.hfcD.fifo = FiFo;
WaitNoBusy(cs); WaitNoBusy(cs);
cs->BC_Write_Reg(cs, HFCD_DATA, cip, 0); cs->BC_Write_Reg(cs, HFCD_DATA, cip, 0);
sti();
WaitForBusy(cs); WaitForBusy(cs);
restore_flags(flags);
return(2); return(2);
} }
static int static int
GetFreeFifoBytes_B(struct BCState *bcs) GetFreeFifoBytes_B(struct BCState *bcs)
{ {
@ -198,14 +177,6 @@ ReadZReg(struct IsdnCardState *cs, u_char reg)
return (val); return (val);
} }
static void
hfc_sched_event(struct BCState *bcs, int event)
{
bcs->event |= 1 << event;
queue_task(&bcs->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
static struct sk_buff static struct sk_buff
*hfc_empty_fifo(struct BCState *bcs, int count) *hfc_empty_fifo(struct BCState *bcs, int count)
{ {
@ -214,22 +185,18 @@ static struct sk_buff
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
int idx; int idx;
int chksum; int chksum;
long flags;
u_char stat, cip; u_char stat, cip;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hfc_empty_fifo"); debugl1(cs, "hfc_empty_fifo");
idx = 0; idx = 0;
save_flags(flags);
if (count > HSCX_BUFMAX + 3) { if (count > HSCX_BUFMAX + 3) {
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hfc_empty_fifo: incoming packet too large"); debugl1(cs, "hfc_empty_fifo: incoming packet too large");
cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
while (idx++ < count) { while (idx++ < count) {
cli();
WaitNoBusy(cs); WaitNoBusy(cs);
ReadReg(cs, HFCD_DATA_NODEB, cip); ReadReg(cs, HFCD_DATA_NODEB, cip);
sti();
} }
skb = NULL; skb = NULL;
} else if (count < 4) { } else if (count < 4) {
@ -239,7 +206,6 @@ static struct sk_buff
#ifdef ERROR_STATISTIC #ifdef ERROR_STATISTIC
bcs->err_inv++; bcs->err_inv++;
#endif #endif
cli();
while ((idx++ < count) && WaitNoBusy(cs)) while ((idx++ < count) && WaitNoBusy(cs))
ReadReg(cs, HFCD_DATA_NODEB, cip); ReadReg(cs, HFCD_DATA_NODEB, cip);
skb = NULL; skb = NULL;
@ -249,31 +215,25 @@ static struct sk_buff
ptr = skb_put(skb, count - 3); ptr = skb_put(skb, count - 3);
idx = 0; idx = 0;
cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
cli();
while (idx < (count - 3)) { while (idx < (count - 3)) {
cli();
if (!WaitNoBusy(cs)) if (!WaitNoBusy(cs))
break; break;
*ptr = ReadReg(cs, HFCD_DATA_NODEB, cip); *ptr = ReadReg(cs, HFCD_DATA_NODEB, cip);
sti();
ptr++; ptr++;
idx++; idx++;
} }
if (idx != count - 3) { if (idx != count - 3) {
sti();
debugl1(cs, "RFIFO BUSY error"); debugl1(cs, "RFIFO BUSY error");
printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
dev_kfree_skb_irq(skb); dev_kfree_skb_irq(skb);
skb = NULL; skb = NULL;
} else { } else {
cli();
WaitNoBusy(cs); WaitNoBusy(cs);
chksum = (ReadReg(cs, HFCD_DATA, cip) << 8); chksum = (ReadReg(cs, HFCD_DATA, cip) << 8);
WaitNoBusy(cs); WaitNoBusy(cs);
chksum += ReadReg(cs, HFCD_DATA, cip); chksum += ReadReg(cs, HFCD_DATA, cip);
WaitNoBusy(cs); WaitNoBusy(cs);
stat = ReadReg(cs, HFCD_DATA, cip); stat = ReadReg(cs, HFCD_DATA, cip);
sti();
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x", debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
bcs->channel, chksum, stat); bcs->channel, chksum, stat);
@ -287,15 +247,11 @@ static struct sk_buff
} }
} }
} }
sti();
WaitForBusy(cs); WaitForBusy(cs);
cli();
WaitNoBusy(cs); WaitNoBusy(cs);
stat = ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F2_INC | stat = ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F2_INC |
HFCB_REC | HFCB_CHANNEL(bcs->channel)); HFCB_REC | HFCB_CHANNEL(bcs->channel));
sti();
WaitForBusy(cs); WaitForBusy(cs);
restore_flags(flags);
return (skb); return (skb);
} }
@ -303,7 +259,6 @@ static void
hfc_fill_fifo(struct BCState *bcs) hfc_fill_fifo(struct BCState *bcs)
{ {
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
long flags;
int idx, fcnt; int idx, fcnt;
int count; int count;
u_char cip; u_char cip;
@ -312,8 +267,6 @@ hfc_fill_fifo(struct BCState *bcs)
return; return;
if (bcs->tx_skb->len <= 0) if (bcs->tx_skb->len <= 0)
return; return;
save_flags(flags);
cli();
SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel)); SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel));
cip = HFCB_FIFO | HFCB_F1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel); cip = HFCB_FIFO | HFCB_F1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel);
WaitNoBusy(cs); WaitNoBusy(cs);
@ -323,7 +276,6 @@ hfc_fill_fifo(struct BCState *bcs)
WaitNoBusy(cs); WaitNoBusy(cs);
bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip); bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip);
bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel)); bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel));
sti();
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2, bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
@ -334,7 +286,6 @@ hfc_fill_fifo(struct BCState *bcs)
if (fcnt > 30) { if (fcnt > 30) {
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo more as 30 frames"); debugl1(cs, "hfc_fill_fifo more as 30 frames");
restore_flags(flags);
return; return;
} }
count = GetFreeFifoBytes_B(bcs); count = GetFreeFifoBytes_B(bcs);
@ -345,25 +296,20 @@ hfc_fill_fifo(struct BCState *bcs)
if (count < bcs->tx_skb->len) { if (count < bcs->tx_skb->len) {
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo no fifo mem"); debugl1(cs, "hfc_fill_fifo no fifo mem");
restore_flags(flags);
return; return;
} }
cip = HFCB_FIFO | HFCB_FIFO_IN | HFCB_SEND | HFCB_CHANNEL(bcs->channel); cip = HFCB_FIFO | HFCB_FIFO_IN | HFCB_SEND | HFCB_CHANNEL(bcs->channel);
idx = 0; idx = 0;
cli();
WaitForBusy(cs); WaitForBusy(cs);
WaitNoBusy(cs); WaitNoBusy(cs);
WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
while (idx < bcs->tx_skb->len) { while (idx < bcs->tx_skb->len) {
cli();
if (!WaitNoBusy(cs)) if (!WaitNoBusy(cs))
break; break;
WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]); WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]);
sti();
idx++; idx++;
} }
if (idx != bcs->tx_skb->len) { if (idx != bcs->tx_skb->len) {
sti();
debugl1(cs, "FIFO Send BUSY error"); debugl1(cs, "FIFO Send BUSY error");
printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
} else { } else {
@ -375,13 +321,10 @@ hfc_fill_fifo(struct BCState *bcs)
bcs->tx_skb = NULL; bcs->tx_skb = NULL;
} }
WaitForBusy(cs); WaitForBusy(cs);
cli();
WaitNoBusy(cs); WaitNoBusy(cs);
ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F1_INC | HFCB_SEND | HFCB_CHANNEL(bcs->channel)); ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F1_INC | HFCB_SEND | HFCB_CHANNEL(bcs->channel));
sti();
WaitForBusy(cs); WaitForBusy(cs);
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
restore_flags(flags);
return; return;
} }
@ -400,20 +343,16 @@ hfc_send_data(struct BCState *bcs)
void void
main_rec_2bds0(struct BCState *bcs) main_rec_2bds0(struct BCState *bcs)
{ {
long flags;
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
int z1, z2, rcnt; int z1, z2, rcnt;
u_char f1, f2, cip; u_char f1, f2, cip;
int receive, count = 5; int receive, count = 5;
struct sk_buff *skb; struct sk_buff *skb;
save_flags(flags);
Begin: Begin:
count--; count--;
cli();
if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
debugl1(cs,"rec_data %d blocked", bcs->channel); debugl1(cs,"rec_data %d blocked", bcs->channel);
restore_flags(flags);
return; return;
} }
SelFiFo(cs, HFCB_REC | HFCB_CHANNEL(bcs->channel)); SelFiFo(cs, HFCB_REC | HFCB_CHANNEL(bcs->channel));
@ -423,15 +362,12 @@ main_rec_2bds0(struct BCState *bcs)
cip = HFCB_FIFO | HFCB_F2 | HFCB_REC | HFCB_CHANNEL(bcs->channel); cip = HFCB_FIFO | HFCB_F2 | HFCB_REC | HFCB_CHANNEL(bcs->channel);
WaitNoBusy(cs); WaitNoBusy(cs);
f2 = ReadReg(cs, HFCD_DATA, cip); f2 = ReadReg(cs, HFCD_DATA, cip);
sti();
if (f1 != f2) { if (f1 != f2) {
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc rec %d f1(%d) f2(%d)", debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
bcs->channel, f1, f2); bcs->channel, f1, f2);
cli();
z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel)); z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel)); z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
sti();
rcnt = z1 - z2; rcnt = z1 - z2;
if (rcnt < 0) if (rcnt < 0)
rcnt += cs->hw.hfcD.bfifosize; rcnt += cs->hw.hfcD.bfifosize;
@ -440,10 +376,8 @@ main_rec_2bds0(struct BCState *bcs)
debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)", debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
bcs->channel, z1, z2, rcnt); bcs->channel, z1, z2, rcnt);
if ((skb = hfc_empty_fifo(bcs, rcnt))) { if ((skb = hfc_empty_fifo(bcs, rcnt))) {
cli();
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
sti(); schedule_event(bcs, B_RCVBUFREADY);
hfc_sched_event(bcs, B_RCVBUFREADY);
} }
rcnt = f1 -f2; rcnt = f1 -f2;
if (rcnt<0) if (rcnt<0)
@ -457,7 +391,6 @@ main_rec_2bds0(struct BCState *bcs)
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
if (count && receive) if (count && receive)
goto Begin; goto Begin;
restore_flags(flags);
return; return;
} }
@ -512,54 +445,56 @@ mode_2bs0(struct BCState *bcs, int mode, int bc)
static void static void
hfc_l2l1(struct PStack *st, int pr, void *arg) hfc_l2l1(struct PStack *st, int pr, void *arg)
{ {
struct BCState *bcs = st->l1.bcs;
struct sk_buff *skb = arg; struct sk_buff *skb = arg;
long flags; u_long flags;
switch (pr) { switch (pr) {
case (PH_DATA | REQUEST): case (PH_DATA | REQUEST):
save_flags(flags); spin_lock_irqsave(&bcs->cs->lock, flags);
cli(); if (bcs->tx_skb) {
if (st->l1.bcs->tx_skb) { skb_queue_tail(&bcs->squeue, skb);
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else { } else {
st->l1.bcs->tx_skb = skb; bcs->tx_skb = skb;
/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); // test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
*/ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); bcs->cs->BC_Send_Data(bcs);
restore_flags(flags);
} }
spin_unlock_irqrestore(&bcs->cs->lock, flags);
break; break;
case (PH_PULL | INDICATION): case (PH_PULL | INDICATION):
if (st->l1.bcs->tx_skb) { spin_lock_irqsave(&bcs->cs->lock, flags);
if (bcs->tx_skb) {
printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
break; } else {
// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->tx_skb = skb;
bcs->cs->BC_Send_Data(bcs);
} }
save_flags(flags); spin_unlock_irqrestore(&bcs->cs->lock, flags);
cli();
/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
*/ st->l1.bcs->tx_skb = skb;
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
restore_flags(flags);
break; break;
case (PH_PULL | REQUEST): case (PH_PULL | REQUEST):
if (!st->l1.bcs->tx_skb) { if (!bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else } else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break; break;
case (PH_ACTIVATE | REQUEST): case (PH_ACTIVATE | REQUEST):
test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); spin_lock_irqsave(&bcs->cs->lock, flags);
mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc); test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
mode_2bs0(bcs, st->l1.mode, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
l1_msg_b(st, pr, arg); l1_msg_b(st, pr, arg);
break; break;
case (PH_DEACTIVATE | REQUEST): case (PH_DEACTIVATE | REQUEST):
l1_msg_b(st, pr, arg); l1_msg_b(st, pr, arg);
break; break;
case (PH_DEACTIVATE | CONFIRM): case (PH_DEACTIVATE | CONFIRM):
test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); spin_lock_irqsave(&bcs->cs->lock, flags);
test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
mode_2bs0(st->l1.bcs, 0, st->l1.bc); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
mode_2bs0(bcs, 0, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
break; break;
} }
@ -611,8 +546,6 @@ setstack_2b(struct PStack *st, struct BCState *bcs)
static void static void
hfcd_bh(struct IsdnCardState *cs) hfcd_bh(struct IsdnCardState *cs)
{ {
/* struct PStack *stptr;
*/
if (!cs) if (!cs)
return; return;
if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
@ -642,19 +575,10 @@ hfcd_bh(struct IsdnCardState *cs)
DChannel_proc_xmt(cs); DChannel_proc_xmt(cs);
} }
void
sched_event_D(struct IsdnCardState *cs, int event)
{
test_and_set_bit(event, &cs->event);
queue_task(&cs->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
static static
int receive_dmsg(struct IsdnCardState *cs) int receive_dmsg(struct IsdnCardState *cs)
{ {
struct sk_buff *skb; struct sk_buff *skb;
long flags;
int idx; int idx;
int rcnt, z1, z2; int rcnt, z1, z2;
u_char stat, cip, f1, f2; u_char stat, cip, f1, f2;
@ -662,11 +586,8 @@ int receive_dmsg(struct IsdnCardState *cs)
int count=5; int count=5;
u_char *ptr; u_char *ptr;
save_flags(flags);
cli();
if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
debugl1(cs, "rec_dmsg blocked"); debugl1(cs, "rec_dmsg blocked");
restore_flags(flags);
return(1); return(1);
} }
SelFiFo(cs, 4 | HFCD_REC); SelFiFo(cs, 4 | HFCD_REC);
@ -686,7 +607,6 @@ int receive_dmsg(struct IsdnCardState *cs)
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)", debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
f1, f2, z1, z2, rcnt); f1, f2, z1, z2, rcnt);
sti();
idx = 0; idx = 0;
cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC; cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC;
if (rcnt > MAX_DFRAME_LEN + 3) { if (rcnt > MAX_DFRAME_LEN + 3) {
@ -697,28 +617,23 @@ int receive_dmsg(struct IsdnCardState *cs)
if (!(WaitNoBusy(cs))) if (!(WaitNoBusy(cs)))
break; break;
ReadReg(cs, HFCD_DATA_NODEB, cip); ReadReg(cs, HFCD_DATA_NODEB, cip);
sti();
idx++; idx++;
} }
} else if (rcnt < 4) { } else if (rcnt < 4) {
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, "empty_fifo d: incoming packet too small"); debugl1(cs, "empty_fifo d: incoming packet too small");
cli();
while ((idx++ < rcnt) && WaitNoBusy(cs)) while ((idx++ < rcnt) && WaitNoBusy(cs))
ReadReg(cs, HFCD_DATA_NODEB, cip); ReadReg(cs, HFCD_DATA_NODEB, cip);
} else if ((skb = dev_alloc_skb(rcnt - 3))) { } else if ((skb = dev_alloc_skb(rcnt - 3))) {
ptr = skb_put(skb, rcnt - 3); ptr = skb_put(skb, rcnt - 3);
while (idx < (rcnt - 3)) { while (idx < (rcnt - 3)) {
cli();
if (!(WaitNoBusy(cs))) if (!(WaitNoBusy(cs)))
break; break;
*ptr = ReadReg(cs, HFCD_DATA_NODEB, cip); *ptr = ReadReg(cs, HFCD_DATA_NODEB, cip);
sti();
idx++; idx++;
ptr++; ptr++;
} }
if (idx != (rcnt - 3)) { if (idx != (rcnt - 3)) {
sti();
debugl1(cs, "RFIFO D BUSY error"); debugl1(cs, "RFIFO D BUSY error");
printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n"); printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n");
dev_kfree_skb_irq(skb); dev_kfree_skb_irq(skb);
@ -727,14 +642,12 @@ int receive_dmsg(struct IsdnCardState *cs)
cs->err_rx++; cs->err_rx++;
#endif #endif
} else { } else {
cli();
WaitNoBusy(cs); WaitNoBusy(cs);
chksum = (ReadReg(cs, HFCD_DATA, cip) << 8); chksum = (ReadReg(cs, HFCD_DATA, cip) << 8);
WaitNoBusy(cs); WaitNoBusy(cs);
chksum += ReadReg(cs, HFCD_DATA, cip); chksum += ReadReg(cs, HFCD_DATA, cip);
WaitNoBusy(cs); WaitNoBusy(cs);
stat = ReadReg(cs, HFCD_DATA, cip); stat = ReadReg(cs, HFCD_DATA, cip);
sti();
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "empty_dfifo chksum %x stat %x", debugl1(cs, "empty_dfifo chksum %x stat %x",
chksum, stat); chksum, stat);
@ -747,33 +660,27 @@ int receive_dmsg(struct IsdnCardState *cs)
#endif #endif
} else { } else {
skb_queue_tail(&cs->rq, skb); skb_queue_tail(&cs->rq, skb);
sched_event_D(cs, D_RCVBUFREADY); schedule_event(cs, D_RCVBUFREADY);
} }
} }
} else } else
printk(KERN_WARNING "HFC: D receive out of memory\n"); printk(KERN_WARNING "HFC: D receive out of memory\n");
sti();
WaitForBusy(cs); WaitForBusy(cs);
cip = HFCD_FIFO | HFCD_F2_INC | HFCD_REC; cip = HFCD_FIFO | HFCD_F2_INC | HFCD_REC;
cli();
WaitNoBusy(cs); WaitNoBusy(cs);
stat = ReadReg(cs, HFCD_DATA, cip); stat = ReadReg(cs, HFCD_DATA, cip);
sti();
WaitForBusy(cs); WaitForBusy(cs);
cip = HFCD_FIFO | HFCD_F2 | HFCD_REC; cip = HFCD_FIFO | HFCD_F2 | HFCD_REC;
cli();
WaitNoBusy(cs); WaitNoBusy(cs);
f2 = cs->readisac(cs, cip) & 0xf; f2 = cs->readisac(cs, cip) & 0xf;
} }
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
restore_flags(flags);
return(1); return(1);
} }
static void static void
hfc_fill_dfifo(struct IsdnCardState *cs) hfc_fill_dfifo(struct IsdnCardState *cs)
{ {
long flags;
int idx, fcnt; int idx, fcnt;
int count; int count;
u_char cip; u_char cip;
@ -783,8 +690,6 @@ hfc_fill_dfifo(struct IsdnCardState *cs)
if (cs->tx_skb->len <= 0) if (cs->tx_skb->len <= 0)
return; return;
save_flags(flags);
cli();
SelFiFo(cs, 4 | HFCD_SEND); SelFiFo(cs, 4 | HFCD_SEND);
cip = HFCD_FIFO | HFCD_F1 | HFCD_SEND; cip = HFCD_FIFO | HFCD_F1 | HFCD_SEND;
WaitNoBusy(cs); WaitNoBusy(cs);
@ -793,7 +698,6 @@ hfc_fill_dfifo(struct IsdnCardState *cs)
cip = HFCD_FIFO | HFCD_F2 | HFCD_SEND; cip = HFCD_FIFO | HFCD_F2 | HFCD_SEND;
cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf; cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf;
cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND); cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND);
sti();
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)", debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",
cs->hw.hfcD.f1, cs->hw.hfcD.f2, cs->hw.hfcD.f1, cs->hw.hfcD.f2,
@ -804,7 +708,6 @@ hfc_fill_dfifo(struct IsdnCardState *cs)
if (fcnt > 14) { if (fcnt > 14) {
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_Dfifo more as 14 frames"); debugl1(cs, "hfc_fill_Dfifo more as 14 frames");
restore_flags(flags);
return; return;
} }
count = GetFreeFifoBytes_D(cs); count = GetFreeFifoBytes_D(cs);
@ -814,37 +717,29 @@ hfc_fill_dfifo(struct IsdnCardState *cs)
if (count < cs->tx_skb->len) { if (count < cs->tx_skb->len) {
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "hfc_fill_Dfifo no fifo mem"); debugl1(cs, "hfc_fill_Dfifo no fifo mem");
restore_flags(flags);
return; return;
} }
cip = HFCD_FIFO | HFCD_FIFO_IN | HFCD_SEND; cip = HFCD_FIFO | HFCD_FIFO_IN | HFCD_SEND;
idx = 0; idx = 0;
cli();
WaitForBusy(cs); WaitForBusy(cs);
WaitNoBusy(cs); WaitNoBusy(cs);
WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx++]); WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx++]);
while (idx < cs->tx_skb->len) { while (idx < cs->tx_skb->len) {
cli();
if (!(WaitNoBusy(cs))) if (!(WaitNoBusy(cs)))
break; break;
WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx]); WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx]);
sti();
idx++; idx++;
} }
if (idx != cs->tx_skb->len) { if (idx != cs->tx_skb->len) {
sti();
debugl1(cs, "DFIFO Send BUSY error"); debugl1(cs, "DFIFO Send BUSY error");
printk(KERN_WARNING "HFC S DFIFO channel BUSY Error\n"); printk(KERN_WARNING "HFC S DFIFO channel BUSY Error\n");
} }
WaitForBusy(cs); WaitForBusy(cs);
cli();
WaitNoBusy(cs); WaitNoBusy(cs);
ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND); ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND);
dev_kfree_skb_any(cs->tx_skb); dev_kfree_skb_any(cs->tx_skb);
cs->tx_skb = NULL; cs->tx_skb = NULL;
sti();
WaitForBusy(cs); WaitForBusy(cs);
restore_flags(flags);
return; return;
} }
@ -865,7 +760,6 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
u_char exval; u_char exval;
struct BCState *bcs; struct BCState *bcs;
int count=15; int count=15;
long flags;
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "HFCD irq %x %s", val, debugl1(cs, "HFCD irq %x %s", val,
@ -878,15 +772,12 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state, debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state,
exval); exval);
cs->dc.hfcd.ph_state = exval; cs->dc.hfcd.ph_state = exval;
sched_event_D(cs, D_L1STATECHANGE); schedule_event(cs, D_L1STATECHANGE);
val &= ~0x40; val &= ~0x40;
} }
while (val) { while (val) {
save_flags(flags);
cli();
if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
cs->hw.hfcD.int_s1 |= val; cs->hw.hfcD.int_s1 |= val;
restore_flags(flags);
return; return;
} }
if (cs->hw.hfcD.int_s1 & 0x18) { if (cs->hw.hfcD.int_s1 & 0x18) {
@ -927,7 +818,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
} else } else
debugl1(cs,"fill_data %d blocked", bcs->channel); debugl1(cs,"fill_data %d blocked", bcs->channel);
} else { } else {
hfc_sched_event(bcs, B_XMTBUFREADY); schedule_event(bcs, B_XMTBUFREADY);
} }
} }
} }
@ -951,7 +842,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
} else } else
debugl1(cs,"fill_data %d blocked", bcs->channel); debugl1(cs,"fill_data %d blocked", bcs->channel);
} else { } else {
hfc_sched_event(bcs, B_XMTBUFREADY); schedule_event(bcs, B_XMTBUFREADY);
} }
} }
} }
@ -963,7 +854,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
del_timer(&cs->dbusytimer); del_timer(&cs->dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
sched_event_D(cs, D_CLEARBUSY); schedule_event(cs, D_CLEARBUSY);
if (cs->tx_skb) { if (cs->tx_skb) {
if (cs->tx_skb->len) { if (cs->tx_skb->len) {
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
@ -988,7 +879,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
debugl1(cs, "hfc_fill_dfifo irq blocked"); debugl1(cs, "hfc_fill_dfifo irq blocked");
} }
} else } else
sched_event_D(cs, D_XMTBUFREADY); schedule_event(cs, D_XMTBUFREADY);
} }
afterXPR: afterXPR:
if (cs->hw.hfcD.int_s1 && count--) { if (cs->hw.hfcD.int_s1 && count--) {
@ -998,7 +889,6 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
debugl1(cs, "HFCD irq %x loop %d", val, 15-count); debugl1(cs, "HFCD irq %x loop %d", val, 15-count);
} else } else
val = 0; val = 0;
restore_flags(flags);
} }
} }
@ -1007,6 +897,7 @@ HFCD_l1hw(struct PStack *st, int pr, void *arg)
{ {
struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
struct sk_buff *skb = arg; struct sk_buff *skb = arg;
u_long flags;
switch (pr) { switch (pr) {
case (PH_DATA | REQUEST): case (PH_DATA | REQUEST):
@ -1014,6 +905,7 @@ HFCD_l1hw(struct PStack *st, int pr, void *arg)
LogFrame(cs, skb->data, skb->len); LogFrame(cs, skb->data, skb->len);
if (cs->debug & DEB_DLOG_VERBOSE) if (cs->debug & DEB_DLOG_VERBOSE)
dlogframe(cs, skb, 0); dlogframe(cs, skb, 0);
spin_lock_irqsave(&cs->lock, flags);
if (cs->tx_skb) { if (cs->tx_skb) {
skb_queue_tail(&cs->sq, skb); skb_queue_tail(&cs->sq, skb);
#ifdef L2FRAME_DEBUG /* psa */ #ifdef L2FRAME_DEBUG /* psa */
@ -1034,12 +926,15 @@ HFCD_l1hw(struct PStack *st, int pr, void *arg)
debugl1(cs, "hfc_fill_dfifo blocked"); debugl1(cs, "hfc_fill_dfifo blocked");
} }
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (PH_PULL | INDICATION): case (PH_PULL | INDICATION):
spin_lock_irqsave(&cs->lock, flags);
if (cs->tx_skb) { if (cs->tx_skb) {
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
skb_queue_tail(&cs->sq, skb); skb_queue_tail(&cs->sq, skb);
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
} }
if (cs->debug & DEB_DLOG_HEX) if (cs->debug & DEB_DLOG_HEX)
@ -1057,6 +952,7 @@ HFCD_l1hw(struct PStack *st, int pr, void *arg)
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
} else } else
debugl1(cs, "hfc_fill_dfifo blocked"); debugl1(cs, "hfc_fill_dfifo blocked");
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (PH_PULL | REQUEST): case (PH_PULL | REQUEST):
#ifdef L2FRAME_DEBUG /* psa */ #ifdef L2FRAME_DEBUG /* psa */
@ -1070,24 +966,32 @@ HFCD_l1hw(struct PStack *st, int pr, void *arg)
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break; break;
case (HW_RESET | REQUEST): case (HW_RESET | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */ cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */
udelay(6); udelay(6);
cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */ cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */
cs->hw.hfcD.mst_m |= HFCD_MASTER; cs->hw.hfcD.mst_m |= HFCD_MASTER;
cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
spin_unlock_irqrestore(&cs->lock, flags);
l1_msg(cs, HW_POWERUP | CONFIRM, NULL); l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
break; break;
case (HW_ENABLE | REQUEST): case (HW_ENABLE | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (HW_DEACTIVATE | REQUEST): case (HW_DEACTIVATE | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
cs->hw.hfcD.mst_m &= ~HFCD_MASTER; cs->hw.hfcD.mst_m &= ~HFCD_MASTER;
cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (HW_INFO3 | REQUEST): case (HW_INFO3 | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
cs->hw.hfcD.mst_m |= HFCD_MASTER; cs->hw.hfcD.mst_m |= HFCD_MASTER;
cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
default: default:
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
@ -1126,10 +1030,6 @@ void __init
init2bds0(struct IsdnCardState *cs) init2bds0(struct IsdnCardState *cs)
{ {
cs->setstack_d = setstack_hfcd; cs->setstack_d = setstack_hfcd;
cs->dbusytimer.function = (void *) hfc_dbusy_timer;
cs->dbusytimer.data = (long) cs;
init_timer(&cs->dbusytimer);
cs->tqueue.routine = (void *) (void *) hfcd_bh;
if (!cs->hw.hfcD.send) if (!cs->hw.hfcD.send)
cs->hw.hfcD.send = init_send_hfcd(16); cs->hw.hfcD.send = init_send_hfcd(16);
if (!cs->bcs[0].hw.hfc.send) if (!cs->bcs[0].hw.hfc.send)
@ -1161,3 +1061,18 @@ release2bds0(struct IsdnCardState *cs)
cs->hw.hfcD.send = NULL; cs->hw.hfcD.send = NULL;
} }
} }
void
set_cs_func(struct IsdnCardState *cs)
{
cs->readisac = &readreghfcd;
cs->writeisac = &writereghfcd;
cs->readisacfifo = &dummyf;
cs->writeisacfifo = &dummyf;
cs->BC_Read_Reg = &ReadReg;
cs->BC_Write_Reg = &WriteReg;
cs->dbusytimer.function = (void *) hfc_dbusy_timer;
cs->dbusytimer.data = (long) cs;
init_timer(&cs->dbusytimer);
INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs);
}

View File

@ -21,18 +21,14 @@ static inline int
WaitForBusy(struct IsdnCardState *cs) WaitForBusy(struct IsdnCardState *cs)
{ {
int to = 130; int to = 130;
long flags;
u_char val; u_char val;
save_flags(flags);
cli();
while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 | val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 |
(cs->hw.hfc.cip & 3)); (cs->hw.hfc.cip & 3));
udelay(1); udelay(1);
to--; to--;
} }
restore_flags(flags);
if (!to) { if (!to) {
printk(KERN_WARNING "HiSax: waitforBusy timeout\n"); printk(KERN_WARNING "HiSax: waitforBusy timeout\n");
return (0); return (0);
@ -82,27 +78,16 @@ ReadZReg(struct BCState *bcs, u_char reg)
return (val); return (val);
} }
void
hfc_sched_event(struct BCState *bcs, int event)
{
bcs->event |= 1 << event;
queue_task(&bcs->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
static void static void
hfc_clear_fifo(struct BCState *bcs) hfc_clear_fifo(struct BCState *bcs)
{ {
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
long flags;
int idx, cnt; int idx, cnt;
int rcnt, z1, z2; int rcnt, z1, z2;
u_char cip, f1, f2; u_char cip, f1, f2;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hfc_clear_fifo"); debugl1(cs, "hfc_clear_fifo");
save_flags(flags);
cli();
cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
@ -149,7 +134,6 @@ hfc_clear_fifo(struct BCState *bcs)
z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel)); z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel)); z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
} }
restore_flags(flags);
return; return;
} }
@ -252,7 +236,6 @@ static void
hfc_fill_fifo(struct BCState *bcs) hfc_fill_fifo(struct BCState *bcs)
{ {
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
long flags;
int idx, fcnt; int idx, fcnt;
int count; int count;
int z1, z2; int z1, z2;
@ -263,8 +246,6 @@ hfc_fill_fifo(struct BCState *bcs)
if (bcs->tx_skb->len <= 0) if (bcs->tx_skb->len <= 0)
return; return;
save_flags(flags);
cli();
cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel); cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel);
if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
@ -287,7 +268,6 @@ hfc_fill_fifo(struct BCState *bcs)
if (fcnt > 30) { if (fcnt > 30) {
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo more as 30 frames"); debugl1(cs, "hfc_fill_fifo more as 30 frames");
restore_flags(flags);
return; return;
} }
count = GetFreeFifoBytes(bcs); count = GetFreeFifoBytes(bcs);
@ -307,7 +287,6 @@ hfc_fill_fifo(struct BCState *bcs)
if (count < bcs->tx_skb->len) { if (count < bcs->tx_skb->len) {
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo no fifo mem"); debugl1(cs, "hfc_fill_fifo no fifo mem");
restore_flags(flags);
return; return;
} }
cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel); cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel);
@ -333,23 +312,19 @@ hfc_fill_fifo(struct BCState *bcs)
bcs->st->lli.l1writewakeup(bcs->st, count); bcs->st->lli.l1writewakeup(bcs->st, count);
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
} }
restore_flags(flags);
return; return;
} }
void void
main_irq_hfc(struct BCState *bcs) main_irq_hfc(struct BCState *bcs)
{ {
long flags;
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
int z1, z2, rcnt; int z1, z2, rcnt;
u_char f1, f2, cip; u_char f1, f2, cip;
int receive, transmit, count = 5; int receive, transmit, count = 5;
struct sk_buff *skb; struct sk_buff *skb;
save_flags(flags);
Begin: Begin:
cli();
count--; count--;
cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
@ -385,14 +360,11 @@ main_irq_hfc(struct BCState *bcs)
/* sti(); */ /* sti(); */
if ((skb = hfc_empty_fifo(bcs, rcnt))) { if ((skb = hfc_empty_fifo(bcs, rcnt))) {
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
hfc_sched_event(bcs, B_RCVBUFREADY); schedule_event(bcs, B_RCVBUFREADY);
} }
} }
receive = 1; receive = 1;
} }
restore_flags(flags);
udelay(1);
cli();
if (bcs->tx_skb) { if (bcs->tx_skb) {
transmit = 1; transmit = 1;
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
@ -408,10 +380,9 @@ main_irq_hfc(struct BCState *bcs)
transmit = 0; transmit = 0;
} else { } else {
transmit = 0; transmit = 0;
hfc_sched_event(bcs, B_XMTBUFREADY); schedule_event(bcs, B_XMTBUFREADY);
} }
} }
restore_flags(flags);
if ((receive || transmit) && count) if ((receive || transmit) && count)
goto Begin; goto Begin;
return; return;
@ -474,54 +445,57 @@ mode_hfc(struct BCState *bcs, int mode, int bc)
static void static void
hfc_l2l1(struct PStack *st, int pr, void *arg) hfc_l2l1(struct PStack *st, int pr, void *arg)
{ {
struct sk_buff *skb = arg; struct BCState *bcs = st->l1.bcs;
long flags; struct sk_buff *skb = arg;
u_long flags;
switch (pr) { switch (pr) {
case (PH_DATA | REQUEST): case (PH_DATA | REQUEST):
save_flags(flags); spin_lock_irqsave(&bcs->cs->lock, flags);
cli(); if (bcs->tx_skb) {
if (st->l1.bcs->tx_skb) { skb_queue_tail(&bcs->squeue, skb);
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else { } else {
st->l1.bcs->tx_skb = skb; bcs->tx_skb = skb;
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); bcs->cs->BC_Send_Data(bcs);
restore_flags(flags); restore_flags(flags);
} }
spin_unlock_irqrestore(&bcs->cs->lock, flags);
break; break;
case (PH_PULL | INDICATION): case (PH_PULL | INDICATION):
if (st->l1.bcs->tx_skb) { spin_lock_irqsave(&bcs->cs->lock, flags);
if (bcs->tx_skb) {
printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
break; } else {
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->tx_skb = skb;
bcs->cs->BC_Send_Data(bcs);
} }
save_flags(flags); spin_unlock_irqrestore(&bcs->cs->lock, flags);
cli();
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
st->l1.bcs->tx_skb = skb;
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
restore_flags(flags);
break; break;
case (PH_PULL | REQUEST): case (PH_PULL | REQUEST):
if (!st->l1.bcs->tx_skb) { if (!bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else } else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break; break;
case (PH_ACTIVATE | REQUEST): case (PH_ACTIVATE | REQUEST):
test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); spin_lock_irqsave(&bcs->cs->lock, flags);
mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc); test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
mode_hfc(bcs, st->l1.mode, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
l1_msg_b(st, pr, arg); l1_msg_b(st, pr, arg);
break; break;
case (PH_DEACTIVATE | REQUEST): case (PH_DEACTIVATE | REQUEST):
l1_msg_b(st, pr, arg); l1_msg_b(st, pr, arg);
break; break;
case (PH_DEACTIVATE | CONFIRM): case (PH_DEACTIVATE | CONFIRM):
test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); spin_lock_irqsave(&bcs->cs->lock, flags);
test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
mode_hfc(st->l1.bcs, 0, st->l1.bc); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
mode_hfc(bcs, 0, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
break; break;
} }

View File

@ -1,6 +1,6 @@
/* $Id$ /* $Id$
* *
* level driver for CCD´s hfc-s+/sp based cards * level driver for Cologne Chip Designs hfc-s+/sp based cards
* *
* Author Werner Cornelius * Author Werner Cornelius
* based on existing driver for CCD HFC PCI cards * based on existing driver for CCD HFC PCI cards
@ -61,25 +61,18 @@ static u_char ccd_sp_irqtab[16] = {
/******************************/ /******************************/
static inline void static inline void
Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val) Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val)
{ unsigned long flags; {
save_flags(flags);
cli();
byteout(cs->hw.hfcsx.base+1, regnum); byteout(cs->hw.hfcsx.base+1, regnum);
byteout(cs->hw.hfcsx.base, val); byteout(cs->hw.hfcsx.base, val);
restore_flags(flags);
} }
static inline u_char static inline u_char
Read_hfc(struct IsdnCardState *cs, u_char regnum) Read_hfc(struct IsdnCardState *cs, u_char regnum)
{ unsigned long flags; {
u_char ret; u_char ret;
save_flags(flags);
cli();
byteout(cs->hw.hfcsx.base+1, regnum); byteout(cs->hw.hfcsx.base+1, regnum);
ret = bytein(cs->hw.hfcsx.base); ret = bytein(cs->hw.hfcsx.base);
restore_flags(flags);
return(ret); return(ret);
} }
@ -89,20 +82,16 @@ Read_hfc(struct IsdnCardState *cs, u_char regnum)
/**************************************************/ /**************************************************/
static void static void
fifo_select(struct IsdnCardState *cs, u_char fifo) fifo_select(struct IsdnCardState *cs, u_char fifo)
{ unsigned long flags; {
if (fifo == cs->hw.hfcsx.last_fifo) if (fifo == cs->hw.hfcsx.last_fifo)
return; /* still valid */ return; /* still valid */
save_flags(flags);
cli();
byteout(cs->hw.hfcsx.base+1, HFCSX_FIF_SEL); byteout(cs->hw.hfcsx.base+1, HFCSX_FIF_SEL);
byteout(cs->hw.hfcsx.base, fifo); byteout(cs->hw.hfcsx.base, fifo);
while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */ while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
udelay(4); udelay(4);
byteout(cs->hw.hfcsx.base, fifo); byteout(cs->hw.hfcsx.base, fifo);
while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */ while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
restore_flags(flags);
} }
/******************************************/ /******************************************/
@ -111,16 +100,12 @@ fifo_select(struct IsdnCardState *cs, u_char fifo)
/******************************************/ /******************************************/
static void static void
reset_fifo(struct IsdnCardState *cs, u_char fifo) reset_fifo(struct IsdnCardState *cs, u_char fifo)
{ unsigned long flags; {
save_flags(flags);
cli();
fifo_select(cs, fifo); /* first select the fifo */ fifo_select(cs, fifo); /* first select the fifo */
byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM); byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM);
byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.cirm | 0x80); /* reset cmd */ byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.cirm | 0x80); /* reset cmd */
udelay(1); udelay(1);
while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */ while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
restore_flags(flags);
} }
@ -131,7 +116,8 @@ reset_fifo(struct IsdnCardState *cs, u_char fifo)
/*************************************************************/ /*************************************************************/
static int static int
write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u_char fifo, int trans_max) write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u_char fifo, int trans_max)
{ unsigned short *msp; {
unsigned short *msp;
int fifo_size, count, z1, z2; int fifo_size, count, z1, z2;
u_char f_msk, f1, f2, *src; u_char f_msk, f1, f2, *src;
@ -325,17 +311,11 @@ read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
void void
release_io_hfcsx(struct IsdnCardState *cs) release_io_hfcsx(struct IsdnCardState *cs)
{ {
unsigned long flags;
save_flags(flags);
cli();
cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */
Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET); /* Reset On */ Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET); /* Reset On */
sti();
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
restore_flags(flags);
Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */ Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */
del_timer(&cs->hw.hfcsx.timer); del_timer(&cs->hw.hfcsx.timer);
release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */ release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */
@ -370,22 +350,15 @@ static int set_fifo_size(struct IsdnCardState *cs)
static void static void
reset_hfcsx(struct IsdnCardState *cs) reset_hfcsx(struct IsdnCardState *cs)
{ {
long flags;
save_flags(flags);
cli();
cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */
Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
printk(KERN_INFO "HFC_SX: resetting card\n"); printk(KERN_INFO "HFC_SX: resetting card\n");
while (1) { while (1) {
Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */ Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */
sti(); mdelay(30);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */ Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */
set_current_state(TASK_UNINTERRUPTIBLE); mdelay(20);
schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
if (Read_hfc(cs, HFCSX_STATUS) & 2) if (Read_hfc(cs, HFCSX_STATUS) & 2)
printk(KERN_WARNING "HFC-SX init bit busy\n"); printk(KERN_WARNING "HFC-SX init bit busy\n");
cs->hw.hfcsx.last_fifo = 0xff; /* invalidate */ cs->hw.hfcsx.last_fifo = 0xff; /* invalidate */
@ -440,7 +413,6 @@ reset_hfcsx(struct IsdnCardState *cs)
cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE; cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE;
Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
if (Read_hfc(cs, HFCSX_INT_S2)); if (Read_hfc(cs, HFCSX_INT_S2));
restore_flags(flags);
} }
/***************************************************/ /***************************************************/
@ -456,29 +428,6 @@ hfcsx_Timer(struct IsdnCardState *cs)
*/ */
} }
/*********************************/
/* schedule a new D-channel task */
/*********************************/
static void
sched_event_D_sx(struct IsdnCardState *cs, int event)
{
test_and_set_bit(event, &cs->event);
queue_task(&cs->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
/*********************************/
/* schedule a new b_channel task */
/*********************************/
static void
hfcsx_sched_event(struct BCState *bcs, int event)
{
bcs->event |= 1 << event;
queue_task(&bcs->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
/************************************************/ /************************************************/
/* select a b-channel entry matching and active */ /* select a b-channel entry matching and active */
/************************************************/ /************************************************/
@ -513,7 +462,7 @@ receive_dmsg(struct IsdnCardState *cs)
skb = read_fifo(cs, HFCSX_SEL_D_RX, 0); skb = read_fifo(cs, HFCSX_SEL_D_RX, 0);
if (skb) { if (skb) {
skb_queue_tail(&cs->rq, skb); skb_queue_tail(&cs->rq, skb);
sched_event_D_sx(cs, D_RCVBUFREADY); schedule_event(cs, D_RCVBUFREADY);
} }
} while (--count && skb); } while (--count && skb);
@ -527,38 +476,29 @@ receive_dmsg(struct IsdnCardState *cs)
void void
main_rec_hfcsx(struct BCState *bcs) main_rec_hfcsx(struct BCState *bcs)
{ {
long flags;
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
int count = 5; int count = 5;
struct sk_buff *skb; struct sk_buff *skb;
save_flags(flags);
Begin: Begin:
count--; count--;
cli();
if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
debugl1(cs, "rec_data %d blocked", bcs->channel); debugl1(cs, "rec_data %d blocked", bcs->channel);
restore_flags(flags);
return; return;
} }
sti();
skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ?
HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX, HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX,
(bcs->mode == L1_MODE_TRANS) ? (bcs->mode == L1_MODE_TRANS) ?
HFCSX_BTRANS_THRESHOLD : 0); HFCSX_BTRANS_THRESHOLD : 0);
if (skb) { if (skb) {
cli();
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
sti(); schedule_event(bcs, B_RCVBUFREADY);
hfcsx_sched_event(bcs, B_RCVBUFREADY);
} }
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
if (count && skb) if (count && skb)
goto Begin; goto Begin;
restore_flags(flags);
return; return;
} }
@ -587,16 +527,12 @@ static void
hfcsx_fill_fifo(struct BCState *bcs) hfcsx_fill_fifo(struct BCState *bcs)
{ {
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
unsigned long flags;
if (!bcs->tx_skb) if (!bcs->tx_skb)
return; return;
if (bcs->tx_skb->len <= 0) if (bcs->tx_skb->len <= 0)
return; return;
save_flags(flags);
sti();
if (write_fifo(cs, bcs->tx_skb, if (write_fifo(cs, bcs->tx_skb,
((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ?
HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX, HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX,
@ -611,10 +547,6 @@ hfcsx_fill_fifo(struct BCState *bcs)
bcs->tx_skb = NULL; bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
} }
cli();
restore_flags(flags);
return;
} }
/**********************************************/ /**********************************************/
@ -663,8 +595,7 @@ hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
if ((ic->arg == 98) && if ((ic->arg == 98) &&
(!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) { (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) {
save_flags(flags); spin_lock_irqsave(&cs->lock, flags);
cli();
Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0); /* HFC ST G0 */ Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0); /* HFC ST G0 */
udelay(10); udelay(10);
cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT; cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT;
@ -676,8 +607,8 @@ hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
cs->dc.hfcsx.ph_state = 1; cs->dc.hfcsx.ph_state = 1;
cs->hw.hfcsx.nt_mode = 1; cs->hw.hfcsx.nt_mode = 1;
cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.nt_timer = 0;
spin_unlock_irqrestore(&cs->lock, flags);
cs->stlist->l2.l2l1 = dch_nt_l2l1; cs->stlist->l2.l2l1 = dch_nt_l2l1;
restore_flags(flags);
debugl1(cs, "NT mode activated"); debugl1(cs, "NT mode activated");
return (0); return (0);
} }
@ -685,8 +616,6 @@ hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
(cs->hw.hfcsx.nt_mode) || (ic->arg != 12)) (cs->hw.hfcsx.nt_mode) || (ic->arg != 12))
return (-EINVAL); return (-EINVAL);
save_flags(flags);
cli();
if (i) { if (i) {
cs->logecho = 1; cs->logecho = 1;
cs->hw.hfcsx.trm |= 0x20; /* enable echo chan */ cs->hw.hfcsx.trm |= 0x20; /* enable echo chan */
@ -701,13 +630,14 @@ hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA; cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;
cs->hw.hfcsx.conn |= 0x10; /* B2-IOM -> B2-ST */ cs->hw.hfcsx.conn |= 0x10; /* B2-IOM -> B2-ST */
cs->hw.hfcsx.ctmt &= ~2; cs->hw.hfcsx.ctmt &= ~2;
spin_lock_irqsave(&cs->lock, flags);
Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt); Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r); Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl); Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm); Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
restore_flags(flags); spin_unlock_irqrestore(&cs->lock, flags);
return (0); return (0);
} /* hfcsx_auxcmd */ } /* hfcsx_auxcmd */
@ -717,21 +647,14 @@ hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
static void static void
receive_emsg(struct IsdnCardState *cs) receive_emsg(struct IsdnCardState *cs)
{ {
unsigned long flags;
int count = 5; int count = 5;
u_char *ptr; u_char *ptr;
struct sk_buff *skb; struct sk_buff *skb;
save_flags(flags);
cli();
if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
debugl1(cs, "echo_rec_data blocked"); debugl1(cs, "echo_rec_data blocked");
restore_flags(flags);
return; return;
} }
sti();
do { do {
skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0); skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0);
if (skb) { if (skb) {
@ -756,7 +679,6 @@ receive_emsg(struct IsdnCardState *cs)
} while (--count && skb); } while (--count && skb);
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
restore_flags(flags);
return; return;
} /* receive_emsg */ } /* receive_emsg */
@ -764,30 +686,28 @@ receive_emsg(struct IsdnCardState *cs)
/*********************/ /*********************/
/* Interrupt handler */ /* Interrupt handler */
/*********************/ /*********************/
static void static irqreturn_t
hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs) hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{ {
struct IsdnCardState *cs = dev_id; struct IsdnCardState *cs = dev_id;
u_char exval; u_char exval;
struct BCState *bcs; struct BCState *bcs;
int count = 15; int count = 15;
long flags; u_long flags;
u_char val, stat; u_char val, stat;
if (!cs) {
printk(KERN_WARNING "HFC-SX: Spurious interrupt!\n");
return;
}
if (!(cs->hw.hfcsx.int_m2 & 0x08)) if (!(cs->hw.hfcsx.int_m2 & 0x08))
return; /* not initialised */ return IRQ_NONE; /* not initialised */
spin_lock_irqsave(&cs->lock, flags);
if (HFCSX_ANYINT & (stat = Read_hfc(cs, HFCSX_STATUS))) { if (HFCSX_ANYINT & (stat = Read_hfc(cs, HFCSX_STATUS))) {
val = Read_hfc(cs, HFCSX_INT_S1); val = Read_hfc(cs, HFCSX_INT_S1);
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "HFC-SX: stat(%02x) s1(%02x)", stat, val); debugl1(cs, "HFC-SX: stat(%02x) s1(%02x)", stat, val);
} else } else {
return; spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_NONE;
}
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "HFC-SX irq %x %s", val, debugl1(cs, "HFC-SX irq %x %s", val,
test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
@ -799,24 +719,22 @@ hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state, debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state,
exval); exval);
cs->dc.hfcsx.ph_state = exval; cs->dc.hfcsx.ph_state = exval;
sched_event_D_sx(cs, D_L1STATECHANGE); schedule_event(cs, D_L1STATECHANGE);
val &= ~0x40; val &= ~0x40;
} }
if (val & 0x80) { /* timer irq */ if (val & 0x80) { /* timer irq */
if (cs->hw.hfcsx.nt_mode) { if (cs->hw.hfcsx.nt_mode) {
if ((--cs->hw.hfcsx.nt_timer) < 0) if ((--cs->hw.hfcsx.nt_timer) < 0)
sched_event_D_sx(cs, D_L1STATECHANGE); schedule_event(cs, D_L1STATECHANGE);
} }
val &= ~0x80; val &= ~0x80;
Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER); Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
} }
while (val) { while (val) {
save_flags(flags);
cli();
if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
cs->hw.hfcsx.int_s1 |= val; cs->hw.hfcsx.int_s1 |= val;
restore_flags(flags); spin_unlock_irqrestore(&cs->lock, flags);
return; return IRQ_HANDLED;
} }
if (cs->hw.hfcsx.int_s1 & 0x18) { if (cs->hw.hfcsx.int_s1 & 0x18) {
exval = val; exval = val;
@ -858,7 +776,7 @@ hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
} else } else
debugl1(cs, "fill_data %d blocked", bcs->channel); debugl1(cs, "fill_data %d blocked", bcs->channel);
} else { } else {
hfcsx_sched_event(bcs, B_XMTBUFREADY); schedule_event(bcs, B_XMTBUFREADY);
} }
} }
} }
@ -882,7 +800,7 @@ hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
} else } else
debugl1(cs, "fill_data %d blocked", bcs->channel); debugl1(cs, "fill_data %d blocked", bcs->channel);
} else { } else {
hfcsx_sched_event(bcs, B_XMTBUFREADY); schedule_event(bcs, B_XMTBUFREADY);
} }
} }
} }
@ -894,7 +812,7 @@ hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
del_timer(&cs->dbusytimer); del_timer(&cs->dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
sched_event_D_sx(cs, D_CLEARBUSY); schedule_event(cs, D_CLEARBUSY);
if (cs->tx_skb) { if (cs->tx_skb) {
if (cs->tx_skb->len) { if (cs->tx_skb->len) {
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
@ -919,7 +837,7 @@ hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
debugl1(cs, "hfcsx_fill_dfifo irq blocked"); debugl1(cs, "hfcsx_fill_dfifo irq blocked");
} }
} else } else
sched_event_D_sx(cs, D_XMTBUFREADY); schedule_event(cs, D_XMTBUFREADY);
} }
afterXPR: afterXPR:
if (cs->hw.hfcsx.int_s1 && count--) { if (cs->hw.hfcsx.int_s1 && count--) {
@ -929,8 +847,9 @@ hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
debugl1(cs, "HFC-SX irq %x loop %d", val, 15 - count); debugl1(cs, "HFC-SX irq %x loop %d", val, 15 - count);
} else } else
val = 0; val = 0;
restore_flags(flags);
} }
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_HANDLED;
} }
/********************************************************************/ /********************************************************************/
@ -949,7 +868,7 @@ HFCSX_l1hw(struct PStack *st, int pr, void *arg)
{ {
struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
struct sk_buff *skb = arg; struct sk_buff *skb = arg;
unsigned long flags; u_long flags;
switch (pr) { switch (pr) {
case (PH_DATA | REQUEST): case (PH_DATA | REQUEST):
@ -957,6 +876,7 @@ HFCSX_l1hw(struct PStack *st, int pr, void *arg)
LogFrame(cs, skb->data, skb->len); LogFrame(cs, skb->data, skb->len);
if (cs->debug & DEB_DLOG_VERBOSE) if (cs->debug & DEB_DLOG_VERBOSE)
dlogframe(cs, skb, 0); dlogframe(cs, skb, 0);
spin_lock_irqsave(&cs->lock, flags);
if (cs->tx_skb) { if (cs->tx_skb) {
skb_queue_tail(&cs->sq, skb); skb_queue_tail(&cs->sq, skb);
#ifdef L2FRAME_DEBUG /* psa */ #ifdef L2FRAME_DEBUG /* psa */
@ -977,12 +897,15 @@ HFCSX_l1hw(struct PStack *st, int pr, void *arg)
debugl1(cs, "hfcsx_fill_dfifo blocked"); debugl1(cs, "hfcsx_fill_dfifo blocked");
} }
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (PH_PULL | INDICATION): case (PH_PULL | INDICATION):
spin_lock_irqsave(&cs->lock, flags);
if (cs->tx_skb) { if (cs->tx_skb) {
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
skb_queue_tail(&cs->sq, skb); skb_queue_tail(&cs->sq, skb);
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
} }
if (cs->debug & DEB_DLOG_HEX) if (cs->debug & DEB_DLOG_HEX)
@ -1000,6 +923,7 @@ HFCSX_l1hw(struct PStack *st, int pr, void *arg)
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
} else } else
debugl1(cs, "hfcsx_fill_dfifo blocked"); debugl1(cs, "hfcsx_fill_dfifo blocked");
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (PH_PULL | REQUEST): case (PH_PULL | REQUEST):
#ifdef L2FRAME_DEBUG /* psa */ #ifdef L2FRAME_DEBUG /* psa */
@ -1013,57 +937,57 @@ HFCSX_l1hw(struct PStack *st, int pr, void *arg)
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break; break;
case (HW_RESET | REQUEST): case (HW_RESET | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3); /* HFC ST 3 */ Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3); /* HFC ST 3 */
udelay(6); udelay(6);
Write_hfc(cs, HFCSX_STATES, 3); /* HFC ST 2 */ Write_hfc(cs, HFCSX_STATES, 3); /* HFC ST 2 */
cs->hw.hfcsx.mst_m |= HFCSX_MASTER; cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION); Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
spin_unlock_irqrestore(&cs->lock, flags);
l1_msg(cs, HW_POWERUP | CONFIRM, NULL); l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
break; break;
case (HW_ENABLE | REQUEST): case (HW_ENABLE | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION); Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (HW_DEACTIVATE | REQUEST): case (HW_DEACTIVATE | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
cs->hw.hfcsx.mst_m &= ~HFCSX_MASTER; cs->hw.hfcsx.mst_m &= ~HFCSX_MASTER;
Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (HW_INFO3 | REQUEST): case (HW_INFO3 | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
cs->hw.hfcsx.mst_m |= HFCSX_MASTER; cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (HW_TESTLOOP | REQUEST): case (HW_TESTLOOP | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
switch ((int) arg) { switch ((int) arg) {
case (1): case (1):
Write_hfc(cs, HFCSX_B1_SSL, 0x80); /* tx slot */ Write_hfc(cs, HFCSX_B1_SSL, 0x80); /* tx slot */
Write_hfc(cs, HFCSX_B1_RSL, 0x80); /* rx slot */ Write_hfc(cs, HFCSX_B1_RSL, 0x80); /* rx slot */
save_flags(flags);
cli();
cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1; cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1;
Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
restore_flags(flags);
break; break;
case (2): case (2):
Write_hfc(cs, HFCSX_B2_SSL, 0x81); /* tx slot */ Write_hfc(cs, HFCSX_B2_SSL, 0x81); /* tx slot */
Write_hfc(cs, HFCSX_B2_RSL, 0x81); /* rx slot */ Write_hfc(cs, HFCSX_B2_RSL, 0x81); /* rx slot */
save_flags(flags);
cli();
cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08; cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08;
Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
restore_flags(flags);
break; break;
default: default:
spin_unlock_irqrestore(&cs->lock, flags);
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg); debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg);
return; return;
} }
save_flags(flags);
cli();
cs->hw.hfcsx.trm |= 0x80; /* enable IOM-loop */ cs->hw.hfcsx.trm |= 0x80; /* enable IOM-loop */
Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm); Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
restore_flags(flags); spin_unlock_irqrestore(&cs->lock, flags);
break; break;
default: default:
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
@ -1103,7 +1027,6 @@ void
mode_hfcsx(struct BCState *bcs, int mode, int bc) mode_hfcsx(struct BCState *bcs, int mode, int bc)
{ {
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
unsigned long flags;
int fifo2; int fifo2;
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
@ -1112,8 +1035,6 @@ mode_hfcsx(struct BCState *bcs, int mode, int bc)
bcs->mode = mode; bcs->mode = mode;
bcs->channel = bc; bcs->channel = bc;
fifo2 = bc; fifo2 = bc;
save_flags(flags);
cli();
if (cs->chanlimit > 1) { if (cs->chanlimit > 1) {
cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */ cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */
cs->hw.hfcsx.sctrl_e &= ~0x80; cs->hw.hfcsx.sctrl_e &= ~0x80;
@ -1207,7 +1128,6 @@ mode_hfcsx(struct BCState *bcs, int mode, int bc)
reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX); reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX);
reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX); reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX);
} }
restore_flags(flags);
} }
/******************************/ /******************************/
@ -1216,54 +1136,56 @@ mode_hfcsx(struct BCState *bcs, int mode, int bc)
static void static void
hfcsx_l2l1(struct PStack *st, int pr, void *arg) hfcsx_l2l1(struct PStack *st, int pr, void *arg)
{ {
struct BCState *bcs = st->l1.bcs;
struct sk_buff *skb = arg; struct sk_buff *skb = arg;
long flags; u_long flags;
switch (pr) { switch (pr) {
case (PH_DATA | REQUEST): case (PH_DATA | REQUEST):
save_flags(flags); spin_lock_irqsave(&bcs->cs->lock, flags);
cli(); if (bcs->tx_skb) {
if (st->l1.bcs->tx_skb) { skb_queue_tail(&bcs->squeue, skb);
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else { } else {
st->l1.bcs->tx_skb = skb; bcs->tx_skb = skb;
/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); // test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
*/ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); bcs->cs->BC_Send_Data(bcs);
restore_flags(flags);
} }
spin_unlock_irqrestore(&bcs->cs->lock, flags);
break; break;
case (PH_PULL | INDICATION): case (PH_PULL | INDICATION):
if (st->l1.bcs->tx_skb) { spin_lock_irqsave(&bcs->cs->lock, flags);
if (bcs->tx_skb) {
printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
break; } else {
// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->tx_skb = skb;
bcs->cs->BC_Send_Data(bcs);
} }
save_flags(flags); spin_unlock_irqrestore(&bcs->cs->lock, flags);
cli();
/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
*/ st->l1.bcs->tx_skb = skb;
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
restore_flags(flags);
break; break;
case (PH_PULL | REQUEST): case (PH_PULL | REQUEST):
if (!st->l1.bcs->tx_skb) { if (!bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else } else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break; break;
case (PH_ACTIVATE | REQUEST): case (PH_ACTIVATE | REQUEST):
test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); spin_lock_irqsave(&bcs->cs->lock, flags);
mode_hfcsx(st->l1.bcs, st->l1.mode, st->l1.bc); test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
mode_hfcsx(bcs, st->l1.mode, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
l1_msg_b(st, pr, arg); l1_msg_b(st, pr, arg);
break; break;
case (PH_DEACTIVATE | REQUEST): case (PH_DEACTIVATE | REQUEST):
l1_msg_b(st, pr, arg); l1_msg_b(st, pr, arg);
break; break;
case (PH_DEACTIVATE | CONFIRM): case (PH_DEACTIVATE | CONFIRM):
test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); spin_lock_irqsave(&bcs->cs->lock, flags);
test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
mode_hfcsx(st->l1.bcs, 0, st->l1.bc); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
mode_hfcsx(bcs, 0, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
break; break;
} }
@ -1327,9 +1249,8 @@ setstack_2b(struct PStack *st, struct BCState *bcs)
static void static void
hfcsx_bh(struct IsdnCardState *cs) hfcsx_bh(struct IsdnCardState *cs)
{ {
unsigned long flags; u_long flags;
/* struct PStack *stptr;
*/
if (!cs) if (!cs)
return; return;
if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
@ -1355,8 +1276,7 @@ hfcsx_bh(struct IsdnCardState *cs)
} else { } else {
switch (cs->dc.hfcsx.ph_state) { switch (cs->dc.hfcsx.ph_state) {
case (2): case (2):
save_flags(flags); spin_lock_irqsave(&cs->lock, flags);
cli();
if (cs->hw.hfcsx.nt_timer < 0) { if (cs->hw.hfcsx.nt_timer < 0) {
cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.nt_timer = 0;
cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
@ -1378,17 +1298,16 @@ hfcsx_bh(struct IsdnCardState *cs)
cs->hw.hfcsx.nt_timer = NT_T1_COUNT; cs->hw.hfcsx.nt_timer = NT_T1_COUNT;
Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3); /* allow G2 -> G3 transition */ Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3); /* allow G2 -> G3 transition */
} }
restore_flags(flags); spin_unlock_irqrestore(&cs->lock, flags);
break; break;
case (1): case (1):
case (3): case (3):
case (4): case (4):
save_flags(flags); spin_lock_irqsave(&cs->lock, flags);
cli();
cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.nt_timer = 0;
cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
restore_flags(flags); spin_unlock_irqrestore(&cs->lock, flags);
break; break;
default: default:
break; break;
@ -1409,10 +1328,6 @@ void __devinit
inithfcsx(struct IsdnCardState *cs) inithfcsx(struct IsdnCardState *cs)
{ {
cs->setstack_d = setstack_hfcsx; cs->setstack_d = setstack_hfcsx;
cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
cs->dbusytimer.data = (long) cs;
init_timer(&cs->dbusytimer);
cs->tqueue.routine = (void *) (void *) hfcsx_bh;
cs->BC_Send_Data = &hfcsx_send_data; cs->BC_Send_Data = &hfcsx_send_data;
cs->bcs[0].BC_SetStack = setstack_2b; cs->bcs[0].BC_SetStack = setstack_2b;
cs->bcs[1].BC_SetStack = setstack_2b; cs->bcs[1].BC_SetStack = setstack_2b;
@ -1430,29 +1345,32 @@ inithfcsx(struct IsdnCardState *cs)
static int static int
hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg) hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{ {
long flags; u_long flags;
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "HFCSX: card_msg %x", mt); debugl1(cs, "HFCSX: card_msg %x", mt);
switch (mt) { switch (mt) {
case CARD_RESET: case CARD_RESET:
spin_lock_irqsave(&cs->lock, flags);
reset_hfcsx(cs); reset_hfcsx(cs);
spin_unlock_irqrestore(&cs->lock, flags);
return (0); return (0);
case CARD_RELEASE: case CARD_RELEASE:
release_io_hfcsx(cs); release_io_hfcsx(cs);
return (0); return (0);
case CARD_INIT: case CARD_INIT:
spin_lock_irqsave(&cs->lock, flags);
inithfcsx(cs); inithfcsx(cs);
save_flags(flags); spin_unlock_irqrestore(&cs->lock, flags);
sti();
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */
/* now switch timer interrupt off */ /* now switch timer interrupt off */
spin_lock_irqsave(&cs->lock, flags);
cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
/* reinit mode reg */ /* reinit mode reg */
Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
restore_flags(flags); spin_unlock_irqrestore(&cs->lock, flags);
return (0); return (0);
case CARD_TEST: case CARD_TEST:
return (0); return (0);
@ -1468,8 +1386,8 @@ static struct isapnp_device_id hfc_ids[] __initdata = {
{ 0, } { 0, }
}; };
static struct isapnp_device_id *hdev = &hfc_ids[0]; static struct isapnp_device_id *ipid __initdata = &hfc_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL; static struct pnp_card *pnp_c __devinitdata = NULL;
#endif #endif
int __devinit int __devinit
@ -1477,33 +1395,35 @@ setup_hfcsx(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs; struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
unsigned long flags;
strcpy(tmp, hfcsx_revision); strcpy(tmp, hfcsx_revision);
printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
#ifdef __ISAPNP__ #ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) { if (!card->para[1] && isapnp_present()) {
struct pci_bus *pb; struct pnp_dev *pnp_d;
struct pci_dev *pd; while(ipid->card_vendor) {
if ((pnp_c = pnp_find_card(ipid->card_vendor,
ipid->card_device, pnp_c))) {
pnp_d = NULL;
if ((pnp_d = pnp_find_dev(pnp_c,
ipid->vendor, ipid->function, pnp_d))) {
int err;
while(hdev->card_vendor) {
if ((pb = isapnp_find_card(hdev->card_vendor,
hdev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
hdev->vendor, hdev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n", printk(KERN_INFO "HiSax: %s detected\n",
(char *)hdev->driver_data); (char *)ipid->driver_data);
pd->prepare(pd); pnp_disable_dev(pnp_d);
pd->deactivate(pd); err = pnp_activate_dev(pnp_d);
pd->activate(pd); if (err<0) {
card->para[1] = pd->resource[0].start; printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
card->para[0] = pd->irq_resource[0].start; __FUNCTION__, err);
return(0);
}
card->para[1] = pnp_port_start(pnp_d, 0);
card->para[0] = pnp_irq(pnp_d, 0);
if (!card->para[0] || !card->para[1]) { if (!card->para[0] || !card->para[1]) {
printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n", printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
card->para[0], card->para[1]); card->para[0], card->para[1]);
pd->deactivate(pd); pnp_disable_dev(pnp_d);
return(0); return(0);
} }
break; break;
@ -1511,10 +1431,10 @@ setup_hfcsx(struct IsdnCard *card)
printk(KERN_ERR "HFC PnP: PnP error card found, no device\n"); printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
} }
} }
hdev++; ipid++;
pnp_c=NULL; pnp_c = NULL;
} }
if (!hdev->card_vendor) { if (!ipid->card_vendor) {
printk(KERN_INFO "HFC PnP: no ISAPnP card found\n"); printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
return(0); return(0);
} }
@ -1527,14 +1447,11 @@ setup_hfcsx(struct IsdnCard *card)
cs->hw.hfcsx.fifo = 255; cs->hw.hfcsx.fifo = 255;
if ((cs->typ == ISDN_CTYPE_HFC_SX) || if ((cs->typ == ISDN_CTYPE_HFC_SX) ||
(cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) { (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) {
if ((!cs->hw.hfcsx.base) || if ((!cs->hw.hfcsx.base) || !request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn")) {
check_region((cs->hw.hfcsx.base), 2)) {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: HFC-SX io-base %#lx already in use\n", "HiSax: HFC-SX io-base %#lx already in use\n",
cs->hw.hfcsx.base); cs->hw.hfcsx.base);
return(0); return(0);
} else {
request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn");
} }
byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
byteout(cs->hw.hfcsx.base + 1, byteout(cs->hw.hfcsx.base + 1,
@ -1561,21 +1478,14 @@ setup_hfcsx(struct IsdnCard *card)
release_region(cs->hw.hfcsx.base, 2); release_region(cs->hw.hfcsx.base, 2);
return(0); return(0);
} }
save_flags(flags);
cli();
if (!(cs->hw.hfcsx.extra = (void *) if (!(cs->hw.hfcsx.extra = (void *)
kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) { kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {
restore_flags(flags);
release_region(cs->hw.hfcsx.base, 2); release_region(cs->hw.hfcsx.base, 2);
printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
return(0); return(0);
} }
restore_flags(flags); printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
tmp[0], (u_int) cs->hw.hfcsx.base, cs->irq, HZ);
printk(KERN_INFO
"HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
tmp[0], (u_int) cs->hw.hfcsx.base,
cs->irq, HZ);
cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */
cs->hw.hfcsx.int_m1 = 0; cs->hw.hfcsx.int_m1 = 0;
Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
@ -1583,6 +1493,10 @@ setup_hfcsx(struct IsdnCard *card)
} else } else
return (0); /* no valid card type */ return (0); /* no valid card type */
cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
cs->dbusytimer.data = (long) cs;
init_timer(&cs->dbusytimer);
INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs);
cs->readisac = NULL; cs->readisac = NULL;
cs->writeisac = NULL; cs->writeisac = NULL;
cs->readisacfifo = NULL; cs->readisacfifo = NULL;

View File

@ -20,16 +20,14 @@ extern const char *CardType[];
static const char *hfcs_revision = "$Revision$"; static const char *hfcs_revision = "$Revision$";
static void static irqreturn_t
hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs) hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{ {
struct IsdnCardState *cs = dev_id; struct IsdnCardState *cs = dev_id;
u_char val, stat; u_char val, stat;
u_long flags;
if (!cs) { spin_lock_irqsave(&cs->lock, flags);
printk(KERN_WARNING "HFCS: Spurious interrupt!\n");
return;
}
if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) &
(stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) { (stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1); val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
@ -40,6 +38,8 @@ hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat); debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat);
} }
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_HANDLED;
} }
static void static void
@ -102,29 +102,36 @@ reset_hfcs(struct IsdnCardState *cs)
static int static int
hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{ {
long flags; u_long flags;
int delay;
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "HFCS: card_msg %x", mt); debugl1(cs, "HFCS: card_msg %x", mt);
switch (mt) { switch (mt) {
case CARD_RESET: case CARD_RESET:
spin_lock_irqsave(&cs->lock, flags);
reset_hfcs(cs); reset_hfcs(cs);
spin_unlock_irqrestore(&cs->lock, flags);
return(0); return(0);
case CARD_RELEASE: case CARD_RELEASE:
release_io_hfcs(cs); release_io_hfcs(cs);
return(0); return(0);
case CARD_INIT: case CARD_INIT:
cs->hw.hfcD.timer.expires = jiffies + 75; delay = (75*HZ)/100 +1;
cs->hw.hfcD.timer.expires = jiffies + delay;
add_timer(&cs->hw.hfcD.timer); add_timer(&cs->hw.hfcD.timer);
spin_lock_irqsave(&cs->lock, flags);
reset_hfcs(cs);
init2bds0(cs); init2bds0(cs);
save_flags(flags); spin_unlock_irqrestore(&cs->lock, flags);
sti(); delay = (80*HZ)/1000 +1;
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((80*HZ)/1000); schedule_timeout((80*HZ)/1000);
spin_lock_irqsave(&cs->lock, flags);
cs->hw.hfcD.ctmt |= HFCD_TIM800; cs->hw.hfcD.ctmt |= HFCD_TIM800;
cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
restore_flags(flags); spin_unlock_irqrestore(&cs->lock, flags);
return(0); return(0);
case CARD_TEST: case CARD_TEST:
return(0); return(0);
@ -158,8 +165,8 @@ static struct isapnp_device_id hfc_ids[] __initdata = {
{ 0, } { 0, }
}; };
static struct isapnp_device_id *hdev = &hfc_ids[0]; static struct isapnp_device_id *ipid __initdata = &hfc_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL; static struct pnp_card *pnp_c __devinitdata = NULL;
#endif #endif
int __init int __init
@ -173,27 +180,30 @@ setup_hfcs(struct IsdnCard *card)
#ifdef __ISAPNP__ #ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) { if (!card->para[1] && isapnp_present()) {
struct pci_bus *pb; struct pnp_dev *pnp_d;
struct pci_dev *pd; while(ipid->card_vendor) {
if ((pnp_c = pnp_find_card(ipid->card_vendor,
ipid->card_device, pnp_c))) {
pnp_d = NULL;
if ((pnp_d = pnp_find_dev(pnp_c,
ipid->vendor, ipid->function, pnp_d))) {
int err;
while(hdev->card_vendor) {
if ((pb = isapnp_find_card(hdev->card_vendor,
hdev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
hdev->vendor, hdev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n", printk(KERN_INFO "HiSax: %s detected\n",
(char *)hdev->driver_data); (char *)ipid->driver_data);
pd->prepare(pd); pnp_disable_dev(pnp_d);
pd->deactivate(pd); err = pnp_activate_dev(pnp_d);
pd->activate(pd); if (err<0) {
card->para[1] = pd->resource[0].start; printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
card->para[0] = pd->irq_resource[0].start; __FUNCTION__, err);
return(0);
}
card->para[1] = pnp_port_start(pnp_d, 0);
card->para[0] = pnp_irq(pnp_d, 0);
if (!card->para[0] || !card->para[1]) { if (!card->para[0] || !card->para[1]) {
printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n", printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
card->para[0], card->para[1]); card->para[0], card->para[1]);
pd->deactivate(pd); pnp_disable_dev(pnp_d);
return(0); return(0);
} }
break; break;
@ -201,10 +211,10 @@ setup_hfcs(struct IsdnCard *card)
printk(KERN_ERR "HFC PnP: PnP error card found, no device\n"); printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
} }
} }
hdev++; ipid++;
pnp_c=NULL; pnp_c = NULL;
} }
if (!hdev->card_vendor) { if (!ipid->card_vendor) {
printk(KERN_INFO "HFC PnP: no ISAPnP card found\n"); printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
return(0); return(0);
} }
@ -226,15 +236,13 @@ setup_hfcs(struct IsdnCard *card)
cs->hw.hfcD.bfifosize = 7*1024 + 512; cs->hw.hfcD.bfifosize = 7*1024 + 512;
} else } else
return (0); return (0);
if (check_region((cs->hw.hfcD.addr), 2)) { if (!request_region(cs->hw.hfcD.addr, 2, "HFCS isdn")) {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n", "HiSax: %s config port %x-%x already in use\n",
CardType[card->typ], CardType[card->typ],
cs->hw.hfcD.addr, cs->hw.hfcD.addr,
cs->hw.hfcD.addr + 2); cs->hw.hfcD.addr + 2);
return (0); return (0);
} else {
request_region(cs->hw.hfcD.addr, 2, "HFCS isdn");
} }
printk(KERN_INFO printk(KERN_INFO
"HFCS: defined at 0x%x IRQ %d HZ %d\n", "HFCS: defined at 0x%x IRQ %d HZ %d\n",
@ -253,7 +261,6 @@ setup_hfcs(struct IsdnCard *card)
cs->hw.hfcD.timer.function = (void *) hfcs_Timer; cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
cs->hw.hfcD.timer.data = (long) cs; cs->hw.hfcD.timer.data = (long) cs;
init_timer(&cs->hw.hfcD.timer); init_timer(&cs->hw.hfcD.timer);
reset_hfcs(cs);
cs->cardmsg = &hfcs_card_msg; cs->cardmsg = &hfcs_card_msg;
cs->irq_func = &hfcs_interrupt; cs->irq_func = &hfcs_interrupt;
return (1); return (1);

View File

@ -50,22 +50,33 @@ MODULE_PARM(debug, "i");
MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>"); MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver"); MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
static struct pci_device_id fcpci_ids[] __devinitdata = { static struct pci_device_id fcpci_ids[] = {
{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1 , PCI_ANY_ID, PCI_ANY_ID, { .vendor = PCI_VENDOR_ID_AVM,
0, 0, (unsigned long) "Fritz!Card PCI" }, .device = PCI_DEVICE_ID_AVM_A1,
{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID, .subvendor = PCI_ANY_ID,
0, 0, (unsigned long) "Fritz!Card PCI v2" }, .subdevice = PCI_ANY_ID,
{ } .driver_data = (unsigned long) "Fritz!Card PCI",
},
{ .vendor = PCI_VENDOR_ID_AVM,
.device = PCI_DEVICE_ID_AVM_A1_V2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long) "Fritz!Card PCI v2" },
{}
}; };
MODULE_DEVICE_TABLE(pci, fcpci_ids); MODULE_DEVICE_TABLE(pci, fcpci_ids);
static struct isapnp_device_id fcpnp_ids[] __devinitdata = { #ifdef __ISAPNP__
{ ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), static struct pnp_device_id fcpnp_ids[] __devinitdata = {
ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), {
(unsigned long) "Fritz!Card PnP" }, .id = "AVM0900",
{ } .driver_data = (unsigned long) "Fritz!Card PnP",
},
}; };
MODULE_DEVICE_TABLE(isapnp, fcpnp_ids); MODULE_DEVICE_TABLE(isapnp, fcpnp_ids);
#endif
static int protocol = 2; /* EURO-ISDN Default */ static int protocol = 2; /* EURO-ISDN Default */
MODULE_PARM(protocol, "i"); MODULE_PARM(protocol, "i");
@ -634,7 +645,8 @@ static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
static void fcpci2_irq(int intno, void *dev, struct pt_regs *regs) static irqreturn_t
fcpci2_irq(int intno, void *dev, struct pt_regs *regs)
{ {
struct fritz_adapter *adapter = dev; struct fritz_adapter *adapter = dev;
unsigned char val; unsigned char val;
@ -642,16 +654,18 @@ static void fcpci2_irq(int intno, void *dev, struct pt_regs *regs)
val = inb(adapter->io + AVM_STATUS0); val = inb(adapter->io + AVM_STATUS0);
if (!(val & AVM_STATUS0_IRQ_MASK)) if (!(val & AVM_STATUS0_IRQ_MASK))
/* hopefully a shared IRQ reqest */ /* hopefully a shared IRQ reqest */
return; return IRQ_NONE;
DBG(2, "STATUS0 %#x", val); DBG(2, "STATUS0 %#x", val);
if (val & AVM_STATUS0_IRQ_ISAC) if (val & AVM_STATUS0_IRQ_ISAC)
isacsx_irq(&adapter->isac); isacsx_irq(&adapter->isac);
if (val & AVM_STATUS0_IRQ_HDLC) if (val & AVM_STATUS0_IRQ_HDLC)
hdlc_irq(adapter); hdlc_irq(adapter);
return IRQ_HANDLED;
} }
static void fcpci_irq(int intno, void *dev, struct pt_regs *regs) static irqreturn_t
fcpci_irq(int intno, void *dev, struct pt_regs *regs)
{ {
struct fritz_adapter *adapter = dev; struct fritz_adapter *adapter = dev;
unsigned char sval; unsigned char sval;
@ -659,13 +673,14 @@ static void fcpci_irq(int intno, void *dev, struct pt_regs *regs)
sval = inb(adapter->io + 2); sval = inb(adapter->io + 2);
if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
/* possibly a shared IRQ reqest */ /* possibly a shared IRQ reqest */
return; return IRQ_NONE;
DBG(2, "sval %#x", sval); DBG(2, "sval %#x", sval);
if (!(sval & AVM_STATUS0_IRQ_ISAC)) if (!(sval & AVM_STATUS0_IRQ_ISAC))
isac_irq(&adapter->isac); isac_irq(&adapter->isac);
if (!(sval & AVM_STATUS0_IRQ_HDLC)) if (!(sval & AVM_STATUS0_IRQ_HDLC))
hdlc_irq(adapter); hdlc_irq(adapter);
return IRQ_HANDLED;
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -814,7 +829,7 @@ static void __devexit fcpcipnp_release(struct fritz_adapter *adapter)
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
static struct fritz_adapter * __devinit static struct fritz_adapter * __devinit
new_adapter(struct pci_dev *pdev) new_adapter(void)
{ {
struct fritz_adapter *adapter; struct fritz_adapter *adapter;
struct hisax_b_if *b_if[2]; struct hisax_b_if *b_if[2];
@ -837,8 +852,6 @@ new_adapter(struct pci_dev *pdev)
adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1; adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;
} }
pci_set_drvdata(pdev, adapter);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
b_if[i] = &adapter->bcs[i].b_if; b_if[i] = &adapter->bcs[i].b_if;
@ -860,10 +873,12 @@ static int __devinit fcpci_probe(struct pci_dev *pdev,
int retval; int retval;
retval = -ENOMEM; retval = -ENOMEM;
adapter = new_adapter(pdev); adapter = new_adapter();
if (!adapter) if (!adapter)
goto err; goto err;
pci_set_drvdata(pdev, adapter);
if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2) if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)
adapter->type = AVM_FRITZ_PCIV2; adapter->type = AVM_FRITZ_PCIV2;
else else
@ -891,27 +906,36 @@ static int __devinit fcpci_probe(struct pci_dev *pdev,
return retval; return retval;
} }
static int __devinit fcpnp_probe(struct pci_dev *pdev, #ifdef __ISAPNP__
const struct isapnp_device_id *ent) static int __devinit fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
{ {
struct fritz_adapter *adapter; struct fritz_adapter *adapter;
int retval; int retval;
if (!pdev)
return(-ENODEV);
retval = -ENOMEM; retval = -ENOMEM;
adapter = new_adapter(pdev); adapter = new_adapter();
if (!adapter) if (!adapter)
goto err; goto err;
pnp_set_drvdata(pdev, adapter);
adapter->type = AVM_FRITZ_PNP; adapter->type = AVM_FRITZ_PNP;
pdev->prepare(pdev); pnp_disable_dev(pdev);
pdev->deactivate(pdev); // why? retval = pnp_activate_dev(pdev);
pdev->activate(pdev); if (retval < 0) {
adapter->io = pdev->resource[0].start; printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__,
adapter->irq = pdev->irq_resource[0].start; (char *)dev_id->driver_data, retval);
goto err_free;
}
adapter->io = pnp_port_start(pdev, 0);
adapter->irq = pnp_irq(pdev, 0);
printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n", printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
(char *) ent->driver_data, adapter->io, adapter->irq); (char *) dev_id->driver_data, adapter->io, adapter->irq);
retval = fcpcipnp_setup(adapter); retval = fcpcipnp_setup(adapter);
if (retval) if (retval)
@ -925,6 +949,25 @@ static int __devinit fcpnp_probe(struct pci_dev *pdev,
return retval; return retval;
} }
static void __devexit fcpnp_remove(struct pnp_dev *pdev)
{
struct fritz_adapter *adapter = pnp_get_drvdata(pdev);
if (adapter) {
fcpcipnp_release(adapter);
delete_adapter(adapter);
}
pnp_disable_dev(pdev);
}
static struct pnp_driver fcpnp_driver = {
name: "fcpnp",
probe: fcpnp_probe,
remove: __devexit_p(fcpnp_remove),
id_table: fcpnp_ids,
};
#endif
static void __devexit fcpci_remove(struct pci_dev *pdev) static void __devexit fcpci_remove(struct pci_dev *pdev)
{ {
struct fritz_adapter *adapter = pci_get_drvdata(pdev); struct fritz_adapter *adapter = pci_get_drvdata(pdev);
@ -934,15 +977,6 @@ static void __devexit fcpci_remove(struct pci_dev *pdev)
delete_adapter(adapter); delete_adapter(adapter);
} }
static void __devexit fcpnp_remove(struct pci_dev *pdev)
{
struct fritz_adapter *adapter = pci_get_drvdata(pdev);
fcpcipnp_release(adapter);
pdev->deactivate(pdev);
delete_adapter(adapter);
}
static struct pci_driver fcpci_driver = { static struct pci_driver fcpci_driver = {
name: "fcpci", name: "fcpci",
probe: fcpci_probe, probe: fcpci_probe,
@ -950,13 +984,6 @@ static struct pci_driver fcpci_driver = {
id_table: fcpci_ids, id_table: fcpci_ids,
}; };
static struct isapnp_driver fcpnp_driver = {
name: "fcpnp",
probe: fcpnp_probe,
remove: __devexit_p(fcpnp_remove),
id_table: fcpnp_ids,
};
static int __init hisax_fcpcipnp_init(void) static int __init hisax_fcpcipnp_init(void)
{ {
int retval, pci_nr_found; int retval, pci_nr_found;
@ -967,10 +994,13 @@ static int __init hisax_fcpcipnp_init(void)
if (retval < 0) if (retval < 0)
goto out; goto out;
pci_nr_found = retval; pci_nr_found = retval;
retval = 0;
retval = isapnp_register_driver(&fcpnp_driver); #ifdef __ISAPNP__
retval = pnp_register_driver(&fcpnp_driver);
if (retval < 0) if (retval < 0)
goto out_unregister_pci; goto out_unregister_pci;
#endif
#if !defined(CONFIG_HOTPLUG) || defined(MODULE) #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
if (pci_nr_found + retval == 0) { if (pci_nr_found + retval == 0) {
@ -982,7 +1012,9 @@ static int __init hisax_fcpcipnp_init(void)
#if !defined(CONFIG_HOTPLUG) || defined(MODULE) #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
out_unregister_isapnp: out_unregister_isapnp:
isapnp_unregister_driver(&fcpnp_driver); #ifdef __ISAPNP__
pnp_unregister_driver(&fcpnp_driver);
#endif
#endif #endif
out_unregister_pci: out_unregister_pci:
pci_unregister_driver(&fcpci_driver); pci_unregister_driver(&fcpci_driver);
@ -992,7 +1024,9 @@ static int __init hisax_fcpcipnp_init(void)
static void __exit hisax_fcpcipnp_exit(void) static void __exit hisax_fcpcipnp_exit(void)
{ {
isapnp_unregister_driver(&fcpnp_driver); #ifdef __ISAPNP__
pnp_unregister_driver(&fcpnp_driver);
#endif
pci_unregister_driver(&fcpci_driver); pci_unregister_driver(&fcpci_driver);
} }

View File

@ -50,10 +50,8 @@ static void
jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value) jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value)
{ {
int to = 50; int to = 50;
long flags;
u_char ret; u_char ret;
save_flags(flags);
cli();
/* Write the data */ /* Write the data */
cs->BC_Write_Reg(cs, -1, COMM_JADE+1, value); cs->BC_Write_Reg(cs, -1, COMM_JADE+1, value);
/* Say JADE we wanna write indirect reg 'reg' */ /* Say JADE we wanna write indirect reg 'reg' */
@ -68,12 +66,10 @@ jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value)
/* Got acknowledge */ /* Got acknowledge */
break; break;
if (!to) { if (!to) {
restore_flags(flags);
printk(KERN_INFO "Can not see ready bit from JADE DSP (reg=0x%X, value=0x%X)\n", reg, value); printk(KERN_INFO "Can not see ready bit from JADE DSP (reg=0x%X, value=0x%X)\n", reg, value);
return; return;
} }
} }
restore_flags(flags);
} }
@ -134,64 +130,61 @@ modejade(struct BCState *bcs, int mode, int bc)
cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00); cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00);
} }
void
jade_sched_event(struct BCState *bcs, int event)
{
bcs->event |= 1 << event;
queue_task(&bcs->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
static void static void
jade_l2l1(struct PStack *st, int pr, void *arg) jade_l2l1(struct PStack *st, int pr, void *arg)
{ {
struct BCState *bcs = st->l1.bcs;
struct sk_buff *skb = arg; struct sk_buff *skb = arg;
long flags; u_long flags;
switch (pr) { switch (pr) {
case (PH_DATA | REQUEST): case (PH_DATA | REQUEST):
save_flags(flags); spin_lock_irqsave(&bcs->cs->lock, flags);
cli(); if (bcs->tx_skb) {
if (st->l1.bcs->tx_skb) { skb_queue_tail(&bcs->squeue, skb);
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else { } else {
st->l1.bcs->tx_skb = skb; bcs->tx_skb = skb;
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
st->l1.bcs->hw.hscx.count = 0; bcs->hw.hscx.count = 0;
restore_flags(flags); bcs->cs->BC_Send_Data(bcs);
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
} }
spin_unlock_irqrestore(&bcs->cs->lock, flags);
break; break;
case (PH_PULL | INDICATION): case (PH_PULL | INDICATION):
if (st->l1.bcs->tx_skb) { spin_lock_irqsave(&bcs->cs->lock, flags);
if (bcs->tx_skb) {
printk(KERN_WARNING "jade_l2l1: this shouldn't happen\n"); printk(KERN_WARNING "jade_l2l1: this shouldn't happen\n");
break; } else {
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->tx_skb = skb;
bcs->hw.hscx.count = 0;
bcs->cs->BC_Send_Data(bcs);
} }
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); spin_unlock_irqrestore(&bcs->cs->lock, flags);
st->l1.bcs->tx_skb = skb;
st->l1.bcs->hw.hscx.count = 0;
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
break; break;
case (PH_PULL | REQUEST): case (PH_PULL | REQUEST):
if (!st->l1.bcs->tx_skb) { if (!bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else } else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break; break;
case (PH_ACTIVATE | REQUEST): case (PH_ACTIVATE | REQUEST):
test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); spin_lock_irqsave(&bcs->cs->lock, flags);
modejade(st->l1.bcs, st->l1.mode, st->l1.bc); test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
modejade(bcs, st->l1.mode, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
l1_msg_b(st, pr, arg); l1_msg_b(st, pr, arg);
break; break;
case (PH_DEACTIVATE | REQUEST): case (PH_DEACTIVATE | REQUEST):
l1_msg_b(st, pr, arg); l1_msg_b(st, pr, arg);
break; break;
case (PH_DEACTIVATE | CONFIRM): case (PH_DEACTIVATE | CONFIRM):
test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); spin_lock_irqsave(&bcs->cs->lock, flags);
test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
modejade(st->l1.bcs, 0, st->l1.bc); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
modejade(bcs, 0, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
break; break;
} }

View File

@ -128,7 +128,6 @@
#define jade_TXAUDIOCH2CFG 0x1A #define jade_TXAUDIOCH2CFG 0x1A
extern int JadeVersion(struct IsdnCardState *cs, char *s); extern int JadeVersion(struct IsdnCardState *cs, char *s);
extern void jade_sched_event(struct BCState *bcs, int event);
extern void modejade(struct BCState *bcs, int mode, int bc); extern void modejade(struct BCState *bcs, int mode, int bc);
extern void clear_pending_jade_ints(struct IsdnCardState *cs); extern void clear_pending_jade_ints(struct IsdnCardState *cs);
extern void initjade(struct IsdnCardState *cs); extern void initjade(struct IsdnCardState *cs);

View File

@ -33,13 +33,8 @@ waitforXFW(struct IsdnCardState *cs, int jade)
static inline void static inline void
WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data) WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data)
{ {
long flags;
save_flags(flags);
cli();
waitforCEC(cs, jade, reg); waitforCEC(cs, jade, reg);
WRITEJADE(cs, jade, reg, data); WRITEJADE(cs, jade, reg, data);
restore_flags(flags);
} }
@ -49,7 +44,6 @@ jade_empty_fifo(struct BCState *bcs, int count)
{ {
u_char *ptr; u_char *ptr;
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
long flags;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "jade_empty_fifo"); debugl1(cs, "jade_empty_fifo");
@ -63,11 +57,8 @@ jade_empty_fifo(struct BCState *bcs, int count)
} }
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
bcs->hw.hscx.rcvidx += count; bcs->hw.hscx.rcvidx += count;
save_flags(flags);
cli();
READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
restore_flags(flags);
if (cs->debug & L1_DEB_HSCX_FIFO) { if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog; char *t = bcs->blog;
@ -85,7 +76,6 @@ jade_fill_fifo(struct BCState *bcs)
int more, count; int more, count;
int fifo_size = 32; int fifo_size = 32;
u_char *ptr; u_char *ptr;
long flags;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "jade_fill_fifo"); debugl1(cs, "jade_fill_fifo");
@ -103,15 +93,12 @@ jade_fill_fifo(struct BCState *bcs)
count = bcs->tx_skb->len; count = bcs->tx_skb->len;
waitforXFW(cs, bcs->hw.hscx.hscx); waitforXFW(cs, bcs->hw.hscx.hscx);
save_flags(flags);
cli();
ptr = bcs->tx_skb->data; ptr = bcs->tx_skb->data;
skb_pull(bcs->tx_skb, count); skb_pull(bcs->tx_skb, count);
bcs->tx_cnt -= count; bcs->tx_cnt -= count;
bcs->hw.hscx.count += count; bcs->hw.hscx.count += count;
WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME)); WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
restore_flags(flags);
if (cs->debug & L1_DEB_HSCX_FIFO) { if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog; char *t = bcs->blog;
@ -166,7 +153,7 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
} }
} }
bcs->hw.hscx.rcvidx = 0; bcs->hw.hscx.rcvidx = 0;
jade_sched_event(bcs, B_RCVBUFREADY); schedule_event(bcs, B_RCVBUFREADY);
} }
if (val & 0x40) { /* RPF */ if (val & 0x40) { /* RPF */
jade_empty_fifo(bcs, fifo_size); jade_empty_fifo(bcs, fifo_size);
@ -179,7 +166,7 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
} }
bcs->hw.hscx.rcvidx = 0; bcs->hw.hscx.rcvidx = 0;
jade_sched_event(bcs, B_RCVBUFREADY); schedule_event(bcs, B_RCVBUFREADY);
} }
} }
if (val & 0x10) { /* XPR */ if (val & 0x10) { /* XPR */
@ -202,7 +189,7 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
jade_fill_fifo(bcs); jade_fill_fifo(bcs);
} else { } else {
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
jade_sched_event(bcs, B_XMTBUFREADY); schedule_event(bcs, B_XMTBUFREADY);
} }
} }
} }

View File

@ -796,6 +796,7 @@ ready:
"Sedlbauer: wrong ISAR version (ret = %d)\n", ver); "Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
else else
break; break;
reset_sedlbauer(cs);
bytecnt--; bytecnt--;
} }
if (!bytecnt) { if (!bytecnt) {

View File

@ -28,21 +28,16 @@ readreg(unsigned int ale, unsigned int adr, u_char off)
{ {
register u_char ret; register u_char ret;
int max_delay = 2000; int max_delay = 2000;
long flags;
save_flags(flags);
cli();
byteout(ale, off); byteout(ale, off);
ret = HFC_BUSY & bytein(ale); ret = HFC_BUSY & bytein(ale);
while (ret && --max_delay) while (ret && --max_delay)
ret = HFC_BUSY & bytein(ale); ret = HFC_BUSY & bytein(ale);
if (!max_delay) { if (!max_delay) {
printk(KERN_WARNING "TeleInt Busy not inactive\n"); printk(KERN_WARNING "TeleInt Busy not inactive\n");
restore_flags(flags);
return (0); return (0);
} }
ret = bytein(adr); ret = bytein(adr);
restore_flags(flags);
return (ret); return (ret);
} }
@ -72,21 +67,16 @@ writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
{ {
register u_char ret; register u_char ret;
int max_delay = 2000; int max_delay = 2000;
long flags;
save_flags(flags);
cli();
byteout(ale, off); byteout(ale, off);
ret = HFC_BUSY & bytein(ale); ret = HFC_BUSY & bytein(ale);
while (ret && --max_delay) while (ret && --max_delay)
ret = HFC_BUSY & bytein(ale); ret = HFC_BUSY & bytein(ale);
if (!max_delay) { if (!max_delay) {
printk(KERN_WARNING "TeleInt Busy not inactive\n"); printk(KERN_WARNING "TeleInt Busy not inactive\n");
restore_flags(flags);
return; return;
} }
byteout(adr, data); byteout(adr, data);
restore_flags(flags);
} }
static inline void static inline void
@ -167,16 +157,14 @@ WriteHFC(struct IsdnCardState *cs, int data, u_char reg, u_char value)
debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value); debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
} }
static void static irqreturn_t
TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs) TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{ {
struct IsdnCardState *cs = dev_id; struct IsdnCardState *cs = dev_id;
u_char val; u_char val;
u_long flags;
if (!cs) { spin_lock_irqsave(&cs->lock, flags);
printk(KERN_WARNING "TeleInt: Spurious interrupt!\n");
return;
}
val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA); val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
Start_ISAC: Start_ISAC:
if (val) if (val)
@ -189,13 +177,17 @@ TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs)
} }
writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF); writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0); writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_HANDLED;
} }
static void static void
TeleInt_Timer(struct IsdnCardState *cs) TeleInt_Timer(struct IsdnCardState *cs)
{ {
int stat = 0; int stat = 0;
u_long flags;
spin_lock_irqsave(&cs->lock, flags);
if (cs->bcs[0].mode) { if (cs->bcs[0].mode) {
stat |= 1; stat |= 1;
main_irq_hfc(&cs->bcs[0]); main_irq_hfc(&cs->bcs[0]);
@ -204,7 +196,11 @@ TeleInt_Timer(struct IsdnCardState *cs)
stat |= 2; stat |= 2;
main_irq_hfc(&cs->bcs[1]); main_irq_hfc(&cs->bcs[1]);
} }
cs->hw.hfc.timer.expires = jiffies + 1; spin_unlock_irqrestore(&cs->lock, flags);
stat = HZ/100;
if (!stat)
stat = 1;
cs->hw.hfc.timer.expires = jiffies + stat;
add_timer(&cs->hw.hfc.timer); add_timer(&cs->hw.hfc.timer);
} }
@ -232,21 +228,32 @@ reset_TeleInt(struct IsdnCardState *cs)
static int static int
TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg) TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{ {
u_long flags;
int delay;
switch (mt) { switch (mt) {
case CARD_RESET: case CARD_RESET:
spin_lock_irqsave(&cs->lock, flags);
reset_TeleInt(cs); reset_TeleInt(cs);
spin_unlock_irqrestore(&cs->lock, flags);
return(0); return(0);
case CARD_RELEASE: case CARD_RELEASE:
release_io_TeleInt(cs); release_io_TeleInt(cs);
return(0); return(0);
case CARD_INIT: case CARD_INIT:
spin_lock_irqsave(&cs->lock, flags);
reset_TeleInt(cs);
inithfc(cs); inithfc(cs);
clear_pending_isac_ints(cs); clear_pending_isac_ints(cs);
initisac(cs); initisac(cs);
/* Reenable all IRQ */ /* Reenable all IRQ */
cs->writeisac(cs, ISAC_MASK, 0); cs->writeisac(cs, ISAC_MASK, 0);
cs->writeisac(cs, ISAC_CMDR, 0x41); cs->writeisac(cs, ISAC_CMDR, 0x41);
cs->hw.hfc.timer.expires = jiffies + 1; spin_unlock_irqrestore(&cs->lock, flags);
delay = HZ/100;
if (!delay)
delay = 1;
cs->hw.hfc.timer.expires = jiffies + delay;
add_timer(&cs->hw.hfc.timer); add_timer(&cs->hw.hfc.timer);
return(0); return(0);
case CARD_TEST: case CARD_TEST:
@ -278,15 +285,13 @@ setup_TeleInt(struct IsdnCard *card)
cs->hw.hfc.timer.function = (void *) TeleInt_Timer; cs->hw.hfc.timer.function = (void *) TeleInt_Timer;
cs->hw.hfc.timer.data = (long) cs; cs->hw.hfc.timer.data = (long) cs;
init_timer(&cs->hw.hfc.timer); init_timer(&cs->hw.hfc.timer);
if (check_region((cs->hw.hfc.addr), 2)) { if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n", "HiSax: %s config port %x-%x already in use\n",
CardType[card->typ], CardType[card->typ],
cs->hw.hfc.addr, cs->hw.hfc.addr,
cs->hw.hfc.addr + 2); cs->hw.hfc.addr + 2);
return (0); return (0);
} else {
request_region(cs->hw.hfc.addr, 2, "TeleInt isdn");
} }
/* HW IO = IO */ /* HW IO = IO */
byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff); byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
@ -318,12 +323,10 @@ setup_TeleInt(struct IsdnCard *card)
byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt); byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
printk(KERN_INFO printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n",
"TeleInt: defined at 0x%x IRQ %d\n", cs->hw.hfc.addr, cs->irq);
cs->hw.hfc.addr,
cs->irq);
reset_TeleInt(cs); setup_isac(cs);
cs->readisac = &ReadISAC; cs->readisac = &ReadISAC;
cs->writeisac = &WriteISAC; cs->writeisac = &WriteISAC;
cs->readisacfifo = &ReadISACfifo; cs->readisacfifo = &ReadISACfifo;