Commit 62a758c5 authored by Kai Germaschewski's avatar Kai Germaschewski

Merge uidc2-166.inav.uiowa.net:kernel/v2.5/linux-2.5.isdn

into tp1.ruhr-uni-bochum.de:/scratch/kai/kernel/v2.5/linux-2.5.isdn
parents 1013687e c3ed6a93
......@@ -175,6 +175,39 @@ WriteHDLCPnP(struct IsdnCardState *cs, int chan, u8 offset, u8 value)
spin_unlock_irqrestore(&avm_pci_lock, flags);
}
static void
hdlc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len)
{
u8 idx = hscx ? AVM_HDLC_2 : AVM_HDLC_1;
int i;
if (cs->subtyp == AVM_FRITZ_PCI) {
u32 *ptr = (u32 *) data;
outl(idx, cs->hw.avm.cfg_reg + 4);
for (i = 0; i < len; i += 4) {
#ifdef __powerpc__
#ifdef CONFIG_APUS
*ptr++ = in_le32((u32 *)(cs->hw.avm.isac +_IO_BASE));
#else
*ptr++ = in_be32((u32 *)(cs->hw.avm.isac +_IO_BASE));
#endif /* CONFIG_APUS */
#else
*ptr++ = inl(cs->hw.avm.isac);
#endif /* __powerpc__ */
}
} else {
outb(idx, cs->hw.avm.cfg_reg + 4);
for (i = 0; i < len; i++) {
*data++ = inb(cs->hw.avm.isac);
}
}
}
static struct bc_hw_ops hdlc_hw_ops = {
.read_fifo = hdlc_read_fifo,
};
static inline
struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
{
......@@ -259,52 +292,7 @@ modehdlc(struct BCState *bcs, int mode, int bc)
static inline void
hdlc_empty_fifo(struct BCState *bcs, int count)
{
register u_int *ptr;
u8 *p;
u8 idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
int cnt=0;
struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hdlc_empty_fifo %d", count);
if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
return;
}
ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
bcs->hw.hdlc.rcvidx += count;
if (cs->subtyp == AVM_FRITZ_PCI) {
outl(idx, cs->hw.avm.cfg_reg + 4);
while (cnt < count) {
#ifdef __powerpc__
#ifdef CONFIG_APUS
*ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
#else
*ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
#endif /* CONFIG_APUS */
#else
*ptr++ = inl(cs->hw.avm.isac);
#endif /* __powerpc__ */
cnt += 4;
}
} else {
outb(idx, cs->hw.avm.cfg_reg + 4);
while (cnt < count) {
*p++ = inb(cs->hw.avm.isac);
cnt++;
}
}
if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog;
if (cs->subtyp == AVM_FRITZ_PNP)
p = (u8 *) ptr;
t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
bcs->channel ? 'B' : 'A', count);
QuickHex(t, p, count);
debugl1(cs, bcs->blog);
}
recv_empty_fifo_b(bcs, count);
}
static void
......@@ -360,15 +348,10 @@ reset_xmit(struct BCState *bcs)
hdlc_fill_fifo(bcs);
}
static struct bc_l1_ops hdlc_l1_ops = {
.fill_fifo = hdlc_fill_fifo,
};
static inline void
HDLC_irq(struct BCState *bcs, u_int stat)
{
int len;
struct sk_buff *skb;
if (bcs->cs->debug & L1_DEB_HSCX)
debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
......@@ -384,7 +367,7 @@ HDLC_irq(struct BCState *bcs, u_int stat)
write_ctrl(bcs, 1);
bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS;
write_ctrl(bcs, 1);
bcs->hw.hdlc.rcvidx = 0;
bcs->rcvidx = 0;
} else {
if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
len = 32;
......@@ -392,21 +375,13 @@ HDLC_irq(struct BCState *bcs, u_int stat)
if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
(bcs->mode == L1_MODE_TRANS)) {
if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx)))
printk(KERN_WARNING "HDLC: receive out of memory\n");
else {
memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx),
bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->hw.hdlc.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
recv_rme_b(bcs);
} else {
if (bcs->cs->debug & L1_DEB_HSCX)
debugl1(bcs->cs, "invalid frame");
else
debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat);
bcs->hw.hdlc.rcvidx = 0;
bcs->rcvidx = 0;
}
}
}
......@@ -492,57 +467,20 @@ void
close_hdlcstate(struct BCState *bcs)
{
modehdlc(bcs, 0, 0);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hdlc.rcvbuf) {
kfree(bcs->hw.hdlc.rcvbuf);
bcs->hw.hdlc.rcvbuf = NULL;
}
if (bcs->blog) {
kfree(bcs->blog);
bcs->blog = NULL;
}
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
bc_close(bcs);
}
int
open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
{
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for hdlc.rcvbuf\n");
return (1);
}
if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for bcs->blog\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
kfree(bcs->hw.hdlc.rcvbuf);
bcs->hw.hdlc.rcvbuf = NULL;
return (2);
}
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->hw.hdlc.rcvidx = 0;
bcs->tx_cnt = 0;
return (0);
return bc_open(bcs);
}
int
setstack_hdlc(struct PStack *st, struct BCState *bcs)
{
bcs->channel = st->l1.bc;
bcs->unit = bcs->channel;
if (open_hdlcstate(st->l1.hardware, bcs))
return (-1);
st->l1.bcs = bcs;
......@@ -553,6 +491,12 @@ setstack_hdlc(struct PStack *st, struct BCState *bcs)
return (0);
}
static struct bc_l1_ops hdlc_l1_ops = {
.fill_fifo = hdlc_fill_fifo,
.open = setstack_hdlc,
.close = close_hdlcstate,
};
void __init
inithdlc(struct IsdnCardState *cs)
{
......@@ -582,10 +526,6 @@ inithdlc(struct IsdnCardState *cs)
debugl1(cs, "HDLC 2 VIN %x", val);
}
cs->bcs[0].BC_SetStack = setstack_hdlc;
cs->bcs[1].BC_SetStack = setstack_hdlc;
cs->bcs[0].BC_Close = close_hdlcstate;
cs->bcs[1].BC_Close = close_hdlcstate;
modehdlc(cs->bcs, -1, 0);
modehdlc(cs->bcs + 1, -1, 1);
}
......@@ -774,6 +714,7 @@ setup_avm_pcipnp(struct IsdnCard *card)
cs->irq, cs->hw.avm.cfg_reg);
cs->dc_hw_ops = &isac_ops;
cs->bc_hw_ops = &hdlc_hw_ops;
cs->bc_l1_ops = &hdlc_l1_ops;
cs->cardmsg = &AVM_card_msg;
cs->irq_func = &avm_pcipnp_interrupt;
......
......@@ -853,10 +853,11 @@ CallcFree(void)
static void
release_b_st(struct Channel *chanp)
{
struct IsdnCardState *cs = chanp->cs;
struct PStack *st = chanp->b_st;
if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) {
chanp->bcs->BC_Close(chanp->bcs);
cs->bc_l1_ops->close(chanp->bcs);
switch (chanp->l2_active_protocol) {
case (ISDN_PROTO_L2_X75I):
releasestack_isdnl2(st);
......@@ -1297,7 +1298,7 @@ init_b_st(struct Channel *chanp, int incoming)
break;
}
chanp->bcs->conmsg = NULL;
if (chanp->bcs->BC_SetStack(st, chanp->bcs))
if (cs->bc_l1_ops->open(st, chanp->bcs))
return (-1);
st->l2.flag = 0;
test_and_set_bit(FLG_LAPB, &st->l2.flag);
......
......@@ -825,9 +825,9 @@ static void closecard(int cardnr)
{
struct IsdnCardState *csta = cards[cardnr].cs;
if (csta->bcs->BC_Close != NULL) {
csta->bcs->BC_Close(csta->bcs + 1);
csta->bcs->BC_Close(csta->bcs);
if (csta->bc_l1_ops->close) {
csta->bc_l1_ops->close(csta->bcs + 1);
csta->bc_l1_ops->close(csta->bcs);
}
skb_queue_purge(&csta->rq);
......@@ -1779,10 +1779,10 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
cs->iif.owner = hisax_d_if->owner; // FIXME should be done before registering
INIT_WORK(&cs->work, hisax_bh, cs);
cs->channel[0].d_st->l1.l2l1 = hisax_d_l2l1;
for (i = 0; i < 2; i++) {
cs->bcs[i].BC_SetStack = hisax_bc_setstack;
cs->bcs[i].BC_Close = hisax_bc_close;
cs->bc_l1_ops->open = hisax_bc_setstack;
cs->bc_l1_ops->close = hisax_bc_close;
for (i = 0; i < 2; i++) {
b_if[i]->ifc.l1l2 = hisax_b_l1l2;
hisax_d_if->b_if[i] = b_if[i];
......
......@@ -272,9 +272,29 @@ mem_hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value);
}
static void
mem_hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len)
{
int i;
for (i = 0; i < len; i++)
*data++ = memreadreg(cs->hw.diva.cfg_reg, hscx ? 0x40 : 0);
}
static void
mem_hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len)
{
int i;
for (i = 0; i < len; i++)
memwritereg(cs->hw.diva.cfg_reg, hscx ? 0x40 : 0, *data++);
}
static struct bc_hw_ops mem_hscx_ops = {
.read_reg = mem_hscx_read,
.write_reg = mem_hscx_write,
.read_fifo = mem_hscx_read_fifo,
.write_fifo = mem_hscx_write_fifo,
};
/* IO-Functions for IPACX type cards */
......@@ -325,9 +345,19 @@ ipacx_bc_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
(hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value);
}
static void
ipacx_bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len)
{
int i;
for (i = 0; i < len ; i++)
*data++ = ipacx_bc_read(cs, hscx, IPACX_RFIFOB);
}
static struct bc_hw_ops ipacx_bc_ops = {
.read_reg = ipacx_bc_read,
.write_reg = ipacx_bc_write,
.read_fifo = ipacx_bc_read_fifo,
};
static void
......@@ -405,213 +435,6 @@ diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs)
writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0);
}
static inline void
MemwaitforCEC(struct IsdnCardState *cs, int hscx)
{
int to = 50;
while ((mem_hscx_read(cs, hscx, HSCX_STAR) & 0x04) && to) {
udelay(1);
to--;
}
if (!to)
printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
}
static inline void
MemwaitforXFW(struct IsdnCardState *cs, int hscx)
{
int to = 50;
while ((!(mem_hscx_read(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
udelay(1);
to--;
}
if (!to)
printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
}
static inline void
MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u8 data)
{
unsigned long flags;
spin_lock_irqsave(&diva_lock, flags);
MemwaitforCEC(cs, hscx);
mem_hscx_write(cs, hscx, HSCX_CMDR, data);
spin_unlock_irqrestore(&diva_lock, flags);
}
static void
Memhscx_empty_fifo(struct BCState *bcs, int count)
{
u8 *ptr;
struct IsdnCardState *cs = bcs->cs;
unsigned long flags;
int cnt;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hscx_empty_fifo");
if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hscx_empty_fifo: incoming packet too large");
MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
bcs->hw.hscx.rcvidx = 0;
return;
}
spin_lock_irqsave(&diva_lock, flags);
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
cnt = count;
while (cnt--)
*ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0);
MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
bcs->hw.hscx.rcvidx += count;
spin_unlock_irqrestore(&diva_lock, flags);
if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog;
t += sprintf(t, "hscx_empty_fifo %c cnt %d",
bcs->hw.hscx.hscx ? 'B' : 'A', count);
QuickHex(t, ptr, count);
debugl1(cs, bcs->blog);
}
}
static void
Memhscx_fill_fifo(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
int more, count;
int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
unsigned char *p;
p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
if (!p)
return;
MemwaitforXFW(cs, bcs->hw.hscx.hscx);
while (count--)
memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0,
*p++);
MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
}
static struct bc_l1_ops mem_hscx_l1_ops = {
.fill_fifo = Memhscx_fill_fifo,
};
static inline void
Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
{
u8 r;
struct BCState *bcs = cs->bcs + hscx;
struct sk_buff *skb;
int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
int count;
if (!test_bit(BC_FLG_INIT, &bcs->Flag))
return;
if (val & 0x80) { /* RME */
r = mem_hscx_read(cs, hscx, HSCX_RSTA);
if ((r & 0xf0) != 0xa0) {
if (!(r & 0x80))
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX invalid frame");
if ((r & 0x40) && bcs->mode)
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX RDO mode=%d",
bcs->mode);
if (!(r & 0x20))
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX CRC error");
MemWriteHSCXCMDR(cs, hscx, 0x80);
} else {
count = mem_hscx_read(cs, hscx, HSCX_RBCL) & (
test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
if (count == 0)
count = fifo_size;
Memhscx_empty_fifo(bcs, count);
if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
if (cs->debug & L1_DEB_HSCX_FIFO)
debugl1(cs, "HX Frame %d", count);
if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "HSCX: receive out of memory\n");
else {
memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
}
bcs->hw.hscx.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
if (val & 0x40) { /* RPF */
Memhscx_empty_fifo(bcs, fifo_size);
if (bcs->mode == L1_MODE_TRANS) {
/* receive audio data */
if (!(skb = dev_alloc_skb(fifo_size)))
printk(KERN_WARNING "HiSax: receive out of memory\n");
else {
memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->hw.hscx.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
}
if (val & 0x10) {
xmit_xpr_b(bcs);/* XPR */
}
}
static void
Memhscx_reset_xmit(struct BCState *bcs)
{
MemWriteHSCXCMDR(bcs->cs, bcs->hw.hscx.hscx, 0x01);
}
static inline void
Memhscx_int_main(struct IsdnCardState *cs, u8 val)
{
u8 exval;
struct BCState *bcs;
if (val & 0x01) { // EXB
bcs = cs->bcs + 1;
exval = mem_hscx_read(cs, 1, HSCX_EXIR);
if (exval & 0x40) {
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX B EXIR %x", exval);
xmit_xdu_b(bcs, Memhscx_reset_xmit);
}
}
if (val & 0xf8) {
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX B interrupt %x", val);
Memhscx_interrupt(cs, val, 1);
}
if (val & 0x02) { // EXA
bcs = cs->bcs;
exval = mem_hscx_read(cs, 0, HSCX_EXIR);
if (exval & 0x40) {
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX A EXIR %x", exval);
xmit_xdu_b(bcs, Memhscx_reset_xmit);
}
}
if (val & 0x04) { // ICA
exval = mem_hscx_read(cs, 0, HSCX_ISTA);
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX A interrupt %x", exval);
Memhscx_interrupt(cs, exval, 0);
}
}
static void
diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs)
{
......@@ -642,7 +465,7 @@ diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs)
if (ista & 0x08)
val |= 0x04;
if (val)
Memhscx_int_main(cs, val);
hscx_int_main(cs, val);
}
if (ista & 0x20) {
val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80);
......@@ -1108,7 +931,6 @@ setup_diva(struct IsdnCard *card)
} else if (cs->subtyp == DIVA_IPAC_PCI) {
cs->dc_hw_ops = &mem_ipac_dc_ops;
cs->bc_hw_ops = &mem_hscx_ops;
cs->bc_l1_ops = &mem_hscx_l1_ops;
cs->irq_func = &diva_irq_ipac_pci;
val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);
printk(KERN_INFO "Diva: IPAC version %x\n", val);
......
......@@ -375,11 +375,6 @@ static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
}
}
static struct bc_l1_ops modem_l1_ops = {
.fill_fifo = modem_fill,
};
static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
{
int status, iir, msr;
......@@ -424,10 +419,10 @@ close_elsastate(struct BCState *bcs)
{
modehscx(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) {
if (bcs->rcvbuf) {
if (bcs->mode != L1_MODE_MODEM)
kfree(bcs->hw.hscx.rcvbuf);
bcs->hw.hscx.rcvbuf = NULL;
kfree(bcs->rcvbuf);
bcs->rcvbuf = NULL;
}
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
......@@ -597,23 +592,23 @@ setstack_elsa(struct PStack *st, struct BCState *bcs)
if (open_hscxstate(st->l1.hardware, bcs))
return (-1);
st->l1.l2l1 = hscx_l2l1;
// bcs->cs->BC_Send_Data = hscx_fill_fifo;
// bcs->cs->BC_Send_Data = hscx_fill_fifo; FIXME
break;
case L1_MODE_MODEM:
bcs->mode = L1_MODE_MODEM;
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf;
bcs->rcvbuf = bcs->cs->hw.elsa.rcvbuf;
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->hw.hscx.rcvidx = 0;
bcs->rcvidx = 0;
bcs->tx_cnt = 0;
bcs->cs->hw.elsa.bcs = bcs;
st->l1.l2l1 = modem_l2l1;
bcs->cs->bc_l1_ops = &modem_l1_ops;
// bcs->cs->bc_l1_ops = &modem_l1_ops;
break;
}
st->l1.bcs = bcs;
......@@ -623,13 +618,17 @@ setstack_elsa(struct PStack *st, struct BCState *bcs)
return (0);
}
static struct bc_l1_ops modem_l1_ops = {
.fill_fifo = modem_fill,
.open = setstack_elsa,
.close = close_elsastate,
};
void
init_modem(struct IsdnCardState *cs) {
init_modem(struct IsdnCardState *cs)
{
cs->bc_l1_ops = &modem_l1_ops;
cs->bcs[0].BC_SetStack = setstack_elsa;
cs->bcs[1].BC_SetStack = setstack_elsa;
cs->bcs[0].BC_Close = close_elsastate;
cs->bcs[1].BC_Close = close_elsastate;
if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF,
GFP_ATOMIC))) {
printk(KERN_WARNING
......
......@@ -850,9 +850,16 @@ unsigned int __init
return(send);
}
static struct bc_l1_ops hfcd_l1_ops = {
.fill_fifo = hfc_fill_fifo,
.open = setstack_2b,
.close = close_2bs0,
};
void __init
init2bds0(struct IsdnCardState *cs)
{
cs->bc_l1_ops = &hfcd_l1_ops;
cs->setstack_d = setstack_hfcd;
cs->dbusytimer.function = (void *) hfc_dbusy_timer;
cs->dbusytimer.data = (long) cs;
......@@ -865,10 +872,6 @@ init2bds0(struct IsdnCardState *cs)
if (!cs->bcs[1].hw.hfc.send)
cs->bcs[1].hw.hfc.send = init_send_hfcd(32);
cs->DC_Send_Data = hfc_fill_dfifo;
cs->bcs[0].BC_SetStack = setstack_2b;
cs->bcs[1].BC_SetStack = setstack_2b;
cs->bcs[0].BC_Close = close_2bs0;
cs->bcs[1].BC_Close = close_2bs0;
mode_2bs0(cs->bcs, 0, 0);
mode_2bs0(cs->bcs + 1, 0, 1);
}
......
......@@ -546,6 +546,8 @@ init_send(struct BCState *bcs)
static struct bc_l1_ops hfc_l1_ops = {
.fill_fifo = hfc_fill_fifo,
.open = setstack_hfc,
.close = close_hfcstate,
};
void __init
......@@ -554,10 +556,6 @@ inithfc(struct IsdnCardState *cs)
init_send(&cs->bcs[0]);
init_send(&cs->bcs[1]);
cs->bc_l1_ops = &hfc_l1_ops;
cs->bcs[0].BC_SetStack = setstack_hfc;
cs->bcs[1].BC_SetStack = setstack_hfc;
cs->bcs[0].BC_Close = close_hfcstate;
cs->bcs[1].BC_Close = close_hfcstate;
mode_hfc(cs->bcs, 0, 0);
mode_hfc(cs->bcs + 1, 0, 0);
}
......
......@@ -1337,6 +1337,8 @@ hfcpci_bh(void *data)
static struct bc_l1_ops hfcpci_l1_ops = {
.fill_fifo = hfcpci_fill_fifo,
.open = setstack_2b,
.close = close_hfcpci,
};
/********************************/
......@@ -1352,10 +1354,6 @@ inithfcpci(struct IsdnCardState *cs)
INIT_WORK(&cs->work, hfcpci_bh, cs);
cs->bc_l1_ops = &hfcpci_l1_ops;
cs->DC_Send_Data = hfcpci_fill_dfifo;
cs->bcs[0].BC_SetStack = setstack_2b;
cs->bcs[1].BC_SetStack = setstack_2b;
cs->bcs[0].BC_Close = close_hfcpci;
cs->bcs[1].BC_Close = close_hfcpci;
mode_hfcpci(cs->bcs, 0, 0);
mode_hfcpci(cs->bcs + 1, 0, 1);
}
......
......@@ -1114,6 +1114,8 @@ hfcsx_bh(void *data)
static struct bc_l1_ops hfcsx_l1_ops = {
.fill_fifo = hfcsx_fill_fifo,
.open = setstack_2b,
.close = close_hfcsx,
};
/********************************/
......@@ -1129,10 +1131,6 @@ inithfcsx(struct IsdnCardState *cs)
INIT_WORK(&cs->work, hfcsx_bh, cs);
cs->bc_l1_ops = &hfcsx_l1_ops;
cs->DC_Send_Data = hfcsx_fill_dfifo;
cs->bcs[0].BC_SetStack = setstack_2b;
cs->bcs[1].BC_SetStack = setstack_2b;
cs->bcs[0].BC_Close = close_hfcsx;
cs->bcs[1].BC_Close = close_hfcsx;
mode_hfcsx(cs->bcs, 0, 0);
mode_hfcsx(cs->bcs + 1, 0, 1);
}
......
......@@ -349,17 +349,12 @@ struct l3_process {
};
struct hscx_hw {
int hscx;
int rcvidx;
u8 *rcvbuf; /* B-Channel receive Buffer */
u8 tsaxr0;
u8 tsaxr1;
};
struct w6692B_hw {
int bchan;
int rcvidx;
u8 *rcvbuf; /* B-Channel receive Buffer */
};
struct isar_reg {
......@@ -407,8 +402,6 @@ struct hdlc_hw {
struct hdlc_stat_reg sr;
} ctrl;
u_int stat;
int rcvidx;
u8 *rcvbuf; /* B-Channel receive Buffer */
};
struct hfcB_hw {
......@@ -479,10 +472,13 @@ struct amd7930_hw {
struct BCState {
int channel;
int mode;
long Flag; /* long req'd for set_bit --RR */
long Flag;
struct IsdnCardState *cs;
int tx_cnt; /* B-Channel transmit counter */
struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
int unit; /* first or second unit (e.g. HSCX) */
int rcvidx;
u8 *rcvbuf; /* B-Channel receive Buffer */
int tx_cnt; /* B-Channel transmit counter */
struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
struct sk_buff_head rqueue; /* B-Channel receive queue */
struct sk_buff_head squeue; /* B-Channel send queue */
struct sk_buff_head cmpl_queue; /* B-Channel send complete queue */
......@@ -492,8 +488,6 @@ struct BCState {
struct timer_list transbusy;
struct work_struct work;
unsigned long event;
int (*BC_SetStack) (struct PStack *, struct BCState *);
void (*BC_Close) (struct BCState *);
#ifdef ERROR_STATISTIC
int err_crc;
int err_tx;
......@@ -882,6 +876,8 @@ struct dc_hw_ops {
struct bc_l1_ops {
void (*fill_fifo) (struct BCState *);
int (*open) (struct PStack *, struct BCState *);
void (*close) (struct BCState *);
};
#define HW_IOM1 0
......
......@@ -25,36 +25,24 @@ static inline u8
hscx_read(struct BCState *bcs, u8 addr)
{
struct IsdnCardState *cs = bcs->cs;
u8 hscx = bcs->hw.hscx.hscx;
return cs->bc_hw_ops->read_reg(cs, hscx, addr);
return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr);
}
static inline void
hscx_write(struct BCState *bcs, u8 addr, u8 val)
{
struct IsdnCardState *cs = bcs->cs;
u8 hscx = bcs->hw.hscx.hscx;
cs->bc_hw_ops->write_reg(cs, hscx, addr, val);
}
static inline void
hscx_read_fifo(struct BCState *bcs, u8 *p, int len)
{
struct IsdnCardState *cs = bcs->cs;
u8 hscx = bcs->hw.hscx.hscx;
cs->bc_hw_ops->read_fifo(cs, hscx, p, len);
cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val);
}
static inline void
hscx_write_fifo(struct BCState *bcs, u8 *p, int len)
{
struct IsdnCardState *cs = bcs->cs;
u8 hscx = bcs->hw.hscx.hscx;
cs->bc_hw_ops->write_fifo(cs, hscx, p, len);
cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len);
}
int __init
......@@ -67,16 +55,16 @@ HscxVersion(struct IsdnCardState *cs, char *s)
printk(KERN_INFO "%s HSCX version A: %s B: %s\n", s,
HSCXVer[verA], HSCXVer[verB]);
if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf))
return (1);
return 1;
else
return (0);
return 0;
}
void
modehscx(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
int hscx = bcs->hw.hscx.hscx;
int hscx = bcs->unit;
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hscx %c mode %d ichan %d",
......@@ -164,52 +152,17 @@ void
close_hscxstate(struct BCState *bcs)
{
modehscx(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) {
kfree(bcs->hw.hscx.rcvbuf);
bcs->hw.hscx.rcvbuf = NULL;
}
if (bcs->blog) {
kfree(bcs->blog);
bcs->blog = NULL;
}
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
skb_queue_purge(&bcs->cmpl_queue);
if (bcs->tx_skb) {
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
bc_close(bcs);
}
int
open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
{
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for hscx.rcvbuf\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
return (1);
}
if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for bcs->blog\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
kfree(bcs->hw.hscx.rcvbuf);
bcs->hw.hscx.rcvbuf = NULL;
return (2);
}
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
skb_queue_head_init(&bcs->cmpl_queue);
}
bc_open(bcs);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->hw.hscx.rcvidx = 0;
bcs->rcvidx = 0;
bcs->tx_cnt = 0;
return (0);
}
......@@ -228,8 +181,12 @@ setstack_hscx(struct PStack *st, struct BCState *bcs)
return (0);
}
static void hscx_fill_fifo(struct BCState *bcs);
static struct bc_l1_ops hscx_l1_ops = {
.fill_fifo = hscx_fill_fifo,
.open = setstack_hscx,
.close = close_hscxstate,
};
void __init
......@@ -238,12 +195,8 @@ inithscx(struct IsdnCardState *cs)
int val, eval;
cs->bc_l1_ops = &hscx_l1_ops;
cs->bcs[0].BC_SetStack = setstack_hscx;
cs->bcs[1].BC_SetStack = setstack_hscx;
cs->bcs[0].BC_Close = close_hscxstate;
cs->bcs[1].BC_Close = close_hscxstate;
cs->bcs[0].hw.hscx.hscx = 0;
cs->bcs[1].hw.hscx.hscx = 1;
cs->bcs[0].unit = 0;
cs->bcs[1].unit = 1;
cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
cs->bcs[0].hw.hscx.tsaxr1 = 3;
cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
......
......@@ -38,4 +38,3 @@ extern int HscxVersion(struct IsdnCardState *cs, char *s);
extern void modehscx(struct BCState *bcs, int mode, int bc);
extern void inithscxisac(struct IsdnCardState *cs);
extern void hscx_int_main(struct IsdnCardState *cs, u8 val);
extern void hscx_fill_fifo(struct BCState *bcs);
......@@ -26,7 +26,7 @@ waitforCEC(struct BCState *bcs)
}
static inline void
static void
waitforXFW(struct BCState *bcs)
{
int to = 50;
......@@ -50,71 +50,25 @@ WriteHSCXCMDR(struct BCState *bcs, u8 data)
static void
hscx_empty_fifo(struct BCState *bcs, int count)
{
u8 *ptr;
struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hscx_empty_fifo");
if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hscx_empty_fifo: incoming packet too large");
WriteHSCXCMDR(bcs, 0x80);
bcs->hw.hscx.rcvidx = 0;
return;
}
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
bcs->hw.hscx.rcvidx += count;
hscx_read_fifo(bcs, ptr, count);
recv_empty_fifo_b(bcs, count);
WriteHSCXCMDR(bcs, 0x80);
if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog;
t += sprintf(t, "hscx_empty_fifo %c cnt %d",
bcs->hw.hscx.hscx ? 'B' : 'A', count);
QuickHex(t, ptr, count);
debugl1(cs, bcs->blog);
}
}
void
static void
hscx_fill_fifo(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
int more, count;
int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
u8 *ptr;
u8 *p;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hscx_fill_fifo");
if (!bcs->tx_skb)
return;
if (bcs->tx_skb->len <= 0)
p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
if (!p)
return;
more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
if (bcs->tx_skb->len > fifo_size) {
more = !0;
count = fifo_size;
} else
count = bcs->tx_skb->len;
waitforXFW(bcs);
ptr = bcs->tx_skb->data;
skb_pull(bcs->tx_skb, count);
bcs->tx_cnt -= count;
bcs->count += count;
hscx_write_fifo(bcs, ptr, count);
hscx_write_fifo(bcs, p, count);
WriteHSCXCMDR(bcs, more ? 0x8 : 0xa);
if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog;
t += sprintf(t, "hscx_fill_fifo %c cnt %d",
bcs->hw.hscx.hscx ? 'B' : 'A', count);
QuickHex(t, ptr, count);
debugl1(cs, bcs->blog);
}
}
static inline void
......@@ -122,7 +76,6 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
{
u8 r;
struct BCState *bcs = cs->bcs + hscx;
struct sk_buff *skb;
int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
int count;
......@@ -155,39 +108,19 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
#endif
}
WriteHSCXCMDR(bcs, 0x80);
bcs->rcvidx = 0;
} else {
count = hscx_read(bcs, HSCX_RBCL) & (
test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
count = hscx_read(bcs, HSCX_RBCL) & (fifo_size-1);
if (count == 0)
count = fifo_size;
hscx_empty_fifo(bcs, count);
if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
if (cs->debug & L1_DEB_HSCX_FIFO)
debugl1(cs, "HX Frame %d", count);
if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "HSCX: receive out of memory\n");
else {
memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
recv_rme_b(bcs);
}
bcs->hw.hscx.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
if (val & 0x40) { /* RPF */
hscx_empty_fifo(bcs, fifo_size);
if (bcs->mode == L1_MODE_TRANS) {
/* receive audio data */
if (!(skb = dev_alloc_skb(fifo_size)))
printk(KERN_WARNING "HiSax: receive out of memory\n");
else {
memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->hw.hscx.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
recv_rpf_b(bcs);
}
if (val & 0x10) {
xmit_xpr_b(bcs);
......@@ -203,11 +136,9 @@ reset_xmit(struct BCState *bcs)
void
hscx_int_main(struct IsdnCardState *cs, u8 val)
{
u8 exval;
struct BCState *bcs;
spin_lock(&cs->lock);
if (val & 0x01) {
bcs = cs->bcs + 1;
exval = hscx_read(bcs, HSCX_EXIR);
......@@ -238,5 +169,4 @@ hscx_int_main(struct IsdnCardState *cs, u8 val)
debugl1(cs, "HSCX A interrupt %x", exval);
hscx_interrupt(cs, exval, 0);
}
spin_unlock(&cs->lock);
}
......@@ -23,7 +23,6 @@
#define DBUSY_TIMER_VALUE 80
#define ARCOFI_USE 0
static spinlock_t icc_lock = SPIN_LOCK_UNLOCKED;
static inline u8
icc_read_reg(struct IsdnCardState *cs, u8 addr)
......@@ -137,33 +136,8 @@ icc_bh(void *data)
void
icc_empty_fifo(struct IsdnCardState *cs, int count)
{
u8 *ptr;
unsigned long flags;
if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
debugl1(cs, "icc_empty_fifo");
if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "icc_empty_fifo overrun %d",
cs->rcvidx + count);
icc_write_reg(cs, ICC_CMDR, 0x80);
cs->rcvidx = 0;
return;
}
ptr = cs->rcvbuf + cs->rcvidx;
cs->rcvidx += count;
spin_lock_irqsave(&icc_lock, flags);
icc_read_fifo(cs, ptr, count);
recv_empty_fifo_d(cs, count);
icc_write_reg(cs, ICC_CMDR, 0x80);
spin_unlock_irqrestore(&icc_lock, flags);
if (cs->debug & L1_DEB_ISAC_FIFO) {
char *t = cs->dlog;
t += sprintf(t, "icc_empty_fifo cnt %d", count);
QuickHex(t, ptr, count);
debugl1(cs, cs->dlog);
}
}
static void
......@@ -171,13 +145,11 @@ icc_fill_fifo(struct IsdnCardState *cs)
{
int count, more;
unsigned char *p;
unsigned long flags;
p = xmit_fill_fifo_d(cs, 32, &count, &more);
if (!p)
return;
spin_lock_irqsave(&icc_lock, flags);
icc_write_fifo(cs, p, count);
icc_write_reg(cs, ICC_CMDR, more ? 0x8 : 0xa);
if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
......@@ -187,16 +159,13 @@ icc_fill_fifo(struct IsdnCardState *cs)
init_timer(&cs->dbusytimer);
cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
add_timer(&cs->dbusytimer);
spin_unlock_irqrestore(&icc_lock, flags);
}
void
icc_interrupt(struct IsdnCardState *cs, u8 val)
{
u8 exval, v1;
struct sk_buff *skb;
unsigned int count;
unsigned long flags;
if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "ICC interrupt %x", val);
......@@ -218,25 +187,14 @@ icc_interrupt(struct IsdnCardState *cs, u8 val)
#endif
}
icc_write_reg(cs, ICC_CMDR, 0x80);
cs->rcvidx = 0;
} else {
count = icc_read_reg(cs, ICC_RBCL) & 0x1f;
if (count == 0)
count = 32;
icc_empty_fifo(cs, count);
spin_lock_irqsave(&icc_lock, flags);
if ((count = cs->rcvidx) > 0) {
cs->rcvidx = 0;
if (!(skb = alloc_skb(count, GFP_ATOMIC)))
printk(KERN_WARNING "HiSax: D receive out of memory\n");
else {
memcpy(skb_put(skb, count), cs->rcvbuf, count);
skb_queue_tail(&cs->rq, skb);
}
}
spin_unlock_irqrestore(&icc_lock, flags);
recv_rme_d(cs);
}
cs->rcvidx = 0;
sched_d_event(cs, D_RCVBUFREADY);
}
if (val & 0x40) { /* RPF */
icc_empty_fifo(cs, 32);
......
......@@ -44,7 +44,7 @@ static inline void dch_int(struct IsdnCardState *cs);
static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs);
static void __devinit dch_init(struct IsdnCardState *cs);
static void bch_l2l1(struct PStack *st, int pr, void *arg);
static void bch_empty_fifo(struct BCState *bcs, int count);
static void ipacx_bc_empty_fifo(struct BCState *bcs, int count);
static void bch_int(struct IsdnCardState *cs, u8 hscx);
static void bch_mode(struct BCState *bcs, int mode, int bc);
static void bch_close_state(struct BCState *bcs);
......@@ -57,18 +57,16 @@ static inline u8
ipacx_bc_read_reg(struct BCState *bcs, u8 addr)
{
struct IsdnCardState *cs = bcs->cs;
u8 hscx = bcs->hw.hscx.hscx;
return cs->bc_hw_ops->read_reg(cs, hscx, addr);
return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr);
}
static inline void
ipacx_bc_write_reg(struct BCState *bcs, u8 addr, u8 val)
{
struct IsdnCardState *cs = bcs->cs;
u8 hscx = bcs->hw.hscx.hscx;
cs->bc_hw_ops->write_reg(cs, hscx, addr, val);
cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val);
}
static inline u8
......@@ -305,33 +303,8 @@ dch_bh(void *data)
static void
dch_empty_fifo(struct IsdnCardState *cs, int count)
{
u8 *ptr;
if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
debugl1(cs, "dch_empty_fifo()");
// message too large, remove
if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
if (cs->debug &L1_DEB_WARN)
debugl1(cs, "dch_empty_fifo() incoming message too large");
ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC
cs->rcvidx = 0;
return;
}
ptr = cs->rcvbuf + cs->rcvidx;
cs->rcvidx += count;
ipacx_read_fifo(cs, ptr, count);
recv_empty_fifo_d(cs, count);
ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC
if (cs->debug &L1_DEB_ISAC_FIFO) {
char *t = cs->dlog;
t += sprintf(t, "dch_empty_fifo() cnt %d", count);
QuickHex(t, ptr, count);
debugl1(cs, cs->dlog);
}
}
//----------------------------------------------------------
......@@ -372,7 +345,6 @@ dch_fill_fifo(struct IsdnCardState *cs)
static inline void
dch_int(struct IsdnCardState *cs)
{
struct sk_buff *skb;
u8 istad, rstad;
int count;
......@@ -383,32 +355,25 @@ dch_int(struct IsdnCardState *cs)
if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
if (!(rstad &0x80))
if (cs->debug &L1_DEB_WARN)
debugl1(cs, "dch_int(): invalid frame");
debugl1(cs, "dch_int(): invalid frame");
if ((rstad &0x40))
if (cs->debug &L1_DEB_WARN)
debugl1(cs, "dch_int(): RDO");
debugl1(cs, "dch_int(): RDO");
if (!(rstad &0x20))
if (cs->debug &L1_DEB_WARN)
debugl1(cs, "dch_int(): CRC error");
ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC
debugl1(cs, "dch_int(): CRC error");
ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC
cs->rcvidx = 0;
} else { // received frame ok
count = ipacx_read_reg(cs, IPACX_RBCLD);
if (count) count--; // RSTAB is last byte
// FIXME this looks flaky
if (count) count--; // RSTAB is last byte
count &= D_FIFO_SIZE-1;
if (count == 0) count = D_FIFO_SIZE;
if (count == 0)
count = D_FIFO_SIZE;
dch_empty_fifo(cs, count);
if ((count = cs->rcvidx) > 0) {
cs->rcvidx = 0;
if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n");
else {
memcpy(skb_put(skb, count), cs->rcvbuf, count);
skb_queue_tail(&cs->rq, skb);
}
}
}
cs->rcvidx = 0;
sched_d_event(cs, D_RCVBUFREADY);
recv_rme_d(cs);
}
}
if (istad &0x40) { // RPF
......@@ -501,49 +466,17 @@ bch_l2l1(struct PStack *st, int pr, void *arg)
// Read B channel fifo to receive buffer
//----------------------------------------------------------
static void
bch_empty_fifo(struct BCState *bcs, int count)
ipacx_bc_empty_fifo(struct BCState *bcs, int count)
{
u8 *ptr, hscx;
struct IsdnCardState *cs;
int cnt;
cs = bcs->cs;
hscx = bcs->hw.hscx.hscx;
if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO))
debugl1(cs, "bch_empty_fifo()");
// message too large, remove
if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
if (cs->debug &L1_DEB_WARN)
debugl1(cs, "bch_empty_fifo() incoming packet too large");
ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC
bcs->hw.hscx.rcvidx = 0;
return;
}
// Read data uninterruptible
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
cnt = count;
while (cnt--) *ptr++ = ipacx_bc_read_reg(bcs, IPACX_RFIFOB);
recv_empty_fifo_b(bcs, count);
ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
bcs->hw.hscx.rcvidx += count;
if (cs->debug &L1_DEB_HSCX_FIFO) {
char *t = bcs->blog;
t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count);
QuickHex(t, ptr, count);
debugl1(cs, bcs->blog);
}
}
//----------------------------------------------------------
// Fill buffer to transmit FIFO
//----------------------------------------------------------
void
ipacx_fill_fifo(struct BCState *bcs)
static void
ipacx_bc_fill_fifo(struct BCState *bcs)
{
int more, count;
unsigned char *p;
......@@ -573,7 +506,6 @@ bch_int(struct IsdnCardState *cs, u8 hscx)
{
u8 istab;
struct BCState *bcs;
struct sk_buff *skb;
int count;
u8 rstab;
......@@ -586,48 +518,28 @@ bch_int(struct IsdnCardState *cs, u8 hscx)
if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
if (!(rstab &0x80))
if (cs->debug &L1_DEB_WARN)
debugl1(cs, "bch_int() B-%d: invalid frame", hscx);
debugl1(cs, "bch_int() B-%d: invalid frame", hscx);
if ((rstab &0x40) && (bcs->mode != L1_MODE_NULL))
if (cs->debug &L1_DEB_WARN)
debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode);
debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode);
if (!(rstab &0x20))
if (cs->debug &L1_DEB_WARN)
debugl1(cs, "bch_int() B-%d: CRC error", hscx);
ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC
}
else { // received frame ok
debugl1(cs, "bch_int() B-%d: CRC error", hscx);
ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC
bcs->rcvidx = 0;
} else { // received frame ok
count = ipacx_bc_read_reg(bcs, IPACX_RBCLB) &(B_FIFO_SIZE-1);
if (count == 0) count = B_FIFO_SIZE;
bch_empty_fifo(bcs, count);
if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
if (cs->debug &L1_DEB_HSCX_FIFO)
debugl1(cs, "bch_int Frame %d", count);
if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n");
else {
memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
if (count == 0)
count = B_FIFO_SIZE;
ipacx_bc_empty_fifo(bcs, count);
recv_rme_b(bcs);
}
bcs->hw.hscx.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
if (istab &0x40) { // RPF
bch_empty_fifo(bcs, B_FIFO_SIZE);
if (bcs->mode == L1_MODE_TRANS) { // queue every chunk
// receive transparent audio data
if (!(skb = dev_alloc_skb(B_FIFO_SIZE)))
printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n");
else {
memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->hw.hscx.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
ipacx_bc_empty_fifo(bcs, B_FIFO_SIZE);
recv_rpf_b(bcs);
}
if (istab &0x20) { // RFO
......@@ -651,7 +563,7 @@ static void
bch_mode(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
int hscx = bcs->hw.hscx.hscx;
int hscx = bcs->unit;
bc = bc ? 1 : 0; // in case bc is greater than 1
if (cs->debug & L1_DEB_HSCX)
......@@ -699,23 +611,7 @@ static void
bch_close_state(struct BCState *bcs)
{
bch_mode(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) {
kfree(bcs->hw.hscx.rcvbuf);
bcs->hw.hscx.rcvbuf = NULL;
}
if (bcs->blog) {
kfree(bcs->blog);
bcs->blog = NULL;
}
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
bc_close(bcs);
}
//----------------------------------------------------------
......@@ -723,30 +619,7 @@ bch_close_state(struct BCState *bcs)
static int
bch_open_state(struct IsdnCardState *cs, struct BCState *bcs)
{
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax open_bchstate(): No memory for hscx.rcvbuf\n");
clear_bit(BC_FLG_INIT, &bcs->Flag);
return (1);
}
if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax open_bchstate: No memory for bcs->blog\n");
clear_bit(BC_FLG_INIT, &bcs->Flag);
kfree(bcs->hw.hscx.rcvbuf);
bcs->hw.hscx.rcvbuf = NULL;
return (2);
}
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
bcs->tx_skb = NULL;
clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->hw.hscx.rcvidx = 0;
bcs->tx_cnt = 0;
return (0);
return bc_open(bcs);
}
//----------------------------------------------------------
......@@ -769,9 +642,7 @@ bch_setstack(struct PStack *st, struct BCState *bcs)
static void __devinit
bch_init(struct IsdnCardState *cs, int hscx)
{
cs->bcs[hscx].BC_SetStack = bch_setstack;
cs->bcs[hscx].BC_Close = bch_close_state;
cs->bcs[hscx].hw.hscx.hscx = hscx;
cs->bcs[hscx].unit = hscx;
cs->bcs[hscx].cs = cs;
bch_mode(cs->bcs + hscx, 0, hscx);
}
......@@ -821,7 +692,9 @@ clear_pending_ints(struct IsdnCardState *cs)
}
static struct bc_l1_ops ipacx_bc_l1_ops = {
.fill_fifo = ipacx_fill_fifo,
.fill_fifo = ipacx_bc_fill_fifo,
.open = bch_setstack,
.close = bch_close_state,
};
//----------------------------------------------------------
......
......@@ -157,6 +157,5 @@
extern void init_ipacx(struct IsdnCardState *cs, int part);
extern void interrupt_ipacx(struct IsdnCardState *cs);
extern void ipacx_fill_fifo(struct BCState *bcs);
#endif
......@@ -39,12 +39,6 @@ isac_write(struct IsdnCardState *cs, u8 addr, u8 val)
cs->dc_hw_ops->write_reg(cs, addr, val);
}
static inline void
isac_read_fifo(struct IsdnCardState *cs, u8 *p, int len)
{
return cs->dc_hw_ops->read_fifo(cs, p, len);
}
static inline void
isac_write_fifo(struct IsdnCardState *cs, u8 *p, int len)
{
......@@ -140,30 +134,8 @@ isac_bh(void *data)
void
isac_empty_fifo(struct IsdnCardState *cs, int count)
{
u8 *ptr;
if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
debugl1(cs, "isac_empty_fifo");
if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "isac_empty_fifo overrun %d",
cs->rcvidx + count);
isac_write(cs, ISAC_CMDR, 0x80);
cs->rcvidx = 0;
return;
}
ptr = cs->rcvbuf + cs->rcvidx;
cs->rcvidx += count;
isac_read_fifo(cs, ptr, count);
recv_empty_fifo_d(cs, count);
isac_write(cs, ISAC_CMDR, 0x80);
if (cs->debug & L1_DEB_ISAC_FIFO) {
char *t = cs->dlog;
t += sprintf(t, "isac_empty_fifo cnt %d", count);
QuickHex(t, ptr, count);
debugl1(cs, cs->dlog);
}
}
static void
......@@ -191,7 +163,6 @@ void
isac_interrupt(struct IsdnCardState *cs, u8 val)
{
u8 exval, v1;
struct sk_buff *skb;
unsigned int count;
if (cs->debug & L1_DEB_ISAC)
......@@ -214,20 +185,13 @@ isac_interrupt(struct IsdnCardState *cs, u8 val)
#endif
}
isac_write(cs, ISAC_CMDR, 0x80);
cs->rcvidx = 0;
} else {
count = isac_read(cs, ISAC_RBCL) & 0x1f;
if (count == 0)
count = 32;
isac_empty_fifo(cs, count);
if ((count = cs->rcvidx) > 0) {
cs->rcvidx = 0;
if (!(skb = alloc_skb(count, GFP_ATOMIC)))
printk(KERN_WARNING "HiSax: D receive out of memory\n");
else {
memcpy(skb_put(skb, count), cs->rcvbuf, count);
skb_queue_tail(&cs->rq, skb);
}
}
recv_rme_d(cs);
}
cs->rcvidx = 0;
sched_d_event(cs, D_RCVBUFREADY);
......
......@@ -1745,14 +1745,12 @@ isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
static struct bc_l1_ops isar_l1_ops = {
.fill_fifo = isar_fill_fifo,
.open = setstack_isar,
.close = close_isarstate,
};
void __devinit
initisar(struct IsdnCardState *cs)
{
cs->bc_l1_ops = &isar_l1_ops;
cs->bcs[0].BC_SetStack = setstack_isar;
cs->bcs[1].BC_SetStack = setstack_isar;
cs->bcs[0].BC_Close = close_isarstate;
cs->bcs[1].BC_Close = close_isarstate;
}
......@@ -358,8 +358,6 @@ init_bcstate(struct IsdnCardState *cs,
bcs->cs = cs;
bcs->channel = bc;
INIT_WORK(&bcs->work, BChannel_bh, bcs);
bcs->BC_SetStack = NULL;
bcs->BC_Close = NULL;
bcs->Flag = 0;
}
......
......@@ -372,7 +372,7 @@ xmit_fill_fifo_b(struct BCState *bcs, int fifo_size, int *count, int *more)
char *t = bcs->blog;
t += sprintf(t, "%s %c cnt %d", __FUNCTION__,
bcs->hw.hscx.hscx ? 'B' : 'A', *count);
bcs->unit ? 'B' : 'A', *count);
QuickHex(t, p, *count);
debugl1(cs, bcs->blog);
}
......@@ -413,3 +413,172 @@ xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more)
}
return p;
}
static inline void
recv_empty_fifo_d(struct IsdnCardState *cs, int count)
{
u8 *p;
if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
debugl1(cs, __FUNCTION__);
if (cs->rcvidx + count > MAX_DFRAME_LEN_L1) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "%s: incoming packet too large", __FUNCTION__);
cs->rcvidx = 0;
return;
}
p = cs->rcvbuf + cs->rcvidx;
cs->rcvidx += count;
cs->dc_hw_ops->read_fifo(cs, p, count);
if (cs->debug & L1_DEB_ISAC_FIFO) {
char *t = cs->dlog;
t += sprintf(t, "%s cnt %d", __FUNCTION__, count);
QuickHex(t, p, count);
debugl1(cs, cs->dlog);
}
}
static inline void
recv_empty_fifo_b(struct BCState *bcs, int count)
{
u8 *p;
struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, __FUNCTION__);
if (bcs->rcvidx + count > HSCX_BUFMAX) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "%s: incoming packet too large", __FUNCTION__);
bcs->rcvidx = 0;
return;
}
p = bcs->rcvbuf + bcs->rcvidx;
bcs->rcvidx += count;
cs->bc_hw_ops->read_fifo(cs, bcs->unit, p, count);
if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog;
t += sprintf(t, "%s %c cnt %d", __FUNCTION__,
bcs->unit ? 'B' : 'A', count);
QuickHex(t, p, count);
debugl1(cs, bcs->blog);
}
}
/* RME - receive message end */
static inline void
recv_rme_d(struct IsdnCardState *cs)
{
struct sk_buff *skb;
int count;
count = cs->rcvidx - 1;
cs->rcvidx = 0;
if (count == 0)
return;
skb = dev_alloc_skb(count);
if (!skb) {
printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__);
return;
}
memcpy(skb_put(skb, count), cs->rcvbuf, count);
skb_queue_tail(&cs->rq, skb);
sched_d_event(cs, D_RCVBUFREADY);
}
static inline void
recv_rme_b(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
struct sk_buff *skb;
int count;
count = bcs->rcvidx - 1;
bcs->rcvidx = 0;
if (count == 0)
return;
if (cs->debug & L1_DEB_HSCX_FIFO)
debugl1(cs, "HX Frame %d", count);
skb = dev_alloc_skb(count);
if (!skb) {
printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__);
return;
}
memcpy(skb_put(skb, count), bcs->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
sched_b_event(bcs, B_RCVBUFREADY);
}
/* RPF - receive pull full */
static inline void
recv_rpf_b(struct BCState *bcs)
{
if (bcs->mode != L1_MODE_TRANS)
return;
recv_rme_b(bcs);
}
static inline int
bc_open(struct BCState *bcs)
{
if (test_and_set_bit(BC_FLG_INIT, &bcs->Flag))
return 0;
bcs->rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC);
if (!bcs->rcvbuf)
goto err;
bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC);
if (!bcs->blog)
goto err_rcvbuf;
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
skb_queue_head_init(&bcs->cmpl_queue);
clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->tx_skb = NULL;
bcs->rcvidx = 0;
bcs->tx_cnt = 0;
bcs->event = 0;
return 0;
err_rcvbuf:
kfree(bcs->rcvbuf);
err:
clear_bit(BC_FLG_INIT, &bcs->Flag);
printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__);
return -ENOMEM;;
}
static inline void
bc_close(struct BCState *bcs)
{
if (!test_and_clear_bit(BC_FLG_INIT, &bcs->Flag))
return;
kfree(bcs->rcvbuf);
bcs->rcvbuf = NULL;
kfree(bcs->blog);
bcs->blog = NULL;
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
skb_queue_purge(&bcs->cmpl_queue);
if (bcs->tx_skb) {
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
......@@ -32,22 +32,12 @@ jade_write_reg(struct IsdnCardState *cs, int jade, u8 addr, u8 val)
cs->bc_hw_ops->write_reg(cs, jade, addr, val);
}
static inline void
jade_read_fifo(struct BCState *bcs, u8 *p, int len)
{
struct IsdnCardState *cs = bcs->cs;
u8 hscx = bcs->hw.hscx.hscx;
cs->bc_hw_ops->read_fifo(cs, hscx, p, len);
}
static inline void
jade_write_fifo(struct BCState *bcs, u8 *p, int len)
{
struct IsdnCardState *cs = bcs->cs;
u8 hscx = bcs->hw.hscx.hscx;
cs->bc_hw_ops->write_fifo(cs, hscx, p, len);
cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len);
}
int __init
......@@ -112,7 +102,7 @@ void
modejade(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
int jade = bcs->hw.hscx.hscx;
int jade = bcs->unit;
if (cs->debug & L1_DEB_HSCX) {
char tmp[40];
......@@ -199,53 +189,14 @@ jade_l2l1(struct PStack *st, int pr, void *arg)
void
close_jadestate(struct BCState *bcs)
{
modejade(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) {
kfree(bcs->hw.hscx.rcvbuf);
bcs->hw.hscx.rcvbuf = NULL;
}
if (bcs->blog) {
kfree(bcs->blog);
bcs->blog = NULL;
}
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
modejade(bcs, 0, bcs->channel);
bc_close(bcs);
}
static int
open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
{
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for hscx.rcvbuf\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
return (1);
}
if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for bcs->blog\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
kfree(bcs->hw.hscx.rcvbuf);
bcs->hw.hscx.rcvbuf = NULL;
return (2);
}
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->hw.hscx.rcvidx = 0;
bcs->tx_cnt = 0;
return (0);
return bc_open(bcs);;
}
......@@ -263,8 +214,12 @@ setstack_jade(struct PStack *st, struct BCState *bcs)
return (0);
}
static void jade_fill_fifo(struct BCState *bcs);
static struct bc_l1_ops jade_l1_ops = {
.fill_fifo = jade_fill_fifo,
.open = setstack_jade,
.close = close_jadestate,
};
void __init
......@@ -273,12 +228,8 @@ initjade(struct IsdnCardState *cs)
int val;
cs->bc_l1_ops = &jade_l1_ops;
cs->bcs[0].BC_SetStack = setstack_jade;
cs->bcs[1].BC_SetStack = setstack_jade;
cs->bcs[0].BC_Close = close_jadestate;
cs->bcs[1].BC_Close = close_jadestate;
cs->bcs[0].hw.hscx.hscx = 0;
cs->bcs[1].hw.hscx.hscx = 1;
cs->bcs[0].unit = 0;
cs->bcs[1].unit = 1;
jade_write_reg(cs, 0, jade_HDLC_IMR, 0x00);
jade_write_reg(cs, 1, jade_HDLC_IMR, 0x00);
......
......@@ -132,7 +132,5 @@ extern void jade_sched_event(struct BCState *bcs, int event);
extern void modejade(struct BCState *bcs, int mode, int bc);
extern void initjade(struct IsdnCardState *cs);
extern void jade_int_main(struct IsdnCardState *cs, u_char val, int jade);
extern void jade_fill_fifo(struct BCState *bcs);
#endif /* __JADE_H__ */
......@@ -9,7 +9,6 @@
* of the GNU General Public License, incorporated herein by reference.
*
*/
static spinlock_t jade_irq_lock = SPIN_LOCK_UNLOCKED;
static inline void
waitforCEC(struct IsdnCardState *cs, int jade, int reg)
......@@ -26,20 +25,17 @@ waitforCEC(struct IsdnCardState *cs, int jade, int reg)
static inline void
waitforXFW(struct IsdnCardState *cs, int jade)
waitforXFW(struct BCState *bcs)
{
/* Does not work on older jade versions, don't care */
}
static inline void
WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u8 data)
WriteJADECMDR(struct BCState *bcs, int reg, u8 data)
{
unsigned long flags;
int jade = bcs->unit;
spin_lock_irqsave(&jade_irq_lock, flags);
waitforCEC(cs, jade, reg);
jade_write_reg(cs, jade, reg, data);
spin_unlock_irqrestore(&jade_irq_lock, flags);
waitforCEC(bcs->cs, jade, reg);
jade_write_reg(bcs->cs, jade, reg, data);
}
......@@ -47,49 +43,24 @@ WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u8 data)
static void
jade_empty_fifo(struct BCState *bcs, int count)
{
u8 *ptr;
struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "jade_empty_fifo");
if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "jade_empty_fifo: incoming packet too large");
WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
bcs->hw.hscx.rcvidx = 0;
return;
}
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
bcs->hw.hscx.rcvidx += count;
jade_read_fifo(bcs, ptr, count);
WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog;
t += sprintf(t, "jade_empty_fifo %c cnt %d",
bcs->hw.hscx.hscx ? 'B' : 'A', count);
QuickHex(t, ptr, count);
debugl1(cs, bcs->blog);
}
recv_empty_fifo_b(bcs, count);
WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC);
}
void
static void
jade_fill_fifo(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
int more, count;
int fifo_size = 32;
int hscx = bcs->hw.hscx.hscx;
unsigned char *p;
p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
if (!p)
return;
waitforXFW(cs, hscx);
waitforXFW(bcs);
jade_write_fifo(bcs, p, count);
WriteJADECMDR(cs, hscx, jade_HDLC_XCMD,
WriteJADECMDR(bcs, jade_HDLC_XCMD,
more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
}
......@@ -99,7 +70,6 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
{
u8 r;
struct BCState *bcs = cs->bcs + jade;
struct sk_buff *skb;
int fifo_size = 32;
int count;
int i_jade = (int) jade; /* To satisfy the compiler */
......@@ -119,39 +89,20 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
if (!(r & 0x20))
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "JADE %c CRC error", 'A'+jade);
WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC);
WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC);
bcs->rcvidx = 0;
} else {
count = jade_read_reg(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
if (count == 0)
count = fifo_size;
jade_empty_fifo(bcs, count);
if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
if (cs->debug & L1_DEB_HSCX_FIFO)
debugl1(cs, "HX Frame %d", count);
if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A"));
else {
memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
recv_rme_b(bcs);
}
bcs->hw.hscx.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
if (val & 0x40) { /* RPF */
jade_empty_fifo(bcs, fifo_size);
if (bcs->mode == L1_MODE_TRANS) {
/* receive audio data */
if (!(skb = dev_alloc_skb(fifo_size)))
printk(KERN_WARNING "HiSax: receive out of memory\n");
else {
memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->hw.hscx.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
recv_rpf_b(bcs);
}
if (val & 0x10) { /* XPR */
xmit_xpr_b(bcs);
......@@ -161,7 +112,7 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
static void
reset_xmit(struct BCState *bcs)
{
WriteJADECMDR(bcs->cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
WriteJADECMDR(bcs, jade_HDLC_XCMD, jadeXCMD_XRES);
}
void
......
......@@ -937,6 +937,8 @@ setstack_tiger(struct PStack *st, struct BCState *bcs)
static struct bc_l1_ops netjet_l1_ops = {
.fill_fifo = netjet_fill_dma,
.open = setstack_tiger,
.close = close_tigerstate,
};
void __init
......@@ -994,10 +996,6 @@ inittiger(struct IsdnCardState *cs)
inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
cs->hw.njet.last_is0 = 0;
cs->bcs[0].BC_SetStack = setstack_tiger;
cs->bcs[1].BC_SetStack = setstack_tiger;
cs->bcs[0].BC_Close = close_tigerstate;
cs->bcs[1].BC_Close = close_tigerstate;
}
void
......
......@@ -57,7 +57,7 @@ w6692_write_reg(struct IsdnCardState *cs, u8 offset, u8 value)
outb(value, cs->hw.w6692.iobase + offset);
}
static inline void
static void
w6692_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
{
insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size);
......@@ -69,6 +69,10 @@ w6692_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size);
}
static struct dc_hw_ops w6692_dc_hw_ops = {
.read_fifo = w6692_read_fifo,
};
static inline u8
w6692_bc_read_reg(struct IsdnCardState *cs, int bchan, u8 offset)
{
......@@ -81,6 +85,16 @@ w6692_bc_write_reg(struct IsdnCardState *cs, int bchan, u8 offset, u8 value)
outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset);
}
static void
w6692_bc_read_fifo(struct IsdnCardState *cs, int bchan, u8 *data, int len)
{
insb(cs->hw.w6692.iobase + W_B_RFIFO + (bchan ? 0x40:0), data, len);
}
static struct bc_hw_ops w6692_bc_hw_ops = {
.read_fifo = w6692_bc_read_fifo,
};
static char *W6692Ver[] __initdata =
{"W6692 V00", "W6692 V01", "W6692 V10",
"W6692 V11"};
......@@ -171,30 +185,8 @@ W6692_bh(void *data)
static void
W6692_empty_fifo(struct IsdnCardState *cs, int count)
{
u8 *ptr;
if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
debugl1(cs, "W6692_empty_fifo");
if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "W6692_empty_fifo overrun %d",
cs->rcvidx + count);
w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK);
cs->rcvidx = 0;
return;
}
ptr = cs->rcvbuf + cs->rcvidx;
cs->rcvidx += count;
w6692_read_fifo(cs, ptr, count);
recv_empty_fifo_d(cs, count);
w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK);
if (cs->debug & L1_DEB_ISAC_FIFO) {
char *t = cs->dlog;
t += sprintf(t, "W6692_empty_fifo cnt %d", count);
QuickHex(t, ptr, count);
debugl1(cs, cs->dlog);
}
}
static void
......@@ -221,31 +213,8 @@ W6692_fill_fifo(struct IsdnCardState *cs)
static void
W6692B_empty_fifo(struct BCState *bcs, int count)
{
u8 *ptr;
struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "W6692B_empty_fifo");
if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "W6692B_empty_fifo: incoming packet too large");
w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
bcs->hw.w6692.rcvidx = 0;
return;
}
ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx;
bcs->hw.w6692.rcvidx += count;
READW6692BFIFO(cs, bcs->channel, ptr, count);
w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog;
t += sprintf(t, "W6692B_empty_fifo %c cnt %d",
bcs->channel + '1', count);
QuickHex(t, ptr, count);
debugl1(cs, bcs->blog);
}
recv_empty_fifo_b(bcs, count);
w6692_bc_write_reg(bcs->cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
}
static void
......@@ -276,7 +245,6 @@ W6692B_interrupt(struct IsdnCardState *cs, u8 bchan)
u8 val;
u8 r;
struct BCState *bcs;
struct sk_buff *skb;
int count;
bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1);
......@@ -298,38 +266,18 @@ W6692B_interrupt(struct IsdnCardState *cs, u8 bchan)
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "W6692 B CRC error");
w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
bcs->rcvidx = 0;
} else {
count = w6692_bc_read_reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
if (count == 0)
count = W_B_FIFO_THRESH;
W6692B_empty_fifo(bcs, count);
if ((count = bcs->hw.w6692.rcvidx) > 0) {
if (cs->debug & L1_DEB_HSCX_FIFO)
debugl1(cs, "W6692 Bchan Frame %d", count);
if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "W6692: Bchan receive out of memory\n");
else {
memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
recv_rme_b(bcs);
}
bcs->hw.w6692.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
if (val & W_B_EXI_RMR) { /* RMR */
W6692B_empty_fifo(bcs, W_B_FIFO_THRESH);
if (bcs->mode == L1_MODE_TRANS) {
/* receive audio data */
if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH)))
printk(KERN_WARNING "HiSax: receive out of memory\n");
else {
memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->hw.w6692.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
recv_rpf_b(bcs);
}
if (val & W_B_EXI_XFR) { /* XFR */
xmit_xpr_b(bcs);
......@@ -344,7 +292,6 @@ W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
struct IsdnCardState *cs = dev_id;
u8 val, exval, v1;
struct sk_buff *skb;
unsigned int count;
int icnt = 5;
......@@ -369,23 +316,14 @@ W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "W6692 D-channel ABORT");
w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
cs->rcvidx = 0;
} else {
count = w6692_read_reg(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
if (count == 0)
count = W_D_FIFO_THRESH;
W6692_empty_fifo(cs, count);
if ((count = cs->rcvidx) > 0) {
cs->rcvidx = 0;
if (!(skb = alloc_skb(count, GFP_ATOMIC)))
printk(KERN_WARNING "HiSax: D receive out of memory\n");
else {
memcpy(skb_put(skb, count), cs->rcvbuf, count);
skb_queue_tail(&cs->rq, skb);
}
}
recv_rme_d(cs);
}
cs->rcvidx = 0;
sched_d_event(cs, D_RCVBUFREADY);
}
if (val & W_INT_D_RMR) { /* RMR */
W6692_empty_fifo(cs, W_D_FIFO_THRESH);
......@@ -632,52 +570,13 @@ static void
close_w6692state(struct BCState *bcs)
{
W6692Bmode(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.w6692.rcvbuf) {
kfree(bcs->hw.w6692.rcvbuf);
bcs->hw.w6692.rcvbuf = NULL;
}
if (bcs->blog) {
kfree(bcs->blog);
bcs->blog = NULL;
}
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
bc_close(bcs);
}
static int
open_w6692state(struct IsdnCardState *cs, struct BCState *bcs)
{
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for w6692.rcvbuf\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
return (1);
}
if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for bcs->blog\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
kfree(bcs->hw.w6692.rcvbuf);
bcs->hw.w6692.rcvbuf = NULL;
return (2);
}
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->hw.w6692.rcvidx = 0;
bcs->tx_cnt = 0;
return (0);
return bc_open(bcs);
}
static int
......@@ -731,10 +630,6 @@ void __init initW6692(struct IsdnCardState *cs, int part)
W6692_new_ph(cs);
ph_command(cs, W_L1CMD_ECK);
cs->bcs[0].BC_SetStack = setstack_w6692;
cs->bcs[1].BC_SetStack = setstack_w6692;
cs->bcs[0].BC_Close = close_w6692state;
cs->bcs[1].BC_Close = close_w6692state;
W6692Bmode(cs->bcs, 0, 0);
W6692Bmode(cs->bcs + 1, 0, 0);
}
......@@ -774,6 +669,8 @@ w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
static struct bc_l1_ops w6692_bc_l1_ops = {
.fill_fifo = W6692B_fill_fifo,
.open = setstack_w6692,
.close = close_w6692state,
};
static int id_idx ;
......@@ -864,6 +761,8 @@ setup_w6692(struct IsdnCard *card)
id_list[cs->subtyp].card_name, cs->irq,
cs->hw.w6692.iobase);
cs->dc_hw_ops = &w6692_dc_hw_ops;
cs->bc_hw_ops = &w6692_bc_hw_ops;
cs->bc_l1_ops = &w6692_bc_l1_ops;
cs->DC_Send_Data = &W6692_fill_fifo;
cs->cardmsg = &w6692_card_msg;
......
......@@ -18,9 +18,6 @@
/* B-channel FIFO read/write routines */
#define READW6692BFIFO(cs,bchan,ptr,count) \
insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count)
#define WRITEW6692BFIFO(cs,bchan,ptr,count) \
outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment