📄 sdl.c
字号:
/***************************************************************************** @(#) sdl.c,v 0.7.8.1 2001/12/11 13:15:35 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:35 by brian *****************************************************************************/static char const ident[] = "sdl.c,v 0.7.8.1 2001/12/11 13:15:35 brian Exp";/* * This is a SDL (Signalling Data Terminal) loadable module which provides * all of the capabilities of the SDLI while allowing device drivers to * provide a few missing functions by registering with the module to provide * a complete SDL driver. This relieves much of the LiS STREAMS burden from * the driver implementation and permits the driver to be more portable. It * also allows SS7 signalling link compliant state machines in the SDT and SL * autopush modules to be tested once, but used by many drivers. */#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 <sys/cmn_err.h>#include "../debug.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 "../lmi/lm.h"#include "../devi/dev.h"#include "../sdli/sdl.h"#define SDL_DESCRIP "SS7/SDLI: (Signalling Data Link Interface) STREAMS DRIVER."#define SDL_COPYRIGHT "Copyright (c) 1997-2001 Brian Bidulock. All Rights Reserved."#define SDL_DEVICES "Supports OpenSS7 SDL drivers."#define SDL_CONTACT "Brian Bidulock <bidulock@openss7.org>"#define SDL_BANNER SDL_DESCRIP "\n" \ SDL_COPYRIGHT "\n" \ SDL_DEVICES "\n" \ SDL_CONTACT "\n"#ifdef MODULEMODULE_AUTHOR(SDL_CONTACT);MODULE_DESCRIPTION(SDL_DESCRIP);MODULE_SUPPORTED_DEVICE(SDL_DEVICES);#define MODULE_STATIC static#else#define MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#define MODULE_STATIC#endif#ifdef SDL_DEBUGstatic int sdl_debug = SL_DEBUG;#elsestatic int sdl_debug = 2;#endif#define DEBUG_LEVEL sdl_debug#define SDL_CMAJOR 0#define SDL_NMINOR 255/* * ======================================================================= * * STREAMS Definitions * * ======================================================================= */static struct module_info sdl_minfo ={ 0, /* Module ID number */ "sdl", /* Module name */ 1, /* Min packet size accepted */ 512, /* Max packet size accepted */ 8*272, /* Hi water mark */ 1*272 /* Lo water mark */};static void sdl_rput (queue_t *, mblk_t *);static void sdl_rsrv (queue_t *);static int sdl_open (queue_t *, dev_t *, int, int, cred_t *);static int sdl_close(queue_t *, int, cred_t *);static struct qinit sdl_rinit ={ sdl_rput, /* Read put (msg from below) */ sdl_rsrv, /* Read queue service */ sdl_open, /* Each open */ sdl_close, /* Last close */ NULL, /* Admin (not used) */ &sdl_minfo, /* Information */ NULL /* Statistics */};static void sdl_wput (queue_t *, mblk_t *);static void sdl_wsrv (queue_t *);static struct qinit sdl_winit ={ sdl_wput, /* Write put (msg from above) */ sdl_wsrv, /* Write queue service */ NULL, /* Each open */ NULL, /* Last close */ NULL, /* Admin (not used) */ &sdl_minfo, /* Information */ NULL /* Statistics */};#ifndef LIS_REGISTEREDstatic#endifstruct streamtab sdl_info ={ &sdl_rinit, /* Upper read queue */ &sdl_winit, /* Upper write queue */ NULL, /* Lower read queue */ NULL /* Lower write queue */};/* * ======================================================================= * * LMI PROTOCOL CONFIGURATION IOCTLs * * ======================================================================= */static intsdl_iocgoptions(sdl_t *sdl, int cmd, void *arg){ bcopy(&sdl->option, arg, _IOC_SIZE(cmd)); return(0);}static intsdl_iocsoptions(sdl_t *sdl, int cmd, void *arg){ bcopy(arg, &sdl->option, _IOC_SIZE(cmd)); return(0);}static intsdl_iocgconfig(sdl_t *sdl, int cmd, void *arg){ bcopy(&sdl->config, arg, _IOC_SIZE(cmd)); return(0);}static intsdl_iocsconfig(sdl_t *sdl, int cmd, void *arg){ signed long int *src, *dst, *end; (void)cmd; dst = (signed long int *)&sdl->config; end = (signed long int *)((&sdl->config)+1); src = arg; while ( dst < end ) { if ( *src != -1 ) *dst = *src; dst++; src++; } return(0);}static intsdl_iocgstatem(sdl_t *sdl, int cmd, void *arg){ bcopy(&sdl->statem, arg, _IOC_SIZE(cmd)); return(0);}static intsdl_iocsstatsp(sdl_t *sdl, int cmd, void *arg){ (void)sdl; (void)cmd; (void)arg; return EOPNOTSUPP;}static intsdl_iocgstatsp(sdl_t *sdl, int cmd, void *arg){ (void)sdl; (void)cmd; (void)arg; return EOPNOTSUPP;}static intsdl_ioccstats(sdl_t *sdl, int cmd, void *arg){ (void)arg; bzero(&sdl->stats, _IOC_SIZE(cmd)); return(0);}static intsdl_iocgstats(sdl_t *sdl, int cmd, void *arg){ bcopy(&sdl->stats, arg, _IOC_SIZE(cmd)); return(0);}static intsdl_iocsnotify(sdl_t *sdl, int cmd, void *arg){ caddr_t dst, src, end; (void)cmd; src = arg; dst = (caddr_t)&sdl->notify; end = (caddr_t)((&sdl->notify)+1); while ( dst < end ) *dst++ |= *src++; return(0);}static intsdl_ioccnotify(sdl_t *sdl, int cmd, void *arg){ caddr_t dst, src, end; (void)cmd; src = arg; dst = (caddr_t)&sdl->notify; end = (caddr_t)((&sdl->notify)+1); while ( dst < end ) *dst++ &= ~*src++; return(0);}static intsdl_iocgnotify(sdl_t *sdl, int cmd, void *arg){ bcopy(&sdl->notify, arg, _IOC_SIZE(cmd)); return(0);}static int (*sdl_ioc_lmiops [])(sdl_t *, int, void *) ={ sdl_iocgoptions, /* SDL_IOCGOPTIONS */ sdl_iocsoptions, /* SDL_IOCSOPTIONS */ sdl_iocgconfig, /* SDL_IOCGCONFIG */ sdl_iocsconfig, /* SDL_IOCSCONFIG */ NULL, /* SDL_IOCTCONFIG */ NULL, /* SDL_IOCCCONFIG */ sdl_iocgstatem, /* SDL_IOCGSTATEM */ NULL, /* SDL_IOCCMRESET */ sdl_iocgstatsp, /* SDL_IOCGSTATSP */ sdl_iocsstatsp, /* SDL_IOCSSTATSP */ sdl_iocgstats, /* SDL_IOCGSTATS */ sdl_ioccstats, /* SDL_IOCCSTATS */ sdl_iocgnotify, /* SDL_IOCGNOTIFY */ sdl_iocsnotify, /* SDL_IOCSNOTIFY */ sdl_ioccnotify /* SDL_IOCCNOTIFY */};/* * ======================================================================= * * SDL->SDT Service Primitives (M_CTL, M_PROTO, M_PCPROTO) * * ======================================================================= */static inline voidsdl_daedr_received_bits_ind(sdl_t *sdl, mblk_t *mp){ /* called by driver */ putq(sdl->rq, mp);}static inline voidsdl_daedr_correct_su_ind(sdl_t *sdl, int count){ /* called by driver */ mblk_t *mp; if ( (mp = allocb(SDL_DAEDR_CORRECT_SU_IND_SIZE, BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; *((int *)mp->b_wptr)++ = SDL_DAEDR_CORRECT_SU_IND; *((int *)mp->b_wptr)++ = count; putq(sdl->rq, mp); }}static inline voidsdl_daedr_su_in_error_ind(sdl_t *sdl){ /* called by driver */ mblk_t *mp; if ( (mp = allocb(SDL_DAEDR_SU_IN_ERROR_IND_SIZE, BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; *((int *)mp->b_wptr)++ = SDL_DAEDR_SU_IN_ERROR_IND; putq(sdl->rq, mp); }}static inline voidsdl_daedt_transmission_request_ind(sdl_t *sdl){ /* called by driver */ mblk_t *mp; if ( (mp = allocb(SDL_DAEDT_TRANSMISSION_REQUEST_IND_SIZE, BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; *((int *)mp->b_wptr)++ = SDL_DAEDT_TRANSMISSION_REQUEST_IND; putq(sdl->rq, mp); }}static struct sdl_ucalls sdl_mod_ucalls ={ sdl_daedr_received_bits_ind, /* daedr_received_bits */ sdl_daedr_correct_su_ind, /* daedr_correct_su */ sdl_daedr_su_in_error_ind, /* daedr_su_in_error */ sdl_daedt_transmission_request_ind /* daedt_tx_request */};/* * ======================================================================= * * SDL->DEV Service Calls (Driver) * * ======================================================================= */static void sdl_dev_xmit(sdl_t *sdl, mblk_t *mp){ ensure( sdl && sdl->driver, return ); if ( sdl->driver) sdl->driver->dcalls->xmit(sdl->device, mp);}static void sdl_dev_tx_start(sdl_t *sdl){ ensure( sdl && sdl->driver, return ); if ( sdl->driver) sdl->driver->dcalls->tx_start(sdl->device);}static void sdl_dev_rx_start(sdl_t *sdl){ ensure( sdl && sdl->driver, return ); if ( sdl->driver) sdl->driver->dcalls->rx_start(sdl->device);}static struct sdl_mcalls sdl_drv_dcalls ={ sdl_dev_xmit, /* xmit */ sdl_dev_tx_start, /* tx_start */ sdl_dev_rx_start /* rx_start */};/* * ======================================================================= * * SDL->DEV Service Primitives (M_CTL, M_PROTO, M_PCPROTO) * * ======================================================================= */static inline void sdl_dprim(sdl_t *sdl, int type, int prim){ mblk_t *mp; if ( (mp = allocb(sizeof(sdl_ulong), BPRI_HI)) ) { mp->b_datap->db_type = type; *((int *)mp->b_wptr)++ = prim; putnext(sdl->wq, mp); /* FIXME */ }}static void sdl_dev_xmit_req(sdl_t *sdl, mblk_t *mp){ if ( mp->b_datap->db_type != M_DATA ) { *((int *)mp->b_rptr) = 0; /* DEV_XMIT_REQ; FIXME */ mp->b_datap->db_type = M_PROTO; } putnext(sdl->wq, mp); /* FIXME */}static void sdl_dev_tx_start_req(sdl_t *sdl){ sdl_dprim(sdl, M_PCPROTO, 1); /* DEV_TX_START_REQ); FIXME */}static void sdl_dev_rx_start_req(sdl_t *sdl){ sdl_dprim(sdl, M_PCPROTO, 2); /* DEV_RX_START_REQ); FIXME */}static struct sdl_mcalls sdl_mod_dcalls ={ sdl_dev_xmit_req, /* xmit */ sdl_dev_tx_start_req, /* tx_start */ sdl_dev_rx_start_req /* rx_start */};/* * ======================================================================= * * PROTOCOL STATE MACHINE FUNCTIONS * * ======================================================================= */static void sdl_daedr_recvd_frame(sdl_t *sdl, mblk_t *mp){ if ( sdl->statem.daedr_state == SDL_STATE_IN_SERVICE ) { /* * Here we check for length and length indicator problems. * The message block should be an M_DATA block. */ int len = mp->b_wptr - mp->b_rptr; if ( sdl->option.popt & SS7_POPT_XSN ) {// ptrace(("message len=%d, li=%d, m=%ld\n", len,// ntohs(((sdl_ushort *)mp->b_rptr)[2]&0x01ff),// sdl->config.m)); if ( 6 <= len && len <= sdl->config.m + 6 ) { int li = ntohs(((sdl_ushort *)mp->b_rptr)[2]) & 0x01ff; len -= 6; if ( len == li || ( li == 0x1ff && len > li ) ) { sdl->ucalls->daedr_received_bits(sdl, mp); return; } } } else {// ptrace(("message len=%d, li=%d, m=%ld\n", len,// (int)(((sdl_uchar *)mp->b_rptr)[2]&0x3f),// sdl->config.m)); if ( 3 <= len && len <= sdl->config.m + 3 ) { int li = ((sdl_uchar *)mp->b_rptr)[2] & 0x3f; len -= 3; if ( len == li || ( li == 0x3f && len > li ) ) { sdl->ucalls->daedr_received_bits(sdl, mp); return; } } } assert(mp->b_datap->db_ref); freemsg(mp); sdl->ucalls->daedr_su_in_error(sdl); return; } assert(mp->b_datap->db_ref); freemsg(mp);}static void sdl_daedr_compr_frame(sdl_t *sdl, int count){ if ( sdl->statem.daedr_state == SDL_STATE_IN_SERVICE ) sdl->ucalls->daedr_correct_su(sdl, count);}static void sdl_daedr_error_frame(sdl_t *sdl){ if ( sdl->statem.daedr_state == SDL_STATE_IN_SERVICE ) if ( !sdl->statem.octet_counting_mode ) sdl->ucalls->daedr_su_in_error(sdl);}static void sdl_daedr_loss_of_sync(sdl_t *sdl){ sdl->statem.octet_counting_mode = 1;}static void sdl_daedr_N_octets(sdl_t *sdl){ if ( sdl->statem.daedr_state == SDL_STATE_IN_SERVICE ) sdl->ucalls->daedr_su_in_error(sdl);}static void sdl_daedt_tx_request(sdl_t *sdl){ if ( sdl->statem.daedt_state == SDL_STATE_IN_SERVICE ) sdl->ucalls->daedt_tx_request(sdl);}/* * ======================================================================= * * SDT->SDL Service Calls (Driver) * * ======================================================================= */static void sdl_daedt_bits_for_trans(sdl_t *sdl, mblk_t *mp){ sdl->dcalls->xmit(sdl, mp);}static void sdl_daedt_start(sdl_t *sdl){ sdl->statem.daedt_state = SDL_STATE_IN_SERVICE; sdl->dcalls->tx_start(sdl);}static void sdl_daedr_start(sdl_t *sdl){ sdl->statem.daedr_state = SDL_STATE_IN_SERVICE; sdl->dcalls->rx_start(sdl);}static struct sdl_dcalls sdl_drv_ops ={ sdl_daedt_bits_for_trans, /* daedt_xmit */ sdl_daedt_start, /* daedt_start */ sdl_daedr_start /* daedr_start */};/* * ======================================================================= * * SDT->SDL Service Primitives (M_CTL, M_PROTO, M_PCPROTO) * * ======================================================================= */static void sdl_daedt_xmit_req(sdl_t *sdl, mblk_t *mp){ sdl_daedt_bits_for_trans(sdl, mp);}static void sdl_daedt_start_req(sdl_t *sdl, mblk_t *mp){ assert(mp->b_datap->db_ref); freemsg(mp); sdl_daedt_start(sdl);}static void sdl_daedr_start_req(sdl_t *sdl, mblk_t *mp){ assert(mp->b_datap->db_ref); freemsg(mp); sdl_daedr_start(sdl);}static void (*sdl_sdt_ops[])(sdl_t *, mblk_t *) ={ sdl_daedt_xmit_req, /* SDL_DAEDT_BITS_FOR_TRANS */ sdl_daedt_start_req, /* SDL_DAEDT_START_REQ */ sdl_daedr_start_req /* SDL_DAEDR_START_REQ */};/* * ======================================================================= * * DEV->SDL Service Calls (Driver) (WARNING: called at IRQ) * * ======================================================================= */static void dev_daedr_recvd_frame(struct dev *dev, mblk_t *mp){ /* FIXME: if (sdl->rq) build mp and place on sdl->rq */ sdl_daedr_recvd_frame(dev->module, mp);}static void dev_daedr_compr_frame(struct dev *dev, int count){ /* FIXME: if (sdl->rq) build mp and place on sdl->rq */ sdl_daedr_compr_frame(dev->module, count);}static void dev_daedr_error_frame(struct dev *dev){ /* FIXME: if (sdl->rq) build mp and place on sdl->rq */ sdl_daedr_error_frame(dev->module);}static void dev_daedr_loss_of_sync(struct dev *dev){ /* FIXME: if (sdl->rq) build mp and place on sdl->rq */ sdl_daedr_loss_of_sync(dev->module);}static void dev_daedr_N_octets(struct dev *dev){ /* FIXME: if (sdl->rq) build mp and place on sdl->rq */ sdl_daedr_N_octets(dev->module);}static void dev_daedt_tx_request(struct dev *dev){ /* FIXME: if (sdl->rq) build mp and place on sdl->rq */ sdl_daedt_tx_request(dev->module);}static dev_ucalls_t sdl_dev_ucalls ={ dev_daedr_recvd_frame, /* daedr_recvd_frame */ dev_daedr_compr_frame, /* daedr_compr_frame */ dev_daedr_error_frame, /* daedr_error_frame */ dev_daedr_loss_of_sync, /* daedr_loss_of_sync */ dev_daedr_N_octets, /* daedr_N_octets */ dev_daedt_tx_request /* daedt_tx_request */};/* * ======================================================================= * * DEV->SDL Service Primitives (M_CTL, M_PROTO, M_PCPROTO * * ======================================================================= */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -