Adjust the ${ISODIR}/.didbootstrap logic a little, add needed licenses.
[dragonfly.git] / share / examples / drivers / make_device_driver.sh
blobc2535d937e0ea3e8eaebfbf5d91f7860d836fd05
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 # \$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 $"
34 DONE
36 grep -v GENERIC < GENERIC >>${UPPER}
38 cat >>${UPPER} <<DONE
39 # trust me, you'll need this
40 options DDB
41 device ${1}0 at isa? port 0x234 bio irq 5
42 DONE
44 cat >../isa/${1}.c <<DONE
46 * Copyright ME
48 * ${1} driver
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 */
78 #endif
80 #define CDEV_MAJOR 20
81 static struct cdevsw ${1}_cdevsw = {
82 ${1}open,
83 ${1}close,
84 ${1}read,
85 ${1}write,
86 ${1}ioctl,
87 nullstop,
88 nullreset,
89 nodevtotty,
90 ${1}poll,
91 ${1}mmap,
92 NULL,
93 "${1}",
94 NULL,
95 -1 };
97 struct isa_driver ${1}driver = {
98 ${1}probe,
99 ${1}attach,
100 "${1}" };
103 * device specific Misc defines
105 #define BUFFERSIZE 1024
106 #define NUMPORTS 4
107 #define UNIT(dev) minor(dev) /* assume one minor number per unit */
110 * One of these per allocated device
112 struct ${1}_softc {
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 */
123 static int
124 ${1}probe (struct isa_device *dev)
126 char val;
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);
135 return (0);
137 if (scp) {
138 printf("unit %d already attached\n", unit);
139 return (0);
143 * try see if the device is there.
145 val = inb (dev->id_iobase);
146 if ( val != 42 ) {
147 return (0);
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.
165 static int
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);
181 if( scp == NULL) {
182 printf("${1}%d failed to allocage driver strorage\n", unit);
183 return (0);
185 bzero(scp, sizeof(*scp));
186 sca[unit] = scp;
189 * Store whatever seems wise.
191 scp->dev = dev;
192 return 1;
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); \
206 return (RETVAL); \
208 if (scp == NULL) { \
209 printf( "%s: unit %d not attached\n", __func__, unit);\
210 return (RETVAL); \
212 } while (0)
213 #ifdef DIAGNOSTIC
214 #define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
215 #else /* DIAGNOSTIC */
216 #define CHECKUNIT_DIAG(RETVAL)
217 #endif /* DIAGNOSTIC */
219 static void
220 ${1}intr(int unit)
222 sc_p scp = sca[unit];
225 * well we got an interrupt, now what?
226 * Theoretically we don't need to check the unit.
228 return;
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);
238 switch (cmd) {
239 case DHIOCRESET:
240 /* whatever resets it */
241 outb(scp->dev->id_iobase, 0xff);
242 break;
243 default:
244 return ENXIO;
246 return (0);
249 * You also need read, write, open, close routines.
250 * This should get you started
252 static int
253 ${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
255 int unit = UNIT (dev);
256 sc_p scp = sca[unit];
258 CHECKUNIT(ENXIO);
261 * Do processing
263 return (0);
266 static int
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);
275 * Do processing
277 return (0);
280 static int
281 ${1}read(dev_t dev, struct uio *uio, int ioflag)
283 int unit = UNIT (dev);
284 sc_p scp = sca[unit];
285 int toread;
288 CHECKUNIT_DIAG(ENXIO);
291 * Do processing
292 * read from buffer
294 toread = (min(uio->uio_resid, sizeof(scp->buffer)));
295 return(uiomove(scp->buffer, toread, uio));
298 static int
299 ${1}write(dev_t dev, struct uio *uio, int ioflag)
301 int unit = UNIT (dev);
302 sc_p scp = sca[unit];
303 int towrite;
305 CHECKUNIT_DIAG(ENXIO);
308 * Do processing
309 * write to buffer
311 towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
312 return(uiomove(scp->buffer, towrite, uio));
315 static int
316 ${1}mmap(dev_t dev, int offset, int nprot)
318 int unit = UNIT (dev);
319 sc_p scp = sca[unit];
321 CHECKUNIT_DIAG(-1);
324 * Do processing
326 #if 0 /* if we had a frame buffer or whatever.. do this */
327 if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
328 return (-1);
330 return i386_btop((FRAMEBASE + offset));
331 #else
332 return (-1);
333 #endif
336 static int
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);
345 * Do processing
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.
357 static void
358 ${1}_drvinit(void *unused)
360 dev_t dev;
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,
367 ${1}_drvinit, NULL)
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>
374 #include <sys/lkm.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};
380 static int
381 ${1}_load (struct lkm_table *lkmtp, int cmd)
383 if (${1}probe (&dev)) {
384 ${1}attach (&dev);
385 uprintf ("${1} driver loaded\n");
386 uprintf ("${1}: interrupts not hooked\n");
387 return 0;
388 } else {
389 uprintf ("${1} driver: probe failed\n");
390 return 1;
394 static int
395 ${1}_unload (struct lkm_table *lkmtp, int cmd)
397 uprintf ("${1} driver unloaded\n");
398 return 0;
401 static int
402 ${1}_stat (struct lkm_table *lkmtp, int cmd)
404 return 0;
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 */
416 DONE
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
423 #ifndef SYS_DHIO_H
424 #define SYS_DHIO_H
426 #ifndef KERNEL
427 #include <sys/types.h>
428 #endif
429 #include <sys/ioccom.h>
432 * define an ioctl here
434 #define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
435 #endif
436 DONE
438 if [ -d /usr/src/lkm/${1} ]
439 then
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
450 KMOD = ${1}_mod
451 SRCS = ${1}.c ${1}.h
453 CFLAGS += -I. -D${UPPER}_MODULE
454 CLEANFILES += ${1}.h
456 BASE_IO=0 # Base IO address
457 IRQ=0 # IRQ number
458 DMA=-1 # DMA channel
459 PHYS_IO=0 # Physical IO Memory base address
460 PHYS_IO_SIZE=0 # Physical IO Memory size
461 INT_INT=0 # Interrupt interface
462 FLAGS=0 # Flags
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}
466 ${1}.h:
467 echo "#define N${UPPER} 1" > ${1}.h
469 afterinstall:
470 \${INSTALL} -c -o \${BINOWN} -g \${BINGRP} -m \${BINMODE} \
471 \${.CURDIR}/${1} \${DESTDIR}/usr/bin
473 .include <bsd.kmod.mk>
474 DONE
477 config ${UPPER}
478 cd ../../compile/${UPPER}
479 make depend
480 make ${1}.o
481 make
482 exit
484 #--------------end of script---------------
486 #edit to your taste..