📄 sdt.c
字号:
return rx_table_valueN(state, byte, 8);}/* * TX (Transmit) Table: * ----------------------------------- * There is one TX table for 8-bit (octet) output values. The table has 256 * entries and is used to perform, for one sample, zero insertion on frame * bits for the transmitted bitstream. It is the reponsiblity of the SDL * driver to perform 8-bit to 7-bit conversion to DS0A. */STATIC voidtx_table_generate(void){ int j, k; for (j = 0; j < SDT_TX_STATES; j++) for (k = 0; k < 256; k++) *tx_index8(j, k) = tx_table_value(j, k);}/* * RX (Received) Tables: * ----------------------------------- * There is one RX table for 8 bit (octet) values. The table has 256 entries * and is used to perform, for one sample, zero deletion, abort detection, * flag detection and residue calculation on the received bitstream. The SDL * driver is responsible for performing 7-bit to 8-bit conversion before * delivering bits to the SDT. */STATIC voidrx_table_generate(void){ int j, k; for (j = 0; j < SDT_RX_STATES; j++) for (k = 0; k < 256; k++) *rx_index8(j, k) = rx_table_value(j, k);}/* * BC (CRC) Tables: * ----------------------------------- * CRC table organization: This is a CRC table which contains lookups for * all bit lengths less than or equal to 8. There are 512 entries. The * first 256 entries are for 8-bit bit lengths, the next 128 entries are for * 7-bit bit lengths, the next 64 entries for 6-bit bit lengths, etc. */STATIC voidbc_table_generate(void){ int pos = 0, bit_string, bit_length = 8, bit_mask = 0x100; do { for (bit_string = 0; bit_string < bit_mask; bit_string++, pos++) bc_table[pos] = bc_table_value(bit_string, bit_length); bit_length--; } while ((bit_mask >>= 1));}/* * Table allocation * ------------------------------------------------------------------------- */STATIC intsdt_init_tables(void){ size_t length; length = SDT_CRC_TABLE_LENGTH * sizeof(bc_entry_t); for (bc_order = 0; PAGE_SIZE << bc_order < length; bc_order++) ; if (!(bc_table = (bc_entry_t *) __get_free_pages(GFP_KERNEL, bc_order))) { cmn_err(CE_PANIC, "%s: Cannot allocate bc_table\n", __FUNCTION__); goto bc_failed; } printd(("sdt: allocated BC table size %u kernel pages\n", 1 << bc_order)); bc_table_generate(); printd(("sdt: generated BC table\n")); length = SDT_TX_TABLE_LENGTH * sizeof(tx_entry_t); for (tx_order = 0; PAGE_SIZE << tx_order < length; tx_order++) ; if (!(tx_table = (tx_entry_t *) __get_free_pages(GFP_KERNEL, tx_order))) { cmn_err(CE_PANIC, "%s: Cannot allocate tx_table\n", __FUNCTION__); goto tx_failed; } printd(("sdt: allocated Tx table size %u kernel pages\n", 1 << tx_order)); tx_table_generate(); printd(("sdt: generated 8-bit Tx table\n")); length = SDT_RX_TABLE_LENGTH * sizeof(rx_entry_t); for (rx_order = 0; PAGE_SIZE << rx_order < length; rx_order++) ; if (!(rx_table = (rx_entry_t *) __get_free_pages(GFP_KERNEL, rx_order))) { cmn_err(CE_PANIC, "%s: Cannot allocate rx_table\n", __FUNCTION__); goto rx_failed; } printd(("sdt: allocated Rx table size %u kernel pages\n", 1 << rx_order)); rx_table_generate(); printd(("sdt: generated 8-bit Rx table\n")); return (0); rx_failed: free_pages((unsigned long) tx_table, tx_order); tx_order = 0; tx_failed: free_pages((unsigned long) bc_table, bc_order); bc_order = 0; bc_failed: return (-ENOMEM);}STATIC intsdt_term_tables(void){ free_pages((unsigned long) bc_table, bc_order); printd(("sdt: freed BC table kernel pages\n")); free_pages((unsigned long) tx_table, tx_order); printd(("sdt: freed Tx table kernel pages\n")); free_pages((unsigned long) rx_table, rx_order); printd(("sdt: freed Rx table kernel pages\n")); return (0);}/* * ======================================================================== * * EVENTS * * ======================================================================== *//* * RX WAKEUP * ----------------------------------- * This is called before the queue service routine unlocks the queue. We * must check if back-enabling has occured on an empty read queue. */STATIC streamscall voidsdt_rx_wakeup(queue_t *q){ (void) q; return;}/* * TX WAKEUP * ----------------------------------- * This is called before the queue service routine unlocks the queue. * sdt_tx_block will pull data from the queue as necessary. */STATIC streamscall voidsdt_tx_wakeup(queue_t *q){ struct sdt *s = SDT_PRIV(q); if ((s->i_state == LMI_ENABLED) && (s->statem.daedt_state != SDT_STATE_IDLE)) sdt_tx_block(q, s); return;}/* * ------------------------------------------------------------------------- * * Timer Events * * ------------------------------------------------------------------------- *//* * T8 TIMEOUT * ----------------------------------- */STATIC intsdt_t8_timeout(struct sdt *s){ queue_t *q = NULL; int err; if (s->statem.eim_state == SDT_STATE_MONITORING) { sdt_timer_start(s, t8); if (s->statem.su_received) { s->statem.su_received = 0; if (!s->statem.interval_error) { if ((s->statem.Ce -= s->config.De) < 0) s->statem.Ce = 0; return (QR_DONE); } } s->statem.Ce += s->config.Ue; if (s->statem.Ce > s->config.Te) { if ((err = sdt_lsc_link_failure_ind(q, s))) { s->statem.Ce -= s->config.Ue; return (err); } s->statem.eim_state = SDT_STATE_IDLE; } s->statem.interval_error = 0; } return (QR_DONE);}/* * ------------------------------------------------------------------------- * * LM User -> LM Provider Primitives * * ------------------------------------------------------------------------- *//* * LMI_INFO_REQ: * ----------------------------------- * We just pass info request along and service them on reply from the lower * level. */STATIC intsdt_info_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); lmi_info_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; return (QR_PASSFLOW); emsgsize: return lmi_error_ack(q, s, LMI_INFO_REQ, LMI_PROTOSHORT, EMSGSIZE);}/* * LMI_ATTACH_REQ: * ----------------------------------- * We do not perform attaches as this is a software SDT. The SDT selected is * the current SDT. We do, however, pass these along to the lower level if * the lower level is of the correct style. */STATIC intsdt_attach_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); lmi_attach_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; if (s->i_state == LMI_UNUSABLE) goto eagain; if (s->i_style != LMI_STYLE2) goto eopnotsupp; if (s->i_state != LMI_UNATTACHED) goto outstate; if (mp->b_wptr < mp->b_rptr + sizeof(*p) + 2) goto badppa; s->i_state = LMI_ATTACH_PENDING; return (QR_PASSFLOW); badppa: ptrace(("%s: %p: PROTO: bad ppa (too short)\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_ATTACH_REQ, LMI_BADPPA, EMSGSIZE); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_ATTACH_REQ, LMI_OUTSTATE, EPROTO); eopnotsupp: ptrace(("%s: %p: PROTO: primitive not supported for style\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_ATTACH_REQ, LMI_NOTSUPP, EOPNOTSUPP); eagain: ptrace(("%s: %p: INFO: waiting for streams to become usable\n", MOD_NAME, s)); return (-EAGAIN); emsgsize: ptrace(("%s: %p: PROTO: M_PROTO block too short\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_ATTACH_REQ, LMI_PROTOSHORT, EMSGSIZE);}/* * LMI_DETACH_REQ: * ----------------------------------- * We do not perform detaches as this is a software SDT. The SDT selected is * the current SDT. We do, however, pass these along to the lower level if * the lower level is of the correct style. */STATIC intsdt_detach_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); lmi_detach_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; if (s->i_state == LMI_UNUSABLE) goto eagain; if (s->i_style != LMI_STYLE2) goto eopnotsupp; if (s->i_state != LMI_DISABLED) goto outstate; s->i_state = LMI_DETACH_PENDING; return (QR_PASSFLOW); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_DETACH_REQ, LMI_OUTSTATE, EPROTO); eopnotsupp: ptrace(("%s: %p: PROTO: primitive not supported for style\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_DETACH_REQ, LMI_NOTSUPP, EOPNOTSUPP); eagain: ptrace(("%s: %p: INFO: waiting for streams to become usable\n", MOD_NAME, s)); return (-EAGAIN); emsgsize: ptrace(("%s: %p: PROTO: M_PROTO block too short\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_DETACH_REQ, LMI_PROTOSHORT, EMSGSIZE);}/* * LMI_ENABLE_REQ: * ----------------------------------- * We must allow the SDL first crack at enabling before we fully enable. We * commit the enable when the LMI_ENABLE_CON is returned from below. */STATIC intsdt_enable_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); lmi_enable_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; if (s->i_state == LMI_UNUSABLE) goto eagain; if (s->i_state != LMI_DISABLED) goto outstate; s->i_state = LMI_ENABLE_PENDING; return (QR_PASSFLOW); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_ENABLE_REQ, LMI_OUTSTATE, EPROTO); eagain: ptrace(("%s: %p: INFO: waiting for streams to become usable\n", MOD_NAME, s)); return (-EAGAIN); emsgsize: ptrace(("%s: %p: PROTO: M_PROTO block too short\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_ENABLE_REQ, LMI_PROTOSHORT, EMSGSIZE);}/* * LMI_DISABLE_REQ: * ----------------------------------- * We must allow the SDL first carack an disabling before we fully disable. * We commit the disable when the LMI_DISABLE_CON is returned from below. */STATIC intsdt_disable_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); lmi_disable_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; if (s->i_state == LMI_UNUSABLE) goto eagain; if (s->i_state != LMI_ENABLED) goto outstate; s->i_state = LMI_DISABLE_PENDING; return (QR_PASSFLOW); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_DISABLE_REQ, LMI_OUTSTATE, EPROTO); eagain: ptrace(("%s: %p: INFO: waiting for streams to become usable\n", MOD_NAME, s)); return (-EAGAIN); emsgsize: ptrace(("%s: %p: PROTO: M_PROTO block too short\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_DISABLE_REQ, LMI_PROTOSHORT, EMSGSIZE);}/* * LMI_OPTMGMT_REQ: * ----------------------------------- */STATIC intsdt_optmgmt_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); lmi_optmgmt_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; return (QR_PASSFLOW); emsgsize: (void) s; ptrace(("%s: %p: PROTO: M_PROTO block too short\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_OPTMGMT_REQ, LMI_PROTOSHORT, EMSGSIZE);}/* * ------------------------------------------------------------------------- * * SDT User -> SDT Provider Primitives * * ------------------------------------------------------------------------- *//* * M_DATA * ----------------------------------- */STATIC intsdt_send_data(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); int len, hlen; if (s->i_state != LMI_ENABLED) goto discard; if (s->statem.daedt_state == SDT_STATE_IDLE) goto discard; /* ignore tramsmissions when daedt shut down */ len = msgdsize(mp); hlen = (s->option.popt & SS7_POPT_XSN) ? 6 : 3; if (len < hlen || len > hlen + s->config.m + 1) goto eproto; /* let tx_wakeup pull from the queue */ return (-EAGAIN); eproto: swerr(); /* length violation, error out stream */ return m_error(q, s, EPROTO); discard: return (QR_DONE); /* silent discard */}/* * SDT_DAEDT_TRANSMISSION_REQ: * ----------------------------------- * This is the non-preferred way of sending data. It is preferred that * M_DATA blocks are used (above). We just strip off the M_PROTO and requeue * only the M_DATA blocks. */STATIC intsdt_daedt_transmission_req(queue_t *q, mblk_t *mp){ mblk_t *dp; if ((dp = mp->b_cont) && dp->b_datap->db_type == M_DATA) { trace(); return (QR_STRIP); } return (-EPROTO);}/* * SDT_DAEDT_START_REQ: * ----------------------------------- */STATIC intsdt_daedt_start_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); sdt_daedt_start_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; if (s->i_state != LMI_ENABLED) goto outstate; if (s->statem.daedt_state == SDT_STATE_IDLE) s->statem.daedt_state = SDT_STATE_IN_SERVICE; return (QR_DONE); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return m_error(q, s, EPROTO); emsgsize: ptrace(("%s: %p: PROTO: M_PROTO block too short\n", MOD_NAME, s)); return (-EMSGSIZE);}/* * SDT_DAEDR_START_REQ: * ----------------------------------- */STATIC intsdt_daedr_start_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); sdt_daedr_start_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; if (s->i_state != LMI_ENABLED) goto outstate; if (s->statem.daedr_state == SDT_STATE_IDLE) s->statem.daedr_state = SDT_STATE_IN_SERVICE; return (QR_DONE); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return m_error(q, s, EPROTO); emsgsize: ptrace(("%s: %p: PROTO: M_PROTO block too short\n", MOD_NAME, s)); return (-EMSGSIZE);}/* * SDT_AERM_START_REQ: * ----------------------------------- */STATIC intsdt_aerm_start_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); sdt_aerm_start_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; if (s->i_state != LMI_ENABLED) goto outstate; if (s->statem.aerm_state != SDT_STATE_MONITORING) { s->statem.Ca = 0; s->statem.aborted_proving = 0; s->statem.aerm_state = SDT_STATE_MONITORING; } return (QR_DONE); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return m_error(q, s, EPROTO); emsgsize: ptrace(("%s: %p: PROTO: M_PROTO block too short\n", MOD_NAME, s)); return (-EMSGSIZE);}/* * SDT_AERM_STOP_REQ: * ----------------------------------- */STATIC intsdt_aerm_stop_req(queue_t *q, mblk_t *mp){ struct sdt *s = SDT_PRIV(q); sdt_aerm_stop_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; if (s->i_state != LMI_ENABLED) goto outstate; if (s->statem.aerm_state != SDT_STATE_IDLE) { s->statem.aerm_state = SDT_STATE_IDLE; s->statem.Ti = s->config.Tin; } return (QR_DONE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -