📄 sdl.c
字号:
mp->b_wptr += sizeof(*p); p->sdl_primitive = SDL_DISCONNECT_IND; putnext(s->oq, mp); return (QR_DONE); } rare(); return (-ENOBUFS);}#endif/* * ========================================================================= * * PROTOCOL STATE MACHINE FUNCTIONS * * ========================================================================= *//* * ------------------------------------------------------------------------- * * Timers * * ------------------------------------------------------------------------- */enum { tall, t9 };STATIC int sdl_t9_timeout(struct sdl *);STATIC void streamscallsdl_t9_expiry(caddr_t data){ ss7_do_timeout(data, "t9", "sdl", &((struct sdl *) data)->timers.t9, (int (*)(struct head *)) &sdl_t9_timeout, &sdl_t9_expiry);}STATIC voidsdl_stop_timer_t9(struct sdl *s){ ss7_stop_timer((struct head *) s, "t9", "sdl", &s->timers.t9);}STATIC voidsdl_start_timer_t9(struct sdl *s){ ss7_start_timer((struct head *) s, "t9", "sdl", &s->timers.t9, &sdl_t9_expiry, s->timestamp - jiffies);};STATIC INLINE void__sdl_timer_stop(struct sdl *s, const uint t){ int single = 1; switch (t) { case tall: single = 0; /* fall through */ case t9: sdl_stop_timer_t9(s); if (single) break; /* fall through */ break; default: swerr(); break; }}STATIC INLINE voidsdl_timer_stop(struct sdl *s, const uint t){ psw_t flags; spin_lock_irqsave(&s->lock, flags); { __sdl_timer_stop(s, t); } spin_unlock_irqrestore(&s->lock, flags);}STATIC INLINE voidsdl_timer_start(struct sdl *s, const uint t){ psw_t flags; spin_lock_irqsave(&s->lock, flags); { __sdl_timer_stop(s, t); switch (t) { case t9: sdl_start_timer_t9(s); break; default: swerr(); break; } } spin_unlock_irqrestore(&s->lock, flags);}/* * ------------------------------------------------------------------------- * * State Machine * * ------------------------------------------------------------------------- *//* * ======================================================================== * * EVENTS * * ======================================================================== *//* * ------------------------------------------------------------------------- * * Timer Events * * ------------------------------------------------------------------------- *//* * T10 EXPIRY * ----------------------------------- */STATIC intsdl_t9_timeout(struct sdl *s){ /* wakeup the write queue */ qenable(s->iq); return (QR_DONE);}/* * ------------------------------------------------------------------------- * * LM User -> LM Provider Primitives * * ------------------------------------------------------------------------- *//* * LMI_INFO_REQ: * ----------------------------------- */STATIC intlmi_info_req(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_PRIV(q); lmi_info_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; return lmi_info_ack(q, s); emsgsize: return lmi_error_ack(q, s, LMI_INFO_REQ, LMI_PROTOSHORT, EMSGSIZE);}/* * LMI_ATTACH_REQ: * ----------------------------------- */STATIC intlmi_attach_req(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_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 lmi_ok_ack(q, s, LMI_ATTACH_REQ); 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: * ----------------------------------- */STATIC intlmi_detach_req(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_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 lmi_ok_ack(q, s, LMI_DETACH_REQ); 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: * ----------------------------------- */STATIC intlmi_enable_req(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_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 lmi_enable_con(q, s); 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: * ----------------------------------- */STATIC intlmi_disable_req(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_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 lmi_disable_con(q, s); 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 intlmi_optmgmt_req(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_PRIV(q); lmi_optmgmt_req_t *p = (typeof(p)) mp->b_rptr; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto emsgsize; goto eopnotsupp; eopnotsupp: ptrace(("%s: %p: PROTO: primitive not supported\n", MOD_NAME, s)); return lmi_error_ack(q, s, LMI_OPTMGMT_REQ, LMI_NOTSUPP, EOPNOTSUPP); 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);}/* * ------------------------------------------------------------------------- * * SDL User -> SDL Provider Primitives * * ------------------------------------------------------------------------- *//* * M_DATA * ----------------------------------- */STATIC intsdl_send_data(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_PRIV(q); int size; if (s->i_state != LMI_ENABLED) goto outstate; if (s->timestamp > jiffies) { printd(("%s: %p: %s sleeping for %ld ms\n", MOD_NAME, s, __FUNCTION__, s->timestamp - jiffies)); sdl_timer_start(s, t9); return (-EAGAIN); } if (s->timestamp < jiffies) { s->bytecount = 0; s->timestamp = jiffies; s->stats.tx_underruns++; } if (s->statem.tx_state != SDL_STATE_IDLE) { size = msgdsize(mp); } else { /* idle when transmitter shut down */ mblk_t *dp; for (size = 0, dp = mp; dp; dp = dp->b_cont) { if (dp->b_wptr > dp->b_rptr) { int len = dp->b_wptr - dp->b_rptr; size += len; memset(dp->b_rptr, 0xff, len); } } } putnext(s->iq, mp); s->stats.tx_octets += size; s->bytecount += size; ensure(s->tickbytes > 0, s->tickbytes = 1); while (s->bytecount >= s->tickbytes) { s->bytecount -= s->tickbytes; s->timestamp++; } return (QR_ABSORBED); outstate: return (-EPROTO); /* ignore */}/* * SDL_BITS_FOR_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 intsdl_bits_for_transmission_req(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_PRIV(q); sdl_bits_for_transmission_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; if (!mp->b_cont || mp->b_cont->b_datap->db_type != M_DATA) goto eproto; trace(); return (QR_STRIP); eproto: ptrace(("%s: %p: ERROR: bad message\n", MOD_NAME, s)); return m_error(q, s, EPROTO); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return m_error(q, s, 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 m_error(q, s, EPROTO);}/* * SDL_CONNECT_REQ: * ----------------------------------- */STATIC intsdl_connect_req(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_PRIV(q); sdl_connect_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->statem.tx_state = SDL_STATE_IN_SERVICE; s->statem.rx_state = SDL_STATE_IN_SERVICE; return (QR_DONE); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return m_error(q, s, 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 m_error(q, s, EPROTO);}/* * SDL_DISCONNECT_REQ: * ----------------------------------- */STATIC intsdl_disconnect_req(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_PRIV(q); sdl_connect_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->statem.tx_state = SDL_STATE_IDLE; s->statem.rx_state = SDL_STATE_IDLE; return (QR_DONE); outstate: ptrace(("%s: %p: PROTO: out of state\n", MOD_NAME, s)); return m_error(q, s, 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 m_error(q, s, EPROTO);}/* * ------------------------------------------------------------------------- * * SDL-Provider -> SDL-User Primitives * * ------------------------------------------------------------------------- *//* * M_DATA * ----------------------------------- */STATIC intsdl_recv_data(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_PRIV(q); int size; if (s->i_state != LMI_ENABLED) goto outstate; if (s->statem.rx_state != SDL_STATE_IDLE) { size = msgdsize(mp); } else { /* idle when receiver shut down */ mblk_t *dp; for (size = 0, dp = mp; dp; dp = dp->b_cont) { if (dp->b_wptr > dp->b_rptr) { int len = dp->b_wptr - dp->b_rptr; size += len; memset(dp->b_rptr, 0xff, len); } } } s->stats.rx_octets += size; putnext(s->oq, mp); return (QR_ABSORBED); outstate: return (QR_DONE); /* ignore */}/* * ========================================================================= * * IO Controls * * ========================================================================= * * LM IO Controls * * ------------------------------------------------------------------------- */STATIC intlmi_test_config(struct sdl *sdl, lmi_config_t * arg){ return (-EOPNOTSUPP);}STATIC intlmi_commit_config(struct sdl *sdl, lmi_config_t * arg){ return (-EOPNOTSUPP);}STATIC intlmi_iocgoptions(queue_t *q, mblk_t *mp){ if (mp->b_cont) { struct sdl *s = SDL_PRIV(q); int ret = 0; psw_t flags; lmi_option_t *arg = (typeof(arg)) mp->b_cont->b_rptr; spin_lock_irqsave(&s->lock, flags); { *arg = s->option; } spin_unlock_irqrestore(&s->lock, flags); return (ret); } rare(); return (-EINVAL);}STATIC intlmi_iocsoptions(queue_t *q, mblk_t *mp){ if (mp->b_cont) { struct sdl *s = SDL_PRIV(q); int ret = 0; psw_t flags; lmi_option_t *arg = (typeof(arg)) mp->b_cont->b_rptr; spin_lock_irqsave(&s->lock, flags); { s->option = *arg; } spin_unlock_irqrestore(&s->lock, flags); return (ret); } rare(); return (-EINVAL);}STATIC intlmi_iocgconfig(queue_t *q, mblk_t *mp){ if (mp->b_cont) { struct sdl *s = SDL_PRIV(q); psw_t flags; lmi_config_t *arg = (typeof(arg)) mp->b_cont->b_rptr; spin_lock_irqsave(&s->lock, flags); { arg->version = s->i_version; arg->style = s->i_style; } spin_unlock_irqrestore(&s->lock, flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -