Date: Sat, 01 Feb 1997 17:18:59 -0800 From: Julian Elischer <julian@whistle.com> To: "Brian J. McGovern" <mcgovern@spoon.beta.com> Cc: hackers@freebsd.org Subject: Re: Device driver help needed... Message-ID: <32F3EB83.41C67EA6@whistle.com> References: <199702012336.SAA12533@spoon.beta.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Brian J. McGovern wrote: > > Ok. I'm sure that now I've terribly bastardized the uio structure, but at > least the damn thing compiles :) Let see if I can get some comment > on my interpretation of the uio stucture: > > struct uio > { > struct iovec *uio_iov; /* Pointer to IO Vector (possible array?) */ pointer to ARRAY OF IOVECS (POSSIBLY ONLY 1) (I know that's what you said but....) > int uio_iovcnt; /* Number of IO vectors (?) */ (size of array above) > off_t uio_offset; /* Offset in to device */ > int uio_resid; /* Length of read request (?) */ number of bytes STILL TO BE TRANSFERED > enum uio_seg uio_segflg; /* I assume a segment of some kind, but I > can only find reference to UIO_SYSSPACE */ the addresses in the iovec are to be interpretted as being in: KV space, User space, etc.etc. > enum uio_rw uio_rw; /* UIO_READ or UIO_WRITE (type of operation(?)) */ yes.. TO or FROM the addresses inn the iovec array > struct proc *uio_procp; /* No idea, but I've seen it set to curproc */ pointer of the proc structure associated with the operation needed if using UIO_USERSPACE. > }; > > Ok, guys. Beat me up, and let me know whats incorrect. > > With that in mind, I've bent my device driver to look like this: > > ------ foo.c --------------------------------------- > #define KERNEL > #include <sys/param.h> > #include <sys/systm.h> > #include <sys/reboot.h> > #include <sys/ioctl.h> > #include <sys/tty.h> > #include <sys/proc.h> > #include <sys/conf.h> > #include <sys/file.h> > #include <sys/uio.h> > #include <sys/kernel.h> > #include <sys/malloc.h> > #include <sys/syslog.h> > #ifdef DEVFS > #include <sys/devfsext.h> > #endif > #include <machine/clock.h> > #include <i386/isa/isa.h> > #include <i386/isa/isa_device.h> > > static char message[] = "The quick brown fox jumps over a lazy dog\n"; > > #define CDEV_MAJOR 20 are you sure 20 is unused? I guess it's for local use.. that's fine. > > static d_read_t fooread; > > static struct cdevsw foo_cdevsw = > { > nxopen, nxclose, fooread, nxwrite, > nxioctl, nxstop, nxreset, nxdevtotty, > nxselect, nxmmap, NULL, "foo", NULL, -1 > }; > you are going to have trouble openning the device if it returns ENXIO.. (nxopen?) > fooinit() > { > } > > static int fooread(dev,myuio, flag) > dev_t dev; > struct uio *myuio; > int flag; > { > unsigned char *buffer_pointer; > int toread; > if ((myuio->uio_iovcnt != 1) || (MINOR(dev) != 0)) what if it's 2? > return ENODEV; and anyway, wouldn't EINVAL be a better response to no user memory buffer.. > while(myuio->uio_resid) exactly.. keep doing it till we have the required data. > { > buffer_pointer = (message + (myuio->uio_offset % sizeof(message))); what's message? is this a ring buffer? > toread = ((long unsigned int)(message + sizeof(message)) - (long unsigned int)buffer_pointer); I don't follow this very well. > uiomove(buffer_pointer, toread, myuio); yep.. (I haven't chaecked the arguments but that's the basic idea how about checking the return value of uiomove eh? it returns an errno value you can pass straight to the user. (return it, the syscall code will put it into errno.) > myuio->uio_offset + toread; you mean += surely.. > myuio->uio_resid = myuio->uio_resid - toread; using -= would be more readable.. > } > } > #define CDEV_MAJOR 20 > > ------------------------------------------------- > > Now, I'm sure there are bugs in there. Hell, I didn't know what I was doing > half the time :) But, now its time to start debugging, which means I need > to get it in to the kernel. Someone mentioned using SYSINIT to get it working > as a pseudo-device driver. The file above is located in > /usr/src/sys/i386/addons/foo.c. Anyone care to give me a set of steps (and > code changes) to get it in the kernel? Thanks. > -Brian ok cd /sys/i386/conf cp GENERIC MYKERN cat > /sys/i386/conf/files.MYKERN <<DONE i386/addons/foo.c optional foodev DONE cat >>MYKERN <<DONE options FOODEV options DDB DONE config MYKERN cd ../../compile/MYKERN make depend make *edit for syntax errors* make {repeat} edit/make/edit/make cp kernel /kernel.test mknod /dev/foo c 20 0 sync sync reboot Boot: kernel.test -s [boot messages] # cat </dev/foo *CRASH* (probable :) * now you are in DDB I suggest you print out the man page before trying this so you can use the debugger.. OR do you have 2 machines? if so, you can use GDB over the serial port.. from the still running machine amazing to use.. julian
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?32F3EB83.41C67EA6>