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