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# It also creates a directory under /usr/src/lkm to help you create
6#loadable kernel modules, though without much use except for development.
7#
8# Trust me, RUN THIS SCRIPT :)
9#
10#-------cut here------------------
11cd /sys/config
12
13if [ "${1}X" = "X" ]
14then
15	echo "Hey , how about some help here.. give me a device name!"
16	exit 1
17fi
18
19if [ -d /usr/src/lkm ]
20then
21	mkdir /usr/src/lkm/${1}
22fi
23
24UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
25cat >files.${UPPER} <<DONE
26i386/isa/${1}.c      optional ${1} device-driver
27DONE
28
29cat >${UPPER} <<DONE
30# Configuration file for kernel type: ${UPPER}
31ident	${UPPER}
32# \$FreeBSD: src/share/examples/drivers/make_device_driver.sh,v 1.6.2.1 2001/07/25 15:56:09 dd Exp $"
33# \$DragonFly: src/share/examples/drivers/make_device_driver.sh,v 1.6 2007/05/17 08:19:01 swildner Exp $"
34DONE
35
36grep -v GENERIC < GENERIC >>${UPPER}
37
38cat >>${UPPER} <<DONE
39# trust me, you'll need this
40options	DDB		
41device ${1}0 at isa? port 0x234 bio irq 5
42DONE
43
44cat >../isa/${1}.c <<DONE
45/*
46 * Copyright ME
47 *
48 * ${1} driver
49 * \$FreeBSD: src/share/examples/drivers/make_device_driver.sh,v 1.6.2.1 2001/07/25 15:56:09 dd Exp $
50 */
51
52
53#include "${1}.h"		/* generated file.. defines N${UPPER} */
54#include <sys/param.h>
55#include <sys/systm.h>
56#include <sys/kernel.h>		/* SYSINIT stuff */
57#include <sys/conf.h>		/* cdevsw stuff */
58#include <sys/malloc.h>		/* malloc region definitions */
59#include <machine/clock.h>	/* DELAY() */
60#include <i386/isa/isa.h>	/* ISA bus port definitions etc. */
61#include <i386/isa/isa_device.h>/* ISA bus configuration structures */
62#include <sys/${1}io.h>		/* ${1} IOCTL definitions */
63
64
65
66/* Function prototypes (these should all be static) */
67static  d_open_t	${1}open;
68static  d_close_t	${1}close;
69static  d_read_t	${1}read;
70static  d_write_t	${1}write;
71static  d_ioctl_t	${1}ioctl;
72static  d_mmap_t	${1}mmap;
73static  d_poll_t	${1}poll;
74static	int		${1}probe (struct isa_device *);
75static	int		${1}attach (struct isa_device *);
76#ifdef ${UPPER}_MODULE
77static	ointhand2_t	${1}intr; /* should actually have type inthand2_t */
78#endif
79 
80#define CDEV_MAJOR 20
81static struct cdevsw ${1}_cdevsw = {
82	${1}open,
83	${1}close,
84	${1}read,
85	${1}write,        
86	${1}ioctl,
87	nullstop,
88	nullreset,
89	nodevtotty, 
90	${1}poll,
91	${1}mmap,
92	NULL,
93	"${1}",
94	NULL,
95	-1 };
96 
97struct isa_driver ${1}driver = {
98	${1}probe,
99	${1}attach,
100	"${1}" };
101
102/* 
103 * device  specific Misc defines 
104 */
105#define BUFFERSIZE 1024
106#define NUMPORTS 4
107#define UNIT(dev) minor(dev)	/* assume one minor number per unit */
108
109/*
110 * One of these per allocated device
111 */
112struct ${1}_softc {
113	struct isa_device *dev;
114	char	buffer[BUFFERSIZE];
115} ;
116
117typedef	struct ${1}_softc *sc_p;
118
119static sc_p sca[N${UPPER}];
120
121/* add your own test to see if it exists */
122/* should return the number of ports needed */
123static int
124${1}probe (struct isa_device *dev)
125{
126	char val;
127	int unit = dev->id_unit;
128	sc_p scp  = sca[unit];
129
130	/*
131	 * Check the unit makes sense.
132	 */
133	if (unit > N${UPPER}) {
134		printf("bad unit (%d)\n", unit);
135		return (0);
136	}
137	if (scp) {
138		printf("unit %d already attached\n", unit);
139		return (0);
140	}
141
142	/*
143	 * try see if the device is there.
144	 */
145	val = inb (dev->id_iobase);
146	if ( val != 42 ) {
147		return (0);
148	}
149
150	/*
151	 * ok, we got one we think 
152	 * do some further (this time possibly destructive) tests.
153	 */
154	outb (dev->id_iobase, 0xff);
155	DELAY (10000); /*  10 ms delay */
156	val = inb (dev->id_iobase) & 0x0f;
157	return ((val & 0x0f) == 0x0f)? NUMPORTS : 0 ;
158}
159
160/*
161 * Called if the probe succeeded.
162 * We can be destructive here as we know we have the device.
163 * we can also trust the unit number.
164 */
165static int
166${1}attach (struct isa_device *dev)
167{
168	int unit = dev->id_unit;
169	sc_p scp  = sca[unit];
170
171	/*
172	 * Attach our interrupt handler to the device struct.  Our caller
173	 * will attach it to the hardware soon after we return.
174	 */
175	dev->id_ointr = ${1}intr;
176
177	/* 
178	 * Allocate storage for this instance .
179	 */
180	scp = kmalloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
181	if( scp == NULL) {
182		printf("${1}%d failed to allocage driver strorage\n", unit);
183		return (0);
184	}
185	bzero(scp, sizeof(*scp));
186	sca[unit] = scp;
187
188	/*
189	 * Store whatever seems wise.
190	 */
191	scp->dev = dev;
192	return 1;
193}
194
195/* 
196 * Macro to check that the unit number is valid
197 * Often this isn't needed as once the open() is performed,
198 * the unit number is pretty much safe.. The exception would be if we
199 * implemented devices that could "go away". in which case all these routines
200 * would be wise to check the number, DIAGNOSTIC or not.
201 */
202#define CHECKUNIT(RETVAL)					\
203do { /* the do-while is a safe way to do this grouping */	\
204	if (unit > N${UPPER}) {					\
205		printf("%s:bad unit %d\n", __func__, unit);	\
206		return (RETVAL);				\
207	}							\
208	if (scp == NULL) { 					\
209		printf( "%s: unit %d not attached\n", __func__, unit);\
210		return (RETVAL);				\
211	}							\
212} while (0)						
213#ifdef	DIAGNOSTIC
214#define	CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
215#else	/* DIAGNOSTIC */
216#define	CHECKUNIT_DIAG(RETVAL)
217#endif 	/* DIAGNOSTIC */
218
219static void
220${1}intr(int unit)
221{
222	sc_p scp  = sca[unit];
223	
224	/* 
225	 * well we got an interrupt, now what?
226	 * Theoretically we don't need to check the unit.
227	 */
228	return;
229}
230
231int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
232{
233	int unit = UNIT (dev);
234	sc_p scp  = sca[unit];
235	
236	CHECKUNIT_DIAG(ENXIO);
237    
238	switch (cmd) {
239	    case DHIOCRESET:
240		/*  whatever resets it */
241		outb(scp->dev->id_iobase, 0xff);
242		break;
243	    default:
244		return ENXIO;
245	}
246	return (0);
247}   
248/*
249 * You also need read, write, open, close routines.
250 * This should get you started
251 */
252static  int
253${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
254{
255	int unit = UNIT (dev);
256	sc_p scp  = sca[unit];
257	
258	CHECKUNIT(ENXIO);
259
260	/* 
261	 * Do processing
262	 */
263	return (0);
264}
265
266static  int
267${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
268{
269	int unit = UNIT (dev);
270	sc_p scp  = sca[unit];
271	
272	CHECKUNIT_DIAG(ENXIO);
273
274	/* 
275	 * Do processing
276	 */
277	return (0);
278}
279
280static  int
281${1}read(dev_t dev, struct uio *uio, int ioflag)
282{
283	int unit = UNIT (dev);
284	sc_p scp  = sca[unit];
285	int     toread;
286	
287	
288	CHECKUNIT_DIAG(ENXIO);
289
290	/* 
291	 * Do processing
292	 * read from buffer
293	 */
294	toread = (min(uio->uio_resid, sizeof(scp->buffer)));
295	return(uiomove(scp->buffer, toread, uio));
296}
297
298static  int
299${1}write(dev_t dev, struct uio *uio, int ioflag)
300{
301	int unit = UNIT (dev);
302	sc_p scp  = sca[unit];
303	int	towrite;
304	
305	CHECKUNIT_DIAG(ENXIO);
306
307	/* 
308	 * Do processing
309	 * write to buffer
310	 */
311	towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
312	return(uiomove(scp->buffer, towrite, uio));
313}
314
315static  int
316${1}mmap(dev_t dev, int offset, int nprot)
317{
318	int unit = UNIT (dev);
319	sc_p scp  = sca[unit];
320	
321	CHECKUNIT_DIAG(-1);
322
323	/* 
324	 * Do processing
325	 */
326#if 0	/* if we had a frame buffer or whatever.. do this */
327	if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
328		return (-1);
329	}
330	return i386_btop((FRAMEBASE + offset));
331#else
332	return (-1);
333#endif
334}
335
336static  int
337${1}poll(dev_t dev, int which, struct proc *p)
338{
339	int unit = UNIT (dev);
340	sc_p scp  = sca[unit];
341	
342	CHECKUNIT_DIAG(ENXIO);
343
344	/* 
345	 * Do processing
346	 */
347	return (0); /* this is the wrong value I'm sure */
348}
349
350#ifndef ${UPPER}_MODULE
351
352/*
353 * Now  for some driver initialisation.
354 * Occurs ONCE during boot (very early).
355 * This is if we are NOT a loadable module.
356 */
357static void             
358${1}_drvinit(void *unused)
359{
360        dev_t dev;
361
362	dev = makedev(CDEV_MAJOR, 0);
363	cdevsw_add(&dev, &${1}_cdevsw, NULL);
364}
365
366SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
367		${1}_drvinit, NULL)
368
369#else  /* ${UPPER}_MODULE */
370/* Here is the support for if we ARE a loadable kernel module */
371
372#include <sys/exec.h>
373#include <sys/sysent.h>
374#include <sys/lkm.h>
375
376MOD_DEV (${1}, LM_DT_CHAR, CDEV_MAJOR, &${1}_cdevsw);
377
378static struct isa_device dev = {0, &${1}driver, BASE_IO, IRQ, DMA, (caddr_t) PHYS_IO, PHYS_IO_SIZE, INT_INT, 0, FLAGS, 0, 0, 0, 0, 1, 0, 0};
379
380static int
381${1}_load (struct lkm_table *lkmtp, int cmd)
382{
383	if (${1}probe (&dev)) {
384		${1}attach (&dev);
385		uprintf ("${1} driver loaded\n");
386		uprintf ("${1}: interrupts not hooked\n");
387		return 0;
388	} else {
389		uprintf ("${1} driver: probe failed\n");
390		return 1;
391	}
392}
393
394static int
395${1}_unload (struct lkm_table *lkmtp, int cmd)
396{
397	uprintf ("${1} driver unloaded\n");
398	return 0;
399}
400
401static int
402${1}_stat (struct lkm_table *lkmtp, int cmd)
403{
404	return 0;
405}
406
407int
408${1}_mod (struct lkm_table *lkmtp, int cmd, int ver)
409{
410	MOD_DISPATCH(${1}, lkmtp, cmd, ver,
411		${1}_load, ${1}_unload, ${1}_stat);
412}
413
414#endif /* ${UPPER}_MODULE */
415
416DONE
417
418cat >../../sys/${1}io.h <<DONE
419/*
420 * Definitions needed to access the ${1} device (ioctls etc)
421 * see mtio.h , ioctl.h as examples
422 */
423#ifndef SYS_DHIO_H
424#define SYS_DHIO_H
425
426#ifndef KERNEL
427#include <sys/types.h>
428#endif
429#include <sys/ioccom.h>
430
431/*
432 * define an ioctl here
433 */
434#define DHIOCRESET _IO('D', 0)   /* reset the ${1} device */
435#endif
436DONE
437
438if [ -d /usr/src/lkm/${1} ]
439then
440	cat >/usr/src/lkm/${1}/Makefile <<DONE
441#	${UPPER} Loadable Kernel Module
442#
443#	This happens not to work, actually. It's written for
444#	a character ISA device driver, but they cannot be
445#	be made into lkm's, because you have to hard code
446#	everything you'll otherwise enter into the kernel
447#	configuration file.
448
449.PATH:	\${.CURDIR}/../../sys/arch/i386/isa
450KMOD	= ${1}_mod
451SRCS	= ${1}.c ${1}.h
452
453CFLAGS		+= -I. -D${UPPER}_MODULE
454CLEANFILES	+= ${1}.h
455
456BASE_IO=0		# Base IO address
457IRQ=0			# IRQ number
458DMA=-1			# DMA channel
459PHYS_IO=0		# Physical IO Memory base address
460PHYS_IO_SIZE=0		# Physical IO Memory size
461INT_INT=0		# Interrupt interface
462FLAGS=0			# Flags
463
464CFLAGS+= -DBASE_IO=\${BASE_IO} -DIRQ=\${IRQ} -DDMA=\${DMA} -DPHYS_IO=\${PHYS_IO} -DPHYS_IO_SIZE=\${PHYS_IO_SIZE} -DINT_INT=\${INT_INT} -DFLAGS=\${FLAGS}
465
466${1}.h:
467	echo "#define N${UPPER} 1" > ${1}.h
468
469afterinstall:
470	\${INSTALL} -c -o \${BINOWN} -g \${BINGRP} -m \${BINMODE} \
471	\${.CURDIR}/${1} \${DESTDIR}/usr/bin
472
473.include <bsd.kmod.mk>
474DONE
475fi
476
477config ${UPPER}
478cd ../../compile/${UPPER}
479make depend
480make ${1}.o
481make
482exit
483
484#--------------end of script---------------
485#
486#edit to your taste..
487#
488#
489
490
491
492
493