Commit 6fa2aea0 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN/HiSax: Separate out some common code from B-Channel receive

Now that a lot of duplicated xmit code is shared, start on the receive
path: Share code which reads a fragment from the FIFO and merges it
into the currently received frame.
parent 05cb64ba
...@@ -262,18 +262,15 @@ hdlc_empty_fifo(struct BCState *bcs, int count) ...@@ -262,18 +262,15 @@ hdlc_empty_fifo(struct BCState *bcs, int count)
register u_int *ptr; register u_int *ptr;
u8 *p; u8 *p;
u8 idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1; u8 idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
int cnt=0; int cnt = 0;
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) p = recv_empty_fifo_b(bcs, count);
debugl1(cs, "hdlc_empty_fifo %d", count); if (!p) {
if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
return; return;
} }
ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
bcs->hw.hdlc.rcvidx += count; ptr = (u_int *) p;
if (cs->subtyp == AVM_FRITZ_PCI) { if (cs->subtyp == AVM_FRITZ_PCI) {
outl(idx, cs->hw.avm.cfg_reg + 4); outl(idx, cs->hw.avm.cfg_reg + 4);
while (cnt < count) { while (cnt < count) {
......
...@@ -446,36 +446,26 @@ MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u8 data) ...@@ -446,36 +446,26 @@ MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u8 data)
static void static void
Memhscx_empty_fifo(struct BCState *bcs, int count) Memhscx_empty_fifo(struct BCState *bcs, int count)
{ {
u8 *ptr; u8 *p;
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
unsigned long flags;
int cnt; int cnt;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) p = recv_empty_fifo_b(bcs, count);
debugl1(cs, "hscx_empty_fifo"); if (!p) {
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); MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
bcs->hw.hscx.rcvidx = 0;
return; return;
} }
spin_lock_irqsave(&diva_lock, flags);
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
cnt = count; cnt = count;
while (cnt--) while (cnt--)
*ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0); *p++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0);
MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); 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) { if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog; char *t = bcs->blog;
t += sprintf(t, "hscx_empty_fifo %c cnt %d", t += sprintf(t, "hscx_empty_fifo %c cnt %d",
bcs->hw.hscx.hscx ? 'B' : 'A', count); bcs->hw.hscx.hscx ? 'B' : 'A', count);
QuickHex(t, ptr, count); QuickHex(t, p, count);
debugl1(cs, bcs->blog); debugl1(cs, bcs->blog);
} }
} }
...@@ -535,18 +525,18 @@ Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) ...@@ -535,18 +525,18 @@ Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
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->hw.hscx.rcvidx - 1) > 0) { if ((count = bcs->rcvidx - 1) > 0) {
if (cs->debug & L1_DEB_HSCX_FIFO) if (cs->debug & L1_DEB_HSCX_FIFO)
debugl1(cs, "HX Frame %d", count); debugl1(cs, "HX Frame %d", count);
if (!(skb = dev_alloc_skb(count))) if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "HSCX: receive out of memory\n"); printk(KERN_WARNING "HSCX: receive out of memory\n");
else { else {
memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); memcpy(skb_put(skb, count), bcs->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
} }
} }
} }
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY); sched_b_event(bcs, B_RCVBUFREADY);
} }
if (val & 0x40) { /* RPF */ if (val & 0x40) { /* RPF */
...@@ -556,10 +546,10 @@ Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) ...@@ -556,10 +546,10 @@ Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
if (!(skb = dev_alloc_skb(fifo_size))) if (!(skb = dev_alloc_skb(fifo_size)))
printk(KERN_WARNING "HiSax: receive out of memory\n"); printk(KERN_WARNING "HiSax: receive out of memory\n");
else { else {
memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); memcpy(skb_put(skb, fifo_size), bcs->rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
} }
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY); sched_b_event(bcs, B_RCVBUFREADY);
} }
} }
......
...@@ -424,10 +424,10 @@ close_elsastate(struct BCState *bcs) ...@@ -424,10 +424,10 @@ close_elsastate(struct BCState *bcs)
{ {
modehscx(bcs, 0, bcs->channel); modehscx(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) { if (bcs->rcvbuf) {
if (bcs->mode != L1_MODE_MODEM) if (bcs->mode != L1_MODE_MODEM)
kfree(bcs->hw.hscx.rcvbuf); kfree(bcs->rcvbuf);
bcs->hw.hscx.rcvbuf = NULL; bcs->rcvbuf = NULL;
} }
skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue); skb_queue_purge(&bcs->squeue);
...@@ -602,14 +602,14 @@ setstack_elsa(struct PStack *st, struct BCState *bcs) ...@@ -602,14 +602,14 @@ setstack_elsa(struct PStack *st, struct BCState *bcs)
case L1_MODE_MODEM: case L1_MODE_MODEM:
bcs->mode = L1_MODE_MODEM; bcs->mode = L1_MODE_MODEM;
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { 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->rqueue);
skb_queue_head_init(&bcs->squeue); skb_queue_head_init(&bcs->squeue);
} }
bcs->tx_skb = NULL; bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0; bcs->event = 0;
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
bcs->tx_cnt = 0; bcs->tx_cnt = 0;
bcs->cs->hw.elsa.bcs = bcs; bcs->cs->hw.elsa.bcs = bcs;
st->l1.l2l1 = modem_l2l1; st->l1.l2l1 = modem_l2l1;
......
...@@ -850,9 +850,14 @@ unsigned int __init ...@@ -850,9 +850,14 @@ unsigned int __init
return(send); return(send);
} }
static struct bc_l1_ops hfcd_l1_ops = {
.fill_fifo = hfc_fill_fifo,
};
void __init void __init
init2bds0(struct IsdnCardState *cs) init2bds0(struct IsdnCardState *cs)
{ {
cs->bc_l1_ops = &hfcd_l1_ops;
cs->setstack_d = setstack_hfcd; cs->setstack_d = setstack_hfcd;
cs->dbusytimer.function = (void *) hfc_dbusy_timer; cs->dbusytimer.function = (void *) hfc_dbusy_timer;
cs->dbusytimer.data = (long) cs; cs->dbusytimer.data = (long) cs;
......
...@@ -350,8 +350,6 @@ struct l3_process { ...@@ -350,8 +350,6 @@ struct l3_process {
struct hscx_hw { struct hscx_hw {
int hscx; int hscx;
int rcvidx;
u8 *rcvbuf; /* B-Channel receive Buffer */
u8 tsaxr0; u8 tsaxr0;
u8 tsaxr1; u8 tsaxr1;
}; };
...@@ -479,10 +477,12 @@ struct amd7930_hw { ...@@ -479,10 +477,12 @@ struct amd7930_hw {
struct BCState { struct BCState {
int channel; int channel;
int mode; int mode;
long Flag; /* long req'd for set_bit --RR */ long Flag;
struct IsdnCardState *cs; struct IsdnCardState *cs;
int tx_cnt; /* B-Channel transmit counter */ int rcvidx;
struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ 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 rqueue; /* B-Channel receive queue */
struct sk_buff_head squeue; /* B-Channel send queue */ struct sk_buff_head squeue; /* B-Channel send queue */
struct sk_buff_head cmpl_queue; /* B-Channel send complete queue */ struct sk_buff_head cmpl_queue; /* B-Channel send complete queue */
......
...@@ -165,9 +165,9 @@ close_hscxstate(struct BCState *bcs) ...@@ -165,9 +165,9 @@ close_hscxstate(struct BCState *bcs)
{ {
modehscx(bcs, 0, bcs->channel); modehscx(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) { if (bcs->rcvbuf) {
kfree(bcs->hw.hscx.rcvbuf); kfree(bcs->rcvbuf);
bcs->hw.hscx.rcvbuf = NULL; bcs->rcvbuf = NULL;
} }
if (bcs->blog) { if (bcs->blog) {
kfree(bcs->blog); kfree(bcs->blog);
...@@ -188,7 +188,7 @@ int ...@@ -188,7 +188,7 @@ int
open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs) open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
{ {
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { if (!(bcs->rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: No memory for hscx.rcvbuf\n"); "HiSax: No memory for hscx.rcvbuf\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
...@@ -198,8 +198,8 @@ open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs) ...@@ -198,8 +198,8 @@ open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: No memory for bcs->blog\n"); "HiSax: No memory for bcs->blog\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
kfree(bcs->hw.hscx.rcvbuf); kfree(bcs->rcvbuf);
bcs->hw.hscx.rcvbuf = NULL; bcs->rcvbuf = NULL;
return (2); return (2);
} }
skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->rqueue);
...@@ -209,7 +209,7 @@ open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs) ...@@ -209,7 +209,7 @@ open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
bcs->tx_skb = NULL; bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0; bcs->event = 0;
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
bcs->tx_cnt = 0; bcs->tx_cnt = 0;
return (0); return (0);
} }
...@@ -228,6 +228,8 @@ setstack_hscx(struct PStack *st, struct BCState *bcs) ...@@ -228,6 +228,8 @@ setstack_hscx(struct PStack *st, struct BCState *bcs)
return (0); return (0);
} }
static void hscx_fill_fifo(struct BCState *bcs);
static struct bc_l1_ops hscx_l1_ops = { static struct bc_l1_ops hscx_l1_ops = {
.fill_fifo = hscx_fill_fifo, .fill_fifo = hscx_fill_fifo,
}; };
......
...@@ -38,4 +38,3 @@ extern int HscxVersion(struct IsdnCardState *cs, char *s); ...@@ -38,4 +38,3 @@ extern int HscxVersion(struct IsdnCardState *cs, char *s);
extern void modehscx(struct BCState *bcs, int mode, int bc); extern void modehscx(struct BCState *bcs, int mode, int bc);
extern void inithscxisac(struct IsdnCardState *cs); extern void inithscxisac(struct IsdnCardState *cs);
extern void hscx_int_main(struct IsdnCardState *cs, u8 val); extern void hscx_int_main(struct IsdnCardState *cs, u8 val);
extern void hscx_fill_fifo(struct BCState *bcs);
...@@ -50,71 +50,42 @@ WriteHSCXCMDR(struct BCState *bcs, u8 data) ...@@ -50,71 +50,42 @@ WriteHSCXCMDR(struct BCState *bcs, u8 data)
static void static void
hscx_empty_fifo(struct BCState *bcs, int count) hscx_empty_fifo(struct BCState *bcs, int count)
{ {
u8 *ptr; u8 *p;
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) p = recv_empty_fifo_b(bcs, count);
debugl1(cs, "hscx_empty_fifo"); if (!p) {
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); WriteHSCXCMDR(bcs, 0x80);
bcs->hw.hscx.rcvidx = 0;
return; return;
} }
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; hscx_read_fifo(bcs, p, count);
bcs->hw.hscx.rcvidx += count;
hscx_read_fifo(bcs, ptr, count);
WriteHSCXCMDR(bcs, 0x80); WriteHSCXCMDR(bcs, 0x80);
if (cs->debug & L1_DEB_HSCX_FIFO) { if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog; char *t = bcs->blog;
t += sprintf(t, "hscx_empty_fifo %c cnt %d", t += sprintf(t, "hscx_empty_fifo %c cnt %d",
bcs->hw.hscx.hscx ? 'B' : 'A', count); bcs->hw.hscx.hscx ? 'B' : 'A', count);
QuickHex(t, ptr, count); QuickHex(t, p, count);
debugl1(cs, bcs->blog); debugl1(cs, bcs->blog);
} }
} }
void static void
hscx_fill_fifo(struct BCState *bcs) hscx_fill_fifo(struct BCState *bcs)
{ {
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
int more, count; int more, count;
int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; 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) p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
return; if (!p)
if (bcs->tx_skb->len <= 0)
return; 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); waitforXFW(bcs);
ptr = bcs->tx_skb->data; hscx_write_fifo(bcs, p, count);
skb_pull(bcs->tx_skb, count);
bcs->tx_cnt -= count;
bcs->count += count;
hscx_write_fifo(bcs, ptr, count);
WriteHSCXCMDR(bcs, more ? 0x8 : 0xa); 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 static inline void
...@@ -161,18 +132,18 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) ...@@ -161,18 +132,18 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
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->hw.hscx.rcvidx - 1) > 0) { if ((count = bcs->rcvidx - 1) > 0) {
if (cs->debug & L1_DEB_HSCX_FIFO) if (cs->debug & L1_DEB_HSCX_FIFO)
debugl1(cs, "HX Frame %d", count); debugl1(cs, "HX Frame %d", count);
if (!(skb = dev_alloc_skb(count))) if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "HSCX: receive out of memory\n"); printk(KERN_WARNING "HSCX: receive out of memory\n");
else { else {
memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); memcpy(skb_put(skb, count), bcs->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
} }
} }
} }
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY); sched_b_event(bcs, B_RCVBUFREADY);
} }
if (val & 0x40) { /* RPF */ if (val & 0x40) { /* RPF */
...@@ -182,10 +153,10 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) ...@@ -182,10 +153,10 @@ hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
if (!(skb = dev_alloc_skb(fifo_size))) if (!(skb = dev_alloc_skb(fifo_size)))
printk(KERN_WARNING "HiSax: receive out of memory\n"); printk(KERN_WARNING "HiSax: receive out of memory\n");
else { else {
memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); memcpy(skb_put(skb, fifo_size), bcs->rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
} }
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY); sched_b_event(bcs, B_RCVBUFREADY);
} }
} }
......
...@@ -44,7 +44,7 @@ static inline void dch_int(struct IsdnCardState *cs); ...@@ -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_setstack(struct PStack *st, struct IsdnCardState *cs);
static void __devinit dch_init(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_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_int(struct IsdnCardState *cs, u8 hscx);
static void bch_mode(struct BCState *bcs, int mode, int bc); static void bch_mode(struct BCState *bcs, int mode, int bc);
static void bch_close_state(struct BCState *bcs); static void bch_close_state(struct BCState *bcs);
...@@ -501,40 +501,29 @@ bch_l2l1(struct PStack *st, int pr, void *arg) ...@@ -501,40 +501,29 @@ bch_l2l1(struct PStack *st, int pr, void *arg)
// Read B channel fifo to receive buffer // Read B channel fifo to receive buffer
//---------------------------------------------------------- //----------------------------------------------------------
static void static void
bch_empty_fifo(struct BCState *bcs, int count) ipacx_bc_empty_fifo(struct BCState *bcs, int count)
{ {
u8 *ptr, hscx; u8 *p, hscx;
struct IsdnCardState *cs; struct IsdnCardState *cs = bcs->cs;
int cnt; int cnt;
cs = bcs->cs; hscx = bcs->hw.hscx.hscx;
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 p = recv_empty_fifo_b(bcs, count);
if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { if (!p) {
if (cs->debug &L1_DEB_WARN) ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC
debugl1(cs, "bch_empty_fifo() incoming packet too large");
ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC
bcs->hw.hscx.rcvidx = 0;
return; return;
} }
// Read data uninterruptible
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
cnt = count; cnt = count;
while (cnt--) *ptr++ = ipacx_bc_read_reg(bcs, IPACX_RFIFOB); while (cnt--) *p++ = ipacx_bc_read_reg(bcs, IPACX_RFIFOB);
ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; p -= count;
bcs->hw.hscx.rcvidx += count;
if (cs->debug &L1_DEB_HSCX_FIFO) { if (cs->debug &L1_DEB_HSCX_FIFO) {
char *t = bcs->blog; char *t = bcs->blog;
t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count); t += sprintf(t, "ipacx_empty_fifo() B-%d cnt %d", hscx, count);
QuickHex(t, ptr, count); QuickHex(t, p, count);
debugl1(cs, bcs->blog); debugl1(cs, bcs->blog);
} }
} }
...@@ -542,8 +531,8 @@ bch_empty_fifo(struct BCState *bcs, int count) ...@@ -542,8 +531,8 @@ bch_empty_fifo(struct BCState *bcs, int count)
//---------------------------------------------------------- //----------------------------------------------------------
// Fill buffer to transmit FIFO // Fill buffer to transmit FIFO
//---------------------------------------------------------- //----------------------------------------------------------
void static void
ipacx_fill_fifo(struct BCState *bcs) ipacx_bc_fill_fifo(struct BCState *bcs)
{ {
int more, count; int more, count;
unsigned char *p; unsigned char *p;
...@@ -598,34 +587,34 @@ bch_int(struct IsdnCardState *cs, u8 hscx) ...@@ -598,34 +587,34 @@ bch_int(struct IsdnCardState *cs, u8 hscx)
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;
bch_empty_fifo(bcs, count); ipacx_bc_empty_fifo(bcs, count);
if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { if ((count = bcs->rcvidx - 1) > 0) {
if (cs->debug &L1_DEB_HSCX_FIFO) if (cs->debug &L1_DEB_HSCX_FIFO)
debugl1(cs, "bch_int Frame %d", count); debugl1(cs, "bch_int Frame %d", count);
if (!(skb = dev_alloc_skb(count))) if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n"); printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n");
else { else {
memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); memcpy(skb_put(skb, count), bcs->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
} }
} }
} }
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY); sched_b_event(bcs, B_RCVBUFREADY);
} }
if (istab &0x40) { // RPF if (istab &0x40) { // RPF
bch_empty_fifo(bcs, B_FIFO_SIZE); ipacx_bc_empty_fifo(bcs, B_FIFO_SIZE);
if (bcs->mode == L1_MODE_TRANS) { // queue every chunk if (bcs->mode == L1_MODE_TRANS) { // queue every chunk
// receive transparent audio data // receive transparent audio data
if (!(skb = dev_alloc_skb(B_FIFO_SIZE))) if (!(skb = dev_alloc_skb(B_FIFO_SIZE)))
printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n"); printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n");
else { else {
memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE); memcpy(skb_put(skb, B_FIFO_SIZE), bcs->rcvbuf, B_FIFO_SIZE);
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
} }
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY); sched_b_event(bcs, B_RCVBUFREADY);
} }
} }
...@@ -700,9 +689,9 @@ bch_close_state(struct BCState *bcs) ...@@ -700,9 +689,9 @@ bch_close_state(struct BCState *bcs)
{ {
bch_mode(bcs, 0, bcs->channel); bch_mode(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) { if (bcs->rcvbuf) {
kfree(bcs->hw.hscx.rcvbuf); kfree(bcs->rcvbuf);
bcs->hw.hscx.rcvbuf = NULL; bcs->rcvbuf = NULL;
} }
if (bcs->blog) { if (bcs->blog) {
kfree(bcs->blog); kfree(bcs->blog);
...@@ -724,7 +713,7 @@ static int ...@@ -724,7 +713,7 @@ static int
bch_open_state(struct IsdnCardState *cs, struct BCState *bcs) bch_open_state(struct IsdnCardState *cs, struct BCState *bcs)
{ {
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { if (!(bcs->rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax open_bchstate(): No memory for hscx.rcvbuf\n"); "HiSax open_bchstate(): No memory for hscx.rcvbuf\n");
clear_bit(BC_FLG_INIT, &bcs->Flag); clear_bit(BC_FLG_INIT, &bcs->Flag);
...@@ -734,8 +723,8 @@ bch_open_state(struct IsdnCardState *cs, struct BCState *bcs) ...@@ -734,8 +723,8 @@ bch_open_state(struct IsdnCardState *cs, struct BCState *bcs)
printk(KERN_WARNING printk(KERN_WARNING
"HiSax open_bchstate: No memory for bcs->blog\n"); "HiSax open_bchstate: No memory for bcs->blog\n");
clear_bit(BC_FLG_INIT, &bcs->Flag); clear_bit(BC_FLG_INIT, &bcs->Flag);
kfree(bcs->hw.hscx.rcvbuf); kfree(bcs->rcvbuf);
bcs->hw.hscx.rcvbuf = NULL; bcs->rcvbuf = NULL;
return (2); return (2);
} }
skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->rqueue);
...@@ -744,7 +733,7 @@ bch_open_state(struct IsdnCardState *cs, struct BCState *bcs) ...@@ -744,7 +733,7 @@ bch_open_state(struct IsdnCardState *cs, struct BCState *bcs)
bcs->tx_skb = NULL; bcs->tx_skb = NULL;
clear_bit(BC_FLG_BUSY, &bcs->Flag); clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0; bcs->event = 0;
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
bcs->tx_cnt = 0; bcs->tx_cnt = 0;
return (0); return (0);
} }
...@@ -821,7 +810,7 @@ clear_pending_ints(struct IsdnCardState *cs) ...@@ -821,7 +810,7 @@ clear_pending_ints(struct IsdnCardState *cs)
} }
static struct bc_l1_ops ipacx_bc_l1_ops = { static struct bc_l1_ops ipacx_bc_l1_ops = {
.fill_fifo = ipacx_fill_fifo, .fill_fifo = ipacx_bc_fill_fifo,
}; };
//---------------------------------------------------------- //----------------------------------------------------------
......
...@@ -157,6 +157,5 @@ ...@@ -157,6 +157,5 @@
extern void init_ipacx(struct IsdnCardState *cs, int part); extern void init_ipacx(struct IsdnCardState *cs, int part);
extern void interrupt_ipacx(struct IsdnCardState *cs); extern void interrupt_ipacx(struct IsdnCardState *cs);
extern void ipacx_fill_fifo(struct BCState *bcs);
#endif #endif
...@@ -413,3 +413,23 @@ xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more) ...@@ -413,3 +413,23 @@ xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more)
} }
return p; return p;
} }
static inline u8 *
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, "hscx_empty_fifo");
if (bcs->rcvidx + count > HSCX_BUFMAX) {
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;
return p;
}
...@@ -201,9 +201,9 @@ close_jadestate(struct BCState *bcs) ...@@ -201,9 +201,9 @@ close_jadestate(struct BCState *bcs)
{ {
modejade(bcs, 0, bcs->channel); modejade(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) { if (bcs->rcvbuf) {
kfree(bcs->hw.hscx.rcvbuf); kfree(bcs->rcvbuf);
bcs->hw.hscx.rcvbuf = NULL; bcs->rcvbuf = NULL;
} }
if (bcs->blog) { if (bcs->blog) {
kfree(bcs->blog); kfree(bcs->blog);
...@@ -223,7 +223,7 @@ static int ...@@ -223,7 +223,7 @@ static int
open_jadestate(struct IsdnCardState *cs, struct BCState *bcs) open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
{ {
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { if (!(bcs->rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: No memory for hscx.rcvbuf\n"); "HiSax: No memory for hscx.rcvbuf\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
...@@ -233,8 +233,8 @@ open_jadestate(struct IsdnCardState *cs, struct BCState *bcs) ...@@ -233,8 +233,8 @@ open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: No memory for bcs->blog\n"); "HiSax: No memory for bcs->blog\n");
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
kfree(bcs->hw.hscx.rcvbuf); kfree(bcs->rcvbuf);
bcs->hw.hscx.rcvbuf = NULL; bcs->rcvbuf = NULL;
return (2); return (2);
} }
skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->rqueue);
...@@ -243,7 +243,7 @@ open_jadestate(struct IsdnCardState *cs, struct BCState *bcs) ...@@ -243,7 +243,7 @@ open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
bcs->tx_skb = NULL; bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0; bcs->event = 0;
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
bcs->tx_cnt = 0; bcs->tx_cnt = 0;
return (0); return (0);
} }
...@@ -263,6 +263,8 @@ setstack_jade(struct PStack *st, struct BCState *bcs) ...@@ -263,6 +263,8 @@ setstack_jade(struct PStack *st, struct BCState *bcs)
return (0); return (0);
} }
static void jade_fill_fifo(struct BCState *bcs);
static struct bc_l1_ops jade_l1_ops = { static struct bc_l1_ops jade_l1_ops = {
.fill_fifo = jade_fill_fifo, .fill_fifo = jade_fill_fifo,
}; };
......
...@@ -132,7 +132,5 @@ extern void jade_sched_event(struct BCState *bcs, int event); ...@@ -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 modejade(struct BCState *bcs, int mode, int bc);
extern void initjade(struct IsdnCardState *cs); extern void initjade(struct IsdnCardState *cs);
extern void jade_int_main(struct IsdnCardState *cs, u_char val, int jade); extern void jade_int_main(struct IsdnCardState *cs, u_char val, int jade);
extern void jade_fill_fifo(struct BCState *bcs);
#endif /* __JADE_H__ */ #endif /* __JADE_H__ */
...@@ -47,34 +47,28 @@ WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u8 data) ...@@ -47,34 +47,28 @@ WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u8 data)
static void static void
jade_empty_fifo(struct BCState *bcs, int count) jade_empty_fifo(struct BCState *bcs, int count)
{ {
u8 *ptr; u8 *p;
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) p = recv_empty_fifo_b(bcs, count);
debugl1(cs, "jade_empty_fifo"); if (!p) {
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); WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
bcs->hw.hscx.rcvidx = 0;
return; return;
} }
ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; jade_read_fifo(bcs, p, count);
bcs->hw.hscx.rcvidx += count;
jade_read_fifo(bcs, ptr, count);
WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
if (cs->debug & L1_DEB_HSCX_FIFO) { if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog; char *t = bcs->blog;
t += sprintf(t, "jade_empty_fifo %c cnt %d", t += sprintf(t, "jade_empty_fifo %c cnt %d",
bcs->hw.hscx.hscx ? 'B' : 'A', count); bcs->hw.hscx.hscx ? 'B' : 'A', count);
QuickHex(t, ptr, count); QuickHex(t, p, count);
debugl1(cs, bcs->blog); debugl1(cs, bcs->blog);
} }
} }
void static void
jade_fill_fifo(struct BCState *bcs) jade_fill_fifo(struct BCState *bcs)
{ {
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
...@@ -125,18 +119,18 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade) ...@@ -125,18 +119,18 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
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->hw.hscx.rcvidx - 1) > 0) { if ((count = bcs->rcvidx - 1) > 0) {
if (cs->debug & L1_DEB_HSCX_FIFO) if (cs->debug & L1_DEB_HSCX_FIFO)
debugl1(cs, "HX Frame %d", count); debugl1(cs, "HX Frame %d", count);
if (!(skb = dev_alloc_skb(count))) if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A")); printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A"));
else { else {
memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); memcpy(skb_put(skb, count), bcs->rcvbuf, count);
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
} }
} }
} }
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY); sched_b_event(bcs, B_RCVBUFREADY);
} }
if (val & 0x40) { /* RPF */ if (val & 0x40) { /* RPF */
...@@ -146,10 +140,10 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade) ...@@ -146,10 +140,10 @@ jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
if (!(skb = dev_alloc_skb(fifo_size))) if (!(skb = dev_alloc_skb(fifo_size)))
printk(KERN_WARNING "HiSax: receive out of memory\n"); printk(KERN_WARNING "HiSax: receive out of memory\n");
else { else {
memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); memcpy(skb_put(skb, fifo_size), bcs->rcvbuf, fifo_size);
skb_queue_tail(&bcs->rqueue, skb); skb_queue_tail(&bcs->rqueue, skb);
} }
bcs->hw.hscx.rcvidx = 0; bcs->rcvidx = 0;
sched_b_event(bcs, B_RCVBUFREADY); sched_b_event(bcs, B_RCVBUFREADY);
} }
} }
......
...@@ -221,29 +221,22 @@ W6692_fill_fifo(struct IsdnCardState *cs) ...@@ -221,29 +221,22 @@ W6692_fill_fifo(struct IsdnCardState *cs)
static void static void
W6692B_empty_fifo(struct BCState *bcs, int count) W6692B_empty_fifo(struct BCState *bcs, int count)
{ {
u8 *ptr; u8 *p;
struct IsdnCardState *cs = bcs->cs; struct IsdnCardState *cs = bcs->cs;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) p = recv_empty_fifo_b(bcs, count);
debugl1(cs, "W6692B_empty_fifo"); if (!p) {
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); w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
bcs->hw.w6692.rcvidx = 0;
return; return;
} }
ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx; READW6692BFIFO(cs, bcs->channel, p, count);
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); 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) { if (cs->debug & L1_DEB_HSCX_FIFO) {
char *t = bcs->blog; char *t = bcs->blog;
t += sprintf(t, "W6692B_empty_fifo %c cnt %d", t += sprintf(t, "W6692B_empty_fifo %c cnt %d",
bcs->channel + '1', count); bcs->channel + '1', count);
QuickHex(t, ptr, count); QuickHex(t, p, count);
debugl1(cs, bcs->blog); debugl1(cs, bcs->blog);
} }
} }
......
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