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