Commit 4e52ad01 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Share RME/RPF B-channel IRQ handling

Again, receive message end / receive pool full are similar enough to
easily share common code.
parent 57d386d3
...@@ -352,7 +352,6 @@ static inline void ...@@ -352,7 +352,6 @@ static inline void
HDLC_irq(struct BCState *bcs, u_int stat) HDLC_irq(struct BCState *bcs, u_int stat)
{ {
int len; int len;
struct sk_buff *skb;
if (bcs->cs->debug & L1_DEB_HSCX) if (bcs->cs->debug & L1_DEB_HSCX)
debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat); debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
...@@ -376,15 +375,7 @@ HDLC_irq(struct BCState *bcs, u_int stat) ...@@ -376,15 +375,7 @@ HDLC_irq(struct BCState *bcs, u_int stat)
if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) { if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) || if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
(bcs->mode == L1_MODE_TRANS)) { (bcs->mode == L1_MODE_TRANS)) {
if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx))) recv_rme_b(bcs);
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);
} else { } else {
if (bcs->cs->debug & L1_DEB_HSCX) if (bcs->cs->debug & L1_DEB_HSCX)
debugl1(bcs->cs, "invalid frame"); debugl1(bcs->cs, "invalid frame");
......
...@@ -496,7 +496,6 @@ Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) ...@@ -496,7 +496,6 @@ Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
{ {
u8 r; u8 r;
struct BCState *bcs = cs->bcs + hscx; struct BCState *bcs = cs->bcs + hscx;
struct sk_buff *skb;
int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
int count; int count;
...@@ -517,39 +516,19 @@ Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) ...@@ -517,39 +516,19 @@ Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX CRC error"); debugl1(cs, "HSCX CRC error");
MemWriteHSCXCMDR(bcs, 0x80); MemWriteHSCXCMDR(bcs, 0x80);
bcs->rcvidx = 0;
} else { } else {
count = mem_hscx_read(cs, hscx, HSCX_RBCL) & ( count = mem_hscx_read(cs, hscx, HSCX_RBCL) & (fifo_size-1);
test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
if (count == 0) if (count == 0)
count = fifo_size; count = fifo_size;
Memhscx_empty_fifo(bcs, count); Memhscx_empty_fifo(bcs, count);
if ((count = bcs->rcvidx - 1) > 0) { recv_rme_b(bcs);
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->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
} }
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
} }
if (val & 0x40) { /* RPF */ if (val & 0x40) { /* RPF */
Memhscx_empty_fifo(bcs, fifo_size); Memhscx_empty_fifo(bcs, fifo_size);
if (bcs->mode == L1_MODE_TRANS) { recv_rpf_b(bcs);
/* 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->rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
} }
if (val & 0x10) { if (val & 0x10) {
xmit_xpr_b(bcs);/* XPR */ xmit_xpr_b(bcs);/* XPR */
......
...@@ -76,7 +76,6 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) ...@@ -76,7 +76,6 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
{ {
u8 r; u8 r;
struct BCState *bcs = cs->bcs + hscx; struct BCState *bcs = cs->bcs + hscx;
struct sk_buff *skb;
int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
int count; int count;
...@@ -109,39 +108,19 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) ...@@ -109,39 +108,19 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
#endif #endif
} }
WriteHSCXCMDR(bcs, 0x80); WriteHSCXCMDR(bcs, 0x80);
bcs->rcvidx = 0;
} else { } else {
count = hscx_read(bcs, HSCX_RBCL) & ( count = hscx_read(bcs, HSCX_RBCL) & (fifo_size-1);
test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
if (count == 0) if (count == 0)
count = fifo_size; count = fifo_size;
hscx_empty_fifo(bcs, count); hscx_empty_fifo(bcs, count);
if ((count = bcs->rcvidx - 1) > 0) { recv_rme_b(bcs);
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->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
} }
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
} }
if (val & 0x40) { /* RPF */ if (val & 0x40) { /* RPF */
hscx_empty_fifo(bcs, fifo_size); hscx_empty_fifo(bcs, fifo_size);
if (bcs->mode == L1_MODE_TRANS) { recv_rpf_b(bcs);
/* 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->rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
} }
if (val & 0x10) { if (val & 0x10) {
xmit_xpr_b(bcs); xmit_xpr_b(bcs);
......
...@@ -541,7 +541,6 @@ bch_int(struct IsdnCardState *cs, u8 hscx) ...@@ -541,7 +541,6 @@ bch_int(struct IsdnCardState *cs, u8 hscx)
{ {
u8 istab; u8 istab;
struct BCState *bcs; struct BCState *bcs;
struct sk_buff *skb;
int count; int count;
u8 rstab; u8 rstab;
...@@ -554,48 +553,28 @@ bch_int(struct IsdnCardState *cs, u8 hscx) ...@@ -554,48 +553,28 @@ bch_int(struct IsdnCardState *cs, u8 hscx)
if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
if (!(rstab &0x80)) if (!(rstab &0x80))
if (cs->debug &L1_DEB_WARN) 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 ((rstab &0x40) && (bcs->mode != L1_MODE_NULL))
if (cs->debug &L1_DEB_WARN) 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 (!(rstab &0x20))
if (cs->debug &L1_DEB_WARN) if (cs->debug &L1_DEB_WARN)
debugl1(cs, "bch_int() B-%d: CRC error", hscx); debugl1(cs, "bch_int() B-%d: CRC error", hscx);
ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC
} bcs->rcvidx = 0;
else { // received frame ok } else { // received frame ok
count = ipacx_bc_read_reg(bcs, IPACX_RBCLB) &(B_FIFO_SIZE-1); count = ipacx_bc_read_reg(bcs, IPACX_RBCLB) &(B_FIFO_SIZE-1);
if (count == 0) count = B_FIFO_SIZE; if (count == 0)
count = B_FIFO_SIZE;
ipacx_bc_empty_fifo(bcs, count); ipacx_bc_empty_fifo(bcs, count);
if ((count = bcs->rcvidx - 1) > 0) { recv_rme_b(bcs);
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->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
} }
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
} }
if (istab &0x40) { // RPF if (istab &0x40) { // RPF
ipacx_bc_empty_fifo(bcs, B_FIFO_SIZE); ipacx_bc_empty_fifo(bcs, B_FIFO_SIZE);
recv_rpf_b(bcs);
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->rcvbuf, B_FIFO_SIZE);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
} }
if (istab &0x20) { // RFO if (istab &0x20) { // RFO
......
...@@ -414,7 +414,7 @@ xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more) ...@@ -414,7 +414,7 @@ xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more)
return p; return p;
} }
static inline u8 * static inline void
recv_empty_fifo_b(struct BCState *bcs, int count) recv_empty_fifo_b(struct BCState *bcs, int count)
{ {
u8 *p; u8 *p;
...@@ -427,7 +427,6 @@ recv_empty_fifo_b(struct BCState *bcs, int count) ...@@ -427,7 +427,6 @@ recv_empty_fifo_b(struct BCState *bcs, int count)
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hscx_empty_fifo: incoming packet too large"); debugl1(cs, "hscx_empty_fifo: incoming packet too large");
bcs->rcvidx = 0; bcs->rcvidx = 0;
return NULL;
} }
p = bcs->rcvbuf + bcs->rcvidx; p = bcs->rcvbuf + bcs->rcvidx;
bcs->rcvidx += count; bcs->rcvidx += count;
...@@ -441,6 +440,39 @@ recv_empty_fifo_b(struct BCState *bcs, int count) ...@@ -441,6 +440,39 @@ recv_empty_fifo_b(struct BCState *bcs, int count)
QuickHex(t, p, count); QuickHex(t, p, count);
debugl1(cs, bcs->blog); debugl1(cs, bcs->blog);
} }
}
return p; 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 "%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);
}
static inline void
recv_rpf_b(struct BCState *bcs)
{
if (bcs->mode != L1_MODE_TRANS)
return;
recv_rme_b(bcs);
} }
...@@ -70,7 +70,6 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade) ...@@ -70,7 +70,6 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
{ {
u8 r; u8 r;
struct BCState *bcs = cs->bcs + jade; struct BCState *bcs = cs->bcs + jade;
struct sk_buff *skb;
int fifo_size = 32; int fifo_size = 32;
int count; int count;
int i_jade = (int) jade; /* To satisfy the compiler */ int i_jade = (int) jade; /* To satisfy the compiler */
...@@ -91,38 +90,19 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade) ...@@ -91,38 +90,19 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, "JADE %c CRC error", 'A'+jade); debugl1(cs, "JADE %c CRC error", 'A'+jade);
WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC); WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC);
bcs->rcvidx = 0;
} else { } else {
count = jade_read_reg(cs, i_jade, jade_HDLC_RBCL) & 0x1F; count = jade_read_reg(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
if (count == 0) if (count == 0)
count = fifo_size; count = fifo_size;
jade_empty_fifo(bcs, count); jade_empty_fifo(bcs, count);
if ((count = bcs->rcvidx - 1) > 0) { recv_rme_b(bcs);
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->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
} }
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
} }
if (val & 0x40) { /* RPF */ if (val & 0x40) { /* RPF */
jade_empty_fifo(bcs, fifo_size); jade_empty_fifo(bcs, fifo_size);
if (bcs->mode == L1_MODE_TRANS) { recv_rpf_b(bcs);
/* 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->rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
} }
if (val & 0x10) { /* XPR */ if (val & 0x10) { /* XPR */
xmit_xpr_b(bcs); xmit_xpr_b(bcs);
......
...@@ -263,7 +263,6 @@ W6692B_interrupt(struct IsdnCardState *cs, u8 bchan) ...@@ -263,7 +263,6 @@ W6692B_interrupt(struct IsdnCardState *cs, u8 bchan)
u8 val; u8 val;
u8 r; u8 r;
struct BCState *bcs; struct BCState *bcs;
struct sk_buff *skb;
int count; int count;
bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1); bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1);
...@@ -285,38 +284,18 @@ W6692B_interrupt(struct IsdnCardState *cs, u8 bchan) ...@@ -285,38 +284,18 @@ W6692B_interrupt(struct IsdnCardState *cs, u8 bchan)
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, "W6692 B CRC error"); 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); w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
bcs->hw.w6692.rcvidx = 0;
} else { } else {
count = w6692_bc_read_reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1); count = w6692_bc_read_reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
if (count == 0) if (count == 0)
count = W_B_FIFO_THRESH; count = W_B_FIFO_THRESH;
W6692B_empty_fifo(bcs, count); W6692B_empty_fifo(bcs, count);
if ((count = bcs->hw.w6692.rcvidx) > 0) { recv_rme_b(bcs);
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);
}
}
} }
bcs->hw.w6692.rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
} }
if (val & W_B_EXI_RMR) { /* RMR */ if (val & W_B_EXI_RMR) { /* RMR */
W6692B_empty_fifo(bcs, W_B_FIFO_THRESH); W6692B_empty_fifo(bcs, W_B_FIFO_THRESH);
if (bcs->mode == L1_MODE_TRANS) { recv_rpf_b(bcs);
/* 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);
}
} }
if (val & W_B_EXI_XFR) { /* XFR */ if (val & W_B_EXI_XFR) { /* XFR */
xmit_xpr_b(bcs); xmit_xpr_b(bcs);
......
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