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