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