Date: Fri, 14 Mar 2003 17:34:28 -0500 (EST) From: Andrew Gallatin <gallatin@cs.duke.edu> To: Eric Anholt <eta@lclark.edu> Cc: freebsd-hackers@FreeBSD.ORG Subject: Re: per-open device private data, mmap Message-ID: <15986.22772.414400.413308@grasshopper.cs.duke.edu> In-Reply-To: <1047679748.622.30.camel@leguin> References: <1047679166.622.23.camel@leguin> <1047679748.622.30.camel@leguin>
next in thread | previous in thread | raw e-mail | index | archive | help
Eric Anholt writes: > shouldn't be too big of an issue. The unique identifier is the big > problem and the fileops trick should work for that. > > However, is this going to get easier some day? Are there any plans to > pass the struct file down to the drivers and have a void * in there for > private data? > I think that phk is working on this for 6.x In the meantime, I have a new driver I"m developing which uses the fileops trick you describe, but takes it a step further and conjurs up a new vnode. That makes it work with mmap. I've not run into any problems yet, but it is lightly tested. Cheers, Drew /* * Conjure up our own vnode out of thin air. We need the * vnode so that we can stash a pointer to the per-connection * priv struct for use in open/close/ioctl and mmap. This is * tricky, because we need make it look enough like the device * vnode so that VOP_GETATTR() works on the slave vnode in mmap() */ static int xxx_conjur_vnode(dev_t dev, struct thread *td) { int error, fd; struct filedesc *fdp; struct file *fp; struct vnode *vn = NULL, *vd = NULL; struct cdev *rdev; fdp = td->td_proc->p_fd; if (fdp == NULL) return (0); if (td->td_dupfd >= 0) return ENODEV; rdev = xxx_malloc(sizeof(*rdev), M_WAITOK); if ((error = falloc(td, &fp, &fd)) != 0) goto abort_with_rdev; vd = SLIST_FIRST(&dev->si_hlist); if ((error = getnewvnode("none", vd->v_mount, vd->v_op, &vn))) goto abort_with_falloc; vn->v_type = VCHR; /* XXXX really should clone v_vdata & not copy pointer */ vn->v_data = vd->v_data; /* for VTOI in devfs_getattr() */ /* copy our cdev info */ vn->v_rdev = rdev; bcopy(vd->v_rdev, vn->v_rdev, sizeof(*rdev)); /* finally, save the data pointer (our softc) */ vn->v_rdev->si_drv2 = 0; fp->f_data = (caddr_t)vn; fp->f_flag = FREAD|FWRITE; fp->f_ops = &xxx_fileops; fp->f_type = DTYPE_VNODE; /* so that we can mmap */ /* * Save the new fd as dupfd in the proc structure, then we have * open() return the special error code (ENXIO). Returning with a * dupfd and ENXIO causes magic things to happen in kern_open(). */ td->td_dupfd = fd; return 0; abort_with_rdev: xxx_free(rdev); abort_with_falloc: FILEDESC_LOCK(fdp); fdp->fd_ofiles[fd] = NULL; FILEDESC_UNLOCK(fdp); fdrop(fp, td); return (error); } static int xxx_fileclose(struct file *fp, struct thread *td) { int ready_to_close; struct vnode *vn; struct cdev *rdev; xxx_port_state_t *ps; vn = (struct vnode *)fp->f_data; rdev = vn->v_rdev; ps = rdev->si_drv2; rdev->si_drv2 = NULL; /* replace the vnode ops so that devfs doesn't try to reclaim anything */ vn->v_op = spec_vnodeop_p; vn->v_type = VNON; /* don't want to freedev() in vgonel()*/ vgone(vn); /* free our private rdev */ xxx_free(rdev); if (ps) { xxx_mutex_enter(&ps->sync); /* Close the port if there are no more mappings */ ready_to_close = ps->ref_count == 0; XXX_DEBUG_PRINT (XXX_DEBUG_OPENCLOSE, ("Board %d, port %d closed\n", ps->is->id, ps->port)); xxx_mutex_exit(&ps->sync); if (ready_to_close) { xxx_common_close (ps); } else { XXX_INFO (("Application closed file descriptor while " "mappings still alive: port destruct delayed\n")); } } return (0); } static int xxx_mmap(dev_t dev, vm_offset_t offset, #if MMAP_RETURNS_PINDEX == 0 vm_offset_t *paddr, #endif int nprot) { int status; xxx_port_state_t *ps; void *kva; #if MMAP_RETURNS_PINDEX vm_offset_t phys; vm_offset_t *paddr = &phys; #endif ps = (xxx_port_state_t *)dev->si_drv2; <...> To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?15986.22772.414400.413308>