Commit c3ed6a93 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN/HiSax: Share D-channel receive code

Basically the same changes which happened to the B-channel code
earlier.
parent f1f5ccc8
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#define DBUSY_TIMER_VALUE 80 #define DBUSY_TIMER_VALUE 80
#define ARCOFI_USE 0 #define ARCOFI_USE 0
static spinlock_t icc_lock = SPIN_LOCK_UNLOCKED;
static inline u8 static inline u8
icc_read_reg(struct IsdnCardState *cs, u8 addr) icc_read_reg(struct IsdnCardState *cs, u8 addr)
...@@ -137,33 +136,8 @@ icc_bh(void *data) ...@@ -137,33 +136,8 @@ icc_bh(void *data)
void void
icc_empty_fifo(struct IsdnCardState *cs, int count) icc_empty_fifo(struct IsdnCardState *cs, int count)
{ {
u8 *ptr; recv_empty_fifo_d(cs, count);
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);
icc_write_reg(cs, ICC_CMDR, 0x80); 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 static void
...@@ -171,13 +145,11 @@ icc_fill_fifo(struct IsdnCardState *cs) ...@@ -171,13 +145,11 @@ icc_fill_fifo(struct IsdnCardState *cs)
{ {
int count, more; int count, more;
unsigned char *p; unsigned char *p;
unsigned long flags;
p = xmit_fill_fifo_d(cs, 32, &count, &more); p = xmit_fill_fifo_d(cs, 32, &count, &more);
if (!p) if (!p)
return; return;
spin_lock_irqsave(&icc_lock, flags);
icc_write_fifo(cs, p, count); icc_write_fifo(cs, p, count);
icc_write_reg(cs, ICC_CMDR, more ? 0x8 : 0xa); icc_write_reg(cs, ICC_CMDR, more ? 0x8 : 0xa);
if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
...@@ -187,16 +159,13 @@ icc_fill_fifo(struct IsdnCardState *cs) ...@@ -187,16 +159,13 @@ icc_fill_fifo(struct IsdnCardState *cs)
init_timer(&cs->dbusytimer); init_timer(&cs->dbusytimer);
cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
add_timer(&cs->dbusytimer); add_timer(&cs->dbusytimer);
spin_unlock_irqrestore(&icc_lock, flags);
} }
void void
icc_interrupt(struct IsdnCardState *cs, u8 val) icc_interrupt(struct IsdnCardState *cs, u8 val)
{ {
u8 exval, v1; u8 exval, v1;
struct sk_buff *skb;
unsigned int count; unsigned int count;
unsigned long flags;
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "ICC interrupt %x", val); debugl1(cs, "ICC interrupt %x", val);
...@@ -218,25 +187,14 @@ icc_interrupt(struct IsdnCardState *cs, u8 val) ...@@ -218,25 +187,14 @@ icc_interrupt(struct IsdnCardState *cs, u8 val)
#endif #endif
} }
icc_write_reg(cs, ICC_CMDR, 0x80); icc_write_reg(cs, ICC_CMDR, 0x80);
cs->rcvidx = 0;
} else { } else {
count = icc_read_reg(cs, ICC_RBCL) & 0x1f; count = icc_read_reg(cs, ICC_RBCL) & 0x1f;
if (count == 0) if (count == 0)
count = 32; count = 32;
icc_empty_fifo(cs, count); icc_empty_fifo(cs, count);
spin_lock_irqsave(&icc_lock, flags); recv_rme_d(cs);
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);
} }
cs->rcvidx = 0;
sched_d_event(cs, D_RCVBUFREADY);
} }
if (val & 0x40) { /* RPF */ if (val & 0x40) { /* RPF */
icc_empty_fifo(cs, 32); icc_empty_fifo(cs, 32);
......
...@@ -303,33 +303,8 @@ dch_bh(void *data) ...@@ -303,33 +303,8 @@ dch_bh(void *data)
static void static void
dch_empty_fifo(struct IsdnCardState *cs, int count) dch_empty_fifo(struct IsdnCardState *cs, int count)
{ {
u8 *ptr; recv_empty_fifo_d(cs, count);
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);
ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC 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);
}
} }
//---------------------------------------------------------- //----------------------------------------------------------
...@@ -370,7 +345,6 @@ dch_fill_fifo(struct IsdnCardState *cs) ...@@ -370,7 +345,6 @@ dch_fill_fifo(struct IsdnCardState *cs)
static inline void static inline void
dch_int(struct IsdnCardState *cs) dch_int(struct IsdnCardState *cs)
{ {
struct sk_buff *skb;
u8 istad, rstad; u8 istad, rstad;
int count; int count;
...@@ -381,32 +355,25 @@ dch_int(struct IsdnCardState *cs) ...@@ -381,32 +355,25 @@ dch_int(struct IsdnCardState *cs)
if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
if (!(rstad &0x80)) if (!(rstad &0x80))
if (cs->debug &L1_DEB_WARN) if (cs->debug &L1_DEB_WARN)
debugl1(cs, "dch_int(): invalid frame"); debugl1(cs, "dch_int(): invalid frame");
if ((rstad &0x40)) if ((rstad &0x40))
if (cs->debug &L1_DEB_WARN) if (cs->debug &L1_DEB_WARN)
debugl1(cs, "dch_int(): RDO"); debugl1(cs, "dch_int(): RDO");
if (!(rstad &0x20)) if (!(rstad &0x20))
if (cs->debug &L1_DEB_WARN) if (cs->debug &L1_DEB_WARN)
debugl1(cs, "dch_int(): CRC error"); debugl1(cs, "dch_int(): CRC error");
ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC
cs->rcvidx = 0;
} else { // received frame ok } else { // received frame ok
count = ipacx_read_reg(cs, IPACX_RBCLD); 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; count &= D_FIFO_SIZE-1;
if (count == 0) count = D_FIFO_SIZE; if (count == 0)
count = D_FIFO_SIZE;
dch_empty_fifo(cs, count); dch_empty_fifo(cs, count);
if ((count = cs->rcvidx) > 0) { recv_rme_d(cs);
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);
} }
if (istad &0x40) { // RPF if (istad &0x40) { // RPF
......
...@@ -39,12 +39,6 @@ isac_write(struct IsdnCardState *cs, u8 addr, u8 val) ...@@ -39,12 +39,6 @@ isac_write(struct IsdnCardState *cs, u8 addr, u8 val)
cs->dc_hw_ops->write_reg(cs, addr, 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 static inline void
isac_write_fifo(struct IsdnCardState *cs, u8 *p, int len) isac_write_fifo(struct IsdnCardState *cs, u8 *p, int len)
{ {
...@@ -140,30 +134,8 @@ isac_bh(void *data) ...@@ -140,30 +134,8 @@ isac_bh(void *data)
void void
isac_empty_fifo(struct IsdnCardState *cs, int count) isac_empty_fifo(struct IsdnCardState *cs, int count)
{ {
u8 *ptr; recv_empty_fifo_d(cs, count);
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);
isac_write(cs, ISAC_CMDR, 0x80); 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 static void
...@@ -191,7 +163,6 @@ void ...@@ -191,7 +163,6 @@ void
isac_interrupt(struct IsdnCardState *cs, u8 val) isac_interrupt(struct IsdnCardState *cs, u8 val)
{ {
u8 exval, v1; u8 exval, v1;
struct sk_buff *skb;
unsigned int count; unsigned int count;
if (cs->debug & L1_DEB_ISAC) if (cs->debug & L1_DEB_ISAC)
...@@ -214,20 +185,13 @@ isac_interrupt(struct IsdnCardState *cs, u8 val) ...@@ -214,20 +185,13 @@ isac_interrupt(struct IsdnCardState *cs, u8 val)
#endif #endif
} }
isac_write(cs, ISAC_CMDR, 0x80); isac_write(cs, ISAC_CMDR, 0x80);
cs->rcvidx = 0;
} else { } else {
count = isac_read(cs, ISAC_RBCL) & 0x1f; count = isac_read(cs, ISAC_RBCL) & 0x1f;
if (count == 0) if (count == 0)
count = 32; count = 32;
isac_empty_fifo(cs, count); isac_empty_fifo(cs, count);
if ((count = cs->rcvidx) > 0) { recv_rme_d(cs);
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);
}
}
} }
cs->rcvidx = 0; cs->rcvidx = 0;
sched_d_event(cs, D_RCVBUFREADY); sched_d_event(cs, D_RCVBUFREADY);
......
...@@ -414,6 +414,33 @@ xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more) ...@@ -414,6 +414,33 @@ xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more)
return p; 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 static inline void
recv_empty_fifo_b(struct BCState *bcs, int count) recv_empty_fifo_b(struct BCState *bcs, int count)
{ {
...@@ -421,12 +448,13 @@ recv_empty_fifo_b(struct BCState *bcs, int count) ...@@ -421,12 +448,13 @@ recv_empty_fifo_b(struct BCState *bcs, int count)
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hscx_empty_fifo"); debugl1(cs, __FUNCTION__);
if (bcs->rcvidx + count > HSCX_BUFMAX) { if (bcs->rcvidx + count > HSCX_BUFMAX) {
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hscx_empty_fifo: incoming packet too large"); debugl1(cs, "%s: incoming packet too large", __FUNCTION__);
bcs->rcvidx = 0; bcs->rcvidx = 0;
return;
} }
p = bcs->rcvbuf + bcs->rcvidx; p = bcs->rcvbuf + bcs->rcvidx;
bcs->rcvidx += count; bcs->rcvidx += count;
...@@ -442,6 +470,28 @@ recv_empty_fifo_b(struct BCState *bcs, int count) ...@@ -442,6 +470,28 @@ recv_empty_fifo_b(struct BCState *bcs, int count)
} }
} }
/* 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 static inline void
recv_rme_b(struct BCState *bcs) recv_rme_b(struct BCState *bcs)
{ {
...@@ -467,6 +517,7 @@ recv_rme_b(struct BCState *bcs) ...@@ -467,6 +517,7 @@ recv_rme_b(struct BCState *bcs)
sched_b_event(bcs, B_RCVBUFREADY); sched_b_event(bcs, B_RCVBUFREADY);
} }
/* RPF - receive pull full */
static inline void static inline void
recv_rpf_b(struct BCState *bcs) recv_rpf_b(struct BCState *bcs)
{ {
......
...@@ -57,7 +57,7 @@ w6692_write_reg(struct IsdnCardState *cs, u8 offset, u8 value) ...@@ -57,7 +57,7 @@ w6692_write_reg(struct IsdnCardState *cs, u8 offset, u8 value)
outb(value, cs->hw.w6692.iobase + offset); outb(value, cs->hw.w6692.iobase + offset);
} }
static inline void static void
w6692_read_fifo(struct IsdnCardState *cs, u8 * data, int size) w6692_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
{ {
insb(cs->hw.w6692.iobase + W_D_RFIFO, data, 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) ...@@ -69,6 +69,10 @@ w6692_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, 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 static inline u8
w6692_bc_read_reg(struct IsdnCardState *cs, int bchan, u8 offset) w6692_bc_read_reg(struct IsdnCardState *cs, int bchan, u8 offset)
{ {
...@@ -181,30 +185,8 @@ W6692_bh(void *data) ...@@ -181,30 +185,8 @@ W6692_bh(void *data)
static void static void
W6692_empty_fifo(struct IsdnCardState *cs, int count) W6692_empty_fifo(struct IsdnCardState *cs, int count)
{ {
u8 *ptr; recv_empty_fifo_d(cs, count);
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);
w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK); 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 static void
...@@ -310,7 +292,6 @@ W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) ...@@ -310,7 +292,6 @@ W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{ {
struct IsdnCardState *cs = dev_id; struct IsdnCardState *cs = dev_id;
u8 val, exval, v1; u8 val, exval, v1;
struct sk_buff *skb;
unsigned int count; unsigned int count;
int icnt = 5; int icnt = 5;
...@@ -335,23 +316,14 @@ W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) ...@@ -335,23 +316,14 @@ W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_WARN)
debugl1(cs, "W6692 D-channel ABORT"); debugl1(cs, "W6692 D-channel ABORT");
w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
cs->rcvidx = 0;
} else { } else {
count = w6692_read_reg(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1); count = w6692_read_reg(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
if (count == 0) if (count == 0)
count = W_D_FIFO_THRESH; count = W_D_FIFO_THRESH;
W6692_empty_fifo(cs, count); W6692_empty_fifo(cs, count);
if ((count = cs->rcvidx) > 0) { recv_rme_d(cs);
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);
}
}
} }
cs->rcvidx = 0;
sched_d_event(cs, D_RCVBUFREADY);
} }
if (val & W_INT_D_RMR) { /* RMR */ if (val & W_INT_D_RMR) { /* RMR */
W6692_empty_fifo(cs, W_D_FIFO_THRESH); W6692_empty_fifo(cs, W_D_FIFO_THRESH);
...@@ -791,6 +763,7 @@ setup_w6692(struct IsdnCard *card) ...@@ -791,6 +763,7 @@ setup_w6692(struct IsdnCard *card)
id_list[cs->subtyp].card_name, cs->irq, id_list[cs->subtyp].card_name, cs->irq,
cs->hw.w6692.iobase); cs->hw.w6692.iobase);
cs->dc_hw_ops = &w6692_dc_hw_ops;
cs->bc_hw_ops = &w6692_bc_hw_ops; cs->bc_hw_ops = &w6692_bc_hw_ops;
cs->bc_l1_ops = &w6692_bc_l1_ops; cs->bc_l1_ops = &w6692_bc_l1_ops;
cs->DC_Send_Data = &W6692_fill_fifo; cs->DC_Send_Data = &W6692_fill_fifo;
......
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