1101214Smarkm#!/bin/sh
222195Sjulian# This writes a skeleton driver and puts it into the kernel tree for you
322195Sjulian#
4161139Srik# arg1 is lowercase "foo"
5161139Srik# arg2 path to the kernel sources, "/sys" if omitted
6161139Srik#
722195Sjulian# Trust me, RUN THIS SCRIPT :)
822195Sjulian#
9101214Smarkm# $FreeBSD$
10101214Smarkm#
1122195Sjulian#-------cut here------------------
1222195Sjulian
13101214Smarkmif [ "${1}X" = "X" ]
1422195Sjulianthen
1522195Sjulian	echo "Hey , how about some help here.. give me a device name!"
1622195Sjulian	exit 1
1722195Sjulianfi
18161139Srikif [ "X${2}" = "X" ]; then
19161139Srik	TOP=`cd /sys; pwd -P`
20161139Srik	echo "Using ${TOP} as the path to the kernel sources!"
21161139Srikelse
22161139Srik	TOP=${2}
23161139Srikfi
2422195Sjulian
25161139Srikfor i in "" "conf" "i386" "i386/conf" "dev" "sys" "modules"
26161139Srikdo
27161139Srik	if [ -d ${TOP}/${i} ]
28161139Srik	then
29161139Srik		continue
30161139Srik	fi
31161139Srik	echo "${TOP}/${i}: no such directory."
32161139Srik	echo "Please, correct the error and try again."
33161139Srik	exit 1
34161139Srikdone
35161139Srik
36101214SmarkmUPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
37161139Srik
38161139Srikif [ -d ${TOP}/modules/${1} ]; then
39161139Srik	echo "There appears to already be a module called ${1}"
40161139Srik	echo -n "Should it be overwritten? [Y]"
41161139Srik	read VAL
42161139Srik	if [ "-z" "$VAL" ]; then
43161139Srik		VAL=YES
44161139Srik	fi
45161139Srik	case ${VAL} in
46161139Srik	[yY]*)
47161139Srik		echo "Cleaning up from prior runs"
48161139Srik		rm -rf ${TOP}/dev/${1}
49161139Srik		rm -rf ${TOP}/modules/${1}
50161139Srik		rm ${TOP}/conf/files.${UPPER}
51161139Srik		rm ${TOP}/i386/conf/${UPPER}
52161139Srik		rm ${TOP}/sys/${1}io.h
53161139Srik		;;
54161139Srik	*)
55161139Srik		exit 1
56161139Srik		;;
57161139Srik	esac
58161139Srikfi
59161139Srik
60161139Srikecho "The following files will be created:"
61161139Srikecho ${TOP}/modules/${1}
62161139Srikecho ${TOP}/conf/files.${UPPER}
63161139Srikecho ${TOP}/i386/conf/${UPPER}
64161139Srikecho ${TOP}/dev/${1}
65161139Srikecho ${TOP}/dev/${1}/${1}.c
66161139Srikecho ${TOP}/sys/${1}io.h
67161139Srikecho ${TOP}/modules/${1}
68161139Srikecho ${TOP}/modules/${1}/Makefile
69161139Srik
70161139Srikmkdir ${TOP}/modules/${1}
71161139Srik
72161139Srikcat >${TOP}/conf/files.${UPPER} <<DONE
73161559Srikdev/${1}/${1}.c      optional ${1}
7422195SjulianDONE
7522195Sjulian
76161139Srikcat >${TOP}/i386/conf/${UPPER} <<DONE
7722195Sjulian# Configuration file for kernel type: ${UPPER}
78101214Smarkm# \$FreeBSD\$
7922195Sjulian
80161139Srikfiles		"${TOP}/conf/files.${UPPER}"
8122195Sjulian
82161139Srikinclude		GENERIC
83161139Srik
84161139Srikident		${UPPER}
85161139Srik
8622195Sjulian# trust me, you'll need this
87161139Srikoptions		KDB
88161139Srikoptions		DDB
89161139Srikdevice		${1}
9022195SjulianDONE
9122195Sjulian
92161139Srikif [ ! -d ${TOP}/dev/${1} ]; then
93161139Srik	mkdir -p ${TOP}/dev/${1}
94161139Srikfi
95161139Srik
96161139Srikcat >${TOP}/dev/${1}/${1}.c <<DONE
9722195Sjulian/*
98161137Srik * Copyright (c) [year] [your name]
99161137Srik * All rights reserved.
10022195Sjulian *
101161137Srik * Redistribution and use in source and binary forms, with or without
102161137Srik * modification, are permitted provided that the following conditions
103161137Srik * are met:
104161137Srik * 1. Redistributions of source code must retain the above copyright
105161137Srik *    notice, this list of conditions and the following disclaimer.
106161137Srik * 2. Redistributions in binary form must reproduce the above copyright
107161137Srik *    notice, this list of conditions and the following disclaimer in the
108161137Srik *    documentation and/or other materials provided with the distribution.
109161137Srik *
110161137Srik * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
111161137Srik * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
112161137Srik * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
113161137Srik * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
114161137Srik * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
115161137Srik * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
116161137Srik * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
117161137Srik * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
118161137Srik * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
119161137Srik * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
120161137Srik * SUCH DAMAGE.
121161137Srik *
12222195Sjulian * ${1} driver
12322195Sjulian */
12422195Sjulian
125101214Smarkm#include <sys/cdefs.h>
126101214Smarkm__FBSDID("\$FreeBSD\$");
12722195Sjulian
12822195Sjulian#include <sys/param.h>
12922195Sjulian#include <sys/systm.h>
13022195Sjulian#include <sys/kernel.h>		/* SYSINIT stuff */
131161137Srik#include <sys/uio.h>		/* SYSINIT stuff */
13222195Sjulian#include <sys/conf.h>		/* cdevsw stuff */
13322195Sjulian#include <sys/malloc.h>		/* malloc region definitions */
13486327Sarr#include <sys/proc.h>
13522195Sjulian#include <sys/${1}io.h>		/* ${1} IOCTL definitions */
13622195Sjulian
137101214Smarkm#include <machine/clock.h>	/* DELAY() */
13822195Sjulian
139161137Srik#define N${UPPER}	3	/* defines number of instances */
14022195Sjulian
141161137Srik/* XXX These should be defined in terms of bus-space ops. */
142161137Srik#define ${UPPER}_INB(port) inb(port)
143161137Srik#define ${UPPER}_OUTB(port, val) (port, (val))
144161137Srik
14540592Sbde/* Function prototypes (these should all be static) */
14622195Sjulianstatic  d_open_t	${1}open;
14722195Sjulianstatic  d_close_t	${1}close;
14822195Sjulianstatic  d_read_t	${1}read;
14922195Sjulianstatic  d_write_t	${1}write;
15022195Sjulianstatic  d_ioctl_t	${1}ioctl;
15122195Sjulianstatic  d_mmap_t	${1}mmap;
15232111Sjulianstatic  d_poll_t	${1}poll;
153101214Smarkm
15422195Sjulian#define CDEV_MAJOR 20
15522195Sjulianstatic struct cdevsw ${1}_cdevsw = {
156161137Srik	.d_version =	D_VERSION,
157161137Srik	.d_open =	${1}open,
158161137Srik	.d_close =	${1}close,
159161137Srik	.d_read =	${1}read,
160161137Srik	.d_write =	${1}write,
161161137Srik	.d_ioctl =	${1}ioctl,
162161137Srik	.d_poll =	${1}poll,
163161137Srik	.d_mmap =	${1}mmap,
164161137Srik	.d_name =	"${1}",
165101214Smarkm};
166101214Smarkm
167101214Smarkm/*
168101214Smarkm * device  specific Misc defines
16922195Sjulian */
17022195Sjulian#define BUFFERSIZE 1024
171183416Sed#define UNIT(dev) dev2unit(dev)	/* assume one minor number per unit */
17222195Sjulian
17322195Sjulian/*
17422195Sjulian * One of these per allocated device
17522195Sjulian */
17622195Sjulianstruct ${1}_softc {
177161137Srik	u_long	iobase;
17822195Sjulian	char	buffer[BUFFERSIZE];
179161137Srik  	struct cdev *dev;
180101214Smarkm};
18122195Sjulian
18222195Sjuliantypedef	struct ${1}_softc *sc_p;
18322195Sjulian
18422195Sjulianstatic sc_p sca[N${UPPER}];
18522195Sjulian
186101214Smarkm/*
18722195Sjulian * Macro to check that the unit number is valid
18822195Sjulian * Often this isn't needed as once the open() is performed,
18922195Sjulian * the unit number is pretty much safe.. The exception would be if we
19022195Sjulian * implemented devices that could "go away". in which case all these routines
19122195Sjulian * would be wise to check the number, DIAGNOSTIC or not.
19222195Sjulian */
193101214Smarkm#define CHECKUNIT(RETVAL)						\
194101214Smarkmdo { /* the do-while is a safe way to do this grouping */		\
195101214Smarkm	if (unit > N${UPPER}) {						\
196143316Sstefanf		printf("%s: bad unit %d\n", __func__, unit);		\
197101214Smarkm		return (RETVAL);					\
198101214Smarkm	}								\
199101214Smarkm	if (scp == NULL) { 						\
200143316Sstefanf		printf("%s: unit %d not attached\n", __func__, unit);	\
201101214Smarkm		return (RETVAL);					\
202101214Smarkm	}								\
203101214Smarkm} while (0)
204101214Smarkm
20522195Sjulian#ifdef	DIAGNOSTIC
20622195Sjulian#define	CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
20722195Sjulian#else	/* DIAGNOSTIC */
20822195Sjulian#define	CHECKUNIT_DIAG(RETVAL)
20922195Sjulian#endif 	/* DIAGNOSTIC */
21022195Sjulian
211101214Smarkmstatic int
212161137Srik${1}ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
21322195Sjulian{
214101214Smarkm	int unit = UNIT(dev);
21522195Sjulian	sc_p scp  = sca[unit];
216101214Smarkm
21722195Sjulian	CHECKUNIT_DIAG(ENXIO);
218101214Smarkm
21922195Sjulian	switch (cmd) {
22022195Sjulian	    case DHIOCRESET:
22122195Sjulian		/*  whatever resets it */
222161137Srik		(void)scp; /* Delete this line after using scp. */
223161137Srik#if 0
224161137Srik		${UPPER}_OUTB(scp->iobase, 0xff);
225161137Srik#endif
22622195Sjulian		break;
22722195Sjulian	    default:
22822195Sjulian		return ENXIO;
22922195Sjulian	}
23022195Sjulian	return (0);
231101214Smarkm}
232101214Smarkm
23322195Sjulian/*
23422195Sjulian * You also need read, write, open, close routines.
23522195Sjulian * This should get you started
23622195Sjulian */
237101214Smarkmstatic int
238161137Srik${1}open(struct cdev *dev, int oflags, int devtype, struct thread *td)
23922195Sjulian{
240101214Smarkm	int unit = UNIT(dev);
24122195Sjulian	sc_p scp  = sca[unit];
242101214Smarkm
24322195Sjulian	CHECKUNIT(ENXIO);
24422195Sjulian
245161137Srik	(void)scp; /* Delete this line after using scp. */
246101214Smarkm	/*
24722195Sjulian	 * Do processing
24822195Sjulian	 */
24922195Sjulian	return (0);
25022195Sjulian}
25122195Sjulian
252101214Smarkmstatic int
253161137Srik${1}close(struct cdev *dev, int fflag, int devtype, struct thread *td)
25422195Sjulian{
255101214Smarkm	int unit = UNIT(dev);
25622195Sjulian	sc_p scp  = sca[unit];
257101214Smarkm
25822195Sjulian	CHECKUNIT_DIAG(ENXIO);
25922195Sjulian
260161137Srik	(void)scp; /* Delete this line after using scp. */
261101214Smarkm	/*
26222195Sjulian	 * Do processing
26322195Sjulian	 */
26422195Sjulian	return (0);
26522195Sjulian}
26622195Sjulian
267101214Smarkmstatic int
268161137Srik${1}read(struct cdev *dev, struct uio *uio, int ioflag)
26922195Sjulian{
270101214Smarkm	int unit = UNIT(dev);
27122195Sjulian	sc_p scp  = sca[unit];
27222195Sjulian	int     toread;
273101214Smarkm
274101214Smarkm
27522195Sjulian	CHECKUNIT_DIAG(ENXIO);
27622195Sjulian
277101214Smarkm	/*
27822195Sjulian	 * Do processing
27922195Sjulian	 * read from buffer
28022195Sjulian	 */
28122195Sjulian	toread = (min(uio->uio_resid, sizeof(scp->buffer)));
28222195Sjulian	return(uiomove(scp->buffer, toread, uio));
28322195Sjulian}
28422195Sjulian
285101214Smarkmstatic int
286161137Srik${1}write(struct cdev *dev, struct uio *uio, int ioflag)
28722195Sjulian{
288101214Smarkm	int unit = UNIT(dev);
28922195Sjulian	sc_p scp  = sca[unit];
29022195Sjulian	int	towrite;
291101214Smarkm
29222195Sjulian	CHECKUNIT_DIAG(ENXIO);
29322195Sjulian
294101214Smarkm	/*
29522195Sjulian	 * Do processing
29622195Sjulian	 * write to buffer
29722195Sjulian	 */
29822195Sjulian	towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
29922195Sjulian	return(uiomove(scp->buffer, towrite, uio));
30022195Sjulian}
30122195Sjulian
302101214Smarkmstatic int
303161137Srik${1}mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
30422195Sjulian{
305101214Smarkm	int unit = UNIT(dev);
30622195Sjulian	sc_p scp  = sca[unit];
307101214Smarkm
30822195Sjulian	CHECKUNIT_DIAG(-1);
30922195Sjulian
310161137Srik	(void)scp; /* Delete this line after using scp. */
311101214Smarkm	/*
31222195Sjulian	 * Do processing
31322195Sjulian	 */
31422195Sjulian#if 0	/* if we had a frame buffer or whatever.. do this */
31522195Sjulian	if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
31622195Sjulian		return (-1);
31722195Sjulian	}
31822195Sjulian	return i386_btop((FRAMEBASE + offset));
31922195Sjulian#else
32022195Sjulian	return (-1);
32122195Sjulian#endif
32222195Sjulian}
32322195Sjulian
324101214Smarkmstatic int
325161137Srik${1}poll(struct cdev *dev, int which, struct thread *td)
32622195Sjulian{
327101214Smarkm	int unit = UNIT(dev);
32822195Sjulian	sc_p scp  = sca[unit];
329101214Smarkm
33022195Sjulian	CHECKUNIT_DIAG(ENXIO);
33122195Sjulian
332161137Srik	(void)scp; /* Delete this line after using scp. */
333101214Smarkm	/*
33422195Sjulian	 * Do processing
33522195Sjulian	 */
33622195Sjulian	return (0); /* this is the wrong value I'm sure */
33722195Sjulian}
33822195Sjulian
33922195Sjulian/*
34022195Sjulian * Now  for some driver initialisation.
34122195Sjulian * Occurs ONCE during boot (very early).
34222195Sjulian */
343101214Smarkmstatic void
34422195Sjulian${1}_drvinit(void *unused)
34522195Sjulian{
34622195Sjulian	int	unit;
347183272Sed	sc_p	scp;
34822195Sjulian
34922195Sjulian	for (unit = 0; unit < N${UPPER}; unit++) {
350101214Smarkm		/*
35122195Sjulian		 * Allocate storage for this instance .
35222195Sjulian		 */
35386327Sarr		scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT | M_ZERO);
35422195Sjulian		if( scp == NULL) {
35522195Sjulian			printf("${1}%d failed to allocate strorage\n", unit);
356101214Smarkm			return;
35722195Sjulian		}
35822195Sjulian		sca[unit] = scp;
359161137Srik    		scp->dev = make_dev(&${1}_cdevsw, unit,
360161137Srik			UID_ROOT, GID_KMEM, 0640, "${1}%d", unit);
36122195Sjulian	}
36222195Sjulian}
36322195Sjulian
36422195SjulianSYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
365183272Sed		${1}_drvinit, NULL);
36622195SjulianDONE
36722195Sjulian
368161139Srikcat >${TOP}/sys/${1}io.h <<DONE
36922195Sjulian/*
37022195Sjulian * Definitions needed to access the ${1} device (ioctls etc)
37122195Sjulian * see mtio.h , ioctl.h as examples
37222195Sjulian */
37322195Sjulian#ifndef SYS_DHIO_H
37422195Sjulian#define SYS_DHIO_H
37522195Sjulian
37622195Sjulian#ifndef KERNEL
37722195Sjulian#include <sys/types.h>
37822195Sjulian#endif
37922195Sjulian#include <sys/ioccom.h>
38022195Sjulian
38122195Sjulian/*
38222195Sjulian * define an ioctl here
38322195Sjulian */
38422195Sjulian#define DHIOCRESET _IO('D', 0)   /* reset the ${1} device */
38522195Sjulian#endif
38622195SjulianDONE
38722195Sjulian
388161139Srikif [ ! -d ${TOP}/modules/${1} ]; then
389161139Srik	mkdir -p ${TOP}/modules/${1}
390161139Srikfi
39122195Sjulian
392161139Srikcat >${TOP}/modules/${1}/Makefile <<DONE
393161139Srik#	${UPPER} Loadable Kernel Module
394161139Srik#
395161139Srik# \$FreeBSD\$
396161139Srik
397161139Srik.PATH:  \${.CURDIR}/../../dev/${1}
398161139SrikKMOD    = ${1}
399161139SrikSRCS    = ${1}.c
400161139Srik
401161139Srik.include <bsd.kmod.mk>
402161139SrikDONE
403161139Srik
404161139Srikecho -n "Do you want to build the '${1}' module? [Y]"
405161139Srikread VAL
406161139Srikif [ "-z" "$VAL" ]; then
407161139Srik	VAL=YES
408161139Srikfi
409161139Srikcase ${VAL} in
410161139Srik[yY]*)
411161139Srik	(cd ${TOP}/modules/${1}; make depend; make )
412161139Srik	;;
413161139Srik*)
414161139Srik#	exit
415161139Srik	;;
416161139Srikesac
417161139Srik
418161139Srikecho ""
419161139Srikecho -n "Do you want to build the '${UPPER}' kernel? [Y]"
420161139Srikread VAL
421161139Srikif [ "-z" "$VAL" ]; then
422161139Srik	VAL=YES
423161139Srikfi
424161139Srikcase ${VAL} in
425161139Srik[yY]*)
426161139Srik	(
427161139Srik	 cd ${TOP}/i386/conf; \
428161139Srik	 config ${UPPER}; \
429161139Srik	 cd ${TOP}/i386/compile/${UPPER}; \
430161139Srik	 make depend; \
431161139Srik	 make; \
432161139Srik	)
433161139Srik	;;
434161139Srik*)
435161139Srik#	exit
436161139Srik	;;
437161139Srikesac
438161139Srik
43922195Sjulian#--------------end of script---------------
44022195Sjulian#
44122195Sjulian#edit to your taste..
44222195Sjulian#
443101214Smarkm#
444