/*---------------------------------------------------------------------------* * Timer T4 start *---------------------------------------------------------------------------*/ static void T4_start(struct isic_softc *sc) { NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc)); sc->sc_I430T4 = 1; START_TIMER(sc->sc_T4_callout, timer4_expired, sc, hz); }
/*---------------------------------------------------------------------------* * I.430 Timer T3 expire function *---------------------------------------------------------------------------*/ static void timer3_expired(struct isic_softc *sc) { if(sc->sc_I430T3) { NDBGL1(L1_T_ERR, "state = %s", isic_printstate(sc)); sc->sc_I430T3 = 0; /* XXX try some recovery here XXX */ switch(sc->sc_cardtyp) { #if NNISACSX > 0 case CARD_TYPEP_AVMA1PCIV2: isic_isacsx_recover(sc); break; #endif /* NNISACSX > 0 */ default: #if NNISAC > 0 isic_recover(sc); #endif /* NNISAC > 0 */ break; } sc->sc_init_tries++; /* increment retry count */ /*XXX*/ if(sc->sc_init_tries > 4) { int s = splnet(); sc->sc_init_tries = 0; if(sc->sc_obuf2 != NULL) { i4b_Dfreembuf(sc->sc_obuf2); sc->sc_obuf2 = NULL; } if(sc->sc_obuf != NULL) { i4b_Dfreembuf(sc->sc_obuf); sc->sc_obuf = NULL; sc->sc_freeflag = 0; sc->sc_op = NULL; sc->sc_ol = 0; } splx(s); isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_NOL1ACC, 0); } isic_next_state(sc, EV_T3); } else { NDBGL1(L1_T_ERR, "expired without starting it ...."); } }
/*---------------------------------------------------------------------------* * Timer T4 stop *---------------------------------------------------------------------------*/ static void T4_stop(struct isic_softc *sc) { NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc)); if(sc->sc_I430T4) { sc->sc_I430T4 = 0; STOP_TIMER(sc->sc_T4_callout, timer4_expired, sc); } }
/*---------------------------------------------------------------------------* * I.430 Timer T3 stop *---------------------------------------------------------------------------*/ static void T3_stop(struct isic_softc *sc) { NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc)); sc->sc_init_tries = 0; /* init connect retry count */ if(sc->sc_I430T3) { sc->sc_I430T3 = 0; STOP_TIMER(sc->sc_T3_callout, timer3_expired, sc); } }
/*---------------------------------------------------------------------------* * Timer T4 expire function *---------------------------------------------------------------------------*/ static void timer4_expired(struct isic_softc *sc) { if(sc->sc_I430T4) { NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc)); sc->sc_I430T4 = 0; isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_PDEACT, 0); } else { NDBGL1(L1_T_ERR, "expired without starting it ...."); } }
/*---------------------------------------------------------------------------* * execute a layer 1 command *---------------------------------------------------------------------------*/ void isic_isacsx_l1_cmd(struct isic_softc *sc, int command) { u_char cmd; #ifdef I4B_SMP_WORKAROUND /* XXXXXXXXXXXXXXXXXXX */ /* * patch from Wolfgang Helbig: * * Here is a patch that makes i4b work on an SMP: * The card (TELES 16.3) didn't interrupt on an SMP machine. * This is a gross workaround, but anyway it works *and* provides * some information as how to finally fix this problem. */ HSCX_WRITE(0, H_MASK, 0xff); HSCX_WRITE(1, H_MASK, 0xff); ISAC_WRITE(I_MASKD, 0xff); ISAC_WRITE(I_MASK, 0xff); DELAY(100); HSCX_WRITE(0, H_MASK, HSCX_A_IMASK); HSCX_WRITE(1, H_MASK, HSCX_B_IMASK); ISAC_WRITE(I_MASKD, isacsx_imaskd); ISAC_WRITE(I_MASK, isacsx_imask); /* XXXXXXXXXXXXXXXXXXX */ #endif /* I4B_SMP_WORKAROUND */ if(command < 0 || command > CMD_ILL) { NDBGL1(L1_I_ERR, "illegal cmd 0x%x in state %s", command, isic_printstate(sc)); return; } cmd = ISACSX_CIX0_LOW; switch(command) { case CMD_TIM: NDBGL1(L1_I_CICO, "tx TIM in state %s", isic_printstate(sc)); cmd |= (ISACSX_CIX0_CTIM << 4); break; case CMD_RS: NDBGL1(L1_I_CICO, "tx RS in state %s", isic_printstate(sc)); cmd |= (ISACSX_CIX0_CRS << 4); break; case CMD_AR8: NDBGL1(L1_I_CICO, "tx AR8 in state %s", isic_printstate(sc)); cmd |= (ISACSX_CIX0_CAR8 << 4); break; case CMD_AR10: NDBGL1(L1_I_CICO, "tx AR10 in state %s", isic_printstate(sc)); cmd |= (ISACSX_CIX0_CAR10 << 4); break; case CMD_DIU: NDBGL1(L1_I_CICO, "tx DIU in state %s", isic_printstate(sc)); cmd |= (ISACSX_CIX0_CDIU << 4); break; } ISAC_WRITE(I_CIX0, cmd); }
/*---------------------------------------------------------------------------* * ISACSX L1 Indication handler *---------------------------------------------------------------------------*/ static void isic_isacsx_ind_hdlr(register struct isic_softc *sc, int ind) { register int event; switch(ind) { case ISACSX_CIR0_IAI8: NDBGL1(L1_I_CICO, "rx AI8 in state %s", isic_printstate(sc)); if(sc->sc_bustyp == BUS_TYPE_IOM2) isic_isacsx_l1_cmd(sc, CMD_AR8); event = EV_INFO48; isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE); break; case ISACSX_CIR0_IAI10: NDBGL1(L1_I_CICO, "rx AI10 in state %s", isic_printstate(sc)); if(sc->sc_bustyp == BUS_TYPE_IOM2) isic_isacsx_l1_cmd(sc, CMD_AR10); event = EV_INFO410; isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE); break; case ISACSX_CIR0_IRSY: NDBGL1(L1_I_CICO, "rx RSY in state %s", isic_printstate(sc)); event = EV_RSY; break; case ISACSX_CIR0_IPU: NDBGL1(L1_I_CICO, "rx PU in state %s", isic_printstate(sc)); event = EV_PU; break; case ISACSX_CIR0_IDR: NDBGL1(L1_I_CICO, "rx DR in state %s", isic_printstate(sc)); isic_isacsx_l1_cmd(sc, CMD_DIU); event = EV_DR; break; case ISACSX_CIR0_IDID: NDBGL1(L1_I_CICO, "rx DID in state %s", isic_printstate(sc)); event = EV_INFO0; isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_IDLE); break; case ISACSX_CIR0_IDIS: NDBGL1(L1_I_CICO, "rx DIS in state %s", isic_printstate(sc)); event = EV_DIS; break; case ISACSX_CIR0_IEI: NDBGL1(L1_I_CICO, "rx EI in state %s", isic_printstate(sc)); isic_isacsx_l1_cmd(sc, CMD_DIU); event = EV_EI; break; case ISACSX_CIR0_IARD: NDBGL1(L1_I_CICO, "rx ARD in state %s", isic_printstate(sc)); event = EV_INFO2; break; case ISACSX_CIR0_ITI: NDBGL1(L1_I_CICO, "rx TI in state %s", isic_printstate(sc)); event = EV_INFO0; break; case ISACSX_CIR0_IATI: NDBGL1(L1_I_CICO, "rx ATI in state %s", isic_printstate(sc)); event = EV_INFO0; break; case ISACSX_CIR0_ISD: NDBGL1(L1_I_CICO, "rx SD in state %s", isic_printstate(sc)); event = EV_INFO0; break; default: NDBGL1(L1_I_ERR, "UNKNOWN Indication 0x%x in state %s", ind, isic_printstate(sc)); event = EV_INFO0; break; } isic_next_state(sc, event); }
/*---------------------------------------------------------------------------* * * L2 -> L1: PH-DATA-REQUEST * ========================= * * parms: * token softc of physical driver * m mbuf containing L2 frame to be sent out * freeflag MBUF_FREE: free mbuf here after having sent * it out * MBUF_DONTFREE: mbuf is freed by Layer 2 * returns: * ==0 fail, nothing sent out * !=0 ok, frame sent out * *---------------------------------------------------------------------------*/ static int isic_std_ph_data_req(isdn_layer1token token, struct mbuf *m, int freeflag) { struct isic_softc *sc = (struct isic_softc*)token; u_char cmd; int s; if (m == NULL) /* failsafe */ return (0); s = splnet(); if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */ { NDBGL1(L1_I_ERR, "still in state F3!"); isic_std_ph_activate_req(token); } if(sc->sc_state & ISAC_TX_ACTIVE) { if(sc->sc_obuf2 == NULL) { sc->sc_obuf2 = m; /* save mbuf ptr */ if(freeflag) sc->sc_freeflag2 = 1; /* IRQ must mfree */ else sc->sc_freeflag2 = 0; /* IRQ must not mfree */ NDBGL1(L1_I_MSG, "using 2nd ISAC TX buffer, state = %s", isic_printstate(sc)); if(sc->sc_trace & TRACE_D_TX) { i4b_trace_hdr hdr; hdr.type = TRC_CH_D; hdr.dir = FROM_TE; hdr.count = ++sc->sc_trace_dcount; isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, m->m_len, m->m_data); } splx(s); return(1); } NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", isic_printstate(sc)); if(freeflag == MBUF_FREE) i4b_Dfreembuf(m); splx(s); return (0); } if(sc->sc_trace & TRACE_D_TX) { i4b_trace_hdr hdr; hdr.type = TRC_CH_D; hdr.dir = FROM_TE; hdr.count = ++sc->sc_trace_dcount; isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, m->m_len, m->m_data); } sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */ NDBGL1(L1_I_MSG, "ISAC_TX_ACTIVE set"); sc->sc_freeflag = 0; /* IRQ must NOT mfree */ ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */ if(m->m_len > ISAC_FIFO_LEN) /* message > 32 bytes ? */ { sc->sc_obuf = m; /* save mbuf ptr */ sc->sc_op = m->m_data + ISAC_FIFO_LEN; /* ptr for irq hdl */ sc->sc_ol = m->m_len - ISAC_FIFO_LEN; /* length for irq hdl */ if(freeflag) sc->sc_freeflag = 1; /* IRQ must mfree */ cmd = ISAC_CMDR_XTF; } else { sc->sc_obuf = NULL; sc->sc_op = NULL; sc->sc_ol = 0; if(freeflag) i4b_Dfreembuf(m); cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME; } ISAC_WRITE(I_CMDR, cmd); ISACCMDRWRDELAY(); splx(s); return(1); }
/*---------------------------------------------------------------------------* * * L2 -> L1: PH-DATA-REQUEST * ========================= * * parms: * unit physical interface unit number * m mbuf containing L2 frame to be sent out * freeflag MBUF_FREE: free mbuf here after having sent * it out * MBUF_DONTFREE: mbuf is freed by Layer 2 * returns: * ==0 fail, nothing sent out * !=0 ok, frame sent out * *---------------------------------------------------------------------------*/ int isic_ph_data_req(int unit, struct mbuf *m, int freeflag) { u_char cmd; int s; struct l1_softc *sc = &l1_sc[unit]; #ifdef NOTDEF NDBGL1(L1_PRIM, "unit %d, freeflag=%d", unit, freeflag); #endif if(m == NULL) /* failsafe */ return (0); s = SPLI4B(); if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */ { NDBGL1(L1_I_ERR, "still in state F3!"); isic_ph_activate_req(unit); } if(sc->sc_state & ISAC_TX_ACTIVE) { if(sc->sc_obuf2 == NULL) { sc->sc_obuf2 = m; /* save mbuf ptr */ if(freeflag) sc->sc_freeflag2 = 1; /* IRQ must mfree */ else sc->sc_freeflag2 = 0; /* IRQ must not mfree */ NDBGL1(L1_I_MSG, "using 2nd ISAC TX buffer, state = %s", isic_printstate(sc)); if(sc->sc_trace & TRACE_D_TX) { i4b_trace_hdr_t hdr; hdr.unit = L0ISICUNIT(unit); hdr.type = TRC_CH_D; hdr.dir = FROM_TE; hdr.count = ++sc->sc_trace_dcount; MICROTIME(hdr.time); i4b_l1_trace_ind(&hdr, m->m_len, m->m_data); } splx(s); return(1); } NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", isic_printstate(sc)); if(freeflag == MBUF_FREE) i4b_Dfreembuf(m); splx(s); return (0); } if(sc->sc_trace & TRACE_D_TX) { i4b_trace_hdr_t hdr; hdr.unit = L0ISICUNIT(unit); hdr.type = TRC_CH_D; hdr.dir = FROM_TE; hdr.count = ++sc->sc_trace_dcount; MICROTIME(hdr.time); i4b_l1_trace_ind(&hdr, m->m_len, m->m_data); } sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */ NDBGL1(L1_I_MSG, "ISAC_TX_ACTIVE set"); sc->sc_freeflag = 0; /* IRQ must NOT mfree */ ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */ if(m->m_len > ISAC_FIFO_LEN) /* message > 32 bytes ? */ { sc->sc_obuf = m; /* save mbuf ptr */ sc->sc_op = m->m_data + ISAC_FIFO_LEN; /* ptr for irq hdl */ sc->sc_ol = m->m_len - ISAC_FIFO_LEN; /* length for irq hdl */ if(freeflag) sc->sc_freeflag = 1; /* IRQ must mfree */ cmd = ISAC_CMDR_XTF; } else { sc->sc_obuf = NULL; sc->sc_op = NULL; sc->sc_ol = 0; if(freeflag) i4b_Dfreembuf(m); cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME; } ISAC_WRITE(I_CMDR, cmd); ISACCMDRWRDELAY(); splx(s); return(1); }