Initial import from FreeBSD RELENG_4:
[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 DONE
34
35 grep -v GENERIC < GENERIC >>${UPPER}
36
37 cat >>${UPPER} <<DONE
38 # trust me, you'll need this
39 options DDB             
40 device ${1}0 at isa? port 0x234 bio irq 5
41 DONE
42
43 cat >../isa/${1}.c <<DONE
44 /*
45  * Copyright ME
46  *
47  * ${1} driver
48  * \$FreeBSD: src/share/examples/drivers/make_device_driver.sh,v 1.6.2.1 2001/07/25 15:56:09 dd Exp $
49  */
50
51
52 #include "${1}.h"               /* generated file.. defines N${UPPER} */
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>         /* SYSINIT stuff */
56 #include <sys/conf.h>           /* cdevsw stuff */
57 #include <sys/malloc.h>         /* malloc region definitions */
58 #include <machine/clock.h>      /* DELAY() */
59 #include <i386/isa/isa.h>       /* ISA bus port definitions etc. */
60 #include <i386/isa/isa_device.h>/* ISA bus configuration structures */
61 #include <sys/${1}io.h>         /* ${1} IOCTL definitions */
62
63
64
65 /* Function prototypes (these should all be static) */
66 static  d_open_t        ${1}open;
67 static  d_close_t       ${1}close;
68 static  d_read_t        ${1}read;
69 static  d_write_t       ${1}write;
70 static  d_ioctl_t       ${1}ioctl;
71 static  d_mmap_t        ${1}mmap;
72 static  d_poll_t        ${1}poll;
73 static  int             ${1}probe (struct isa_device *);
74 static  int             ${1}attach (struct isa_device *);
75 #ifdef ${UPPER}_MODULE
76 static  ointhand2_t     ${1}intr; /* should actually have type inthand2_t */
77 #endif
78  
79 #define CDEV_MAJOR 20
80 static struct cdevsw ${1}_cdevsw = {
81         ${1}open,
82         ${1}close,
83         ${1}read,
84         ${1}write,        
85         ${1}ioctl,
86         nullstop,
87         nullreset,
88         nodevtotty, 
89         ${1}poll,
90         ${1}mmap,
91         NULL,
92         "${1}",
93         NULL,
94         -1 };
95  
96 struct isa_driver ${1}driver = {
97         ${1}probe,
98         ${1}attach,
99         "${1}" };
100
101 /* 
102  * device  specific Misc defines 
103  */
104 #define BUFFERSIZE 1024
105 #define NUMPORTS 4
106 #define UNIT(dev) minor(dev)    /* assume one minor number per unit */
107
108 /*
109  * One of these per allocated device
110  */
111 struct ${1}_softc {
112         struct isa_device *dev;
113         char    buffer[BUFFERSIZE];
114 } ;
115
116 typedef struct ${1}_softc *sc_p;
117
118 static sc_p sca[N${UPPER}];
119
120 /* add your own test to see if it exists */
121 /* should return the number of ports needed */
122 static int
123 ${1}probe (struct isa_device *dev)
124 {
125         char val;
126         int unit = dev->id_unit;
127         sc_p scp  = sca[unit];
128
129         /*
130          * Check the unit makes sense.
131          */
132         if (unit > N${UPPER}) {
133                 printf("bad unit (%d)\n", unit);
134                 return (0);
135         }
136         if (scp) {
137                 printf("unit %d already attached\n", unit);
138                 return (0);
139         }
140
141         /*
142          * try see if the device is there.
143          */
144         val = inb (dev->id_iobase);
145         if ( val != 42 ) {
146                 return (0);
147         }
148
149         /*
150          * ok, we got one we think 
151          * do some further (this time possibly destructive) tests.
152          */
153         outb (dev->id_iobase, 0xff);
154         DELAY (10000); /*  10 ms delay */
155         val = inb (dev->id_iobase) & 0x0f;
156         return ((val & 0x0f) == 0x0f)? NUMPORTS : 0 ;
157 }
158
159 /*
160  * Called if the probe succeeded.
161  * We can be destructive here as we know we have the device.
162  * we can also trust the unit number.
163  */
164 static int
165 ${1}attach (struct isa_device *dev)
166 {
167         int unit = dev->id_unit;
168         sc_p scp  = sca[unit];
169
170         /*
171          * Attach our interrupt handler to the device struct.  Our caller
172          * will attach it to the hardware soon after we return.
173          */
174         dev->id_ointr = ${1}intr;
175
176         /* 
177          * Allocate storage for this instance .
178          */
179         scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
180         if( scp == NULL) {
181                 printf("${1}%d failed to allocage driver strorage\n", unit);
182                 return (0);
183         }
184         bzero(scp, sizeof(*scp));
185         sca[unit] = scp;
186
187         /*
188          * Store whatever seems wise.
189          */
190         scp->dev = dev;
191         return 1;
192 }
193
194 /* 
195  * Macro to check that the unit number is valid
196  * Often this isn't needed as once the open() is performed,
197  * the unit number is pretty much safe.. The exception would be if we
198  * implemented devices that could "go away". in which case all these routines
199  * would be wise to check the number, DIAGNOSTIC or not.
200  */
201 #define CHECKUNIT(RETVAL)                                       \
202 do { /* the do-while is a safe way to do this grouping */       \
203         if (unit > N${UPPER}) {                                 \
204                 printf(__FUNCTION__ ":bad unit %d\n", unit);    \
205                 return (RETVAL);                                \
206         }                                                       \
207         if (scp == NULL) {                                      \
208                 printf( __FUNCTION__ ": unit %d not attached\n", unit);\
209                 return (RETVAL);                                \
210         }                                                       \
211 } while (0)                                             
212 #ifdef  DIAGNOSTIC
213 #define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
214 #else   /* DIAGNOSTIC */
215 #define CHECKUNIT_DIAG(RETVAL)
216 #endif  /* DIAGNOSTIC */
217
218 static void
219 ${1}intr(int unit)
220 {
221         sc_p scp  = sca[unit];
222         
223         /* 
224          * well we got an interupt, now what?
225          * Theoretically we don't need to check the unit.
226          */
227         return;
228 }
229
230 int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
231 {
232         int unit = UNIT (dev);
233         sc_p scp  = sca[unit];
234         
235         CHECKUNIT_DIAG(ENXIO);
236     
237         switch (cmd) {
238             case DHIOCRESET:
239                 /*  whatever resets it */
240                 outb(scp->dev->id_iobase, 0xff);
241                 break;
242             default:
243                 return ENXIO;
244         }
245         return (0);
246 }   
247 /*
248  * You also need read, write, open, close routines.
249  * This should get you started
250  */
251 static  int
252 ${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
253 {
254         int unit = UNIT (dev);
255         sc_p scp  = sca[unit];
256         
257         CHECKUNIT(ENXIO);
258
259         /* 
260          * Do processing
261          */
262         return (0);
263 }
264
265 static  int
266 ${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
267 {
268         int unit = UNIT (dev);
269         sc_p scp  = sca[unit];
270         
271         CHECKUNIT_DIAG(ENXIO);
272
273         /* 
274          * Do processing
275          */
276         return (0);
277 }
278
279 static  int
280 ${1}read(dev_t dev, struct uio *uio, int ioflag)
281 {
282         int unit = UNIT (dev);
283         sc_p scp  = sca[unit];
284         int     toread;
285         
286         
287         CHECKUNIT_DIAG(ENXIO);
288
289         /* 
290          * Do processing
291          * read from buffer
292          */
293         toread = (min(uio->uio_resid, sizeof(scp->buffer)));
294         return(uiomove(scp->buffer, toread, uio));
295 }
296
297 static  int
298 ${1}write(dev_t dev, struct uio *uio, int ioflag)
299 {
300         int unit = UNIT (dev);
301         sc_p scp  = sca[unit];
302         int     towrite;
303         
304         CHECKUNIT_DIAG(ENXIO);
305
306         /* 
307          * Do processing
308          * write to buffer
309          */
310         towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
311         return(uiomove(scp->buffer, towrite, uio));
312 }
313
314 static  int
315 ${1}mmap(dev_t dev, int offset, int nprot)
316 {
317         int unit = UNIT (dev);
318         sc_p scp  = sca[unit];
319         
320         CHECKUNIT_DIAG(-1);
321
322         /* 
323          * Do processing
324          */
325 #if 0   /* if we had a frame buffer or whatever.. do this */
326         if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
327                 return (-1);
328         }
329         return i386_btop((FRAMEBASE + offset));
330 #else
331         return (-1);
332 #endif
333 }
334
335 static  int
336 ${1}poll(dev_t dev, int which, struct proc *p)
337 {
338         int unit = UNIT (dev);
339         sc_p scp  = sca[unit];
340         
341         CHECKUNIT_DIAG(ENXIO);
342
343         /* 
344          * Do processing
345          */
346         return (0); /* this is the wrong value I'm sure */
347 }
348
349 #ifndef ${UPPER}_MODULE
350
351 /*
352  * Now  for some driver initialisation.
353  * Occurs ONCE during boot (very early).
354  * This is if we are NOT a loadable module.
355  */
356 static void             
357 ${1}_drvinit(void *unused)
358 {
359         dev_t dev;
360
361         dev = makedev(CDEV_MAJOR, 0);
362         cdevsw_add(&dev, &${1}_cdevsw, NULL);
363 }
364
365 SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
366                 ${1}_drvinit, NULL)
367
368 #else  /* ${UPPER}_MODULE */
369 /* Here is the support for if we ARE a loadable kernel module */
370
371 #include <sys/exec.h>
372 #include <sys/sysent.h>
373 #include <sys/lkm.h>
374
375 MOD_DEV (${1}, LM_DT_CHAR, CDEV_MAJOR, &${1}_cdevsw);
376
377 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};
378
379 static int
380 ${1}_load (struct lkm_table *lkmtp, int cmd)
381 {
382         if (${1}probe (&dev)) {
383                 ${1}attach (&dev);
384                 uprintf ("${1} driver loaded\n");
385                 uprintf ("${1}: interrupts not hooked\n");
386                 return 0;
387         } else {
388                 uprintf ("${1} driver: probe failed\n");
389                 return 1;
390         }
391 }
392
393 static int
394 ${1}_unload (struct lkm_table *lkmtp, int cmd)
395 {
396         uprintf ("${1} driver unloaded\n");
397         return 0;
398 }
399
400 static int
401 ${1}_stat (struct lkm_table *lkmtp, int cmd)
402 {
403         return 0;
404 }
405
406 int
407 ${1}_mod (struct lkm_table *lkmtp, int cmd, int ver)
408 {
409         MOD_DISPATCH(${1}, lkmtp, cmd, ver,
410                 ${1}_load, ${1}_unload, ${1}_stat);
411 }
412
413 #endif /* ${UPPER}_MODULE */
414
415 DONE
416
417 cat >../../sys/${1}io.h <<DONE
418 /*
419  * Definitions needed to access the ${1} device (ioctls etc)
420  * see mtio.h , ioctl.h as examples
421  */
422 #ifndef SYS_DHIO_H
423 #define SYS_DHIO_H
424
425 #ifndef KERNEL
426 #include <sys/types.h>
427 #endif
428 #include <sys/ioccom.h>
429
430 /*
431  * define an ioctl here
432  */
433 #define DHIOCRESET _IO('D', 0)   /* reset the ${1} device */
434 #endif
435 DONE
436
437 if [ -d /usr/src/lkm/${1} ]
438 then
439         cat >/usr/src/lkm/${1}/Makefile <<DONE
440 #       ${UPPER} Loadable Kernel Module
441 #
442 #       This happens not to work, actually. It's written for
443 #       a character ISA device driver, but they cannot be
444 #       be made into lkm's, because you have to hard code
445 #       everything you'll otherwise enter into the kernel
446 #       configuration file.
447
448 .PATH:  \${.CURDIR}/../../sys/i386/isa
449 KMOD    = ${1}_mod
450 SRCS    = ${1}.c ${1}.h
451
452 CFLAGS          += -I. -D${UPPER}_MODULE
453 CLEANFILES      += ${1}.h
454
455 BASE_IO=0               # Base IO address
456 IRQ=0                   # IRQ number
457 DMA=-1                  # DMA channel
458 PHYS_IO=0               # Physical IO Memory base address
459 PHYS_IO_SIZE=0          # Physical IO Memory size
460 INT_INT=0               # Interrupt interface
461 FLAGS=0                 # Flags
462
463 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}
464
465 ${1}.h:
466         echo "#define N${UPPER} 1" > ${1}.h
467
468 afterinstall:
469         \${INSTALL} -c -o \${BINOWN} -g \${BINGRP} -m \${BINMODE} \
470         \${.CURDIR}/${1} \${DESTDIR}/usr/bin
471
472 .include <bsd.kmod.mk>
473 DONE
474 fi
475
476 config ${UPPER}
477 cd ../../compile/${UPPER}
478 make depend
479 make ${1}.o
480 make
481 exit
482
483 #--------------end of script---------------
484 #
485 #edit to your taste..
486 #
487
488
489
490
491