From owner-freebsd-hackers Fri Mar 14 14:34:42 2003 Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8720E37B404 for ; Fri, 14 Mar 2003 14:34:37 -0800 (PST) Received: from duke.cs.duke.edu (duke.cs.duke.edu [152.3.140.1]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4A2FF43FBD for ; Fri, 14 Mar 2003 14:34:34 -0800 (PST) (envelope-from gallatin@cs.duke.edu) Received: from grasshopper.cs.duke.edu (grasshopper.cs.duke.edu [152.3.145.30]) by duke.cs.duke.edu (8.12.8/8.12.8) with ESMTP id h2EMYXRv017678 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=NO); Fri, 14 Mar 2003 17:34:33 -0500 (EST) Received: (from gallatin@localhost) by grasshopper.cs.duke.edu (8.11.6/8.9.1) id h2EMYSS91800; Fri, 14 Mar 2003 17:34:28 -0500 (EST) (envelope-from gallatin@cs.duke.edu) From: Andrew Gallatin MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15986.22772.414400.413308@grasshopper.cs.duke.edu> Date: Fri, 14 Mar 2003 17:34:28 -0500 (EST) To: Eric Anholt Cc: freebsd-hackers@FreeBSD.ORG Subject: Re: per-open device private data, mmap In-Reply-To: <1047679748.622.30.camel@leguin> References: <1047679166.622.23.camel@leguin> <1047679748.622.30.camel@leguin> X-Mailer: VM 6.75 under 21.1 (patch 12) "Channel Islands" XEmacs Lucid Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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