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/sdli/cdi.c


File /code/strss7/drivers/sdli/cdi.c



#ident "@(#) $RCSfile: cdi.c,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2003/04/03 19:50:56 $"

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

#if defined(LINUX) && defined(MODULE)
#define __NO_VERSION__
#include <linux/config.h>
#include <linux/version.h>
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/module.h>
#else
#define MOD_INC_USE_COUNT do { } while(0)
#define MOD_DEC_USE_COUNT do { } while(0)
#endif

#if defined(SOLARIS)
#endif

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

#include <sys/cdi.h>

#include <ss7/lmi.h>
#include <ss7/lmi_ioctl.h>
#include <ss7/devi.h>
#include <ss7/devi_ioctl.h>
#include <ss7/sdli.h>
#include <ss7/sdli_ioctl.h>

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

#if defined(LINUX_2_4) || defined(SOLARIS)
#define INT int
#else
#define INT void
#endif

/*
 *  =========================================================================
 *
 *  STREAMS Definitions
 *
 *  =========================================================================
 */
extern struct module_info cdi_minfo = {
	0,				/* Module ID number */
	"cdi-sdl",			/* Module name */
	0,				/* Min packet size accepted */
	INFPSZ,				/* Max packet size accepted */
	1,				/* Hi water mark */
	0				/* Lo water mark */
};

STATIC int cdi_open(queue_t *, dev_t *, int, int, cred_t *);
STATIC int cdi_close(queue_t *, int, cred_t *);

STATIC INT cdi_rput(queue_t *, mblk_t *);

STATIC struct qinit cdi_rinit = {
	cdi_rput,			/* Read put (msg from below) */
	NULL,				/* Read queue service */
	cdi_open,			/* Each open */
	cdi_close,			/* Last close */
	NULL,				/* Admin (not used) */
	&cdi_minfo,			/* Information */
	NULL				/* Statistics */
};

STATIC INT cdi_wput(queue_t *, mblk_t *);

STATIC struct qinit cdi_winit = {
	cdi_wput,			/* Write put (msg from above) */
	NULL,				/* Write queue service */
	NULL,				/* Each open */
	NULL,				/* Last close */
	NULL,				/* Admin (not used) */
	&cdi_minfo,			/* Information */
	NULL				/* Statistics */
};

#define QR_DONE		0
#define QR_ABSORBED	1
#define QR_TRIMMED	2
#define QR_LOOP		3
#define QR_PASSALONG	4
#define QR_PASSFLOW	5
#define QR_DISABLE	6

/*
 *  =========================================================================
 *
 *  CDI-SDL Private Structure
 *
 *  =========================================================================
 */

typedef struct cdi {
	struct cdi *next;		/* list of structures */
	queue_t *rq;			/* rd queue */
	queue_t *wq;			/* wr queue */
#ifndef SOLARIS
	lis_spin_lock_t lock;		/* queue lock */
	struct task_struct *user;	/* user of this queue */
#endif
	uint i_state;			/* interface state */
	uint rbid;			/* rd bufcall id */
	uint wbid;			/* wr bufcall id */
} cdi_t;

#define CDI_PRIV(__q) = ((__q)->q_ptr)

/*
 *  ========================================================================
 *
 *  Buffer Allocation
 *
 *  ========================================================================
 */
STATIC INLINE mblk_t *cd_allocb(mblk_t * bp, int len, int prio, int *rtn)
{
	mblk_t *mp;
	if (bp) {
		if (bp->db_datap->db_lim - bp->b_rptr > len) {
			bp->db_datap->db_type = M_DATA;
			bp->b_wptr = bp->b_rptr;
			*rtn = QR_ABSORBED;
			return (bp);
		}
		if (bp->db_datap->db_lim - bp->db_datap->db_base > len) {
			bp->db_datap->db_type = M_DATA;
			bp->b_wptr = bp->b_rptr = bp->b_datap->db_base;
			*rtn = QR_ABSORBED;
			return (bp);
		}
		if ((mp = allocb(len, prio))) {
			mp->b_cont = bp->b_cont;
			*rtn = QR_TRIMMED;
			return (mp);
		}
		*rtn = -ENOBUFS;
		return (NULL);
	}
	*rtn = -EFAULT;
	return (NULL);

}

/*
 *  =========================================================================
 *
 *  CDI-Provider --> CDI-User Primitives
 *
 *  =========================================================================
 */
/*
 *  CD_INFO_ACK:
 */
STATIC INLINE int cd_info_ack(queue_t * q, mblk_t * mp, ulong max_sdu, ulong min_sdu,
			      ulong ppa_style)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	cd_info_ack_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->cd_primitive = CD_INFO_ACK;
		p->cd_state = cd->i_state;
		p->cd_max_sdu = max_sdu;
		p->cd_min_sdu = min_sdu;
		p->cd_class = CD_HDLC;
		p->cd_duplex = CD_FULLDUPLEX;
		p->cd_output_style = CD_UNACKEDOUTPUT;
		p->cd_features = CD_CANREAD | CD_AUTOALLOW | CD_KEEPALIVE;
		p->cd_addr_length = sizeof(ulong);
		p->cd_ppa_style = ppa_style;
		putnext(q, mp);
	}
	return (err);
}

/*
 *  CD_OK_ACK:
 */
STATIC INLINE int cd_ok_ack(queue_t * q, mblk_t * mp, int prim)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	cd_ok_ack_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->cd_primitive = CD_OK_ACK;
		p->cd_state = cd->i_state;
		p->cd_correct_primitive = prim;
		putnext(q, mp);
	}
	return (err);
}

/*
 *  CD_ERROR_ACK:
 */
STATIC INLINE int cd_error_ack(queue_t * q, mblk_t * mp, int prim, int errno, int exp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	cd_error_ack_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->cd_primitive = CD_ERROR_ACK;
		p->cd_state = cd->i_state;
		p->cd_error_primitive = prim;
		p->cd_errno = errno;
		p->cd_explanation = exp;
		putnext(q, mp);
	}
	return (err);
}

/*
 *  CD_ENABLE_CON:
 */
STATIC INLINE int cd_enable_con(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	cd_enable_con_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->cd_primitive = CD_ENABLE_CON;
		p->cd_state = cd->i_state;
		putnext(q, mp);
	}
	return (err);
}

/*
 *  CD_DISABLE_CON:
 */
STATIC INLINE int cd_disable_con(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	cd_disable_con_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->cd_primitive = CD_DISABLE_CON;
		p->cd_state = cd->i_state;
		putnext(q, mp);
	}
	return (err);
}

/*
 *  CD_ERROR_IND:
 */
STATIC INLINE int cd_error_ind(queue_t * q, mblk_t * mp, int errno, int exp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	cd_error_ind_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->cd_primitive = CD_ERROR_IND;
		p->cd_state = cd->i_state;
		p->cd_errno = errno;
		p->cd_explanation = exp;
		putnext(q, mp);
	}
	return (err);
}

/*
 *  CD_UNITDATA_ACK:
 */
STATIC INLINE int cd_unitdata_ack(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	cd_unitdata_ack_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->cd_primitive = CD_UNITDATA_ACK;
		p->cd_state = cd->i_state;
		putnext(q, mp);
	}
	return (err);
}

/*
 *  CD_UNITDATA_IND:
 */
STATIC INLINE int cd_unitdata_ind(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	cd_unitdata_ind_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;
		p->cd_primitive = CD_UNITDATA_IND;
		p->cd_state = cd->i_state;
		p->cd_src_addr_length = 0;
		p->cd_src_addr_offset = 0;
		p->cd_addr_type = FIXME;
		p->cd_priority = FIXME;
		p->cd_dest_addr_length = 0;
		p->cd_dest_addr_offset = 0;
		putnext(q, mp);
	}
	return (err);
}

/*
 *  CD_BAD_FRAME_IND:
 */
/*
 *  CD_MODEM_SIG_IND:
 */

/*
 *  =========================================================================
 *
 *  SDL-User --> SDL-Provider Primitives
 *
 *  =========================================================================
 */
/*
 *  LMI_INFO_REQ
 */
STATIC INLINE int lmi_info_req(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	lmi_info_req_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;

		putnext(q, mp);
	}
	return (err);
}

/*
 *  LMI_ATTACH_REQ
 */
STATIC INLINE int lmi_attach_req(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	lmi_attach_req_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;

		putnext(q, mp);
	}
	return (err);
}

/*
 *  LMI_DETACH_REQ
 */
STATIC INLINE int lmi_detach_req(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	lmi_detach_req_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;

		putnext(q, mp);
	}
	return (err);
}

/*
 *  LMI_ENABLE_REQ
 */
STATIC INLINE int lmi_enable_req(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	lmi_enable_req_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;

		putnext(q, mp);
	}
	return (err);
}

/*
 *  LMI_DISABLE_REQ
 */
STATIC INLINE int lmi_disable_req(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	lmi_disable_req_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;

		putnext(q, mp);
	}
	return (err);
}

/*
 *  LMI_OPTMGMT_REQ
 */
STATIC INLINE int lmi_optmgmt_req(queue_t * q, mblk_t * mp)
{
	int err = 0;
	cdi_t *cd = CDI_PRIV(q);
	mblk_t *mp;
	lmi_optmgmt_req_t *p;
	if ((mp = cd_allocb(mp, sizeof(*p), BPRI_MED, &err))) {
		mp->b_datap->db_type = M_PCPROTO;
		p = ((typeof(p)) mp->b_wptr)++;

		putnext(q, mp);
	}
	return (err);
}

/*
 *  =========================================================================
 *
 *  CDI-User --> CDI-Provider Primitives
 *
 *  =========================================================================
 */
/*
 *  CD_INFO_REQ:
 */
STATIC INLINE int cd_info_req(queue_t * q, mblk_t * mp)
{
	return lmi_info_req(q, mp);
}

/*
 *  CD_ATTACH_REQ:
 */
STATIC INLINE int cd_attach_req(queue_t * q, mblk_t * mp)
{
	ulong ppa = ((cd_attach_req_t *) mp->b_rptr)->cd_ppa;
	return lmi_attach_req(q, mp, ppa);
}

/*
 *  CD_DETACH_REQ:
 */
STATIC INLINE int cd_detach_req(queue_t * q, mblk_t * mp)
{
	return lmi_detach_req(q, mp);
}

/*
 *  CD_ENABLE_REQ:
 */
STATIC INLINE int cd_enable_req(queue_t * q, mblk_t * mp)
{
	return lmi_enable_req(q, mp);
}

/*
 *  CD_DISABLE_REQ:
 */
STATIC INLINE int cd_disable_req(queue_t * q, mblk_t * mp)
{
	ulong disposal = ((cd_disable_req_t *) mp->b_rptr)->cd_disposal;
	return lmi_disable_req(q, mp);
}

/*
 *  CD_ALLOW_INPUT_REQ:
 */
STATIC INLINE int cd_allow_input_req(queue_t * q, mblk_t * mp)
{
}

/*
 *  CD_READ_REQ:
 */
STATIC INLINE int cd_read_req(queue_t * q, mblk_t * mp)
{
}

/*
 *  CD_UNITDATA_REQ:
 */
STATIC INLINE int cd_unitdata_req(queue_t * q, mblk_t * mp)
{
}

/*
 *  CD_WRITE_READ_REQ:
 */
STATIC INLINE int cd_write_read_req(queue_t * q, mblk_t * mp)
{
}

/*
 *  CD_HALT_INPUT_REQ:
 */
STATIC INLINE int cd_halt_input_req(queue_t * q, mblk_t * mp)
{
}

/*
 *  CD_ABORT_OUTPUT_REQ:
 */
STATIC INLINE int cd_abort_output_req(queue_t * q, mblk_t * mp)
{
}

/*
 *  CD_MUX_NAME_REQ:
 */
/*
 *  CD_MODEM_SIG_REQ:
 */
/*
 *  CD_MODEM_SIG_POLL:
 */

/*
 *  =========================================================================
 *
 *  SDL-Provider --> SDL-User Primitives
 *
 *  =========================================================================
 */
/*
 *  Translate primitives.
 */
STATIC INLINE int xlat_prim(int prim)
{
	switch (prim) {
	case LMI_INFO_REQ:
		return (CD_INFO_REQ);
	case LMI_ATTACH_REQ:
		return (CD_ATTACH_REQ);
	case LMI_DETACH_REQ:
		return (CD_DETACH_REQ);
	case LMI_ENABLE_REQ:
		return (CD_ENABLE_REQ);
	case LMI_DISABLE_REQ:
		return (CD_DISABLE_REQ);
	}
	return (0);
}

/*
 *  Translate state.
 */
STATIC INLINE int xlat_state(int state)
{
	switch (state) {
	case LMI_UNATTACHED:
		return (CD_UNATTACHED);
	case LMI_ATTACH_PENDING:
		return (CD_UNATTACHED);
	case LMI_UNUSABLE:
		return (CD_UNUSABLE);
	case LMI_DISABLED:
		return (CD_DISABLED);
	case LMI_ENABLE_PENDING:
		return (CD_ENABLE_PENDING);
	case LMI_ENABLED:
		return (CD_ENABLED);
	case LMI_DISABLE_PENDING:
		return (CD_DISABLE_PENDING);
	case LMI_DETACH_PENDING:
		return (CD_DISABLED);
	}
	return (0);
}
STATIC INLINE int xlat_reason(int reason)
{
}
STATIC INLINE int xlat_errno(int errno)
{
}

/*
 * LMI_INFO_ACK
 */
STATIC INLINE int lmi_info_ack(queue_t * q, mblk_t * mp)
{
	lmi_info_ack_t *p = ((typeof(p)) mp->b_rptr);
	return cd_info_ack(q, mp, p->lmi_max_sdu, p->lmi_min_sdu, p->lmi_ppa_style);
}

/*
 * LMI_OK_ACK
 */
STATIC INLINE int lmi_ok_ack(queue_t * q, mblk_t * mp)
{
	int err;
	cdi_t *cd = CD_PRIV(q);
	lmi_ok_ack_t *p = ((typeof(p)) mp->b_rptr);
	int oldstate = cd->i_state;
	cd->i_state = xlat_state(p->lmi_state);
	if ((err = cd_ok_ack(q, mp, xlat_prim(p->lmi_correct_primitive))) < 0)
		cd->i_state = oldstate;
	return (err);
}

/*
 * LMI_ERROR_ACK
 */
STATIC INLINE int lmi_error_ack(queue_t * q, mblk_t * mp)
{
	int prim;
	lmi_error_ack_t *p = ((typeof(p)) mp->b_rptr);
	switch (p->lmi_error_primitive) {
	case LMI_INFO_REQ:
		prim = CD_INFO_REQ;
		break;
	case LMI_ATTACH_REQ:
		prim = CD_ATTACH_REQ;
		break;
	case LMI_DETACH_REQ:
		prim = CD_DETACH_REQ;
		break;
	case LMI_ENABLE_REQ:
		prim = CD_ENABLE_REQ;
		break;
	case LMI_DISABLE_REQ:
		prim = CD_DISABLE_REQ;
		break;
	default:
		return (QR_DONE);
	}
	switch (p->lmi_state) {
	}
	switch (p->lmi_errno) {
	}
	switch (p->lmi_reason) {
	case LMI_UNSPEC:
		break;
	case LMI_BADADDRESS:
		errno = CD_BADADDRESS;
		break;
	case LMI_BADADDRTYPE:
		errno = CD_BADADDRTYPE;
		break;
	case LMI_BADDIAL:
		errno = CD_BADDIAL;
		break;
	case LMI_BADDIALTYPE:
		errno = CD_BADDIALTYPE;
		break;
	case LMI_BADDISPOSAL:
		errno = CD_BADDISPOSAL;
		break;
	case LMI_BADFRAME:
		errno = CD_BADFRAME;
		break;
	case LMI_BADPPA:
		errno = CD_BADPPA;
		break;
	case LMI_BADPRIM:
		errno = CD_BADPRIM;
		break;
	case LMI_DISC:
		errno = CD_DISC;
		break;
	case LMI_EVENT:
		errno = CD_EVENT;
		break;
	case LMI_FATALERR:
		errno = CD_FATALERR;
		break;
	case LMI_INITFAILED:
		errno = CD_INITFAILED;
		break;
	case LMI_NOTSUPP:
		errno = CD_NOTSUPP;
		break;
	case LMI_OUTSTATE:
		errno = CD_OUTSTATE;
		break;
	case LMI_PROTOSHORT:
		errno = CD_PROTOSHORT;
		break;
	case LMI_SYSERR:
		errno = CD_SYSERR;
		break;
	case LMI_WRITEFAIL:
		errno = CD_WRITEFAIL;
		break;
	case LMI_CRCERR:
		exp = CD_CRCERR;
		break;
	case LMI_DLE_EOT:
		exp = CD_DLE_EOT;
		break;
	case LMI_FORMAT:
		exp = CD_FORMAT;
		break;
	case LMI_HDLC_ABORT:
		exp = CD_HDLC_ABORT;
		break;
	case LMI_OVERRUN:
		exp = CD_OVERRUN;
		break;
	case LMI_TOOSHORT:
		exp = CD_TOOSHORT;
		break;
	case LMI_INCOMPLETE:
		exp = CD_INCOMPLETE;
		break;
	case LMI_BUSY:
		exp = CD_BUSY;
		break;
	case LMI_NOANSWER:
		exp = CD_NOANSWER;
		break;
	case LMI_CALLREJECT:
		exp = CD_CALLREJECT;
		break;
	case LMI_HDLC_IDLE:
		exp = CD_HDLC_IDLE;
		break;
	case LMI_HDLC_NOTIDLE:
		exp = CD_HDLC_NOTIDLE;
		break;
	case LMI_QUIESCENT:
		exp = CD_QUIESCENT;
		break;
	case LMI_RESUMED:
		exp = CD_RESUMED;
		break;
	case LMI_DSRTIMEOUT:
		exp = CD_DSRTIMEOUT;
		break;
	case LMI_LAN_COLLISIONS:
		exp = CD_LAN_COLLISIONS;
		break;
	case LMI_LAN_REFUSED:
		exp = CD_LAN_REFUSED;
		break;
	case LMI_LAN_NOSTATION:
		exp = CD_LAN_NOSTATION;
		break;
	case LMI_LOSTCTS:
		exp = CD_LOSTCTS;
		break;
	case LMI_DEVERR:
		exp = CD_DEVERR;
		break;
	}
	return cd_error_ack(q, mp);
}

/*
 * LMI_ENABLE_CON
 */
STATIC INLINE int lmi_enable_con(queue_t * q, mblk_t * mp)
{
	return cd_enable_con(q, mp);
}

/*
 * LMI_DISABLE_CON
 */
STATIC INLINE int lmi_disable_con(queue_t * q, mblk_t * mp)
{
	return cd_disable_con(q, mp);
}

/*
 * LMI_OPTMGMT_ACK
 */
STATIC INLINE int lmi_optmgmt_ack(queue_t * q, mblk_t * mp)
{
}

/*
 * LMI_ERROR_IND
 */
STATIC INLINE int lmi_error_ind(queue_t * q, mblk_t * mp)
{
	return cd_error_ind(q, mp);
}

/*
 * LMI_STATS_IND
 */
STATIC INLINE int lmi_stats_ind(queue_t * q, mblk_t * mp)
{
}

/*
 * LMI_EVENT_IND
 */
STATIC INLINE int lmi_event_ind(queue_t * q, mblk_t * mp)
{
}

/*
 *  =========================================================================
 *
 *  STREAMS Message Handling
 *
 *  =========================================================================
 */
/*
 *  -------------------------------------------------------------------------
 *
 *  M_DATA Handling
 *
 *  -------------------------------------------------------------------------
 */
STATIC INLINE int cdi_w_data(queue_t * q, mblk_t * mp)
{
	return (QR_PASSALONG);
}
STATIC INLINE int cdi_r_data(queue_t * q, mblk_t * mp)
{
	return (QR_PASSALONG);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_PROTO, M_PCPROTO Handling
 *
 *  -------------------------------------------------------------------------
 */
STATIC INLINE int cdi_w_proto(queue_t * q, mblk_t * mp)
{
	int rtn;
	cdi_t *cd = CD_PRIV(q);
	ulong oldstate = cd->i_state;
	switch (*((ulong *) mp->b_rptr)) {
	case CD_INFO_REQ:
		rtn = cd_info_req(q, mp);
		break;
	case CD_ATTACH_REQ:
		rtn = cd_attach_req(q, mp);
		break;
	case CD_DETACH_REQ:
		rtn = cd_detach_req(q, mp);
		break;
	case CD_ENABLE_REQ:
		rtn = cd_enable_req(q, mp);
		break;
	case CD_DISABLE_REQ:
		rtn = cd_disable_req(q, mp);
		break;
	case CD_ALLOW_INPUT_REQ:
		rtn = cd_allow_input_req(q, mp);
		break;
	case CD_READ_REQ:
		rtn = cd_read_req(q, mp);
		break;
	case CD_UNITDATA_REQ:
		rtn = cd_unitdata_req(q, mp);
		break;
	case CD_WRITE_READ_REQ:
		rtn = cd_write_read_req(q, mp);
		break;
	case CD_HALT_INPUT_REQ:
		rtn = cd_halt_input_req(q, mp);
		break;
	case CD_ABORT_OUTPUT_REQ:
		rtn = cd_abort_output_req(q, mp);
		break;
	default:
		rtn = -EOPNOTSUPP;
		break;
	}
	if (rtn < 0) {
		cd->i_state = oldstate;
	}
	return (rtn);
}

STATIC INLINE int cdi_r_prim(queue_t * q, mblk_t * mp)
{
	switch (*((ulong *) mp->b_rptr)) {
	case LMI_INFO_ACK:
		return lmi_info_ack(q, mp);
	case LMI_OK_ACK:
		return lmi_ok_ack(q, mp);
	case LMI_ERROR_ACK:
		return lmi_error_ack(q, mp);
	case LMI_ENABLE_CON:
		return lmi_enable_con(q, mp);
	case LMI_DISABLE_CON:
		return lmi_disable_con(q, mp);
	case LMI_OPTMGMT_ACK:
		return lmi_optmgmt_ack(q, mp);
	case LMI_ERROR_IND:
		return lmi_error_ind(q, mp);
	case LMI_STATS_IND:
		return lmi_stats_ind(q, mp);
	case LMI_EVENT_IND:
		return lmi_event_ind(q, mp);
	default:
		return (-EOPNOTSUPP);
	}
}

/*
 *  -------------------------------------------------------------------------
 *
 *  M_IOCTL Handling
 *
 *  -------------------------------------------------------------------------
 */
/*
 *  -------------------------------------------------------------------------
 *
 *  M_FLUSH Handling
 *
 *  -------------------------------------------------------------------------
 */
STATIC INLINE int cdi_m_flush(queue_t * q, mblk_t * mp, const uint8_t mflag)
{
	if (*mp->b_rptr & mflag) {
		if (*mp->b_rptr & FLUSHBAND)
			flushband(q, mp->b_rptr[1], FLUSHALL);
		else
			flushq(q, FLUSHALL);
	}
	return (QR_PASSALONG);
}
STATIC INLINE int cdi_w_flush(queue_t * q, mblk_t * mp)
{
	return cdi_m_flush(q, mp, FLUSHW);
}
STATIC INLINE int cdi_r_flush(queue_t * q, mblk_t * mp)
{
	return cdi_m_flush(q, mp, FLUSHR);
}

/*
 *  =========================================================================
 *
 *  PUT and SRV
 *
 *  =========================================================================
 */
STATIC INLINE int cdi_r_prim(queue_t * q, mblk_t * mp)
{
	switch (mp->b_datap->db_type) {
	case M_DATA:
		return cdi_r_data(q, mp);
	case M_PROTO:
	case M_PCPROTO:
		return cdi_r_proto(q, mp);
	case M_FLUSH:
		return cdi_r_flush(q, mp);
	}
	return (QR_PASSFLOW);
}
STATIC INLINE int cdi_w_prim(queue_t * q, mblk_t * mp)
{
	switch (mp->b_datap->db_type) {
	case M_DATA:
		return cdi_w_data(q, mp);
	case M_PROTO:
	case M_PCPROTO:
		return cdi_w_proto(q, mp);
	case M_FLUSH:
		return cdi_w_flush(q, mp);
	case M_IOCTL:
		return cdi_w_ioctl(q, mp);
	}
	return (QR_PASSALONG);
}
STATIC INLINE int cdi_putq(queue_t * q, mblk_t * mp, int (*proc) (queue_t *, mblk_t *))
{
	int rtn = 0;
	ensure(q, return (-EFAULT));
	ensure(mp, return (-EFAULT));
	cdi_spinlock(q);
	switch ((rtn = proc(q, mp))) {
	case QR_DONE:
		freemsg(mp);
	case QR_ABSORBED:
		break;
	case QR_TRIMMED:
		freeb(mp);
		break;
	case QR_LOOP:
	case QR_PASSALONG:
		putnext(q, mp);
		break;
	default:
		ptrace(("ERROR: (q dropping) %d\n", rtn));
		freemsg(mp);
		break;
	}
	cdi_spinunlock(q);
	return ((INT) (rtn));
}
STATIC INT cdi_rput(queue_t * q, mblk_t * mp)
{
	return (INT) cdi_putq(q, mp, &cdi_r_prim);
}
STATIC INT cdi_wput(queue_t * q, mblk_t * mp)
{
	return (INT) cdi_putq(q, mp, &cdi_w_prim);
}

/*
 *  =========================================================================
 *
 *  OPEN and CLOSE
 *
 *  =========================================================================
 */
STATIC int cdi_open(queue_t * q, dev_t * devp, int flag, int sflag, cred_t * crp)
{
	(void) crp;
	if (CDI_PRIV(q))	/* already open */
		return (0);
	if (sflag == MODOPEN || WR(q)->q_next) {
		if (!(cdi_alloc_priv(q)))
			return (ENOMEM);
		return (0);
	}
	return (EIO);
}
STATIC int cdi_close(queue_t * q, int flag, cred_t * crp)
{
	(void) flag;
	(void) crp;
	cdi_free_priv(q);
	return (0);
}


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

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

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