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/sscop/sscop2.c


File /code/strss7/drivers/sscop/sscop2.c



#ident "@(#) $RCSfile: sscop2.c,v $ $Name:  $($Revision: 0.8.2.5 $) $Date: 2003/04/14 12:13:34 $"

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

#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/dlk.h>

#include <sys/npi.h>
#include <sys/npi_ip.h>

#include "../debug.h"
#include "../bufq.h"

#define SSCOP_DESCRIP	"SSCOP STREAMS MODULE."
#define SSCOP_COPYRIGHT	"Copyright (c) 1997-2002 OpenSS7 Corporation.  All Rights Reserved."
#define SSCOP_DEVICE	"Part of the OpenSS7 Stack for LiS STREAMS."
#define SSCOP_CONTACT	"Brian Bidulock <bidulock@openss7.org>"
#define SSCOP_LICENSE	"GPL"
#define SSCOP_BANNER	SSCOP_DESCRIP	"\n" \
			SSCOP_COPYRIGHT	"\n" \
			SSCOP_DEVICE	"\n" \
			SSCOP_CONTACT	"\n"

MODULE_AUTHOR(SSCOP_CONTACT);
MODULE_DESCRIPTION(SSCOP_DESCRIP);
MODULE_SUPPORTED_DEVICE(SSCOP_DEVICE);
#ifdef MODULE_LICENSE
MODULE_LICENSE(SSCOP_LICENSE);
#endif

#ifndef INT
#define INT void
#endif

typedef void (*bufcall_fnc_t) (long);

/*
 *  =========================================================================
 *
 *  STREAMS Definitions
 *
 *  =========================================================================
 */
static struct module_info s_minfo = {
	0,				/* Module ID number */
	"sscop",			/* Module name */
	0,				/* Min packet size accepted */
	INFPSZ,				/* Max packet size accepted */
	1 << 15,			/* Hi water mark */
	1 << 10				/* Lo water mark */
};

static int s_open(queue_t *, dev_t *, int, int, cred_t *);
static int s_close(queue_t *, int, cred_t *);

static INT s_rput(queue_t *, mblk_t *);

static struct qinit s_rinit = {
	s_rput,				/* Read put (msg from below) */
	NULL,				/* Read queue service */
	s_open,				/* Each open */
	s_close,			/* Last close */
	NULL,				/* Admin (not used) */
	&s_minfo,			/* Information */
	NULL				/* Statistics */
};

static INT s_wput(queue_t *, mblk_t *);

static struct qinit s_winit = {
	s_wput,				/* Write put (msg from below) */
	NULL,				/* Write queue service */
	NULL,				/* Each open */
	NULL,				/* Last close */
	NULL,				/* Admin (not used) */
	&s_minfo,			/* Information */
	NULL				/* Statistics */
};

static struct streamtab s_info = {
	&s_rinit,			/* Upper read queue */
	&s_winit,			/* Upper write queue */
	NULL,				/* Lower read queue */
	NULL				/* Lower write queue */
};

/*
 *  =========================================================================
 *
 *  SSCOP Private Structure
 *
 *  =========================================================================
 */

typedef struct sscop {
	queue_t *rq;			/* read queue */
	queue_t *wq;			/* write queue */
	uint i_state;			/* interface state */
	ulong token;			/* my bind token */

	bufq_t rb;			/* receive buffer */
	bufq_t tb;			/* transmission buffer */
	bufq_t rtb;			/* retransmission buffer */

} sscop_t;

/*
 *
 *
 *
 *
 *
 *
 *
 *
 *  FIXME: Much more to do here....
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

/*
 *  =========================================================================
 *
 *  STREAMS Message Handling
 *
 *  =========================================================================
 */
/*
 *  -------------------------------------------------------------------------
 *
 *  M_IOCTL Handling
 *
 *  -------------------------------------------------------------------------
 */
static int s_w_iocdata(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (4);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_IOCDATA Handling
 *
 *  -------------------------------------------------------------------------
 */
static int s_w_iocdata(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (4);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_PROTO, M_PCPROTO Handling
 *
 *  -------------------------------------------------------------------------
 */
static int s_w_proto(queue_t * q, mblk_t * mp)
{
	int rtn;
	sscop_t *sp = (sscop_t *) q->q_ptr;
	uint oldstate = sp->i_state;
	switch (*((long *) mp->b_rptr)) {
	case N_CONN_REQ:
		rtn = n_conn_req(sp, mp);
		break;
	case N_CONN_RES:
		rtn = n_conn_res(sp, mp);
		break;
	case N_DISCON_REQ:
		rtn = n_discon_req(sp, mp);
		break;
	case N_DATA_REQ:
		rtn = n_data_req(sp, mp);
		break;
	case N_EXDATA_REQ:
		rtn = n_exdata_req(sp, mp);
		break;
	case N_INFO_REQ:
		rtn = n_info_req(sp, mp);
		break;
	case N_BIND_REQ:
		rtn = n_bind_req(sp, mp);
		break;
	case N_UNBIND_REQ:
		rtn = n_unbind_req(sp, mp);
		break;
	case N_UNITDATA_REQ:
		rtn = n_unitdata_req(sp, mp);
		break;
	case N_OPTMGMT_REQ:
		rtn = n_optmgmt_req(sp, mp);
		break;
	case N_DATACK_REQ:
		rtn = n_datack_req(sp, mp);
		break;
	case N_RESET_REQ:
		rtn = n_reset_req(sp, mp);
		break;
	case N_RESET_RES:
		rtn = n_reset_res(sp, mp);
		break;
	default:
		rtn = -EOPNOTSUPP;
		break;
	}
	if (rtn < 0) {
		seldom();
		sp->i_state = oldstate;
	}
	return (rtn);
}
static int s_r_proto(queue_t q, mblk_t * mp)
{
	int rtn;
	sscop_t *sp = (sscop_t *) q->q_ptr;
	switch (*((long *) mp->b_rptr)) {
	case N_INFO_ACK:
		rtn = l_info_ack(sp, mp);
		break;
	case N_BIND_ACK:
		rtn = l_bind_ack(sp, mp);
		break;
	case N_ERROR_ACK:
		rtn = l_error_ack(sp, mp);
		break;
	case N_OK_ACK:
		rtn = l_ok_ack(sp, mp);
		break;
	case N_UNITDATA_IND:
		rtn = l_unitdata_ind(sp, mp);
		break;
	case N_UDERROR_IND:
		rtn = l_uderror_ind(sp, mp);
		break;
	default:
		rtn = -EFAULT;
		break;
	}
	if (rtn < 0) {
		rare();
	}
	return (rtn);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_DATA Handling
 *
 *  -------------------------------------------------------------------------
 */
static int s_w_data(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	/* 
	 *  FIXME:  We have to attach an SSCOP trailer and place in retransmit
	 *  buffer.
	 */
	return (4);
}
static int s_r_data(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	/* 
	 *  FIXME:  We have to attach an SSCOP trailer and place in retransmit
	 *  buffer.
	 */
	return (4);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_FLUSH Handling
 *
 *  -------------------------------------------------------------------------
 */
static int s_w_flush(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (3);
}
static int s_r_flush(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (3);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_ERROR Handling
 *
 *  -------------------------------------------------------------------------
 */
static int s_r_error(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (4);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_HANGUP Handling
 *
 *  -------------------------------------------------------------------------
 */
static int s_r_hangup(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (4);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  Other messages
 *
 *  -------------------------------------------------------------------------
 */
static int s_w_other(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (4);
}
static int s_r_other(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (4);
}

/*
 *  =========================================================================
 *
 *  PUT and SRV
 *
 *  =========================================================================
 */
static INT s_wput(queue_t * q, mblk_t * mp)
{
	int rtn = 0;
	sscop_t *sp = (sscop_t *) q->q_ptr;
	ensure(q, return ((INT) (-EFAULT)));
	ensure(sp, return ((INT) (-EFAULT)));
	ensure(mp, return ((INT) (-EFAULT)));
	switch (mp->b_datap->db_type) {
	case M_DATA:
		rtn = s_w_data(q, mp);
		break;
	case M_PROTO:
	case M_PCPROTO:
		rtn = s_w_proto(q, mp);
		break;
	case M_FLUSH:
		rtn = s_w_flush(q, mp);
		break;
	case M_IOCTL:
		rtn = s_w_ioctl(q, mp);
		break;
	case M_IOCDATA:
		rtn = s_w_iocdata(q, mp);
		break;
	default:
		rtn = s_w_other(q, mp);
		break;
	}
	switch (rtn) {
	case 0:
		freemsg(mp);
	case 1:
		break;
	case 2:
		freeb(mp);
		break;
	case 3:
	case 4:
		putnext(q, mp);
		break;
	default:
		ptrace(("Error = %d\n", rtn));
		freemsg(mp);
		s_tx_wakeup(sp);
		return (INT) (rtn);
	}
	s_tx_wakeup(sp);
	return (INT) (0);
}

static INT s_rput(queue_t * q, mblk_t * mp)
{
	int rtn = 0;
	sscop_t *sp = (sscop_t *) q->q_ptr;
	ensure(q, return ((INT) (-EFAULT)));
	ensure(sp, return ((INT) (-EFAULT)));
	ensure(mp, return ((INT) (-EFAULT)));
	switch (mp->b_datap->db_type) {
	case M_DATA:
		rtn = s_r_data(q, mp);
		break;
	case M_PROTO:
	case M_PCPROTO:
		rtn = s_r_proto(q, mp);
		break;
	case M_CTL:
		rtn = s_r_ctrl(q, mp);
		break;
	case M_ERROR:
		rtn = s_r_error(q, mp);
		break;
	case M_HANGUP:
		rtn = s_r_hangup(q, mp);
		break;
	case M_FLUSH:
		rtn = s_r_flush(q, mp);
		break;
	default:
		rtn = s_r_other(q, mp);
		break;
	}
	switch (rtn) {
	case 0:
		freemsg(mp);
	case 1:
		break;
	case 2:
		freeb(mp);
		break;
	case 3:
	case 4:
		putnext(q, mp);
		break;
	default:
		ptrace(("Error = %d\n", rtn));
		freemsg(mp);
		s_rx_wakeup(sp);
		s_tx_wakeup(sp);
		return (INT) (rtn);
	}
	s_rx_wakeup(sp);
	s_tx_wakeup(sp);
	return (INT) (0);
}

/*
 *  =========================================================================
 *
 *  Private structure allocation, deallocation and cache
 *
 *  =========================================================================
 */
kmem_cache_t *s_cachep = NULL;

static void s_init_caches(void)
{
	if (!(s_cachep) &&
	    !(s_cachep = kmem_cache_create
	      ("sscop_cachep", sizeof(sscop_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL)))
		panic("%s:Cannot alloc s_cachep.\n", __FUNCTION__);
	return;
}
static void s_term_caches(void)
{
	if (s_cachep)
		if (kmem_cache_destroy(s_cachep))
			cmn_err(CE_WARN, "%s: did not destroy s_cache", __FUNCTION__);
	return;
}
static sscop_t *s_alloc_priv(queue_t * q)
{
	sscop_t *sp;
	if ((sp = kmem_cache_alloc(s_cachep, SLAB_ATOMIC))) {
		bzero(sp, sizeof(*sp));
		RD(q)->q_ptr = WR(q)->q_ptr = sp;
		sp->rq = RD(q);
		sp->wq = WR(q);
		bufq_init(&sp->rb);
		bufq_init(&sp->tb);
		bufq_init(&sp->rtb);
	}
	return (sp);
}
static void s_free_priv(queue_t * q)
{
	sscop_t *sp = (sscop_t *) q->q_ptr;
	bufq_purge(&sl->rb);
	bufq_purge(&sl->tb);
	bufq_purge(&sl->rtb);
	kmem_cache_free(s_cachep, sp);
	return;
}

/*
 *  =========================================================================
 *
 *  OPEN and CLOSE
 *
 *  =========================================================================
 */
static int s_open(queue_t * q, dev_t * devp, int flag, int sflag, cred_t * crp)
{
	(void) crp;
	if (q->q_ptr != NULL)	/* already open */
		return (0);
	if (sflag == MODOPEN || WR(q)->q_next != NULL) {
		fixme(("Check module we are being pushed over.\n"));
		if (!(s_alloc_priv(q)))
			return ENOMEM;
		return (0);
	}
	return EIO;
}
static int s_close(queue_t * q, int flag, cred_t * crp)
{
	(void) flag;
	(void) crp;
	s_free_priv(q);
	return (0);
}

/*
 *  =========================================================================
 *
 *  LiS Module Initialization
 *
 *  =========================================================================
 */
void s_init(void)
{
	int modnum;
	unless(s_minfo.mi_idnum, return);
	cmn_err(CE_NOTE, SSCOP_BANNER);	/* console splash */
	s_init_caches();
	if (!(modnum = lis_register_strmod(&s_info, s_minfo.mi_idname))) {
		s_minfo.mi_idnum = 0;
		rare();
		cmn_err(CE_NOTE, "sscop: couldn't register as module\n");
		return;
	}
	s_minfo.mi_idnum = modnum;
	return;
}
void s_terminate(void)
{
	ensure(s_minfo.mi_idnum, return);
	if ((s_minfo.mi_idnum = lis_unregister_strmod(&s_minfo)))
		cmn_err(CE_WARN, "sscop: couldn't unregister module!\n");
	s_term_caches();
	return;
}

/*
 *  =========================================================================
 *
 *  Kernel Module Initialization
 *
 *  =========================================================================
 */
int init_module(void)
{
	s_init();
	return (0);
}
void cleanup_module(void)
{
	s_terminate();
	return;
}


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

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

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