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 @@
#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);
......
......@@ -303,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);
}
}
//----------------------------------------------------------
......@@ -370,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;
......@@ -381,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
......
......@@ -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);
......
......@@ -414,6 +414,33 @@ 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)
{
......@@ -421,12 +448,13 @@ recv_empty_fifo_b(struct BCState *bcs, int count)
struct IsdnCardState *cs = bcs->cs;
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 (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;
return;
}
p = bcs->rcvbuf + bcs->rcvidx;
bcs->rcvidx += 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
recv_rme_b(struct BCState *bcs)
{
......@@ -467,6 +517,7 @@ recv_rme_b(struct BCState *bcs)
sched_b_event(bcs, B_RCVBUFREADY);
}
/* RPF - receive pull full */
static inline void
recv_rpf_b(struct BCState *bcs)
{
......
......@@ -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)
{
......@@ -181,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
......@@ -310,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;
......@@ -335,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);
......@@ -791,6 +763,7 @@ 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;
......
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