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/modules/timod/timod.c


File /code/strss7/modules/timod/timod.c



#ident "@(#) $RCSfile: timod.c,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2003/06/16 09:04:09 $"

static char const ident[] = "$RCSfile: timod.c,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2003/06/16 09:04:09 $";

#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/ddi.h>
#include <sys/dki.h>

#include <sys/tpi.h>
#include <sys/xti.h>

#include "../../drivers/debug.h"
#include "../../drivers/priv.h"
#include "../../drivers/lock.h"
#include "../../drivers/queue.h"
#include "../../drivers/allocb.h"
#include "../../drivers/bufq.h"

#define TMOD_DESCRIP	"X/OPEN XNS 5.2 (TIMOD) XTI SOCKETS MODULE" "\n" \
			"Part of the OpenSS7 Stack for LiS STREAMS."
#define TMOD_COPYRIGHT	"Copyright (c) 1997-2003 OpenSS7 Corporation.  All Rights Reserved."
#define TMOD_DEVICE	"Supports LiS STREAMS TPI Drivers."
#define TMOD_CONTACT	"Brian Bidulock <bidulock@openss7.org>"
#define TMOD_LICENSE	"GPL"
#define TMOD_BANNER	TMOD_DESCRIP	"\n" \
			TMOD_COPYRIGHT	"\n" \
			TMOD_DEVICE	"\n" \
			TMOD_CONTACT	"\n"

MODULE_AUTHOR(TMOD_CONTACT);
MODULE_DESCRIPTION(TMOD_DESCRIP);
MODULE_SUPPORTED_DEVICE(TMOD_DEVICE);
#ifdef MODULE_LICENSE
MODULE_LICENSE(TMOD_LICENSE);
#endif

#ifdef LINUX_2_4
#define INT int
#else
#define INT void
#endif

/*
 *  =========================================================================
 *
 *  STREAMS Definitions
 *
 *  =========================================================================
 */
#define TMOD_MOD_NAME		"timod"
#define TMOD_MOD_ID		(TMOD_IOC_MAGIC<<8)

static struct module_info tmod_info = {
	mi_idnum:TMOD_MOD_ID,			/* Module ID number */
	mi_idname:TMOD_MOD_NAME,		/* Module name */
	mi_minpsz:0,				/* Min packet size accepted */
	mi_maxpsz:INFPSZ,			/* Max packet size accepted */
	mi_hiwat:(1 << 15),			/* Hi water mark */
	mi_lowat:(1 << 10),			/* Lo water mark */
};

static int tmod_open(queue_t *, dev_t *, int, int, cred_t *);
static int tmod_close(queue_t *, int, cred_t *);

static struct qinit tmod_rinit = {
	qi_putp:ss7_oput,			/* Read put (msg from below) */
	qi_qopen:tmod_open,			/* Each open */
	qi_qclose:tmod_close,			/* Last close */
	qi_minfo:&tmod_minfo,			/* Information */
};

static struct qinit tmod_winit = {
	qi_putp:ss7_iput,			/* Write put (msg from above) */
	qi_minfo:&tmod_minfo,			/* Information */
};

static struct streamtab tmod_info = {
	st_rdinit:&tmod_rinit,			/* Upper read queue */
	st_wrinit:&tmod_winit,			/* Upper write queue */
};

/*
 *  =========================================================================
 *
 *  Private Structure
 *
 *  =========================================================================
 */
typedef struct tmod {
	STR_DECLARATION (struct tmod);		/* stream declarations */
	tmod_addr_t src;			/* src address */
	tmod_size_t src_len;			/* src address length */
	tmod_addr_t dst;			/* dst address */
	tmod_size_t dst_len;			/* dst address length */
	bufq_t conq;				/* connection indication queue */
	uint conind;				/* number of connection indications */
} tmod_t;

#define TMOD_PRIV(q) ((struct tmod *)((__q)->q_ptr)

/*
 *  -------------------------------------------------------------------------
 *
 *  Private structure allocation, deallocation and cache
 *
 *  -------------------------------------------------------------------------
 */
STATIC kmem_cache_t *tmod_priv_cachep = NULL;
STATIC int tmod_init_caches(void)
{
	if (!tmod_priv_cachep &&
	    !(tmod_priv_cachep = kmem_cache_create
	      ("tmod_priv_cachep", sizeof(struct tmod), 0, SLAB_HWCACHE_ALIGN, NULL, NULL))) {
		cmn_err(CE_PANIC, "%s: ERROR: could not allocate tmod_priv_cachep", __FUNCTION__);
		return (-ENOMEM);
	} else
		printd(("%s: intialized tmod private cache\n", TMOD_MOD_NAME));
	return (0);
}
STATIC void tmod_term_caches(void)
{
	if (tmod_priv_cachep) {
		if (kmem_cache_destroy(tmod_priv_cachep))
			cmn_err(CE_WARN, "%s: ERROR: could not destroy tmod_priv_cachep", __FUNCTION__);
		else
			printd(("%s: destroyed tmod_priv_cachep\n", TMOD_MOD_NAME));
	}
	return;
}

/*
 *  TIMOD allocation and deallocation
 *  -------------------------------------------------------------------------
 */
STATIC struct tmod *tmod_alloc_priv(queue_t *q, struct tmod **tmodp, dev_t *devp, cred_t *crp)
{
	struct tmod *tmod;
	if ((tmod = kmem_cache_alloc(tmod_priv_cachep, SLAB_ATOMIC))) {
		printd(("%s: %p: allocated tmod private structure\n", TMOD_MOD_NAME, tmod));
		bzero(tmod, sizeof(*tmod));
		tmod->u.dev.cmajor = getmajor(*devp);
		tmod->u.dev.cminor = getminor(*devp);
		tmod->cred = *crp;
		lis_spin_lock_init(&tmod->qlock, "tmod-queue-lock");
		(tmod->oq = RD(q))->q_ptr = tmod_get(tmod);
		(tmod->iq = WR(q))->q_ptr = tmod_get(tmod);
		tmod->o_prim = &tmod_r_prim;
		tmod->i_prim = &tmod_w_prim;
		tmod->o_wakeup = NULL;
		tmod->i_wakeup = NULL;
		tmod->state = 0;	/* unintialized */
		lis_spin_lock_init(&tmod->lock, "tmod-lock");
		if ((tmod->next = *tmodp))
			tmod->next->prev = &tmod->next;
		tmod->prev = tmodp;
		*tmodp = tmod_get(tmod);
		printd(("%s: %p: linked tmod private structure\n", TMOD_MOD_NAME));
	} else
		ptrace(("%s: ERROR: could not allocate tmod private structure\n", TMOD_MOD_NAME));
	return (tmod);
}
STATIC void tmod_free_priv(queue_t *q)
{
	struct tmod *tmod = TMOD_PRIV(q);
	int flags = 0;
	ensure(tmod, return);
	lis_spin_lock_irqsave(&tmod->lock, &flags);
	{
		ss7_unbufcall((str_t *) tmod);
		if ((*tmod->prev = tmod->next))
			tmod->next->prev = tmod->prev;
		tmod->next = NULL;
		tmod->prev = &tmod->next;
		tmod_put(tmod);
		tmod->oq->q_ptr = NULL;
		flushq(tmod->oq, FLUSHALL);
		tmod->oq = NULL;
		tmod_put(tmod);
		tmod->iq->q_ptr = NULL;
		flushq(tmod->iq, FLUSHALL);
		tmod->iq = NULL;
	}
	lis_spin_lock_irqrestore(&tmod->lock, &flags);
	tmod_put(tmod);		/* final put */
	return;
}
STATIC struct tmod *tmod_get(struct tmod *tmod)
{
	atomic_inc(&tmod->refcnt);
	return (tmod);
}
STATIC void tmod_put(struct tmod *tmod)
{
	if (atomic_dec_and_test(&tmod->refcnt)) {
		kmem_cache_free(tmod_priv_cachep);
		printd(("%s: %p: freed tmod private structure\n", TMOD_MOD_NAME, tmod));
	}
}

/*
 *  =========================================================================
 *
 *  PROTOCOL PRIMITIVES
 *
 *  =========================================================================
 */

/*
 *  -------------------------------------------------------------------------
 *
 *  Primitives from above
 *
 *  -------------------------------------------------------------------------
 */
/*
 *  T_CONN_REQ
 *  -----------------------------------
 */
STATIC int t_conn_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_CONN_RES
 *  -----------------------------------
 */
STATIC int t_conn_res(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_DISCON_REQ
 *  -----------------------------------
 */
STATIC int t_discon_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_DATA_REQ
 *  -----------------------------------
 */
STATIC int t_data_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_EXDATA_REQ
 *  -----------------------------------
 */
STATIC int t_exdata_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_INFO_REQ
 *  -----------------------------------
 */
STATIC int t_info_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_BIND_REQ
 *  -----------------------------------
 */
STATIC int t_bind_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_UNBIND_REQ
 *  -----------------------------------
 */
STATIC int t_unbind_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_UNITDATA_REQ
 *  -----------------------------------
 */
STATIC int t_unitdata_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_OPTMGMT_REQ
 *  -----------------------------------
 */
STATIC int t_optmgmt_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_ORDREL_REQ
 *  -----------------------------------
 */
STATIC int t_ordrel_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_OPTDATA_REQ
 *  -----------------------------------
 */
STATIC int t_optdata_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_ADDR_REQ
 *  -----------------------------------
 */
STATIC int t_addr_req(queue_t *q, mblk_t *mp)
{
}

/*
 *  -------------------------------------------------------------------------
 *
 *  Primitives from below
 *
 *  -------------------------------------------------------------------------
 */

/*
 *  T_CONN_IND
 *  -----------------------------------
 */
STATIC int t_conn_ind(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_CONN_CON
 *  -----------------------------------
 */
STATIC int t_conn_con(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_DISCON_IND
 *  -----------------------------------
 */
STATIC int t_discon_ind(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_DATA_IND
 *  -----------------------------------
 */
STATIC int t_data_ind(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_EXDATA_IND
 *  -----------------------------------
 */
STATIC int t_exdata_ind(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_INFO_ACK
 *  -----------------------------------
 */
STATIC int t_info_ack(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_BIND_ACK
 *  -----------------------------------
 */
STATIC int t_bind_ack(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_ERROR_ACK
 *  -----------------------------------
 */
STATIC int t_error_ack(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_OK_ACK
 *  -----------------------------------
 */
STATIC int t_ok_ack(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_UNITDATA_IND
 *  -----------------------------------
 */
STATIC int t_unitdata_ind(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_UDERROR_IND
 *  -----------------------------------
 */
STATIC int t_uderror_ind(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_OPTMGMT_ACK
 *  -----------------------------------
 */
STATIC int t_optmgmt_ack(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_ORDREL_IND
 *  -----------------------------------
 */
STATIC int t_ordrel_ind(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_OPTDATA_IND
 *  -----------------------------------
 */
STATIC int t_optdata_ind(queue_t *q, mblk_t *mp)
{
}

/*
 *  T_ADDR_ACK
 *  -----------------------------------
 */
STATIC int t_addr_ack(queue_t *q, mblk_t *mp)
{
}

/*
 *  =========================================================================
 *
 *  I/O Controls
 *
 *  =========================================================================
 */

/*
 *  TI_GETINFO
 *  -----------------------------------
 */
STATIC int tmod_ti_getinfo(queue_t *q, mblk_t *mp, int *rvp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	struct copyresp *resp = (typeof(resp)) mp->b_rptr;
	switch (mp->b_datap->db_type) {
	case M_IOCTL:
		break;
	case M_IOCDATA:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCACK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCNAK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	default:
		*rvp = -1;
		return (-EINVAL);
	}
}

/*
 *  TI_OPTMGMT
 *  -----------------------------------
 */
STATIC int tmod_ti_optmgmt(queue_t *q, mblk_t *mp, int *rvp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	struct copyresp *resp = (typeof(resp)) mp->b_rptr;
	switch (mp->b_datap->db_type) {
	case M_IOCTL:
		break;
	case M_IOCDATA:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCACK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCNAK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	default:
		*rvp = -1;
		return (-EINVAL);
	}
}

/*
 *  TI_BIND
 *  -----------------------------------
 */
STATIC int tmod_ti_bind(queue_t *q, mblk_t *mp, int *rvp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	struct copyresp *resp = (typeof(resp)) mp->b_rptr;
	switch (mp->b_datap->db_type) {
	case M_IOCTL:
		break;
	case M_IOCDATA:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCACK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCNAK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	default:
		*rvp = -1;
		return (-EINVAL);
	}
}

/*
 *  TI_UNBIND
 *  -----------------------------------
 */
STATIC int tmod_ti_unbind(queue_t *q, mblk_t *mp, int *rvp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	struct copyresp *resp = (typeof(resp)) mp->b_rptr;
	switch (mp->b_datap->db_type) {
	case M_IOCTL:
		break;
	case M_IOCDATA:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCACK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCNAK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	default:
		*rvp = -1;
		return (-EINVAL);
	}
}

/*
 *  TI_GETMYNAME
 *  -----------------------------------
 */
STATIC int tmod_ti_getmyname(queue_t *q, mblk_t *mp, int *rvp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	struct copyresp *resp = (typeof(resp)) mp->b_rptr;
	switch (mp->b_datap->db_type) {
	case M_IOCTL:
		break;
	case M_IOCDATA:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCACK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCNAK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	default:
		*rvp = -1;
		return (-EINVAL);
	}
}

/*
 *  TI_GETPEERNAME
 *  -----------------------------------
 */
STATIC int tmod_ti_getpeername(queue_t *q, mblk_t *mp, int *rvp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	struct copyresp *resp = (typeof(resp)) mp->b_rptr;
	switch (mp->b_datap->db_type) {
	case M_IOCTL:
		break;
	case M_IOCDATA:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCACK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCNAK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	default:
		*rvp = -1;
		return (-EINVAL);
	}
}

/*
 *  TI_SETMYNAME
 *  -----------------------------------
 */
STATIC int tmod_ti_setmyname(queue_t *q, mblk_t *mp, int *rvp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	struct copyresp *resp = (typeof(resp)) mp->b_rptr;
	switch (mp->b_datap->db_type) {
	case M_IOCTL:
		break;
	case M_IOCDATA:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCACK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCNAK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	default:
		*rvp = -1;
		return (-EINVAL);
	}
}

/*
 *  TI_SETPEERNAME
 *  -----------------------------------
 */
STATIC int tmod_ti_setpeername(queue_t *q, mblk_t *mp, int *rvp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	struct copyresp *resp = (typeof(resp)) mp->b_rptr;
	switch (mp->b_datap->db_type) {
	case M_IOCTL:
		break;
	case M_IOCDATA:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCACK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	case M_IOCNAK:
		switch (tmod->ioc_state) {
		case TMOD_IOCS_NULL:
			*rvp = -1;
			return (-EINVAL);
		}
		break;
	default:
		*rvp = -1;
		return (-EINVAL);
	}
}

/*
 *  =========================================================================
 *
 *  STREAMS Message Handling
 *
 *  =========================================================================
 *
 *  M_IOCTL Handling
 *
 *  -------------------------------------------------------------------------
 */
STATIC int tmod_w_ioctl(queue_t *q, mblk_t *mp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	void *arg = mp->b_cont ? mp->b_cont->b_rptr : NULL;
	int cmd = iocp->ioc_cmd, count = iocp->ioc_count;
	int type = _IOC_TYPE(cmd), nr = _IOC_NR(cmd), size = _IOC_SIZE(cmd);
	int err = -EOPNOTSUPP, ret = -1;
	switch (type) {
	case TMOD_IOC_MAGIC:
	{
		/* These are TIMOD IOCTLs */
		switch (nr) {
		case _IOC_NR(TI_GETINFO):
			printd(("%s: %p: -> TI_GETINFO\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_getinfo(q, mp, &ret);
			break;
		case _IOC_NR(TI_OPTMGMT):
			printd(("%s: %p: -> TI_OPTMGMT\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_optmgmt(q, mp, &ret);
			break;
		case _IOC_NR(TI_BIND):
			printd(("%s: %p: -> TI_BIND\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_bind(q, mp, &ret);
			break;
		case _IOC_NR(TI_UNBIND):
			printd(("%s: %p: -> TI_UNBIND\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_unbind(q, mp, &ret);
			break;
		case _IOC_NR(TI_GETMYNAME):
			printd(("%s: %p: -> TI_GETMYNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_getmyname(q, mp, &ret);
			break;
		case _IOC_NR(TI_GETPEERNAME):
			printd(("%s: %p: -> TI_GETPEERNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_getpeername(q, mp, &ret);
			break;
		case _IOC_NR(TI_SETMYNAME):
			printd(("%s: %p: -> TI_SETMYNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_setmyname(q, mp, &ret);
			break;
		case _IOC_NR(TI_SETPEERNAME):
			printd(("%s: %p: -> TI_SETPEERNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_setpeername(q, mp, &ret);
			break;
		default:
			ptrace(("%s: %p: ERROR: Unsupported TIMOD ioctl %c, %d\n", SOCK_MOD_NAME,
				tmod(char) type, nr));
			break;
		}
		break;
	}
	default:
		ptrace(("%s: %p: ERROR: Unsupported ioctl %c, %d\n", SOCK_MOD_NAME, tmod, (char) type, nr));
		break;
	}
	if (err > 0)
		return (err);
	else if (err == 0)
		mp->b_datap->db_type = M_IOCACK;
	else
		mp->b_datap->db_type = M_IOCNAK;
	iocp->ioc_error = -err;
	iocp->ioc_rval = ret;
	qreply(q, mp);
	return (QR_ABSORBED);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_IOCDATA Handling
 *
 *  -------------------------------------------------------------------------
 */
STATIC int tmod_w_iocdata(queue_t *q, mblk_t *mp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct copyresp *resp = (typeof(resp)) mp->b_rptr;
	mblk_t *dp = mp->b_cont;
	void *arg = dp ? dp->b_rptr : NULL;
	int cmd = resp->cp_cmd, count = dp ? dp->b_wptr - dp->b_rptr : 0;
	int type = _IOC_TYPE(cmd), nr = _IOC_NR(cmd), size = _IOC_SIZE(cmd);
	int err = -EOPNOTSUPP, ret = -1;
	if (resp->cp_rval != 0)
		goto efault;
	if (tmod->ioc_state == IOC_STATE_NULL)
		goto einval;
	switch (type) {
	case TMOD_IOC_MAGIC:
	{
		/* These are TIMOD IOCTLs */
		switch (nr) {
		case _IOC_NR(TI_GETINFO):
			printd(("%s: %p: -> TI_GETINFO\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_getinfo(q, mp, &ret);
			break;
		case _IOC_NR(TI_OPTMGMT):
			printd(("%s: %p: -> TI_OPTMGMT\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_optmgmt(q, mp, &ret);
			break;
		case _IOC_NR(TI_BIND):
			printd(("%s: %p: -> TI_BIND\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_bind(q, mp, &ret);
			break;
		case _IOC_NR(TI_UNBIND):
			printd(("%s: %p: -> TI_UNBIND\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_unbind(q, mp, &ret);
			break;
		case _IOC_NR(TI_GETMYNAME):
			printd(("%s: %p: -> TI_GETMYNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_getmyname(q, mp, &ret);
			break;
		case _IOC_NR(TI_GETPEERNAME):
			printd(("%s: %p: -> TI_GETPEERNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_getpeername(q, mp, &ret);
			break;
		case _IOC_NR(TI_SETMYNAME):
			printd(("%s: %p: -> TI_SETMYNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_setmyname(q, mp, &ret);
			break;
		case _IOC_NR(TI_SETPEERNAME):
			printd(("%s: %p: -> TI_SETPEERNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_setpeername(q, mp, &ret);
			break;
		default:
			ptrace(("%s: %p: ERROR: Unsupported TIMOD ioctl %c, %d\n", SOCK_MOD_NAME,
				tmod(char) type, nr));
			break;
		}
		break;
	}
	default:
		ptrace(("%s: %p: ERROR: Unsupported ioctl %c, %d\n", SOCK_MOD_NAME, tmod, (char) type, nr));
		break;
	}
      done:
	if (err > 0)
		return (err);
	else if (err == 0)
		mp->b_datap->db_type = M_IOCACK;
	else
		mp->b_datap->db_type = M_IOCNAK;
	iocp->ioc_error = -err;
	iocp->ioc_rval = ret;
	qreply(q, mp);
	return (QR_ABSORBED);
      efault:
	err = -EFAULT;
	ret = -1;
	goto done;
      einval:
	err = -EINVAL;
	ret = -1;
	goto done;
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_IOCACK, M_IOCNAK Handling
 *
 *  -------------------------------------------------------------------------
 */
STATIC int tmod_r_iocack(queue_t *q, mblk_t *mp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	struct iocblk *iocp = (typeof(iocp)) mp->b_rptr;
	mblk_t *bp = mp->b_cont;
	void *arg = bp ? bp->b_rptr : NULL;
	int cmd = iocp->ioc_cmd, count = iocp->ioc_count;
	int type = _IOC_TYPE(cmd), nr = _IOC_NR(cmd), size = _IOC_SIZE(cmd);
	int err = QR_PASSALONG, ret = -1;
	if (iocp->ioc_id != ss->ioc_id)
		goto passalong;
	switch (type) {
	case TMOD_IOC_MAGIC:
	{
		/* These are TIMOD IOCTLs */
		switch (nr) {
		case _IOC_NR(TI_GETINFO):
			printd(("%s: %p: -> TI_GETINFO\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_getinfo(q, mp, &ret);
			break;
		case _IOC_NR(TI_OPTMGMT):
			printd(("%s: %p: -> TI_OPTMGMT\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_optmgmt(q, mp, &ret);
			break;
		case _IOC_NR(TI_BIND):
			printd(("%s: %p: -> TI_BIND\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_bind(q, mp, &ret);
			break;
		case _IOC_NR(TI_UNBIND):
			printd(("%s: %p: -> TI_UNBIND\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_unbind(q, mp, &ret);
			break;
		case _IOC_NR(TI_GETMYNAME):
			printd(("%s: %p: -> TI_GETMYNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_getmyname(q, mp, &ret);
			break;
		case _IOC_NR(TI_GETPEERNAME):
			printd(("%s: %p: -> TI_GETPEERNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_getpeername(q, mp, &ret);
			break;
		case _IOC_NR(TI_SETMYNAME):
			printd(("%s: %p: -> TI_SETMYNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_setmyname(q, mp, &ret);
			break;
		case _IOC_NR(TI_SETPEERNAME):
			printd(("%s: %p: -> TI_SETPEERNAME\n", TMOD_MOD_NAME, tmod));
			err = tmod_ti_setpeername(q, mp, &ret);
			break;
		default:
			ptrace(("%s: %p: ERROR: Unsupported TIMOD ioctl %c, %d\n", SOCK_MOD_NAME,
				tmod(char) type, nr));
			break;
		}
		break;
	}
	}
      done:
	if (err > 0)
		return (err);
	else if (err == 0)
		mp->b_datap->db_type = M_IOCACK;
	else
		mp->b_datap->db_type = M_IOCNAK;
	iocp->ioc_error = -err;
	iocp->ioc_rval = ret;
	putnext(q, mp);
	return (QR_ABSORBED);
      efault:
	err = -EFAULT;
	ret = -1;
	goto done;
      passalong:
	err = QR_PASSALONG;
	ret = 0;
	goto done;
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_PROTO, M_PCPROTO Handling
 *
 *  -------------------------------------------------------------------------
 */
/*
 *  Primitives from TIMOD user to TIMOD
 *  -----------------------------------------------------------
 */
STATIC int tmod_w_proto(queue_t *q, mblk_t *mp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	int rtn;
	ulong prim;
	(void) tmod;
	switch ((prim = *(ulong *) mp->b_rptr)) {
	case T_CONN_REQ:
		printd(("%s: %p: -> T_CONN_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_conn_req(q, mp);
		break;
	case T_CONN_RES:
		printd(("%s: %p: -> T_CONN_RES\n", TMOD_MOD_NAME, tmod));
		rtn = t_conn_res(q, mp);
		break;
	case T_DISCON_REQ:
		printd(("%s: %p: -> T_DISCON_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_discon_req(q, mp);
		break;
	case T_DATA_REQ:
		printd(("%s: %p: -> T_DATA_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_data_req(q, mp);
		break;
	case T_EXDATA_REQ:
		printd(("%s: %p: -> T_EXDATA_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_exdata_req(q, mp);
		break;
	case T_INFO_REQ:
		printd(("%s: %p: -> T_INFO_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_info_req(q, mp);
		break;
	case T_BIND_REQ:
		printd(("%s: %p: -> T_BIND_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_bind_req(q, mp);
		break;
	case T_UNBIND_REQ:
		printd(("%s: %p: -> T_UNBIND_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_unbind_req(q, mp);
		break;
	case T_UNITDATA_REQ:
		printd(("%s: %p: -> T_UNITDATA_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_unitdata_req(q, mp);
		break;
	case T_OPTMGMT_REQ:
		printd(("%s: %p: -> T_OPTMGMT_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_optmgmt_req(q, mp);
		break;
	case T_ORDREL_REQ:
		printd(("%s: %p: -> T_ORDREL_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_ordrel_req(q, mp);
		break;
	case T_OPTDATA_REQ:
		printd(("%s: %p: -> T_OPTDATA_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_optdata_req(q, mp);
		break;
	case T_ADDR_REQ:
		printd(("%s: %p: -> T_ADDR_REQ\n", TMOD_MOD_NAME, tmod));
		rtn = t_addr_req(q, mp);
		break;
	default:
		printd(("%s: %p: -> T_????\n", TMOD_MOD_NAME, tmod));
		rtn = QR_PASSALONG;
		break;
	}
	return (rtn);
}

/*
 *  Primitives from TPI provider to TIMOD
 *  -----------------------------------------------------------
 */
STATIC int tmod_r_proto(queue_t *q, mblk_t *mp)
{
	struct tmod *tmod = TMOD_PRIV(q);
	int rtn;
	ulong prim;
	(void) tmod;
	switch ((prim = *(ulong *) mp->b_rptr)) {
	case T_CONN_IND:
		printd(("%s: %p: T_CONN_IND <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_conn_ind(q, mp);
		break;
	case T_CONN_CON:
		printd(("%s: %p: T_CONN_CON <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_conn_con(q, mp);
		break;
	case T_DISCON_IND:
		printd(("%s: %p: T_DISCON_IND <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_discon_ind(q, mp);
		break;
	case T_DATA_IND:
		printd(("%s: %p: T_DATA_IND <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_data_ind(q, mp);
		break;
	case T_EXDATA_IND:
		printd(("%s: %p: T_EXDATA_IND <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_exdata_ind(q, mp);
		break;
	case T_INFO_ACK:
		printd(("%s: %p: T_INFO_ACK <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_info_ack(q, mp);
		break;
	case T_BIND_ACK:
		printd(("%s: %p: T_BIND_ACK <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_bind_ack(q, mp);
		break;
	case T_ERROR_ACK:
		printd(("%s: %p: T_ERROR_ACK <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_error_ack(q, mp);
		break;
	case T_OK_ACK:
		printd(("%s: %p: T_OK_ACK <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_ok_ack(q, mp);
		break;
	case T_UNITDATA_IND:
		printd(("%s: %p: T_UNITDATA_IND <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_unitdata_ind(q, mp);
		break;
	case T_UDERROR_IND:
		printd(("%s: %p: T_UDERROR_IND <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_uderror_ind(q, mp);
		break;
	case T_OPTMGMT_ACK:
		printd(("%s: %p: T_OPTMGMT_ACK <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_optmgmt_ack(q, mp);
		break;
	case T_ORDREL_IND:
		printd(("%s: %p: T_ORDREL_IND <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_ordrel_ind(q, mp);
		break;
	case T_OPTDATA_IND:
		printd(("%s: %p: T_OPTDATA_IND <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_optdata_ind(q, mp);
		break;
	case T_ADDR_ACK:
		printd(("%s: %p: T_ADDR_ACK <-\n", TMOD_MOD_NAME, tmod));
		rtn = t_addr_ack(q, mp);
		break;
	default:
		printd(("%s: %p: T_???? <-\n", TMOD_MOD_NAME, tmod));
		rtn = QR_PASSALONG;
		break;
	}
	return (rtn);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_DATA Handling
 *
 *  -------------------------------------------------------------------------
 */
STATIC INLINE int tmod_w_data(queue_t *q, mblk_t *mp)
{
	/* data from above */
	printd(("%s: %p: -> M_DATA\n", TMOD_MOD_NAME, TMOD_PRIV(q)));
	return (QR_PASSFLOW);
}
STATIC INLINE int tmod_r_data(queue_t *q, mblk_t *mp)
{
	/* data from below */
	printd(("%s: %p: M_DATA <-\n", TMOD_MOD_NAME, TMOD_PRIV(q)));
	return (QR_PASSFLOW);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_ERROR, M_HANGUP Handling
 *
 *  -------------------------------------------------------------------------
 */
STATIC int tmod_r_error(queue_t *q, mblk_t *mp)
{
	printd(("%s: %p: M_ERROR <-\n", TMOD_MOD_NAME, TMOD_PRIV(q)));
	tmod->state = TMODS_UNUSABLE;
	return (QR_PASSALONG);
}
STATIC int tmod_r_hangup(queue_t *q, mblk_t *mp)
{
	printd(("%s: %p: M_HANGUP <-\n", TMOD_MOD_NAME, TMOD_PRIV(q)));
	tmod->state = TMODS_UNUSABLE;
	return (QR_PASSALONG);
}

/*
 *  =========================================================================
 *
 *  PUT and SRV
 *
 *  =========================================================================
 */
STATIC INLINE int tmod_w_prim(queue_t *q, mblk_t *mp)
{
	ulong type;
	/* Fast Path */
	if ((type = mp->b_datap->db_type) == M_DATA)
		return tmod_w_data(q, mp);
	switch (type) {
	case M_DATA:
		return tmod_w_data(q, mp);
	case M_PROTO:
	case M_PCPROTO:
		return tmod_w_proto(q, mp);
	case M_FLUSH:
		return ss7_w_flush(q, mp);
	case M_IOCTL:
		return tmod_w_ioctl(q, mp);
	case M_IOCDATA:
		return tmod_w_iocdata(q, mp);
	}
	return (QR_PASSALONG);
}
STATIC INLINE int tmod_r_prim(queue_t *q, mblk_t *mp)
{
	ulong type;
	/* Fast Path */
	if ((type = mp->b_datap->db_type) == M_DATA)
		return tmod_r_data(q, mp);
	switch (type) {
	case M_DATA:
		return tmod_r_data(q, mp);
	case M_PROTO:
	case M_PCPROTO:
		return tmod_r_proto(q, mp);
	case M_FLUSH:
		return ss7_r_flush(q, mp);
	case M_IOCACK:
	case M_IOCNAK:
		return tmod_r_iocack(q, mp);
	case M_ERROR:
		return tmod_r_error(q, mp);
	case M_HANGUP:
		return tmod_r_hangup(q, mp);
	}
	return (QR_PASSALONG);
}

/*
 *  =========================================================================
 *
 *  OPEN and CLOSE
 *
 *  =========================================================================
 */
STATIC int tmod_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
{
	int err;
	MOD_INC_USE_COUNT;	/* keep module from unloading */
	if (q->q_ptr != NULL) {
		MOD_DEC_USE_COUNT;
		return (0);	/* already open */
	}
	if (sflag == MODOPEN || WR(q)->q_next != NULL) {
		int cmajor = getmajor(*devp);
		int cminor = getminor(*devp);
		struct tmod *tmod;
		for (tmod = tmod_opens; tmod; tmod = tmod->next) {
			if (tmod->u.dev.cmajor == cmajor && tmod->u.dev.cminor == cminor) {
				MOD_DEC_USE_COUNT;
				return (ENXIO);	/* double push */
			}
		}
		if (!tmod_alloc_priv(q, &tmod_opens, devp, crp)) {
			MOD_DEC_USE_COUNT;
			return (ENOMEM);
		}
		/* generate immediate information request */
		if ((err = t_info_req(q)) < 0) {
			tmod_free_priv(q);
			MOD_DEC_USE_COUNT;
			return (-err);
		}
		return (0);
	}
	MOD_DEC_USE_COUNT;
	return (EIO);		/* can't be opened as driver */
}
STATIC int tmod_close(queue_t *q, int flag, cred_t *crp)
{
	(void) flag;
	(void) crp;
	tmod_free_priv(q);
	MOD_DEC_USE_COUNT;
	return (0);
}

/*
 *  =========================================================================
 *
 *  LiS Module Initialization
 *
 *  =========================================================================
 */
STAIC int tmod_initialized = 0;
void tmod_init(void)
{
	unless(tmod_initialized > 0, return);
	cmn_err(CE_NOTE, TMOD_BANNER);	/* console splash */
	if ((tmod_initialized = tmod_init_caches())) {
		cmn_err(CE_PANIC, "%s: ERROR: could not allocate caches", TMOD_MOD_NAME);
	} else if ((tmod_initialized = lis_register_strmod(&tmod_info, TMOD_NOD_NAME)) < 0) {
		cmn_err(CE_WARN, "%s: ERROR: could not register module", TMOD_MOD_NAME);
		tmod_term_caches();
	}
	return;
}
void tmod_term(void)
{
	ensure(tmod_initialized > 0, return);
	if ((tmod_initialized = lis_unregister_strmod(&tmod_info)) < 0) {
		cmn_err(CE_PANIC, "%s: ERROR: could not unregister module", TMOD_MOD_NAME);
	} else {
		tmod_term_caches();
	}
	return;
}

/*
 *  =========================================================================
 *
 *  Kernel Module Initialization
 *
 *  =========================================================================
 */
int init_module(void)
{
	tmod_init();
	if (tmod_initialized < 0)
		return tmod_initialized;
	return (0);
}
void cleanup_module(void)
{
	tmod_terminate();
	return;
}


Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/modules/timod/timod.c

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

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