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 $"
35 grep -v GENERIC < GENERIC >>${UPPER}
38 # trust me, you'll need this
40 device ${1}0 at isa? port 0x234 bio irq 5
43 cat >../isa/${1}.c <<DONE
48 * \$FreeBSD: src/share/examples/drivers/make_device_driver.sh,v 1.6.2.1 2001/07/25 15:56:09 dd Exp $
52 #include "${1}.h" /* generated file.. defines N${UPPER} */
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h> /* SYSINIT stuff */
56 #include <sys/conf.h> /* cdevsw stuff */
57 #include <sys/malloc.h> /* malloc region definitions */
58 #include <machine/clock.h> /* DELAY() */
59 #include <i386/isa/isa.h> /* ISA bus port definitions etc. */
60 #include <i386/isa/isa_device.h>/* ISA bus configuration structures */
61 #include <sys/${1}io.h> /* ${1} IOCTL definitions */
65 /* Function prototypes (these should all be static) */
66 static d_open_t ${1}open;
67 static d_close_t ${1}close;
68 static d_read_t ${1}read;
69 static d_write_t ${1}write;
70 static d_ioctl_t ${1}ioctl;
71 static d_mmap_t ${1}mmap;
72 static d_poll_t ${1}poll;
73 static int ${1}probe (struct isa_device *);
74 static int ${1}attach (struct isa_device *);
75 #ifdef ${UPPER}_MODULE
76 static ointhand2_t ${1}intr; /* should actually have type inthand2_t */
80 static struct cdevsw ${1}_cdevsw = {
96 struct isa_driver ${1}driver = {
102 * device specific Misc defines
104 #define BUFFERSIZE 1024
106 #define UNIT(dev) minor(dev) /* assume one minor number per unit */
109 * One of these per allocated device
112 struct isa_device *dev;
113 char buffer[BUFFERSIZE];
116 typedef struct ${1}_softc *sc_p;
118 static sc_p sca[N${UPPER}];
120 /* add your own test to see if it exists */
121 /* should return the number of ports needed */
123 ${1}probe (struct isa_device *dev)
126 int unit = dev->id_unit;
127 sc_p scp = sca[unit];
130 * Check the unit makes sense.
132 if (unit > N${UPPER}) {
133 printf("bad unit (%d)\n", unit);
137 printf("unit %d already attached\n", unit);
142 * try see if the device is there.
144 val = inb (dev->id_iobase);
150 * ok, we got one we think
151 * do some further (this time possibly destructive) tests.
153 outb (dev->id_iobase, 0xff);
154 DELAY (10000); /* 10 ms delay */
155 val = inb (dev->id_iobase) & 0x0f;
156 return ((val & 0x0f) == 0x0f)? NUMPORTS : 0 ;
160 * Called if the probe succeeded.
161 * We can be destructive here as we know we have the device.
162 * we can also trust the unit number.
165 ${1}attach (struct isa_device *dev)
167 int unit = dev->id_unit;
168 sc_p scp = sca[unit];
171 * Attach our interrupt handler to the device struct. Our caller
172 * will attach it to the hardware soon after we return.
174 dev->id_ointr = ${1}intr;
177 * Allocate storage for this instance .
179 scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
181 printf("${1}%d failed to allocage driver strorage\n", unit);
184 bzero(scp, sizeof(*scp));
188 * Store whatever seems wise.
195 * Macro to check that the unit number is valid
196 * Often this isn't needed as once the open() is performed,
197 * the unit number is pretty much safe.. The exception would be if we
198 * implemented devices that could "go away". in which case all these routines
199 * would be wise to check the number, DIAGNOSTIC or not.
201 #define CHECKUNIT(RETVAL) \
202 do { /* the do-while is a safe way to do this grouping */ \
203 if (unit > N${UPPER}) { \
204 printf(__FUNCTION__ ":bad unit %d\n", unit); \
208 printf( __FUNCTION__ ": unit %d not attached\n", unit);\
213 #define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
214 #else /* DIAGNOSTIC */
215 #define CHECKUNIT_DIAG(RETVAL)
216 #endif /* DIAGNOSTIC */
221 sc_p scp = sca[unit];
224 * well we got an interupt, now what?
225 * Theoretically we don't need to check the unit.
230 int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
232 int unit = UNIT (dev);
233 sc_p scp = sca[unit];
235 CHECKUNIT_DIAG(ENXIO);
239 /* whatever resets it */
240 outb(scp->dev->id_iobase, 0xff);
248 * You also need read, write, open, close routines.
249 * This should get you started
252 ${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
254 int unit = UNIT (dev);
255 sc_p scp = sca[unit];
266 ${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
268 int unit = UNIT (dev);
269 sc_p scp = sca[unit];
271 CHECKUNIT_DIAG(ENXIO);
280 ${1}read(dev_t dev, struct uio *uio, int ioflag)
282 int unit = UNIT (dev);
283 sc_p scp = sca[unit];
287 CHECKUNIT_DIAG(ENXIO);
293 toread = (min(uio->uio_resid, sizeof(scp->buffer)));
294 return(uiomove(scp->buffer, toread, uio));
298 ${1}write(dev_t dev, struct uio *uio, int ioflag)
300 int unit = UNIT (dev);
301 sc_p scp = sca[unit];
304 CHECKUNIT_DIAG(ENXIO);
310 towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
311 return(uiomove(scp->buffer, towrite, uio));
315 ${1}mmap(dev_t dev, int offset, int nprot)
317 int unit = UNIT (dev);
318 sc_p scp = sca[unit];
325 #if 0 /* if we had a frame buffer or whatever.. do this */
326 if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
329 return i386_btop((FRAMEBASE + offset));
336 ${1}poll(dev_t dev, int which, struct proc *p)
338 int unit = UNIT (dev);
339 sc_p scp = sca[unit];
341 CHECKUNIT_DIAG(ENXIO);
346 return (0); /* this is the wrong value I'm sure */
349 #ifndef ${UPPER}_MODULE
352 * Now for some driver initialisation.
353 * Occurs ONCE during boot (very early).
354 * This is if we are NOT a loadable module.
357 ${1}_drvinit(void *unused)
361 dev = makedev(CDEV_MAJOR, 0);
362 cdevsw_add(&dev, &${1}_cdevsw, NULL);
365 SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
368 #else /* ${UPPER}_MODULE */
369 /* Here is the support for if we ARE a loadable kernel module */
371 #include <sys/exec.h>
372 #include <sys/sysent.h>
375 MOD_DEV (${1}, LM_DT_CHAR, CDEV_MAJOR, &${1}_cdevsw);
377 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};
380 ${1}_load (struct lkm_table *lkmtp, int cmd)
382 if (${1}probe (&dev)) {
384 uprintf ("${1} driver loaded\n");
385 uprintf ("${1}: interrupts not hooked\n");
388 uprintf ("${1} driver: probe failed\n");
394 ${1}_unload (struct lkm_table *lkmtp, int cmd)
396 uprintf ("${1} driver unloaded\n");
401 ${1}_stat (struct lkm_table *lkmtp, int cmd)
407 ${1}_mod (struct lkm_table *lkmtp, int cmd, int ver)
409 MOD_DISPATCH(${1}, lkmtp, cmd, ver,
410 ${1}_load, ${1}_unload, ${1}_stat);
413 #endif /* ${UPPER}_MODULE */
417 cat >../../sys/${1}io.h <<DONE
419 * Definitions needed to access the ${1} device (ioctls etc)
420 * see mtio.h , ioctl.h as examples
426 #include <sys/types.h>
428 #include <sys/ioccom.h>
431 * define an ioctl here
433 #define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
437 if [ -d /usr/src/lkm/${1} ]
439 cat >/usr/src/lkm/${1}/Makefile <<DONE
440 # ${UPPER} Loadable Kernel Module
442 # This happens not to work, actually. It's written for
443 # a character ISA device driver, but they cannot be
444 # be made into lkm's, because you have to hard code
445 # everything you'll otherwise enter into the kernel
446 # configuration file.
448 .PATH: \${.CURDIR}/../../sys/i386/isa
452 CFLAGS += -I. -D${UPPER}_MODULE
455 BASE_IO=0 # Base IO address
458 PHYS_IO=0 # Physical IO Memory base address
459 PHYS_IO_SIZE=0 # Physical IO Memory size
460 INT_INT=0 # Interrupt interface
463 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}
466 echo "#define N${UPPER} 1" > ${1}.h
469 \${INSTALL} -c -o \${BINOWN} -g \${BINGRP} -m \${BINMODE} \
470 \${.CURDIR}/${1} \${DESTDIR}/usr/bin
472 .include <bsd.kmod.mk>
477 cd ../../compile/${UPPER}
483 #--------------end of script---------------
485 #edit to your taste..