OpenSS7 SS7 for the Common Man |
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |
||||||||||||||||||||||||||
Home | Overview | Status | News | Documentation | Resources | About | |||||||||||||||||||||
File /code/strss7/drivers/m2ua2/m2ua.c#ident "@(#) $RCSfile: m2ua.c,v $ $Name: $($Revision: 0.8.2.4 $) $Date: 2003/04/14 12:12:57 $" static char const ident[] = "$RCSfile: m2ua.c,v $ $Name: $($Revision: 0.8.2.4 $) $Date: 2003/04/14 12:12:57 $"; #include <linux/config.h> #include <linux/version.h> #ifdef MODVERSIONS #include <linux/modversions.h> #endif #include <linux/module.h> #include <sys/stream.h> #include <sys/stropts.h> #include <sys/cmn_err.h> #include <sys/dki.h> #include <ss7/lmi.h> #include <ss7/lmi_ioctl.h> #include <ss7/devi.h> #include <ss7/devi_ioctl.h> #include <ss7/sdli.h> #include <ss7/sdli_ioctl.h> #include <ss7/sdti.h> #include <ss7/sdti_ioctl.h> #include <ss7/sl.h> #include <ss7/sl_ioctl.h> #include <ss7/ua_lm.h> #include "../lock.h" #include "../debug.h" #include "../bufq.h" #include "m2ua_data.h" /* M2UA private structure definitions */ #include "m2ua_msg.h" /* M2ua message definitions */ #define M2UA_DESCRIP "SL STREAMS MULTIPLEXING DRIVER." #define M2UA_COPYRIGHT "Copyright (c) 1997-2002 OpenSS7 Corporation. All Rights Reserved." #define M2UA_DEVICE "Part of the OpenSS7 Stack for LiS STREAMS." #define M2UA_CONTACT "Brian Bidulock <bidulock@openss7.org> #define M2UA_LICENSE "GPL" #define M2UA_BANNER M2UA_DESCRIP "\n" \ M2UA_COPYRIGHT "\n" \ M2UA_DEVICE "\n" \ M2UA_CONTACT "\n" MODULE_AUTHOR(M2UA_CONTACT); MODULE_DESCRIPTION(M2UA_DESCRIP); MODULE_SUPPORTED_DEVICE(M2UA_DEVICE); #ifdef MODULE_LICENSE MODULE_LICENSE(M2UA_LICENSE); #endif #ifndef INT #define INT void #endif /* * ========================================================================= * * STREAMS Definitions * * ========================================================================= */ static struct module_info m2ua_u_minfo = { 0, /* Module ID number */ "m2ua-slu", /* Module name */ 0, /* Min packet size accepted */ INFPSZ, /* Max packet size accepted */ 1, /* Hi water mark */ 0 /* Lo water mark */ }; static struct module_info m2ua_l_minfo = { 0, /* Module ID number */ "m2ua-slp", /* Module name */ 0, /* Min packet size accepted */ INFPSZ, /* Max packet size accepted */ 1, /* Hi water mark */ 0 /* Lo water mark */ }; static int m2ua_open (queue_t *, dev_t *, int, int, cred_t *); static int m2ua_close(queue_t *, int, cred_t *); static INT m2ua_u_wput(queue_t *, mblk_t *); static INT m2ua_u_wsrv(queue_t *); static struct qinit m2ua_u_winit = { m2ua_u_wput, /* Write put (msg from above) */ m2ua_u_wsrv, /* Write queue service */ NULL, /* Each open */ NULL, /* Last close */ NULL, /* Admin (not used) */ &m2ua_u_minfo, /* Information */ NULL /* Statistics */ }; static INT m2ua_u_rput(queue_t *, mblk_t *); static INT m2ua_u_rsrv(queue_t *); static struct qinit m2ua_u_rinit = { m2ua_u_rput, /* Read put (msg from below) */ m2ua_u_rsrv, /* Read queue service */ m2ua_open, /* Each open */ m2ua_close, /* Last close */ NULL, /* Admin (not used) */ &m2ua_u_minfo, /* Information */ NULL /* Statistics */ }; static INT m2ua_l_wput(queue_t *, mblk_t *); static INT m2ua_l_wsrv(queue_t *); static struct qinit m2ua_l_winit = { m2ua_l_rput, /* Write put (msg from above) */ m2ua_l_rsrv, /* Write queue service */ NULL, /* Each open */ NULL, /* Last close */ NULL, /* Admin (not used) */ &m2ua_l_minfo, /* Information */ NULL /* Statistics */ }; static INT m2ua_l_rput(queue_t *, mblk_t *); static INT m2ua_l_rsrv(queue_t *); static struct qinit m2ua_l_rinit = { m2ua_l_rput, /* Read put (msg from below) */ m2ua_l_rsrv, /* Read queue service */ NULL, /* Each open */ NULL, /* Last close */ NULL, /* Admin (not used) */ &m2ua_l_minfo, /* Information */ NULL /* Statistics */ }; static struct streamtab m2ua_info = { &m2ua_u_rinit, /* Upper read queue */ &m2ua_u_winit, /* Upper write queue */ &m2ua_l_rinit, /* Lower read queue */ &m2ua_l_winit /* Lower write queue */ }; /* * ========================================================================= * * SLM --> SL User Primitives * * ========================================================================= */ static int lmi_ok_ack_reply(queue_t *q, long prim, ulong state, mblk_t *mp) { lmi_ok_ack_t *p; if ( mp->b_cont ) freemsg(mp->b_cont); mp->b_datap->db_type = M_PCPROTO; p = (lmi_ok_ack_t *)mp->b_rptr; mp->b_wptr = mp->b_rptr + sizeof(*p); p->lmi_primitive = LMI_OK_ACK; p->lmi_correct_primitive = prim; p->lmi_state = state; qreply(q, mp); return(1); } static int lmi_error_ack_reply(queue_t *q, long prim, ulong state, long err, mblk_t *mp) { lmi_error_ack_t *p; if ( mp->b_cont ) freemsg(mp->b_cont); mp->b_datap->db_type = M_PCPROTO; p = (lmi_error_ack_t *)mp->b_rptr; mp->b_wptr = mp->b_rptr + sizeof(*p); p->lmi_primitive = LMI_ERROR_ACK; p->lmi_errno = err < 0 ? LMI_SYSERR : err; p->lmi_reason = err < 0 ? -err : 0 ; p->lmi_error_primitive = prim; p->lmi_state = state; qreply(q, mp); return(1); } /* * ========================================================================= * * SLM --> SL Provider Primitives * * ========================================================================= */ /* * ========================================================================= * * SL User --> SLM Primitives * * ========================================================================= */ static int lmi_info_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; do { if ( q->q_next ) { { fixme(("We should answer the request ourselves if not attached\n")); return(4); } } err = -EFAULT; break; } while(0); seldom(); return lmi_error_ack_reply(q, LMI_INFO_REQ, ua->state, err, mp); } static int lmi_attach_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; do { if ( ua->state == LMI_UNATTACHED ) { { fixme(("Search for Signalling Link Identifier\n")); ua->state = LMI_DISABLED; return lmi_ok_ack_reply(q, LMI_ATTACH_REQ, ua->state, mp); } } err = LMI_OUTSTATE; break; } while(0); seldom(); return lmi_error_ack_reply(q, LMI_ATTACH_REQ, ua->state, err, mp); } static int lmi_detach_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; do { if ( ua->state == LMI_DISABLED ) { { fixme(("Detach from the lower queue\n")); ua->state = LMI_UNATTACHED; return lmi_ok_ack_reply(q, LMI_DETACH_REQ, ua->state, mp); } } err = LMI_OUTSTATE; break; } while(0); seldom(); return lmi_error_ack_reply(q, LMI_DETACH_REQ, ua->state, err, mp); } static int lmi_enable_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; do { if ( ua->state == LMI_DISABLED ) { if ( q->q_next ) { { ua->state = LMI_ENABLE_PENDING; return(4); } } err = -EFAULT; break; } err = LMI_OUTSTATE; break; } while(0); seldom(); return lmi_error_ack_reply(q, LMI_ENABLE_REQ, ua->state, err, mp); } static int lmi_disable_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; do { if ( ua->state == LMI_ENABLED ) { if ( q->q_next ) { { ua->state = LMI_DISABLE_PENDING; return(4); } } err = -EFAULT; break; } err = LMI_OUTSTATE; break; } while(0); seldom(); return lmi_error_ack_reply(q, LMI_DISABLE_REQ, ua->state, err, mp); } static int lmi_optmgmt_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; do { if ( q->q_next ) { { fixme(("Can we handle this ourselves?\n")); return(4); } } err = -EFAULT; break; } while(0); seldom(); return lmi_error_ack_reply(q, LMI_OPTMGMT_REQ, ua->state, err, mp); } /* * ========================================================================= * * SL Provider --> SLM Primitives * * ========================================================================= */ static int lmi_info_ack(queue_t *q, mblk_t *mp) { return(4); } static int lmi_ok_ack(queue_t *q, mblk_t *mp) { return(4); } static int lmi_error_ack(queue_t *q, mblk_t *mp) { ua_t *ua = (ua_t *)q->q_ptr; if ( ua->uq ) { ua_t *ua = (ua_t *)q->q_ptr; switch ( ua->state ) { case LMI_ENABLE_PENDING: ua->state = LMI_DISABLED; break; case LMI_DISABLE_PENDING: ua->state = LMI_ENABLED; break; default: ua->state = LMI_DISABLED; break; } } return(4); } static int lmi_enable_con(queue_t *q, mblk_t *mp) { ua_t *ua = (ua_t *)q->q_ptr; if ( ua->uq ) { ua_t *ua = (ua_t *)q->q_ptr; if ( ua->state == LMI_ENABLE_PENDING ) ua->state = LMI_ENABLED; } return(4); } static int lmi_disable_con(queue_t *q, mblk_t *mp) { } static int lmi_optmgmt_ack(queue_t *q, mblk_t *mp) { } static int lmi_error_ind(queue_t *q, mblk_t *mp) { } static int lmi_stats_ind(queue_t *q, mblk_t *mp) { } static int lmi_event_ind(queue_t *q, mblk_t *mp) { } /* * ========================================================================= * * OUTPUT EVENTS * * ========================================================================= */ /* * ------------------------------------------------------------------------- * * Buffer Allocation * * ------------------------------------------------------------------------- */ /* * BUFSRV calls service routine * ------------------------------------ */ static void ua_bufsrv(long data) { ua_t *ua = (ua_t *)data; if ( ua->bid ) { ua->bid = 0; qenable(ua->rq); qenable(ua->wq); } } /* * BUFCALL for enobufs * ------------------------------------ */ static int ua_bufcall(ua_t *ua, size_t size) { if ( !ua->bid ) ua->bid = bufcall(size, BPRI_MED, *ua_bufsrv, (long)ua); return(-ENOBUFS); } /* * REUSEB * ------------------------------------ * Attempt to reuse a mblk before allocating one. */ static int reuseb(ua_t *ua, size_t size, int prior, mblk_t **mp) { int rtn; if ( !(*mp) || (*mp)->b_datap->db_lim = (*mp)->b_datap->db_base < size ) { rtn = 0; if ( !((*mp) = allocb(size, prior)) ) return ua_bufcall(ua, size); } else { rtn = 1; if ( (*mp)->b_cont ) { freemsg((*mp)->b_cont); (*mp)->b_cont = NULL; } (*mp)->b_wptr = (*mp)->b_rptr = (*mp)->b_datap->db_base; } return(rtn); } /* * M2UA_TYPE_CTL Upstream Primitives * ----------------------------------- */ static int lm_ok_ack(ua_t *ua, mblk_t *mp, ulong prim) { int rtn; lm_ok_ack_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->prim = LM_OK_ACK; p->correct_prim = prim; putnext(ua->mq, mp); } return(rtn); } static int lm_error_ack(ua_t *ua, mblk_t *mp, ulong prim, int err) { int rtn; lm_error_ack_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->prim = LM_ERROR_ACK; p->error_prim = prim; p->errno = err < 0 ? LM_SYSERR : err; p->unix_error = err < 0 ? -err : 0 ; putnext(ua->mq, mp); } return(rtn); } static int lm_reg_ind(ua_t *ua, mblk_t *mp) { int rtn; lm_reg_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->prim = LM_REG_IND; p->muxid = ua->u.btm.muxid; p->aspid = FIXME; p->load = FIXME; p->prio = FIXME; p->KEY_number = FIXME; p->KEY_offset = FIXME; p->KEY_length = FIXME; putnext(ua->mq, mp); } return(rtn); } static int lm_dereg_ind(ua_t *ua, mblk_t *mp, ulong key) { int rtn; lm_dereg_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->prim = LM_DEREG_IND; p->muxid = ua->u.btm.muxid; p->KEY_number = key; putnext(ua->mq, mp); } return(rtn); } static int lm_error_ind(ua_t *ua, mblk_t *mp, int err) { int rtn; lm_error_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->prim = LM_ERROR_IND; p->muxid = ua->u.btm.muxid; p->errno = err < 0 ? LM_SYSERR : err; p->unix_error = err < 0 ? -err : 0 ; putnext(ua->mq, mp); } return(rtn); } /* * M2UA_TYPE_TOP Upstream Primitives * ----------------------------------- */ static int lmi_info_ack(ua_t *ua, mblk_t *mp) { int rtn; lmi_info_ack_t *p; size_t plen = sizeof(ua->id); if ( (rtn = reuseb(ua, sizeof(*p)+plen, BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_INFO_ACK; p->lmi_version = FIXME; p->lmi_state = ua->state; p->lmi_max_sdu = ua->rq->q_info->qi_maxpsz; p->lmi_min_sdu = ua->rq->q_info->qi_minpsz; p->lmi_header_len = 0; p->lmi_ppa_style = LMI_STYLE2; bcopy(ua->id, mp->b_wptr, sizeof(ua->id)); mp->b_wptr += sizeof(ua->id); putnext(ua->rq, mp); } return(rtn); } static int lmi_ok_ack(ua_t *ua, mblk_t *mp, long prim) { int rtn; lmi_ok_ack_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_OK_ACK; p->lmi_correct_primitive= prim; p->lmi_state = ua->state; putnext(ua->rq, mp); } return(rtn); } static int lmi_error_ack(ua_t *ua, mblk_t *mp, long prim, int err) { int rtn; lmi_error_ack_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_ERROR_ACK; p->lmi_errno = err < 0 ? LMI_SYSERR : err; p->lmi_reason = err < 0 ? -err : 0 ; p->lmi_state = ua->state; putnext(ua->rq, mp); } return(rtn); } static int lmi_enable_con(ua_t *ua, mblk_t *mp) { int rtn; lmi_enable_con_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_ENABLE_CON; p->lmi_state = ua->state; putnext(ua->rq, mp); } return(rtn); } static int lmi_disable_con(ua_t *ua, mblk_t *mp) { int rtn; lmi_disable_con_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_DISABLE_CON; p->lmi_state = ua->state; putnext(ua->rq, mp); } return(rtn); } static int lmi_optmgmt_ack(ua_t *ua, mblk_t *mp, void *opt_ptr, size_t opt_len, ulong flags) { int rtn; lmi_optmgmt_ack_t *p; if ( (rtn = reuseb(ua, sizeof(*p)+opt_len, BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_OPTMGMT_ACK; p->lmi_opt_length = opt_len; p->lmi_opt_offset = opt_len?sizeof(*p):0; p->lmi_mgmt_flags = flags; bcopy(opt_ptr, mp->b_wptr, opt_len); mp->b_wptr += opt_len; putnext(ua->rq, mp); } return(rtn); } static int lmi_error_ind(ua_t *ua, mblk_t *mp) { int rtn; lmi_error_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_ERROR_IND; p->lmi_errno = err < 0 ? LMI_SYSERR : err; p->lmi_reason = err < 0 ? -err : 0 ; p->lmi_state = ua->state; putnext(ua->rq, mp); } return(rtn); } static int lmi_stats_ind(ua_t *ua, mblk_t *mp, ulong interval, ulong timestamp) { int rtn; lmi_stats_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_STATS_IND; p->lmi_interval = interval; p->lmi_timestamp = timestamp; putnext(ua->rq, mp); } return(rtn); } static int lmi_event_ind(ua_t *ua, mblk_t *mp, ulong oid, ulong level) { int rtn; lmi_even_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_EVENT_IND; p->lmi_objectid = oid; p->lmi_timestamp = jiffies; p->lmi_severity = level; putnext(ua->rq, mp); } return(rtn); } static int sl_pdu_ind(ua_t *ua, mblk_t *mp, mblk_t *dp) { int rtn; sl_pdu_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_PDU_IND; mp->b_cont = dp; putnext(ua->rq, mp); } return(rtn); } static int sl_link_congested_ind(ua_t *ua, mblk_t *mp, ulong cong, ulong disc) { int rtn; sl_link_congested_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_LINK_CONGESTED_IND; p->sl_timestamp = jiffies; p->sl_cong_status = cong; p->sl_disc_status = disc; putnext(ua->rq, mp); } return(rtn); } static int sl_link_congestion_ceased_ind(ua_t *ua, mblk_t *mp, ulong cong, ulong disc) { int rtn; sl_link_congestion_ceased_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_LINK_CONGESTION_CEASED_IND; p->sl_timestamp = jiffies; p->sl_cong_status = cong; p->sl_disc_status = disc; putnext(ua->rq, mp); } return(rtn); } static int sl_retrieved_messsage_ind(ua_t *ua, mblk_t *mp, mblk_t *dp) { int rtn; sl_retreived_message_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_RETRIEVED_MESSAGE_IND; mp->b_cont = dp; putnext(ua->rq, mp); } return(rtn); } static int sl_retrieval_complete_ind(ua_t *ua, mblk_t *mp) { int rtn; sl_retrieval_complete_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_RETRIEVAL_COMPLETE_IND; putnext(ua->rq, mp); } return(rtn); } static int sl_rb_cleared_ind(ua_t *ua, mblk_t *mp) { int rtn; sl_rb_cleared_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_RB_CLEARED_IND; putnext(ua->rq, mp); } return(rtn); } static int sl_bsnt_ind(ua_t *ua, mblk_t *mp, ulong bsnt) { int rtn; sl_bsnt_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_BSNT_IND; p->sl_bsnt = bsnt; putnext(ua->rq, mp); } return(rtn); } static int sl_in_service_ind(ua_t *ua, mblk_t *mp) { int rtn; sl_in_service_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_IN_SERVICE_IND; putnext(ua->rq, mp); } return(rtn); } static int sl_out_of_service_ind(ua_t *ua, mblk_t *mp, ulong reason) { int rtn; sl_out_of_service_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_OUT_OF_SERVICE_IND; p->sl_timestamp = jiffies; p->sl_reason = reason; putnext(ua->rq, mp); } return(rtn); } static int sl_remote_processor_outage_ind(ua_t *ua, mblk_t *mp) { int rtn; sl_remote_processor_outage_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_REMOTE_PROCESSOR_OUTAGE_IND; putnext(ua->rq, mp); } return(rtn); } static int sl_remote_processor_recovered_ind(ua_t *ua, mblk_t *mp) { int rtn; sl_remove_processor_recovered_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_REMOTE_PROCESSOR_RECOVERED_IND; putnext(ua->rq, mp); } return(rtn); } static int sl_rtb_cleared_ind(ua_t *ua, mblk_t *mp) { int rtn; sl_rtb_cleared_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_RTB_CLEARED_IND; putnext(ua->rq, mp); } return(rtn); } static int sl_retrieval_not_possible_ind(ua_t *ua, mblk_t *mp) { int rtn; sl_retrieval_not_possible_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_RETRIEVAL_NOT_POSSIBLE_IND; putnext(ua->rq, mp); } return(rtn); } static int sl_bsnt_not_retrievable_ind(ua_t *ua, mblk_t *mp, ulong bsnt) { int rtn; sl_bsnt_not_retrievable_ind_t *p; if ( (rtn = reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0 ) { p = ((typeof(p))mp->b_wptr)++; mp->b_datap->db_type = M_PCPROTO; p->sl_primitive = SL_BSNT_NOT_RETRIEVABLE_IND; p->sl_bsnt = bsnt; putnext(ua->rq, mp); } return(rtn); } /* * ========================================================================= * * INPUT EVENTS * * ========================================================================= */ /* * M2UA_TYPE_CTL Downstream Primitives * ----------------------------------- */ static int lm_as_add_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int lm_as_del_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int lm_proc_add_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int lm_proc_del_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int lm_link_add_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int lm_link_del_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int lm_route_add_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int lm_route_del_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int lm_reg_res(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } /* * M2UA_TYPE_TOP Downstream Primitives * ----------------------------------- */ static int slu_info_req(queue_t *q, mblk_t *mp) { ua_t *ua = (ua_t *)q->q_ptr; } static int slu_attach_req(queue_t *q, mblk_t *mp) { ua_t *ua = (ua_t *)q->q_ptr; } static int slu_detach_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_enable_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_disable_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_optmgmt_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_pdu_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_emergency_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_emergency_ceases_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_start_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_stop_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_retrieve_bsnt_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_retrieval_request_and_fsnc_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_resume_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_clear_buffers_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_clear_rtb_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_local_processor_outage_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_congestion_discard_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_congestion_accept_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_no_congestion_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int slu_power_on_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } /* * M2UA_TYPE_BTM Upstream Primitives * ------------------------------------ */ static int sll_info_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_ok_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_error_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_enable_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_disable_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_optmgmt_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_error_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_stats_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_event_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_pdu_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_link_congested_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_link_congestion_ceased_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_retrieved_messsage_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_retrieval_complete_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_rb_cleared_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_bsnt_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_in_service_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_out_of_service_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_remote_processor_outage_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_remote_processor_recovered_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_rtb_cleared_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_retrieval_not_possible_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int sll_bsnt_not_retrievable_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } /* * M2UA message read for upper stream (need translating). */ static int m2ua_mgmt_r_err(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_mgmt_r_ntfy(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_r_duna(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_r_dava(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_r_daud(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_r_scon(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_r_dupu(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_r_drst(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_r_aspup_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_r_aspdn_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_r_hbeat_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_r_aspup_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_r_aspdn_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_r_hbeat_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_aspt_r_aspac_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_aspt_r_aspia_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_aspt_r_aspac_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_aspt_r_aspia_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_rkmm_r_reg_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_rkmm_r_reg_rsp(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_rkmm_r_dereg_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_rkmm_r_dereg_rsp(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_data(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_estab_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_estab_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_rel_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_rel_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_state_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_state_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_state_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_retr_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_retr_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_retr_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_retr_comp_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_cong_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_r_data_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } /* * M2UA message written for lower stream (need translating). */ static int m2ua_mgmt_w_err(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_mgmt_w_ntfy(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_w_duna(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_w_dava(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_w_daud(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_w_scon(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_w_dupu(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_snmm_w_drst(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_w_aspup_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_w_aspdn_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_w_hbeat_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_w_aspup_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_w_aspdn_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_asps_w_hbeat_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_aspt_w_aspac_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_aspt_w_aspia_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_aspt_w_aspac_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_aspt_w_aspia_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_rkmm_w_reg_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_rkmm_w_reg_rsp(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_rkmm_w_dereg_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_rkmm_w_dereg_rsp(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_data(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_estab_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_estab_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_rel_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_rel_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_state_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_state_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_state_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_retr_req(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_retr_con(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_retr_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_retr_comp_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_cong_ind(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } static int m2ua_maup_w_data_ack(queue_t *q, mblk_t *mp) { int err; ua_t *ua = (ua_t *)q->q_ptr; } /* * ========================================================================= * * STREAMS Message Handling * * ========================================================================= */ /* * ------------------------------------------------------------------------- * * M_IOCDATA Handling * * ------------------------------------------------------------------------- */ static int m2ua_u_w_iocdata(queue_t *q, mblk_t *mp) { (void)q; (void)mp; ptrace(("Received M_IOCDATA on upper WR(q)\n")); return(-EOPNOTSUPP); } /* * ------------------------------------------------------------------------- * * M_IOCTL Handling * * ------------------------------------------------------------------------- */ static ua_t *m2ua_links_list = NULL; static int m2ua_u_w_ioctl(queue_t *q, mblk_t *mp) { int err = EOPNOTSUPP; struct iocblk *iocp = (struct iocblk *)mp->b_rptr; switch ( _IOC_TYPE(iocp->ioc_cmd) ) { case __SID: { lp_t *lp; ua_t *ua = (ua_t *)q->q_ptr; struct linkblk *lb = (struct linkblk *) (mp->b_cont?mp->b_cont->b_rptr:NULL); switch ( iocp->ioc_cmd ) { case I_PLINK: err = EPERM; if ( iocp->ioc_cr->cr_uid != 0 ) break; case I_LINK: err = 0; if ( lb->l_qbot->q_ptr != NULL ) break; /* already linked */ if ( (lp = kmem_cache_alloc(m2ua_cachep, SLAB_ATOMIC)) ) { bzero(lp, sizeof(lp_t)); if ( (lp->next = m2ua_links_list) ) lp->next->prev = &lp->next; lp->prev = &m2ua_links_list; m2ua_links_list = lp; lp->id.mux = lb->l_index; lp->rq = RD(lb->l_qbot); lp->wq = WR(lb->l_qbot); lp->mq = RD(q); lp->rq->q_ptr = lp->wq->q_ptr = lp; } err = ENOMEM; break; case I_PUNLINK: err = EPERM; if ( iocp->ioc_cr->cr_uid != 0 ) break; case I_UNLINK: err = 0; if ( !(lp = (lp_t *)lb->l_qbot->q_ptr) ) break; /* already unlinked */ fixme(("More thinks to unlink\n")); if ( (*(lp->prev) = lp->next) ) lp->next->prev = lp->prev; lp->prev = NULL; lp->next = NULL; if ( lp->bid ) unbufcall(lp->bid); lp->rq->q_ptr = lp->wq->q_ptr = NULL; kmem_cache_free(m2ua_cachep, lp); break; } } /* case SL_IOC_MAGIC: */ /* can't control these thru M2UA */ /* case SDT_IOC_MAGIC: */ /* can't control these thru M2UA */ /* case SDL_IOC_MAGIC: */ /* can't control these thru M2UA */ /* case DEV_IOC_MAGIC: */ /* can't control these thru M2UA */ } if ( err ) { mp->b_datap->db_type = M_IOCNAK; iocp->ioc_error = err; iocp->ioc_rval = -1; } else { mp->b_datap->db_type = M_IOCACK; iocp->ioc_error = 0; iocp->ioc_rval = 0; } qreply(q, mp); return(1); } /* * ------------------------------------------------------------------------- * * M_PROTO Handling * * ------------------------------------------------------------------------- */ static int m2ua_u_w_proto(queue_t *q, mblk_t *mp) { switch ( *((long *)mp->b_rptr) ) { case LM_AS_ADD_REQ: return lm_as_add_req (q, mp); case LM_AS_DEL_REQ: return lm_as_del_req (q, mp); case LM_PROC_ADD_REQ: return lm_proc_add_req (q, mp); case LM_PROC_DEL_REQ: return lm_proc_del_req (q, mp); case LM_LINK_ADD_REQ: return lm_link_add_req (q, mp); case LM_LINK_DEL_REQ: return lm_link_del_req (q, mp); case LM_ROUTE_ADD_REQ: return lm_route_add_req (q, mp); case LM_ROUTE_DEL_REQ: return lm_route_del_req (q, mp); case LM_REG_RES: return lm_reg_res (q, mp); case LMI_INFO_REQ: return slu_info_req (q, mp); case LMI_ATTACH_REQ: return slu_attach_req (q, mp); case LMI_DETACH_REQ: return slu_detach_req (q, mp); case LMI_ENABLE_REQ: return slu_enable_req (q, mp); case LMI_DISABLE_REQ: return slu_disable_req (q, mp); case LMI_OPTMGMT_REQ: return slu_optmgmt_req (q, mp); case SL_PDU_REQ: return slu_pdu_req (q, mp); case SL_EMERGENCY_REQ: return slu_emergency_req (q, mp); case SL_EMERGENCY_CEASES_REQ: return slu_emergency_ceases_req (q, mp); case SL_START_REQ: return slu_start_req (q, mp); case SL_STOP_REQ: return slu_stop_req (q, mp); case SL_RETRIEVE_BSNT_REQ: return slu_retrieve_bsnt_req (q, mp); case SL_RETRIEVAL_REQUEST_AND_FSNC_REQ: return slu_retrieval_request_and_fsnc_req(q, mp); case SL_RESUME_REQ: return slu_resume_req (q, mp); case SL_CLEAR_BUFFERS_REQ: return slu_clear_buffers_req (q, mp); case SL_CLEAR_RTB_REQ: return slu_clear_rtb_req (q, mp); case SL_LOCAL_PROCESSOR_OUTAGE_REQ: return slu_local_processor_outage_req (q, mp); case SL_CONGESTION_DISCARD_REQ: return slu_congestion_discard_req (q, mp); case SL_CONGESTION_ACCEPT_REQ: return slu_congestion_accept_req (q, mp); case SL_NO_CONGESTION_REQ: return slu_no_congestion_req (q, mp); case SL_POWER_ON_REQ: return slu_power_on_req (q, mp); } return(-EOPNOTSUPP); } static int m2ua_l_r_proto(queue_t *q, mblk_t *mp) { switch ( *((long *)mp->b_rptr) ) { case LMI_INFO_ACK: return sll_info_ack (q, mp); case LMI_OK_ACK: return sll_ok_ack (q, mp); case LMI_ERROR_ACK: return sll_error_ack (q, mp); case LMI_ENABLE_CON: return sll_enable_con (q, mp); case LMI_DISABLE_CON: return sll_disable_con (q, mp); case LMI_OPTMGMT_ACK: return sll_optmgmt_ack (q, mp); case LMI_ERROR_IND: return sll_error_ind (q, mp); case LMI_STATS_IND: return sll_stats_ind (q, mp); case LMI_EVENT_IND: return sll_event_ind (q, mp); case SL_PDU_IND: return sll_pdu_ind (q, mp); case SL_LINK_CONGESTED_IND: return sll_link_congested_ind (q, mp); case SL_LINK_CONGESTION_CEASED_IND: return sll_link_congestion_ceased_ind (q, mp); case SL_RETRIEVED_MESSAGE_IND: return sll_retrieved_messsage_ind (q, mp); case SL_RETRIEVAL_COMPLETE_IND: return sll_retrieval_complete_ind (q, mp); case SL_RB_CLEARED_IND: return sll_rb_cleared_ind (q, mp); case SL_BSNT_IND: return sll_bsnt_ind (q, mp); case SL_IN_SERVICE_IND: return sll_in_service_ind (q, mp); case SL_OUT_OF_SERVICE_IND: return sll_out_of_service_ind (q, mp); case SL_REMOTE_PROCESSOR_OUTAGE_IND: return sll_remote_processor_outage_ind (q, mp); case SL_REMOTE_PROCESSOR_RECOVERED_IND: return sll_remote_processor_recovered_ind(q, mp); case SL_RTB_CLEARED_IND: return sll_rtb_cleared_ind (q, mp); case SL_RETRIEVAL_NOT_POSSIBLE_IND: return sll_retrieval_not_possible_ind (q, mp); case SL_BSNT_NOT_RETRIEVABLE_IND: return sll_bsnt_not_retrievable_ind (q, mp); } return(-EOPNOTSUPP); } static int m2ua_u_r_proto(queue_t *q, mblk_t *mp) { return(5); } static int m2ua_l_w_proto(queue_t *q, mblk_t *mp) { return(5); } /* * ------------------------------------------------------------------------- * * M_PCPROTO Handling * * ------------------------------------------------------------------------- */ static int m2ua_u_w_pcproto(queue_t *q, mblk_t *mp) { return m2ua_u_w_proto(q, mp); } static int m2ua_l_r_pcproto(queue_t *q, mblk_t *mp) { return m2ua_l_r_proto(q, mp); } static int m2ua_u_r_pcproto(queue_t *q, mblk_t *mp) { return(4); } static int m2ua_l_w_pcproto(queue_t *q, mblk_t *mp) { return(4); } /* * ------------------------------------------------------------------------- * * M_DATA Handling * * ------------------------------------------------------------------------- */ /* * Any M_DATA written by the upper SS7 user must be converted to M_PROTO to * avoid interfering with the internal interface. */ static int m2ua_u_w_data(queue_t *q, mblk_t *dp) { int err; mblk_t *mp; sl_pdu_req_t *p; if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = ((typeof(p))mp->b_wptr)++; p->sl_primitive = SL_PDU_REQ; mp->b_cont = dp; switch ( (err = sl_pdu_req(q, mp)) ) { case 0: freeb(mp); return(0); case 1: break; case 2: freeb(mp); break; case 3: if ( !q->q_next ) { qreply(q, mp); break; } case 4: if ( q->q_next ) { putnext(q, mp); break; } case 5: if ( canputnext(q) ) { putnext(q, mp); break; } default: freeb(mp); return(err); } return(1); } return(-ENOBUFS); } /* * Any M_DATA read by the lower SS7 provider must be converted to M_PROTO to * avoid interfering with the internal interface. */ static int m2ua_l_r_data(queue_t *q, mblk_t *dp) { int err; mblk_t *mp; sl_pdu_ind_t *p; if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = ((typeof(p))mp->b_wptr)++; p->sl_primitive = SL_PDU_IND; mp->b_cont = dp; switch ( (err = sl_pdu_ind(q, mp)) ) { case 0: freeb(mp); return(0); case 1: break; case 2: freeb(mp); break; case 3: if ( !q->q_next ) { qreply(q, mp); break; } case 4: if ( q->q_next ) { putnext(q, mp); break; } case 5: if ( canputnext(q) ) { putnext(q, mp); break; } default: freeb(mp); return(err); } return(1); } return(-ENOBUFS); } /* * This is an M2UA message that must be converted into an SS7 primitive before * it is transferred to the SS7 user. */ static int m2ua_u_r_data(queue_t *q, mblk_t *mp) { switch ( *((uint32_t *)mp->b_rptr) ) { case UA_MGMT_ERR: m2ua_mgmt_r_err (q, mp); case UA_MGMT_NTFY: m2ua_mgmt_r_ntfy (q, mp); case UA_SNMM_DUNA: m2ua_snmm_r_duna (q, mp); case UA_SNMM_DAVA: m2ua_snmm_r_dava (q, mp); case UA_SNMM_DAUD: m2ua_snmm_r_daud (q, mp); case UA_SNMM_SCON: m2ua_snmm_r_scon (q, mp); case UA_SNMM_DUPU: m2ua_snmm_r_dupu (q, mp); case UA_SNMM_DRST: m2ua_snmm_r_drst (q, mp); case UA_ASPS_ASPUP_REQ: m2ua_asps_r_aspup_req (q, mp); case UA_ASPS_ASPDN_REQ: m2ua_asps_r_aspdn_req (q, mp); case UA_ASPS_HBEAT_REQ: m2ua_asps_r_hbeat_req (q, mp); case UA_ASPS_ASPUP_ACK: m2ua_asps_r_aspup_ack (q, mp); case UA_ASPS_ASPDN_ACK: m2ua_asps_r_aspdn_ack (q, mp); case UA_ASPS_HBEAT_ACK: m2ua_asps_r_hbeat_ack (q, mp); case UA_ASPT_ASPAC_REQ: m2ua_aspt_r_aspac_req (q, mp); case UA_ASPT_ASPIA_REQ: m2ua_aspt_r_aspia_req (q, mp); case UA_ASPT_ASPAC_ACK: m2ua_aspt_r_aspac_ack (q, mp); case UA_ASPT_ASPIA_ACK: m2ua_aspt_r_aspia_ack (q, mp); case UA_RKMM_REQ_REQ: m2ua_rkmm_r_reg_req (q, mp); case UA_RKMM_REG_RSP: m2ua_rkmm_r_reg_rsp (q, mp); case UA_RKMM_DEREG_REQ: m2ua_rkmm_r_dereg_req (q, mp); case UA_RKMM_DREG_RSP: m2ua_rkmm_r_dereg_rsp (q, mp); case M2UA_MAUP_DATA: m2ua_maup_r_data (q, mp); case M2UA_MAUP_ESTAB_REQ: m2ua_maup_r_estab_req (q, mp); case M2UA_MAUP_ESTAB_CON: m2ua_maup_r_estab_con (q, mp); case M2UA_MAUP_REL_REQ: m2ua_maup_r_rel_req (q, mp); case M2UA_MAUP_REL_CON: m2ua_maup_r_rel_con (q, mp); case M2UA_MAUP_STATE_REQ: m2ua_maup_r_state_req (q, mp); case M2UA_MAUP_STATE_CON: m2ua_maup_r_state_con (q, mp); case M2UA_MAUP_STATE_IND: m2ua_maup_r_state_ind (q, mp); case M2UA_MAUP_RETR_REQ: m2ua_maup_r_retr_req (q, mp); case M2UA_MAUP_RETR_CON: m2ua_maup_r_retr_con (q, mp); case M2UA_MAUP_RETR_IND: m2ua_maup_r_retr_ind (q, mp); case M2UA_MAUP_RETR_COMP_IND: m2ua_maup_r_retr_comp_ind (q, mp); case M2UA_MAUP_CONG_IND: m2ua_maup_r_cong_ind (q, mp); case M2UA_MAUP_DATA_ACK: m2ua_maup_r_data_ack (q, mp); default: m2ua_maup_r_other (q, mp); } } /* * This is an M2UA message that must be converted into an SS7 primitive before * it is transferred to the SS7 provider. */ static int m2ua_l_w_data(queue_t *q, mblk_t *mp) { switch ( *((uint32_t *)mp->b_rptr) ) { case UA_MGMT_ERR: m2ua_mgmt_w_err (q, mp); case UA_MGMT_NTFY: m2ua_mgmt_w_ntfy (q, mp); case UA_SNMM_DUNA: m2ua_snmm_w_duna (q, mp); case UA_SNMM_DAVA: m2ua_snmm_w_dava (q, mp); case UA_SNMM_DAUD: m2ua_snmm_w_daud (q, mp); case UA_SNMM_SCON: m2ua_snmm_w_scon (q, mp); case UA_SNMM_DUPU: m2ua_snmm_w_dupu (q, mp); case UA_SNMM_DRST: m2ua_snmm_w_drst (q, mp); case UA_ASPS_ASPUP_REQ: m2ua_asps_w_aspup_req (q, mp); case UA_ASPS_ASPDN_REQ: m2ua_asps_w_aspdn_req (q, mp); case UA_ASPS_HBEAT_REQ: m2ua_asps_w_hbeat_req (q, mp); case UA_ASPS_ASPUP_ACK: m2ua_asps_w_aspup_ack (q, mp); case UA_ASPS_ASPDN_ACK: m2ua_asps_w_aspdn_ack (q, mp); case UA_ASPS_HBEAT_ACK: m2ua_asps_w_hbeat_ack (q, mp); case UA_ASPT_ASPAC_REQ: m2ua_aspt_w_aspac_req (q, mp); case UA_ASPT_ASPIA_REQ: m2ua_aspt_w_aspia_req (q, mp); case UA_ASPT_ASPAC_ACK: m2ua_aspt_w_aspac_ack (q, mp); case UA_ASPT_ASPIA_ACK: m2ua_aspt_w_aspia_ack (q, mp); case UA_RKMM_REQ_REQ: m2ua_rkmm_w_reg_req (q, mp); case UA_RKMM_REG_RSP: m2ua_rkmm_w_reg_rsp (q, mp); case UA_RKMM_DEREG_REQ: m2ua_rkmm_w_dereg_req (q, mp); case UA_RKMM_DREG_RSP: m2ua_rkmm_w_dereg_rsp (q, mp); case M2UA_MAUP_DATA: m2ua_maup_w_data (q, mp); case M2UA_MAUP_ESTAB_REQ: m2ua_maup_w_estab_req (q, mp); case M2UA_MAUP_ESTAB_CON: m2ua_maup_w_estab_con (q, mp); case M2UA_MAUP_REL_REQ: m2ua_maup_w_rel_req (q, mp); case M2UA_MAUP_REL_CON: m2ua_maup_w_rel_con (q, mp); case M2UA_MAUP_STATE_REQ: m2ua_maup_w_state_req (q, mp); case M2UA_MAUP_STATE_CON: m2ua_maup_w_state_con (q, mp); case M2UA_MAUP_STATE_IND: m2ua_maup_w_state_ind (q, mp); case M2UA_MAUP_RETR_REQ: m2ua_maup_w_retr_req (q, mp); case M2UA_MAUP_RETR_CON: m2ua_maup_w_retr_con (q, mp); case M2UA_MAUP_RETR_IND: m2ua_maup_w_retr_ind (q, mp); case M2UA_MAUP_RETR_COMP_IND: m2ua_maup_w_retr_comp_ind (q, mp); case M2UA_MAUP_CONG_IND: m2ua_maup_w_cong_ind (q, mp); case M2UA_MAUP_DATA_ACK: m2ua_maup_w_data_ack (q, mp); default: m2ua_maup_w_other (q, mp); } } /* * ------------------------------------------------------------------------- * * M_CTL Handling * * ------------------------------------------------------------------------- */ static int m2ua_u_w_ctl(queue_t *q, mblk_t *mp) { (void)q; (void)mp; rare(); return(-EOPNOTSUPP); } static int m2ua_l_r_ctl(queue_t *q, mblk_t *mp) { (void)q; (void)mp; rare(); return(-EOPNOTSUPP); } static int m2ua_u_r_ctl(queue_t *q, mblk_t *mp) { return m2ua_u_r_data(q, mp); } static int m2ua_l_w_ctl(queue_t *q, mblk_t *mp) { return m2ua_l_w_data(q, mp); } /* * ------------------------------------------------------------------------- * * M_HANGUP Handling * * ------------------------------------------------------------------------- */ static int m2ua_u_w_hangup(queue_t *q, mblk_t *mp) { /* * We need to treat this as a close and do all the things that we * would do before deallocating the structure (except deallocating * the structure.) */ fixme(("Stuff to do here...\n")); return(-EFAULT); } static int m2ua_l_r_hangup(queue_t *q, mblk_t *mp) { /* * We need to propagate the hangup to all users of this provider. */ fixme(("Stuff to do here...\n")); return(-EFAULT); } static int m2ua_u_r_hangup(queue_t *q, mblk_t *mp) { return(4); } static int m2ua_l_w_hangup(queue_t *q, mblk_t *mp) { /* * This is the same effect as a close on a linked stream. We need to * do all the things that would otherwise be done if the stream was * closed. The other thing that we could do is write drivers to * accept M_HANGUP written and treat them as a close (without * deallocation of the private structure). */ fixme(("Stuff to do here...\n")); return(4); } /* * ------------------------------------------------------------------------- * * M_ERROR Handling * * ------------------------------------------------------------------------- */ static int m2ua_l_r_error(queue_t *q, mblk_t *mp) { /* * The provider stream has errored out, so we need to propagate the * error to all users of this stream. */ fixme(("Stuff to do here...\n")); return(-EFAULT); } static int m2ua_u_r_error(queue_t *q, mblk_t *mp) { return(4); } /* * ------------------------------------------------------------------------- * * M_FLUSH Handling * * ------------------------------------------------------------------------- */ static int m2ua_m_flush(queue_t *q, mblk_t *mp, const uint8_t mflag, const uint8_t oflag); { if ( mp->b_rptr[0] & mflag ) { if ( mp->b_rptr[0] & FLUSHBAND ) flushband(q, mp->b_rptr[1], FLUSHALL); else flushq(q, FLUSHALL); if ( q->q_next ) { putnext(q, mp); return(1); } mp->b_rptr[0] &= ~FLUSHW; } if ( mp->b_rptr[0] & oflag && !(mp->b_flag & MSGNOLOOP) ) { queue_t *oq = q->q_other; if ( mp->b_rptr[0] & FLUSHBAND ) flushband(oq, mp->b_rptr[1], FLUSHALL); else flushq(oq, FLUSHALL); mp->b_flag |= MSGNOLOOP; qreply(q, mp); return(1); } return(0); } static int m2ua_u_w_flush(queue_t *q, mblk_t *mp) { return m2ua_m_flush(q, mp, FLUSHW, FLUSHR); } static int m2ua_l_r_flush(queue_t *q, mblk_t *mp) { return m2ua_m_flush(q, mp, FLUSHR, FLUSHW); } static int m2ua_u_r_flush(queue_t *q, mblk_t *mp) { return m2ua_m_flush(q, mp, FLUSHR, FLUSHW); } static int m2ua_l_w_flush(queue_t *q, mblk_t *mp) { return m2ua_m_flush(q, mp, FLUSHW, FLUSHR); } /* * ------------------------------------------------------------------------- * * Other message Handling * * ------------------------------------------------------------------------- */ static int m2ua_u_w_other(queue_t *q, mblk_t *mp) { (void)q; (void)mp; ptrace(("Received unexpected message %ld on upper WR(q)\n", *((long *)mp->b_rptr))); return(-EOPNOTSUPP); } static int m2ua_l_r_other(queue_t *q, mblk_t *mp) { (void)q; (void)mp; ptrace(("Received unexpected message %ld on lower RD(q)\n", *((long *)mp->b_rptr))); return(-EOPNOTSUPP); } static int m2ua_u_r_other(queue_t *q, mblk_t *mp) { if ( mp->b_datap->db_type >= QPCTL || canputnext(q) ) return(4); return(-EBUSY); } static int m2ua_l_w_other(queue_t *q, mblk_t *mp) { if ( mp->b_datap->db_type >= QPCTL || canputnext(q) ) return(4); return(-EBUSY); } /* * ========================================================================= * * STREAMS PUTQ and SRVQ routines * * ========================================================================= */ /* * UA PUTQ * ------------------------------------------------------------------------- */ static int ua_putq(queue_t *q, mblk_t *mp, int (*proc)(queue_t *, mblk_t *)) { int rtn; ensure( q, return(-EFAULT) ); ensure( mp, return(-EFAULT) ); if ( mp->b_datap->db_type < QPCTL && q->q_count ) { seldom(); putq(q, mp); return(0); } switch ( (rtn = (*proc)(q, mp)) ) { case 0: freemsg(mp); case 1: break; case 2: freeb(mp); break; case 3: if ( !q->q_next ) { qreply(q, mp); break; } case 4: if ( q->q_next ) { putnext(q, mp); break; } rtn = -EOPNOTSUPP; default: ptrace(("Error (dropping) %d\n", rtn)); freemsg(mp); return(rtn); case 5: if ( canputnext(q) ) { putnext(q, mp); break; } case -ENOBUFS: /* caller must schedule bufcall */ case -EBUSY: /* caller must have failed canput */ case -EAGAIN: /* caller must re-enable queue */ case -ENOMEM: /* caller must re-enable queue */ putq(q, mp); break; } return(0); } /* * UA SRVQ * ------------------------------------------------------------------------- */ static int ua_srvq(queue_t *q, int (*proc)(queue_t *, mblk_t *)) { int rtn; mblk_t *mp; while ( (mp = getq(q)) ) { switch ( (rtn = (*proc)(q, mp)) ) { case 0: freemsg(mp); case 1: continue; case 2: freeb(mp); continue; case 3: if ( !q->q_next ) { qreply(q, mp); continue; } case 4: if ( q->q_next ) { putnext(q, mp); continue; } rtn = -EOPNOTSUPP; default: ptrace(("Error (dropping) %d\n", rtn)); freemsg(mp); continue; case 5: if ( canputnext(q) ) { putnext(q, mp); continue; } case -ENOBUFS: /* caller must schedule bufcall */ case -EBUSY: /* caller must have failed canput */ case -EAGAIN: /* caller must re-enable queue */ case -ENOMEM: /* caller must re-enable queue */ if ( mp->b_datap->db_type < QPCTL ) { putb(q, mp); return(rtn); } ptrace(("Error (dropping) %d\n", rtn)); freemsg(mp); continue; } } return(0); } /* * UPPER WR and RD PUT and SRV * ----------------------------------- */ static int m2ua_u_w_prim(queue_t *q, mblk_t *mp) { switch ( mp->b_datap->db_type ) { case M_DATA: return m2ua_u_w_data (q, mp); case M_PROTO: return m2ua_u_w_proto (q, mp); case M_PCPROTO: return m2ua_u_w_pcproto (q, mp); case M_IOCTL: return m2ua_u_w_ioctl (q, mp); case M_IOCDATA: return m2ua_u_w_iocdata (q, mp); case M_HANGUP: return m2ua_u_w_hangup (q, mp); case M_FLUSH: return m2ua_u_w_flush (q, mp); default: return m2ua_u_w_other (q, mp); } } static INT m2ua_u_wput(queue_t *q, mblk_t *mp) { return((INT)ua_putq(q, mp, &m2ua_u_w_prim)); } static INT m2ua_u_wsrv(queue_t *q) { return((INT)ua_srvq(q, &m2ua_u_w_prim)); } static int m2ua_u_r_prim(queue_t *q, mblk_t *mp) { switch ( mp->b_datap->db_type ) { case M_DATA: return m2ua_u_r_data (q, mp); case M_PROTO: return m2ua_u_r_proto (q, mp); case M_PCPROTO: return m2ua_u_r_pcproto (q, mp); case M_CTL: return m2ua_u_r_ctl (q, mp); case M_HANGUP: return m2ua_u_r_hangup (q, mp); case M_ERROR: return m2ua_u_r_error (q, mp); case M_FLUSH: return m2ua_u_r_flush (q, mp); default: return m2ua_u_r_other (q, mp); } } static INT m2ua_u_rput(queue_t *q, mblk_t *mp) { return((INT)ua_putq(q, mp, &m2ua_u_r_prim)); } static INT m2ua_u_rsrv(queue_t *q) { return((INT)ua_srvq(q, &m2ua_u_r_prim)); } /* * LOWER WR and RD PUT and SRV * ----------------------------------- */ static int m2ua_l_w_prim(queue_t *q, mblk_t *mp) { switch ( mp->b_datap->db_type ) { case M_DATA: return m2ua_l_w_data (q, mp); case M_PROTO: return m2ua_l_w_proto (q, mp); case M_PCPROTO: return m2ua_l_w_pcproto (q, mp); case M_HANGUP: return m2ua_l_w_hangup (q, mp); case M_FLUSH: return m2ua_l_w_flush (q, mp); default: return m2ua_l_w_other (q, mp); } } static INT m2ua_l_wput(queue_t *q, mblk_t *mp) { return((INT)ua_putq(q, mp, &m2ua_l_w_prim)); } static INT m2ua_l_wsrv(queue_t *q) { return((INT)ua_srvq(q, &m2ua_l_w_prim)); } static int m2ua_l_r_prim(queue_t *q, mblk_t *mp) { switch ( mp->b_datap->db_type ) { case M_DATA: return m2ua_l_r_data (q, mp); case M_PROTO: return m2ua_l_r_proto (q, mp); case M_PCPROTO: return m2ua_l_r_pcproto (q, mp); case M_CTL: return m2ua_l_r_ctl (q, mp); case M_HANGUP: return m2ua_l_r_hangup (q, mp); case M_ERROR: return m2ua_l_r_error (q, mp); case M_FLUSH: return m2ua_l_r_flush (q, mp); default: return m2ua_l_r_other (q, mp); } } static INT m2ua_l_rput(queue_t *q, mblk_t *mp) { return((INT)ua_putq(q, mp, &m2ua_l_r_prim)); } static INT m2ua_l_rsrv(queue_t *q) { return((INT)ua_srvq(q, &m2ua_l_r_prim)); } /* * ========================================================================= * * Private Structure cache * * ========================================================================= */ kmem_cache_t *m2ua_cachep = NULL; static int m2ua_init_caches(void) { if (!(m2ua_cachep) && !(m2ua_cachep = kmem_cache_create ("m2ua_cachep", sizeof(ua_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL))) return (ENOMEM); return; } static void m2ua_term_caches(void) { if (m2ua_cachep) if (kmem_cache_destroy(m2ua_cachep)) cmn_err(CE_WARN, "m2ua: did not destroy m2ua_cachep"); return; } /* * ========================================================================= * * OPEN and CLOSE * * ========================================================================= */ static ua_t *m2ua_opens_list = NULL; static int m2ua_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp) { int cmajor = getmajor(*devp); int cminor = getminor(*devp); dp_t *dp, **dpp; if ( q->q_ptr != NULL ) return(0); /* already open */ if ( sflag == MODOPEN || WR(q)->q_next ) return(EIO); /* can't open as module */ if ( !cminor ) sflag = CLONEOPEN; if ( sflag == CLONEOPEN ) cminor = 1; dpp = &m2ua_opens_list; for ( ; *dpp && getmajor((*dpp)->id.dev) < cmajor; dpp = &(*dpp)->next ); for ( ; *dpp && cminor <= M2UA_NMINOR; dpp = &(*dpp)->next ) { ushort dminor = getminor((*dpp)->id.dev); if ( cminor < dminor ) break; if ( cminor == dminor ) { if ( sflag == CLONEOPEN ) { cminor++; continue; } return(EIO); /* requested device in use */ } } if ( cminor > M2UA_NMINOR ) return(ENXIO); *devp = makedevice(cmajor, minor); if ( !(dp = kmem_cache_alloc(m2ua_cachep, SLAB_ATOMIC)) ) return(ENOMEM); bzero(dp, sizeof(ua_t)); if ( (dp->next = *dpp) ) dp->next->prev = &dp->next; dp->prev = dpp; *dpp = dp; dp->id.dev = *devp; dp->rq = RD(q); dp->wq = WR(q); dp->mq = RD(q); dp->rq->q_ptr = dp->wq->q_ptr = dp; return(0); } static int m2ua_close(queue_t *q, int flag, cred_t *crp) { dp_t *dp = (dp_t *)q->q_ptr; if ( (*(dp->prev) = dp->next) ) dp->next->prev = dp->prev; dp->prev = NULL; dp->next = NULL; if ( dp->bid ) unbufcall(dp->bid); dp->rq->q_ptr = NULL; dp->rq->q_ptr = NULL; kmem_cache_free(m2ua_cachep, dp); return(0); } /* * ========================================================================= * * LiS Module Initialization * * ========================================================================= */ int m2ua_init(void) { int err; int cmajor; if ( !m2ua_u_minfo.mi_idnum ) { if ( (err = m2ua_init_caches()) ) return(err); if ( (cmajor = lis_regsiter_strdev(M2UA_CMAJOR, &m2ua_info, M2UA_NMINOR, m2ua_u_minfo.mi_idname)) < 0 ) { m2ua_u_minfo.mi_idnum = 0; rare(); cnm_err(CE_NOTE, "m2ua: couldn't register driver\n"); return; } m2ua_u_minfo.mi_idnum = cmajor; } return(0); } void m2ua_terminate(void) { if ( m2ua_u_minfo.mi_idnum ) { m2ua_term_caches(); if ( (m2ua_u_minfo.mi_idnum = lis_unregister_strdev(m2ua_u_minfo.mi_idnum)) ) { m2ua_u_minfo.mi_idnum = 0; rare(); cmn_err(CE_WARN, "m2ua: couldn't unregister driver!\n"); } } } /* * ========================================================================= * * Kernel Module Initialization * * ========================================================================= */ int init_module(void) { int err; m2ua_init(); return(0); } void cleanup_module(void) { m2ua_terminate(); return; }
|
|||||||||||||||||||||||||||
OpenSS7 SS7 for the Common Man |
Home | Overview | Status | News | Documentation | Resources | About | ||||||||||||||||||||
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |