Date: Wed, 29 Jul 2009 13:56:51 -0400 From: John Baldwin <jhb@freebsd.org> To: "Chris Harrer" <cjharrer@comcast.net> Cc: freebsd-drivers@freebsd.org Subject: Re: Driver development question Message-ID: <200907291356.51702.jhb@freebsd.org> In-Reply-To: <000c01ca1071$54991d70$fdcb5850$@net> References: <002801ca06f0$b1d42af0$157c80d0$@net> <20090725035643.GT49724@elvis.mu.org> <000c01ca1071$54991d70$fdcb5850$@net>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wednesday 29 July 2009 1:23:46 pm Chris Harrer wrote: > Warning LONG message below, I figured I'd give as much information as > possible to try and help me along. > > > > On Tuesday 21 July 2009 8:07:13 pm Alfred Perlstein wrote: > > > * John Baldwin <jhb@freebsd.org> [090721 14:44] wrote: > > > > On Tuesday 21 July 2009 2:34:21 am Marc Loerner wrote: > > > > > Am Dienstag 21 Juli 2009 00:38:56 schrieb Sam Leffler: > > > > > > John Baldwin wrote: > > > > > > > On Friday 17 July 2009 11:10:17 am Chris Harrer wrote: > > > > > > >> Hi All, > > > > > > >> > > > > > > >> I'm hoping someone can point me in the right direction... I'm > > > > > > >> developing a FreeBSD driver for a PCIe card. The driver > controls a > > > > > > >> hardware device that has DRAM and various state information on > it. > > I'm > > > > > > >> trying to mimic functionality I have for other OS support such > that > > I > > > > > > >> can dump memory and state information from the card to a file I > > > create > > > > > > >> from within my driver (kernel module). > > > > > > >> > > > > > > >> For example, in a Linux driver I use filp_open to create the > dump > > file > > > > > > >> (represented by fp), then use fp->f_op->write to put > information > > into > > > > > > >> the file. > > > > > > >> > > > > > > >> FreeBSD doesn't have filp_* API's. I've tried searching for > > example > > > > > > >> drivers and googling for file API's from kernel modules to no > > avail. > > > > > > >> Can someone please offer some guidance as to how I might > proceed > > here? > > > > > > >> > > > > > > >> Thanks in advance and any insight would be most appreciated! > > > > > > > > > > > > > > You can look at sys/kern/kern_ktrace.c to see how the ktrace() > > system > > > > > > > call creates a file. I think in general you will wind up using > > > > > > > NDINIT/namei() (to lookup the vnode for a pathname) and then > > vn_open() / > > > > > > > vn_rdwr() / vn_close(). > > > > > > > > > > > > man alq(9). > > > > > > > > > > > > > > > > > > > > > > Why not use kern_open, kern_close, kern_preadv, kern_pwritev? > > > > > > > > Those affect the state of the current process by opening a new file > > > > descriptor, etc. That is generally bad practice for a device driver > to be > > > > interfering with a process' state, and it will not work for kernel > > threads. > > > > You can rather easily have userland open a file and then pass the file > > > > > descriptor to a driver which can then do operations on a file > directly. > > > > > > If the vnode operations are annoying to wrap ones head around, one > > > could have the driver defer this this to a kernel resident process > > > that the driver would create on attach. > > > > Kernel processes don't have file descriptor tables. > > Hi All, > > I'm hoping you can provide a bit more guidance here as I'm still struggling > with this and I'm running out of ideas. Again, what I want to do is, some > event (interrupt from an intelligent PCIe card indicating it's "dead") will > cause me to: > > 1) Open/create a file > 2) write raw/random/non-patterned/variable sized data to the file > 3) close/save the file > > from within my device driver. To this point, I've tried several things > using vn_open, vn_open_cred, alq_open and cutting/massaging the code from > alq_open with no success. I've done this from within the context of my > interrupt handler as well as a timer (callout_init, callout_reset) thread as > well as from a thread I create with kproc_create. In each and every > instance, I get the following crash: The problem is that kernel threads do not have a valid file descriptor table, hence fd_cdir is NULL. You could work around this if you create a dedicated kproc and set fd_cdir to rootvnode (but vref() rootvnode when you do this). You should also set fd_rdir and fd_jdir to rootvnode as well (also doing appropriate vref() of rootvnode for each reference). Something like this: struct filedesc *fdp; fdp = curthread->td_proc->p_fd; FILEDESC_XLOCK(fdp); fd->fd_rdir = rootvnode; vref(rootvnode); fd->fd_jdir = rootvnode; vref(rootvnode); fd->fd_cdir = rootvnode; vref(rootvnode); FILEDESC_XUNLOCK(fdp); You should not do this from a callout routine or interrupt handler however. You could do this via a TASK to a private taskqueue with a dedicated kernel process however. (i.e. queue a task that does the above during after creating the taskqueue and then queue a task to create the file later). -- John Baldwin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907291356.51702.jhb>