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