📄 spm.c
字号:
} case SDL_IOC_MAGIC: { if (count < size || PRIV(q)->state == LMI_UNATTACHED) { ret = -EINVAL; break; } switch (cmd) { case SDL_IOCGOPTIONS: /* lmi_option_t */ ret = sdl_iocgoptions(q, mp); break; case SDL_IOCSOPTIONS: /* lmi_option_t */ ret = sdl_iocsoptions(q, mp); break; case SDL_IOCGCONFIG: /* sdt_config_t */ ret = sdl_iocgconfig(q, mp); break; case SDL_IOCSCONFIG: /* sdt_config_t */ ret = sdl_iocsconfig(q, mp); break; case SDL_IOCTCONFIG: /* sdt_config_t */ ret = sdl_ioctconfig(q, mp); break; case SDL_IOCCCONFIG: /* sdt_config_t */ ret = sdl_ioccconfig(q, mp); break; case SDL_IOCGSTATEM: /* sdt_statem_t */ ret = sdl_iocgstatem(q, mp); break; case SDL_IOCCMRESET: /* sdt_statem_t */ ret = sdl_ioccmreset(q, mp); break; case SDL_IOCGSTATSP: /* lmi_sta_t */ ret = sdl_iocgstatsp(q, mp); break; case SDL_IOCSSTATSP: /* lmi_sta_t */ ret = sdl_iocsstatsp(q, mp); break; case SDL_IOCGSTATS: /* sdt_stats_t */ ret = sdl_iocgstats(q, mp); break; case SDL_IOCCSTATS: /* sdt_stats_t */ ret = sdl_ioccstats(q, mp); break; case SDL_IOCGNOTIFY: /* sdt_notify_t */ ret = sdl_iocgnotify(q, mp); break; case SDL_IOCSNOTIFY: /* sdt_notify_t */ ret = sdl_iocsnotify(q, mp); break; case SDL_IOCCNOTIFY: /* sdt_notify_t */ ret = sdl_ioccnotify(q, mp); break; default: ret = -EOPNOTSUPP; break; } ret = -EFAULT; break; } default: return (QR_PASSALONG); } 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 * ----------------------------------------------------------------------- */STATIC intspm_m_proto(queue_t *q, mblk_t *mp){ int rtn; ulong prim; spm_t *s = PRIV(q); ulong oldstate = s->state; if ((prim = *(ulong *) mp->b_rptr) == SDL_BITS_FOR_TRANSMISSION_REQ) rtn = sdl_bits_for_transmission_req(q, mp); else switch (prim) { case SDL_BITS_FOR_TRANSMISSION_REQ: rtn = sdl_bits_for_transmission_req(q, mp); break; case SDL_CONNECT_REQ: rtn = sdl_connect_req(q, mp); break; case SDL_DISCONNECT_REQ: rtn = sdl_disconnect_req(q, mp); break; case LMI_INFO_REQ: rtn = lmi_info_req(q, mp); break; case LMI_ATTACH_REQ: rtn = lmi_attach_req(q, mp); break; case LMI_DETACH_REQ: rtn = lmi_detach_req(q, mp); break; case LMI_ENABLE_REQ: rtn = lmi_enable_req(q, mp); break; case LMI_DISABLE_REQ: rtn = lmi_disable_req(q, mp); break; case LMI_OPTMGMT_REQ: rtn = lmi_optmgmt_req(q, mp); break; default: /* pass along anything we don't recognize */ rtn = QR_PASSFLOW; break; } if (rtn < 0) s->state = oldstate; return (rtn);}/* * M_DATA Handling * ------------------------------------------------------------------------- * We need to throttle these to avoid locking up the processor. The throttle * is for 10 blocks every 10ms maximum which is precisely 64kbps. */STATIC void streamscallspm_w_timeout(caddr_t data){ queue_t *q = (queue_t *) data; spm_t *s = PRIV(q); if (!xchg(&s->wtim, 0)) return; enableok(q); qenable(q); return;}STATIC void streamscallspm_r_timeout(caddr_t data){ queue_t *q = (queue_t *) data; spm_t *s = PRIV(q); if (!xchg(&s->rtim, 0)) return; enableok(q); qenable(q); return;}STATIC INLINE intspm_w_data(queue_t *q, mblk_t *mp){ spm_t *s = PRIV(q); if (s->wts == jiffies) { if (s->wno++ >= 10) { /* come back in a tick */ s->wtim = timeout(&spm_w_timeout, (caddr_t) q, 1); // printd(("spm: tx: blocking\n")); return (QR_DISABLE); } } else { s->wno = 1; s->wts = jiffies; } return (QR_PASSFLOW);}STATIC INLINE intspm_r_data(queue_t *q, mblk_t *mp){ spm_t *s = PRIV(q); if (s->rts == jiffies) { if (s->rno++ >= 10) { /* come back in a tick */ s->rtim = timeout(&spm_r_timeout, (caddr_t) q, 1); // printd(("spm: rx: blocking\n")); return (QR_DISABLE); } } else { s->rno = 1; s->rts = jiffies; } return (QR_PASSFLOW);}/* * M_RSE, M_PCRSE Handling * ------------------------------------------------------------------------- */STATIC intspm_m_pcrse(queue_t *q, mblk_t *mp){ int rtn; switch (*(ulong *) mp->b_rptr) { default: rtn = -EFAULT; break; } return (rtn);}/* * M_FLUSH Handling * ------------------------------------------------------------------------- */STATIC INLINE intspm_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_LOOP);}STATIC intspm_w_flush(queue_t *q, mblk_t *mp){ return spm_m_flush(q, mp, FLUSHW);}STATIC intspm_r_flush(queue_t *q, mblk_t *mp){ return spm_m_flush(q, mp, FLUSHR);}/* * ========================================================================= * * PUT and SRV * * ========================================================================= */STATIC INLINE streamscall intspm_r_prim(queue_t *q, mblk_t *mp){ /* Fast Path */ if (mp->b_datap->db_type == M_DATA) return spm_r_data(q, mp); switch (mp->b_datap->db_type) { case M_DATA: return spm_r_data(q, mp); case M_PROTO: case M_PCPROTO: return spm_m_proto(q, mp); case M_RSE: case M_PCRSE: return spm_m_pcrse(q, mp); case M_FLUSH: return spm_r_flush(q, mp); case M_IOCTL: return spm_m_ioctl(q, mp); } return (QR_PASSFLOW);}STATIC INLINE streamscall intspm_w_prim(queue_t *q, mblk_t *mp){ /* Fast Path */ if (mp->b_datap->db_type == M_DATA) return spm_w_data(q, mp); switch (mp->b_datap->db_type) { case M_DATA: return spm_w_data(q, mp); case M_PROTO: case M_PCPROTO: return spm_m_proto(q, mp); case M_RSE: case M_PCRSE: return spm_m_pcrse(q, mp); case M_FLUSH: return spm_w_flush(q, mp); case M_IOCTL: return spm_m_ioctl(q, mp); } return (QR_PASSFLOW);}STATIC streamscall voidspm_rx_wakeup(queue_t *q){}STATIC streamscall intspm_rput(queue_t *q, mblk_t *mp){ return (int) ss7_putq(q, mp, &spm_r_prim, &spm_rx_wakeup);}STATIC streamscall intspm_rsrv(queue_t *q){ return (int) ss7_srvq(q, &spm_r_prim, &spm_rx_wakeup);}STATIC streamscall voidspm_tx_wakeup(queue_t *q){}STATIC streamscall intspm_wput(queue_t *q, mblk_t *mp){ return (int) ss7_putq(q, mp, &spm_w_prim, &spm_tx_wakeup);}STATIC streamscall intspm_wsrv(queue_t *q){ return (int) ss7_srvq(q, &spm_w_prim, &spm_tx_wakeup);}/* * ======================================================================= * * OPEN and CLOSE * * ======================================================================= */STATIC spm_t *spm_list = NULL;STATIC streamscall intspm_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp){ int cmajor = getmajor(*devp); int cminor = getminor(*devp); spm_t *s, **sp = &spm_list; (void) 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 == DRVOPEN || WR(q)->q_next == NULL) { ptrace(("spm: ERROR: Can't open as driver\n")); MOD_DEC_USE_COUNT; return (EIO); } for (; *sp && (*sp)->cmajor < cmajor; sp = &(*sp)->next) ; for (; *sp && (*sp)->cmajor == cmajor && (*sp)->cminor < cminor; sp = &(*sp)->next) ; if (*sp && (*sp)->cmajor == cmajor && (*sp)->cminor == cminor) { ptrace(("spm: ERROR: Multiple push\n")); MOD_DEC_USE_COUNT; return (ENXIO); } printd(("spm: Pushed module for char device %d:%d\n", cmajor, cminor)); if (!(s = spm_alloc_priv(q, sp, cmajor, cminor))) { ptrace(("spm: ERROR: No cache memory\n")); MOD_DEC_USE_COUNT; return (ENOMEM); } return (0);}STATIC streamscall intspm_close(queue_t *q, int flag, cred_t *crp){ spm_t *s = PRIV(q); (void) flag; (void) crp; (void) s; printd(("spm: Popped module for char device %hu:%hu\n", (ushort) s->cmajor, (ushort) s->cminor)); spm_free_priv(q); MOD_DEC_USE_COUNT; return (0);}/* * ========================================================================= * * 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 SPM module. (0 for allocation.)");/* * Linux Fast-STREAMS Registration * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */#ifdef LFSSTATIC struct fmodsw spm_fmod = { .f_name = MOD_NAME, .f_str = &spminfo, .f_flag = 0, .f_kmod = THIS_MODULE,};STATIC intspm_register_strmod(void){ int err; if ((err = register_strmod(&spm_fmod)) < 0) return (err); return (0);}STATIC intspm_unregister_strmod(void){ int err; if ((err = unregister_strmod(&spm_fmod)) < 0) return (err); return (0);}#endif /* LFS *//* * Linux STREAMS Registration * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */#ifdef LISSTATIC intspm_register_strmod(void){ int err; if ((err = lis_register_strmod(&spminfo, MOD_NAME)) == LIS_NULL_MID) return (-EIO); return (0);}STATIC intspm_unregister_strmod(void){ int err; if ((err = lis_unregister_strmod(&spminfo)) < 0) return (err); return (0);}#endif /* LIS */MODULE_STATIC int __initspminit(void){ int err; cmn_err(CE_NOTE, MOD_BANNER); /* banner message */ if ((err = spm_init_caches())) { cmn_err(CE_WARN, "%s: could not init caches, err = %d", MOD_NAME, err); return (err); } if ((err = spm_register_strmod())) { cmn_err(CE_WARN, "%s: could not register module, err = %d", MOD_NAME, err); spm_term_caches(); return (err); } if (modid == 0) modid = err; return (0);}MODULE_STATIC void __exitspmterminate(void){ int err; if ((err = spm_unregister_strmod())) cmn_err(CE_WARN, "%s: could not unregister module", MOD_NAME); if ((err = spm_term_caches())) cmn_err(CE_WARN, "%s: could not terminate caches", MOD_NAME); return;}/* * Linux Kernel Module Initialization * ------------------------------------------------------------------------- */module_init(spminit);module_exit(spmterminate);#endif /* LINUX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -