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