2 # This writes a skeleton driver and puts it into the kernel tree for you
3 #arg1 is lowercase "foo"
5 # It also creates a directory under /usr/src/lkm to help you create
6 #loadable kernel modules, though without much use except for development.
8 # Trust me, RUN THIS SCRIPT :)
10 #-------cut here------------------
15 echo "Hey , how about some help here.. give me a device name!"
19 if [ -d /usr/src/lkm ]
21 mkdir /usr/src/lkm/${1}
24 UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
25 cat >files.${UPPER} <<DONE
26 i386/isa/${1}.c optional ${1} device-driver
30 # Configuration file for kernel type: ${UPPER}
32 # \$FreeBSD: src/share/examples/drivers/make_device_driver.sh,v 1.6.2.1 2001/07/25 15:56:09 dd Exp $"
33 # \$DragonFly: src/share/examples/drivers/make_device_driver.sh,v 1.6 2007/05/17 08:19:01 swildner Exp $"
36 grep -v GENERIC < GENERIC >>${UPPER}
39 # trust me, you'll need this
41 device ${1}0 at isa? port 0x234 bio irq 5
44 cat >../isa/${1}.c <<DONE
49 * \$FreeBSD: src/share/examples/drivers/make_device_driver.sh,v 1.6.2.1 2001/07/25 15:56:09 dd Exp $
53 #include "${1}.h" /* generated file.. defines N${UPPER} */
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/kernel.h> /* SYSINIT stuff */
57 #include <sys/conf.h> /* cdevsw stuff */
58 #include <sys/malloc.h> /* malloc region definitions */
59 #include <machine/clock.h> /* DELAY() */
60 #include <i386/isa/isa.h> /* ISA bus port definitions etc. */
61 #include <i386/isa/isa_device.h>/* ISA bus configuration structures */
62 #include <sys/${1}io.h> /* ${1} IOCTL definitions */
66 /* Function prototypes (these should all be static) */
67 static d_open_t ${1}open;
68 static d_close_t ${1}close;
69 static d_read_t ${1}read;
70 static d_write_t ${1}write;
71 static d_ioctl_t ${1}ioctl;
72 static d_mmap_t ${1}mmap;
73 static d_poll_t ${1}poll;
74 static int ${1}probe (struct isa_device *);
75 static int ${1}attach (struct isa_device *);
76 #ifdef ${UPPER}_MODULE
77 static ointhand2_t ${1}intr; /* should actually have type inthand2_t */
81 static struct cdevsw ${1}_cdevsw = {
97 struct isa_driver ${1}driver = {
103 * device specific Misc defines
105 #define BUFFERSIZE 1024
107 #define UNIT(dev) minor(dev) /* assume one minor number per unit */
110 * One of these per allocated device
113 struct isa_device *dev;
114 char buffer[BUFFERSIZE];
117 typedef struct ${1}_softc *sc_p;
119 static sc_p sca[N${UPPER}];
121 /* add your own test to see if it exists */
122 /* should return the number of ports needed */
124 ${1}probe (struct isa_device *dev)
127 int unit = dev->id_unit;
128 sc_p scp = sca[unit];
131 * Check the unit makes sense.
133 if (unit > N${UPPER}) {
134 printf("bad unit (%d)\n", unit);
138 printf("unit %d already attached\n", unit);
143 * try see if the device is there.
145 val = inb (dev->id_iobase);
151 * ok, we got one we think
152 * do some further (this time possibly destructive) tests.
154 outb (dev->id_iobase, 0xff);
155 DELAY (10000); /* 10 ms delay */
156 val = inb (dev->id_iobase) & 0x0f;
157 return ((val & 0x0f) == 0x0f)? NUMPORTS : 0 ;
161 * Called if the probe succeeded.
162 * We can be destructive here as we know we have the device.
163 * we can also trust the unit number.
166 ${1}attach (struct isa_device *dev)
168 int unit = dev->id_unit;
169 sc_p scp = sca[unit];
172 * Attach our interrupt handler to the device struct. Our caller
173 * will attach it to the hardware soon after we return.
175 dev->id_ointr = ${1}intr;
178 * Allocate storage for this instance .
180 scp = kmalloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
182 printf("${1}%d failed to allocage driver strorage\n", unit);
185 bzero(scp, sizeof(*scp));
189 * Store whatever seems wise.
196 * Macro to check that the unit number is valid
197 * Often this isn't needed as once the open() is performed,
198 * the unit number is pretty much safe.. The exception would be if we
199 * implemented devices that could "go away". in which case all these routines
200 * would be wise to check the number, DIAGNOSTIC or not.
202 #define CHECKUNIT(RETVAL) \
203 do { /* the do-while is a safe way to do this grouping */ \
204 if (unit > N${UPPER}) { \
205 printf("%s:bad unit %d\n", __func__, unit); \
209 printf( "%s: unit %d not attached\n", __func__, unit);\
214 #define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
215 #else /* DIAGNOSTIC */
216 #define CHECKUNIT_DIAG(RETVAL)
217 #endif /* DIAGNOSTIC */
222 sc_p scp = sca[unit];
225 * well we got an interrupt, now what?
226 * Theoretically we don't need to check the unit.
231 int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
233 int unit = UNIT (dev);
234 sc_p scp = sca[unit];
236 CHECKUNIT_DIAG(ENXIO);
240 /* whatever resets it */
241 outb(scp->dev->id_iobase, 0xff);
249 * You also need read, write, open, close routines.
250 * This should get you started
253 ${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
255 int unit = UNIT (dev);
256 sc_p scp = sca[unit];
267 ${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
269 int unit = UNIT (dev);
270 sc_p scp = sca[unit];
272 CHECKUNIT_DIAG(ENXIO);
281 ${1}read(dev_t dev, struct uio *uio, int ioflag)
283 int unit = UNIT (dev);
284 sc_p scp = sca[unit];
288 CHECKUNIT_DIAG(ENXIO);
294 toread = (min(uio->uio_resid, sizeof(scp->buffer)));
295 return(uiomove(scp->buffer, toread, uio));
299 ${1}write(dev_t dev, struct uio *uio, int ioflag)
301 int unit = UNIT (dev);
302 sc_p scp = sca[unit];
305 CHECKUNIT_DIAG(ENXIO);
311 towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
312 return(uiomove(scp->buffer, towrite, uio));
316 ${1}mmap(dev_t dev, int offset, int nprot)
318 int unit = UNIT (dev);
319 sc_p scp = sca[unit];
326 #if 0 /* if we had a frame buffer or whatever.. do this */
327 if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
330 return i386_btop((FRAMEBASE + offset));
337 ${1}poll(dev_t dev, int which, struct proc *p)
339 int unit = UNIT (dev);
340 sc_p scp = sca[unit];
342 CHECKUNIT_DIAG(ENXIO);
347 return (0); /* this is the wrong value I'm sure */
350 #ifndef ${UPPER}_MODULE
353 * Now for some driver initialisation.
354 * Occurs ONCE during boot (very early).
355 * This is if we are NOT a loadable module.
358 ${1}_drvinit(void *unused)
362 dev = makedev(CDEV_MAJOR, 0);
363 cdevsw_add(&dev, &${1}_cdevsw, NULL);
366 SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
369 #else /* ${UPPER}_MODULE */
370 /* Here is the support for if we ARE a loadable kernel module */
372 #include <sys/exec.h>
373 #include <sys/sysent.h>
376 MOD_DEV (${1}, LM_DT_CHAR, CDEV_MAJOR, &${1}_cdevsw);
378 static struct isa_device dev = {0, &${1}driver, BASE_IO, IRQ, DMA, (caddr_t) PHYS_IO, PHYS_IO_SIZE, INT_INT, 0, FLAGS, 0, 0, 0, 0, 1, 0, 0};
381 ${1}_load (struct lkm_table *lkmtp, int cmd)
383 if (${1}probe (&dev)) {
385 uprintf ("${1} driver loaded\n");
386 uprintf ("${1}: interrupts not hooked\n");
389 uprintf ("${1} driver: probe failed\n");
395 ${1}_unload (struct lkm_table *lkmtp, int cmd)
397 uprintf ("${1} driver unloaded\n");
402 ${1}_stat (struct lkm_table *lkmtp, int cmd)
408 ${1}_mod (struct lkm_table *lkmtp, int cmd, int ver)
410 MOD_DISPATCH(${1}, lkmtp, cmd, ver,
411 ${1}_load, ${1}_unload, ${1}_stat);
414 #endif /* ${UPPER}_MODULE */
418 cat >../../sys/${1}io.h <<DONE
420 * Definitions needed to access the ${1} device (ioctls etc)
421 * see mtio.h , ioctl.h as examples
427 #include <sys/types.h>
429 #include <sys/ioccom.h>
432 * define an ioctl here
434 #define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
438 if [ -d /usr/src/lkm/${1} ]
440 cat >/usr/src/lkm/${1}/Makefile <<DONE
441 # ${UPPER} Loadable Kernel Module
443 # This happens not to work, actually. It's written for
444 # a character ISA device driver, but they cannot be
445 # be made into lkm's, because you have to hard code
446 # everything you'll otherwise enter into the kernel
447 # configuration file.
449 .PATH: \${.CURDIR}/../../sys/arch/i386/isa
453 CFLAGS += -I. -D${UPPER}_MODULE
456 BASE_IO=0 # Base IO address
459 PHYS_IO=0 # Physical IO Memory base address
460 PHYS_IO_SIZE=0 # Physical IO Memory size
461 INT_INT=0 # Interrupt interface
464 CFLAGS+= -DBASE_IO=\${BASE_IO} -DIRQ=\${IRQ} -DDMA=\${DMA} -DPHYS_IO=\${PHYS_IO} -DPHYS_IO_SIZE=\${PHYS_IO_SIZE} -DINT_INT=\${INT_INT} -DFLAGS=\${FLAGS}
467 echo "#define N${UPPER} 1" > ${1}.h
470 \${INSTALL} -c -o \${BINOWN} -g \${BINGRP} -m \${BINMODE} \
471 \${.CURDIR}/${1} \${DESTDIR}/usr/bin
473 .include <bsd.kmod.mk>
478 cd ../../compile/${UPPER}
484 #--------------end of script---------------
486 #edit to your taste..