Captain's Universe Home
Captain's Universe Home
Cosmic Ray Muon DetectorTeleGarden Pages
Time on MarsBryophyllum Plants
Jupiter Radio AstronomyAncient Pages
Salzburg Tourist GuideEarth Magnetometer
  H O M E     AJAX & MORE     LINUX & MORE     RTAI     XENOMAI     ADEOS IPIPE      
    JAVA & BROWSERS     *NIX     ELECTRONICS     REVIEWS     ARTEMIA     FAIRY SHRIMP      


FreeBSD Device Driver Template/Skeleton (Kernel Module)


This is a FreeBSD 5.3 Device Driver Template/Skeleton. The driver creates a device entry in /dev/, which can be used to communicate with the kernel module (read, write, ioctl).

  • Compile the kernel module with "make" (Makefile)
  • Load the module with "load.sh"
  • Test the module with "devtest"

"devtest" does an ioctl (IO CONTROL) (look at the kernel log in /var/log/messages). Furthermore it writes a string to kernel space and reads it back.

If you want to implement a blocking read operation, see the FreeBSD Parallel Port Interrupt Device Driver Template/Skeleton for usage of tsleep and wakeup.

Compilation is done with "gcc" - it is installed by default with the CD set.

skeleton.c
/* FreeBSD 5.3 Device Driver / Kernel Module Template/Skeleton
   *******************************************************
   
 Compile with: make
 Load the module with: kldload -v ./skeleton.ko
 Test with "devtest.c"
 
*/

#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/uio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>

struct skeleton_softc 
{
	bus_space_tag_t	bst;
	bus_space_handle_t bsh;
	dev_t		dev0;
	dev_t		dev1;
	u_int32_t	open_mask;
	u_int32_t	read_mask;
	struct resource *res;
	int		rid;
};

static devclass_t skeleton_devclass;

static	d_open_t	skeleton_open;
static	d_close_t	skeleton_close;
static	d_read_t	skeleton_read;
static	d_write_t	skeleton_write;
static	d_ioctl_t	skeleton_ioctl;

#define Nskeleton 2
#define MAJOR 199
#define MAXMSGLEN 128
#define TEST1 1

static struct cdevsw skeleton_cdevsw = {
	.d_version	=	D_VERSION,
	.d_name	=	"skeleton",
	.d_flags	=	D_NEEDGIANT,
	.d_open	=	skeleton_open,	/* open */
	.d_close	=	skeleton_close,	/* close */
	.d_read	=	skeleton_read,	/* read */
	.d_write	=	skeleton_write,	/* write */
	.d_ioctl	=	skeleton_ioctl	/* ioctl */
};

static int skeleton_open(struct cdev *dev, int flags, int fmt, struct thread *td) {
	int unit = minor(dev) >> 16;
	int skeleton = minor(dev) & 0xff;
	struct skeleton_softc *sc;
	if (skeleton >= Nskeleton)
		return ENXIO;
	sc = devclass_get_softc(skeleton_devclass, unit);
	if (sc == NULL)
		return ENXIO;
	if (sc->open_mask & (1 << skeleton))
		return EBUSY;
	sc->open_mask |= 1 << skeleton;
	sc->read_mask |= 1 << skeleton;
	return 0;
}

static int skeleton_close(struct cdev *dev, int flags, int fmt, struct thread *td) {
	int unit = minor(dev) >> 16;
	int skeleton = minor(dev) & 0xff;
	struct skeleton_softc *sc;
	if (skeleton >= Nskeleton)
		return ENXIO;
	sc = devclass_get_softc(skeleton_devclass, unit);
	if (sc == NULL)
		return ENXIO;
	sc->open_mask &= ~(1 << skeleton);
	return 0;
}

char teststr[128];

static int skeleton_read(struct cdev *dev, struct uio *uio, int flag) {
	int resid = MAXMSGLEN;
	int error = 0;
	//printf("reading...\n");
	do {
		if (uio->uio_resid < resid)
			resid = uio->uio_resid;
		error = uiomove(teststr, resid, uio);	
	} while (resid > 0 && error == 0);
	return(error);
}

static int skeleton_write(struct cdev *dev, struct uio *uio, int flag) {
	int resid = MAXMSGLEN;
	int error = 0;
	//printf("writing...\n");
	do {
		if (uio->uio_resid < resid)
			resid = uio->uio_resid;
		error = uiomove(teststr, resid, uio);	
	} while (resid > 0 && error == 0);
	return(error);
}

static int skeleton_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
	int fflag, struct thread *td)
{
	int error = 0;
	switch(cmd) {
	case TEST1:
		printf("Skeleton IOCTL: TEST1\n");
		break;
	default:
		break;
	}
	return(error);
}


static void skeleton_identify (driver_t *driver, device_t parent) {
	devclass_t dc;
	device_t child;
	dc = devclass_find("skeleton");
	if (devclass_get_device(dc, 0) == NULL) {
		child = BUS_ADD_CHILD(parent, 0, "skeleton", -1);
	}
}

static int skeleton_probe(device_t dev) {
	if (device_get_unit(dev) != 0)
		return (ENXIO);
	device_set_desc(dev, "FreeBSD Device Driver Template/Skeleton");
	return (0);
}

static int skeleton_attach(device_t dev) {
	struct skeleton_softc *sc;
	sc = (struct skeleton_softc *) device_get_softc(dev);
	sc->rid = 0;
	sc->dev0 = make_dev(&skeleton_cdevsw, 0, UID_ROOT, GID_WHEEL, 0644, "skeleton0");
//	sc->dev1 = make_dev(&skeleton_cdevsw, 1, UID_ROOT, GID_WHEEL, 0644, "skeleton1");
	sc->open_mask = 0;
	sc->read_mask = 0;
	return 0;
}

static int skeleton_detach(device_t dev) {
	struct skeleton_softc *sc;
	sc = (struct skeleton_softc *) device_get_softc(dev);
	destroy_dev(sc->dev0);
//	destroy_dev(sc->dev1);
	bus_generic_detach(dev);
	return 0;
}

static device_method_t skeleton_methods[] = {
	/* Device interface */
	DEVMETHOD(device_identify,	skeleton_identify),
	DEVMETHOD(device_probe,		skeleton_probe),
	DEVMETHOD(device_attach,	skeleton_attach),
	DEVMETHOD(device_detach,	skeleton_detach),

	{ 0, 0 }
};

static driver_t skeleton_driver = {
	"skeleton",
	skeleton_methods,
	sizeof(struct skeleton_softc),
};

DRIVER_MODULE(skeleton, isa, skeleton_driver, skeleton_devclass, 0, 0);

devtest.c
// compile with: gcc -o devtest devtest.c

#include <sys/types.h>
#include <sys/ioctl.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>

#define TEST1 1

int main(void) {
	int error, fd, wlen;
	double testval;
	char teststr[128];
	char mystring[] = "hello captain!";
	
	fd = open("/dev/skeleton0", O_RDWR);
	if (fd == -1)
		err(1, "open");

	error = ioctl(fd, TEST1, NULL);
	if (error == -1)
		err(1, "ioctl");

	wlen = strlen(mystring) + 1;
	error = write(fd, mystring, wlen);
	if (error == -1)
		err(1, "write");

	error = read(fd, teststr, 128);
	if (error == -1)
		err(1, "read");
	printf("read2: %s\n", teststr);

	close(fd);
	exit(0);
}



Makefile
SRCS=skeleton.c
KMOD=skeleton

.include <bsd.kmod.mk>

load.sh
#!/bin/sh
kldunload skeleton
kldload -v ./skeleton.ko

Last-Modified: Sat, 04 Feb 2006 16:03:13 GMT

Google
 
Web www.captain.at
go to top
© 1996-2010 . All rights reserved.
No reproduction, distribution, publishing or transmission of the copyrighted materials at this site is permitted. Policy
go to top