📄 sl_mux.c
字号:
*x++ = (tlen << 4) & 0xf0; for (i = 0; i < tlen; i++) *x++ = tbyte; mp->b_wptr = x; __printd(("mtp: Sent SLTM\n")); qreply(q, mp); } ls->sltm_timer = timeout(&failed_sltm, (caddr_t) q, 4 * HZ); /* T1T */}STATIC inthandle_message(queue_t *q, mblk_t *mp){ struct ls *ls = (struct ls *) q->q_ptr; unsigned char *x = mp->b_rptr; uint sio, dpc, opc, sls, h0, h1, b; int i; __printd(("mtp: M_DATA: ")); for (i = 0; i < mp->b_wptr - mp->b_rptr; i++) __printd(("%02x ", x[i] & 0x0ff)); __printd(("\n")); sio = *x++; if ((sio & 0xf) == 1 || (sio & 0xf) == 2) { ptrace(("Got Test Message\n")); b = *x++ & 0x00ff; dpc = ((b << 0) & 0xff); b = *x++ & 0x00ff; dpc |= ((b << 8) & 0x3f00); opc = ((b >> 6) & 0x03); b = *x++ & 0x00ff; opc |= ((b << 2) & 0x3fc); b = *x++ & 0x00ff; opc |= ((b << 10) & 0x3c00); sls = (b >> 4) & 0x0f; b = *x++ & 0x00ff; h0 = b & 0x0f; h1 = b >> 4; if (h0 == 1 && h1 == 1) { mblk_t *dp; __printd(("mtp: Got SLTM\n")); if ((dp = copymsg(mp))) { x = dp->b_rptr; h1 = 2; x++; *x++ = opc; *x++ = ((opc >> 8) & 0x3f) | (dpc << 6); *x++ = (dpc >> 2); *x++ = ((dpc >> 10) & 0x0f) | (sls << 4); *x++ = h0 | (h1 << 4); /* send back */ __printd(("mtp: Sent SLTA\n")); qreply(q, dp); freemsg(mp); return (1); } } else if (h0 == 1 && h1 == 2) { __printd(("mtp: Got SLTA\n")); if (ls->sltm_timer) untimeout(ls->sltm_timer); ls->sltm_failures = 0; ls->sltm_timer = timeout(&send_sltm, (caddr_t) q, 2 * 60 * HZ); /* T2T */ } } return (0);}/* * ========================================================================= * * STREAMS Message Handling * * ========================================================================= *//* * ------------------------------------------------------------------------- * * M_DATA Handling * * ------------------------------------------------------------------------- */STATIC intsl_r_data(queue_t *q, mblk_t *mp){ if (handle_message(q, mp)) return (QR_ABSORBED); return (QR_PASSFLOW);}/* * ------------------------------------------------------------------------- * * M_PROTO, M_PCPROTO Handling * * ------------------------------------------------------------------------- */STATIC intsl_r_proto(queue_t *q, mblk_t *mp){ struct ls *ls = (struct ls *) q->q_ptr; ptrace(("Got M_PROTO = %ld\n", *(long *) mp->b_rptr)); switch (*(long *) mp->b_rptr) { case SL_OUT_OF_SERVICE_IND: __printd(("mtp: Got SL_OUT_OF_SERVICE_IND\n")); if (ls->sltm_timer) untimeout(xchg(&ls->sltm_timer, 0)); if (ls->recovery_timer) untimeout(xchg(&ls->recovery_timer, 0)); if (!ls->recovery_attempts) restart_link((caddr_t) q); else ls->recovery_timer = timeout(&restart_link, (caddr_t) q, 1 * HZ); /* T17 */ return (QR_DONE); case SL_PDU_IND: __printd(("mtp: Got SL_PDU_IND\n")); if (handle_message(q, mp->b_cont)) return (QR_TRIMMED); break; case SL_IN_SERVICE_IND: __printd(("mtp: Got SL_IN_SERVICE_IND\n")); ls->recovery_attempts = 0; send_sltm((caddr_t) q); return (QR_DONE); } return (QR_PASSFLOW);}/* * ------------------------------------------------------------------------- * * M_IOCTL Handling * * ------------------------------------------------------------------------- */STATIC intsl_w_ioctl(queue_t *q, mblk_t *mp){ struct sl *sl = SL_PRIV(q); struct iocblk *iocp = (struct iocblk *) mp->b_rptr; void *arg = mp->b_cont ? mp->b_cont->b_rptr : NULL; int cmd = iocp->ioc_cmd, count = iocp->ioc_count; int type = _IOC_TYPE(cmd), nr = _IOC_NR(cmd), size = _IOC_SIZE(cmd); int ret = 0; (void) sl; (void) size; (void) count; switch (type) { case _IOC_TYPE(__SID): { psw_t flags; struct ls *ls, **lpp; struct linkblk *lb = (struct linkblk *) arg; if (lb == NULL) { swerr(); ret = -EINVAL; break; } switch (nr) { case _IOC_NR(I_PLINK): ptrace(("%s: %p: I_PLINK\n", DRV_NAME, sl)); if (iocp->ioc_cr->cr_uid != 0) { ptrace(("%s: %p: ERROR: Non-root attempt to I_PLINK\n", DRV_NAME, sl)); ret = -EPERM; break; } case _IOC_NR(I_LINK): ptrace(("%s: %p: I_LINK\n", DRV_NAME, sl)); MOD_INC_USE_COUNT; /* keep module from unloading */ spin_lock_irqsave(&master.lock, flags); { /* place in list in ascending index order */ for (lpp = &master.ls.list; *lpp && (*lpp)->u.mux.index < lb->l_index; lpp = &(*lpp)->next) ; if ((ls = slm_alloc_ls(lb->l_qbot, lpp, lb->l_index, iocp->ioc_cr))) { spin_unlock_irqrestore(&master.lock, flags); break; } MOD_DEC_USE_COUNT; ret = -ENOMEM; } spin_unlock_irqrestore(&master.lock, flags); break; case _IOC_NR(I_PUNLINK): ptrace(("%s: %p: I_PUNLINK\n", DRV_NAME, sl)); if (iocp->ioc_cr->cr_uid != 0) { ptrace(("%s: %p: ERROR: Non-root attempt to I_PUNLINK\n", DRV_NAME, sl)); ret = -EPERM; break; } case _IOC_NR(I_UNLINK): ptrace(("%s: %p: I_UNLINK\n", DRV_NAME, sl)); spin_lock_irqsave(&master.lock, flags); { for (ls = master.ls.list; ls; ls = ls->next) if (ls->u.mux.index == lb->l_index) break; if (ls == NULL) { ret = -EINVAL; ptrace(("%s: %p: ERROR: Couldn't find I_UNLINK muxid %u\n", DRV_NAME, sl, lb->l_index)); spin_unlock_irqrestore(&master.lock, flags); break; } slm_free_ls(ls->iq); MOD_DEC_USE_COUNT; } spin_unlock_irqrestore(&master.lock, flags); break; default: case _IOC_NR(I_STR): ptrace(("%s: %p: ERROR: Unsupported STREAMS ioctl %c, %d\n", DRV_NAME, sl, (char) type, nr)); ret = -EOPNOTSUPP; break; } break; } default: ptrace(("%s: %p: ERROR: Unsupported ioctl %c, %d\n", DRV_NAME, sl, (char) type, nr)); ret = -EOPNOTSUPP; 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);}/* * ------------------------------------------------------------------------- * * Message Handling * * ------------------------------------------------------------------------- *//* * UPPER MUX Queues * ----------------------------------- */STATIC streamscall intsl_r_prim(queue_t *q, mblk_t *mp){ switch (mp->b_datap->db_type) { case M_FLUSH: return ss7_r_flush(q, mp); default: return (QR_PASSFLOW); }}STATIC streamscall intsl_w_prim(queue_t *q, mblk_t *mp){ switch (mp->b_datap->db_type) { case M_IOCTL: return sl_w_ioctl(q, mp); case M_FLUSH: return ss7_w_flush(q, mp); default: return (QR_PASSFLOW); }}/* * LOWER MUX Queues * ----------------------------------- */STATIC streamscall intls_r_prim(queue_t *q, mblk_t *mp){ switch (mp->b_datap->db_type) { case M_DATA: return sl_r_data(q, mp); case M_PROTO: case M_PCPROTO: return sl_r_proto(q, mp); case M_FLUSH: return ss7_r_flush(q, mp); default: return (QR_PASSFLOW); }}STATIC streamscall intls_w_prim(queue_t *q, mblk_t *mp){ switch (mp->b_datap->db_type) { case M_FLUSH: return ss7_w_flush(q, mp); default: return (QR_PASSFLOW); }}/* * ========================================================================= * * OPEN and CLOSE * * ========================================================================= */STATIC major_t slm_majors[CMAJORS] = { CMAJOR_0, };/* * OPEN * ------------------------------------------------------------------------- */STATIC streamscall intsl_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp){ psw_t flags; int mindex = 0; major_t cmajor = getmajor(*devp); minor_t cminor = getminor(*devp); struct sl *sl, **spp; MOD_INC_USE_COUNT; if (q->q_ptr != NULL) { MOD_DEC_USE_COUNT; return (0); /* already open */ } if (sflag == MODOPEN || WR(q)->q_next) { ptrace(("%s: ERROR: cannot push as module\n", DRV_NAME)); MOD_DEC_USE_COUNT; return (EIO); } if (cmajor != CMAJOR_0 || cminor > 0) { MOD_DEC_USE_COUNT; return (ENXIO); } /* allocate a new device */ cminor = 1; spin_lock_irqsave(&master.lock, flags); for (spp = &master.sl.list; *spp; spp = &(*spp)->next) { major_t dmajor = (*spp)->u.dev.cmajor; if (cmajor != dmajor) break; if (cmajor == dmajor) { minor_t dminor = (*spp)->u.dev.cminor; if (cminor < dminor) break; if (cminor > dminor) continue; if (cminor == dminor) { if (++cminor >= NMINORS) { if (++mindex >= CMAJORS || !(cmajor = slm_majors[mindex])) break; cminor = 0; } continue; } } } if (mindex >= CMAJORS || !cmajor) { ptrace(("%s: ERROR: no device numbers available\n", DRV_NAME)); spin_unlock_irqrestore(&master.lock, flags); MOD_DEC_USE_COUNT; return (ENXIO); } printd(("%s: opened character device %hu:%hu\n", DRV_NAME, cmajor, cminor)); *devp = makedevice(cmajor, cminor); if (!(sl = slm_alloc_sl(q, spp, cmajor, cminor, crp))) { ptrace(("%s: ERROR: no memory\n", DRV_NAME)); spin_unlock_irqrestore(&master.lock, flags); MOD_DEC_USE_COUNT; return (ENOMEM); } spin_unlock_irqrestore(&master.lock, flags); return (0);}/* * CLOSE * ------------------------------------------------------------------------- */STATIC streamscall intsl_close(queue_t *q, int sflag, cred_t *crp){ struct sl *sl = SL_PRIV(q); psw_t flags; (void) sl; printd(("%s: %p: closing character device %hu:%hu\n", DRV_NAME, sl, sl->u.dev.cmajor, sl->u.dev.cminor)); spin_lock_irqsave(&master.lock, flags); { slm_free_sl(q); } spin_unlock_irqrestore(&master.lock, flags); MOD_DEC_USE_COUNT; return (0);}/* * ========================================================================= * * Registration and initialization * * ========================================================================= */#ifdef LINUX/* * Linux Registration * ------------------------------------------------------------------------- */unsigned short modid = DRV_ID;#ifndef module_paramMODULE_PARM(modid, "h");#elsemodule_param(modid, ushort, 0);#endifMODULE_PARM_DESC(modid, "Module ID for the SDL-MUX driver. (0 for allocation.)");major_t major = CMAJOR_0;#ifndef module_paramMODULE_PARM(major, "h");#elsemodule_param(major, uint, 0);#endifMODULE_PARM_DESC(major, "Device number for the SDL-MUX driver. (0 for allocation.)");/* * Linux Fast-STREAMS Registration * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */#ifdef LFSSTATIC struct cdevsw slm_cdev = { .d_name = DRV_NAME, .d_str = &sl_muxinfo, .d_flag = 0, .d_fop = NULL, .d_mode = S_IFCHR, .d_kmod = THIS_MODULE,};STATIC intslm_register_strdev(major_t major){ int err; if ((err = register_strdev(&slm_cdev, major)) < 0) return (err); return (0);}STATIC intslm_unregister_strdev(major_t major){ int err; if ((err = unregister_strdev(&slm_cdev, major)) < 0) return (err); return (0);}#endif /* LFS *//* * Linux STREAMS Registration * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */#ifdef LISSTATIC intslm_register_strdev(major_t major){ int err; if ((err = lis_register_strdev(major, &sl_muxinfo, UNITS, DRV_NAME)) < 0) return (err); return (0);}STATIC intslm_unregister_strdev(major_t major){ int err; if ((err = lis_unregister_strdev(major)) < 0) return (err); return (0);}#endif /* LIS */MODULE_STATIC void __exitsl_muxterminate(void){ int err, mindex; for (mindex = CMAJORS - 1; mindex >= 0; mindex--) { if (slm_majors[mindex]) { if ((err = slm_unregister_strdev(slm_majors[mindex]))) cmn_err(CE_PANIC, "%s: cannot unregister major %d", DRV_NAME, slm_majors[mindex]); if (mindex) slm_majors[mindex] = 0; } } if ((err = slm_term_caches())) cmn_err(CE_WARN, "%s: could not terminate caches", DRV_NAME); return;}MODULE_STATIC int __initsl_muxinit(void){ int err, mindex = 0; cmn_err(CE_NOTE, DRV_BANNER); /* console splash */ if ((err = slm_init_caches())) { cmn_err(CE_WARN, "%s: could not init caches, err = %d", DRV_NAME, err); sl_muxterminate(); return (err); } for (mindex = 0; mindex < CMAJORS; mindex++) { if ((err = slm_register_strdev(slm_majors[mindex])) < 0) { if (mindex) { cmn_err(CE_WARN, "%s: could not register major %d", DRV_NAME, slm_majors[mindex]); continue; } else { cmn_err(CE_WARN, "%s: could not register driver, err = %d", DRV_NAME, err); sl_muxterminate(); return (err); } } if (slm_majors[mindex] == 0) slm_majors[mindex] = err;#if 0 LIS_DEVFLAGS(slm_majors[mindex]) |= LIS_MODFLG_CLONE;#endif if (major == 0) major = slm_majors[0]; } return (0);}/* * Linux Kernel Module Initialization * ------------------------------------------------------------------------- */module_init(sl_muxinit);module_exit(sl_muxterminate);#endif /* LINUX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -