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/sscop_t.c


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



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

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

#define SSCOP_DESCRIP	"SSCOP-MCE/IP STREAMS DRIVER."
#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"

#ifdef MODULE
MODULE_AUTHOR(SSCOP_CONTACT);
MODULE_DESCRIPTION(SSCOP_DESCRIP);
MODULE_SUPPORTED_DEVICE(SSCOP_DEVICE);
#ifdef MODULE_LICENSE
MODULE_LICENSE(SSCOP_LICENSE);
#endif
#define MODULE_STATIC static
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#define MODULE_STATIC
#endif

#ifdef SSCOP_DEBUG
static int sscop_debug = SSCOP_DEBUG;
#else
static int sscop_debug = 2;
#endif

#ifndef SSCOP_CMAJOR
#define SSCOP_CMAJOR 240
#endif
#define SSCOP_NMINOR 255

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

typedef void (*bufcall_fnc_t) (long);

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

static struct module_info sscop_info = {
	0,				/* Module ID number *//* FIXME */
	"sscop",			/* Module name */
	1,				/* Min packet size accepted */
	512,				/* Max packet size accepted */
	8 * 512,			/* Hi water mark */
	1 * 512				/* Lo water mark */
};

static INT sscop_rput(queue_t *, mblk_t *);
static INT sscop_rsrv(queue_t *);
static int sscop_open(queue_t *, dev_t *, int, int, cred_t *);
static int sscop_close(queue_t *, int, cred_t *);

static struct qinit sscop_rinit = {
	sscop_rput,			/* Read put (msg from below) */
	sscop_rsrv,			/* Read queue service */
	sscop_open,			/* Each open */
	sscop_close,			/* Last close */
	NULL,				/* Admin (not used) */
	&sscop_info,			/* Information */
	NULL				/* Statistics */
};

static INT sscop_wput(queue_t *, mblk_t *);
static INT sscop_wsrv(queue_t *);

static struct qinit sscop_winit = {
	sscop_wput,			/* Write put (msg from above) */
	sscop_wsrv,			/* Write queue service */
	NULL,				/* Each open */
	NULL,				/* Last close */
	NULL,				/* Admin (not used) */
	&sscop_info,			/* Information */
	NULL				/* Statistics */
};

MODULE_STATIC struct streamtab sscop_info = {
	&sscop_rinit,			/* Upper read queue */
	&sscop_winit,			/* Upper write queue */
	NULL,				/* Lower read queue */
	NULL				/* Lower write queue */
};

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

/*
 *  SSCOP Protocol Parameters and Defaults
 */
int sscop_some_parameters = 3 * HZ;

#define SSCOP_PRIV(__q) ((sscop_t *)(__q)->q_ptr)

kmem_cachep_t sscop_priv_cachep = NULL;

struct sscop {
	struct sscop *next;		/* linkage for master list */
	struct sscop *pprev;		/* linkage for master list */
};

/*
 *  =========================================================================
 *
 *  SSCOP Message Structures
 *
 *  =========================================================================
 */

#define SSCOP_BGN
#define SSCOP_BGACK
#define SSCOP_BGREJ
#define SSCOP_END
#define SSCOP_ENDAK
#define SSCOP_RS
#define SSCOP_RSAK
#define SSCOP_ER
#define SSCOP_ERAK
#define SSCOP_SD
#define SSCOP_POLL
#define SSCOP_STAT
#define SSCOP_USTAT
#define SSCOP_UD
#define SSCOP_MD

/*
 *  =========================================================================
 *
 *  SSCOP T-Provider --> T-User Primitives (M_CTL, M_PROTO, M_PCPROTO)
 *
 *  =========================================================================
 *
 *  These functions package up the necessary primitive format given the
 *  input parameters necessary to create them.  They are all inlined and
 *  return NULL if a message block could not be allocated.  The reason for not
 *  passing the mblk up the queue yet is because the caller may wish to
 *  allocate the response before committing to processing the action which
 *  causes these indications and confirmations to the T-User.
 */

#include "sscop_t_prov.h"

/*
 *  =========================================================================
 *
 *  SSCOP T-Provider --> N-Provider (IP) Primitives (M_CTL, M_PROTO, M_PCPROTO)
 *
 *  =========================================================================
 *
 *  These functions package up the necessary primitive format given the
 *  input parameters necessary to create them.  They are all inlined and
 *  return NULL if a message block could not be allocated.
 */

/*
 *  N_UNITDATA_REQ
 *  -------------------------------------------------------------------------
 */
static inline mblk_t *n_unitdata_req(caddr_t dst_ptr, size_t dst_len)
{
	mblk_t *mp;
	N_unitdata_req_t *p;
	if ((mp = allocb(sizeof(*p) + dst_len, BPRI_MED))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = (N_unitdata_req_t *) mp->b_wptr;
		p->PRIM_type = N_DISCON_REQ;
		p->DEST_length = dst_len;
		p->DEST_offset = dst_len ? sizeof(*p) : 0;
		p->RESERVED_field[0] = 0;
		p->RESERVED_field[1] = 0;
		mp->b_wptr += sizeof(*p);
		bcopy(dst_ptr, mp->b_wptr, dst_len);
		mp->b_wptr += dst_len;
	}
	return (mp);
}

/*
 *  =========================================================================
 *
 *  SSCOP --> SSCOP Peer Primitives (Send Messages)
 *
 *  =========================================================================
 */

#include "sscop_send.h"

/*
 *  =========================================================================
 *
 *  SSCOP State Machine TIMEOUTS
 *
 *  =========================================================================
 */

#include "sscop_time.h"

/*
 *  =========================================================================
 *
 *  SSCOP Peer --> SSCOP Primitives (Received Messages)
 *
 *  =========================================================================
 */

extern int sscop_recv_msg(const queue_t *, const mblk_t *);

/*
 *  =========================================================================
 *
 *  N-Provider --> N-User (SSCOP) Primitives (M_PROTO, M_PCPROTO)
 *
 *  =========================================================================
 */

/*
 *  N_UNITDATA_IND
 *  -------------------------------------------------------------------------
 */
static int n_unitdata_ind(queue_t * q, mblk_t * pdu)
{
	mblk_t *mp;
	sscop_t *sp = SSCOP_PRIV(q);
	N_unitdata_ind_t *p = (N_unitdata_ind_t *) pdu->b_rptr;
	const caddr_t dst_ptr = p->DEST_offset + pdu->b_rptr;
	const size_t dst_len = p->DEST_length;
	const caddr_t src_ptr = p->SRC_offset + pdu->b_rptr;
	const size_t src_len = p->SRC_length;
}

/*
 *  N_UDERROR_IND
 *  -------------------------------------------------------------------------
 */
static int n_uderror_ind(queue_t * q, mblk_t * pdu)
{
	mblk_t *mp;
	sscop_t *sp = SSCOP_PRIV(q);
	N_uderror_ind_t *p = (N_uderror_ind_t *) pdu->b_rptr;
	const caddr_t dst_ptr = p->DEST_offset + pdu->b_rptr;
	const size_t dst_len = p->DEST_length;
	const uint error = p->ERROR_type;
}

static int (*n_prim[]) (queue_t *, mblk_t *) = {
	NULL,			/* N_CONN_REQ 0 */
	    NULL,		/* N_CONN_RES 1 */
	    NULL,		/* N_DISCON_REQ 2 */
	    NULL,		/* N_DATA_REQ 3 */
	    NULL,		/* N_EXDATA_REQ 4 */
	    NULL,		/* N_INFO_REQ 5 */
	    NULL,		/* N_BIND_REQ 6 */
	    NULL,		/* N_UNBIND_REQ 7 */
	    NULL,		/* N_UNITDATA_REQ 8 */
	    NULL,		/* N_OPTMGMT_REQ 9 */
	    NULL,		/* not used 10 */
	    NULL,		/* N_CONN_IND 11 */
	    NULL,		/* N_CONN_CON 12 */
	    NULL,		/* N_DISCON_IND 13 */
	    NULL,		/* N_DATA_IND 14 */
	    NULL,		/* N_EXDATA_IND 15 */
	    NULL,		/* N_INFO_ACK 16 */
	    NULL,		/* N_BIND_ACK 17 */
	    NULL,		/* N_ERROR_ACK 18 */
	    NULL,		/* N_OK_ACK 19 */
	    &n_unitdata_ind,	/* N_UNITDATA_IND 20 */
	    &n_uderror_ind,	/* N_UDERROR_IND 21 */
	    NULL,		/* not used 22 */
	    NULL,		/* N_DATACK_REQ 23 */
	    NULL,		/* N_DATACK_IND 24 */
	    NULL,		/* N_RESET_REQ 25 */
	    NULL,		/* N_RESET_IND 26 */
	    NULL,		/* N_RESET_RES 27 */
	    NULL		/* N_RESET_CON 28 */
};

/*
 *  =========================================================================
 *
 *  T-User --> T-Provider (SSCOP) Primitives (M_CTL, M_PROTO, M_PCPROTO)
 *
 *  =========================================================================
 */

extern int sscop_w_proto(queue_t *, mblk_t *);
extern int sscop_w_pcproto(queue_t *, mblk_t *);

/*
 *  =========================================================================
 *
 *  SSCOP IOCTLs
 *
 *  =========================================================================
 */

static int (*sscop_ioctl[]) (queue_t *, uint, void *) = {
};

/*
 *  =========================================================================
 *
 *  SSCOP STREAMS Message Handling
 *
 *  =========================================================================
 *
 *  M_DATA Handling
 *
 *  -------------------------------------------------------------------------
 */
static inline int sscop_w_data(queue_t * q, mblk_t * mp)
{
	return sscop_write_data(q, mp);
}
static inline int sscop_r_data(queue_t * q, mblk_t * mp)
{
	return sscop_recv_sdu(q, mp);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_PROTO, M_PCPROTO Handling
 *
 *  -------------------------------------------------------------------------
 */

static inline int sscop_r_proto(queue_t * q, mblk_t * mp)
{
	int prim = ((union N_primitives *) (mp->b_rptr))->type;
	if (0 <= prim && prim < sizeof(n_prim) / sizeof(void *))
		if (n_prim[prim])
			return (*n_prim[prim]) (q, mp);
	return (-EOPNOTSUPP);
}
static inline int sscop_r_pcproto(queue_t * q, mblk_t * mp)
{
	return sscop_r_proto(q, mp);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_CTL Handling
 *
 *  -------------------------------------------------------------------------
 */
static inline int sscop_w_ctl(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (-EOPNOTSUPP);
}
static inline int sscop_r_ctl(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return (-EOPNOTSUPP);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_IOCTL Handling
 *
 *  -------------------------------------------------------------------------
 */
static inline int sscop_w_ioctl(queue_t * q, mblk_t * mp)
{
	int ret;
	struct iocblk *iocp = (struct iocblk *) mp->b_rptr;
	int cmd = iocp->ioc_cmd;
	void *arg = mp->b_cont ? mp->b_cont->b_rptr : NULL;
	int type = _IOC_TYPE(cmd);
	int nr = _IOC_NR(cmd);
	int size = _IOC_SIZE(cmd);

	switch (type) {
	case __SID:
		switch (cmd) {
		case I_LINK:
		case I_PLINK:
		case I_UNLINK:
		case I_PUNLINK:
		{
			struct linkblk *lp = (struct linkblk *) arg;
			(void) lp;
		}
		default:
		case I_FDINSERT:
			ret = -EINVAL;
		}
		break;

	case SSCOP_IOC_MAGIC:
		if (iocp->ioc_count >= size) {
			if (0 <= nr && nr < sizeof(sscop_ioctl) / sizeof(void *)) {
				if (sscop_ioctl[nr])
					ret = (*sscop_ioctl[nr]) (q, cmd, arg);
				else
					ret = -EOPNOTSUPP;
			}
		} else
			return = -EINVAL;
		break;

	default:
		if (q->q_next) {
			putnext(q, mp);
			return (0);
		}
		ret = -EOPNOTSUPP;
	}
	mp->b_datap->db_type = ret ? M_IOCNAK : M_IOCACK;
	iocp->ioc_error = -ret;
	iocp->ioc_rval = ret ? -1 : 0;
	qrepy(q, mp);
	return (0);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_FLUSH Handling
 *
 *  -------------------------------------------------------------------------
 */
static inline void sscop_w_flush(queue_t * q, mblk_t * mp)
{
	if (*mp->b_rptr & M_FLUSHW) {
		flushq(q, FLUSHALL);
		if (q - q_next) {
			putnext(q, mp);
			return;
		}
		*mp->b_rptr &= ~FLUSHW;
	}
	if (*mp->b_rptr & FLUSHR) {
		flushq(RD(q), FLUSHALL);
		qreply(q, mp);
		return;
	}
	if (q->q_next) {
		putnext(q, mp);
		return;
	}
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_ERROR Handling
 *
 *  -------------------------------------------------------------------------
 */
static inline void sscop_r_error(queue_t * q, mblk_t * mp)
{
	sscop_t *sp = SSCOP_PRIV(q);
	sp->zapped = 1;
	if (q->q_next) {
		putnext(q, mp);
		return;
	}
}

/*
 *  =========================================================================
 *
 *  STREAMS QUEUE PUT and QUEUE SERVICE routines
 *
 *  =========================================================================
 *
 *  READ QUEUE PUT and SRV routines
 *
 *  -------------------------------------------------------------------------
 *
 *  SSCOP RPUT - Message from below.
 *
 *  If the message is a priority message we attempt to process it immediately.
 *  If the message is a non-priority message, but there are no messages on the
 *  queue yet, we attempt to process it immediately.  If the message is not
 *  supported, we pass it up-queue if possible.  If the message cannot be
 *  processed immediately we place it on the queue.
 */
static INT sscop_rput(queue_t * q, mblk_t * mp)
{
	int err = -EOPNOTSUPP;

	if (mp->b_datap->db_type < QPCTL && q->q_count) {
		putq(q, mp);
		/* 
		 *  NOTE:- after placing messages on the queue here, I should
		 *  check if placing the message on the queue crosses a band
		 *  threshold for congestion accept and congestion discard.
		 *  When crossing congestion accept, I should sent busy to the
		 *  peer and notify MTP3.  When crossing congestion discard I
		 *  should notify MTP3.
		 */
		return (0);
	}
	switch (mp->b_datap->db_type) {
	case M_DATA:
		if ((err = sscop_r_data(q, mp)))
			break;
		return (0);
	case M_PROTO:
		if ((err = sscop_r_proto(q, mp)))
			break;
		return (0);
	case M_PCPROTO:
		if ((err = sscop_r_pcproto(q, mp)))
			break;
		return (0);
	case M_CTL:
		if ((err = sscop_r_ctl(q, mp)))
			break;
		return (0);
	case M_ERROR:
		sscop_r_error(q, mp);
		return (0);
	}
	switch (err) {
	case -EAGAIN:
		putq(q, mp);
		return (0);
	case -EOPNOTSUPP:
		if (q->q_next) {
			putnext(q, mp);
			return (0);
		}
	}
	freemsg(mp);
	return (err);
}

/*
 *  SSCOP RSRV - Queued message from below.
 *
 *  If the message is a priority message we attempt to process it immediately
 *  and without flow control.  If the message is a non-priority message and
 *  the next queue is flow controlled, we put the message back on the queue
 *  and wait.  If we cannot process a priority message immediately we cannot
 *  place it back on the queue and discard it.  We requeue non-priority
 *  messages which cannot be processed immediately.  Unrecognized messages are
 *  passed down-queue.
 */
static INT sscop_rsrv(queue_t * q)
{
	mblk_t *mp;
	int err = -EOPNOTSUPP;

	while ((mp = getq(q))) {
		if (mp->b_datap->db_type < QPCTL && !canputnext(q)) {
			putbq(q, mp);
			return (0);
		}
		switch (mp->b_datap->db_type) {
		case M_DATA:
			if ((err = sscop_r_data(q, mp)))
				break;
			goto rsrv_continue;
		case M_PROTO:
			if ((err = sscop_r_proto(q, mp)))
				break;
			goto rsrv_continue;
		case M_PCPROTO:
			if ((err = sscop_r_pcproto(q, mp)))
				break;
			goto rsrv_continue;
		case M_CTL:
			if ((err = sscop_r_ctl(q, mp)))
				break;
			goto rsrv_continue;
		}
		switch (err) {
		case -EAGAIN:
			if (mp->b_datap->db_type < QPCTL) {
				putbq(q, mp);
				return (0);
			}
		case -EOPNOTSUPP:
			if (q->q_next) {
				putnext(q, mp);
				goto rsrv_continue;
			}
			break;
		}
		freemsg(mp);
	      rsrv_continue:
		/* 
		 *  NOTE:-  I have removed and processed a message from the
		 *  receive queue, so I should check for receive congestion
		 *  abatement.  If receive congestion has abated below the
		 *  accept threshold, I should signal MTP that there is no
		 *  longer any receive congestion.
		 */
		continue;
	}
	return (0);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  WRITE QUEUE PUT and SRV routines
 *
 *  -------------------------------------------------------------------------
 *
 *  SSCOP WPUT - Message from above.
 *
 *  If the message is priority message we attempt to process it immediately.
 *  If the message is non-priority message, but there are no messages on the
 *  queue yet, we attempt to process it immediately.  If the message is not
 *  supported, we pass it down-queue if possible.  If the message cannot be
 *  processed immediately, we place it on the queue.
 */
static INT sscop_wput(queue_t * q, mblk_t * mp)
{
	mblk_t *mp;
	int err = -EOPNOTSUPP;
	if (q->q_count && mp->b_datap->db_type < QPCTL) {
		putq(q, mp);
		/* 
		 *  NOTE:- after placing messages on the queue here, I should
		 *  check for transmit congestion.  I should check if placing
		 *  the message on the queue crosses a band threshold for
		 *  congestion onset and abatement.  When crossing congestion
		 *  thresholds, I should notify MTP3.
		 */
		return (0);
	}
	switch (mp->b_datap->db_type) {
	case M_DATA:
		if ((err = sscop_w_data(q, mp)))
			break;
		return (0);
	case M_PROTO:
		if ((err = sscop_w_proto(q, mp)))
			break;
		return (0);
	case M_PCPROTO:
		if ((err = sscop_w_pcproto(q, mp)))
			break;
		return (0);
	case M_CTL:
		if ((err = sscop_w_ctl(q, mp)))
			break;
		return (0);
	case M_IOCTL:
		if ((err = sscop_w_ioctl(q, mp)))
			break;
		return (0);
	case M_FLUSH:
		sscop_w_flush(q, mp);
		return (0);
	}
	switch (err) {
	case -EAGAIN:
		if (mp->b_datap->db_type < QPCTL) {
			putq(q, mp);
			return (0);
		}
	case -EOPNOTSUPP:
		if (q->q_next) {
			putnext(q, mp);
			return (0);
		}
	}
	freemsg(mp);
	return (err);
}

/*
 *  SSCOP WSRV = Queued message from above.
 *
 *  If the message is a priority message we attempt to process it immediately
 *  and without flow control.  If the message is a non-priority message and
 *  the next queue is flow controlled, we put the message back on the queue
 *  and wait.  If we cannot process a priority message immediately we cannot
 *  place it back on the queue, we discard it.  We requeue non-priority
 *  messages which cannot be processed immediately.  Unrecognized messages are
 *  passed down-queue.
 */
static INT sscop_wsrv(queue_t * q)
{
	int err = -EOPNOTSUPP;
	mblk_t *mp;

	while ((mp = getq(q))) {
		if (q->q_next && mp->b_datap->db_type < QPCTL && !canputnext(q)) {
			putbq(q, mp);
			return (0);
		}
		switch (mp->b_datap->db_type) {
		case M_DATA:
			if ((err = sscop_w_data(q, mp)))
				break;
			goto wsrv_continue;
		case M_PROTO:
			if ((err = sscop_w_proto(q, mp)))
				break;
			goto wsrv_continue;
		case M_PCPROTO:
			if ((err = sscop_w_pcproto(q, mp)))
				break;
			goto wsrv_continue;
		case M_CTL:
			if ((err = sscop_w_ctl(q, mp)))
				break;
			goto wsrv_continue;
		}
		switch (err) {
		case -EAGAIN:
			if (mp->b_datap->db_type < QPCTL) {
				putbq(q, mp);
				return (0);
			}
		case -EOPNOTSUPP:
			if (q->q_next) {
				putnext(q, mp);
				goto wsrv_continue;
			}
		}
		freemsg(mp);
	      wsrv_continue:
		/* 
		 *  NOTE:-   I have removed a message from the queue, so I
		 *  should check for band congestion abatement for the data
		 *  band to see if transmit congestion has abated.  If it has,
		 *  I should notify MTP3 of transmit abatement.
		 */
		continue;
	}
	return (0);
}

/*
 *  =========================================================================
 *
 *  OPEN and CLOSE
 *
 *  =========================================================================
 */
/*
 *  Private structure allocation and deallocation.
 *
 *  We use Linux hardware aligned cache here for speedy access to information
 *  contained in the private data structure.
 */
static sscop_t *sscop_priv_list = NULL;

kmem_cache_t *sscop_cachep = NULL;

static sscop_t *sscop_alloc_priv(queue_t * q)
{
	sscop_t *sp;

	if ((sp = kmem_cache_alloc(sscop_cachep))) {
		bzero(sp, sizeof(*sp));
		RD(q)->q_ptr = WR(q)->q_tpr = sp;
		sp->rq = RD(q);
		sp->wq = WR(q);

		/* link into master list */
		if ((sp->next = sscop_priv_list))
			sp->next->pprev = &sp->next;
		sp->pprev = &sscop_priv_list;
		sscop_priv_list = sp;

		sp->t_state = TS_UNINIT;

		sp->n_ostr = sscop_default_o_streams;
		sp->n_istr = sscop_default_i_streams;
		sp->a_rwnd = sscop_default_rmem;

		bufq_init(&sp->out_of_order_queue);
		bufq_init(&sp->duplicate_queue);
		bufq_init(&sp->write_queue);
		bufq_init(&sp->urgent_queue);
		bufq_init(&sp->retrans_queue);
		bufq_init(&sp->error_queue);
		bufq_init(&sp->connect_queue);

		sp->pmtu = 576;

		sp->max_retrans = sscop_assoc_max_retrans;
		sp->max_inits = sscop_max_init_retries;
	}
	return (sp);
}

static void sscop_free_priv(queue_t * q)
{
	sscop_t *sp = SSCOP_PRIV(q);
	kmem_cache_free(sscop_cachep, sp);
	return;
}

static void sscop_init_priv(void)
{
	if (!(sscop_cachep = kmem_find_general_cachep(sizeof(sscop_t)))) {
		/* allocate a new cachep */
	}
	return;
}

/*
 *  -------------------------------------------------------------------------
 *
 *  OPEN - Each open
 *
 *  -------------------------------------------------------------------------
 */
static int sscop_open(queue_t * q, dev_t * devp, int flag, int sflag, cred_t * crp)
{
	(void) crp;

	if (q->q_ptr != NULL)
		return (0);

	/* 
	 *  FIXME: we have to open this as a driver, not a module
	 */
	if (sflag == MODOPEN || WR(q)->q_next != NULL) {
		/* 
		 *  FIXME: check to make sure that the module we are being
		 *  pushed over is compatible (i.e. it is the right kind of
		 *  transport module.
		 */
		if (!(sp = kmem_cache_alloc(sscop_priv_cachep, SLAB_HWCACHE_ALIGN)))
			return ENOMEM;
		RD(q)->q_ptr = WR(q)->q_ptr = sp;
		sp->rq = RD(q);
		sp->wq = WR(q);
		/* 
		 *  TODO: more structure initialization
		 */
		return (0);
	}
	return EIO;
}

/*
 *  -------------------------------------------------------------------------
 *
 *  CLOSE - Last close
 *
 *  -------------------------------------------------------------------------
 */
static int sscop_close(queue_t * q, int flag, cred_t * crp)
{
	sscop_t *sp = SSCOP_PRIV(q);

	(void) flag;
	(void) crp;

	/* 
	 *  TODO: make sure everything is deallocated
	 */
	kmem_cache_free(sscop_priv_cachep, sp);
	return (0);
}

/*
 *  =========================================================================
 *
 *  LiS MODULE INITIALIZATION
 *
 *  =========================================================================
 */

static int sscop_initialized = 0;

#ifndef LIS_REGISTERED
static inline void sscop_init(void)
#else
__initfunc(void sscop_init(void))
#endif
{
	if (sscop_initialized)
		return;
	sscop_initialized = 1;
	printk(KERN_INFO SSCOP_BANNER);	/* console splash */
#ifndef LIS_REGISTERED
	if (!(sscop_minfo.mi_idnum = lis_register_strmod(&sscop_info, sscop_minfo.mi_idname))) {
		cmn_err(CE_NOTE, "sscop: couldn't register as module\n");
		sscop_minfo.mi_idnum = 0;
	}
#endif
}

#ifndef LIS_REGISTERED
static inline void sscop_terminate(void)
#else
__initfunc(void sscop_terminate(void))
#endif
{
	if (!sscop_initialized)
		return;
	sscop_initialized = 0;
#ifndef LIS_REGISTERED
	if (sscop_minfo.mi_idnum)
		if ((sdt_minfo.mi_idnum = lis_unregister_strmod(&sscop_info))) {
			cmn_err(CE_WARN, "sdt: couldn't unregister as module!\n");
		}
#endif
};

/*
 *  =========================================================================
 *
 *  LINUX KERNEL MODULE INITIALIZATION
 *
 *  =========================================================================
 */

#ifdef MODULE
int init_module(void)
{
	sscop_init();
	return (0);
}
void cleanup_module(void)
{
	sscop_terminate();
	return;
}
#endif


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

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

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