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/config
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}
24DONE
25
26grep -v X86_64_GENERIC < X86_64_GENERIC >>${UPPER}
27
28cat >>${UPPER} <<DONE
29# trust me, you'll need this
30options	DDB		
31pseudo-device	${1}	4	# might as well allow 4 of them 
32DONE
33
34cat >../../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) */
54static  d_open_t	${1}open;
55static  d_close_t	${1}close;
56static  d_read_t	${1}read;
57static  d_write_t	${1}write;
58static  d_ioctl_t	${1}ioctl;
59static  d_mmap_t	${1}mmap;
60static  d_poll_t	${1}poll;
61 
62#define CDEV_MAJOR 20
63static 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 */
88struct ${1}_softc {
89	struct isa_device *dev;
90	char	buffer[BUFFERSIZE];
91} ;
92
93typedef	struct ${1}_softc *sc_p;
94
95static 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)					\
105do { /* 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
121int ${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 */
142static  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
156static  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
170static  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
188static  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
205static  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
226static  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 */
244static 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
267SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
268		${1}_drvinit, NULL)
269
270
271DONE
272
273cat >../../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
291DONE
292
293config ${UPPER}
294cd ../../compile/${UPPER}
295make depend
296make ${1}.o
297make
298exit
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
310