int iavc_send(capi_softc_t *capi_sc, struct mbuf *m) { iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx; if (sc->sc_state != IAVC_UP) { printf("iavc%d: attempt to send before device up\n", sc->sc_unit); if (m->m_next) i4b_Bfreembuf(m->m_next); i4b_Dfreembuf(m); return (ENXIO); } if (_IF_QFULL(&sc->sc_txq)) { #if defined (__FreeBSD__) && __FreeBSD__ > 4 _IF_DROP(&sc->sc_txq); #else IF_DROP(&sc->sc_txq); #endif printf("iavc%d: tx overflow, message dropped\n", sc->sc_unit); if (m->m_next) i4b_Bfreembuf(m->m_next); i4b_Dfreembuf(m); } else { _IF_ENQUEUE(&sc->sc_txq, m); iavc_start_tx(sc); } return 0; }
int iavc_send(capi_softc_t *capi_sc, struct mbuf *m) { iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx; if (sc->sc_state != IAVC_UP) { aprint_error_dev(&sc->sc_dev, "attempt to send before device up\n"); if (m->m_next) i4b_Bfreembuf(m->m_next); i4b_Dfreembuf(m); return (ENXIO); } if (IF_QFULL(&sc->sc_txq)) { IF_DROP(&sc->sc_txq); aprint_error_dev(&sc->sc_dev, "tx overflow, message dropped\n"); if (m->m_next) i4b_Bfreembuf(m->m_next); i4b_Dfreembuf(m); } else { IF_ENQUEUE(&sc->sc_txq, m); iavc_start_tx(sc); } return 0; }
/*---------------------------------------------------------------------------* * i4bputqueue_hipri - put message into front of queue to userland *---------------------------------------------------------------------------*/ void i4bputqueue_hipri(struct mbuf *m) { if(!openflag) { i4b_Dfreembuf(m); return; } crit_enter(); if(IF_QFULL(&i4b_rdqueue)) { struct mbuf *m1; IF_DEQUEUE(&i4b_rdqueue, m1); i4b_Dfreembuf(m1); NDBGL4(L4_ERR, "ERROR, queue full, removing entry!"); } IF_PREPEND(&i4b_rdqueue, m); crit_exit(); if(readflag) { readflag = 0; wakeup((caddr_t) &i4b_rdqueue); } KNOTE(&kq_rd_info.ki_note, 0); }
/*---------------------------------------------------------------------------* * 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 ...."); } }
/*---------------------------------------------------------------------------* * i4bread - device driver read routine *---------------------------------------------------------------------------*/ PDEVSTATIC int i4bread(dev_t dev, struct uio *uio, int ioflag) { struct mbuf *m; int x; int error = 0; if(minor(dev)) return(ENODEV); while(IF_QEMPTY(&i4b_rdqueue)) { x = splimp(); readflag = 1; splx(x); tsleep((caddr_t) &i4b_rdqueue, (PZERO + 1) | PCATCH, "bird", 0); } x = splimp(); IF_DEQUEUE(&i4b_rdqueue, m); splx(x); if(m && m->m_len) error = uiomove(m->m_data, m->m_len, uio); else error = EIO; if(m) i4b_Dfreembuf(m); return(error); }
/*---------------------------------------------------------------------------* * got s or i frame, check if valid ack for last sent frame *---------------------------------------------------------------------------*/ void i4b_rxd_ack(l2_softc_t *l2sc, int nr) { #ifdef NOTDEF NDBGL2(L2_ERROR, "N(R)=%d, UA=%d, V(R)=%d, V(S)=%d, V(A)=%d", nr, l2sc->ua_num, l2sc->vr, l2sc->vs, l2sc->va); #endif if(l2sc->ua_num != UA_EMPTY) { CRIT_VAR; CRIT_BEG; M128DEC(nr); if(l2sc->ua_num != nr) NDBGL2(L2_ERROR, "((N(R)-1)=%d) != (UA=%d) !!!", nr, l2sc->ua_num); i4b_Dfreembuf(l2sc->ua_frame); l2sc->ua_num = UA_EMPTY; CRIT_END; } }
/*---------------------------------------------------------------------------* * got s or i frame, check if valid ack for last sent frame *---------------------------------------------------------------------------*/ void i4b_rxd_ack(l2_softc_t *l2sc, struct isdn_l3_driver *drv, int nr) { #ifdef NOTDEF NDBGL2(L2_ERROR, "N(R)=%d, UA=%d, V(R)=%d, V(S)=%d, V(A)=%d", nr, l2sc->ua_num, l2sc->vr, l2sc->vs, l2sc->va); #endif if(l2sc->ua_num != UA_EMPTY) { int s; s = splnet(); M128DEC(nr); if(l2sc->ua_num != nr) NDBGL2(L2_ERROR, "((N(R)-1)=%d) != (UA=%d) !!!", nr, l2sc->ua_num); i4b_Dfreembuf(l2sc->ua_frame); l2sc->ua_num = UA_EMPTY; splx(s); } }
/*---------------------------------------------------------------------------* * i4bread - device driver read routine *---------------------------------------------------------------------------*/ PDEVSTATIC int i4bread(struct dev_read_args *ap) { cdev_t dev = ap->a_head.a_dev; struct mbuf *m; int error = 0; if (minor(dev)) return(ENODEV); crit_enter(); while(IF_QEMPTY(&i4b_rdqueue)) { readflag = 1; error = tsleep((caddr_t) &i4b_rdqueue, PCATCH, "bird", 0); if (error != 0) { crit_exit(); return error; } } IF_DEQUEUE(&i4b_rdqueue, m); crit_exit(); if(m && m->m_len) error = uiomove(m->m_data, m->m_len, ap->a_uio); else error = EIO; if(m) i4b_Dfreembuf(m); return(error); }
/*---------------------------------------------------------------------------* * i4bread - device driver read routine *---------------------------------------------------------------------------*/ PDEVSTATIC int isdnread(dev_t dev, struct uio *uio, int ioflag) { struct mbuf *m; int x; int error = 0; if(minor(dev)) return(ENODEV); x = splnet(); while(IF_QEMPTY(&i4b_rdqueue)) { readflag = 1; error = tsleep((void *) &i4b_rdqueue, (PZERO + 1) | PCATCH, "bird", 0); if (error != 0) { splx(x); return error; } } IF_DEQUEUE(&i4b_rdqueue, m); splx(x); if(m && m->m_len) error = uiomove(m->m_data, m->m_len, uio); else error = EIO; if(m) i4b_Dfreembuf(m); return(error); }
/*---------------------------------------------------------------------------* * got s or i frame, check if valid ack for last sent frame *---------------------------------------------------------------------------*/ void i4b_rxd_ack(l2_softc_t *l2sc, int nr) { #ifdef NOTDEF DBGL2(L2_ERROR, "i4b_rxd_ack", ("N(R)=%d, UA=%d, V(R)=%d, V(S)=%d, V(A)=%d\n", nr, l2sc->ua_num, l2sc->vr, l2sc->vs, l2sc->va)); #endif if(l2sc->ua_num != UA_EMPTY) { int s; M128DEC(nr); if(l2sc->ua_num != nr) DBGL2(L2_ERROR, "i4b_rxd_ack", ("((N(R)-1)=%d) != (UA=%d) !!!\n", nr, l2sc->ua_num)); s = SPLI4B(); i4b_Dfreembuf(l2sc->ua_frame); l2sc->ua_num = UA_EMPTY; splx(s); } }
/*---------------------------------------------------------------------------* * routine CLEAR EXCEPTION CONDITIONS (Q.921 03/93 page 83) *---------------------------------------------------------------------------*/ void i4b_clear_exception_conditions(l2_softc_t *l2sc) { CRIT_VAR; CRIT_BEG; /*XXX -------------------------------------------------------------- */ /*XXX is this really appropriate here or should it moved elsewhere ? */ i4b_Dcleanifq(&l2sc->i_queue); if(l2sc->ua_num != UA_EMPTY) { i4b_Dfreembuf(l2sc->ua_frame); l2sc->ua_num = UA_EMPTY; } /*XXX -------------------------------------------------------------- */ l2sc->peer_busy = 0; l2sc->rej_excpt = 0; l2sc->own_busy = 0; l2sc->ack_pend = 0; CRIT_END; }
/*---------------------------------------------------------------------------* * I.430 Timer T3 expire function *---------------------------------------------------------------------------*/ static void timer3_expired(struct l1_softc *sc) { if(sc->sc_I430T3) { NDBGL1(L1_T_ERR, "state = %s", ifpnp_printstate(sc)); sc->sc_I430T3 = 0; /* XXX try some recovery here XXX */ ifpnp_recover(sc); sc->sc_init_tries++; /* increment retry count */ /*XXX*/ if(sc->sc_init_tries > 4) { int s = SPLI4B(); 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); i4b_l1_mph_status_ind(L0IFPNPUNIT(sc->sc_unit), STI_NOL1ACC, 0, NULL); } ifpnp_next_state(sc, EV_T3); } else { NDBGL1(L1_T_ERR, "expired without starting it ...."); } }
/*---------------------------------------------------------------------------* * dl_unit_data_ind - process a rx'd U-frame got from layer 2 *---------------------------------------------------------------------------*/ int i4b_dl_unit_data_ind(int unit, struct mbuf *m) { #ifdef NOTDEF DBGL2(L2_PRIM, "DL-UNIT-DATA-IND", ("unit %d\n",unit)); #endif i4b_decode_q931(unit, m->m_len, m->m_data); i4b_Dfreembuf(m); return(0); }
static void iavc_start_tx(iavc_softc_t *sc) { struct mbuf *m; u_int32_t txlen; /* If device has put us on hold, punt. */ if (sc->sc_blocked) { return; } /* If using DMA and transmitter busy, punt. */ if (sc->sc_dma && (sc->sc_csr & EN_TX_TC_INT)) { return; } /* Else, see if we have messages to send. */ IF_DEQUEUE(&sc->sc_txq, m); if (!m) { return; } /* Have message, will send. */ if (CAPIMSG_LEN(m->m_data)) { /* A proper CAPI message, possibly with B3 data */ txlen = iavc_tx_capimsg(sc, m); } else { /* A board control message to be sent as is */ txlen = iavc_tx_ctrlmsg(sc, m); } if (m->m_next) { i4b_Bfreembuf(m->m_next); m->m_next = NULL; } i4b_Dfreembuf(m); /* Kick DMA into motion if applicable */ if (sc->sc_dma) { txlen = (txlen + 3) & ~3; bus_dmamap_sync(sc->dmat, sc->tx_map, 0, txlen, BUS_DMASYNC_PREWRITE); AMCC_WRITE(sc, AMCC_TXPTR, sc->tx_map->dm_segs[0].ds_addr); AMCC_WRITE(sc, AMCC_TXLEN, txlen); sc->sc_csr |= EN_TX_TC_INT; if (!sc->sc_intr) AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); } }
/*---------------------------------------------------------------------------* * i4bputqueue_hipri - put message into front of queue to userland *---------------------------------------------------------------------------*/ void i4bputqueue_hipri(struct mbuf *m) { int x; if(!openflag) { i4b_Dfreembuf(m); return; } x = splimp(); if(IF_QFULL(&i4b_rdqueue)) { struct mbuf *m1; IF_DEQUEUE(&i4b_rdqueue, m1); i4b_Dfreembuf(m1); DBGL4(L4_ERR, "i4bputqueue", ("ERROR, queue full, removing entry!\n")); } IF_PREPEND(&i4b_rdqueue, m); splx(x); if(readflag) { readflag = 0; wakeup((caddr_t) &i4b_rdqueue); } if(selflag) { selflag = 0; selwakeup(&select_rd_info); } }
/*---------------------------------------------------------------------------* * i4bputqueue_hipri - put message into front of queue to userland *---------------------------------------------------------------------------*/ void i4bputqueue_hipri(struct mbuf *m) { int x; if(!openflag) { i4b_Dfreembuf(m); return; } x = splnet(); if(IF_QFULL(&i4b_rdqueue)) { struct mbuf *m1; IF_DEQUEUE(&i4b_rdqueue, m1); i4b_Dfreembuf(m1); NDBGL4(L4_ERR, "ERROR, queue full, removing entry!"); } IF_PREPEND(&i4b_rdqueue, m); splx(x); if(readflag) { readflag = 0; wakeup((void *) &i4b_rdqueue); } if(selflag) { selflag = 0; selnotify(&select_rd_info, 0, 0); } }
/*---------------------------------------------------------------------------* * L2 -> L1: PH-DATA-REQUEST (D-Channel) * * NOTE: We may get called here from ihfc_hdlc_Dread or isac_hdlc_Dread * via the upper layers. *---------------------------------------------------------------------------*/ static int ihfc_ph_data_req(int unit, struct mbuf *m, int freeflag) { ihfc_sc_t *sc = &ihfc_softc[unit]; u_char chan = 0; HFC_VAR; if (!m) return 0; HFC_BEG; if(S_PHSTATE != 3) { NDBGL1(L1_PRIM, "L1 was not running: " "ihfc_ph_activate_req(unit = %d)!", unit); ihfc_ph_activate_req(unit); } /* "Allow" I-frames (-hp) */ if (freeflag == MBUF_DONTFREE) m = m_copypacket(m, M_DONTWAIT); if (!_IF_QFULL(&S_IFQUEUE) && m) { IF_ENQUEUE(&S_IFQUEUE, m); ihfc_B_start(unit, chan); /* (recycling) */ } else { NDBGL1(L1_ERROR, "No frame out (unit = %d)", unit); if (m) i4b_Dfreembuf(m); HFC_END; return 0; } if (S_INTR_ACTIVE) S_INT_S1 |= 0x04; HFC_END; return 1; }
/*---------------------------------------------------------------------------* * ISACSX interrupt service routine *---------------------------------------------------------------------------*/ void isic_isacsx_irq(struct isic_softc *sc, int ista) { register u_char c = 0; register u_char istad = 0; NDBGL1(L1_F_MSG, "%s: ista = 0x%02x", device_xname(&sc->sc_dev), ista); /* was it an HDLC interrupt ? */ if (ista & ISACSX_ISTA_ICD) { istad = ISAC_READ(I_ISTAD); NDBGL1(L1_F_MSG, "%s: istad = 0x%02x", device_xname(&sc->sc_dev), istad); if(istad & (ISACSX_ISTAD_RFO|ISACSX_ISTAD_XMR|ISACSX_ISTAD_XDU)) { /* not really EXIR, but very similar */ c |= isic_isacsx_exir_hdlr(sc, istad); } } if(istad & ISACSX_ISTAD_RME) /* receive message end */ { register int rest; u_char rsta; /* get rx status register */ rsta = ISAC_READ(I_RSTAD); /* Check for Frame and CRC valid */ if((rsta & ISACSX_RSTAD_MASK) != (ISACSX_RSTAD_VFR|ISACSX_RSTAD_CRC)) { int error = 0; if(!(rsta & ISACSX_RSTAD_VFR)) /* VFR error */ { error++; NDBGL1(L1_I_ERR, "%s: Frame not valid error", device_xname(&sc->sc_dev)); } if(!(rsta & ISACSX_RSTAD_CRC)) /* CRC error */ { error++; NDBGL1(L1_I_ERR, "%s: CRC error", device_xname(&sc->sc_dev)); } if(rsta & ISACSX_RSTAD_RDO) /* ReceiveDataOverflow */ { error++; NDBGL1(L1_I_ERR, "%s: Data Overrun error", device_xname(&sc->sc_dev)); } if(rsta & ISACSX_RSTAD_RAB) /* ReceiveABorted */ { error++; NDBGL1(L1_I_ERR, "%s: Receive Aborted error", device_xname(&sc->sc_dev)); } if(error == 0) NDBGL1(L1_I_ERR, "%s: RME unknown error, RSTAD = 0x%02x!", device_xname(&sc->sc_dev), rsta); i4b_Dfreembuf(sc->sc_ibuf); c |= ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES; sc->sc_ibuf = NULL; sc->sc_ib = NULL; sc->sc_ilen = 0; ISAC_WRITE(I_CMDRD, ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES); return; } rest = (ISAC_READ(I_RBCLD) & (ISACSX_FIFO_LEN-1)); if(rest == 0) rest = ISACSX_FIFO_LEN; if(sc->sc_ibuf == NULL) { if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL) sc->sc_ib = sc->sc_ibuf->m_data; else panic("isic_isacsx_irq: RME, i4b_Dgetmbuf returns NULL!\n"); sc->sc_ilen = 0; } if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest)) { ISAC_RDFIFO(sc->sc_ib, rest); /* the last byte contains status, strip it */ sc->sc_ilen += rest - 1; sc->sc_ibuf->m_pkthdr.len = sc->sc_ibuf->m_len = sc->sc_ilen; if(sc->sc_trace & TRACE_D_RX) { i4b_trace_hdr hdr; memset(&hdr, 0, sizeof hdr); hdr.type = TRC_CH_D; hdr.dir = FROM_NT; hdr.count = ++sc->sc_trace_dcount; isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data); } c |= ISACSX_CMDRD_RMC; if(sc->sc_intr_valid == ISIC_INTR_VALID && (((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S)) { isdn_layer2_data_ind(&sc->sc_l2, sc->sc_l3token, sc->sc_ibuf); } else { i4b_Dfreembuf(sc->sc_ibuf); } } else { NDBGL1(L1_I_ERR, "RME, input buffer overflow!"); i4b_Dfreembuf(sc->sc_ibuf); c |= ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES; } sc->sc_ibuf = NULL; sc->sc_ib = NULL; sc->sc_ilen = 0; } if(istad & ISACSX_ISTAD_RPF) /* receive fifo full */ { if(sc->sc_ibuf == NULL) { if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL) sc->sc_ib= sc->sc_ibuf->m_data; else panic("isic_isacsx_irq: RPF, i4b_Dgetmbuf returns NULL!\n"); sc->sc_ilen = 0; } if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISACSX_FIFO_LEN)) { ISAC_RDFIFO(sc->sc_ib, ISACSX_FIFO_LEN); sc->sc_ilen += ISACSX_FIFO_LEN; sc->sc_ib += ISACSX_FIFO_LEN; c |= ISACSX_CMDRD_RMC; } else { NDBGL1(L1_I_ERR, "RPF, input buffer overflow!"); i4b_Dfreembuf(sc->sc_ibuf); sc->sc_ibuf = NULL; sc->sc_ib = NULL; sc->sc_ilen = 0; c |= ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES; } } if(istad & ISACSX_ISTAD_XPR) /* transmit fifo empty (XPR bit set) */ { if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL)) { sc->sc_freeflag = sc->sc_freeflag2; sc->sc_obuf = sc->sc_obuf2; sc->sc_op = sc->sc_obuf->m_data; sc->sc_ol = sc->sc_obuf->m_len; sc->sc_obuf2 = NULL; #ifdef NOTDEF printf("ob2=%x, op=%x, ol=%d, f=%d #", sc->sc_obuf, sc->sc_op, sc->sc_ol, sc->sc_state); #endif } else { #ifdef NOTDEF printf("ob=%x, op=%x, ol=%d, f=%d #", sc->sc_obuf, sc->sc_op, sc->sc_ol, sc->sc_state); #endif } if(sc->sc_obuf) { ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISACSX_FIFO_LEN)); if(sc->sc_ol > ISACSX_FIFO_LEN) /* length > 32 ? */ { sc->sc_op += ISACSX_FIFO_LEN; /* bufferptr+32 */ sc->sc_ol -= ISACSX_FIFO_LEN; /* length - 32 */ c |= ISACSX_CMDRD_XTF; /* set XTF bit */ } else { if(sc->sc_freeflag) { i4b_Dfreembuf(sc->sc_obuf); sc->sc_freeflag = 0; } sc->sc_obuf = NULL; sc->sc_op = NULL; sc->sc_ol = 0; c |= ISACSX_CMDRD_XTF | ISACSX_CMDRD_XME; } } else { sc->sc_state &= ~ISAC_TX_ACTIVE; } } if(ista & ISACSX_ISTA_CIC) /* channel status change CISQ */ { register u_char ci; /* get command/indication rx register*/ ci = ISAC_READ(I_CIR0); /* C/I code change IRQ (flag already cleared by CIR0 read) */ if(ci & ISACSX_CIR0_CIC0) isic_isacsx_ind_hdlr(sc, (ci >> 4) & 0xf); } if(c) { ISAC_WRITE(I_CMDRD, c); } }
static int iavc_receive(iavc_softc_t *sc, u_int8_t *dmabuf, int b3data) { struct mbuf *m; u_int32_t ApplId, Length; /* * byte 0x21 = RECEIVE_MESSAGE * dword ApplId * dword length * ... CAPI msg * * --or-- * * byte 0x22 = RECEIVE_DATA_B3_IND * dword ApplId * dword length * ... CAPI msg * dword datalen * ... B3 data */ if (sc->sc_dma) { dmabuf = amcc_get_word(dmabuf, &ApplId); dmabuf = amcc_get_word(dmabuf, &Length); } else { ApplId = iavc_get_word(sc); Length = iavc_get_slice(sc, sc->sc_recvbuf); dmabuf = sc->sc_recvbuf; } m = i4b_Dgetmbuf(Length); if (!m) { aprint_error_dev(&sc->sc_dev, "can't get memory for receive\n"); return (ENOMEM); } memcpy(mtod(m, u_int8_t*), dmabuf, Length); #if 0 { u_int8_t *p = mtod(m, u_int8_t*); int len = 0; printf("%s: applid=%d, len=%d\n", device_xname(&sc->sc_dev), ApplId, Length); while (len < m->m_len) { printf(" %02x", p[len]); if (len && (len % 16) == 0) printf("\n"); len++; } if (len % 16) printf("\n"); } #endif if (b3data) { if (sc->sc_dma) { dmabuf = amcc_get_word(dmabuf + Length, &Length); } else { Length = iavc_get_slice(sc, sc->sc_recvbuf); dmabuf = sc->sc_recvbuf; } m->m_next = i4b_Bgetmbuf(Length); if (!m->m_next) { aprint_error_dev(&sc->sc_dev, "can't get memory for receive\n"); i4b_Dfreembuf(m); return (ENOMEM); } memcpy(mtod(m->m_next, u_int8_t*), dmabuf, Length); } capi_ll_receive(&sc->sc_capi, m); return 0; }
/*---------------------------------------------------------------------------* * process a received U-frame *---------------------------------------------------------------------------*/ void i4b_rxd_u_frame(int unit, struct mbuf *m) { l2_softc_t *l2sc = &l2_softc[unit]; u_char *ptr = m->m_data; int sapi = GETSAPI(*(ptr + OFF_SAPI)); int tei = GETTEI(*(ptr + OFF_TEI)); int pfbit = GETUPF(*(ptr + OFF_CNTL)); switch(*(ptr + OFF_CNTL) & ~UPFBIT) { /* commands */ case SABME: if((l2sc->tei_valid == TEI_VALID) && (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) { l2sc->stat.rx_sabme++; NDBGL2(L2_U_MSG, "SABME, sapi = %d, tei = %d", sapi, tei); l2sc->rxd_PF = pfbit; i4b_next_l2state(l2sc, EV_RXSABME); } i4b_Dfreembuf(m); break; case UI: if(sapi == SAPI_L2M && tei == GROUP_TEI && *(ptr + OFF_MEI) == MEI) { /* layer 2 management (SAPI = 63) */ l2sc->stat.rx_tei++; i4b_tei_rxframe(unit, m); } else if(sapi == SAPI_CCP && tei == GROUP_TEI) { /* call control (SAPI = 0) */ l2sc->stat.rx_ui++; /* strip ui header */ m_adj(m, UI_HDR_LEN); /* to upper layer */ DL_Unit_Data_Ind(unit, m); } else { l2sc->stat.err_rx_badui++; NDBGL2(L2_U_ERR, "unknown UI frame!"); i4b_Dfreembuf(m); } break; case DISC: if((l2sc->tei_valid == TEI_VALID) && (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) { l2sc->stat.rx_disc++; NDBGL2(L2_U_MSG, "DISC, sapi = %d, tei = %d", sapi, tei); l2sc->rxd_PF = pfbit; i4b_next_l2state(l2sc, EV_RXDISC); } i4b_Dfreembuf(m); break; case XID: if((l2sc->tei_valid == TEI_VALID) && (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) { l2sc->stat.rx_xid++; NDBGL2(L2_U_MSG, "XID, sapi = %d, tei = %d", sapi, tei); } i4b_Dfreembuf(m); break; /* responses */ case DM: if((l2sc->tei_valid == TEI_VALID) && (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) { l2sc->stat.rx_dm++; NDBGL2(L2_U_MSG, "DM, sapi = %d, tei = %d", sapi, tei); i4b_print_frame(m->m_len, m->m_data); l2sc->rxd_PF = pfbit; i4b_next_l2state(l2sc, EV_RXDM); } i4b_Dfreembuf(m); break; case UA: if((l2sc->tei_valid == TEI_VALID) && (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) { l2sc->stat.rx_ua++; NDBGL2(L2_U_MSG, "UA, sapi = %d, tei = %d", sapi, tei); l2sc->rxd_PF = pfbit; i4b_next_l2state(l2sc, EV_RXUA); } i4b_Dfreembuf(m); break; case FRMR: if((l2sc->tei_valid == TEI_VALID) && (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) { l2sc->stat.rx_frmr++; NDBGL2(L2_U_MSG, "FRMR, sapi = %d, tei = %d", sapi, tei); l2sc->rxd_PF = pfbit; i4b_next_l2state(l2sc, EV_RXFRMR); } i4b_Dfreembuf(m); break; default: if((l2sc->tei_valid == TEI_VALID) && (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) { NDBGL2(L2_U_ERR, "UNKNOWN TYPE ERROR, sapi = %d, tei = %d, frame = ", sapi, tei); i4b_print_frame(m->m_len, m->m_data); } else { NDBGL2(L2_U_ERR, "not mine - UNKNOWN TYPE ERROR, sapi = %d, tei = %d, frame = ", sapi, tei); i4b_print_frame(m->m_len, m->m_data); } l2sc->stat.err_rx_badui++; i4b_Dfreembuf(m); break; } }
/*---------------------------------------------------------------------------* * ISAC interrupt service routine *---------------------------------------------------------------------------*/ void ifpnp_isac_irq(struct l1_softc *sc, int ista) { u_char c = 0; NDBGL1(L1_F_MSG, "unit %d: ista = 0x%02x", sc->sc_unit, ista); if(ista & ISAC_ISTA_EXI) /* extended interrupt */ { c |= ifpnp_isac_exir_hdlr(sc, ISAC_READ(I_EXIR)); } if(ista & ISAC_ISTA_RME) /* receive message end */ { int rest; u_char rsta; /* get rx status register */ rsta = ISAC_READ(I_RSTA); if((rsta & ISAC_RSTA_MASK) != 0x20) { int error = 0; if(!(rsta & ISAC_RSTA_CRC)) /* CRC error */ { error++; NDBGL1(L1_I_ERR, "unit %d: CRC error", sc->sc_unit); } if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */ { error++; NDBGL1(L1_I_ERR, "unit %d: Data Overrun error", sc->sc_unit); } if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */ { error++; NDBGL1(L1_I_ERR, "unit %d: Receive Aborted error", sc->sc_unit); } if(error == 0) NDBGL1(L1_I_ERR, "unit %d: RME unknown error, RSTA = 0x%02x!", sc->sc_unit, rsta); i4b_Dfreembuf(sc->sc_ibuf); c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; sc->sc_ibuf = NULL; sc->sc_ib = NULL; sc->sc_ilen = 0; ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES); ISACCMDRWRDELAY(); return; } rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1)); if(rest == 0) rest = ISAC_FIFO_LEN; if(sc->sc_ibuf == NULL) { if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL) sc->sc_ib = sc->sc_ibuf->m_data; else panic("ifpnp_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n"); sc->sc_ilen = 0; } if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest)) { ISAC_RDFIFO(sc->sc_ib, rest); sc->sc_ilen += rest; sc->sc_ibuf->m_pkthdr.len = sc->sc_ibuf->m_len = sc->sc_ilen; if(sc->sc_trace & TRACE_D_RX) { i4b_trace_hdr_t hdr; hdr.unit = L0IFPNPUNIT(sc->sc_unit); hdr.type = TRC_CH_D; hdr.dir = FROM_NT; hdr.count = ++sc->sc_trace_dcount; MICROTIME(hdr.time); i4b_l1_trace_ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data); } c |= ISAC_CMDR_RMC; if(sc->sc_enabled && (ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)) { i4b_l1_ph_data_ind(L0IFPNPUNIT(sc->sc_unit), sc->sc_ibuf); } else { i4b_Dfreembuf(sc->sc_ibuf); } } else { NDBGL1(L1_I_ERR, "RME, input buffer overflow!"); i4b_Dfreembuf(sc->sc_ibuf); c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; } sc->sc_ibuf = NULL; sc->sc_ib = NULL; sc->sc_ilen = 0; } if(ista & ISAC_ISTA_RPF) /* receive fifo full */ { if(sc->sc_ibuf == NULL) { if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL) sc->sc_ib= sc->sc_ibuf->m_data; else panic("ifpnp_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n"); sc->sc_ilen = 0; } if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN)) { ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN); sc->sc_ilen += ISAC_FIFO_LEN; sc->sc_ib += ISAC_FIFO_LEN; c |= ISAC_CMDR_RMC; } else { NDBGL1(L1_I_ERR, "RPF, input buffer overflow!"); i4b_Dfreembuf(sc->sc_ibuf); sc->sc_ibuf = NULL; sc->sc_ib = NULL; sc->sc_ilen = 0; c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; } } if(ista & ISAC_ISTA_XPR) /* transmit fifo empty (XPR bit set) */ { if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL)) { sc->sc_freeflag = sc->sc_freeflag2; sc->sc_obuf = sc->sc_obuf2; sc->sc_op = sc->sc_obuf->m_data; sc->sc_ol = sc->sc_obuf->m_len; sc->sc_obuf2 = NULL; #ifdef NOTDEF kprintf("ob2=%x, op=%x, ol=%d, f=%d #", sc->sc_obuf, sc->sc_op, sc->sc_ol, sc->sc_state); #endif } else { #ifdef NOTDEF kprintf("ob=%x, op=%x, ol=%d, f=%d #", sc->sc_obuf, sc->sc_op, sc->sc_ol, sc->sc_state); #endif } if(sc->sc_obuf) { ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN)); if(sc->sc_ol > ISAC_FIFO_LEN) /* length > 32 ? */ { sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */ sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */ c |= ISAC_CMDR_XTF; /* set XTF bit */ } else { if(sc->sc_freeflag) { i4b_Dfreembuf(sc->sc_obuf); sc->sc_freeflag = 0; } sc->sc_obuf = NULL; sc->sc_op = NULL; sc->sc_ol = 0; c |= ISAC_CMDR_XTF | ISAC_CMDR_XME; } } else { sc->sc_state &= ~ISAC_TX_ACTIVE; } } if(ista & ISAC_ISTA_CISQ) /* channel status change CISQ */ { u_char ci; /* get command/indication rx register*/ ci = ISAC_READ(I_CIRR); /* if S/Q IRQ, read SQC reg to clr SQC IRQ */ if(ci & ISAC_CIRR_SQC) ISAC_READ(I_SQRR); /* C/I code change IRQ (flag already cleared by CIRR read) */ if(ci & ISAC_CIRR_CIC0) ifpnp_isac_ind_hdlr(sc, (ci >> 2) & 0xf); }
/*---------------------------------------------------------------------------* * Data source switch for Read channels - 1, 3 and 5 (B and D-Channel) *---------------------------------------------------------------------------*/ void ihfc_putmbuf (ihfc_sc_t *sc, u_char chan, struct mbuf *m) { i4b_trace_hdr_t hdr; if (chan < 2) { if(S_TRACE & TRACE_D_RX) { hdr.count = ++S_DTRACECOUNT; hdr.dir = FROM_NT; hdr.type = TRC_CH_D; hdr.unit = S_I4BUNIT; MICROTIME(hdr.time); i4b_l1_trace_ind(&hdr, m->m_len, m->m_data); } if (!S_ENABLED) { i4b_Dfreembuf(m); return; } m->m_pkthdr.len = m->m_len; i4b_l1_ph_data_ind(S_I4BUNIT, m); } else { if(S_TRACE & TRACE_B_RX) { hdr.count = ++S_BTRACECOUNT; hdr.dir = FROM_NT; hdr.type = (chan < 4) ? TRC_CH_B1 : TRC_CH_B2; hdr.unit = S_I4BUNIT; MICROTIME(hdr.time); i4b_l1_trace_ind(&hdr, m->m_len, m->m_data); } if (!S_ENABLED) { i4b_Bfreembuf(m); return; } if (S_PROT == BPROT_NONE) { if(!i4b_l1_bchan_tel_silence(m->m_data, m->m_len)) { S_BDRVLINK->bch_activity(S_BDRVLINK->unit, ACT_RX); } if (!_IF_QFULL(&S_IFQUEUE)) { S_BYTES += m->m_len; IF_ENQUEUE(&S_IFQUEUE, m); S_BDRVLINK->bch_rx_data_ready(S_BDRVLINK->unit); } return; } if (S_PROT == BPROT_RHDLC) { S_MBUFDUMMY = m; S_BYTES += m->m_pkthdr.len = m->m_len; S_BDRVLINK->bch_rx_data_ready(S_BDRVLINK->unit); S_MBUFDUMMY = NULL; return; } NDBGL1(L1_ERROR, "Unknown protocol: %d", S_PROT); } }
/*---------------------------------------------------------------------------* * * 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 ifpi_ph_data_req(int unit, struct mbuf *m, int freeflag) { u_char cmd; struct l1_softc *sc = ifpi_scp[unit]; #ifdef NOTDEF NDBGL1(L1_PRIM, "PH-DATA-REQ, unit %d, freeflag=%d", unit, freeflag); #endif if(m == NULL) /* failsafe */ return (0); crit_enter(); if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */ { NDBGL1(L1_I_ERR, "still in state F3!"); ifpi_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", ifpi_printstate(sc)); if(sc->sc_trace & TRACE_D_TX) { i4b_trace_hdr_t hdr; hdr.unit = L0IFPIUNIT(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); } crit_exit(); return(1); } NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", ifpi_printstate(sc)); if(freeflag == MBUF_FREE) i4b_Dfreembuf(m); crit_exit(); return (0); } if(sc->sc_trace & TRACE_D_TX) { i4b_trace_hdr_t hdr; hdr.unit = L0IFPIUNIT(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(); crit_exit(); return(1); }
/*---------------------------------------------------------------------------* * ISAC interrupt service routine *---------------------------------------------------------------------------*/ void isic_isac_irq(struct isic_softc *sc, int ista) { register u_char c = 0; NDBGL1(L1_F_MSG, "%s: ista = 0x%02x", device_xname(&sc->sc_dev), ista); if(ista & ISAC_ISTA_EXI) /* extended interrupt */ { u_int8_t exirstat = ISAC_READ(I_EXIR); if (sc->sc_intr_valid == ISIC_INTR_VALID) c |= isic_isac_exir_hdlr(sc, exirstat); } if(ista & ISAC_ISTA_RME) /* receive message end */ { register int rest; u_char rsta; /* get rx status register */ rsta = ISAC_READ(I_RSTA); if((rsta & ISAC_RSTA_MASK) != 0x20) { int error = 0; if(!(rsta & ISAC_RSTA_CRC)) /* CRC error */ { error++; NDBGL1(L1_I_ERR, "%s: CRC error", device_xname(&sc->sc_dev)); } if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */ { error++; NDBGL1(L1_I_ERR, "%s: Data Overrun error", device_xname(&sc->sc_dev)); } if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */ { error++; NDBGL1(L1_I_ERR, "%s: Receive Aborted error", device_xname(&sc->sc_dev)); } if(error == 0) { NDBGL1(L1_I_ERR, "%s: RME unknown error, RSTA = 0x%02x!", device_xname(&sc->sc_dev), rsta); } i4b_Dfreembuf(sc->sc_ibuf); c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; sc->sc_ibuf = NULL; sc->sc_ib = NULL; sc->sc_ilen = 0; ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES); ISACCMDRWRDELAY(); return; } rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1)); if(rest == 0) rest = ISAC_FIFO_LEN; if(sc->sc_ibuf == NULL) { if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL) sc->sc_ib = sc->sc_ibuf->m_data; else panic("isic_isac_irq: RME, i4b_Dgetmbuf returns NULL!"); sc->sc_ilen = 0; } if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest)) { ISAC_RDFIFO(sc->sc_ib, rest); sc->sc_ilen += rest; sc->sc_ibuf->m_pkthdr.len = sc->sc_ibuf->m_len = sc->sc_ilen; if(sc->sc_trace & TRACE_D_RX) { i4b_trace_hdr hdr; memset(&hdr, 0, sizeof hdr); hdr.type = TRC_CH_D; hdr.dir = FROM_NT; hdr.count = ++sc->sc_trace_dcount; isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data); } c |= ISAC_CMDR_RMC; if(sc->sc_intr_valid == ISIC_INTR_VALID && (((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S)) { isdn_layer2_data_ind(&sc->sc_l2, sc->sc_l3token, sc->sc_ibuf); } else { i4b_Dfreembuf(sc->sc_ibuf); } } else { NDBGL1(L1_I_ERR, "RME, input buffer overflow!"); i4b_Dfreembuf(sc->sc_ibuf); c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; } sc->sc_ibuf = NULL; sc->sc_ib = NULL; sc->sc_ilen = 0; } if(ista & ISAC_ISTA_RPF) /* receive fifo full */ { if(sc->sc_ibuf == NULL) { if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL) sc->sc_ib= sc->sc_ibuf->m_data; else panic("isic_isac_irq: RPF, i4b_Dgetmbuf returns NULL!"); sc->sc_ilen = 0; } if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN)) { ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN); sc->sc_ilen += ISAC_FIFO_LEN; sc->sc_ib += ISAC_FIFO_LEN; c |= ISAC_CMDR_RMC; } else { NDBGL1(L1_I_ERR, "RPF, input buffer overflow!"); i4b_Dfreembuf(sc->sc_ibuf); sc->sc_ibuf = NULL; sc->sc_ib = NULL; sc->sc_ilen = 0; c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; } } if(ista & ISAC_ISTA_XPR) /* transmit fifo empty (XPR bit set) */ { if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL)) { sc->sc_freeflag = sc->sc_freeflag2; sc->sc_obuf = sc->sc_obuf2; sc->sc_op = sc->sc_obuf->m_data; sc->sc_ol = sc->sc_obuf->m_len; sc->sc_obuf2 = NULL; #ifdef NOTDEF printf("ob2=%x, op=%x, ol=%d, f=%d #", sc->sc_obuf, sc->sc_op, sc->sc_ol, sc->sc_state); #endif } else { #ifdef NOTDEF printf("ob=%x, op=%x, ol=%d, f=%d #", sc->sc_obuf, sc->sc_op, sc->sc_ol, sc->sc_state); #endif } if(sc->sc_obuf) { ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN)); if(sc->sc_ol > ISAC_FIFO_LEN) /* length > 32 ? */ { sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */ sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */ c |= ISAC_CMDR_XTF; /* set XTF bit */ } else { if(sc->sc_freeflag) { i4b_Dfreembuf(sc->sc_obuf); sc->sc_freeflag = 0; } sc->sc_obuf = NULL; sc->sc_op = NULL; sc->sc_ol = 0; c |= ISAC_CMDR_XTF | ISAC_CMDR_XME; } } else { sc->sc_state &= ~ISAC_TX_ACTIVE; } } if(ista & ISAC_ISTA_CISQ) /* channel status change CISQ */ { register u_char ci; /* get command/indication rx register*/ ci = ISAC_READ(I_CIRR); /* if S/Q IRQ, read SQC reg to clr SQC IRQ */ if(ci & ISAC_CIRR_SQC) (void) ISAC_READ(I_SQRR); /* C/I code change IRQ (flag already cleared by CIRR read) */ if(ci & ISAC_CIRR_CIC0) isic_isac_ind_hdlr(sc, (ci >> 2) & 0xf); } if(c) { ISAC_WRITE(I_CMDR, c); ISACCMDRWRDELAY(); } }
/*---------------------------------------------------------------------------* * * 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); }