OpenSS7
SS7 for the
Common Man

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified:

Home Overview Status News Documentation Resources About
   
 Overview
 Status
 News
 Documentation
 Resources
 About

   
Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/drivers/m2ua2/m2ua.c


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;
}


Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/drivers/m2ua2/m2ua.c

OpenSS7
SS7 for the
Common Man
Home Overview Status News Documentation Resources About

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified: