Add a cvsup example to track the 1.4 release.
[dragonfly.git] / share / examples / drivers / make_device_driver.sh
1 #!/bin/sh 
2 # This writes a skeleton driver and puts it into the kernel tree for you
3 #arg1 is lowercase "foo" 
4 #
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.
7 #
8 # Trust me, RUN THIS SCRIPT :)
9 #
10 #-------cut here------------------
11 cd /sys/i386/conf
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
19 if [ -d /usr/src/lkm ]
20 then
21         mkdir /usr/src/lkm/${1}
22 fi
23
24 UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"` 
25 cat >files.${UPPER} <<DONE
26 i386/isa/${1}.c      optional ${1} device-driver
27 DONE
28
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.3 2005/02/17 13:59:35 joerg Exp $"
34 DONE
35
36 grep -v GENERIC < GENERIC >>${UPPER}
37
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
43
44 cat >../isa/${1}.c <<DONE
45 /*
46  * Copyright ME
47  *
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 $
50  */
51
52
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 */
63
64
65
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
79  
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 };
96  
97 struct isa_driver ${1}driver = {
98         ${1}probe,
99         ${1}attach,
100         "${1}" };
101
102 /* 
103  * device  specific Misc defines 
104  */
105 #define BUFFERSIZE 1024
106 #define NUMPORTS 4
107 #define UNIT(dev) minor(dev)    /* assume one minor number per unit */
108
109 /*
110  * One of these per allocated device
111  */
112 struct ${1}_softc {
113         struct isa_device *dev;
114         char    buffer[BUFFERSIZE];
115 } ;
116
117 typedef struct ${1}_softc *sc_p;
118
119 static sc_p sca[N${UPPER}];
120
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)
125 {
126         char val;
127         int unit = dev->id_unit;
128         sc_p scp  = sca[unit];
129
130         /*
131          * Check the unit makes sense.
132          */
133         if (unit > N${UPPER}) {
134                 printf("bad unit (%d)\n", unit);
135                 return (0);
136         }
137         if (scp) {
138                 printf("unit %d already attached\n", unit);
139                 return (0);
140         }
141
142         /*
143          * try see if the device is there.
144          */
145         val = inb (dev->id_iobase);
146         if ( val != 42 ) {
147                 return (0);
148         }
149
150         /*
151          * ok, we got one we think 
152          * do some further (this time possibly destructive) tests.
153          */
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 ;
158 }
159
160 /*
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.
164  */
165 static int
166 ${1}attach (struct isa_device *dev)
167 {
168         int unit = dev->id_unit;
169         sc_p scp  = sca[unit];
170
171         /*
172          * Attach our interrupt handler to the device struct.  Our caller
173          * will attach it to the hardware soon after we return.
174          */
175         dev->id_ointr = ${1}intr;
176
177         /* 
178          * Allocate storage for this instance .
179          */
180         scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
181         if( scp == NULL) {
182                 printf("${1}%d failed to allocage driver strorage\n", unit);
183                 return (0);
184         }
185         bzero(scp, sizeof(*scp));
186         sca[unit] = scp;
187
188         /*
189          * Store whatever seems wise.
190          */
191         scp->dev = dev;
192         return 1;
193 }
194
195 /* 
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.
201  */
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);                                \
207         }                                                       \
208         if (scp == NULL) {                                      \
209                 printf( "%s: unit %d not attached\n", __func__, unit);\
210                 return (RETVAL);                                \
211         }                                                       \
212 } while (0)                                             
213 #ifdef  DIAGNOSTIC
214 #define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
215 #else   /* DIAGNOSTIC */
216 #define CHECKUNIT_DIAG(RETVAL)
217 #endif  /* DIAGNOSTIC */
218
219 static void
220 ${1}intr(int unit)
221 {
222         sc_p scp  = sca[unit];
223         
224         /* 
225          * well we got an interupt, now what?
226          * Theoretically we don't need to check the unit.
227          */
228         return;
229 }
230
231 int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
232 {
233         int unit = UNIT (dev);
234         sc_p scp  = sca[unit];
235         
236         CHECKUNIT_DIAG(ENXIO);
237     
238         switch (cmd) {
239             case DHIOCRESET:
240                 /*  whatever resets it */
241                 outb(scp->dev->id_iobase, 0xff);
242                 break;
243             default:
244                 return ENXIO;
245         }
246         return (0);
247 }   
248 /*
249  * You also need read, write, open, close routines.
250  * This should get you started
251  */
252 static  int
253 ${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
254 {
255         int unit = UNIT (dev);
256         sc_p scp  = sca[unit];
257         
258         CHECKUNIT(ENXIO);
259
260         /* 
261          * Do processing
262          */
263         return (0);
264 }
265
266 static  int
267 ${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
268 {
269         int unit = UNIT (dev);
270         sc_p scp  = sca[unit];
271         
272         CHECKUNIT_DIAG(ENXIO);
273
274         /* 
275          * Do processing
276          */
277         return (0);
278 }
279
280 static  int
281 ${1}read(dev_t dev, struct uio *uio, int ioflag)
282 {
283         int unit = UNIT (dev);
284         sc_p scp  = sca[unit];
285         int     toread;
286         
287         
288         CHECKUNIT_DIAG(ENXIO);
289
290         /* 
291          * Do processing
292          * read from buffer
293          */
294         toread = (min(uio->uio_resid, sizeof(scp->buffer)));
295         return(uiomove(scp->buffer, toread, uio));
296 }
297
298 static  int
299 ${1}write(dev_t dev, struct uio *uio, int ioflag)
300 {
301         int unit = UNIT (dev);
302         sc_p scp  = sca[unit];
303         int     towrite;
304         
305         CHECKUNIT_DIAG(ENXIO);
306
307         /* 
308          * Do processing
309          * write to buffer
310          */
311         towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
312         return(uiomove(scp->buffer, towrite, uio));
313 }
314
315 static  int
316 ${1}mmap(dev_t dev, int offset, int nprot)
317 {
318         int unit = UNIT (dev);
319         sc_p scp  = sca[unit];
320         
321         CHECKUNIT_DIAG(-1);
322
323         /* 
324          * Do processing
325          */
326 #if 0   /* if we had a frame buffer or whatever.. do this */
327         if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
328                 return (-1);
329         }
330         return i386_btop((FRAMEBASE + offset));
331 #else
332         return (-1);
333 #endif
334 }
335
336 static  int
337 ${1}poll(dev_t dev, int which, struct proc *p)
338 {
339         int unit = UNIT (dev);
340         sc_p scp  = sca[unit];
341         
342         CHECKUNIT_DIAG(ENXIO);
343
344         /* 
345          * Do processing
346          */
347         return (0); /* this is the wrong value I'm sure */
348 }
349
350 #ifndef ${UPPER}_MODULE
351
352 /*
353  * Now  for some driver initialisation.
354  * Occurs ONCE during boot (very early).
355  * This is if we are NOT a loadable module.
356  */
357 static void             
358 ${1}_drvinit(void *unused)
359 {
360         dev_t dev;
361
362         dev = makedev(CDEV_MAJOR, 0);
363         cdevsw_add(&dev, &${1}_cdevsw, NULL);
364 }
365
366 SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
367                 ${1}_drvinit, NULL)
368
369 #else  /* ${UPPER}_MODULE */
370 /* Here is the support for if we ARE a loadable kernel module */
371
372 #include <sys/exec.h>
373 #include <sys/sysent.h>
374 #include <sys/lkm.h>
375
376 MOD_DEV (${1}, LM_DT_CHAR, CDEV_MAJOR, &${1}_cdevsw);
377
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};
379
380 static int
381 ${1}_load (struct lkm_table *lkmtp, int cmd)
382 {
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;
391         }
392 }
393
394 static int
395 ${1}_unload (struct lkm_table *lkmtp, int cmd)
396 {
397         uprintf ("${1} driver unloaded\n");
398         return 0;
399 }
400
401 static int
402 ${1}_stat (struct lkm_table *lkmtp, int cmd)
403 {
404         return 0;
405 }
406
407 int
408 ${1}_mod (struct lkm_table *lkmtp, int cmd, int ver)
409 {
410         MOD_DISPATCH(${1}, lkmtp, cmd, ver,
411                 ${1}_load, ${1}_unload, ${1}_stat);
412 }
413
414 #endif /* ${UPPER}_MODULE */
415
416 DONE
417
418 cat >../../sys/${1}io.h <<DONE
419 /*
420  * Definitions needed to access the ${1} device (ioctls etc)
421  * see mtio.h , ioctl.h as examples
422  */
423 #ifndef SYS_DHIO_H
424 #define SYS_DHIO_H
425
426 #ifndef KERNEL
427 #include <sys/types.h>
428 #endif
429 #include <sys/ioccom.h>
430
431 /*
432  * define an ioctl here
433  */
434 #define DHIOCRESET _IO('D', 0)   /* reset the ${1} device */
435 #endif
436 DONE
437
438 if [ -d /usr/src/lkm/${1} ]
439 then
440         cat >/usr/src/lkm/${1}/Makefile <<DONE
441 #       ${UPPER} Loadable Kernel Module
442 #
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.
448
449 .PATH:  \${.CURDIR}/../../sys/i386/isa
450 KMOD    = ${1}_mod
451 SRCS    = ${1}.c ${1}.h
452
453 CFLAGS          += -I. -D${UPPER}_MODULE
454 CLEANFILES      += ${1}.h
455
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
463
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}
465
466 ${1}.h:
467         echo "#define N${UPPER} 1" > ${1}.h
468
469 afterinstall:
470         \${INSTALL} -c -o \${BINOWN} -g \${BINGRP} -m \${BINMODE} \
471         \${.CURDIR}/${1} \${DESTDIR}/usr/bin
472
473 .include <bsd.kmod.mk>
474 DONE
475 fi
476
477 config ${UPPER}
478 cd ../../compile/${UPPER}
479 make depend
480 make ${1}.o
481 make
482 exit
483
484 #--------------end of script---------------
485 #
486 #edit to your taste..
487 #
488
489
490
491
492