/*---------------------------------------------------------------------------* * send RELEASE message *---------------------------------------------------------------------------*/ void i4b_l3_tx_release(call_desc_t *cd, int send_cause_flag) { struct mbuf *m; u_char *ptr; int len = I_FRAME_HDRLEN + MSG_RELEASE_LEN; DBGL3(L3_PRIM, "tx RELEASE", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); if(send_cause_flag == 0) len -= 4; if((m = i4b_Dgetmbuf(len)) == NULL) panic("i4b_l3_tx_release: can't allocate mbuf\n"); ptr = m->m_data + I_FRAME_HDRLEN; *ptr++ = PD_Q931; /* protocol discriminator */ *ptr++ = 0x01; /* call reference length */ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ *ptr++ = RELEASE; /* message type = release complete */ if(send_cause_flag) { *ptr++ = IEI_CAUSE; /* cause ie */ *ptr++ = CAUSE_LEN; *ptr++ = CAUSE_STD_LOC_OUT; *ptr++ = make_q931_cause(cd->cause_out); } DL_Data_Req(ctrl_desc[cd->controller].unit, m); }
/*---------------------------------------------------------------------------* * send MSG_DISCONNECT_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_disconnect_ind(call_desc_t *cd) { struct mbuf *m; if(cd->timeout_active) callout_stop(&cd->idle_timeout); if(cd->dlt != NULL) { (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd); i4b_unlink_bchandrvr(cd); } if((cd->channelid >= 0) && (cd->channelid < ctrl_desc[cd->controller].nbch)) { ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE; } else { /* no error, might be hunting call for callback */ NDBGL4(L4_MSG, "channel free not valid but %d!", cd->channelid); } if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL) { msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data; mp->header.type = MSG_DISCONNECT_IND; mp->header.cdid = cd->cdid; mp->cause = cd->cause_in; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send STATUS message *---------------------------------------------------------------------------*/ void i4b_l3_tx_status(call_desc_t *cd, u_char q850cause) { struct mbuf *m; u_char *ptr; DBGL3(L3_PRIM, "tx STATUS", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_STATUS_LEN)) == NULL) panic("i4b_l3_tx_status: can't allocate mbuf\n"); ptr = m->m_data + I_FRAME_HDRLEN; *ptr++ = PD_Q931; /* protocol discriminator */ *ptr++ = 0x01; /* call reference length */ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ *ptr++ = STATUS; /* message type = connect ack */ *ptr++ = IEI_CAUSE; /* cause ie */ *ptr++ = CAUSE_LEN; *ptr++ = CAUSE_STD_LOC_OUT; *ptr++ = q850cause; *ptr++ = IEI_CALLSTATE; /* call state ie */ *ptr++ = CALLSTATE_LEN; *ptr++ = i4b_status_tab[cd->Q931state]; DL_Data_Req(ctrl_desc[cd->controller].unit, m); }
/*---------------------------------------------------------------------------* * send MSG_CONNECT_ACTIVE_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_connect_active_ind(call_desc_t *cd) { struct mbuf *m; crit_enter(); cd->last_active_time = cd->connect_time = SECOND; NDBGL4(L4_TIMO, "last_active/connect_time=%ld", (long)cd->connect_time); i4b_link_bchandrvr(cd); (*cd->dlt->line_connected)(cd->driver_unit, (void *)cd); i4b_l4_setup_timeout(cd); crit_exit(); if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL) { msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data; mp->header.type = MSG_CONNECT_ACTIVE_IND; mp->header.cdid = cd->cdid; mp->controller = cd->controller; mp->channel = cd->channelid; if(cd->datetime[0] != '\0') strcpy(mp->datetime, cd->datetime); else mp->datetime[0] = '\0'; i4bputqueue(m); } }
static int iavc_send_init(iavc_softc_t *sc) { struct mbuf *m = i4b_Dgetmbuf(15); u_int8_t *p; int s; if (!m) { aprint_error_dev(&sc->sc_dev, "can't get memory\n"); return (ENOMEM); } /* * byte 0x11 = SEND_INIT * dword NumApplications * dword NumNCCIs * dword BoardNumber */ p = amcc_put_byte(mtod(m, u_int8_t*), 0); p = amcc_put_byte(p, 0); p = amcc_put_byte(p, SEND_INIT); p = amcc_put_word(p, 1); /* XXX MaxAppl XXX */ p = amcc_put_word(p, sc->sc_capi.sc_nbch); p = amcc_put_word(p, sc->sc_unit); s = splnet(); IF_ENQUEUE(&sc->sc_txq, m); iavc_start_tx(sc); sc->sc_state = IAVC_INIT; splx(s); return 0; }
/*---------------------------------------------------------------------------* * send MSG_ACCT_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_accounting(int driver, int driver_unit, int accttype, int ioutbytes, int iinbytes, int ro, int ri, int outbytes, int inbytes) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL) { msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data; md->header.type = MSG_ACCT_IND; md->header.cdid = -1; md->driver = driver; md->driver_unit = driver_unit; md->accttype = accttype; md->ioutbytes = ioutbytes; md->iinbytes = iinbytes; md->outbps = ro; md->inbps = ri; md->outbytes = outbytes; md->inbytes = inbytes; i4bputqueue(m); } }
int iavc_release(capi_softc_t *capi_sc, int applid) { iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx; struct mbuf *m = i4b_Dgetmbuf(7); u_int8_t *p; if (!m) { aprint_error_dev(&sc->sc_dev, "can't get memory\n"); return (ENOMEM); } /* * byte 0x14 = SEND_RELEASE * dword ApplId */ p = amcc_put_byte(mtod(m, u_int8_t*), 0); p = amcc_put_byte(p, 0); p = amcc_put_byte(p, SEND_RELEASE); p = amcc_put_word(p, applid); IF_ENQUEUE(&sc->sc_txq, m); iavc_start_tx(sc); return 0; }
/*---------------------------------------------------------------------------* * send DISCONNECT message *---------------------------------------------------------------------------*/ void i4b_l3_tx_disconnect(call_desc_t *cd) { struct mbuf *m; u_char *ptr; DBGL3(L3_PRIM, "tx DISCONNECT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_DISCONNECT_LEN)) == NULL) panic("i4b_l3_tx_disconnect: can't allocate mbuf\n"); ptr = m->m_data + I_FRAME_HDRLEN; *ptr++ = PD_Q931; /* protocol discriminator */ *ptr++ = 0x01; /* call ref length */ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ *ptr++ = DISCONNECT; /* message type = disconnect */ *ptr++ = IEI_CAUSE; /* cause ie */ *ptr++ = CAUSE_LEN; *ptr++ = CAUSE_STD_LOC_OUT; *ptr++ = make_q931_cause(cd->cause_out); DL_Data_Req(ctrl_desc[cd->controller].unit, m); }
/*---------------------------------------------------------------------------* * send MSG_IDLE_TIMEOUT_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_idle_timeout_ind(call_desc_t *cd) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL) { msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data; mp->header.type = MSG_IDLE_TIMEOUT_IND; mp->header.cdid = cd->cdid; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send MSG_NEGOTIATION_COMPL message to userland *---------------------------------------------------------------------------*/ void i4b_l4_negcomplete(call_desc_t *cd) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL) { msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data; md->header.type = MSG_NEGCOMP_IND; md->header.cdid = cd->cdid; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send MSG_ALERT_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_alert_ind(call_desc_t *cd) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL) { msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data; mp->header.type = MSG_ALERT_IND; mp->header.cdid = cd->cdid; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send MSG_PDEACT_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_pdeact(int controller, int numactive) { struct mbuf *m; int i; call_desc_t *cd; for(i=0; i < N_CALL_DESC; i++) { if((call_desc[i].cdid != CDID_UNUSED) && (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && (ctrl_desc[call_desc[i].controller].unit == controller)) { cd = &call_desc[i]; if(cd->timeout_active) { callout_stop(&cd->idle_timeout); } if(cd->dlt != NULL) { (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd); i4b_unlink_bchandrvr(cd); } if((cd->channelid >= 0) & (cd->channelid < ctrl_desc[cd->controller].nbch)) { ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE; } cd->cdid = CDID_UNUSED; } } if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL) { msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data; md->header.type = MSG_PDEACT_IND; md->header.cdid = -1; md->controller = controller; md->numactive = numactive; i4bputqueue_hipri(m); /* URGENT !!! */ } }
/*---------------------------------------------------------------------------* * send MSG_IFSTATE_CHANGED_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_ifstate_changed(call_desc_t *cd, int new_state) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL) { msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data; md->header.type = MSG_IFSTATE_CHANGED_IND; md->header.cdid = cd->cdid; md->state = new_state; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send MSG_INFO_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_proceeding_ind(call_desc_t *cd) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL) { msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data; mp->header.type = MSG_PROCEEDING_IND; mp->header.cdid = cd->cdid; mp->controller = cd->controller; mp->channel = cd->channelid; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send MSG_DIALOUT_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_dialout(int driver, int driver_unit) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL) { msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data; md->header.type = MSG_DIALOUT_IND; md->header.cdid = -1; md->driver = driver; md->driver_unit = driver_unit; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send MSG_TEIASG_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_teiasg(int controller, int tei) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL) { msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data; md->header.type = MSG_TEIASG_IND; md->header.cdid = -1; md->controller = controller; md->tei = ctrl_desc[controller].tei; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send MSG_DRVRDISC_REQ message to userland *---------------------------------------------------------------------------*/ void i4b_l4_drvrdisc(int driver, int driver_unit) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL) { msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data; md->header.type = MSG_DRVRDISC_REQ; md->header.cdid = -1; md->driver = driver; md->driver_unit = driver_unit; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * build U-frame for sending *---------------------------------------------------------------------------*/ struct mbuf * i4b_build_u_frame(l2_softc_t *l2sc, crbit_to_nt_t crbit, pbit_t pbit, u_char type) { struct mbuf *m; if((m = i4b_Dgetmbuf(U_FRAME_LEN)) == NULL) return(NULL); PUTSAPI(SAPI_CCP, crbit, m->m_data[OFF_SAPI]); PUTTEI(l2sc->tei, m->m_data[OFF_TEI]); if(pbit) m->m_data[OFF_CNTL] = type | UPBITSET; else m->m_data[OFF_CNTL] = type & ~UPBITSET; return(m); }
/*---------------------------------------------------------------------------* * send MSG_L12STAT_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_l12stat(int controller, int layer, int state) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL) { msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data; md->header.type = MSG_L12STAT_IND; md->header.cdid = -1; md->controller = controller; md->layer = layer; md->state = state; i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send CONNECT ACKNOWLEDGE message *---------------------------------------------------------------------------*/ void i4b_l3_tx_connect_ack(call_desc_t *cd) { struct mbuf *m; u_char *ptr; DBGL3(L3_PRIM, "tx CONNECT-ACK", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_ACK_LEN)) == NULL) panic("i4b_l3_tx_connect_ack: can't allocate mbuf\n"); ptr = m->m_data + I_FRAME_HDRLEN; *ptr++ = PD_Q931; /* protocol discriminator */ *ptr++ = 0x01; /* call reference length */ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ *ptr++ = CONNECT_ACKNOWLEDGE; /* message type = connect ack */ DL_Data_Req(ctrl_desc[cd->controller].unit, m); }
/*---------------------------------------------------------------------------* * send ALERTING message *---------------------------------------------------------------------------*/ void i4b_l3_tx_alert(call_desc_t *cd) { struct mbuf *m; u_char *ptr; if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_ALERT_LEN)) == NULL) panic("i4b_l3_tx_alert: can't allocate mbuf\n"); DBGL3(L3_PRIM, "tx ALERT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); ptr = m->m_data + I_FRAME_HDRLEN; *ptr++ = PD_Q931; /* protocol discriminator */ *ptr++ = 0x01; /* call reference length */ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ *ptr++ = ALERT; /* message type = alert */ DL_Data_Req(ctrl_desc[cd->controller].unit, m); }
/*---------------------------------------------------------------------------* * send MSG_PACKET_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_packet_ind(int driver, int driver_unit, int dir, struct mbuf *pkt) { struct mbuf *m; int len = pkt->m_pkthdr.len; unsigned char *ip = pkt->m_data; if((m = i4b_Dgetmbuf(sizeof(msg_packet_ind_t))) != NULL) { msg_packet_ind_t *mp = (msg_packet_ind_t *)m->m_data; mp->header.type = MSG_PACKET_IND; mp->header.cdid = -1; mp->driver = driver; mp->driver_unit = driver_unit; mp->direction = dir; memcpy(mp->pktdata, ip, len <MAX_PACKET_LOG ? len : MAX_PACKET_LOG); i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send MSG_CHARGING_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_charging_ind(call_desc_t *cd) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL) { msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data; mp->header.type = MSG_CHARGING_IND; mp->header.cdid = cd->cdid; mp->units_type = cd->units_type; /*XXX*/ if(mp->units_type == CHARGE_CALC) mp->units = cd->cunits; else mp->units = cd->units; i4bputqueue(m); } }
int iavc_register(capi_softc_t *capi_sc, int applid, int nchan) { iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx; struct mbuf *m = i4b_Dgetmbuf(23); u_int8_t *p; if (!m) { aprint_error("iavc%d: can't get memory\n", sc->sc_unit); return (ENOMEM); } /* * byte 0x12 = SEND_REGISTER * dword ApplId * dword NumMessages * dword NumB3Connections 0..nbch * dword NumB3Blocks * dword B3Size */ p = amcc_put_byte(mtod(m, u_int8_t*), 0); p = amcc_put_byte(p, 0); p = amcc_put_byte(p, SEND_REGISTER); p = amcc_put_word(p, applid); #if 0 p = amcc_put_word(p, 1024 + (nchan + 1)); #else p = amcc_put_word(p, 1024 * (nchan + 1)); #endif p = amcc_put_word(p, nchan); p = amcc_put_word(p, 8); p = amcc_put_word(p, 2048); IF_ENQUEUE(&sc->sc_txq, m); iavc_start_tx(sc); return 0; }
/*---------------------------------------------------------------------------* * send MSG_CONNECT_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_connect_ind(call_desc_t *cd) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL) { msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data; mp->header.type = MSG_CONNECT_IND; mp->header.cdid = cd->cdid; mp->controller = cd->controller; mp->channel = cd->channelid; mp->bprot = cd->bprot; cd->dir = DIR_INCOMING; if(strlen(cd->dst_telno) > 0) strcpy(mp->dst_telno, cd->dst_telno); else strcpy(mp->dst_telno, TELNO_EMPTY); if(strlen(cd->src_telno) > 0) strcpy(mp->src_telno, cd->src_telno); else strcpy(mp->src_telno, TELNO_EMPTY); strcpy(mp->display, cd->display); mp->scr_ind = cd->scr_ind; mp->prs_ind = cd->prs_ind; T400_start(cd); i4bputqueue(m); } }
static int iavc_receive_start(iavc_softc_t *sc, u_int8_t *dmabuf) { struct mbuf *m = i4b_Dgetmbuf(3); u_int8_t *p; if (sc->sc_blocked && sc->sc_state == IAVC_UP) printf("iavc%d: receive_start\n", sc->sc_unit); if (!m) { printf("iavc%d: can't get memory\n", sc->sc_unit); return (ENOMEM); } /* * byte 0x73 = SEND_POLLACK */ p = amcc_put_byte(mtod(m, u_int8_t*), 0); p = amcc_put_byte(p, 0); p = amcc_put_byte(p, SEND_POLLACK); _IF_PREPEND(&sc->sc_txq, m); NDBGL4(L4_IAVCDBG, "iavc%d: blocked = %d, state = %d", sc->sc_unit, sc->sc_blocked, sc->sc_state); sc->sc_blocked = FALSE; iavc_start_tx(sc); /* If this was our first START, register our readiness */ if (sc->sc_state != IAVC_UP) { sc->sc_state = IAVC_UP; capi_ll_control(&sc->sc_capi, CAPI_CTRL_READY, TRUE); } return 0; }
/*---------------------------------------------------------------------------* * send MSG_DIALOUTNUMBER_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_dialoutnumber(int driver, int driver_unit, int cmdlen, char *cmd) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_dialoutnumber_ind_t))) != NULL) { msg_dialoutnumber_ind_t *md = (msg_dialoutnumber_ind_t *)m->m_data; md->header.type = MSG_DIALOUTNUMBER_IND; md->header.cdid = -1; md->driver = driver; md->driver_unit = driver_unit; if(cmdlen > TELNO_MAX) cmdlen = TELNO_MAX; md->cmdlen = cmdlen; bcopy(cmd, md->cmd, cmdlen); i4bputqueue(m); } }
/*---------------------------------------------------------------------------* * send MSG_KEYPAD_IND message to userland *---------------------------------------------------------------------------*/ void i4b_l4_keypad(int driver, int driver_unit, int cmdlen, char *cmd) { struct mbuf *m; if((m = i4b_Dgetmbuf(sizeof(msg_keypad_ind_t))) != NULL) { msg_keypad_ind_t *md = (msg_keypad_ind_t *)m->m_data; md->header.type = MSG_KEYPAD_IND; md->header.cdid = -1; md->driver = driver; md->driver_unit = driver_unit; if(cmdlen > KEYPAD_MAX) cmdlen = KEYPAD_MAX; md->cmdlen = cmdlen; bcopy(cmd, md->cmd, cmdlen); i4bputqueue(m); } }
static int iavc_receive_start(iavc_softc_t *sc) { struct mbuf *m = i4b_Dgetmbuf(3); u_int8_t *p; if (sc->sc_blocked && sc->sc_state == IAVC_UP) printf("%s: receive_start\n", device_xname(&sc->sc_dev)); if (!m) { aprint_error_dev(&sc->sc_dev, "can't get memory\n"); return (ENOMEM); } /* * byte 0x73 = SEND_POLLACK */ p = amcc_put_byte(mtod(m, u_int8_t*), 0); p = amcc_put_byte(p, 0); p = amcc_put_byte(p, SEND_POLLACK); IF_PREPEND(&sc->sc_txq, m); NDBGL4(L4_IAVCDBG, "%s: blocked = %d, state = %d", device_xname(&sc->sc_dev), sc->sc_blocked, sc->sc_state); sc->sc_blocked = 0; iavc_start_tx(sc); /* If this was our first START, register our readiness */ if (sc->sc_state != IAVC_UP) { sc->sc_state = IAVC_UP; capi_ll_control(&sc->sc_capi, CAPI_CTRL_READY, 1); } return 0; }
/*---------------------------------------------------------------------------* * 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); } }