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
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);
......@@ -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_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");
......
......@@ -496,7 +496,6 @@ 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;
......@@ -517,39 +516,19 @@ Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX CRC error");
MemWriteHSCXCMDR(bcs, 0x80);
bcs->rcvidx = 0;
} else {
count = mem_hscx_read(cs, hscx, HSCX_RBCL) & (
test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
count = mem_hscx_read(cs, hscx, HSCX_RBCL) & (fifo_size-1);
if (count == 0)
count = fifo_size;
Memhscx_empty_fifo(bcs, count);
if ((count = bcs->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->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
recv_rme_b(bcs);
}
bcs->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->rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
recv_rpf_b(bcs);
}
if (val & 0x10) {
xmit_xpr_b(bcs);/* XPR */
......
......@@ -76,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;
......@@ -109,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->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->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
recv_rme_b(bcs);
}
bcs->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->rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
recv_rpf_b(bcs);
}
if (val & 0x10) {
xmit_xpr_b(bcs);
......
......@@ -541,7 +541,6 @@ bch_int(struct IsdnCardState *cs, u8 hscx)
{
u8 istab;
struct BCState *bcs;
struct sk_buff *skb;
int count;
u8 rstab;
......@@ -562,40 +561,20 @@ bch_int(struct IsdnCardState *cs, u8 hscx)
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
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;
if (count == 0)
count = B_FIFO_SIZE;
ipacx_bc_empty_fifo(bcs, count);
if ((count = bcs->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->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
recv_rme_b(bcs);
}
}
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
if (istab &0x40) { // RPF
ipacx_bc_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->rcvbuf, B_FIFO_SIZE);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
recv_rpf_b(bcs);
}
if (istab &0x20) { // RFO
......
......@@ -414,7 +414,7 @@ xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more)
return p;
}
static inline u8 *
static inline void
recv_empty_fifo_b(struct BCState *bcs, int count)
{
u8 *p;
......@@ -427,7 +427,6 @@ recv_empty_fifo_b(struct BCState *bcs, int count)
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hscx_empty_fifo: incoming packet too large");
bcs->rcvidx = 0;
return NULL;
}
p = bcs->rcvbuf + bcs->rcvidx;
bcs->rcvidx += count;
......@@ -441,6 +440,39 @@ recv_empty_fifo_b(struct BCState *bcs, int count)
QuickHex(t, p, count);
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)
{
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 */
......@@ -91,38 +90,19 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "JADE %c CRC error", 'A'+jade);
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->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->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb);
}
}
recv_rme_b(bcs);
}
bcs->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->rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb);
}
bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY);
}
recv_rpf_b(bcs);
}
if (val & 0x10) { /* XPR */
xmit_xpr_b(bcs);
......
......@@ -263,7 +263,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);
......@@ -285,38 +284,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->hw.w6692.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);
......
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