📄 loop.c
字号:
loop = (struct loop *) q->q_ptr; switch (mp->b_datap->db_type) { case M_IOCTL: { struct iocblk *iocb; int error; iocb = (struct iocblk *) mp->b_rptr; switch (iocb->ioc_cmd) { case LOOP_SET: { int to; if (iocb->ioc_count != sizeof(int)) { printk("Expected ioctl len %d, got %d\n", sizeof(int), iocb->ioc_count); error = EINVAL; goto iocnak; } to = *(int *) mp->b_cont->b_rptr; if (to >= loop_cnt || to < 0 || !loop_loop[to].qptr) { error = ENXIO; goto iocnak; } if (loop->oqptr || loop_loop[to].oqptr) { error = EBUSY; goto iocnak; } loop->oqptr = RD(loop_loop[to].qptr); loop_loop[to].oqptr = RD(q); break; } case LOOP_PUTNXT: loop->use_putnext = 1; /* instead of service queue */ break; case LOOP_MSGLVL: if (mp->b_cont != NULL) loop->msglvl = *(int *) mp->b_cont->b_rptr; else { printk("loop_wput: no data buffer in ioctl\n"); error = EINVAL; goto iocnak; } break; case LOOP_CONCAT: if (mp->b_cont != NULL) loop->catlvl = *(int *) mp->b_cont->b_rptr; else { printk("loop_wput: no data buffer in ioctl\n"); error = EINVAL; goto iocnak; } break; case LOOP_TIMR: if (mp->b_cont != NULL) loop->timr = *(int *) mp->b_cont->b_rptr; else { printk("loop_wput: no data buffer in ioctl\n"); error = EINVAL; goto iocnak; } break; case LOOP_MARK: loop->mark++; /* mark next message */ break; case LOOP_GET_DEV: /* get minor number */ { int *devp; if (iocb->ioc_count != sizeof(int)) { printk("Expected ioctl len %d, got %d\n", sizeof(int), iocb->ioc_count); error = EINVAL; goto iocnak; } if (mp->b_cont != NULL) devp = (int *) mp->b_cont->b_rptr; else { printk("loop_wput: no data buffer in ioctl\n"); error = EINVAL; goto iocnak; } *devp = loop->minor_nr; /* return minor device nr */ rtn_count = sizeof(int); } break; case LOOP_BUFCALL: loop->use_bufcall++; break; case LOOP_COPY: loop->copy_bfr = 1; break; case LOOP_BURST: loop->burst = *(int *) mp->b_cont->b_rptr; break; /* * Fetch the loop module's xparent structure from user space. * When it arrives then copy data into or out of kernel space * as requested. */ case LOOP_XPARENT_COPYIN: case LOOP_XPARENT_COPYOUT: { void **ptr_ptr; void *uptr; if (mp->b_cont == NULL) { printk ("loop_wput: LOOP_XPARENT_COPYIN/OUT: no M_DATA\n"); error = EINVAL; goto iocnak; } ptr_ptr = (void **) mp->b_cont->b_rptr; uptr = *ptr_ptr; if (loop_request_copyio(q, loop, mp, M_COPYIN, uptr, sizeof(loop_xparent_t)) < 0) { error = EINVAL; goto iocnak; } return (0); /* don't respond w/iocack yet */ } case LOOP_DENY_OPEN: loop->deny_2nd_open ^= 1 ; /* flip flag */ break ; case LOOP_FLUSH: { mblk_t *fmp ; if (loop->oqptr == NULL) { error = EINVAL ; goto iocnak ; } if ((fmp = allocb(4, BPRI_MED)) == NULL) { error = ENOMEM ; goto iocnak ; } fmp->b_datap->db_type = M_FLUSH ; *fmp->b_wptr++ = FLUSHR ; putnext(loop->oqptr, fmp) ; if (mp->b_cont != NULL) { /* follow with data */ fmp = mp->b_cont ; mp->b_cont = NULL ; putnext(loop->oqptr, fmp) ; } } break ; default: printk("Expected ioctl %x, got %x\n", LOOP_SET, iocb->ioc_cmd); error = EINVAL; iocnak:{ mp->b_datap->db_type = M_IOCNAK; iocb->ioc_error = error; qreply(q, mp); } return (0); } /* end of switch on ioc_cmd */ mp->b_datap->db_type = M_IOCACK; iocb->ioc_count = rtn_count; qreply(q, mp); break; } case M_IOCDATA: { struct iocblk *iocb; int err; iocb = (struct iocblk *) mp->b_rptr; if ((err = loop_iocdata(q, mp)) < 0) { mp->b_datap->db_type = M_IOCNAK; iocb->ioc_cmd &= 0xff; /* original cmnd */ iocb->ioc_count = 0; iocb->ioc_error = -err; mp->b_wptr = mp->b_rptr + sizeof(*iocb); qreply(q, mp); return (0); } if (err > 0) /* more message xchg going on */ break; mp->b_datap->db_type = M_IOCACK; iocb->ioc_cmd &= 0xff; /* original cmnd */ iocb->ioc_count = 0; iocb->ioc_error = 0; mp->b_wptr = mp->b_rptr + sizeof(*iocb); qreply(q, mp); /* finally ack the ioctl */ break; } case M_FLUSH: { if (*mp->b_rptr & FLUSHW) flushq(q, FLUSHDATA); if (*mp->b_rptr & FLUSHR) { flushq(RD(q), FLUSHDATA); *mp->b_rptr &= ~FLUSHW; qreply(q, mp); } else freemsg(mp); break; } default: if (loop->oqptr == NULL) { putctl1(RD(q)->q_next, M_ERROR, ENXIO); freemsg(mp); break; } if (loop->burst) { mblk_t *new_mp; for (--loop->burst; loop->burst > 0; loop->burst--) { new_mp = copymsg(mp); if (new_mp == NULL) { printk("loop_wput:burst: can't copy message.\n"); break ; } putnext(loop->oqptr, new_mp); } /* * Fall through and send original with rest of options */ } else if (loop->copy_bfr) { mblk_t *new_mp; new_mp = copymsg(mp); if (new_mp == NULL) printk("loop_wput: can't copy message. Sending original\n"); else { freemsg(mp); mp = new_mp; } } if (loop->mark) { loop->mark--; mp->b_flag |= MSGMARK; } if (loop->catlvl > 0) /* concatenating msgs */ { mp = loop_concat(loop, mp); /* do it */ if (--loop->catlvl > 0) /* send it yet? */ { loop->saved_msg = mp; /* no, save it */ break; /* and exit */ } } if (loop->use_putnext && bcanputnext(loop->oqptr, mp->b_band)) putnext(loop->oqptr, mp); else if (loop->use_bufcall) { noenable(q); /* prevent queue enable */ putq(q, mp); bufcall(0, 0, loop_bufcall, (long) q); } else { loop->msgcnt++; /* count enqueued message */ if (loop->msglvl > 0 || loop->timr != 0) noenable(q); /* prevent queue enable */ /* ensure timer running before putting into queue */ if (loop->timr != 0 && loop->timr_hndl == 0) loop->timr_hndl = timeout(loop_timeout, (caddr_t) loop, loop->timr); putq(q, mp); if (loop->timr_hndl == 0 && loop->msgcnt > loop->msglvl) qenable(q); } break; } return (0);}/* ------------------------------------------------------------------- */static int loop_wsrv(queue_t * q){ mblk_t *mp; register struct loop *loop; loop = (struct loop *) q->q_ptr; if (loop->use_bufcall == 0 && loop->timr_hndl == 0 && loop->msgcnt <= loop->msglvl) return (0); if (loop->timr_hndl != 0) { untimeout(loop->timr_hndl); loop->timr_hndl = 0; } while ((mp = getq(q)) != NULL) { if (loop->oqptr == NULL) /* other side closed */ { freemsg(mp); flushq(q, FLUSHALL); break; } if (mp->b_datap->db_type <= QPCTL && !bcanputnext(loop->oqptr, mp->b_band)) { putbq(q, mp); if (loop->use_bufcall) bufcall(0, 0, loop_bufcall, (long) q); break; } if (loop->use_bufcall) loop->use_bufcall--; putnext(loop->oqptr, mp); if (--loop->msgcnt <= loop->msglvl) break; } return (0);}/* ------------------------------------------------------------------- */static int loop_rsrv(queue_t * q){ struct loop *loop; loop = (struct loop *) q->q_ptr; if (loop->oqptr == NULL) return (0); qenable(WR(loop->oqptr)); return (0);}/* ------------------------------------------------------------------- */static int loop_close(queue_t * q, int dummy, cred_t * credp){ struct loop *loop; loop = (struct loop *) q->q_ptr; loop->qptr = NULL; if (loop->timr_hndl != 0) { untimeout(loop->timr_hndl); loop->timr_hndl = 0; } if (loop->oqptr) { ((struct loop *) loop->oqptr->q_ptr)->qptr = NULL; ((struct loop *) loop->oqptr->q_ptr)->oqptr = NULL; putctl(loop->oqptr->q_next, M_HANGUP); loop->oqptr = NULL; } flushq(q, FLUSHALL); flushq(WR(q), FLUSHALL); if (loop->saved_msg != NULL) { freemsg(loop->saved_msg); loop->saved_msg = NULL; } if (loop->copy_buf != NULL) { FREE(loop->copy_buf); loop->copy_buf = NULL; } loop->use_putnext = 0; loop->use_bufcall = 0; loop->msglvl = 0; loop->msgcnt = 0; loop->timr = 0; loop->mark = 0; loop->copy_bfr = 0; loop->minor_nr = 0; loop->catlvl = 0; loop->deny_2nd_open = 0; MOD_DEC_USE_COUNT; return (0);}#ifdef MODULEint init_module(void){ int ret = lis_register_strdev(SLOOP__CMAJOR_0, &sloop_info, NLOOP, "loop"); if (ret < 0) { printk("loop.init_module: Unable to register driver.\n"); return ret; } return 0;}void cleanup_module(void){ if (lis_unregister_strdev(SLOOP__CMAJOR_0) < 0) printk("loop.cleanup_module: Unable to unregister driver.\n"); else printk("loop.cleanup_module: Unregistered, ready to be unloaded.\n"); return;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -