xref: /freebsd/share/examples/drivers/make_device_driver.sh (revision 97232e04ca07dffeef629c1628f1cc95f062b41a)
15e176f9aSJulian Elischer#!/bin/sh
287e78fdfSJulian Elischer# This writes a skeleton driver and puts it into the kernel tree for you.
387e78fdfSJulian Elischer# It also adds FOO and files.FOO configuration files so you can compile
487e78fdfSJulian Elischer# a kernel with your FOO driver linked in.
587e78fdfSJulian Elischer# To do so:
611027719SBrian Somers# cd /usr/src; make buildkernel KERNCONF=FOO
75e176f9aSJulian Elischer#
887e78fdfSJulian Elischer# More interestingly, it creates a modules/foo directory
987e78fdfSJulian Elischer# which it populates, to allow you to compile a FOO module
1011027719SBrian Somers# which can be linked with your presently running kernel (if you feel brave).
1187e78fdfSJulian Elischer# To do so:
1287e78fdfSJulian Elischer# cd /sys/modules/foo; make depend; make; make install; kldload foo
1387e78fdfSJulian Elischer#
1487e78fdfSJulian Elischer# arg1 to this script is expected to be lowercase "foo"
1536a64d13SRoman Kurakin# arg2 path to the kernel sources, "/sys" if omitted
164308b695SJulian Elischer#
175e176f9aSJulian Elischer# Trust me, RUN THIS SCRIPT :)
1887e78fdfSJulian Elischer#
196715fca9SWarner Losh# TODO:
206715fca9SWarner Losh#   o generate foo_isa.c, foo_pci.c, foo_pccard.c, foo_cardbus.c, and foovar.h
216715fca9SWarner Losh#   o Put pccard stuff in here.
226715fca9SWarner Losh#
235e176f9aSJulian Elischer#
24e904636aSJulian Elischer#
25e4dcc1fdSDiomidis Spinellisif [ "X${1}" = "X" ]; then
26e4dcc1fdSDiomidis Spinellis	echo "Hey, how about some help here... give me a device name!"
275e176f9aSJulian Elischer	exit 1
285e176f9aSJulian Elischerfi
2936a64d13SRoman Kurakinif [ "X${2}" = "X" ]; then
3036a64d13SRoman Kurakin	TOP=`cd /sys; pwd -P`
3136a64d13SRoman Kurakin	echo "Using ${TOP} as the path to the kernel sources!"
3236a64d13SRoman Kurakinelse
3336a64d13SRoman Kurakin	TOP=${2}
3436a64d13SRoman Kurakinfi
3545b4f5afSJulian ElischerUPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
365e176f9aSJulian Elischer
37e4dcc1fdSDiomidis Spinellisif [ -d ${TOP}/modules/${1} ]; then
3887e78fdfSJulian Elischer	echo "There appears to already be a module called ${1}"
3987e78fdfSJulian Elischer	echo -n "Should it be overwritten? [Y]"
4087e78fdfSJulian Elischer	read VAL
41e4dcc1fdSDiomidis Spinellis	if [ "-z" "$VAL" ]; then
4287e78fdfSJulian Elischer		VAL=YES
4387e78fdfSJulian Elischer	fi
4487e78fdfSJulian Elischer	case ${VAL} in
4587e78fdfSJulian Elischer	[yY]*)
4687e78fdfSJulian Elischer		echo "Cleaning up from prior runs"
4787e78fdfSJulian Elischer		rm -rf ${TOP}/dev/${1}
4887e78fdfSJulian Elischer		rm -rf ${TOP}/modules/${1}
4936a64d13SRoman Kurakin		rm ${TOP}/conf/files.${UPPER}
5087e78fdfSJulian Elischer		rm ${TOP}/i386/conf/${UPPER}
5187e78fdfSJulian Elischer		rm ${TOP}/sys/${1}io.h
5287e78fdfSJulian Elischer		;;
5387e78fdfSJulian Elischer	*)
5487e78fdfSJulian Elischer		exit 1
5587e78fdfSJulian Elischer		;;
5687e78fdfSJulian Elischer	esac
5787e78fdfSJulian Elischerfi
5887e78fdfSJulian Elischer
5987e78fdfSJulian Elischerecho "The following files will be created:"
6045b4f5afSJulian Elischerecho ${TOP}/modules/${1}
6136a64d13SRoman Kurakinecho ${TOP}/conf/files.${UPPER}
6245b4f5afSJulian Elischerecho ${TOP}/i386/conf/${UPPER}
6345b4f5afSJulian Elischerecho ${TOP}/dev/${1}
6445b4f5afSJulian Elischerecho ${TOP}/dev/${1}/${1}.c
6545b4f5afSJulian Elischerecho ${TOP}/sys/${1}io.h
6645b4f5afSJulian Elischerecho ${TOP}/modules/${1}
6745b4f5afSJulian Elischerecho ${TOP}/modules/${1}/Makefile
6845b4f5afSJulian Elischer
6945b4f5afSJulian Elischer	mkdir ${TOP}/modules/${1}
704308b695SJulian Elischer
7145b4f5afSJulian Elischer#######################################################################
7245b4f5afSJulian Elischer#######################################################################
7345b4f5afSJulian Elischer#
7445b4f5afSJulian Elischer# Create configuration information needed to create a kernel
7545b4f5afSJulian Elischer# containing this driver.
7645b4f5afSJulian Elischer#
7745b4f5afSJulian Elischer# Not really needed if we are going to do this as a module.
7845b4f5afSJulian Elischer#######################################################################
7945b4f5afSJulian Elischer# First add the file to a local file list.
8045b4f5afSJulian Elischer#######################################################################
8145b4f5afSJulian Elischer
8236a64d13SRoman Kurakincat >${TOP}/conf/files.${UPPER} <<DONE
8345ddd9afSJulian Elischerdev/${1}/${1}.c	 optional ${1}
845e176f9aSJulian ElischerDONE
855e176f9aSJulian Elischer
8645b4f5afSJulian Elischer#######################################################################
8745b4f5afSJulian Elischer# Then create a configuration file for a kernel that contains this driver.
8845b4f5afSJulian Elischer#######################################################################
8945b4f5afSJulian Elischercat >${TOP}/i386/conf/${UPPER} <<DONE
905e176f9aSJulian Elischer# Configuration file for kernel type: ${UPPER}
915e176f9aSJulian Elischer
92be115021SRoman Kurakinfiles		"${TOP}/conf/files.${UPPER}"
93be115021SRoman Kurakin
9436a64d13SRoman Kurakininclude		GENERIC
9536a64d13SRoman Kurakin
9636a64d13SRoman Kurakinident		${UPPER}
9736a64d13SRoman Kurakin
9836a64d13SRoman KurakinDONE
995e176f9aSJulian Elischer
10045b4f5afSJulian Elischercat >>${TOP}/i386/conf/${UPPER} <<DONE
101be115021SRoman Kurakin# trust me, you'll need this
102be115021SRoman Kurakinoptions		KDB
103be115021SRoman Kurakinoptions		DDB
10445ddd9afSJulian Elischerdevice		${1}
1055e176f9aSJulian ElischerDONE
1065e176f9aSJulian Elischer
107e4dcc1fdSDiomidis Spinellisif [ ! -d ${TOP}/dev/${1} ]; then
10845b4f5afSJulian Elischer	mkdir -p ${TOP}/dev/${1}
10945b4f5afSJulian Elischerfi
11045b4f5afSJulian Elischer
11145b4f5afSJulian Elischercat >${TOP}/dev/${1}/${1}.c <<DONE
1125e176f9aSJulian Elischer/*
11396305e8fSJulian Elischer * Copyright (c) [year] [your name]
11496305e8fSJulian Elischer *
11596305e8fSJulian Elischer * Redistribution and use in source and binary forms, with or without
11696305e8fSJulian Elischer * modification, are permitted provided that the following conditions
11796305e8fSJulian Elischer * are met:
11896305e8fSJulian Elischer * 1. Redistributions of source code must retain the above copyright
11996305e8fSJulian Elischer *    notice, this list of conditions and the following disclaimer.
12096305e8fSJulian Elischer * 2. Redistributions in binary form must reproduce the above copyright
12196305e8fSJulian Elischer *    notice, this list of conditions and the following disclaimer in the
12296305e8fSJulian Elischer *    documentation and/or other materials provided with the distribution.
12396305e8fSJulian Elischer *
12496305e8fSJulian Elischer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
12596305e8fSJulian Elischer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12696305e8fSJulian Elischer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12796305e8fSJulian Elischer * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
12896305e8fSJulian Elischer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12996305e8fSJulian Elischer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13096305e8fSJulian Elischer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13196305e8fSJulian Elischer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13296305e8fSJulian Elischer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13396305e8fSJulian Elischer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13496305e8fSJulian Elischer * SUCH DAMAGE.
1355e176f9aSJulian Elischer */
1365e176f9aSJulian Elischer
1374a3a6ee4SJulian Elischer/*
1384a3a6ee4SJulian Elischer * http://www.daemonnews.org/200008/isa.html is required reading.
1394a3a6ee4SJulian Elischer * hopefully it will make it's way into the handbook.
1404a3a6ee4SJulian Elischer */
1415e176f9aSJulian Elischer
1425e176f9aSJulian Elischer#include <sys/param.h>
1435e176f9aSJulian Elischer#include <sys/systm.h>
1445e176f9aSJulian Elischer#include <sys/conf.h>		/* cdevsw stuff */
14545b4f5afSJulian Elischer#include <sys/kernel.h>		/* SYSINIT stuff */
14645b4f5afSJulian Elischer#include <sys/uio.h>		/* SYSINIT stuff */
1475e176f9aSJulian Elischer#include <sys/malloc.h>		/* malloc region definitions */
14845b4f5afSJulian Elischer#include <sys/module.h>
14945b4f5afSJulian Elischer#include <sys/bus.h>
150853fbff5SAndrew R. Reiter#include <sys/proc.h>
151418df1e4SMark Murray#include <sys/time.h>
152418df1e4SMark Murray#include <sys/${1}io.h>		/* ${1} IOCTL definitions */
153418df1e4SMark Murray
15445b4f5afSJulian Elischer#include <machine/bus.h>
15545b4f5afSJulian Elischer#include <machine/resource.h>
156ff7cd805SDiomidis Spinellis#include <sys/rman.h>
1575e176f9aSJulian Elischer
158ff7cd805SDiomidis Spinellis#include <dev/pci/pcireg.h>
159ff7cd805SDiomidis Spinellis#include <dev/pci/pcivar.h>
160e904636aSJulian Elischer
16145b4f5afSJulian Elischer#include <isa/isavar.h>
162418df1e4SMark Murray
16345b4f5afSJulian Elischer#include "isa_if.h"
16445b4f5afSJulian Elischer
165e4dcc1fdSDiomidis Spinellis/* XXX These should be defined in terms of bus-space ops. */
16687e78fdfSJulian Elischer#define ${UPPER}_INB(port) inb(port_start)
16787e78fdfSJulian Elischer#define ${UPPER}_OUTB(port, val) ( port_start, (val))
16845b4f5afSJulian Elischer#define SOME_PORT 123
16945b4f5afSJulian Elischer#define EXPECTED_VALUE 0x42
1705e176f9aSJulian Elischer
17111027719SBrian Somers/*
17211027719SBrian Somers * The softc is automatically allocated by the parent bus using the
173e4dcc1fdSDiomidis Spinellis * size specified in the driver_t declaration below.
17411027719SBrian Somers */
1756715fca9SWarner Losh#define DEV2SOFTC(dev)	((struct ${1}_softc *) (dev)->si_drv1)
1766715fca9SWarner Losh#define DEVICE2SOFTC(dev) ((struct ${1}_softc *) device_get_softc(dev))
1776715fca9SWarner Losh
1785e176f9aSJulian Elischer/*
179e4dcc1fdSDiomidis Spinellis * Device specific misc defines.
1805e176f9aSJulian Elischer */
1815e176f9aSJulian Elischer#define BUFFERSIZE	1024
1825e176f9aSJulian Elischer#define NUMPORTS	4
183e4dcc1fdSDiomidis Spinellis#define MEMSIZE		(4 * 1024) /* Imaginable h/w buffer size. */
1845e176f9aSJulian Elischer
1855e176f9aSJulian Elischer/*
186e4dcc1fdSDiomidis Spinellis * One of these per allocated device.
1875e176f9aSJulian Elischer */
1885e176f9aSJulian Elischerstruct ${1}_softc {
18945b4f5afSJulian Elischer	bus_space_tag_t bt;
19045b4f5afSJulian Elischer	bus_space_handle_t bh;
191d1d3a974SJulian Elischer	int rid_ioport;
192d1d3a974SJulian Elischer	int rid_memory;
193d1d3a974SJulian Elischer	int rid_irq;
194d1d3a974SJulian Elischer	int rid_drq;
195e4dcc1fdSDiomidis Spinellis	struct resource* res_ioport;	/* Resource for port range. */
196e4dcc1fdSDiomidis Spinellis	struct resource* res_memory;	/* Resource for mem range. */
197e4dcc1fdSDiomidis Spinellis	struct resource* res_irq;	/* Resource for irq range. */
198e4dcc1fdSDiomidis Spinellis	struct resource* res_drq;	/* Resource for dma channel. */
19945b4f5afSJulian Elischer	device_t device;
200a299217fSRoman Kurakin	struct cdev *dev;
201d1d3a974SJulian Elischer	void	*intr_cookie;
202e4dcc1fdSDiomidis Spinellis	void	*vaddr;			/* Virtual address of mem resource. */
203e4dcc1fdSDiomidis Spinellis	char	buffer[BUFFERSIZE];	/* If we need to buffer something. */
2045e176f9aSJulian Elischer};
2055e176f9aSJulian Elischer
206e4dcc1fdSDiomidis Spinellis/* Function prototypes (these should all be static). */
207e904636aSJulian Elischerstatic int ${1}_deallocate_resources(device_t device);
208e904636aSJulian Elischerstatic int ${1}_allocate_resources(device_t device);
2096715fca9SWarner Loshstatic int ${1}_attach(device_t device, struct ${1}_softc *scp);
2106715fca9SWarner Loshstatic int ${1}_detach(device_t device, struct ${1}_softc *scp);
211e904636aSJulian Elischer
212e904636aSJulian Elischerstatic d_open_t		${1}open;
213e904636aSJulian Elischerstatic d_close_t	${1}close;
214e904636aSJulian Elischerstatic d_read_t		${1}read;
215e904636aSJulian Elischerstatic d_write_t	${1}write;
216e904636aSJulian Elischerstatic d_ioctl_t	${1}ioctl;
217e904636aSJulian Elischerstatic d_mmap_t		${1}mmap;
218e904636aSJulian Elischerstatic d_poll_t		${1}poll;
219e904636aSJulian Elischerstatic	void		${1}intr(void *arg);
220e904636aSJulian Elischer
221e904636aSJulian Elischerstatic struct cdevsw ${1}_cdevsw = {
222a299217fSRoman Kurakin	.d_version =	D_VERSION,
223ff7cd805SDiomidis Spinellis	.d_open =	${1}open,
224ff7cd805SDiomidis Spinellis	.d_close =	${1}close,
225ff7cd805SDiomidis Spinellis	.d_read =	${1}read,
226ff7cd805SDiomidis Spinellis	.d_write =	${1}write,
227ff7cd805SDiomidis Spinellis	.d_ioctl =	${1}ioctl,
228ff7cd805SDiomidis Spinellis	.d_poll =	${1}poll,
229ff7cd805SDiomidis Spinellis	.d_mmap =	${1}mmap,
230ff7cd805SDiomidis Spinellis	.d_name =	"${1}",
231e904636aSJulian Elischer};
232e904636aSJulian Elischer
2337dd17df7SJulian Elischerstatic devclass_t ${1}_devclass;
2347dd17df7SJulian Elischer
2356715fca9SWarner Losh/*
236e4dcc1fdSDiomidis Spinellis ******************************************
237e4dcc1fdSDiomidis Spinellis * ISA Attachment structures and functions.
238e4dcc1fdSDiomidis Spinellis ******************************************
2396715fca9SWarner Losh */
240e904636aSJulian Elischerstatic void ${1}_isa_identify (driver_t *, device_t);
241e904636aSJulian Elischerstatic int ${1}_isa_probe (device_t);
242e904636aSJulian Elischerstatic int ${1}_isa_attach (device_t);
243e904636aSJulian Elischerstatic int ${1}_isa_detach (device_t);
2445e176f9aSJulian Elischer
24545b4f5afSJulian Elischerstatic struct isa_pnp_id ${1}_ids[] = {
24645b4f5afSJulian Elischer	{0x12345678,	"ABCco Widget"},
24745b4f5afSJulian Elischer	{0xfedcba98,	"shining moon Widget ripoff"},
2484a3a6ee4SJulian Elischer	{0,		NULL}
24945b4f5afSJulian Elischer};
25045b4f5afSJulian Elischer
25145b4f5afSJulian Elischerstatic device_method_t ${1}_methods[] = {
25287e78fdfSJulian Elischer	DEVMETHOD(device_identify,	${1}_isa_identify),
25345b4f5afSJulian Elischer	DEVMETHOD(device_probe,		${1}_isa_probe),
25445b4f5afSJulian Elischer	DEVMETHOD(device_attach,	${1}_isa_attach),
25545b4f5afSJulian Elischer	DEVMETHOD(device_detach,	${1}_isa_detach),
256*a9029fbbSMarius Strobl	DEVMETHOD_END
25745b4f5afSJulian Elischer};
25845b4f5afSJulian Elischer
25945b4f5afSJulian Elischerstatic driver_t ${1}_isa_driver = {
26045b4f5afSJulian Elischer	"${1}",
26145b4f5afSJulian Elischer	${1}_methods,
26245b4f5afSJulian Elischer	sizeof (struct ${1}_softc)
26345b4f5afSJulian Elischer};
26445b4f5afSJulian Elischer
26545b4f5afSJulian ElischerDRIVER_MODULE(${1}, isa, ${1}_isa_driver, ${1}_devclass, 0, 0);
26645b4f5afSJulian Elischer
26787e78fdfSJulian Elischer/*
26887e78fdfSJulian Elischer * Here list some port addresses we might expect our widget to appear at:
2696715fca9SWarner Losh * This list should only be used for cards that have some non-destructive
2706715fca9SWarner Losh * (to other cards) way of probing these address.  Otherwise the driver
2716715fca9SWarner Losh * should not go looking for instances of itself, but instead rely on
2726715fca9SWarner Losh * the hints file.  Strange failures for people with other cards might
2736715fca9SWarner Losh * result.
27487e78fdfSJulian Elischer */
27587e78fdfSJulian Elischerstatic struct localhints {
27687e78fdfSJulian Elischer	int ioport;
27787e78fdfSJulian Elischer	int irq;
27887e78fdfSJulian Elischer	int drq;
27987e78fdfSJulian Elischer	int mem;
28087e78fdfSJulian Elischer} res[] = {
28187e78fdfSJulian Elischer	{ 0x210, 11, 2, 0xcd000},
28287e78fdfSJulian Elischer	{ 0x310, 12, 3, 0xdd000},
28387e78fdfSJulian Elischer	{ 0x320, 9, 6, 0xd4000},
28487e78fdfSJulian Elischer	{0,0,0,0}
28587e78fdfSJulian Elischer};
28645b4f5afSJulian Elischer
287e4dcc1fdSDiomidis Spinellis#define MAXHINTS 10 /* Just an arbitrary safety limit. */
28887e78fdfSJulian Elischer/*
2894a3a6ee4SJulian Elischer * Called once when the driver is somehow connected with the bus,
2904a3a6ee4SJulian Elischer * (Either linked in and the bus is started, or loaded as a module).
2914a3a6ee4SJulian Elischer *
2924a3a6ee4SJulian Elischer * The aim of this routine in an ISA driver is to add child entries to
2934a3a6ee4SJulian Elischer * the parent bus so that it looks as if the devices were detected by
29411027719SBrian Somers * some pnp-like method, or at least mentioned in the hints.
2954a3a6ee4SJulian Elischer *
2964a3a6ee4SJulian Elischer * For NON-PNP "dumb" devices:
29787e78fdfSJulian Elischer * Add entries into the bus's list of likely devices, so that
29887e78fdfSJulian Elischer * our 'probe routine' will be called for them.
29987e78fdfSJulian Elischer * This is similar to what the 'hints' code achieves, except this is
30087e78fdfSJulian Elischer * loadable with the driver.
3014a3a6ee4SJulian Elischer * In the 'dumb' case we end up with more children than needed but
3024a3a6ee4SJulian Elischer * some (or all) of them will fail probe() and only waste a little memory.
3034a3a6ee4SJulian Elischer *
3044a3a6ee4SJulian Elischer * For NON-PNP "Smart" devices:
3054a3a6ee4SJulian Elischer * If the device has a NON-PNP way of being detected and setting/sensing
3064a3a6ee4SJulian Elischer * the card, then do that here and add a child for each set of
3074a3a6ee4SJulian Elischer * hardware found.
3084a3a6ee4SJulian Elischer *
3094a3a6ee4SJulian Elischer * For PNP devices:
3104a3a6ee4SJulian Elischer * If the device is always PNP capable then this function can be removed.
3116715fca9SWarner Losh * The ISA PNP system will have automatically added it to the system and
3126715fca9SWarner Losh * so your identify routine needn't do anything.
3134a3a6ee4SJulian Elischer *
31411027719SBrian Somers * If the device is mentioned in the 'hints' file then this
31511027719SBrian Somers * function can be removed. All devices mentioned in the hints
3164a3a6ee4SJulian Elischer * file get added as children for probing, whether or not the
3174a3a6ee4SJulian Elischer * driver is linked in. So even as a module it MAY still be there.
3184a3a6ee4SJulian Elischer * See isa/isahint.c for hints being added in.
31987e78fdfSJulian Elischer */
32087e78fdfSJulian Elischerstatic void
32187e78fdfSJulian Elischer${1}_isa_identify (driver_t *driver, device_t parent)
32287e78fdfSJulian Elischer{
32387e78fdfSJulian Elischer	u_int32_t	irq=0;
32487e78fdfSJulian Elischer	u_int32_t	ioport;
32587e78fdfSJulian Elischer	device_t	child;
32687e78fdfSJulian Elischer	int i;
32787e78fdfSJulian Elischer
32887e78fdfSJulian Elischer	/*
32987e78fdfSJulian Elischer	 * If we've already got ${UPPER} attached somehow, don't try again.
3304a3a6ee4SJulian Elischer	 * Maybe it was in the hints file. or it was loaded before.
33187e78fdfSJulian Elischer	 */
33287e78fdfSJulian Elischer	if (device_find_child(parent, "${1}", 0)) {
33387e78fdfSJulian Elischer		printf("${UPPER}: already attached\n");
33487e78fdfSJulian Elischer		return;
33587e78fdfSJulian Elischer	}
336e4dcc1fdSDiomidis Spinellis/* XXX Look at dev/acpica/acpi_isa.c for use of ISA_ADD_CONFIG() macro. */
33787e78fdfSJulian Elischer/* XXX What is ISA_SET_CONFIG_CALLBACK(parent, child, pnpbios_set_config, 0)? */
33887e78fdfSJulian Elischer	for (i = 0; i < MAXHINTS; i++) {
33999fcf983SJulian Elischer
34099fcf983SJulian Elischer		ioport = res[i].ioport;
34199fcf983SJulian Elischer		irq = res[i].irq;
342418df1e4SMark Murray		if ((ioport == 0) && (irq == 0))
343e4dcc1fdSDiomidis Spinellis			return; /* We've added all our local hints. */
34487e78fdfSJulian Elischer
34587e78fdfSJulian Elischer		child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "${1}", -1);
34687e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_IOPORT,	0, ioport, NUMPORTS);
34787e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_IRQ,	0, irq, 1);
34887e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_DRQ,	0, res[i].drq, 1);
34987e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_MEMORY,	0, res[i].mem, MEMSIZE);
35087e78fdfSJulian Elischer
35187e78fdfSJulian Elischer#if 0
35287e78fdfSJulian Elischer		/*
35387e78fdfSJulian Elischer		 * If we wanted to pretend PNP found it
35487e78fdfSJulian Elischer		 * we could do this, and put matching entries
35587e78fdfSJulian Elischer		 * in the PNP table, but I think it's probably too hacky.
35687e78fdfSJulian Elischer		 * As you see, some people have done it though.
357e4dcc1fdSDiomidis Spinellis		 * Basically EISA (remember that?) would do this I think.
35887e78fdfSJulian Elischer		 */
35987e78fdfSJulian Elischer		isa_set_vendorid(child, PNP_EISAID("ESS1888"));
36087e78fdfSJulian Elischer		isa_set_logicalid(child, PNP_EISAID("ESS1888"));
36187e78fdfSJulian Elischer#endif
36287e78fdfSJulian Elischer	}
3634a3a6ee4SJulian Elischer#if 0
3646715fca9SWarner Losh	/*
3656715fca9SWarner Losh	 * Do some smart probing (e.g. like the lnc driver)
3666715fca9SWarner Losh	 * and add a child for each one found.
3676715fca9SWarner Losh	 */
3684a3a6ee4SJulian Elischer#endif
36987e78fdfSJulian Elischer
37087e78fdfSJulian Elischer	return;
37187e78fdfSJulian Elischer}
37245b4f5afSJulian Elischer/*
37345b4f5afSJulian Elischer * The ISA code calls this for each device it knows about,
37445b4f5afSJulian Elischer * whether via the PNP code or via the hints etc.
3754a3a6ee4SJulian Elischer * If the device nas no PNP capabilities, remove all the
3764a3a6ee4SJulian Elischer * PNP entries, but keep the call to ISA_PNP_PROBE()
3774a3a6ee4SJulian Elischer * As it will guard against accidentally recognising
3784a3a6ee4SJulian Elischer * foreign hardware. This is because we will be called to check against
3794a3a6ee4SJulian Elischer * ALL PNP hardware.
38045b4f5afSJulian Elischer */
3815e176f9aSJulian Elischerstatic int
38245b4f5afSJulian Elischer${1}_isa_probe (device_t device)
3835e176f9aSJulian Elischer{
38445b4f5afSJulian Elischer	int error;
38587e78fdfSJulian Elischer	device_t parent = device_get_parent(device);
3866715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
38787e78fdfSJulian Elischer	u_long	port_start, port_count;
38887e78fdfSJulian Elischer
38945b4f5afSJulian Elischer	bzero(scp, sizeof(*scp));
39045b4f5afSJulian Elischer	scp->device = device;
3915e176f9aSJulian Elischer
3925e176f9aSJulian Elischer	/*
393e4dcc1fdSDiomidis Spinellis	 * Check this device for a PNP match in our table.
39445b4f5afSJulian Elischer	 * There are several possible outcomes.
395e4dcc1fdSDiomidis Spinellis	 * error == 0		We match a PNP.
39611027719SBrian Somers	 * error == ENXIO,	It is a PNP device but not in our table.
39711027719SBrian Somers	 * error == ENOENT,	It is not a PNP device.. try heuristic probes.
39845b4f5afSJulian Elischer	 *    -- logic from if_ed_isa.c, added info from isa/isa_if.m:
39999fcf983SJulian Elischer	 *
40099fcf983SJulian Elischer	 * If we had a list of devices that we could handle really well,
40199fcf983SJulian Elischer	 * and a list which we could handle only basic functions, then
40299fcf983SJulian Elischer	 * we would call this twice, once for each list,
40399fcf983SJulian Elischer	 * and return a value of '-2' or something if we could
40499fcf983SJulian Elischer	 * only handle basic functions. This would allow a specific
40599fcf983SJulian Elischer	 * Widgetplus driver to make a better offer if it knows how to
406e4dcc1fdSDiomidis Spinellis	 * do all the extended functions. (See non-pnp part for more info).
4075e176f9aSJulian Elischer	 */
40887e78fdfSJulian Elischer	error = ISA_PNP_PROBE(parent, device, ${1}_ids);
40945b4f5afSJulian Elischer	switch (error) {
41045b4f5afSJulian Elischer	case 0:
41145b4f5afSJulian Elischer		/*
41245b4f5afSJulian Elischer		 * We found a PNP device.
413e4dcc1fdSDiomidis Spinellis		 * Do nothing, as it's all done in attach().
41445b4f5afSJulian Elischer		 */
41545ddd9afSJulian Elischer		break;
41645b4f5afSJulian Elischer	case ENOENT:
41745b4f5afSJulian Elischer		/*
41845b4f5afSJulian Elischer		 * Well it didn't show up in the PNP tables
41945b4f5afSJulian Elischer		 * so look directly at known ports (if we have any)
42045b4f5afSJulian Elischer		 * in case we are looking for an old pre-PNP card.
42145b4f5afSJulian Elischer		 *
42287e78fdfSJulian Elischer		 * Hopefully the  'identify' routine will have picked these
42399fcf983SJulian Elischer		 * up for us first if they use some proprietary detection
42499fcf983SJulian Elischer		 * method.
42587e78fdfSJulian Elischer		 *
42699fcf983SJulian Elischer		 * The ports, irqs etc should come from a 'hints' section
42745b4f5afSJulian Elischer		 * which is read in by code in isa/isahint.c
4284a3a6ee4SJulian Elischer		 * and kern/subr_bus.c to create resource entries,
4294a3a6ee4SJulian Elischer		 * or have been added by the 'identify routine above.
43011027719SBrian Somers		 * Note that HINTS based resource requests have NO
43199fcf983SJulian Elischer		 * SIZE for the memory or ports requests  (just a base)
43299fcf983SJulian Elischer		 * so we may need to 'correct' this before we
43399fcf983SJulian Elischer		 * do any probing.
43499fcf983SJulian Elischer		 */
43599fcf983SJulian Elischer		/*
436e4dcc1fdSDiomidis Spinellis		 * Find out the values of any resources we
43799fcf983SJulian Elischer		 * need for our dumb probe. Also check we have enough ports
43899fcf983SJulian Elischer		 * in the request. (could be hints based).
43999fcf983SJulian Elischer		 * Should probably do the same for memory regions too.
44099fcf983SJulian Elischer		 */
44199fcf983SJulian Elischer		error = bus_get_resource(device, SYS_RES_IOPORT, 0,
44299fcf983SJulian Elischer		    &port_start, &port_count);
44399fcf983SJulian Elischer		if (port_count != NUMPORTS) {
44499fcf983SJulian Elischer			bus_set_resource(device, SYS_RES_IOPORT, 0,
44599fcf983SJulian Elischer			    port_start, NUMPORTS);
44699fcf983SJulian Elischer		}
44799fcf983SJulian Elischer
44899fcf983SJulian Elischer		/*
44999fcf983SJulian Elischer		 * Make a temporary resource reservation.
4504a3a6ee4SJulian Elischer		 * If we can't get the resources we need then
4514a3a6ee4SJulian Elischer		 * we need to abort.  Possibly this indicates
45299fcf983SJulian Elischer		 * the resources were used by another device
45399fcf983SJulian Elischer		 * in which case the probe would have failed anyhow.
45445b4f5afSJulian Elischer		 */
4554a3a6ee4SJulian Elischer		if ((error = (${1}_allocate_resources(device)))) {
4564a3a6ee4SJulian Elischer			error = ENXIO;
4574a3a6ee4SJulian Elischer			goto errexit;
45887e78fdfSJulian Elischer		}
45987e78fdfSJulian Elischer
460e4dcc1fdSDiomidis Spinellis		/* Dummy heuristic type probe. */
4614a3a6ee4SJulian Elischer		if (inb(port_start) != EXPECTED_VALUE) {
4625e176f9aSJulian Elischer			/*
46387e78fdfSJulian Elischer			 * It isn't what we hoped, so quit looking for it.
4645e176f9aSJulian Elischer			 */
46545ddd9afSJulian Elischer			error = ENXIO;
46645ddd9afSJulian Elischer		} else {
4674a3a6ee4SJulian Elischer			u_long membase = bus_get_resource_start(device,
4684a3a6ee4SJulian Elischer					SYS_RES_MEMORY, 0 /*rid*/);
4694a3a6ee4SJulian Elischer			u_long memsize;
4704a3a6ee4SJulian Elischer			/*
4714a3a6ee4SJulian Elischer			 * If we discover in some way that the device has
4724a3a6ee4SJulian Elischer			 * XXX bytes of memory window, we can override
4734a3a6ee4SJulian Elischer			 * or set the memory size in the child resource list.
4744a3a6ee4SJulian Elischer			 */
4754a3a6ee4SJulian Elischer			memsize = inb(port_start + 1) * 1024; /* for example */
4764a3a6ee4SJulian Elischer			error = bus_set_resource(device, SYS_RES_MEMORY,
4774a3a6ee4SJulian Elischer				/*rid*/0, membase, memsize);
47845ddd9afSJulian Elischer			/*
47999fcf983SJulian Elischer			 * We found one, return non-positive numbers..
4805665fe6bSUlrich Spörlein			 * Return -N if we can't handle it, but not well.
481e4dcc1fdSDiomidis Spinellis			 * Return -2 if we would LIKE the device.
482e4dcc1fdSDiomidis Spinellis			 * Return -1 if we want it a lot.
483e4dcc1fdSDiomidis Spinellis			 * Return 0 if we MUST get the device.
4844a3a6ee4SJulian Elischer			 * This allows drivers to 'bid' for a device.
48545ddd9afSJulian Elischer			 */
4864a3a6ee4SJulian Elischer			device_set_desc(device, "ACME Widget model 1234");
487e4dcc1fdSDiomidis Spinellis			error = -1; /* We want it but someone else
488e4dcc1fdSDiomidis Spinellis					may be even better. */
48945ddd9afSJulian Elischer		}
4904a3a6ee4SJulian Elischer		/*
4914a3a6ee4SJulian Elischer		 * Unreserve the resources for now because
4924a3a6ee4SJulian Elischer		 * another driver may bid for device too.
49311027719SBrian Somers		 * If we lose the bid, but still hold the resources, we will
49411027719SBrian Somers		 * effectively have disabled the other driver from getting them
4954a3a6ee4SJulian Elischer		 * which will result in neither driver getting the device.
4964a3a6ee4SJulian Elischer		 * We will ask for them again in attach if we win.
4974a3a6ee4SJulian Elischer		 */
4984a3a6ee4SJulian Elischer		${1}_deallocate_resources(device);
49945b4f5afSJulian Elischer		break;
50045b4f5afSJulian Elischer	case  ENXIO:
501e4dcc1fdSDiomidis Spinellis		/* It was PNP but not ours, leave immediately. */
50245b4f5afSJulian Elischer	default:
50345b4f5afSJulian Elischer		error = ENXIO;
50445b4f5afSJulian Elischer	}
5054a3a6ee4SJulian Elischererrexit:
50645b4f5afSJulian Elischer	return (error);
5075e176f9aSJulian Elischer}
5085e176f9aSJulian Elischer
5095e176f9aSJulian Elischer/*
5104a3a6ee4SJulian Elischer * Called if the probe succeeded and our bid won the device.
5115e176f9aSJulian Elischer * We can be destructive here as we know we have the device.
5124a3a6ee4SJulian Elischer * This is the first place we can be sure we have a softc structure.
513e904636aSJulian Elischer * You would do ISA specific attach things here, but generically there aren't
514e4dcc1fdSDiomidis Spinellis * any (yay new-bus!).
5155e176f9aSJulian Elischer */
5165e176f9aSJulian Elischerstatic int
51745b4f5afSJulian Elischer${1}_isa_attach (device_t device)
5185e176f9aSJulian Elischer{
519e904636aSJulian Elischer        int	error;
5206715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
521e904636aSJulian Elischer
522e904636aSJulian Elischer        error =  ${1}_attach(device, scp);
523418df1e4SMark Murray        if (error)
524e904636aSJulian Elischer                ${1}_isa_detach(device);
525e904636aSJulian Elischer        return (error);
526e904636aSJulian Elischer}
527e904636aSJulian Elischer
528e904636aSJulian Elischer/*
529e4dcc1fdSDiomidis Spinellis * Detach the driver (e.g. module unload),
530e904636aSJulian Elischer * call the bus independent version
531e904636aSJulian Elischer * and undo anything we did in the ISA attach routine.
532e904636aSJulian Elischer */
533e904636aSJulian Elischerstatic int
534e904636aSJulian Elischer${1}_isa_detach (device_t device)
535e904636aSJulian Elischer{
536e904636aSJulian Elischer        int	error;
5376715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
538e904636aSJulian Elischer
539e904636aSJulian Elischer        error =  ${1}_detach(device, scp);
540e904636aSJulian Elischer        return (error);
541e904636aSJulian Elischer}
542e904636aSJulian Elischer
5436715fca9SWarner Losh/*
5446715fca9SWarner Losh ***************************************
5456715fca9SWarner Losh * PCI Attachment structures and code
5466715fca9SWarner Losh ***************************************
5476715fca9SWarner Losh */
548e904636aSJulian Elischer
549418df1e4SMark Murraystatic int	${1}_pci_probe(device_t);
550418df1e4SMark Murraystatic int	${1}_pci_attach(device_t);
551418df1e4SMark Murraystatic int	${1}_pci_detach(device_t);
552e904636aSJulian Elischer
553e904636aSJulian Elischerstatic device_method_t ${1}_pci_methods[] = {
554e904636aSJulian Elischer	/* Device interface */
555e904636aSJulian Elischer	DEVMETHOD(device_probe,		${1}_pci_probe),
556e904636aSJulian Elischer	DEVMETHOD(device_attach,	${1}_pci_attach),
557e904636aSJulian Elischer	DEVMETHOD(device_detach,	${1}_pci_detach),
558e904636aSJulian Elischer	{ 0, 0 }
559e904636aSJulian Elischer};
560e904636aSJulian Elischer
561e904636aSJulian Elischerstatic driver_t ${1}_pci_driver = {
562e904636aSJulian Elischer	"${1}",
563e904636aSJulian Elischer	${1}_pci_methods,
564e904636aSJulian Elischer	sizeof(struct ${1}_softc),
565e904636aSJulian Elischer};
566e904636aSJulian Elischer
5677dd17df7SJulian ElischerDRIVER_MODULE(${1}, pci, ${1}_pci_driver, ${1}_devclass, 0, 0);
5686715fca9SWarner Losh/*
5696715fca9SWarner Losh * Cardbus is a pci bus plus extra, so use the pci driver unless special
5706715fca9SWarner Losh * things need to be done only in the cardbus case.
5716715fca9SWarner Losh */
5726715fca9SWarner LoshDRIVER_MODULE(${1}, cardbus, ${1}_pci_driver, ${1}_devclass, 0, 0);
573e904636aSJulian Elischer
574e904636aSJulian Elischerstatic struct _pcsid
575e904636aSJulian Elischer{
576e904636aSJulian Elischer	u_int32_t	type;
577e904636aSJulian Elischer	const char	*desc;
578e904636aSJulian Elischer} pci_ids[] = {
579e904636aSJulian Elischer	{ 0x1234abcd,	"ACME PCI Widgetplus"	},
5806715fca9SWarner Losh	{ 0x1243fedc,	"Happy moon brand RIPOFFplus"	},
581e904636aSJulian Elischer	{ 0x00000000,	NULL					}
582e904636aSJulian Elischer};
583e904636aSJulian Elischer
58499fcf983SJulian Elischer/*
58511027719SBrian Somers * See if this card is specifically mentioned in our list of known devices.
58699fcf983SJulian Elischer * Theoretically we might also put in a weak bid for some devices that
5876715fca9SWarner Losh * report themselves to be some generic type of device if we can handle
58899fcf983SJulian Elischer * that generic type. (other PCI_XXX calls give that info).
58999fcf983SJulian Elischer * This would allow a specific driver to over-ride us.
59099fcf983SJulian Elischer *
59199fcf983SJulian Elischer * See the comments in the ISA section regarding returning non-positive
59299fcf983SJulian Elischer * values from probe routines.
59399fcf983SJulian Elischer */
594e904636aSJulian Elischerstatic int
595e904636aSJulian Elischer${1}_pci_probe (device_t device)
596e904636aSJulian Elischer{
597e904636aSJulian Elischer	u_int32_t	type = pci_get_devid(device);
598e904636aSJulian Elischer	struct _pcsid	*ep =pci_ids;
599e904636aSJulian Elischer
600e904636aSJulian Elischer	while (ep->type && ep->type != type)
601e904636aSJulian Elischer		++ep;
602e904636aSJulian Elischer	if (ep->desc) {
603e904636aSJulian Elischer		device_set_desc(device, ep->desc);
6046715fca9SWarner Losh		return 0; /* If there might be a better driver, return -2 */
605418df1e4SMark Murray	} else
606e904636aSJulian Elischer		return ENXIO;
607e904636aSJulian Elischer}
608e904636aSJulian Elischer
609e904636aSJulian Elischerstatic int
610e904636aSJulian Elischer${1}_pci_attach(device_t device)
611e904636aSJulian Elischer{
612e904636aSJulian Elischer        int	error;
6136715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
614e904636aSJulian Elischer
615e904636aSJulian Elischer        error =  ${1}_attach(device, scp);
616418df1e4SMark Murray        if (error)
617e904636aSJulian Elischer                ${1}_pci_detach(device);
618e904636aSJulian Elischer        return (error);
619e904636aSJulian Elischer}
620e904636aSJulian Elischer
621e904636aSJulian Elischerstatic int
622e904636aSJulian Elischer${1}_pci_detach (device_t device)
623e904636aSJulian Elischer{
624e904636aSJulian Elischer        int	error;
6256715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
626e904636aSJulian Elischer
627e904636aSJulian Elischer        error =  ${1}_detach(device, scp);
628e904636aSJulian Elischer        return (error);
629e904636aSJulian Elischer}
630e904636aSJulian Elischer
6316715fca9SWarner Losh/*
6326715fca9SWarner Losh ****************************************
63311027719SBrian Somers *  Common Attachment sub-functions
6346715fca9SWarner Losh ****************************************
6356715fca9SWarner Losh */
636e904636aSJulian Elischerstatic int
6376715fca9SWarner Losh${1}_attach(device_t device, struct ${1}_softc * scp)
638e904636aSJulian Elischer{
639d1d3a974SJulian Elischer	device_t parent	= device_get_parent(device);
6406715fca9SWarner Losh	int	unit	= device_get_unit(device);
6415e176f9aSJulian Elischer
64245ddd9afSJulian Elischer	scp->dev = make_dev(&${1}_cdevsw, 0,
64345ddd9afSJulian Elischer			UID_ROOT, GID_OPERATOR, 0600, "${1}%d", unit);
644e904636aSJulian Elischer	scp->dev->si_drv1 = scp;
64545ddd9afSJulian Elischer
646418df1e4SMark Murray	if (${1}_allocate_resources(device))
64745ddd9afSJulian Elischer		goto errexit;
64845ddd9afSJulian Elischer
6494a3a6ee4SJulian Elischer	scp->bt = rman_get_bustag(scp->res_ioport);
6504a3a6ee4SJulian Elischer	scp->bh = rman_get_bushandle(scp->res_ioport);
65145ddd9afSJulian Elischer
652e4dcc1fdSDiomidis Spinellis	/* Register the interrupt handler. */
6534a3a6ee4SJulian Elischer	/*
6544a3a6ee4SJulian Elischer	 * The type should be one of:
6554a3a6ee4SJulian Elischer	 *	INTR_TYPE_TTY
6564a3a6ee4SJulian Elischer	 *	INTR_TYPE_BIO
6574a3a6ee4SJulian Elischer	 *	INTR_TYPE_CAM
6584a3a6ee4SJulian Elischer	 *	INTR_TYPE_NET
6594a3a6ee4SJulian Elischer	 *	INTR_TYPE_MISC
6606715fca9SWarner Losh	 * This will probably change with SMPng.  INTR_TYPE_FAST may be
66111027719SBrian Somers	 * OR'd into this type to mark the interrupt fast.  However, fast
6626715fca9SWarner Losh	 * interrupts cannot be shared at all so special precautions are
66311027719SBrian Somers	 * necessary when coding fast interrupt routines.
6644a3a6ee4SJulian Elischer	 */
665d1d3a974SJulian Elischer	if (scp->res_irq) {
666e4dcc1fdSDiomidis Spinellis		/* Default to the tty mask for registration. */  /* XXX */
667d1d3a974SJulian Elischer		if (BUS_SETUP_INTR(parent, device, scp->res_irq, INTR_TYPE_TTY,
66845ddd9afSJulian Elischer				${1}intr, scp, &scp->intr_cookie) == 0) {
669e4dcc1fdSDiomidis Spinellis			/* Do something if successful. */
670418df1e4SMark Murray		} else
671e904636aSJulian Elischer			goto errexit;
672d1d3a974SJulian Elischer	}
6734a3a6ee4SJulian Elischer
6744a3a6ee4SJulian Elischer	/*
6754a3a6ee4SJulian Elischer	 * If we want to access the memory we will need
6764a3a6ee4SJulian Elischer	 * to know where it was mapped.
6776715fca9SWarner Losh	 *
6786715fca9SWarner Losh	 * Use of this function is discouraged, however.  You should
6796715fca9SWarner Losh	 * be accessing the device with the bus_space API if at all
6806715fca9SWarner Losh	 * possible.
6814a3a6ee4SJulian Elischer	 */
6824a3a6ee4SJulian Elischer	scp->vaddr = rman_get_virtual(scp->res_memory);
68345b4f5afSJulian Elischer	return 0;
68445ddd9afSJulian Elischer
68545ddd9afSJulian Elischererrexit:
68645ddd9afSJulian Elischer	/*
687e4dcc1fdSDiomidis Spinellis	 * Undo anything we may have done.
68845ddd9afSJulian Elischer	 */
689e904636aSJulian Elischer	${1}_detach(device, scp);
69045ddd9afSJulian Elischer	return (ENXIO);
69145b4f5afSJulian Elischer}
69264b2faf8SBruce Evans
69345b4f5afSJulian Elischerstatic int
6946715fca9SWarner Losh${1}_detach(device_t device, struct ${1}_softc *scp)
69545b4f5afSJulian Elischer{
696d1d3a974SJulian Elischer	device_t parent = device_get_parent(device);
69745b4f5afSJulian Elischer
69845ddd9afSJulian Elischer	/*
69945ddd9afSJulian Elischer	 * At this point stick a strong piece of wood into the device
70045ddd9afSJulian Elischer	 * to make sure it is stopped safely. The alternative is to
70145ddd9afSJulian Elischer	 * simply REFUSE to detach if it's busy. What you do depends on
70245ddd9afSJulian Elischer	 * your specific situation.
7036715fca9SWarner Losh	 *
7046715fca9SWarner Losh	 * Sometimes the parent bus will detach you anyway, even if you
7056715fca9SWarner Losh	 * are busy.  You must cope with that possibility.  Your hardware
7066715fca9SWarner Losh	 * might even already be gone in the case of cardbus or pccard
7076715fca9SWarner Losh	 * devices.
70845ddd9afSJulian Elischer	 */
70945ddd9afSJulian Elischer	/* ZAP some register */
71045ddd9afSJulian Elischer
71145ddd9afSJulian Elischer	/*
71245ddd9afSJulian Elischer	 * Take our interrupt handler out of the list of handlers
71345ddd9afSJulian Elischer	 * that can handle this irq.
71445ddd9afSJulian Elischer	 */
71545ddd9afSJulian Elischer	if (scp->intr_cookie != NULL) {
716d1d3a974SJulian Elischer		if (BUS_TEARDOWN_INTR(parent, device,
717418df1e4SMark Murray			scp->res_irq, scp->intr_cookie) != 0)
718d1d3a974SJulian Elischer				printf("intr teardown failed.. continuing\n");
71945ddd9afSJulian Elischer		scp->intr_cookie = NULL;
72045ddd9afSJulian Elischer	}
72145ddd9afSJulian Elischer
72245ddd9afSJulian Elischer	/*
723e4dcc1fdSDiomidis Spinellis	 * Deallocate any system resources we may have
72445ddd9afSJulian Elischer	 * allocated on behalf of this driver.
72545ddd9afSJulian Elischer	 */
7264a3a6ee4SJulian Elischer	scp->vaddr = NULL;
72745ddd9afSJulian Elischer	return ${1}_deallocate_resources(device);
72845ddd9afSJulian Elischer}
72945ddd9afSJulian Elischer
73045ddd9afSJulian Elischerstatic int
73145ddd9afSJulian Elischer${1}_allocate_resources(device_t device)
73245ddd9afSJulian Elischer{
73345ddd9afSJulian Elischer	int error;
7346715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
735e4dcc1fdSDiomidis Spinellis	int	size = 16; /* SIZE of port range used. */
73645ddd9afSJulian Elischer
73745ddd9afSJulian Elischer	scp->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT,
73845ddd9afSJulian Elischer			&scp->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE);
739418df1e4SMark Murray	if (scp->res_ioport == NULL)
74045ddd9afSJulian Elischer		goto errexit;
74145ddd9afSJulian Elischer
74245ddd9afSJulian Elischer	scp->res_irq = bus_alloc_resource(device, SYS_RES_IRQ,
7434a3a6ee4SJulian Elischer			&scp->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE|RF_ACTIVE);
744418df1e4SMark Murray	if (scp->res_irq == NULL)
74545ddd9afSJulian Elischer		goto errexit;
74645ddd9afSJulian Elischer
74745ddd9afSJulian Elischer	scp->res_drq = bus_alloc_resource(device, SYS_RES_DRQ,
74845ddd9afSJulian Elischer			&scp->rid_drq, 0ul, ~0ul, 1, RF_ACTIVE);
749418df1e4SMark Murray	if (scp->res_drq == NULL)
75045ddd9afSJulian Elischer		goto errexit;
75145ddd9afSJulian Elischer
75287e78fdfSJulian Elischer	scp->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
75345ddd9afSJulian Elischer			&scp->rid_memory, 0ul, ~0ul, MSIZE, RF_ACTIVE);
754418df1e4SMark Murray	if (scp->res_memory == NULL)
75545ddd9afSJulian Elischer		goto errexit;
75645ddd9afSJulian Elischer	return (0);
75745ddd9afSJulian Elischer
75845ddd9afSJulian Elischererrexit:
75945ddd9afSJulian Elischer	error = ENXIO;
760e4dcc1fdSDiomidis Spinellis	/* Cleanup anything we may have assigned. */
76145ddd9afSJulian Elischer	${1}_deallocate_resources(device);
762e4dcc1fdSDiomidis Spinellis	return (ENXIO); /* For want of a better idea. */
76345ddd9afSJulian Elischer}
76445ddd9afSJulian Elischer
76545ddd9afSJulian Elischerstatic int
76645ddd9afSJulian Elischer${1}_deallocate_resources(device_t device)
76745ddd9afSJulian Elischer{
7686715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
76945ddd9afSJulian Elischer
77045ddd9afSJulian Elischer	if (scp->res_irq != 0) {
771d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_IRQ,
772d1d3a974SJulian Elischer			scp->rid_irq, scp->res_irq);
773d1d3a974SJulian Elischer		bus_release_resource(device, SYS_RES_IRQ,
774d1d3a974SJulian Elischer			scp->rid_irq, scp->res_irq);
775d1d3a974SJulian Elischer		scp->res_irq = 0;
776d1d3a974SJulian Elischer	}
777d1d3a974SJulian Elischer	if (scp->res_ioport != 0) {
778d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_IOPORT,
779d1d3a974SJulian Elischer			scp->rid_ioport, scp->res_ioport);
78045b4f5afSJulian Elischer		bus_release_resource(device, SYS_RES_IOPORT,
781d1d3a974SJulian Elischer			scp->rid_ioport, scp->res_ioport);
782d1d3a974SJulian Elischer		scp->res_ioport = 0;
783d1d3a974SJulian Elischer	}
78499fcf983SJulian Elischer	if (scp->res_memory != 0) {
785d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_MEMORY,
786d1d3a974SJulian Elischer			scp->rid_memory, scp->res_memory);
787d1d3a974SJulian Elischer		bus_release_resource(device, SYS_RES_MEMORY,
788d1d3a974SJulian Elischer			scp->rid_memory, scp->res_memory);
78999fcf983SJulian Elischer		scp->res_memory = 0;
790d1d3a974SJulian Elischer	}
791d1d3a974SJulian Elischer	if (scp->res_drq != 0) {
792d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_DRQ,
793d1d3a974SJulian Elischer			scp->rid_drq, scp->res_drq);
794d1d3a974SJulian Elischer		bus_release_resource(device, SYS_RES_DRQ,
795d1d3a974SJulian Elischer			scp->rid_drq, scp->res_drq);
796d1d3a974SJulian Elischer		scp->res_drq = 0;
797d1d3a974SJulian Elischer	}
798418df1e4SMark Murray	if (scp->dev)
79945b4f5afSJulian Elischer		destroy_dev(scp->dev);
8005e176f9aSJulian Elischer	return (0);
8015e176f9aSJulian Elischer}
8025e176f9aSJulian Elischer
80364b2faf8SBruce Evansstatic void
80445b4f5afSJulian Elischer${1}intr(void *arg)
8055e176f9aSJulian Elischer{
8066715fca9SWarner Losh	struct ${1}_softc *scp = (struct ${1}_softc *) arg;
8075e176f9aSJulian Elischer
8085e176f9aSJulian Elischer	/*
809e4dcc1fdSDiomidis Spinellis	 * Well we got an interrupt, now what?
8106715fca9SWarner Losh	 *
8116715fca9SWarner Losh	 * Make sure that the interrupt routine will always terminate,
8126715fca9SWarner Losh	 * even in the face of "bogus" data from the card.
8135e176f9aSJulian Elischer	 */
814ff7cd805SDiomidis Spinellis	(void)scp; /* Delete this line after using scp. */
8155e176f9aSJulian Elischer	return;
8165e176f9aSJulian Elischer}
8175e176f9aSJulian Elischer
81845b4f5afSJulian Elischerstatic int
819a299217fSRoman Kurakin${1}ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
8205e176f9aSJulian Elischer{
8216715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8225e176f9aSJulian Elischer
823ff7cd805SDiomidis Spinellis	(void)scp; /* Delete this line after using scp. */
8245e176f9aSJulian Elischer	switch (cmd) {
8255e176f9aSJulian Elischer	case DHIOCRESET:
826e4dcc1fdSDiomidis Spinellis		/* Whatever resets it. */
82787e78fdfSJulian Elischer#if 0
82845b4f5afSJulian Elischer		${UPPER}_OUTB(SOME_PORT, 0xff);
82987e78fdfSJulian Elischer#endif
8305e176f9aSJulian Elischer		break;
8315e176f9aSJulian Elischer	default:
8325e176f9aSJulian Elischer		return ENXIO;
8335e176f9aSJulian Elischer	}
8345e176f9aSJulian Elischer	return (0);
8355e176f9aSJulian Elischer}
8365e176f9aSJulian Elischer/*
8375e176f9aSJulian Elischer * You also need read, write, open, close routines.
838e4dcc1fdSDiomidis Spinellis * This should get you started.
8395e176f9aSJulian Elischer */
8405e176f9aSJulian Elischerstatic int
841a299217fSRoman Kurakin${1}open(struct cdev *dev, int oflags, int devtype, struct thread *td)
8425e176f9aSJulian Elischer{
8436715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8445e176f9aSJulian Elischer
8455e176f9aSJulian Elischer	/*
846e4dcc1fdSDiomidis Spinellis	 * Do processing.
8475e176f9aSJulian Elischer	 */
848ff7cd805SDiomidis Spinellis	(void)scp; /* Delete this line after using scp. */
8495e176f9aSJulian Elischer	return (0);
8505e176f9aSJulian Elischer}
8515e176f9aSJulian Elischer
8525e176f9aSJulian Elischerstatic int
853a299217fSRoman Kurakin${1}close(struct cdev *dev, int fflag, int devtype, struct thread *td)
8545e176f9aSJulian Elischer{
8556715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8565e176f9aSJulian Elischer
8575e176f9aSJulian Elischer	/*
858e4dcc1fdSDiomidis Spinellis	 * Do processing.
8595e176f9aSJulian Elischer	 */
860ff7cd805SDiomidis Spinellis	(void)scp; /* Delete this line after using scp. */
8615e176f9aSJulian Elischer	return (0);
8625e176f9aSJulian Elischer}
8635e176f9aSJulian Elischer
8645e176f9aSJulian Elischerstatic int
865a299217fSRoman Kurakin${1}read(struct cdev *dev, struct uio *uio, int ioflag)
8665e176f9aSJulian Elischer{
8676715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8685e176f9aSJulian Elischer	int	 toread;
8695e176f9aSJulian Elischer
8705e176f9aSJulian Elischer	/*
871e4dcc1fdSDiomidis Spinellis	 * Do processing.
872e4dcc1fdSDiomidis Spinellis	 * Read from buffer.
8735e176f9aSJulian Elischer	 */
874ff7cd805SDiomidis Spinellis	(void)scp; /* Delete this line after using scp. */
8755e176f9aSJulian Elischer	toread = (min(uio->uio_resid, sizeof(scp->buffer)));
8765e176f9aSJulian Elischer	return(uiomove(scp->buffer, toread, uio));
8775e176f9aSJulian Elischer}
8785e176f9aSJulian Elischer
8795e176f9aSJulian Elischerstatic int
880a299217fSRoman Kurakin${1}write(struct cdev *dev, struct uio *uio, int ioflag)
8815e176f9aSJulian Elischer{
8826715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8835e176f9aSJulian Elischer	int	towrite;
8845e176f9aSJulian Elischer
8855e176f9aSJulian Elischer	/*
886e4dcc1fdSDiomidis Spinellis	 * Do processing.
887e4dcc1fdSDiomidis Spinellis	 * Write to buffer.
8885e176f9aSJulian Elischer	 */
889ff7cd805SDiomidis Spinellis	(void)scp; /* Delete this line after using scp. */
8905e176f9aSJulian Elischer	towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
8915e176f9aSJulian Elischer	return(uiomove(scp->buffer, towrite, uio));
8925e176f9aSJulian Elischer}
8935e176f9aSJulian Elischer
8945e176f9aSJulian Elischerstatic int
895a299217fSRoman Kurakin${1}mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
8965e176f9aSJulian Elischer{
8976715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8985e176f9aSJulian Elischer
8995e176f9aSJulian Elischer	/*
90087e78fdfSJulian Elischer	 * Given a byte offset into your device, return the PHYSICAL
90187e78fdfSJulian Elischer	 * page number that it would map to.
9025e176f9aSJulian Elischer	 */
903ff7cd805SDiomidis Spinellis	(void)scp; /* Delete this line after using scp. */
904e4dcc1fdSDiomidis Spinellis#if 0	/* If we had a frame buffer or whatever... do this. */
905418df1e4SMark Murray	if (offset > FRAMEBUFFERSIZE - PAGE_SIZE)
9065e176f9aSJulian Elischer		return (-1);
9075e176f9aSJulian Elischer	return i386_btop((FRAMEBASE + offset));
9085e176f9aSJulian Elischer#else
9095e176f9aSJulian Elischer	return (-1);
9105e176f9aSJulian Elischer#endif
9115e176f9aSJulian Elischer}
9125e176f9aSJulian Elischer
9135e176f9aSJulian Elischerstatic int
914a299217fSRoman Kurakin${1}poll(struct cdev *dev, int which, struct thread *td)
9155e176f9aSJulian Elischer{
9166715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
9175e176f9aSJulian Elischer
9185e176f9aSJulian Elischer	/*
919e4dcc1fdSDiomidis Spinellis	 * Do processing.
9205e176f9aSJulian Elischer	 */
921ff7cd805SDiomidis Spinellis	(void)scp; /* Delete this line after using scp. */
922e4dcc1fdSDiomidis Spinellis	return (0); /* This is the wrong value I'm sure. */
9235e176f9aSJulian Elischer}
9245e176f9aSJulian Elischer
9255e176f9aSJulian ElischerDONE
9265e176f9aSJulian Elischer
92745b4f5afSJulian Elischercat >${TOP}/sys/${1}io.h <<DONE
9285e176f9aSJulian Elischer/*
9295e176f9aSJulian Elischer * Definitions needed to access the ${1} device (ioctls etc)
930e4dcc1fdSDiomidis Spinellis * see mtio.h, ioctl.h as examples.
9315e176f9aSJulian Elischer */
9325e176f9aSJulian Elischer#ifndef SYS_DHIO_H
9335e176f9aSJulian Elischer#define SYS_DHIO_H
9345e176f9aSJulian Elischer
9355e176f9aSJulian Elischer#ifndef KERNEL
9365e176f9aSJulian Elischer#include <sys/types.h>
9375e176f9aSJulian Elischer#endif
9385e176f9aSJulian Elischer#include <sys/ioccom.h>
9395e176f9aSJulian Elischer
9405e176f9aSJulian Elischer/*
941e4dcc1fdSDiomidis Spinellis * Define an ioctl here.
9425e176f9aSJulian Elischer */
943e4dcc1fdSDiomidis Spinellis#define DHIOCRESET _IO('D', 0) /* Reset the ${1} device. */
9445e176f9aSJulian Elischer#endif
9455e176f9aSJulian ElischerDONE
9465e176f9aSJulian Elischer
947e4dcc1fdSDiomidis Spinellisif [ ! -d ${TOP}/modules/${1} ]; then
94845b4f5afSJulian Elischer	mkdir -p ${TOP}/modules/${1}
94945b4f5afSJulian Elischerfi
95045b4f5afSJulian Elischer
95145b4f5afSJulian Elischercat >${TOP}/modules/${1}/Makefile <<DONE
9524308b695SJulian Elischer#	${UPPER} Loadable Kernel Module
9534308b695SJulian Elischer
95445b4f5afSJulian Elischer.PATH:  \${.CURDIR}/../../dev/${1}
95545b4f5afSJulian ElischerKMOD    = ${1}
95645b4f5afSJulian ElischerSRCS    = ${1}.c
95745b4f5afSJulian ElischerSRCS    += opt_inet.h device_if.h bus_if.h pci_if.h isa_if.h
9584308b695SJulian Elischer
959e4dcc1fdSDiomidis Spinellis# You may need to do this is your device is an if_xxx driver.
96045b4f5afSJulian Elischeropt_inet.h:
96145b4f5afSJulian Elischer	echo "#define INET 1" > opt_inet.h
9624308b695SJulian Elischer
9634308b695SJulian Elischer.include <bsd.kmod.mk>
9644308b695SJulian ElischerDONE
96545b4f5afSJulian Elischer
96636a64d13SRoman Kurakinecho -n "Do you want to build the '${1}' module? [Y]"
96736a64d13SRoman Kurakinread VAL
96836a64d13SRoman Kurakinif [ "-z" "$VAL" ]; then
96936a64d13SRoman Kurakin	VAL=YES
97036a64d13SRoman Kurakinfi
97136a64d13SRoman Kurakincase ${VAL} in
97236a64d13SRoman Kurakin[yY]*)
97345b4f5afSJulian Elischer	(cd ${TOP}/modules/${1}; make depend; make )
97436a64d13SRoman Kurakin	;;
97536a64d13SRoman Kurakin*)
97636a64d13SRoman Kurakin#	exit
97736a64d13SRoman Kurakin	;;
97836a64d13SRoman Kurakinesac
9794308b695SJulian Elischer
98036a64d13SRoman Kurakinecho ""
981be115021SRoman Kurakinecho -n "Do you want to build the '${UPPER}' kernel? [Y]"
982be115021SRoman Kurakinread VAL
983be115021SRoman Kurakinif [ "-z" "$VAL" ]; then
984be115021SRoman Kurakin	VAL=YES
985be115021SRoman Kurakinfi
986be115021SRoman Kurakincase ${VAL} in
987be115021SRoman Kurakin[yY]*)
988be115021SRoman Kurakin	(
989be115021SRoman Kurakin	 cd ${TOP}/i386/conf; \
990be115021SRoman Kurakin	 config ${UPPER}; \
991be115021SRoman Kurakin	 cd ${TOP}/i386/compile/${UPPER}; \
992be115021SRoman Kurakin	 make depend; \
993be115021SRoman Kurakin	 make; \
994be115021SRoman Kurakin	)
995be115021SRoman Kurakin	;;
996be115021SRoman Kurakin*)
997be115021SRoman Kurakin#	exit
998be115021SRoman Kurakin	;;
999be115021SRoman Kurakinesac
10005e176f9aSJulian Elischer
10015e176f9aSJulian Elischer#--------------end of script---------------
10025e176f9aSJulian Elischer#
1003e4dcc1fdSDiomidis Spinellis# Edit to your taste...
10045e176f9aSJulian Elischer#
10055e176f9aSJulian Elischer#
1006