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)
}
}
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
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) {
/* Here we lost an TX interrupt, so
* 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);
xmit_xdu_b(bcs, reset_xmit);
} else if (stat & HDLC_INT_XPR) {
xmit_xpr_b(bcs);
}
......
......@@ -559,10 +559,16 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
}
}
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
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;
exval = MemReadHSCX(cs, 1, HSCX_EXIR);
if (exval & 0x40) {
if (cs->debug & L1_DEB_WARN)
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX B EXIR %x", exval);
if (bcs->mode == L1_MODE_TRANS)
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);
xmit_xdu_b(bcs, Memhscx_reset_xmit);
}
}
if (val & 0xf8) {
if (cs->debug & L1_DEB_HSCX)
......@@ -597,19 +594,10 @@ Memhscx_int_main(struct IsdnCardState *cs, u_char val)
bcs = cs->bcs;
exval = MemReadHSCX(cs, 0, HSCX_EXIR);
if (exval & 0x40) {
if (cs->debug & L1_DEB_WARN)
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX A EXIR %x", exval);
if (bcs->mode == L1_MODE_TRANS)
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);
xmit_xdu_b(bcs, Memhscx_reset_xmit);
}
}
if (val & 0x04) { // ICA
exval = MemReadHSCX(cs, 0, HSCX_ISTA);
......
......@@ -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
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) {
bcs = cs->bcs + 1;
exval = READHSCX(cs, 1, HSCX_EXIR);
if (exval & 0x40) {
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)
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX B EXIR %x", exval);
if (exval & 0x40) {
xmit_xdu_b(bcs, reset_xmit);
}
}
if (val & 0xf8) {
if (cs->debug & L1_DEB_HSCX)
......@@ -226,17 +226,11 @@ hscx_int_main(struct IsdnCardState *cs, u_char val)
if (val & 0x02) {
bcs = cs->bcs;
exval = READHSCX(cs, 0, HSCX_EXIR);
if (exval & 0x40) {
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)
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HSCX A EXIR %x", exval);
if (exval & 0x40) {
xmit_xdu_b(bcs, reset_xmit);
}
}
if (val & 0x04) {
exval = READHSCX(cs, 0, HSCX_ISTA);
......
......@@ -637,6 +637,13 @@ ipacx_fill_fifo(struct BCState *bcs)
//----------------------------------------------------------
// 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
bch_int(struct IsdnCardState *cs, u_char hscx)
{
......@@ -706,18 +713,11 @@ bch_int(struct IsdnCardState *cs, u_char hscx)
}
if (istab &0x10) { // XPR
xmit_xpr(bcs);
xmit_xpr_b(bcs);
}
if (istab &0x04) { // XDU
if (cs->debug &L1_DEB_WARN)
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
}
xmit_xdu_b(bcs, reset_xmit);
}
}
......
......@@ -159,3 +159,20 @@ xmit_xpr_b(struct BCState *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)
}
}
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
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;
}
if (val & jadeISR_XDU) {
if (cs->debug & L1_DEB_WARN)
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);
}
xmit_xdu_b(bcs, reset_xmit);
}
if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) {
if (cs->debug & L1_DEB_HSCX)
......
......@@ -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
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 */
xmit_xpr(bcs);
xmit_xpr_b(bcs);
}
if (val & W_B_EXI_XDUN) { /* XDUN */
if (cs->debug & L1_DEB_WARN)
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);
}
xmit_xdu_b(bcs, reset_xmit);
}
}
......
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