📄 sdl.c
字号:
break; } break; } case LMI_IOC_MAGIC: { if (count < size || s->i_state == LMI_UNATTACHED) { ret = (-EINVAL); break; } switch (nr) { case _IOC_NR(LMI_IOCGOPTIONS): /* lmi_option_t */ ret = lmi_iocgoptions(q, mp); break; case _IOC_NR(LMI_IOCSOPTIONS): /* lmi_option_t */ ret = lmi_iocsoptions(q, mp); break; case _IOC_NR(LMI_IOCGCONFIG): /* lmi_config_t */ ret = lmi_iocgconfig(q, mp); break; case _IOC_NR(LMI_IOCSCONFIG): /* lmi_config_t */ ret = lmi_iocsconfig(q, mp); break; case _IOC_NR(LMI_IOCTCONFIG): /* lmi_config_t */ ret = lmi_ioctconfig(q, mp); break; case _IOC_NR(LMI_IOCCCONFIG): /* lmi_config_t */ ret = lmi_ioccconfig(q, mp); break; case _IOC_NR(LMI_IOCGSTATEM): /* lmi_statem_t */ ret = lmi_iocgstatem(q, mp); break; case _IOC_NR(LMI_IOCCMRESET): /* lmi_statem_t */ ret = lmi_ioccmreset(q, mp); break; case _IOC_NR(LMI_IOCGSTATSP): /* lmi_sta_t */ ret = lmi_iocgstatsp(q, mp); break; case _IOC_NR(LMI_IOCSSTATSP): /* lmi_sta_t */ ret = lmi_iocsstatsp(q, mp); break; case _IOC_NR(LMI_IOCGSTATS): /* lmi_stats_t */ ret = lmi_iocgstats(q, mp); break; case _IOC_NR(LMI_IOCCSTATS): /* lmi_stats_t */ ret = lmi_ioccstats(q, mp); break; case _IOC_NR(LMI_IOCGNOTIFY): /* lmi_notify_t */ ret = lmi_iocgnotify(q, mp); break; case _IOC_NR(LMI_IOCSNOTIFY): /* lmi_notify_t */ ret = lmi_iocsnotify(q, mp); break; case _IOC_NR(LMI_IOCCNOTIFY): /* lmi_notify_t */ ret = lmi_ioccnotify(q, mp); break; default: ptrace(("%s: %p: ERROR: Unsupported LMI ioctl %d\n", MOD_NAME, s, nr)); ret = -EOPNOTSUPP; break; } break; } case SDL_IOC_MAGIC: { if (count < size || s->i_state == LMI_UNATTACHED) { ret = (-EINVAL); break; } switch (nr) { case _IOC_NR(SDL_IOCGOPTIONS): /* lmi_option_t */ ret = sdl_iocgoptions(q, mp); break; case _IOC_NR(SDL_IOCSOPTIONS): /* lmi_option_t */ ret = sdl_iocsoptions(q, mp); break; case _IOC_NR(SDL_IOCGCONFIG): /* sdl_config_t */ ret = sdl_iocgconfig(q, mp); break; case _IOC_NR(SDL_IOCSCONFIG): /* sdl_config_t */ ret = sdl_iocsconfig(q, mp); break; case _IOC_NR(SDL_IOCTCONFIG): /* sdl_config_t */ ret = sdl_ioctconfig(q, mp); break; case _IOC_NR(SDL_IOCCCONFIG): /* sdl_config_t */ ret = sdl_ioccconfig(q, mp); break; case _IOC_NR(SDL_IOCGSTATEM): /* sdl_statem_t */ ret = sdl_iocgstatem(q, mp); break; case _IOC_NR(SDL_IOCCMRESET): /* sdl_statem_t */ ret = sdl_ioccmreset(q, mp); break; case _IOC_NR(SDL_IOCGSTATSP): /* lmi_sta_t */ ret = sdl_iocgstatsp(q, mp); break; case _IOC_NR(SDL_IOCSSTATSP): /* lmi_sta_t */ ret = sdl_iocsstatsp(q, mp); break; case _IOC_NR(SDL_IOCGSTATS): /* sdl_stats_t */ ret = sdl_iocgstats(q, mp); break; case _IOC_NR(SDL_IOCCSTATS): /* sdl_stats_t */ ret = sdl_ioccstats(q, mp); break; case _IOC_NR(SDL_IOCGNOTIFY): /* sdl_notify_t */ ret = sdl_iocgnotify(q, mp); break; case _IOC_NR(SDL_IOCSNOTIFY): /* sdl_notify_t */ ret = sdl_iocsnotify(q, mp); break; case _IOC_NR(SDL_IOCCNOTIFY): /* sdl_notify_t */ ret = sdl_ioccnotify(q, mp); break; case _IOC_NR(SDL_IOCCDISCTX): /* */ ret = sdl_ioccdisctx(q, mp); break; case _IOC_NR(SDL_IOCCCONNTX): /* */ ret = sdl_ioccconntx(q, mp); break; default: ptrace(("%s: ERROR: Unsupported SDL ioctl %d\n", MOD_NAME, nr)); ret = -EOPNOTSUPP; break; } break; } default: ret = (QR_PASSFLOW); break; } if (ret > 0) { return (ret); } else if (ret == 0) { mp->b_datap->db_type = M_IOCACK; iocp->ioc_error = 0; iocp->ioc_rval = 0; } else { mp->b_datap->db_type = M_IOCNAK; iocp->ioc_error = -ret; iocp->ioc_rval = -1; } qreply(q, mp); return (QR_ABSORBED);}/* * ----------------------------------------------------------------------- * * M_PROTO, M_PCPROTO Handling * * ----------------------------------------------------------------------- *//* * Primitives from User to SDL. * ----------------------------------- */STATIC intsdl_w_proto(queue_t *q, mblk_t *mp){ int rtn; ulong prim; struct sdl *s = SDL_PRIV(q); ulong oldstate = s->i_state; if ((prim = *(ulong *) mp->b_rptr) == SDL_BITS_FOR_TRANSMISSION_REQ) { printd(("%s: %p: -> SDL_BITS_FOR_TRANSMISSION_REQ [%d]\n", MOD_NAME, s, msgdsize(mp->b_cont))); if ((rtn = sdl_bits_for_transmission_req(q, mp)) < 0) s->i_state = oldstate; return (rtn); } switch (prim) { case SDL_BITS_FOR_TRANSMISSION_REQ: printd(("%s: %p: -> SDL_BITS_FOR_TRANSMISSION_REQ [%d]\n", MOD_NAME, s, msgdsize(mp->b_cont))); rtn = sdl_bits_for_transmission_req(q, mp); break; case SDL_CONNECT_REQ: printd(("%s: %p: -> SDL_CONNECT_REQ\n", MOD_NAME, s)); rtn = sdl_connect_req(q, mp); break; case SDL_DISCONNECT_REQ: printd(("%s: %p: -> SDL_DISCONNECT_REQ\n", MOD_NAME, s)); rtn = sdl_disconnect_req(q, mp); break; case LMI_INFO_REQ: printd(("%s: %p: -> LMI_INFO_REQ\n", MOD_NAME, s)); rtn = lmi_info_req(q, mp); break; case LMI_ATTACH_REQ: printd(("%s: %p: -> LMI_ATTACH_REQ\n", MOD_NAME, s)); rtn = lmi_attach_req(q, mp); break; case LMI_DETACH_REQ: printd(("%s: %p: -> LMI_DETACH_REQ\n", MOD_NAME, s)); rtn = lmi_detach_req(q, mp); break; case LMI_ENABLE_REQ: printd(("%s: %p: -> LMI_ENABLE_REQ\n", MOD_NAME, s)); rtn = lmi_enable_req(q, mp); break; case LMI_DISABLE_REQ: printd(("%s: %p: -> LMI_DISABLE_REQ\n", MOD_NAME, s)); rtn = lmi_disable_req(q, mp); break; case LMI_OPTMGMT_REQ: printd(("%s: %p: -> LMI_OPTMGMT_REQ\n", MOD_NAME, s)); rtn = lmi_optmgmt_req(q, mp); break; default: /* discard anything we don't recognize */ swerr(); rtn = (-EOPNOTSUPP); break; } if (rtn < 0) s->i_state = oldstate; return (rtn);}/* * ------------------------------------------------------------------------- * * M_DATA Handling * * ------------------------------------------------------------------------- */STATIC INLINE intsdl_w_data(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_PRIV(q); (void) s; printd(("%s: %p: -> M_DATA [%d]\n", MOD_NAME, s, msgdsize(mp))); return sdl_send_data(q, mp);}STATIC INLINE intsdl_r_data(queue_t *q, mblk_t *mp){ struct sdl *s = SDL_PRIV(q); (void) s; printd(("%s: %p: M_DATA [%d] <-\n", MOD_NAME, s, msgdsize(mp))); return sdl_recv_data(q, mp);}/* * ========================================================================= * * PUT and SRV * * ========================================================================= */STATIC INLINE streamscall intsdl_w_prim(queue_t *q, mblk_t *mp){ /* Fast Path */ if (mp->b_datap->db_type == M_DATA) return sdl_w_data(q, mp); switch (mp->b_datap->db_type) { case M_DATA: return sdl_w_data(q, mp); case M_PROTO: case M_PCPROTO: return sdl_w_proto(q, mp); case M_FLUSH: return ss7_w_flush(q, mp); case M_IOCTL: return sdl_w_ioctl(q, mp); } return (QR_PASSALONG);}STATIC INLINE streamscall intsdl_r_prim(queue_t *q, mblk_t *mp){ /* Fast Path */ if (mp->b_datap->db_type == M_DATA) return sdl_r_data(q, mp); switch (mp->b_datap->db_type) { case M_DATA: return sdl_r_data(q, mp); case M_FLUSH: return ss7_r_flush(q, mp); } return (QR_PASSALONG);}/* * ======================================================================= * * OPEN and CLOSE * * ======================================================================= */STATIC streamscall intsdl_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp){ MOD_INC_USE_COUNT; /* keep module from unloading in our face */ if (q->q_ptr != NULL) { MOD_DEC_USE_COUNT; return (0); /* already open */ } if (sflag == MODOPEN || WR(q)->q_next != NULL) { int cmajor = getmajor(*devp); int cminor = getminor(*devp); struct sdl *s; /* test for multiple push */ for (s = sdl_opens; s; s = s->next) { if (s->u.dev.cmajor == cmajor && s->u.dev.cminor == cminor) { MOD_DEC_USE_COUNT; return (ENXIO); } } if (!(sdl_alloc_priv(q, &sdl_opens, devp, crp))) { MOD_DEC_USE_COUNT; return (ENOMEM); } return (0); } MOD_DEC_USE_COUNT; return (EIO);}STATIC streamscall intsdl_close(queue_t *q, int flag, cred_t *crp){ (void) flag; (void) crp; sdl_free_priv(q); MOD_DEC_USE_COUNT; return (0);}/* * ======================================================================== * * PRIVATE struct allocation, deallocation and cache * * ======================================================================== */STATIC kmem_cache_t *sdl_priv_cachep = NULL;STATIC intsdl_init_caches(void){ if (!sdl_priv_cachep && !(sdl_priv_cachep = kmem_cache_create("sdl_priv_cachep", sizeof(struct sdl), 0, SLAB_HWCACHE_ALIGN, NULL, NULL))) { cmn_err(CE_PANIC, "%s: Cannot allocate sdl_priv_cachep", __FUNCTION__); return (-ENOMEM); } printd(("%s: Allocated/selected private structure cache\n", MOD_NAME)); return (0);}STATIC intsdl_term_caches(void){ if (sdl_priv_cachep) { if (kmem_cache_destroy(sdl_priv_cachep)) { cmn_err(CE_WARN, "%s: id not destroy sdl_priv_cachep.", __FUNCTION__); return (-EBUSY); } else printd(("%s: destroyed sdl_priv_cachep\n", MOD_NAME)); } return (0);}STATIC struct sdl *sdl_alloc_priv(queue_t *q, struct sdl **sp, dev_t *devp, cred_t *crp){ struct sdl *s; if ((s = kmem_cache_alloc(sdl_priv_cachep, SLAB_ATOMIC))) { printd(("%s: %p: allocated module private structure\n", MOD_NAME, s)); bzero(s, sizeof(*s)); sdl_get(s); /* first get */ s->u.dev.cmajor = getmajor(*devp); s->u.dev.cminor = getminor(*devp); s->cred = *crp; (s->oq = RD(q))->q_ptr = sdl_get(s); (s->iq = WR(q))->q_ptr = sdl_get(s); spin_lock_init(&s->qlock); /* "sdl-queue-lock" */ s->o_prim = &sdl_r_prim; s->i_prim = &sdl_w_prim; s->o_wakeup = NULL; // &sdl_rx_wakeup; s->i_wakeup = NULL; // &sdl_tx_wakeup; s->i_state = LMI_DISABLED; s->i_style = LMI_STYLE1; s->i_version = 1; spin_lock_init(&s->qlock); /* "sdl-priv_lock" */ if ((s->next = *sp)) s->next->prev = &s->next; s->prev = sp; *sp = sdl_get(s); printd(("%s: %p: linked module private structure\n", MOD_NAME, s)); s->timestamp = jiffies; s->tickbytes = s->config.ifrate / HZ / 8; s->bytecount = 0; /* configuration defaults */ s->option = lmi_default; s->config = sdl_default; printd(("%s: %p: setting module private structure defaults\n", MOD_NAME, s)); } else ptrace(("%s: ERROR: Could not allocate module private structure\n", MOD_NAME)); return (s);}STATIC voidsdl_free_priv(queue_t *q){ struct sdl *s = SDL_PRIV(q); psw_t flags; ensure(s, return); spin_lock_irqsave(&s->lock, flags); { ss7_unbufcall((str_t *) s); sdl_timer_stop(s, tall); if ((*(s->prev) = s->next)) s->next->prev = s->prev; s->next = NULL; s->prev = &s->next; sdl_put(s); s->oq->q_ptr = NULL; flushq(s->oq, FLUSHALL); s->oq = NULL; sdl_put(s); s->iq->q_ptr = NULL; flushq(s->iq, FLUSHALL); s->iq = NULL; sdl_put(s); } spin_unlock_irqrestore(&s->lock, flags); sdl_put(s); /* final put */}STATIC struct sdl *sdl_get(struct sdl *s){ atomic_inc(&s->refcnt); return (s);}STATIC voidsdl_put(struct sdl *s){ if (atomic_dec_and_test(&s->refcnt)) { kmem_cache_free(sdl_priv_cachep, s); printd(("%s: %p: freed sdl private structure\n", MOD_NAME, s)); }}/* * ========================================================================= * * Registration and initialization * * ========================================================================= */#ifdef LINUX/* * Linux Registration * ------------------------------------------------------------------------- */unsigned short modid = MOD_ID;#ifndef module_paramMODULE_PARM(modid, "h");#elsemodule_param(modid, ushort, 0);#endifMODULE_PARM_DESC(modid, "Module ID for the SDL module. (0 for allocation.)");/* * Linux Fast-STREAMS Registration * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */#ifdef LFSSTATIC struct fmodsw sdl_fmod = { .f_name = MOD_NAME, .f_str = &sdlinfo, .f_flag = 0, .f_kmod = THIS_MODULE,};STATIC intsdl_register_strmod(void){ int err; if ((err = register_strmod(&sdl_fmod)) < 0) return (err); return (0);}STATIC intsdl_unregister_strmod(void){ int err; if ((err = unregister_strmod(&sdl_fmod)) < 0) return (err); return (0);}#endif /* LFS *//* * Linux STREAMS Registration * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */#ifdef LISSTATIC intsdl_register_strmod(void){ int err; if ((err = lis_register_strmod(&sdlinfo, MOD_NAME)) == LIS_NULL_MID) return (-EIO); return (0);}STATIC intsdl_unregister_strmod(void){ int err; if ((err = lis_unregister_strmod(&sdlinfo)) < 0) return (err); return (0);}#endif /* LIS */MODULE_STATIC int __initsdlinit(void){ int err; cmn_err(CE_NOTE, MOD_BANNER); /* banner message */ if ((err = sdl_init_caches())) { cmn_err(CE_WARN, "%s: could not init caches, err = %d", MOD_NAME, err); return (err); } if ((err = sdl_register_strmod())) { cmn_err(CE_WARN, "%s: could not register module, err = %d", MOD_NAME, err); sdl_term_caches(); return (err); } if (modid == 0) modid = err; return (0);}MODULE_STATIC void __exitsdlterminate(void){ int err; if ((err = sdl_unregister_strmod())) cmn_err(CE_WARN, "%s: could not unregister module", MOD_NAME); if ((err = sdl_term_caches())) cmn_err(CE_WARN, "%s: could not terminate caches", MOD_NAME); return;}/* * Linux Kernel Module Initialization * ------------------------------------------------------------------------- */module_init(sdlinit);module_exit(sdlterminate);#endif /* LINUX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -