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: 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.2 2003/06/17 04:36:57 dillon Exp $"
26DONE
27
28grep -v GENERIC < GENERIC >>${UPPER}
29
30cat >>${UPPER} <<DONE
31# trust me, you'll need this
32options	DDB		
33pseudo-device	${1}	4	# might as well allow 4 of them 
34DONE
35
36cat >../../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) */
57static  d_open_t	${1}open;
58static  d_close_t	${1}close;
59static  d_read_t	${1}read;
60static  d_write_t	${1}write;
61static  d_ioctl_t	${1}ioctl;
62static  d_mmap_t	${1}mmap;
63static  d_poll_t	${1}poll;
64 
65#define CDEV_MAJOR 20
66static 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 */
91struct ${1}_softc {
92	struct isa_device *dev;
93	char	buffer[BUFFERSIZE];
94} ;
95
96typedef	struct ${1}_softc *sc_p;
97
98static 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)					\
108do { /* the do-while is a safe way to do this grouping */	\
109	if (unit > N${UPPER}) {					\
110		printf(__FUNCTION__ ":bad unit %d\n", unit);	\
111		return (RETVAL);				\
112	}							\
113	if (scp == NULL) { 					\
114		printf( __FUNCTION__ ": unit %d not attached\n", 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
124int ${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 */
145static  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
159static  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
173static  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
191static  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
208static  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
229static  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 */
247static 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
270SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
271		${1}_drvinit, NULL)
272
273
274DONE
275
276cat >../../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
294DONE
295
296config ${UPPER}
297cd ../../compile/${UPPER}
298make depend
299make ${1}.o
300make
301exit
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
313