Ignore machine-check MSRs
[freebsd-src/fkvm-freebsd.git] / share / examples / drivers / make_pseudo_driver.sh
bloba7d49ac1df8acf0eb718d87ec8eb4c97870ab414
1 #!/bin/sh
2 # This writes a skeleton driver and puts it into the kernel tree for you
4 # arg1 is lowercase "foo"
5 # arg2 path to the kernel sources, "/sys" if omitted
7 # Trust me, RUN THIS SCRIPT :)
9 # $FreeBSD$
11 #-------cut here------------------
13 if [ "${1}X" = "X" ]
14 then
15 echo "Hey , how about some help here.. give me a device name!"
16 exit 1
18 if [ "X${2}" = "X" ]; then
19 TOP=`cd /sys; pwd -P`
20 echo "Using ${TOP} as the path to the kernel sources!"
21 else
22 TOP=${2}
25 for i in "" "conf" "i386" "i386/conf" "dev" "sys" "modules"
27 if [ -d ${TOP}/${i} ]
28 then
29 continue
31 echo "${TOP}/${i}: no such directory."
32 echo "Please, correct the error and try again."
33 exit 1
34 done
36 UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
38 if [ -d ${TOP}/modules/${1} ]; then
39 echo "There appears to already be a module called ${1}"
40 echo -n "Should it be overwritten? [Y]"
41 read VAL
42 if [ "-z" "$VAL" ]; then
43 VAL=YES
45 case ${VAL} in
46 [yY]*)
47 echo "Cleaning up from prior runs"
48 rm -rf ${TOP}/dev/${1}
49 rm -rf ${TOP}/modules/${1}
50 rm ${TOP}/conf/files.${UPPER}
51 rm ${TOP}/i386/conf/${UPPER}
52 rm ${TOP}/sys/${1}io.h
55 exit 1
57 esac
60 echo "The following files will be created:"
61 echo ${TOP}/modules/${1}
62 echo ${TOP}/conf/files.${UPPER}
63 echo ${TOP}/i386/conf/${UPPER}
64 echo ${TOP}/dev/${1}
65 echo ${TOP}/dev/${1}/${1}.c
66 echo ${TOP}/sys/${1}io.h
67 echo ${TOP}/modules/${1}
68 echo ${TOP}/modules/${1}/Makefile
70 mkdir ${TOP}/modules/${1}
72 cat >${TOP}/conf/files.${UPPER} <<DONE
73 dev/${1}/${1}.c optional ${1}
74 DONE
76 cat >${TOP}/i386/conf/${UPPER} <<DONE
77 # Configuration file for kernel type: ${UPPER}
78 # \$FreeBSD\$
80 files "${TOP}/conf/files.${UPPER}"
82 include GENERIC
84 ident ${UPPER}
86 # trust me, you'll need this
87 options KDB
88 options DDB
89 device ${1}
90 DONE
92 if [ ! -d ${TOP}/dev/${1} ]; then
93 mkdir -p ${TOP}/dev/${1}
96 cat >${TOP}/dev/${1}/${1}.c <<DONE
98 * Copyright (c) [year] [your name]
99 * All rights reserved.
101 * Redistribution and use in source and binary forms, with or without
102 * modification, are permitted provided that the following conditions
103 * are met:
104 * 1. Redistributions of source code must retain the above copyright
105 * notice, this list of conditions and the following disclaimer.
106 * 2. Redistributions in binary form must reproduce the above copyright
107 * notice, this list of conditions and the following disclaimer in the
108 * documentation and/or other materials provided with the distribution.
110 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
111 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
112 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
113 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
114 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
115 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
116 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
117 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
118 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
119 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
120 * SUCH DAMAGE.
122 * ${1} driver
125 #include <sys/cdefs.h>
126 __FBSDID("\$FreeBSD\$");
128 #include <sys/param.h>
129 #include <sys/systm.h>
130 #include <sys/kernel.h> /* SYSINIT stuff */
131 #include <sys/uio.h> /* SYSINIT stuff */
132 #include <sys/conf.h> /* cdevsw stuff */
133 #include <sys/malloc.h> /* malloc region definitions */
134 #include <sys/proc.h>
135 #include <sys/${1}io.h> /* ${1} IOCTL definitions */
137 #include <machine/clock.h> /* DELAY() */
139 #define N${UPPER} 3 /* defines number of instances */
141 /* XXX These should be defined in terms of bus-space ops. */
142 #define ${UPPER}_INB(port) inb(port)
143 #define ${UPPER}_OUTB(port, val) (port, (val))
145 /* Function prototypes (these should all be static) */
146 static d_open_t ${1}open;
147 static d_close_t ${1}close;
148 static d_read_t ${1}read;
149 static d_write_t ${1}write;
150 static d_ioctl_t ${1}ioctl;
151 static d_mmap_t ${1}mmap;
152 static d_poll_t ${1}poll;
154 #define CDEV_MAJOR 20
155 static struct cdevsw ${1}_cdevsw = {
156 .d_version = D_VERSION,
157 .d_open = ${1}open,
158 .d_close = ${1}close,
159 .d_read = ${1}read,
160 .d_write = ${1}write,
161 .d_ioctl = ${1}ioctl,
162 .d_poll = ${1}poll,
163 .d_mmap = ${1}mmap,
164 .d_name = "${1}",
168 * device specific Misc defines
170 #define BUFFERSIZE 1024
171 #define UNIT(dev) minor(dev) /* assume one minor number per unit */
174 * One of these per allocated device
176 struct ${1}_softc {
177 u_long iobase;
178 char buffer[BUFFERSIZE];
179 struct cdev *dev;
182 typedef struct ${1}_softc *sc_p;
184 static sc_p sca[N${UPPER}];
187 * Macro to check that the unit number is valid
188 * Often this isn't needed as once the open() is performed,
189 * the unit number is pretty much safe.. The exception would be if we
190 * implemented devices that could "go away". in which case all these routines
191 * would be wise to check the number, DIAGNOSTIC or not.
193 #define CHECKUNIT(RETVAL) \
194 do { /* the do-while is a safe way to do this grouping */ \
195 if (unit > N${UPPER}) { \
196 printf("%s: bad unit %d\n", __func__, unit); \
197 return (RETVAL); \
199 if (scp == NULL) { \
200 printf("%s: unit %d not attached\n", __func__, unit); \
201 return (RETVAL); \
203 } while (0)
205 #ifdef DIAGNOSTIC
206 #define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
207 #else /* DIAGNOSTIC */
208 #define CHECKUNIT_DIAG(RETVAL)
209 #endif /* DIAGNOSTIC */
211 static int
212 ${1}ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
214 int unit = UNIT(dev);
215 sc_p scp = sca[unit];
217 CHECKUNIT_DIAG(ENXIO);
219 switch (cmd) {
220 case DHIOCRESET:
221 /* whatever resets it */
222 (void)scp; /* Delete this line after using scp. */
223 #if 0
224 ${UPPER}_OUTB(scp->iobase, 0xff);
225 #endif
226 break;
227 default:
228 return ENXIO;
230 return (0);
234 * You also need read, write, open, close routines.
235 * This should get you started
237 static int
238 ${1}open(struct cdev *dev, int oflags, int devtype, struct thread *td)
240 int unit = UNIT(dev);
241 sc_p scp = sca[unit];
243 CHECKUNIT(ENXIO);
245 (void)scp; /* Delete this line after using scp. */
247 * Do processing
249 return (0);
252 static int
253 ${1}close(struct cdev *dev, int fflag, int devtype, struct thread *td)
255 int unit = UNIT(dev);
256 sc_p scp = sca[unit];
258 CHECKUNIT_DIAG(ENXIO);
260 (void)scp; /* Delete this line after using scp. */
262 * Do processing
264 return (0);
267 static int
268 ${1}read(struct cdev *dev, struct uio *uio, int ioflag)
270 int unit = UNIT(dev);
271 sc_p scp = sca[unit];
272 int toread;
275 CHECKUNIT_DIAG(ENXIO);
278 * Do processing
279 * read from buffer
281 toread = (min(uio->uio_resid, sizeof(scp->buffer)));
282 return(uiomove(scp->buffer, toread, uio));
285 static int
286 ${1}write(struct cdev *dev, struct uio *uio, int ioflag)
288 int unit = UNIT(dev);
289 sc_p scp = sca[unit];
290 int towrite;
292 CHECKUNIT_DIAG(ENXIO);
295 * Do processing
296 * write to buffer
298 towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
299 return(uiomove(scp->buffer, towrite, uio));
302 static int
303 ${1}mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
305 int unit = UNIT(dev);
306 sc_p scp = sca[unit];
308 CHECKUNIT_DIAG(-1);
310 (void)scp; /* Delete this line after using scp. */
312 * Do processing
314 #if 0 /* if we had a frame buffer or whatever.. do this */
315 if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
316 return (-1);
318 return i386_btop((FRAMEBASE + offset));
319 #else
320 return (-1);
321 #endif
324 static int
325 ${1}poll(struct cdev *dev, int which, struct thread *td)
327 int unit = UNIT(dev);
328 sc_p scp = sca[unit];
330 CHECKUNIT_DIAG(ENXIO);
332 (void)scp; /* Delete this line after using scp. */
334 * Do processing
336 return (0); /* this is the wrong value I'm sure */
340 * Now for some driver initialisation.
341 * Occurs ONCE during boot (very early).
343 static void
344 ${1}_drvinit(void *unused)
346 int unit;
347 sc_p scp = sca[unit];
349 for (unit = 0; unit < N${UPPER}; unit++) {
351 * Allocate storage for this instance .
353 scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT | M_ZERO);
354 if( scp == NULL) {
355 printf("${1}%d failed to allocate strorage\n", unit);
356 return;
358 sca[unit] = scp;
359 scp->dev = make_dev(&${1}_cdevsw, unit,
360 UID_ROOT, GID_KMEM, 0640, "${1}%d", unit);
364 SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
365 ${1}_drvinit, NULL)
366 DONE
368 cat >${TOP}/sys/${1}io.h <<DONE
370 * Definitions needed to access the ${1} device (ioctls etc)
371 * see mtio.h , ioctl.h as examples
373 #ifndef SYS_DHIO_H
374 #define SYS_DHIO_H
376 #ifndef KERNEL
377 #include <sys/types.h>
378 #endif
379 #include <sys/ioccom.h>
382 * define an ioctl here
384 #define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
385 #endif
386 DONE
388 if [ ! -d ${TOP}/modules/${1} ]; then
389 mkdir -p ${TOP}/modules/${1}
392 cat >${TOP}/modules/${1}/Makefile <<DONE
393 # ${UPPER} Loadable Kernel Module
395 # \$FreeBSD\$
397 .PATH: \${.CURDIR}/../../dev/${1}
398 KMOD = ${1}
399 SRCS = ${1}.c
401 .include <bsd.kmod.mk>
402 DONE
404 echo -n "Do you want to build the '${1}' module? [Y]"
405 read VAL
406 if [ "-z" "$VAL" ]; then
407 VAL=YES
409 case ${VAL} in
410 [yY]*)
411 (cd ${TOP}/modules/${1}; make depend; make )
414 # exit
416 esac
418 echo ""
419 echo -n "Do you want to build the '${UPPER}' kernel? [Y]"
420 read VAL
421 if [ "-z" "$VAL" ]; then
422 VAL=YES
424 case ${VAL} in
425 [yY]*)
427 cd ${TOP}/i386/conf; \
428 config ${UPPER}; \
429 cd ${TOP}/i386/compile/${UPPER}; \
430 make depend; \
431 make; \
435 # exit
437 esac
439 #--------------end of script---------------
441 #edit to your taste..