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/sigtran/isua.c


File /code/strss7/drivers/sigtran/isua.c



#ident "@(#) $RCSfile: isua.c,v $ $Name:  $($Revision: 0.8.2.4 $) $Date: 2003/04/14 12:13:19 $"

static char const ident[] =
    "$RCSfile: isua.c,v $ $Name:  $($Revision: 0.8.2.4 $) $Date: 2003/04/14 12:13:19 $";

#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 "../debug.h"
#include "../bufq.h"

#define ISUA_DESCRIP	"SIGTRAN ISUA STREAMS MULTIPLEXING DRIVER."
#define ISUA_COPYRIGHT	"Copyright (c) 1997-2002 OpenSS7 Corporation.  All Rights Reserved."
#define ISUA_DEVICE	"Part of the OpenSS7 Stack for LiS STREAMS."
#define ISUA_CONTACT	"Brian Bidulock <bidulock@openss7.org>"
#define ISUA_LICENSE	"GPL"
#define ISUA_BANNER	ISUA_DESCRIP	"\n" \
			ISUA_COPYRIGHT	"\n" \
			ISUA_DEVICE	"\n" \
			ISUA_CONTACT	"\n"

MODULE_AUTHOR(ISUA_CONTACT);
MODULE_DESCRIPTION(ISUA_DESCRIP);
MODULE_SUPPORTED_DEVICE(ISUA_DEVICE);
#ifdef MODULE_LICENSE
MODULE_LICENSE(ISUA_LICENSE);
#endif

#ifndef INT
#define INT void
#endif

/* 
 *  =========================================================================
 *
 *  STREAMS Definitions
 *
 *  =========================================================================
 */

static int isua_open(queue_t *, dev_t *, int, int, cred_t *);
static int isua_close(queue_t *, int, cred_t *);

static struct module_info isua_m_minfo = {
	0,				/* Module ID number */
	"isua-lm",			/* Module name */
	0,				/* Min packet size accepted */
	INFPSZ,				/* Max packet size accepted */
	1,				/* Hi water mark */
	0				/* Lo water mark */
};

static INT isua_m_rput(queue_t *, mblk_t *);
static INT isua_m_rsrv(queue_t *);

static struct qinit isua_m_rinit {
	isua_m_rput,			/* Read put (msg from below) */
	isua_m_rsrv,			/* Read queue service */
	isua_open,			/* Each open */
	isua_close,			/* Last close */
	NULL,				/* Admin (not used) */
	&isua_m_minfo,			/* Information */
	NULL				/* Statistics */
};

static INT isua_m_wput(queue_t *, mblk_t *);
static INT isua_m_wsrv(queue_t *);

static struct qinit isua_m_winit {
	isua_m_wput,			/* Write put (msg from above) */
	isua_m_wsrv,			/* Write queue service */
	isua_open,			/* Each open */
	isua_close,			/* Last close */
	NULL,				/* Admin (not used) */
	&isua_m_minfo,			/* Information */
	NULL				/* Statistics */
};

static struct module_info isua_u_minfo = {
	0,				/* Module ID number */
	"isua-slu",			/* Module name */
	0,				/* Min packet size accepted */
	INFPSZ,				/* Max packet size accepted */
	1,				/* Hi water mark */
	0				/* Lo water mark */
};

static INT isua_u_rput(queue_t *, mblk_t *);
static INT isua_u_rsrv(queue_t *);

static struct qinit isua_u_rinit {
	isua_u_rput,			/* Read put (msg from below) */
	isua_u_rsrv,			/* Read queue service */
	isua_open,			/* Each open */
	isua_close,			/* Last close */
	NULL,				/* Admin (not used) */
	&isua_u_minfo,			/* Information */
	NULL				/* Statistics */
};

static INT isua_u_wput(queue_t *, mblk_t *);
static INT isua_u_wsrv(queue_t *);

static struct qinit isua_u_winit {
	isua_u_wput,			/* Write put (msg from above) */
	isua_u_wsrv,			/* Write queue service */
	isua_open,			/* Each open */
	isua_close,			/* Last close */
	NULL,				/* Admin (not used) */
	&isua_u_minfo,			/* Information */
	NULL				/* Statistics */
};

static struct module_info isua_l_info = {
	0,				/* Module ID number */
	"isua-slp",			/* Module name */
	0,				/* Min packet size accepted */
	INFPSZ,				/* Max packet size accepted */
	1,				/* Hi water mark */
	0				/* Lo water mark */
};

static INT isua_l_rput(queue_t *, mblk_t *);
static INT isua_l_rsrv(queue_t *);

static struct qinit isua_l_rinit {
	isua_l_rput,			/* Read put (msg from below) */
	isua_l_rsrv,			/* Read queue service */
	isua_open,			/* Each open */
	isua_close,			/* Last close */
	NULL,				/* Admin (not used) */
	&isua_l_info,			/* Information */
	NULL				/* Statistics */
};

static INT isua_l_wput(queue_t *, mblk_t *);
static INT isua_l_wsrv(queue_t *);

static struct qinit isua_l_winit {
	isua_l_wput,			/* Write put (msg from above) */
	isua_l_wsrv,			/* Write queue service */
	isua_open,			/* Each open */
	isua_close,			/* Last close */
	NULL,				/* Admin (not used) */
	&isua_l_info,			/* Information */
	NULL				/* Statistics */
};

static struct streamtab isua_m_info = {
	&isua_m_rinit,			/* Upper read queue */
	&isua_m_winit,			/* Upper write queue */
	&isua_l_rinit,			/* Lower read queue */
	&isua_l_winit			/* Lower write queue */
};

static struct streamtab isua_u_info = {
	&isua_u_rinit,			/* Upper read queue */
	&isua_u_winit,			/* Upper write queue */
	&isua_l_rinit,			/* Lower read queue */
	&isua_l_winit			/* Lower write queue */
};

/* 
 *  =========================================================================
 *
 *  OUTPUT Events
 *
 *  =========================================================================
 */
/* 
 *  ISUA --> LM Primitives
 *  -----------------------------------
 */
int lm_ok_ack(ua_t * ua, mblk_t * mp)
{
	int rtn;
	lm_ok_ack_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->prim = LM_OK_ACK;

		putq(ua->rq, mp);
	}
	return (rtn);
}

int lm_error_ack(ua_t * ua, mblk_t * mp)
{
	int rtn;
	lm_error_ack_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->prim = LM_ERROR_ACK;

		putq(ua->rq, mp);
	}
	return (rtn);
}

int lm_reg_ind(ua_t * ua, mblk_t * mp)
{
	int rtn;
	lm_reg_ind_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->prim = LM_REG_IND;

		putq(ua->rq, mp);
	}
	return (rtn);
}

int lm_dereg_ind(ua_t * ua, mblk_t * mp)
{
	int rtn;
	lm_dereg_ind_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->prim = LM_DEREG_IND;

		putq(ua->rq, mp);
	}
	return (rtn);
}

int lm_error_ind(ua_t * ua, mblk_t * mp)
{
	int rtn;
	lm_error_ind_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->prim = LM_ERROR_IND;

		putq(ua->rq, mp);
	}
	return (rtn);
}

/* 
 *  ISUA --> ISUPP Primitives
 *  -----------------------------------
 */
static int n_info_ack(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_info_ack_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_INFO_ACK;

		putq(ua->wq, mp);
	}
	return (rtn);
}
static int n_bind_ack(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_bind_ack_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_BIND_ACK;

		putq(ua->wq, mp);
	}
	return (rtn);
}
static int n_error_ack(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_error_ack_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_ERROR_ACK;

		putq(ua->wq, mp);
	}
	return (rtn);
}
static int n_ok_ack(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_ok_ack_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_OK_ACK;

		putq(ua->wq, mp);
	}
	return (rtn);
}
static int n_unitdata_ind(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_unitdata_ind_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_UNITDATA_IND;

		putq(ua->wq, mp);
	}
	return (rtn);
}
static int n_uderror_ind(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_uderror_ind_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_UDERROR_IND;

		putq(ua->wq, mp);
	}
	return (rtn);
}

/* 
 *  ISUA --> ISUPU Primitives
 *  -----------------------------------
 */
static int n_info_req(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_info_req_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_INFO_REQ;

		putq(ua->rq, mp);
	}
	return (rtn);
}
static int n_bind_req(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_bind_req_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_BIND_REQ;

		putq(ua->rq, mp);
	}
	return (rtn);
}
static int n_unbind_req(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_unbind_req_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_UNBIND_REQ;

		putq(ua->rq, mp);
	}
	return (rtn);
}
static int n_unitdata_req(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_unitdata_req_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_UNITDATA_REQ;

		putq(ua->rq, mp);
	}
	return (rtn);
}
static int n_optmgmt_req(ua_t * ua, mblk_t * mp)
{
	int rtn;
	N_optmgmt_req_t *p;
	if ((rtn = ua_reuseb(ua, sizeof(*p), BPRI_MED, &mp)) >= 0) {
		mp->b_datap->db_type = M_PROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->PRIM_type = N_OPTMGMT_REQ;

		putq(ua->rq, mp);
	}
	return (rtn);
}

/* 
 *  =========================================================================
 *
 *  STREAMS Message Handling
 *
 *  =========================================================================
 */
/* 
 *  -------------------------------------------------------------------------
 *
 *  Management Stream (LM) Message Handling
 *
 *  -------------------------------------------------------------------------
 */
int lm_as_add_req(queue_t * q, mblk_t * mp)
{
}
int lm_as_del_req(queue_t * q, mblk_t * mp)
{
}
int lm_proc_add_req(queue_t * q, mblk_t * mp)
{
}
int lm_proc_del_req(queue_t * q, mblk_t * mp)
{
}
int lm_link_add_req(queue_t * q, mblk_t * mp)
{
}
int lm_link_del_req(queue_t * q, mblk_t * mp)
{
}
int lm_route_add_req(queue_t * q, mblk_t * mp)
{
}
int lm_route_del_req(queue_t * q, mblk_t * mp)
{
}
int lm_reg_res(queue_t * q, mblk_t * mp)
{
}
int lm_reg_ref(queue_t * q, mblk_t * mp)
{
}
static int isua_m_w_ioctl(queue_t * q, mblk_t * mp)
{
}
static int isua_m_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 LM_REG_REF:
		return lm_reg_ref(q, mp);
	}
	return (-EOPNOTSUPP);
}
static int isua_m_w_pcproto(queue_t * q, mblk_t * mp)
{
	return isua_m_w_proto(q, mp);
}
static int isua_m_w_prim(queue_t * q, mblk_t * mp)
{
	switch (mp->b_datap->db_type) {
	case M_PROTO:
		return isua_m_w_proto(q, mp);
	case M_PCPROTO:
		return isua_m_w_pcproto(q, mp);
	case M_IOCTL:
		return isua_m_w_ioctl(q, mp);
	case M_FLUSH:
		return ua_w_flush(q, mp);
	}
	return (-EOPNOTSUPP);
}

static INT isua_m_wput(queue_t * q, mblk_t * mp)
{
	return ((INT) ua_putq(q, mp, &isua_m_w_prim));
}

static INT isua_m_wsrv(queue_t * q)
{
	return ((INT) ua_srvq(q, &isua_m_w_prim));
}

static int isua_m_r_prim(queue_t * q, mblk_t * mp)
{
	switch (mp->b_datap->db_type) {
	case M_FLUSH:
		return ua_r_flush(q, mp);
	}
	return (5);
}

static INT isua_m_rput(queue_t * q, mblk_t * mp)
{
	return ((INT) ua_putq(q, mp, &isua_m_r_prim));
}

static INT isua_m_rsrv(queue_t * q)
{
	return ((INT) ua_srvq(q, &isua_m_r_prim));
}

/* 
 *  -------------------------------------------------------------------------
 *
 *  ISUP User (ISUPU) Stream Message Handling
 *
 *  -------------------------------------------------------------------------
 */
static int isupu_info_req(queue_t * q, mblk_t * mp)
{
}
static int isupu_bind_req(queue_t * q, mblk_t * mp)
{
}
static int isupu_unbind_req(queue_t * q, mblk_t * mp)
{
}
static int isupu_unitdata_req(queue_t * q, mblk_t * mp)
{
}
static int isupu_optmgmt_req(queue_t * q, mblk_t * mp)
{
}
static int isua_u_w_ioctl(queue_t * q, mblk_t * mp)
{
}
static int isua_u_w_data(queue_t * q, mblk_t * dp)
{
	/* 
	 *  Need to convert data to SL_PDU_REQ.
	 */
	int rtn;
	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 ((rtn = slu_pdu_req(q, mp))) {
		}
		return (1);
	}
	return (-ENOBUFS);
}
static int isua_u_w_proto(queue_t * q, mblk_t * mp)
{
	switch (*((long *) mp->b - rptr)) {
	case N_INFO_REQ:
		return isupu_info_req(q, mp);
	case N_BIND_REQ:
		return isupu_bind_req(q, mp);
	case N_UNBIND_REQ:
		return isupu_unbind_req(q, mp);
	case N_UNITDATA_REQ:
		return isupu_unitdata_req(q, mp);
	case N_OPTMGMT_REQ:
		return isupu_optmgmt_req(q, mp);
	}
	return (-EOPNOTSUPP);
}
static int isua_u_w_pcproto(queue_t * q, mblk_t * mp)
{
	return isua_u_w_proto(q, mp);
}
static int isua_u_w_prim(queue_t * q, mblk_t * mp)
{
	switch (mp->b_datap->db_type) {
	case M_DATA:
		return isua_u_w_data(q, mp);
	case M_PROTO:
		return isua_u_w_proto(q, mp);
	case M_PCPROTO:
		return isua_u_w_pcproto(q, mp);
	case M_IOCTL:
		return isua_u_w_ioctl(q, mp);
	case M_FLUSH:
		return ua_w_flush(q, mp);
	}
	return (-EOPNOTSUPP);
}

static INT isua_u_wput(queue_t * q, mblk_t * mp)
{
	return ((INT) ua_putq(q, mp, &isua_u_w_prim));
}

static INT isua_u_wsrv(queue_t * q)
{
	return ((INT) ua_srvq(q, &isua_u_w_prim));
}

static int isua_u_r_data(queue_t * q, mblk_t * mp)
{
}
static int isua_u_r_ctl(queue_t * q, mblk_t * mp)
{
}
static int isua_u_r_prim(queue_t * q, mblk_t * mp)
{
	switch (mp->b_datap->db_type) {
	case M_DATA:
		return isua_u_r_data(q, mp);
	case M_CTL:
		return isua_u_r_ctl(q, mp);
	case M_FLUSH:
		return ua_r_flush(q, mp);
	}
	return (5);
}

static INT isua_u_rput(queue_t * q, mblk_t * mp)
{
	return ((INT) ua_putq(q, mp, &isua_u_r_prim));
}

static INT isua_u_rsrv(queue_t * q)
{
	return ((INT) ua_srvq(q, &isua_u_r_prim));
}

/* 
 *  -------------------------------------------------------------------------
 *
 *  ISUP Provider (ISUPP) Stream Message Handling
 *
 *  -------------------------------------------------------------------------
 */
static int isupp_info_ack(queue_t * q, mblk_t * mp)
{
}
static int isupp_bind_ack(queue_t * q, mblk_t * mp)
{
}
static int isupp_error_ack(queue_t * q, mblk_t * mp)
{
}
static int isupp_ok_ack(queue_t * q, mblk_t * mp)
{
}
static int isupp_unitdata_ind(queue_t * q, mblk_t * mp)
{
}
static int isupp_uderror_ind(queue_t * q, mblk_t * mp)
{
}
static int isua_l_w_data(queue_t * q, mblk_t * mp)
{
}
static int isua_l_w_ctl(queue_t * q, mblk_t * mp)
{
}
static int isua_l_w_error(queue_t * q, mblk_t * mp)
{
}
static int isua_l_w_hangup(queue_t * q, mblk_t * mp)
{
}
static int isua_l_w_prim(queue_t * q, mblk_t * mp)
{
	switch (mp->b_datap->db_type) {
	case M_DATA:
		return isua_l_w_data(q, mp);
	case M_CTL:
		return isua_l_w_ctl(q, mp);
	case M_ERROR:
		return isua_l_w_error(q, mp);
	case M_HANGUP:
		return isua_l_w_hangup(q, mp);
	case M_FLUSH:
		return ua_w_flush(q, mp);
	}
	return (5);
}

static INT isua_l_wput(queue_t * q, mblk_t * mp)
{
	return ((INT) ua_putq(q, mp, &isua_l_w_prim));
}

static INT isua_l_wsrv(queue_t * q)
{
	return ((INT) ua_srvq(q, &isua_l_w_prim));
}

static int isua_l_r_data(queue_t * q, mblk_t * dp)
{
	/* 
	 *  Need to convert data to SL_PDU_IND.
	 */
	int rtn;
	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 ((rtn = sl_pdu_ind(q, mp))) {
		}
		return (1);
	}
	return (-ENOBUFS);
}
static int isua_l_r_proto(queue_t * q, mblk_t * mp)
{
	switch (*((long *) mp->b_rptr)) {
	case N_INFO_ACK:
		return isupp_info_ack(q, mp);
	case N_BIND_ACK:
		return isupp_bind_ack(q, mp);
	case N_ERROR_ACK:
		return isupp_error_ack(q, mp);
	case N_OK_ACK:
		return isupp_ok_ack(q, mp);
	case N_UNITDATA_IND:
		return isupp_unitdata_ind(q, mp);
	case N_UDERROR_IND:
		return isupp_uderror_ind(q, mp);
	}
	return (-EOPNOTSUPP);
}
static int isua_l_r_pcproto(queue_t * q, mblk_t * mp)
{
	return isua_l_r_proto(q, mp);
}
static int isua_l_r_ctl(queue_t * q, mblk_t * mp)
{
}
static int isua_l_r_error(queue_t * q, mblk_t * mp)
{
}
static int isua_l_r_hangup(queue_t * q, mblk_t * mp)
{
}
static int isua_l_r_prim(queue_t * q, mblk_t * mp)
{
	switch (mp->b_datap->db_type) {
	case M_DATA:
	      return isua_l_r_data(q, mp):
	case M_PROTO:
		return isua_l_r_proto(q, mp);
	case M_PCPROTO:
		return isua_l_r_pcproto(q, mp);
	case M_CTL:
		return isua_l_r_ctl(q, mp);
	case M_ERROR:
		return isua_l_r_error(q, mp);
	case M_HANGUP:
		return isua_l_r_hangup(q, mp);
	case M_FLUSH:
		return ua_r_flush(q, mp);
	}
	return (-EOPNOTSUPP);
}

static INT isua_l_rput(queue_t * q, mblk_t * mp)
{
	return ((INT) ua_putq(q, mp, &isua_l_r_prim));
}

static INT isua_l_rsrv(queue_t * q)
{
	return ((INT) ua_srvq(q, &isua_l_r_prim));
}

/* 
 *  =========================================================================
 *
 *  OPEN and CLOSE
 *
 *  =========================================================================
 *
 *  NOTE:-  There are two specialized minor device numbers: 0 and 1.  Minor
 *          device numer '0' is a clone device that will chose the next
 *          available normal device number (major and minor).  Minor device
 *          number '1' is the control stream.  These minor device numbers only
 *          apply to the lowest numerical major device number.
 */
static int isua_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 (sflag == MODOPEN || WR(q)->q_next) {
		ptrace(("Can't open as module\n"));
		return (EIO);
	}
	if (cmajor == ISUA_CMAJOR && cminor == 1 && crp->cr_uid != 0) {
		ptrace(("Non-root priviledge user attempting to open control stream\n"));
		return (EPERM);
	}
	if (q->q_ptr != NULL) {
		ptrace(("Device already open\n"));
		return (0);
	}
	if (cmajor == ISUA_CMAJOR && cminor == 0) {
		ptrace(("Clone minor opened\n"));
		sflag = CLONEOPEN;
	}
	if (sflag == CLONEOPEN) {
		ptrace(("Clone open in effect\n"));
		cmajor = ISUA_CMAJOR;
		cminor = 2;
	}
	for (dpp = &isua_opens_list; *dpp; dpp = &(*dpp)->next) {
		ushort dmajor = getmajor(*devp);
		if (cmajor < dmajor)
			break;
		if (cmajor == dmajor) {
			ushort dminor = getminor(*devp);
			if (cminor < dminor)
				break;
			if (cminor == dminor) {
				if (sflag == CLONEOPEN) {
					if (++cminor > ISUA_NMINOR) {
						if (++cmajor > ISUA_CMAJOR + (ISUA_NMAJOR - 1))
							break;
						cminor = 0;
					}
					continue;
				}
				ptrace(("Requested device in use\n"));
				return (EIO);
			}
		}
	}
	if (cmajor > ISUA_CMAJOR + (ISUA_NMAJOR - 1)) {
		ptrace(("No devices available\n"));
		return (ENXIO);
	}
	*devp = makedevice(cmajor, cminor);
	if (!(dp = kmem_cache_alloc(ua_pp_cachep, SLAB_ATOMIC))) {
		ptrace(("Cannot allocate cache entry for device\n"));
		return (ENOMEM);
	}
	bzero(dp, sizeof(dp_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;
	dp->wq->q_ptr = dp;
	if (cmajor == ISUA_CMAJOR && cminor == 1) {
		ptrace(("Control stream opened\n"));
		dp->rq->q_minpsz = isua_m_minfo.mi_minpsz;
		dp->rq->q_maxpsz = isua_m_minfo.mi_maxpsz;
		dp->rq->q_hiwat = isua_m_minfo.mi_hiwat;
		dp->rq->q_lowat = isua_m_minfo.mi_lowat;
		dp->rq->q_qinfo = &isua_m_rinit;
		dp->wq->q_minpsz = isua_m_minfo.mi_minpsz;
		dp->wq->q_maxpsz = isua_m_minfo.mi_maxpsz;
		dp->wq->q_hiwat = isua_m_minfo.mi_hiwat;
		dp->wq->q_lowat = isua_m_minfo.mi_lowat;
		dp->wq->q_qinfo = &isua_m_winit;
	}
	return (0);
}
static int isua_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->wq->q_ptr = NULL;
	fixme(("Make sure that no XPs reference us...\n"));
	kmem_cache_free(ua_pp_cachep, dp);
	return (0);
}

/* 
 *  =========================================================================
 *
 *  LiS Module Initialization
 *
 *  =========================================================================
 */
int isua_init(void)
{
	int rtn;
	if (!isua_u_minfo.mi_idnum) {
		if ((rtn =
		     lis_register_strdev(ISUA_CMAJOR, &isua_u_info, ISUA_NMINOR,
					 isua_u_minfo.mi_idname)) < 0) {
			cmn_err(CE_WARN, "isua: couldn't register driver\n");
			return (-rtn);
		}
		isua_u_minfo.mi_idnum = rtn;
	}
	return (0);
}

void isua_terminate(void)
{
	int rtn;
	if (isua_u_minfo.mi_idnum) {
		if ((rtn = lis_unregister_strdev(isua_u_minfo.mi_idnum))) {
			cmn_err(CE_WARN, "isua: couldn't unregister driver\n");
			return;
		}
		isua_u_minfo.mi_idnum = rtn;
	}
	return;
}

/* 
 *  =========================================================================
 *
 *  Kernel Module Initialization
 *
 *  =========================================================================
 */
int init_module(void)
{
	cmn_err(CE_NOTE, ISUA_BANNER);
	return isua_init();
}

void cleanup_module(void)
{
	return isua_terminate();
}


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

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

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