]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - share/examples/drivers/make_pseudo_driver.sh
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / share / examples / drivers / make_pseudo_driver.sh
1 #!/bin/sh
2 # This writes a skeleton driver and puts it into the kernel tree for you
3 #
4 # arg1 is lowercase "foo"
5 # arg2 path to the kernel sources, "/sys" if omitted
6 #
7 # Trust me, RUN THIS SCRIPT :)
8 #
9 # $FreeBSD$
10 #
11 #-------cut here------------------
12
13 if [ "${1}X" = "X" ]
14 then
15         echo "Hey , how about some help here.. give me a device name!"
16         exit 1
17 fi
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}
23 fi
24
25 for i in "" "conf" "i386" "i386/conf" "dev" "sys" "modules"
26 do
27         if [ -d ${TOP}/${i} ]
28         then
29                 continue
30         fi
31         echo "${TOP}/${i}: no such directory."
32         echo "Please, correct the error and try again."
33         exit 1
34 done
35
36 UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
37
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
44         fi
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
53                 ;;
54         *)
55                 exit 1
56                 ;;
57         esac
58 fi
59
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
69
70 mkdir ${TOP}/modules/${1}
71
72 cat >${TOP}/conf/files.${UPPER} <<DONE
73 dev/${1}/${1}.c      optional ${1}
74 DONE
75
76 cat >${TOP}/i386/conf/${UPPER} <<DONE
77 # Configuration file for kernel type: ${UPPER}
78 # \$FreeBSD\$
79
80 files           "${TOP}/conf/files.${UPPER}"
81
82 include         GENERIC
83
84 ident           ${UPPER}
85
86 # trust me, you'll need this
87 options         KDB
88 options         DDB
89 device          ${1}
90 DONE
91
92 if [ ! -d ${TOP}/dev/${1} ]; then
93         mkdir -p ${TOP}/dev/${1}
94 fi
95
96 cat >${TOP}/dev/${1}/${1}.c <<DONE
97 /*
98  * Copyright (c) [year] [your name]
99  * All rights reserved.
100  *
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.
109  *
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.
121  *
122  * ${1} driver
123  */
124
125 #include <sys/cdefs.h>
126 __FBSDID("\$FreeBSD\$");
127
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 */
136
137 #include <machine/clock.h>      /* DELAY() */
138
139 #define N${UPPER}       3       /* defines number of instances */
140
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))
144
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;
153
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}",
165 };
166
167 /*
168  * device  specific Misc defines
169  */
170 #define BUFFERSIZE 1024
171 #define UNIT(dev) dev2unit(dev) /* assume one minor number per unit */
172
173 /*
174  * One of these per allocated device
175  */
176 struct ${1}_softc {
177         u_long  iobase;
178         char    buffer[BUFFERSIZE];
179         struct cdev *dev;
180 };
181
182 typedef struct ${1}_softc *sc_p;
183
184 static sc_p sca[N${UPPER}];
185
186 /*
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.
192  */
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);                                        \
198         }                                                               \
199         if (scp == NULL) {                                              \
200                 printf("%s: unit %d not attached\n", __func__, unit);   \
201                 return (RETVAL);                                        \
202         }                                                               \
203 } while (0)
204
205 #ifdef  DIAGNOSTIC
206 #define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
207 #else   /* DIAGNOSTIC */
208 #define CHECKUNIT_DIAG(RETVAL)
209 #endif  /* DIAGNOSTIC */
210
211 static int
212 ${1}ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
213 {
214         int unit = UNIT(dev);
215         sc_p scp  = sca[unit];
216
217         CHECKUNIT_DIAG(ENXIO);
218
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;
229         }
230         return (0);
231 }
232
233 /*
234  * You also need read, write, open, close routines.
235  * This should get you started
236  */
237 static int
238 ${1}open(struct cdev *dev, int oflags, int devtype, struct thread *td)
239 {
240         int unit = UNIT(dev);
241         sc_p scp  = sca[unit];
242
243         CHECKUNIT(ENXIO);
244
245         (void)scp; /* Delete this line after using scp. */
246         /*
247          * Do processing
248          */
249         return (0);
250 }
251
252 static int
253 ${1}close(struct cdev *dev, int fflag, int devtype, struct thread *td)
254 {
255         int unit = UNIT(dev);
256         sc_p scp  = sca[unit];
257
258         CHECKUNIT_DIAG(ENXIO);
259
260         (void)scp; /* Delete this line after using scp. */
261         /*
262          * Do processing
263          */
264         return (0);
265 }
266
267 static int
268 ${1}read(struct cdev *dev, struct uio *uio, int ioflag)
269 {
270         int unit = UNIT(dev);
271         sc_p scp  = sca[unit];
272         int     toread;
273
274
275         CHECKUNIT_DIAG(ENXIO);
276
277         /*
278          * Do processing
279          * read from buffer
280          */
281         toread = (min(uio->uio_resid, sizeof(scp->buffer)));
282         return(uiomove(scp->buffer, toread, uio));
283 }
284
285 static int
286 ${1}write(struct cdev *dev, struct uio *uio, int ioflag)
287 {
288         int unit = UNIT(dev);
289         sc_p scp  = sca[unit];
290         int     towrite;
291
292         CHECKUNIT_DIAG(ENXIO);
293
294         /*
295          * Do processing
296          * write to buffer
297          */
298         towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
299         return(uiomove(scp->buffer, towrite, uio));
300 }
301
302 static int
303 ${1}mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
304 {
305         int unit = UNIT(dev);
306         sc_p scp  = sca[unit];
307
308         CHECKUNIT_DIAG(-1);
309
310         (void)scp; /* Delete this line after using scp. */
311         /*
312          * Do processing
313          */
314 #if 0   /* if we had a frame buffer or whatever.. do this */
315         if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
316                 return (-1);
317         }
318         return i386_btop((FRAMEBASE + offset));
319 #else
320         return (-1);
321 #endif
322 }
323
324 static int
325 ${1}poll(struct cdev *dev, int which, struct thread *td)
326 {
327         int unit = UNIT(dev);
328         sc_p scp  = sca[unit];
329
330         CHECKUNIT_DIAG(ENXIO);
331
332         (void)scp; /* Delete this line after using scp. */
333         /*
334          * Do processing
335          */
336         return (0); /* this is the wrong value I'm sure */
337 }
338
339 /*
340  * Now  for some driver initialisation.
341  * Occurs ONCE during boot (very early).
342  */
343 static void
344 ${1}_drvinit(void *unused)
345 {
346         int     unit;
347         sc_p    scp;
348
349         for (unit = 0; unit < N${UPPER}; unit++) {
350                 /*
351                  * Allocate storage for this instance .
352                  */
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;
357                 }
358                 sca[unit] = scp;
359                 scp->dev = make_dev(&${1}_cdevsw, unit,
360                         UID_ROOT, GID_KMEM, 0640, "${1}%d", unit);
361         }
362 }
363
364 SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
365                 ${1}_drvinit, NULL);
366 DONE
367
368 cat >${TOP}/sys/${1}io.h <<DONE
369 /*
370  * Definitions needed to access the ${1} device (ioctls etc)
371  * see mtio.h , ioctl.h as examples
372  */
373 #ifndef SYS_DHIO_H
374 #define SYS_DHIO_H
375
376 #ifndef KERNEL
377 #include <sys/types.h>
378 #endif
379 #include <sys/ioccom.h>
380
381 /*
382  * define an ioctl here
383  */
384 #define DHIOCRESET _IO('D', 0)   /* reset the ${1} device */
385 #endif
386 DONE
387
388 if [ ! -d ${TOP}/modules/${1} ]; then
389         mkdir -p ${TOP}/modules/${1}
390 fi
391
392 cat >${TOP}/modules/${1}/Makefile <<DONE
393 #       ${UPPER} Loadable Kernel Module
394 #
395 # \$FreeBSD\$
396
397 .PATH:  \${.CURDIR}/../../dev/${1}
398 KMOD    = ${1}
399 SRCS    = ${1}.c
400
401 .include <bsd.kmod.mk>
402 DONE
403
404 echo -n "Do you want to build the '${1}' module? [Y]"
405 read VAL
406 if [ "-z" "$VAL" ]; then
407         VAL=YES
408 fi
409 case ${VAL} in
410 [yY]*)
411         (cd ${TOP}/modules/${1}; make depend; make )
412         ;;
413 *)
414 #       exit
415         ;;
416 esac
417
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
423 fi
424 case ${VAL} in
425 [yY]*)
426         (
427          cd ${TOP}/i386/conf; \
428          config ${UPPER}; \
429          cd ${TOP}/i386/compile/${UPPER}; \
430          make depend; \
431          make; \
432         )
433         ;;
434 *)
435 #       exit
436         ;;
437 esac
438
439 #--------------end of script---------------
440 #
441 #edit to your taste..
442 #
443 #