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/sli/sm_mod.c


File /code/strss7/drivers/sli/sm_mod.c



#ident "@(#) $RCSfile: sm_mod.c,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2003/04/03 19:51:13 $"

static char const ident[] = "$RCSfile: sm_mod.c,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2003/04/03 19:51:13 $";

#include <linux/config.h>
#include <linux/version.h>
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/module.h>

#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/cmn_err.h>
#include <sys/dki.h>

#include <ss7/lmi.h>
#include <ss7/mtpi.h>

#include "../debug.h"

#define SM_DESCRIP	"SIMPLE SINGLE LINK MTP."
#define SM_COPYRIGHT	"Copyright (c) 1997-2002 OpenSS7 Corporation.  All Rights Reserved."
#define SM_DEVICE	"Part of the OpenSS7 Stack for LiS STREAMS."
#define SM_CONTACT	"Brian Bidulock <bidulock@openss7.org>"
#define SM_LICENSE	"GPL"
#define SM_BANNER	SM_DESCRIP	"\n" \
			SM_COPYRIGHT	"\n" \
			SM_DEVICE	"\n" \
			SM_CONTACT

MODULE_AUTHOR(SM_CONTACT);
MODULE_DESCRIPTION(SM_DESCRIP);
MODULE_SUPPORTED_DEVICE(SM_DEVICE);
#ifdef MODULE_LICENSE
MODULE_LICENSE(SM_LICENSE);
#endif

static struct module_info sm_minfo = {
	0,					/* id */
	"sm-mod",				/* name */
	0,					/* min packet size accepted */
	INFPSZ,					/* max packet size accepted */
	10240L,					/* high water mark */
	512L					/* low water mark */
};

static int sm_open(queue_t *, dev_t *, int, int, cred_t *);
static int sm_close(queue_t *, int, cred_t *);

static int sm_wput(queue_t *, mblk_t *);
static int sm_rput(queue_t *, mblk_t *);

static struct qinit sm_rinit = {
	sm_rput,				/* put */
	NULL,					/* service */
	sm_open,				/* open */
	sm_close,				/* close */
	NULL,					/* admin */
	&sm_minfo,				/* info */
	NULL					/* stat */
};

static struct qinit sm_winit = {
	sm_wput,				/* put */
	NULL,					/* service */
	NULL,					/* open */
	NULL,					/* close */
	NULL,					/* admin */
	&sm_minfo,				/* info */
	NULL					/* stat */
};

static struct streamtab sm_info = {
	&sm_rinit,				/* read queue */
	&sm_winit,				/* write queue */
	NULL,					/* mux read queue */
	NULL					/* mux write queue */
};

struct priv {
	uint32_t opc;
	uint32_t dpc;
	uint32_t sio;
};

static int sm_rput(queue_t * q, mblk_t * dp)
{
	/* message from below, strip MTP header and add MTP-TRANSFER primitive */
	switch (dp->b_datap->db_type) {
	case M_DATA:
	{
		mblk_t *mp;
		struct MTP_transfer_ind *m;
		struct mtp_addr *a;
		uint sio, dpc, opc, sls, b;
		sio = *dp->b_rptr++;
		if ((sio & 0xf) != 5) {
			__ptrace(("Discarding bad message sio = %#02x\n", sio));
			freemsg(dp);
			return (0);
		}
		b = *dp->b_rptr++;
		dpc = ((b << 0) & 0xff);
		b = *dp->b_rptr++ & 0x00ff;
		dpc |= ((b << 8) & 0x3f00);
		opc = ((b >> 6) & 0x03);
		b = *dp->b_rptr++ & 0x00ff;
		opc |= ((b << 2) & 0x3fc);
		b = *dp->b_rptr++ & 0x00ff;
		opc |= ((b << 10) & 0x3c00);
		sls = (b >> 4) & 0x0f;
		mp = allocb(sizeof(*m) + sizeof(*a), BPRI_MED);
		mp->b_datap->db_type = M_PROTO;
		m = ((typeof(m)) mp->b_wptr)++;
		m->mtp_primitive = MTP_TRANSFER_IND;
		m->mtp_srce_length = sizeof(*a);
		m->mtp_srce_offset = sizeof(*m);
		m->mtp_mp = 0;
		m->mtp_sls = sls;
		a = ((typeof(a)) mp->b_wptr)++;
		a->ni = 0;
		a->pc = opc;
		a->si = sio & 0x0f;
		mp->b_cont = dp;
		putnext(q, mp);
		return (0);
	}
	}
	/* pass along unrecognized */
	putnext(q, dp);
	return (0);
}

static int sm_wput(queue_t * q, mblk_t * mp)
{
	/* message from above, strip MTP-TRANSFER primitive and add header */
	switch (mp->b_datap->db_type) {
	case M_PROTO:
	case M_PCPROTO:
	{
		mblk_t *dp;
		struct MTP_transfer_req *m = (typeof(m)) mp->b_rptr;
		struct priv *p = q->q_ptr;
		if (m->mtp_primitive != MTP_TRANSFER_REQ)
			break;
		dp = allocb(11, BPRI_MED);
		dp->b_wptr += 6;
		*dp->b_wptr++ = p->sio;
		*dp->b_wptr++ = p->dpc;
		*dp->b_wptr++ = ((p->dpc >> 8) & 0x3f) | ((p->opc & 0x3) << 6);
		*dp->b_wptr++ = ((p->opc >> 2) & 0x0ff);
		*dp->b_wptr++ = ((p->opc >> 10) & 0x0f) | ((m->mtp_sls & 0x0f) << 4);
		dp->b_cont = mp->b_cont;
		freeb(mp);
		pullupmsg(dp, -1);
		dp->b_rptr += 6;
		putnext(q, dp);
		return (0);
	}
	}
	/* pass along unrecognized */
	putnext(q, mp);
	return (0);
}

static int sm_open(queue_t * q, dev_t * devp, int flag, int sflag, cred_t * crp)
{
	struct priv *p;
	if (q->q_ptr)
		return (0);
	if (!(p = kmalloc(sizeof(*p), GFP_ATOMIC)))
		return (ENOMEM);
	bzero(p, sizeof(*p));
	p->opc = 0x11ae;	/* our point code */
	p->dpc = 0x11d8;	/* their point code */
	p->sio = 0x05;		/* isup */
	RD(q)->q_ptr = p;
	WR(q)->q_ptr = p;
	return (0);
}

static int sm_close(queue_t * q, int sflag, cred_t * crp)
{
	struct priv *p = q->q_ptr;
	RD(q)->q_ptr = NULL;
	WR(q)->q_ptr = NULL;
	kfree(p);
	return (0);
}

/*
 *  =========================================================================
 *
 *  Kernel Module Initialization
 *
 *  =========================================================================
 */
int init_module(void)
{
	cmn_err(CE_NOTE, SM_BANNER);	/* console splash */
	lis_register_strmod(&sm_info, "sm-mod");
	return (0);
}
void cleanup_module(void)
{
	lis_unregister_strmod(&sm_info);
	return;
}


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

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

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