📄 lm.c
字号:
/***************************************************************************** @(#) lm.c,v 0.7.8.1 2001/12/11 13:15:12 brian Exp ----------------------------------------------------------------------------- Copyright (C) 1997-2001 Brian Bidulock <bidulock@dallas.net> All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ----------------------------------------------------------------------------- Last Modified 2001/12/11 13:15:12 by brian *****************************************************************************/static char const ident[] = "lm.c,v 0.7.8.1 2001/12/11 13:15:12 brian Exp";#define __NO_VERSION__#include <linux/config.h>#include <linux/version.h>#include <linux/modversions.h>#include <linux/module.h>#include <sys/stream.h>#include <sys/stropts.h>//#include <linux/version.h>//#include <linux/modversions.h>//#include <linux/kmod.h>#include "../debug.h"#include <ss7/lmi.h>#include <ss7/lmi_ioctl.h>#include "../lmi/lm.h"#define DEBUG_LEVEL 2/* * ----------------------------------------------------------------------- * * LMI PRIMITIVES * * ----------------------------------------------------------------------- */static inline mblk_t *lmi_reuseb(mblk_t *mp, size_t room){ mblk_t *m2; if ( mp && mp->b_datap->db_ref < 2 && mp->b_datap->db_lim - mp->b_datap->db_base >= room ) { mp->b_rptr = mp->b_datap->db_base; mp->b_wptr = mp->b_rptr + room; if ( mp->b_cont && (m2 = unlinkb(mp)) ) freemsg(m2); return mp; } if ( (m2 = allocb(room, BPRI_HI)) ) { m2->b_wptr += room; if ( !mp ) return m2; m2->b_datap->db_type = mp->b_datap->db_type; freemsg(mp); return m2; } if ( mp ) freemsg(mp); return NULL;}/* * ======================================================================= * * LMI PRIMITIVES * * ======================================================================= *//* Upstream Primitives */static inline intlmi_error_ind(lmi_t *lmi, mblk_t **mpp, int err){ if ( (*mpp = lmi_reuseb(*mpp, LMI_ERROR_IND_SIZE)) ) { lmi_error_ind_t *p = (lmi_error_ind_t *)(*mpp)->b_rptr; (*mpp)->b_datap->db_type = M_PCPROTO; p->lmi_primitive = LMI_ERROR_IND; p->lmi_state = lmi->state; p->lmi_errno = err&0x0000ffff; p->lmi_reason = err&0xffff0000; qreply(lmi->wq, *mpp); *mpp = NULL; } return(0);}static inline intlmi_error_ack(lmi_t *lmi, mblk_t **mpp, int prim, int err){ if ( (*mpp = lmi_reuseb(*mpp, LMI_ERROR_ACK_SIZE)) ) { lmi_error_ack_t *p = (lmi_error_ack_t *)(*mpp)->b_rptr; p->lmi_primitive = LMI_ERROR_ACK; p->lmi_state = lmi->state; p->lmi_error_primitive = prim; p->lmi_errno = err&0x0000ffff; p->lmi_reason = err&0xffff0000; qreply(lmi->wq, *mpp); *mpp = NULL; } return(0);}static inline intlmi_ok_ack(lmi_t *lmi, mblk_t **mpp, int prim, int err){ if ( err ) return lmi_error_ack(lmi, mpp, prim, err); if ( (*mpp = lmi_reuseb(*mpp, LMI_OK_ACK_SIZE)) ) { lmi_ok_ack_t *p = (lmi_ok_ack_t *)(*mpp)->b_rptr; p->lmi_primitive = LMI_OK_ACK; p->lmi_state = lmi->state; p->lmi_correct_primitive= prim; qreply(lmi->wq, *mpp); *mpp = NULL; } return(0);}static inline intlmi_info_ack(lmi_t *lmi, mblk_t **mpp, int prim, void *ppa, int len, int err){ if ( err ) return lmi_error_ack(lmi, mpp, prim, err); if ( (*mpp = lmi_reuseb(*mpp, LMI_INFO_ACK_SIZE+len)) ) { lmi_info_ack_t *p = (lmi_info_ack_t *)(*mpp)->b_rptr; p->lmi_primitive = LMI_INFO_ACK; p->lmi_version = 0x00070200; p->lmi_state = lmi->state; p->lmi_max_sdu = 0xffffffff; p->lmi_min_sdu = 0; p->lmi_header_len = 0; ptrace(("ppa len = %d, ppa addr = 0x%08x\n", len, (unsigned int)ppa)); if ( len ) { p->lmi_ppa_style = LMI_STYLE2; bcopy(ppa, p->lmi_ppa_addr, len); } else { p->lmi_ppa_style = LMI_STYLE1; } qreply(lmi->wq, *mpp); } return(0);}static inline intlmi_enable_con(lmi_t *lmi, mblk_t **mpp, int err){ if ( err ) return lmi_error_ind(lmi, mpp, err); if ( (*mpp = lmi_reuseb(*mpp, LMI_ENABLE_CON_SIZE)) ) { lmi_enable_con_t *p = (lmi_enable_con_t *)(*mpp)->b_rptr; p->lmi_primitive = LMI_ENABLE_CON; p->lmi_state = lmi->state; qreply(lmi->wq, *mpp); } return(0);}static inline intlmi_enable_ack(lmi_t *lmi, mblk_t **mpp, int prim, int err){ int ret; if ( err ) return lmi_error_ack(lmi, mpp, prim, err); if ( !(ret = lmi_ok_ack(lmi, mpp, prim, 0)) ) ret = lmi_enable_con(lmi, mpp, 0); return(ret);}static inline intlmi_disable_con(lmi_t *lmi, mblk_t **mpp, int err){ if ( err ) return lmi_error_ind(lmi, mpp, err); if ( (*mpp = lmi_reuseb(*mpp, LMI_DISABLE_CON_SIZE)) ) { lmi_disable_con_t *p = (lmi_disable_con_t *)(*mpp)->b_rptr; p->lmi_primitive = LMI_DISABLE_CON; p->lmi_state = lmi->state; qreply(lmi->wq, *mpp); } return(0);}static inline intlmi_disable_ack(lmi_t *lmi, mblk_t **mpp, int prim, int err){ int ret; if ( err ) return lmi_error_ack(lmi, mpp, prim, err); if ( !(ret = lmi_ok_ack(lmi, mpp, prim, 0)) ) ret = lmi_disable_con(lmi, mpp, 0); return(ret);}/* Downstream Primitives */intlmi_info(lmi_t *lmi, void **ppap, int *lenp){ int err; lmi_driver_t *drv = lmi->driver; if ( drv && (err = drv->ops.lmi.info(lmi->device, ppap, lenp)) ) return (err); return(0);}intlmi_attach(lmi_t *lmi, void *ppa, int len){ int err; lmi_driver_t *drv = lmi->driver; if ( lmi->state != LMI_UNATTACHED ) return (EINVAL|LMI_OUTSTATE); if ( drv && (err = drv->ops.lmi.attach(lmi->device, ppa, len)) ) return (err); lmi->state = LMI_DISABLED; return(0);}intlmi_detach(lmi_t *lmi){ int err; lmi_driver_t *drv = lmi->driver; if ( lmi->state != LMI_DISABLED ) return (EINVAL|LMI_OUTSTATE); if ( drv && (err = drv->ops.lmi.detach(lmi->device)) ) return (err); lmi->state = LMI_UNATTACHED; return(0);}intlmi_enable(lmi_t *lmi){ int err; lmi_driver_t *drv = lmi->driver; if ( lmi->state != LMI_DISABLED ) return (EINVAL|LMI_OUTSTATE); if ( drv && (err = drv->ops.lmi.enable(lmi->device)) ) return (err); lmi->state = LMI_ENABLED; return(0);}intlmi_disable(lmi_t *lmi){ int err; lmi_driver_t *drv = lmi->driver; if ( lmi->state != LMI_ENABLED ) return (EINVAL|LMI_OUTSTATE); if ( drv && (err = drv->ops.lmi.disable(lmi->device)) ) return (err); lmi->state = LMI_DISABLED; return(0);}static intlmi_info_req(lmi_t *lmi, mblk_t *mp){ static void *ppa = NULL; static int len = 0; int err = lmi_info(lmi, &ppa, &len); return lmi_info_ack(lmi, &mp, *((int *)mp->b_rptr), ppa, len, err);}static intlmi_attach_req(lmi_t *lmi, mblk_t *mp){ union LMI_primitives *p = (union LMI_primitives *)mp->b_rptr; return lmi_ok_ack(lmi, &mp, *((int *)mp->b_rptr), lmi_attach(lmi, p->attach_req.lmi_ppa, mp->b_wptr - mp->b_rptr - LMI_ATTACH_REQ_SIZE));}static intlmi_detach_req(lmi_t *lmi, mblk_t *mp){ return lmi_ok_ack(lmi, &mp, *((int *)mp->b_rptr), lmi_detach(lmi));}static intlmi_enable_req(lmi_t *lmi, mblk_t *mp){ return lmi_enable_ack(lmi, &mp, *((int *)mp->b_rptr), lmi_enable(lmi));}static intlmi_disable_req(lmi_t *lmi, mblk_t *mp){ return lmi_disable_ack(lmi, &mp, *((int *)mp->b_rptr), lmi_disable(lmi));}int (*lmi_lmi_ops[5])(lmi_t *, mblk_t *) ={ lmi_info_req, /* LMI_INFO_REQ */ lmi_attach_req, /* LMI_ATTACH_REQ */ lmi_detach_req, /* LMI_DETACH_REQ */ lmi_enable_req, /* LMI_ENABLE_REQ */ lmi_disable_req /* LMI_DISABLE_REQ */};/* * ======================================================================= * * DRIVER * * ======================================================================= */lmi_t *lmi_drv_attach(dev_t dev, lmi_driver_t *list, size_t size){ lmi_driver_t *drv; lmi_ops_t *ops; lmi_t **lmip, *lmi = NULL; int cminor = getminor(dev); int cmajor = getmajor(dev); for ( drv = list; drv; drv = drv->next ) if ( cmajor == drv->cmajor ) break; if ( !drv ) return NULL; ops = &drv->ops; if ( cminor >= drv->nminor ) return NULL; for ( lmip = &drv->list; *lmip; lmip = &(*lmip)->next ) { if ( cminor < getminor((*lmip)->devnum) ) { lmi = NULL; break; } if ( cminor == getminor((*lmip)->devnum) ) { lmi = *lmip; break; } } if ( !lmi ) { if ( !(lmi = kmalloc(size, GFP_KERNEL)) ) return NULL; bzero(drv, size); if ( !(lmi->device = ops->dev.attach(dev)) ) { kfree(lmi); return NULL; } lmi->next = *lmip; *lmip = lmi; lmi->devnum = dev; lmi->driver = drv; } lmi->state = LMI_UNATTACHED; return lmi;}intlmi_drv_close(lmi_t *lmi, lmi_ulong *tids, int ntids, lmi_ulong *bids, int nbids){ int i; lmi_t **lmip; lmi_driver_t *drv = lmi->driver; lmi_ops_t *ops = &drv->ops; for ( lmip = &drv->list; *lmip; lmip = &(*lmip)->next ) if ( *lmip == lmi ) break; if ( !*lmip ) return ENXIO; if ( lmi->state == LMI_ENABLED ) { ops->lmi.disable(lmi); lmi->state = LMI_DISABLED; } if ( lmi->state == LMI_DISABLED ) { ops->lmi.detach(lmi); lmi->state = LMI_UNATTACHED; } for ( i=0; i<ntids; i++ ) if ( tids[i] ) { untimeout(tids[i]); tids[i] = 0; } for ( i=0; i<nbids; i++ ) if ( bids[i] ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -