systat - Filter out non-useful devices by default
[dragonfly.git] / share / examples / drivers / make_device_driver.sh
blob8a4614cbecd725cbc147b7a4948e2e2f9e94b811
1 #!/bin/sh
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------------------
11 cd /sys/config
13 if [ "${1}X" = "X" ]
14 then
15 echo "Hey , how about some help here.. give me a device name!"
16 exit 1
19 if [ -d /usr/src/lkm ]
20 then
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
27 DONE
29 cat >${UPPER} <<DONE
30 # Configuration file for kernel type: ${UPPER}
31 ident ${UPPER}
32 DONE
34 grep -v X86_64_GENERIC < X86_64_GENERIC >>${UPPER}
36 cat >>${UPPER} <<DONE
37 # trust me, you'll need this
38 options DDB
39 device ${1}0 at isa? port 0x234 bio irq 5
40 DONE
42 cat >../isa/${1}.c <<DONE
44 * Copyright ME
46 * ${1} driver
50 #include "${1}.h" /* generated file.. defines N${UPPER} */
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/kernel.h> /* SYSINIT stuff */
54 #include <sys/conf.h> /* cdevsw stuff */
55 #include <sys/malloc.h> /* malloc region definitions */
56 #include <machine/clock.h> /* DELAY() */
57 #include <i386/isa/isa.h> /* ISA bus port definitions etc. */
58 #include <i386/isa/isa_device.h>/* ISA bus configuration structures */
59 #include <sys/${1}io.h> /* ${1} IOCTL definitions */
63 /* Function prototypes (these should all be static) */
64 static d_open_t ${1}open;
65 static d_close_t ${1}close;
66 static d_read_t ${1}read;
67 static d_write_t ${1}write;
68 static d_ioctl_t ${1}ioctl;
69 static d_mmap_t ${1}mmap;
70 static d_poll_t ${1}poll;
71 static int ${1}probe (struct isa_device *);
72 static int ${1}attach (struct isa_device *);
73 #ifdef ${UPPER}_MODULE
74 static ointhand2_t ${1}intr; /* should actually have type inthand2_t */
75 #endif
77 #define CDEV_MAJOR 20
78 static struct cdevsw ${1}_cdevsw = {
79 ${1}open,
80 ${1}close,
81 ${1}read,
82 ${1}write,
83 ${1}ioctl,
84 nullstop,
85 nullreset,
86 nodevtotty,
87 ${1}poll,
88 ${1}mmap,
89 NULL,
90 "${1}",
91 NULL,
92 -1 };
94 struct isa_driver ${1}driver = {
95 ${1}probe,
96 ${1}attach,
97 "${1}" };
99 /*
100 * device specific Misc defines
102 #define BUFFERSIZE 1024
103 #define NUMPORTS 4
104 #define UNIT(dev) minor(dev) /* assume one minor number per unit */
107 * One of these per allocated device
109 struct ${1}_softc {
110 struct isa_device *dev;
111 char buffer[BUFFERSIZE];
114 typedef struct ${1}_softc *sc_p;
116 static sc_p sca[N${UPPER}];
118 /* add your own test to see if it exists */
119 /* should return the number of ports needed */
120 static int
121 ${1}probe (struct isa_device *dev)
123 char val;
124 int unit = dev->id_unit;
125 sc_p scp = sca[unit];
128 * Check the unit makes sense.
130 if (unit > N${UPPER}) {
131 printf("bad unit (%d)\n", unit);
132 return (0);
134 if (scp) {
135 printf("unit %d already attached\n", unit);
136 return (0);
140 * try see if the device is there.
142 val = inb (dev->id_iobase);
143 if ( val != 42 ) {
144 return (0);
148 * ok, we got one we think
149 * do some further (this time possibly destructive) tests.
151 outb (dev->id_iobase, 0xff);
152 DELAY (10000); /* 10 ms delay */
153 val = inb (dev->id_iobase) & 0x0f;
154 return ((val & 0x0f) == 0x0f)? NUMPORTS : 0 ;
158 * Called if the probe succeeded.
159 * We can be destructive here as we know we have the device.
160 * we can also trust the unit number.
162 static int
163 ${1}attach (struct isa_device *dev)
165 int unit = dev->id_unit;
166 sc_p scp = sca[unit];
169 * Attach our interrupt handler to the device struct. Our caller
170 * will attach it to the hardware soon after we return.
172 dev->id_ointr = ${1}intr;
175 * Allocate storage for this instance .
177 scp = kmalloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
178 if( scp == NULL) {
179 printf("${1}%d failed to allocage driver strorage\n", unit);
180 return (0);
182 bzero(scp, sizeof(*scp));
183 sca[unit] = scp;
186 * Store whatever seems wise.
188 scp->dev = dev;
189 return 1;
193 * Macro to check that the unit number is valid
194 * Often this isn't needed as once the open() is performed,
195 * the unit number is pretty much safe.. The exception would be if we
196 * implemented devices that could "go away". in which case all these routines
197 * would be wise to check the number, DIAGNOSTIC or not.
199 #define CHECKUNIT(RETVAL) \
200 do { /* the do-while is a safe way to do this grouping */ \
201 if (unit > N${UPPER}) { \
202 printf("%s:bad unit %d\n", __func__, unit); \
203 return (RETVAL); \
205 if (scp == NULL) { \
206 printf( "%s: unit %d not attached\n", __func__, unit);\
207 return (RETVAL); \
209 } while (0)
210 #ifdef DIAGNOSTIC
211 #define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
212 #else /* DIAGNOSTIC */
213 #define CHECKUNIT_DIAG(RETVAL)
214 #endif /* DIAGNOSTIC */
216 static void
217 ${1}intr(int unit)
219 sc_p scp = sca[unit];
222 * well we got an interrupt, now what?
223 * Theoretically we don't need to check the unit.
225 return;
228 int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
230 int unit = UNIT (dev);
231 sc_p scp = sca[unit];
233 CHECKUNIT_DIAG(ENXIO);
235 switch (cmd) {
236 case DHIOCRESET:
237 /* whatever resets it */
238 outb(scp->dev->id_iobase, 0xff);
239 break;
240 default:
241 return ENXIO;
243 return (0);
246 * You also need read, write, open, close routines.
247 * This should get you started
249 static int
250 ${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
252 int unit = UNIT (dev);
253 sc_p scp = sca[unit];
255 CHECKUNIT(ENXIO);
258 * Do processing
260 return (0);
263 static int
264 ${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
266 int unit = UNIT (dev);
267 sc_p scp = sca[unit];
269 CHECKUNIT_DIAG(ENXIO);
272 * Do processing
274 return (0);
277 static int
278 ${1}read(dev_t dev, struct uio *uio, int ioflag)
280 int unit = UNIT (dev);
281 sc_p scp = sca[unit];
282 int toread;
285 CHECKUNIT_DIAG(ENXIO);
288 * Do processing
289 * read from buffer
291 toread = (min(uio->uio_resid, sizeof(scp->buffer)));
292 return(uiomove(scp->buffer, toread, uio));
295 static int
296 ${1}write(dev_t dev, struct uio *uio, int ioflag)
298 int unit = UNIT (dev);
299 sc_p scp = sca[unit];
300 int towrite;
302 CHECKUNIT_DIAG(ENXIO);
305 * Do processing
306 * write to buffer
308 towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
309 return(uiomove(scp->buffer, towrite, uio));
312 static int
313 ${1}mmap(dev_t dev, int offset, int nprot)
315 int unit = UNIT (dev);
316 sc_p scp = sca[unit];
318 CHECKUNIT_DIAG(-1);
321 * Do processing
323 #if 0 /* if we had a frame buffer or whatever.. do this */
324 if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
325 return (-1);
327 return i386_btop((FRAMEBASE + offset));
328 #else
329 return (-1);
330 #endif
333 static int
334 ${1}poll(dev_t dev, int which, struct proc *p)
336 int unit = UNIT (dev);
337 sc_p scp = sca[unit];
339 CHECKUNIT_DIAG(ENXIO);
342 * Do processing
344 return (0); /* this is the wrong value I'm sure */
347 #ifndef ${UPPER}_MODULE
350 * Now for some driver initialisation.
351 * Occurs ONCE during boot (very early).
352 * This is if we are NOT a loadable module.
354 static void
355 ${1}_drvinit(void *unused)
357 dev_t dev;
359 dev = makedev(CDEV_MAJOR, 0);
360 cdevsw_add(&dev, &${1}_cdevsw, NULL);
363 SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
364 ${1}_drvinit, NULL)
366 #else /* ${UPPER}_MODULE */
367 /* Here is the support for if we ARE a loadable kernel module */
369 #include <sys/exec.h>
370 #include <sys/sysent.h>
371 #include <sys/lkm.h>
373 MOD_DEV (${1}, LM_DT_CHAR, CDEV_MAJOR, &${1}_cdevsw);
375 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};
377 static int
378 ${1}_load (struct lkm_table *lkmtp, int cmd)
380 if (${1}probe (&dev)) {
381 ${1}attach (&dev);
382 uprintf ("${1} driver loaded\n");
383 uprintf ("${1}: interrupts not hooked\n");
384 return 0;
385 } else {
386 uprintf ("${1} driver: probe failed\n");
387 return 1;
391 static int
392 ${1}_unload (struct lkm_table *lkmtp, int cmd)
394 uprintf ("${1} driver unloaded\n");
395 return 0;
398 static int
399 ${1}_stat (struct lkm_table *lkmtp, int cmd)
401 return 0;
405 ${1}_mod (struct lkm_table *lkmtp, int cmd, int ver)
407 MOD_DISPATCH(${1}, lkmtp, cmd, ver,
408 ${1}_load, ${1}_unload, ${1}_stat);
411 #endif /* ${UPPER}_MODULE */
413 DONE
415 cat >../../sys/${1}io.h <<DONE
417 * Definitions needed to access the ${1} device (ioctls etc)
418 * see mtio.h , ioctl.h as examples
420 #ifndef SYS_DHIO_H
421 #define SYS_DHIO_H
423 #ifndef KERNEL
424 #include <sys/types.h>
425 #endif
426 #include <sys/ioccom.h>
429 * define an ioctl here
431 #define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
432 #endif
433 DONE
435 if [ -d /usr/src/lkm/${1} ]
436 then
437 cat >/usr/src/lkm/${1}/Makefile <<DONE
438 # ${UPPER} Loadable Kernel Module
440 # This happens not to work, actually. It's written for
441 # a character ISA device driver, but they cannot be
442 # be made into lkm's, because you have to hard code
443 # everything you'll otherwise enter into the kernel
444 # configuration file.
446 .PATH: \${.CURDIR}/../../sys/arch/i386/isa
447 KMOD = ${1}_mod
448 SRCS = ${1}.c ${1}.h
450 CFLAGS += -I. -D${UPPER}_MODULE
451 CLEANFILES += ${1}.h
453 BASE_IO=0 # Base IO address
454 IRQ=0 # IRQ number
455 DMA=-1 # DMA channel
456 PHYS_IO=0 # Physical IO Memory base address
457 PHYS_IO_SIZE=0 # Physical IO Memory size
458 INT_INT=0 # Interrupt interface
459 FLAGS=0 # Flags
461 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}
463 ${1}.h:
464 echo "#define N${UPPER} 1" > ${1}.h
466 afterinstall:
467 \${INSTALL} -c -o \${BINOWN} -g \${BINGRP} -m \${BINMODE} \
468 \${.CURDIR}/${1} \${DESTDIR}/usr/bin
470 .include <bsd.kmod.mk>
471 DONE
474 config ${UPPER}
475 cd ../../compile/${UPPER}
476 make depend
477 make ${1}.o
478 make
479 exit
481 #--------------end of script---------------
483 #edit to your taste..