This commit is contained in:
Karsten Keil 2001-02-11 22:57:24 +00:00
parent 680cd22ed6
commit 33a9b1afac
5 changed files with 85 additions and 51 deletions

View File

@ -22,6 +22,7 @@ discard_queue(struct sk_buff_head *q)
return(ret);
}
int
init_dchannel(dchannel_t *dch) {
if (!(dch->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
@ -46,8 +47,6 @@ init_dchannel(dchannel_t *dch) {
dch->tx_idx = 0;
dch->next_skb = NULL;
dch->event = 0;
dch->tqueue.next = 0;
dch->tqueue.sync = 0;
dch->tqueue.data = dch;
skb_queue_head_init(&dch->rqueue);
return(0);
@ -55,6 +54,9 @@ init_dchannel(dchannel_t *dch) {
int
free_dchannel(dchannel_t *dch) {
if (dch->tqueue.sync)
printk(KERN_ERR"free_dchannel tqueue.sync\n");
discard_queue(&dch->rqueue);
if (dch->rx_buf) {
kfree(dch->rx_buf);
@ -102,6 +104,9 @@ init_bchannel(bchannel_t *bch) {
int
free_bchannel(bchannel_t *bch) {
if (bch->tqueue.sync)
printk(KERN_ERR"free_bchannel tqueue.sync\n");
discard_queue(&bch->rqueue);
if (bch->rx_buf) {
kfree(bch->rx_buf);

View File

@ -299,6 +299,7 @@ struct isac_chip {
#define FLG_ARCOFI_TIMER 10
#define FLG_ARCOFI_ERROR 11
#define FLG_HW_L1_UINT 12
#define FLG_HW_INIT 13
typedef struct _dchannel_t {
hisaxinstance_t inst;

View File

@ -653,13 +653,13 @@ dbusy_timer_handler(dchannel_t *dch)
void
init_isac(dchannel_t *dch)
{
dch->writeisac(dch->inst.data, ISAC_MASK, 0xff);
dch->tqueue.routine = (void *) (void *) isac_bh;
dch->hw.isac.mon_tx = NULL;
dch->hw.isac.mon_rx = NULL;
dch->dbusytimer.function = (void *) dbusy_timer_handler;
dch->dbusytimer.data = (long) dch;
init_timer(&dch->dbusytimer);
dch->writeisac(dch->inst.data, ISAC_MASK, 0xff);
dch->hw.isac.mocr = 0xaa;
if (test_bit(HW_IOM1, &dch->DFlags)) {
/* IOM 1 Mode */
@ -680,6 +680,7 @@ init_isac(dchannel_t *dch)
dch->writeisac(dch->inst.data, ISAC_TIMR, 0x00);
dch->writeisac(dch->inst.data, ISAC_ADF1, 0x00);
}
isac_sched_event(dch, D_L1STATECHANGE);
ph_command(dch, ISAC_CMD_RS);
dch->writeisac(dch->inst.data, ISAC_MASK, 0x0);
}
@ -689,6 +690,8 @@ clear_pending_isac_ints(dchannel_t *dch)
{
int val, eval;
/* Disable all IRQ */
dch->writeisac(dch->inst.data, ISAC_MASK, 0xFF);
val = dch->readisac(dch->inst.data, ISAC_STAR);
debugprint(&dch->inst, "ISAC STAR %x", val);
val = dch->readisac(dch->inst.data, ISAC_MODE);
@ -704,7 +707,4 @@ clear_pending_isac_ints(dchannel_t *dch)
val = dch->readisac(dch->inst.data, ISAC_CIR0);
debugprint(&dch->inst, "ISAC CIR0 %x", val);
dch->hw.isac.ph_state = (val >> 2) & 0xf;
isac_sched_event(dch, D_L1STATECHANGE);
/* Disable all IRQ */
dch->writeisac(dch->inst.data, ISAC_MASK, 0xFF);
}

View File

@ -418,6 +418,12 @@ reterror:
static void
isar_bh(bchannel_t *bch)
{
if (!bch)
return;
if (!bch->inst.up.func) {
printk(KERN_WARNING "HiSax: isar_bh without up.func\n");
return;
}
if (test_and_clear_bit(B_XMTBUFREADY, &bch->event)) {
struct sk_buff *skb = bch->next_skb;
@ -470,7 +476,7 @@ isar_bh(bchannel_t *bch)
static void
isar_sched_event(bchannel_t *bch, int event)
{
bch->event |= 1 << event;
test_and_set_bit(event, &bch->event);
queue_task(&bch->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}

View File

@ -2,14 +2,13 @@
*
* sedl_fax.c low level stuff for Sedlbauer Speedfax + cards
*
* Copyright (C) 1997,1998 Marcus Niemann (for the modifications to
* the original file asuscom.c)
* (C) 2000 Karsten Keil (kkeil@suse.de)
* Copyright (C) 2000,2001 Karsten Keil (kkeil@suse.de)
*
* Author Karsten Keil (kkeil@suse.de)
*
* Author Marcus Niemann (niemann@www-bib.fh-bielefeld.de)
* Karsten Keil (kkeil@suse.de)
*
* Thanks to Sedlbauer AG for informations
* Marcus Niemann
* Edgar Toernig
*
* This file is (c) under GNU PUBLIC LICENSE
@ -25,8 +24,7 @@
* Important:
* For the sedlbauer speed fax+ to work properly you have to download
* the firmware onto the card.
* For example: hisaxctrl <DriverID> 9 ISAR.BIN
*/
*/
#include <linux/config.h>
#include "hisax.h"
@ -112,7 +110,7 @@ typedef struct _sedl_fax {
#ifdef SPIN_DEBUG
void *lock_adr;
#endif
u_int in_irq;
volatile u_int in_irq;
struct isar_reg ir;
dchannel_t dch;
bchannel_t bch[2];
@ -245,15 +243,19 @@ do_sedl_interrupt(sedl_fax *sf)
if (val)
isac_interrupt(&sf->dch, val);
val = readreg(sf->addr, sf->isar, ISAR_IRQBIT);
if ((val & ISAR_IRQSTA) && --cnt) {
if ((val & ISAR_IRQSTA) && cnt) {
cnt--;
if (sf->dch.debug & L1_DEB_HSCX)
printk(KERN_DEBUG "ISAR IntStat after IntRoutine\n");
printk(KERN_DEBUG "ISAR IntStat after IntRoutine cpu%d\n",
smp_processor_id());
goto Start_ISAR;
}
val = readreg(sf->addr, sf->isac, ISAC_ISTA);
if (val && --cnt) {
if (val && cnt) {
cnt--;
if (sf->dch.debug & L1_DEB_ISAC)
printk(KERN_DEBUG "ISAC IntStat after IntRoutine\n");
printk(KERN_DEBUG "ISAC IntStat after IntRoutine cpu%d\n",
smp_processor_id());
goto Start_ISAC;
}
if (!cnt)
@ -304,7 +306,6 @@ release_sedlbauer(sedl_fax *sf)
bytecnt = 16;
if (sf->cfg)
release_region(sf->cfg, bytecnt);
free_irq(sf->irq, sf);
}
static void
@ -332,16 +333,31 @@ static int init_card(sedl_fax *sf)
{
int irq_cnt, cnt = 3;
long flags;
u_int shared = SA_SHIRQ;
void *irq_func = speedfax_pci_interrupt;
irq_cnt = kstat_irqs(sf->irq);
printk(KERN_INFO "Sedlbauer speedfax: IRQ %d count %d\n", sf->irq, irq_cnt);
if (sf->subtyp == SEDL_SPEEDFAX_ISA) {
irq_func = speedfax_isa_interrupt;
shared = 0;
}
save_flags(flags);
irq_cnt = kstat_irqs(sf->irq);
printk(KERN_INFO "%s: IRQ %d count %d cpu%d\n",
sf->dch.inst.id, sf->irq, irq_cnt, smp_processor_id());
lock_dev(sf);
sf->in_irq = 1;
if (request_irq(sf->irq, irq_func, shared, "speedfax", sf)) {
printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
sf->irq);
unlock_dev(sf);
return(-EIO);
}
while (cnt) {
lock_dev(sf);
clear_pending_isac_ints(&sf->dch);
init_isac(&sf->dch);
init_isar(&sf->bch[0]);
init_isar(&sf->bch[1]);
sf->in_irq = 0;
WriteISAC(sf, ISAC_MASK, 0);
/* RESET Receiver and Transmitter */
WriteISAC(sf, ISAC_CMDR, 0x41);
@ -351,8 +367,9 @@ static int init_card(sedl_fax *sf)
/* Timeout 10ms */
schedule_timeout((10*HZ)/1000);
restore_flags(flags);
printk(KERN_INFO "Sedlbauer speedfax: IRQ %d count %d\n",
sf->irq, kstat_irqs(sf->irq));
printk(KERN_INFO "%s: IRQ %d count %d cpu%d\n",
sf->dch.inst.id, sf->irq, kstat_irqs(sf->irq), smp_processor_id());
// irq_cnt = kstat_irqs(sf->irq);
if (kstat_irqs(sf->irq) == irq_cnt) {
printk(KERN_WARNING
"Sedlbauer speedfax: IRQ(%d) getting no interrupts during init %d\n",
@ -366,8 +383,9 @@ static int init_card(sedl_fax *sf)
} else {
return(0);
}
lock_dev(sf);
}
restore_flags(flags);
unlock_dev(sf);
return(-EIO);
}
@ -500,14 +518,6 @@ setup_speedfax(sedl_fax *sf, u_int io_cfg, u_int irq_cfg)
sf->addr = sf->cfg + SEDL_PCI_ADR;
sf->isac = sf->cfg + SEDL_PCI_ISAC;
sf->isar = sf->cfg + SEDL_PCI_ISAR;
if (request_irq(sf->irq, speedfax_pci_interrupt, SA_SHIRQ,
"speedfax", sf)) {
printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
sf->irq);
sf->irq = 0;
release_sedlbauer(sf);
return(-EIO);
}
byteout(sf->cfg + TIGER_RESET_ADDR, 0xff);
mdelay(1);
byteout(sf->cfg + TIGER_RESET_ADDR, 0x00);
@ -522,14 +532,6 @@ setup_speedfax(sedl_fax *sf, u_int io_cfg, u_int irq_cfg)
sf->addr = sf->cfg + SEDL_ISA_ADR;
sf->isac = sf->cfg + SEDL_ISA_ISAC;
sf->isar = sf->cfg + SEDL_ISA_ISAR;
if (request_irq(sf->irq, speedfax_isa_interrupt, 0,
"speedfax", sf)) {
printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
sf->irq);
sf->irq = 0;
release_sedlbauer(sf);
return(-EIO);
}
}
sf->bch[0].hw.isar.reg = &sf->ir;
sf->bch[1].hw.isar.reg = &sf->ir;
@ -623,15 +625,28 @@ add_if(hisaxinstance_t *inst, int channel, hisaxif_t *hif) {
}
static int
del_if(hisaxinstance_t *inst, hisaxif_t *hif) {
del_if(hisaxinstance_t *inst, int channel, hisaxif_t *hif) {
int err;
sedl_fax *card = inst->data;
hisaxif_t ohif;
printk(KERN_DEBUG "speedfax del_if lay %d/%d %p/%p\n", hif->layer,
hif->stat, hif->func, hif->fdata);
if ((hif->func == inst->up.func) && (hif->fdata == inst->up.fdata)) {
ohif.protocol = inst->up.protocol;
ohif.layer = inst->up.layer;
inst->up.stat = IF_NOACTIV;
inst->up.protocol = ISDN_PID_NONE;
err = speedfax.ctrl(inst->st, MGR_ADDIF | REQUEST, &inst->up);
if (channel == 2) {
ohif.fdata = &card->dch;
ohif.func = ISAC_l1hw;
} else {
ohif.fdata = &card->bch[channel];
ohif.fdata = isar_down;
}
err = speedfax.ctrl(inst->st, MGR_DELIF | REQUEST, &ohif);
} else {
printk(KERN_DEBUG "speedfax del_if no if found\n");
return(-EINVAL);
@ -641,8 +656,9 @@ del_if(hisaxinstance_t *inst, hisaxif_t *hif) {
static void
release_card(sedl_fax *card) {
lock_dev(card);
card->in_irq = 1;
free_irq(card->irq, card);
free_isar(&card->bch[1]);
free_isar(&card->bch[0]);
free_isac(&card->dch);
@ -651,13 +667,13 @@ release_card(sedl_fax *card) {
reset_speedfax(card);
WriteISAR(card, 0, ISAR_IRQBIT, 0);
WriteISAC(card, ISAC_MASK, 0xFF);
unlock_dev(card);
release_sedlbauer(card);
free_bchannel(&card->bch[1]);
free_bchannel(&card->bch[0]);
free_dchannel(&card->dch);
REMOVE_FROM_LISTBASE(card, cardlist);
kfree(card);
unlock_dev(card);
sedl_cnt--;
speedfax.refcnt--;
}
@ -669,8 +685,11 @@ speedfax_manager(void *data, u_int prim, void *arg) {
int i,channel = -1;
hisaxstack_t *st = data;
if (!data)
if (!data) {
printk(KERN_ERR "speedfax_manager no data prim %x arg %p\n",
prim, arg);
return(-EINVAL);
}
while(card) {
if (card->dch.inst.st == st) {
inst = &card->dch.inst;
@ -689,8 +708,11 @@ speedfax_manager(void *data, u_int prim, void *arg) {
}
card = card->next;
}
if (channel<0)
if (channel<0) {
printk(KERN_ERR "speedfax_manager no channel data %p prim %x arg %p\n",
data, prim, arg);
return(-EINVAL);
}
switch(prim) {
case MGR_ADDLAYER | CONFIRM:
if (!card) {
@ -704,9 +726,9 @@ speedfax_manager(void *data, u_int prim, void *arg) {
card->dch.inst.st->protocols[3] = ISDN_PID_NONE;
card->dch.inst.st->protocols[4] = ISDN_PID_NONE;
return(0);
}
for (i=0;i<=MAX_LAYER;i++)
card->bch[channel].inst.st->protocols[i] = ISDN_PID_NONE;
} else
for (i=0;i<=MAX_LAYER;i++)
card->bch[channel].inst.st->protocols[i] = ISDN_PID_NONE;
break;
case MGR_RELEASE | INDICATION:
if (!card) {
@ -732,7 +754,7 @@ speedfax_manager(void *data, u_int prim, void *arg) {
printk(KERN_WARNING "speedfax_manager del interface request failed\n");
return(-ENODEV);
}
return(del_if(inst, arg));
return(del_if(inst, channel, arg));
break;
default:
printk(KERN_WARNING "speedfax_manager prim %x not handled\n", prim);