Initial import from FreeBSD RELENG_4:
[dragonfly.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 #arg1 is lowercase "foo" 
4 #
5 # Trust me, RUN THIS SCRIPT :)
6 #
7 #-------cut here------------------
8 cd /sys/i386/conf
9
10 if [ "${1}X" = "X" ] 
11 then
12         echo "Hey , how about some help here.. give me a device name!"
13         exit 1
14 fi
15
16 UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"` 
17 cat >files.${UPPER} <<DONE
18 dev/${1}.c      optional ${1} device-driver
19 DONE
20
21 cat >${UPPER} <<DONE
22 # Configuration file for kernel type: ${UPPER}
23 ident   ${UPPER}
24 # \$FreeBSD: src/share/examples/drivers/make_pseudo_driver.sh,v 1.5.2.1 2001/07/25 15:56:09 dd Exp $"
25 DONE
26
27 grep -v GENERIC < GENERIC >>${UPPER}
28
29 cat >>${UPPER} <<DONE
30 # trust me, you'll need this
31 options DDB             
32 pseudo-device   ${1}    4       # might as well allow 4 of them 
33 DONE
34
35 cat >../../dev/${1}.c <<DONE
36 /*
37  * Copyright ME
38  *
39  * ${1} driver
40  * \$FreeBSD: src/share/examples/drivers/make_pseudo_driver.sh,v 1.5.2.1 2001/07/25 15:56:09 dd Exp $
41  */
42
43
44 #include "${1}.h"               /* generated file.. defines N${UPPER} */
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>         /* SYSINIT stuff */
48 #include <sys/conf.h>           /* cdevsw stuff */
49 #include <sys/malloc.h>         /* malloc region definitions */
50 #include <machine/clock.h>      /* DELAY() */
51 #include <sys/${1}io.h>         /* ${1} IOCTL definitions */
52
53
54
55 /* Function prototypes (these should all be static) */
56 static  d_open_t        ${1}open;
57 static  d_close_t       ${1}close;
58 static  d_read_t        ${1}read;
59 static  d_write_t       ${1}write;
60 static  d_ioctl_t       ${1}ioctl;
61 static  d_mmap_t        ${1}mmap;
62 static  d_poll_t        ${1}poll;
63  
64 #define CDEV_MAJOR 20
65 static struct cdevsw ${1}_cdevsw = {
66         ${1}open,
67         ${1}close,
68         ${1}read,
69         ${1}write,        
70         ${1}ioctl,
71         nullstop,
72         nullreset,
73         nodevtotty, 
74         ${1}poll,
75         ${1}mmap,
76         NULL,
77         "${1}",
78         NULL,
79         -1 };
80  
81 /* 
82  * device  specific Misc defines 
83  */
84 #define BUFFERSIZE 1024
85 #define UNIT(dev) minor(dev)    /* assume one minor number per unit */
86
87 /*
88  * One of these per allocated device
89  */
90 struct ${1}_softc {
91         struct isa_device *dev;
92         char    buffer[BUFFERSIZE];
93 } ;
94
95 typedef struct ${1}_softc *sc_p;
96
97 static sc_p sca[N${UPPER}];
98
99 /* 
100  * Macro to check that the unit number is valid
101  * Often this isn't needed as once the open() is performed,
102  * the unit number is pretty much safe.. The exception would be if we
103  * implemented devices that could "go away". in which case all these routines
104  * would be wise to check the number, DIAGNOSTIC or not.
105  */
106 #define CHECKUNIT(RETVAL)                                       \
107 do { /* the do-while is a safe way to do this grouping */       \
108         if (unit > N${UPPER}) {                                 \
109                 printf(__FUNCTION__ ":bad unit %d\n", unit);    \
110                 return (RETVAL);                                \
111         }                                                       \
112         if (scp == NULL) {                                      \
113                 printf( __FUNCTION__ ": unit %d not attached\n", unit);\
114                 return (RETVAL);                                \
115         }                                                       \
116 } while (0)                                             
117 #ifdef  DIAGNOSTIC
118 #define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
119 #else   /* DIAGNOSTIC */
120 #define CHECKUNIT_DIAG(RETVAL)
121 #endif  /* DIAGNOSTIC */
122
123 int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
124 {
125         int unit = UNIT (dev);
126         sc_p scp  = sca[unit];
127         
128         CHECKUNIT_DIAG(ENXIO);
129     
130         switch (cmd) {
131             case DHIOCRESET:
132                 /*  whatever resets it */
133                 outb(scp->dev->id_iobase, 0xff);
134                 break;
135             default:
136                 return ENXIO;
137         }
138         return (0);
139 }   
140 /*
141  * You also need read, write, open, close routines.
142  * This should get you started
143  */
144 static  int
145 ${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
146 {
147         int unit = UNIT (dev);
148         sc_p scp  = sca[unit];
149         
150         CHECKUNIT(ENXIO);
151
152         /* 
153          * Do processing
154          */
155         return (0);
156 }
157
158 static  int
159 ${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
160 {
161         int unit = UNIT (dev);
162         sc_p scp  = sca[unit];
163         
164         CHECKUNIT_DIAG(ENXIO);
165
166         /* 
167          * Do processing
168          */
169         return (0);
170 }
171
172 static  int
173 ${1}read(dev_t dev, struct uio *uio, int ioflag)
174 {
175         int unit = UNIT (dev);
176         sc_p scp  = sca[unit];
177         int     toread;
178         
179         
180         CHECKUNIT_DIAG(ENXIO);
181
182         /* 
183          * Do processing
184          * read from buffer
185          */
186         toread = (min(uio->uio_resid, sizeof(scp->buffer)));
187         return(uiomove(scp->buffer, toread, uio));
188 }
189
190 static  int
191 ${1}write(dev_t dev, struct uio *uio, int ioflag)
192 {
193         int unit = UNIT (dev);
194         sc_p scp  = sca[unit];
195         int     towrite;
196         
197         CHECKUNIT_DIAG(ENXIO);
198
199         /* 
200          * Do processing
201          * write to buffer
202          */
203         towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
204         return(uiomove(scp->buffer, towrite, uio));
205 }
206
207 static  int
208 ${1}mmap(dev_t dev, int offset, int nprot)
209 {
210         int unit = UNIT (dev);
211         sc_p scp  = sca[unit];
212         
213         CHECKUNIT_DIAG(-1);
214
215         /* 
216          * Do processing
217          */
218 #if 0   /* if we had a frame buffer or whatever.. do this */
219         if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
220                 return (-1);
221         }
222         return i386_btop((FRAMEBASE + offset));
223 #else
224         return (-1);
225 #endif
226 }
227
228 static  int
229 ${1}poll(dev_t dev, int which, struct proc *p)
230 {
231         int unit = UNIT (dev);
232         sc_p scp  = sca[unit];
233         
234         CHECKUNIT_DIAG(ENXIO);
235
236         /* 
237          * Do processing
238          */
239         return (0); /* this is the wrong value I'm sure */
240 }
241
242 /*
243  * Now  for some driver initialisation.
244  * Occurs ONCE during boot (very early).
245  */
246 static void             
247 ${1}_drvinit(void *unused)
248 {
249         dev_t dev;
250         int     unit;
251         sc_p scp  = sca[unit];
252
253         dev = makedev(CDEV_MAJOR, 0);
254         cdevsw_add(&dev, &${1}_cdevsw, NULL);
255         for (unit = 0; unit < N${UPPER}; unit++) {
256                 /* 
257                  * Allocate storage for this instance .
258                  */
259                 scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
260                 if( scp == NULL) {
261                         printf("${1}%d failed to allocate strorage\n", unit);
262                         return ;
263                 }
264                 bzero(scp, sizeof(*scp));
265                 sca[unit] = scp;
266         }
267 }
268
269 SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
270                 ${1}_drvinit, NULL)
271
272
273 DONE
274
275 cat >../../sys/${1}io.h <<DONE
276 /*
277  * Definitions needed to access the ${1} device (ioctls etc)
278  * see mtio.h , ioctl.h as examples
279  */
280 #ifndef SYS_DHIO_H
281 #define SYS_DHIO_H
282
283 #ifndef KERNEL
284 #include <sys/types.h>
285 #endif
286 #include <sys/ioccom.h>
287
288 /*
289  * define an ioctl here
290  */
291 #define DHIOCRESET _IO('D', 0)   /* reset the ${1} device */
292 #endif
293 DONE
294
295 config ${UPPER}
296 cd ../../compile/${UPPER}
297 make depend
298 make ${1}.o
299 make
300 exit
301
302 #--------------end of script---------------
303 #
304 #you also need to add an entry into the cdevsw[]
305 #array in conf.c, but it's too hard to do in a script..
306 #
307 #edit to your taste..
308 #
309
310
311