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