Commit c0dcd234 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN/HiSax: Share XDU handling for B-Channel

Again, the hardware is similar enough to use a shared function,
only the method of resetting the transmitter needs to be specified.
parent 54e36513
...@@ -375,6 +375,17 @@ hdlc_fill_fifo(struct BCState *bcs) ...@@ -375,6 +375,17 @@ hdlc_fill_fifo(struct BCState *bcs)
} }
} }
static void
reset_xmit(struct BCState *bcs)
{
bcs->hw.hdlc.ctrl.sr.xml = 0;
bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
write_ctrl(bcs, 1);
bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
write_ctrl(bcs, 1);
hdlc_fill_fifo(bcs);
}
static inline void static inline void
HDLC_irq(struct BCState *bcs, u_int stat) HDLC_irq(struct BCState *bcs, u_int stat)
{ {
...@@ -423,17 +434,7 @@ HDLC_irq(struct BCState *bcs, u_int stat) ...@@ -423,17 +434,7 @@ HDLC_irq(struct BCState *bcs, u_int stat)
} }
} }
if (stat & HDLC_INT_XDU) { if (stat & HDLC_INT_XDU) {
/* Here we lost an TX interrupt, so xmit_xdu_b(bcs, reset_xmit);
* restart transmitting the whole frame. */
if (bcs->cs->debug & L1_DEB_WARN)
debugl1(bcs->cs, "ch%d XDU", bcs->channel);
xmit_restart_b(bcs);
bcs->hw.hdlc.ctrl.sr.xml = 0;
bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
write_ctrl(bcs, 1);
bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
write_ctrl(bcs, 1);
hdlc_fill_fifo(bcs);
} else if (stat & HDLC_INT_XPR) { } else if (stat & HDLC_INT_XPR) {
xmit_xpr_b(bcs); xmit_xpr_b(bcs);
} }
......
...@@ -559,10 +559,16 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) ...@@ -559,10 +559,16 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
} }
} }
if (val & 0x10) { if (val & 0x10) {
xmit_xpr(bcs);/* XPR */ xmit_xpr_b(bcs);/* XPR */
} }
} }
static void
Memhscx_reset_xmit(struct BCState *bcs)
{
MemWriteHSCXCMDR(bcs->cs, bcs->hw.hscx.hscx, 0x01);
}
static inline void static inline void
Memhscx_int_main(struct IsdnCardState *cs, u_char val) Memhscx_int_main(struct IsdnCardState *cs, u_char val)
{ {
...@@ -574,19 +580,10 @@ Memhscx_int_main(struct IsdnCardState *cs, u_char val) ...@@ -574,19 +580,10 @@ Memhscx_int_main(struct IsdnCardState *cs, u_char val)
bcs = cs->bcs + 1; bcs = cs->bcs + 1;
exval = MemReadHSCX(cs, 1, HSCX_EXIR); exval = MemReadHSCX(cs, 1, HSCX_EXIR);
if (exval & 0x40) { if (exval & 0x40) {
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX B EXIR %x", exval); debugl1(cs, "HSCX B EXIR %x", exval);
if (bcs->mode == L1_MODE_TRANS) xmit_xdu_b(bcs, Memhscx_reset_xmit);
Memhscx_fill_fifo(bcs); }
else {
/* Here we lost an TX interrupt, so
* restart transmitting the whole frame.
*/
xmit_restart_b(bcs);
MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
}
} else if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX B EXIR %x", exval);
} }
if (val & 0xf8) { if (val & 0xf8) {
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
...@@ -597,19 +594,10 @@ Memhscx_int_main(struct IsdnCardState *cs, u_char val) ...@@ -597,19 +594,10 @@ Memhscx_int_main(struct IsdnCardState *cs, u_char val)
bcs = cs->bcs; bcs = cs->bcs;
exval = MemReadHSCX(cs, 0, HSCX_EXIR); exval = MemReadHSCX(cs, 0, HSCX_EXIR);
if (exval & 0x40) { if (exval & 0x40) {
if (cs->debug & L1_DEB_WARN) if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX A EXIR %x", exval); debugl1(cs, "HSCX A EXIR %x", exval);
if (bcs->mode == L1_MODE_TRANS) xmit_xdu_b(bcs, Memhscx_reset_xmit);
Memhscx_fill_fifo(bcs); }
else {
/* Here we lost an TX interrupt, so
* restart transmitting the whole frame.
*/
xmit_restart_b(bcs);
MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
}
} else if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX A EXIR %x", exval);
} }
if (val & 0x04) { // ICA if (val & 0x04) { // ICA
exval = MemReadHSCX(cs, 0, HSCX_ISTA); exval = MemReadHSCX(cs, 0, HSCX_ISTA);
......
...@@ -195,6 +195,12 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) ...@@ -195,6 +195,12 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
} }
} }
static void
reset_xmit(struct BCState *bcs)
{
WriteHSCXCMDR(bcs->cs, bcs->hw.hscx.hscx, 0x01);
}
static inline void static inline void
hscx_int_main(struct IsdnCardState *cs, u_char val) hscx_int_main(struct IsdnCardState *cs, u_char val)
{ {
...@@ -206,17 +212,11 @@ hscx_int_main(struct IsdnCardState *cs, u_char val) ...@@ -206,17 +212,11 @@ hscx_int_main(struct IsdnCardState *cs, u_char val)
if (val & 0x01) { if (val & 0x01) {
bcs = cs->bcs + 1; bcs = cs->bcs + 1;
exval = READHSCX(cs, 1, HSCX_EXIR); exval = READHSCX(cs, 1, HSCX_EXIR);
if (exval & 0x40) { if (cs->debug & L1_DEB_HSCX)
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX B EXIR %x", exval);
if (bcs->mode == L1_MODE_TRANS)
hscx_fill_fifo(bcs);
else {
xmit_restart_b(bcs);
WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
}
} else if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX B EXIR %x", exval); debugl1(cs, "HSCX B EXIR %x", exval);
if (exval & 0x40) {
xmit_xdu_b(bcs, reset_xmit);
}
} }
if (val & 0xf8) { if (val & 0xf8) {
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
...@@ -226,17 +226,11 @@ hscx_int_main(struct IsdnCardState *cs, u_char val) ...@@ -226,17 +226,11 @@ hscx_int_main(struct IsdnCardState *cs, u_char val)
if (val & 0x02) { if (val & 0x02) {
bcs = cs->bcs; bcs = cs->bcs;
exval = READHSCX(cs, 0, HSCX_EXIR); exval = READHSCX(cs, 0, HSCX_EXIR);
if (exval & 0x40) { if (cs->debug & L1_DEB_HSCX)
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX A EXIR %x", exval);
if (bcs->mode == L1_MODE_TRANS)
hscx_fill_fifo(bcs);
else {
xmit_restart_b(bcs);
WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
}
} else if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX A EXIR %x", exval); debugl1(cs, "HSCX A EXIR %x", exval);
if (exval & 0x40) {
xmit_xdu_b(bcs, reset_xmit);
}
} }
if (val & 0x04) { if (val & 0x04) {
exval = READHSCX(cs, 0, HSCX_ISTA); exval = READHSCX(cs, 0, HSCX_ISTA);
......
...@@ -637,6 +637,13 @@ ipacx_fill_fifo(struct BCState *bcs) ...@@ -637,6 +637,13 @@ ipacx_fill_fifo(struct BCState *bcs)
//---------------------------------------------------------- //----------------------------------------------------------
// B channel interrupt handler // B channel interrupt handler
//---------------------------------------------------------- //----------------------------------------------------------
static void
reset_xmit(struct BCState *bcs)
{
bcs->cs->BC_Write_Reg(bcs->cs, bcs->hw.hscx.hscx, IPACX_CMDRB, 0x01); // XRES
}
static void static void
bch_int(struct IsdnCardState *cs, u_char hscx) bch_int(struct IsdnCardState *cs, u_char hscx)
{ {
...@@ -706,18 +713,11 @@ bch_int(struct IsdnCardState *cs, u_char hscx) ...@@ -706,18 +713,11 @@ bch_int(struct IsdnCardState *cs, u_char hscx)
} }
if (istab &0x10) { // XPR if (istab &0x10) { // XPR
xmit_xpr(bcs); xmit_xpr_b(bcs);
} }
if (istab &0x04) { // XDU if (istab &0x04) { // XDU
if (cs->debug &L1_DEB_WARN) xmit_xdu_b(bcs, reset_xmit);
debugl1(cs, "bch_int() B-%d XDU error", hscx);
if (bcs->mode == L1_MODE_TRANS) {
ipacx_fill_fifo(bcs);
} else {
xmit_restart_b(bcs);
cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01); // XRES
}
} }
} }
......
...@@ -159,3 +159,20 @@ xmit_xpr_b(struct BCState *bcs) ...@@ -159,3 +159,20 @@ xmit_xpr_b(struct BCState *bcs)
xmit_ready_b(bcs); xmit_ready_b(bcs);
} }
/* XDU - transmit data underrun */
/* called with the card lock held */
static inline void
xmit_xdu_b(struct BCState *bcs, void (*reset_xmit)(struct BCState *bcs))
{
struct IsdnCardState *cs = bcs->cs;
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX %c EXIR XDU", 'A' + bcs->channel);
if (bcs->mode == L1_MODE_TRANS) {
cs->BC_Send_Data(bcs);
} else {
xmit_restart_b(bcs);
reset_xmit(bcs);
}
}
...@@ -181,10 +181,16 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) ...@@ -181,10 +181,16 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
} }
} }
if (val & 0x10) { /* XPR */ if (val & 0x10) { /* XPR */
xmit_xpr(bcs); xmit_xpr_b(bcs);
} }
} }
static void
reset_xmit(struct BCState *bcs)
{
WriteJADECMDR(bcs->cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
}
static inline void static inline void
jade_int_main(struct IsdnCardState *cs, u_char val, int jade) jade_int_main(struct IsdnCardState *cs, u_char val, int jade)
{ {
...@@ -197,19 +203,7 @@ jade_int_main(struct IsdnCardState *cs, u_char val, int jade) ...@@ -197,19 +203,7 @@ jade_int_main(struct IsdnCardState *cs, u_char val, int jade)
val &= ~jadeISR_RFO; val &= ~jadeISR_RFO;
} }
if (val & jadeISR_XDU) { if (val & jadeISR_XDU) {
if (cs->debug & L1_DEB_WARN) xmit_xdu_b(bcs, reset_xmit);
debugl1(cs, "JADE %c EXIR %x", 'A'+jade, val);
/* relevant in HDLC mode only */
/* don't reset XPR here */
if (bcs->mode == L1_MODE_TRANSPARENT)
jade_fill_fifo(bcs);
else {
/* Here we lost an TX interrupt, so
* restart transmitting the whole frame.
*/
xmit_restart_b(bcs);
WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
}
} }
if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) { if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) {
if (cs->debug & L1_DEB_HSCX) if (cs->debug & L1_DEB_HSCX)
......
...@@ -278,6 +278,13 @@ W6692B_fill_fifo(struct BCState *bcs) ...@@ -278,6 +278,13 @@ W6692B_fill_fifo(struct BCState *bcs)
} }
} }
static void
reset_xmit(struct BCState *bcs)
{
bcs->cs->BC_Write_Reg(bcs->cs, bcs->channel, W_B_CMDR,
W_B_CMDR_XRST | W_B_CMDR_RACT);
}
static void static void
W6692B_interrupt(struct IsdnCardState *cs, u_char bchan) W6692B_interrupt(struct IsdnCardState *cs, u_char bchan)
{ {
...@@ -340,20 +347,10 @@ W6692B_interrupt(struct IsdnCardState *cs, u_char bchan) ...@@ -340,20 +347,10 @@ W6692B_interrupt(struct IsdnCardState *cs, u_char bchan)
} }
} }
if (val & W_B_EXI_XFR) { /* XFR */ if (val & W_B_EXI_XFR) { /* XFR */
xmit_xpr(bcs); xmit_xpr_b(bcs);
} }
if (val & W_B_EXI_XDUN) { /* XDUN */ if (val & W_B_EXI_XDUN) { /* XDUN */
if (cs->debug & L1_DEB_WARN) xmit_xdu_b(bcs, reset_xmit);
debugl1(cs, "W6692 B EXIR %x", val);
if (bcs->mode == L1_MODE_TRANSPARENT)
W6692B_fill_fifo(bcs);
else {
/* Here we lost an TX interrupt, so
* restart transmitting the whole frame.
*/
xmit_restart_b(bcs);
cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
}
} }
} }
......
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