📄 lm.c
字号:
untimeout(bids[i]); bids[i] = 0; } ops->dev.close(lmi->device); *lmip = lmi->next; kfree(lmi); return (0);}intlmi_drv_open(lmi_t *lmi){ int err; if ( !lmi || !lmi->driver ) return ENXIO; if ( (err = lmi->driver->ops.dev.open(lmi->device)) ) { lmi->state = LMI_UNUSABLE; lmi_drv_close(lmi, NULL, 0, NULL, 0); } return (err);}/* * ======================================================================= * * MUX OPEN and CLOSE * * ======================================================================= */intlmi_mux_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp, lmi_driver_t *list, size_t size){ lmi_t *lmi = NULL; if ( q->q_ptr != NULL ) return(0); /* do this in caller to avoid false success */ if ( size < sizeof(lmi_t) ) return EFAULT; if ( sflag == DRVOPEN || WR(q)->q_next == NULL ) { int err; lmi_t **lmip, *dev = NULL; lmi_driver_t *drv; int cminor = getminor(*devp); int cmajor = getmajor(*devp); for ( drv = list; drv; drv = drv->next ) if ( cmajor == drv->cmajor ) break; if ( drv ) { ptrace(("Driver open for cmajor %d, cminor %d, size %d\n", cmajor, cminor, size)); if ( sflag == CLONEOPEN || cminor == 0 ) { for ( cminor = 1, lmip = &drv->list; cminor <= drv->nminor && *lmip; lmip = &(*lmip)->next ) { if ( cminor < getminor((*lmip)->devnum) ) { ptrace(("Calling device attach\n")); while ( !(dev = drv->ops.dev.attach(makedevice(cmajor, cminor))) ) if ( ++cminor < getminor((*lmip)->devnum) ) break; if ( dev ) break; } if ( cminor == getminor((*lmip)->devnum) ) cminor++; } if ( !*lmip && cminor <= drv->nminor ) { ptrace(("Calling device attach\n")); dev = drv->ops.dev.attach(makedevice(cmajor, cminor)); } if ( !dev || cminor > drv->nminor ) return ENXIO; *devp = makedevice(getmajor(*devp), cminor); } else { if ( cminor > drv->nminor ) return ENXIO; if ( !(dev = drv->ops.dev.attach(*devp)) ) return ENXIO; for ( lmip = &drv->list; *lmip; lmip = &(*lmip)->next ) { if ( cminor < getminor((*lmip)->devnum) ) break; if ( cminor == getminor((*lmip)->devnum) ) return EBUSY; } } if ( !(lmi = kmalloc(size, GFP_KERNEL)) ) return ENOMEM; bzero(lmi, size); lmi->devnum = *devp; lmi->driver = drv; lmi->device = dev; ptrace(("Calling device open\n")); if ( (err = drv->ops.dev.open(dev)) ) { kfree(lmi); return(err); } dev->module = lmi; dev->ucalls = drv->ucalls; lmi->next = *lmip; *lmip = lmi; } else { ptrace(("Multiplexor open for size %d\n", size)); /* FIXME: check permissions if minor number = 0 */ if ( !(lmi = kmalloc(size, GFP_KERNEL)) ) return ENOMEM; bzero(lmi, size); } } else return EIO; /* these muxes can't be pushed */ lmi->rq = RD(q); lmi->wq = WR(q); lmi->state = LMI_UNATTACHED; q->q_ptr = WR(q)->q_ptr = lmi; return(0);}intlmi_mux_close(queue_t *q, int flag, cred_t *crp, lmi_ulong *tids, int ntids, lmi_ulong *bids, int nbids){ int i; lmi_t **lmip = NULL, *lmi = (lmi_t *)q->q_ptr; lmi_driver_t *drv = lmi->driver; if ( drv ) { for ( lmip = &drv->list; *lmip; lmip = &(*lmip)->next ) if ( *lmip == lmi ) break; if ( !*lmip ) return EFAULT; } lmi_disable(lmi); for ( i=0; i<ntids; i++ ) if ( tids[i] ) { untimeout(tids[i]); tids[i] = 0; } for ( i=0; i<nbids; i++ ) if ( bids[i] ) { untimeout(bids[i]); bids[i] = 0; } lmi_detach(lmi); lmi->rq->q_ptr = lmi->wq->q_ptr = NULL; if ( drv ) { drv->ops.dev.close(lmi->device); *lmip = lmi->next; } kfree(lmi); return(0);}/* * ======================================================================= * * OPEN and CLOSE * * ======================================================================= */intlmi_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp, lmi_driver_t *list, size_t size){ lmi_t *lmi = NULL; if ( q->q_ptr != NULL ) return(0); /* do this in caller to avoid false success */ if ( size < sizeof(lmi_t) ) return EFAULT; if ( sflag == DRVOPEN || WR(q)->q_next == NULL ) { int err; lmi_t **lmip, *dev = NULL; lmi_driver_t *drv; int cminor = getminor(*devp); int cmajor = getmajor(*devp); ptrace(("Driver open for cmajor %d, cminor %d, size %d\n", cmajor, cminor, size)); for ( drv = list; drv; drv = drv->next ) if ( cmajor == drv->cmajor ) break; if ( !drv ) return ENXIO; if ( sflag == CLONEOPEN || cminor == 0 ) { for ( cminor = 1, lmip = &drv->list; cminor <= drv->nminor && *lmip; lmip = &(*lmip)->next ) { if ( cminor < getminor((*lmip)->devnum) ) { ptrace(("Calling device attach\n")); while ( !(dev = drv->ops.dev.attach(makedevice(cmajor, cminor))) ) if ( ++cminor < getminor((*lmip)->devnum) ) break; if ( dev ) break; } if ( cminor == getminor((*lmip)->devnum) ) cminor++; } if ( !*lmip && cminor <= drv->nminor ) { ptrace(("Calling device attach\n")); dev = drv->ops.dev.attach(makedevice(cmajor, cminor)); } if ( !dev || cminor > drv->nminor ) return ENXIO; *devp = makedevice(getmajor(*devp), cminor); } else { if ( cminor > drv->nminor ) return ENXIO; if ( !(dev = drv->ops.dev.attach(*devp)) ) return ENXIO; for ( lmip = &drv->list; *lmip; lmip = &(*lmip)->next ) { if ( cminor < getminor((*lmip)->devnum) ) break; if ( cminor == getminor((*lmip)->devnum) ) return EBUSY; } } if ( !(lmi = kmalloc(size, GFP_KERNEL)) ) return ENOMEM; bzero(lmi, size); lmi->devnum = *devp; lmi->driver = drv; lmi->device = dev; ptrace(("Calling device open\n")); if ( (err = drv->ops.dev.open(dev)) ) { kfree(lmi); return(err); } dev->module = lmi; dev->ucalls = drv->ucalls; lmi->next = *lmip; *lmip = lmi; } else if ( sflag == MODOPEN || WR(q)->q_next != NULL ) { ptrace(("Module open for size %d\n", size)); if ( !(lmi = kmalloc(size, GFP_KERNEL)) ) return ENOMEM; bzero(lmi, size); } else return EIO; lmi->rq = RD(q); lmi->wq = WR(q); lmi->state = LMI_UNATTACHED; q->q_ptr = WR(q)->q_ptr = lmi; return(0);}intlmi_close(queue_t *q, int flag, cred_t *crp, lmi_ulong *tids, int ntids, lmi_ulong *bids, int nbids){ int i; lmi_t **lmip = NULL, *lmi = (lmi_t *)q->q_ptr; lmi_driver_t *drv = lmi->driver; if ( drv ) { for ( lmip = &drv->list; *lmip; lmip = &(*lmip)->next ) if ( *lmip == lmi ) break; if ( !*lmip ) return EFAULT; } lmi_disable(lmi); for ( i=0; i<ntids; i++ ) if ( tids[i] ) { untimeout(tids[i]); tids[i] = 0; } for ( i=0; i<nbids; i++ ) if ( bids[i] ) { untimeout(bids[i]); bids[i] = 0; } lmi_detach(lmi); lmi->rq->q_ptr = lmi->wq->q_ptr = NULL; if ( drv ) { drv->ops.dev.close(lmi->device); *lmip = lmi->next; } kfree(lmi); return(0);}/* * ======================================================================= * * DRIVER Registration * * ======================================================================= */intlmi_register_driver(list, cmajor, strtab, nminor, name, ops, dcalls, ucalls) lmi_driver_t **list; major_t cmajor; struct streamtab *strtab; int nminor; char *name; lmi_ops_t *ops; void *dcalls; void *ucalls;{ int ret; lmi_driver_t *drv; if ( nminor < 1 || !list || !strtab || !dcalls || !ucalls || !ops || !ops->dev.attach || !ops->dev.open || !ops->dev.close || !ops->lmi.info || !ops->lmi.attach || !ops->lmi.detach || !ops->lmi.enable || !ops->lmi.disable || !ops->lmi.ioctl ) { __ptrace(("required pointer is NULL!\n")); return -EINVAL; } if ( !(drv = kmalloc(sizeof(*drv), GFP_KERNEL)) ) { __ptrace(("couldn't allocate memory!\n")); return -ENOMEM; } bzero(drv, sizeof(*drv)); drv->next = *list; /* should spin lock this global */ drv->cmajor = cmajor; drv->nminor = nminor; drv->info = strtab; drv->ops = *ops; drv->ucalls = ucalls; drv->dcalls = dcalls; if ( (ret = lis_register_strdev(cmajor, strtab, nminor, name)) >= 0 ) { if ( ret && !cmajor ) drv->cmajor = cmajor = ret; *list = drv; } else { kfree(drv); __ptrace(("couldn't register driver with LiS!\n")); } return(ret);}intlmi_unregister_driver(lmi_driver_t **list, major_t cmajor){ int ret; lmi_driver_t **drvp, *drv; for ( drvp = list; *drvp; drvp = &(*drvp)->next ) if ( cmajor == (*drvp)->cmajor ) break; if ( !(drv = *drvp) ) { __ptrace(("couldn't find driver!\n")); return -ENXIO; } if ( drv->list ) { __ptrace(("drivers still running!\n")); return -EBUSY; } if ( (ret = lis_unregister_strdev(cmajor)) ) { __ptrace(("couldn't unregister driver from LiS!\n")); return(ret); } *drvp = drv->next; kfree(drv); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -