xref: /freebsd/share/examples/drivers/make_device_driver.sh (revision e904636ad48b97e10a52a816c486f98f5be7870b)
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:
687e78fdfSJulian Elischer# cd /sys/i386/conf; config FOO; cd ../../compile/FOO; make depend; make
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
1087e78fdfSJulian Elischer# which can be lonked 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"
154308b695SJulian Elischer#
165e176f9aSJulian Elischer# Trust me, RUN THIS SCRIPT :)
1787e78fdfSJulian Elischer#
1845b4f5afSJulian Elischer# $FreeBSD$"
195e176f9aSJulian Elischer#
20e904636aSJulian Elischer#
215e176f9aSJulian Elischerif [ "${1}X" = "X" ]
225e176f9aSJulian Elischerthen
235e176f9aSJulian Elischer	echo "Hey , how about some help here.. give me a device name!"
245e176f9aSJulian Elischer	exit 1
255e176f9aSJulian Elischerfi
2645b4f5afSJulian ElischerUPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
275e176f9aSJulian Elischer
2845b4f5afSJulian ElischerHERE=`pwd`
2945b4f5afSJulian Elischercd /sys
3045b4f5afSJulian ElischerTOP=`pwd`
3145b4f5afSJulian Elischer
3296305e8fSJulian ElischerRCS_KEYWORD=FreeBSD
3396305e8fSJulian Elischer
3487e78fdfSJulian Elischerif [ -d ${TOP}/modules/${1} ]
3587e78fdfSJulian Elischerthen
3687e78fdfSJulian Elischer	echo "There appears to already be a module called ${1}"
3787e78fdfSJulian Elischer	echo -n "Should it be overwritten? [Y]"
3887e78fdfSJulian Elischer	read VAL
3987e78fdfSJulian Elischer	if [ "-z" "$VAL" ]
4087e78fdfSJulian Elischer	then
4187e78fdfSJulian Elischer	  VAL=YES
4287e78fdfSJulian Elischer	fi
4387e78fdfSJulian Elischer	case ${VAL} in
4487e78fdfSJulian Elischer	[yY]*)
4587e78fdfSJulian Elischer	  echo "Cleaning up from prior runs"
4687e78fdfSJulian Elischer	  rm -rf ${TOP}/dev/${1}
4787e78fdfSJulian Elischer	  rm -rf ${TOP}/modules/${1}
4887e78fdfSJulian Elischer	  rm ${TOP}/i386/conf/files.${UPPER}
4987e78fdfSJulian Elischer	  rm ${TOP}/i386/conf/${UPPER}
5087e78fdfSJulian Elischer	  rm ${TOP}/sys/${1}io.h
5187e78fdfSJulian Elischer	  ;;
5287e78fdfSJulian Elischer	*)
5387e78fdfSJulian Elischer	  exit 1
5487e78fdfSJulian Elischer	  ;;
5587e78fdfSJulian Elischer	esac
5687e78fdfSJulian Elischerfi
5787e78fdfSJulian Elischer
5887e78fdfSJulian Elischerecho "The following files will be created:"
5945b4f5afSJulian Elischerecho ${TOP}/modules/${1}
6045b4f5afSJulian Elischerecho ${TOP}/i386/conf/files.${UPPER}
6145b4f5afSJulian Elischerecho ${TOP}/i386/conf/${UPPER}
6245b4f5afSJulian Elischerecho ${TOP}/dev/${1}
6345b4f5afSJulian Elischerecho ${TOP}/dev/${1}/${1}.c
6445b4f5afSJulian Elischerecho ${TOP}/sys/${1}io.h
6545b4f5afSJulian Elischerecho ${TOP}/modules/${1}
6645b4f5afSJulian Elischerecho ${TOP}/modules/${1}/Makefile
6745b4f5afSJulian Elischer
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
8245b4f5afSJulian Elischercat >${TOP}/i386/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 Elischerident	${UPPER}
9296305e8fSJulian Elischer# \$${RCS_KEYWORD}: $
935e176f9aSJulian ElischerDONE
945e176f9aSJulian Elischer
9545b4f5afSJulian Elischergrep -v GENERIC < /sys/i386/conf/GENERIC >>${TOP}/i386/conf/${UPPER}
965e176f9aSJulian Elischer
9745b4f5afSJulian Elischercat >>${TOP}/i386/conf/${UPPER} <<DONE
9845b4f5afSJulian Elischeroptions		DDB		# trust me, you'll need this
9945ddd9afSJulian Elischerdevice		${1}
1005e176f9aSJulian ElischerDONE
1015e176f9aSJulian Elischer
10245b4f5afSJulian Elischerif [ ! -d ${TOP}/dev/${1} ]
10345b4f5afSJulian Elischerthen
10445b4f5afSJulian Elischer	mkdir -p ${TOP}/dev/${1}
10545b4f5afSJulian Elischerfi
10645b4f5afSJulian Elischer
10745b4f5afSJulian Elischer
10845b4f5afSJulian Elischer
10945b4f5afSJulian Elischer
11045b4f5afSJulian Elischercat >${TOP}/dev/${1}/${1}.c <<DONE
1115e176f9aSJulian Elischer/*
11296305e8fSJulian Elischer * Copyright (c) [year] [your name]
11396305e8fSJulian Elischer * All rights reserved.
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.
13596305e8fSJulian Elischer *
1365e176f9aSJulian Elischer *
1375e176f9aSJulian Elischer * ${1} driver
13896305e8fSJulian Elischer * \$${RCS_KEYWORD}: $
1395e176f9aSJulian Elischer */
1405e176f9aSJulian Elischer
1414a3a6ee4SJulian Elischer/*
1424a3a6ee4SJulian Elischer * http://www.daemonnews.org/200008/isa.html is required reading.
1434a3a6ee4SJulian Elischer * hopefully it will make it's way into the handbook.
1444a3a6ee4SJulian Elischer */
1455e176f9aSJulian Elischer
1465e176f9aSJulian Elischer#include <sys/param.h>
1475e176f9aSJulian Elischer#include <sys/systm.h>
1485e176f9aSJulian Elischer#include <sys/conf.h>		/* cdevsw stuff */
14945b4f5afSJulian Elischer#include <sys/kernel.h>		/* SYSINIT stuff */
15045b4f5afSJulian Elischer#include <sys/uio.h>		/* SYSINIT stuff */
1515e176f9aSJulian Elischer#include <sys/malloc.h>		/* malloc region definitions */
15245b4f5afSJulian Elischer#include <sys/module.h>
15345b4f5afSJulian Elischer#include <sys/bus.h>
15445b4f5afSJulian Elischer#include <machine/bus.h>
15545b4f5afSJulian Elischer#include <machine/resource.h>
156e904636aSJulian Elischer#include <machine/bus_pio.h>
157e904636aSJulian Elischer#include <machine/bus_memio.h>
15845b4f5afSJulian Elischer#include <sys/rman.h>
15945b4f5afSJulian Elischer#include <sys/time.h>
1605e176f9aSJulian Elischer
161e904636aSJulian Elischer#include <pci/pcireg.h>
162e904636aSJulian Elischer#include <pci/pcivar.h>
163e904636aSJulian Elischer
16445b4f5afSJulian Elischer#include <isa/isavar.h>
16545b4f5afSJulian Elischer#include "isa_if.h"
16645b4f5afSJulian Elischer#include <sys/${1}io.h>		/* ${1} IOCTL definitions */
16745b4f5afSJulian Elischer
16887e78fdfSJulian Elischer/* XXX These should be defined in terms of bus-space ops */
16987e78fdfSJulian Elischer#define ${UPPER}_INB(port) inb(port_start)
17087e78fdfSJulian Elischer#define ${UPPER}_OUTB(port, val) ( port_start, (val))
17145b4f5afSJulian Elischer#define SOME_PORT 123
17245b4f5afSJulian Elischer#define EXPECTED_VALUE 0x42
1735e176f9aSJulian Elischer
1745e176f9aSJulian Elischer/* 
1755e176f9aSJulian Elischer * device specific Misc defines 
1765e176f9aSJulian Elischer */
1775e176f9aSJulian Elischer#define BUFFERSIZE	1024
1785e176f9aSJulian Elischer#define NUMPORTS	4
17987e78fdfSJulian Elischer#define MEMSIZE		(4 * 1024) /* imaginable h/w buffer size */
1805e176f9aSJulian Elischer
1815e176f9aSJulian Elischer/*
1825e176f9aSJulian Elischer * One of these per allocated device
1835e176f9aSJulian Elischer */
1845e176f9aSJulian Elischerstruct ${1}_softc {
18545b4f5afSJulian Elischer	bus_space_tag_t bt;
18645b4f5afSJulian Elischer	bus_space_handle_t bh;
187d1d3a974SJulian Elischer	int rid_ioport;
188d1d3a974SJulian Elischer	int rid_memory;
189d1d3a974SJulian Elischer	int rid_irq;
190d1d3a974SJulian Elischer	int rid_drq;
191d1d3a974SJulian Elischer	struct resource* res_ioport;	/* resource for port range */
192d1d3a974SJulian Elischer	struct resource* res_memory;	/* resource for mem range */
193d1d3a974SJulian Elischer	struct resource* res_irq;	/* resource for irq range */
194d1d3a974SJulian Elischer	struct resource* res_drq;	/* resource for dma channel */
19545b4f5afSJulian Elischer	device_t device;
196d1d3a974SJulian Elischer	dev_t dev;
197d1d3a974SJulian Elischer	void	*intr_cookie;
1984a3a6ee4SJulian Elischer	void	*vaddr;			/* Virtual address of mem resource */
19987e78fdfSJulian Elischer	char	buffer[BUFFERSIZE];	/* if we needed to buffer something */
2005e176f9aSJulian Elischer} ;
2015e176f9aSJulian Elischer
2025e176f9aSJulian Elischertypedef	struct ${1}_softc *sc_p;
2035e176f9aSJulian Elischer
204e904636aSJulian Elischer
205e904636aSJulian Elischer/* Function prototypes (these should all be static) */
206e904636aSJulian Elischerstatic int ${1}_deallocate_resources(device_t device);
207e904636aSJulian Elischerstatic int ${1}_allocate_resources(device_t device);
208e904636aSJulian Elischerstatic int ${1}_attach(device_t device, sc_p scp);
209e904636aSJulian Elischerstatic int ${1}_detach(device_t device, sc_p scp);
210e904636aSJulian Elischer
211e904636aSJulian Elischerstatic d_open_t		${1}open;
212e904636aSJulian Elischerstatic d_close_t	${1}close;
213e904636aSJulian Elischerstatic d_read_t		${1}read;
214e904636aSJulian Elischerstatic d_write_t	${1}write;
215e904636aSJulian Elischerstatic d_ioctl_t	${1}ioctl;
216e904636aSJulian Elischerstatic d_mmap_t		${1}mmap;
217e904636aSJulian Elischerstatic d_poll_t		${1}poll;
218e904636aSJulian Elischerstatic	void		${1}intr(void *arg);
219e904636aSJulian Elischer 
220e904636aSJulian Elischer#define CDEV_MAJOR 20
221e904636aSJulian Elischerstatic struct cdevsw ${1}_cdevsw = {
222e904636aSJulian Elischer	/* open */	${1}open,
223e904636aSJulian Elischer	/* close */	${1}close,
224e904636aSJulian Elischer	/* read */	${1}read,
225e904636aSJulian Elischer	/* write */	${1}write,
226e904636aSJulian Elischer	/* ioctl */	${1}ioctl,
227e904636aSJulian Elischer	/* poll */	${1}poll,
228e904636aSJulian Elischer	/* mmap */	${1}mmap,
229e904636aSJulian Elischer	/* strategy */	nostrategy,	/* not a block type device */
230e904636aSJulian Elischer	/* name */	"${1}",
231e904636aSJulian Elischer	/* maj */	CDEV_MAJOR,
232e904636aSJulian Elischer	/* dump */	nodump,		/* not a block type device */
233e904636aSJulian Elischer	/* psize */	nopsize,	/* not a block type device */
234e904636aSJulian Elischer	/* flags */	0,
235e904636aSJulian Elischer	/* bmaj */	-1
236e904636aSJulian Elischer};
237e904636aSJulian Elischer 
238e904636aSJulian Elischer/*****************************************\
239e904636aSJulian Elischer* ISA Attachment structures and functions
240e904636aSJulian Elischer\*****************************************/
241e904636aSJulian Elischerstatic void ${1}_isa_identify (driver_t *, device_t);
242e904636aSJulian Elischerstatic int ${1}_isa_probe (device_t);
243e904636aSJulian Elischerstatic int ${1}_isa_attach (device_t);
244e904636aSJulian Elischerstatic int ${1}_isa_detach (device_t);
2455e176f9aSJulian Elischer
24645b4f5afSJulian Elischerstatic struct isa_pnp_id ${1}_ids[] = {
24745b4f5afSJulian Elischer	{0x12345678,	"ABCco Widget"},
24845b4f5afSJulian Elischer	{0xfedcba98,	"shining moon Widget ripoff"},
2494a3a6ee4SJulian Elischer	{0,		NULL}
25045b4f5afSJulian Elischer};
25145b4f5afSJulian Elischer
25245b4f5afSJulian Elischerstatic device_method_t ${1}_methods[] = {
25387e78fdfSJulian Elischer	DEVMETHOD(device_identify,	${1}_isa_identify),
25445b4f5afSJulian Elischer	DEVMETHOD(device_probe,		${1}_isa_probe),
25545b4f5afSJulian Elischer	DEVMETHOD(device_attach,	${1}_isa_attach),
25645b4f5afSJulian Elischer	DEVMETHOD(device_detach,	${1}_isa_detach),
25745b4f5afSJulian Elischer	{ 0, 0 }
25845b4f5afSJulian Elischer};
25945b4f5afSJulian Elischer
26045b4f5afSJulian Elischerstatic driver_t ${1}_isa_driver = {
26145b4f5afSJulian Elischer	"${1}",
26245b4f5afSJulian Elischer	${1}_methods,
26345b4f5afSJulian Elischer	sizeof (struct ${1}_softc)
26445b4f5afSJulian Elischer};
26545b4f5afSJulian Elischer
266e904636aSJulian Elischerstatic devclass_t ${1}_devclass;
267e904636aSJulian Elischer
26845b4f5afSJulian ElischerDRIVER_MODULE(${1}, isa, ${1}_isa_driver, ${1}_devclass, 0, 0);
26945b4f5afSJulian Elischer
27087e78fdfSJulian Elischer/*
27187e78fdfSJulian Elischer * Here list some port addresses we might expect our widget to appear at:
27287e78fdfSJulian Elischer */
27387e78fdfSJulian Elischerstatic struct localhints {
27487e78fdfSJulian Elischer	int ioport;
27587e78fdfSJulian Elischer	int irq;
27687e78fdfSJulian Elischer	int drq;
27787e78fdfSJulian Elischer	int mem;
27887e78fdfSJulian Elischer} res[] = {
27987e78fdfSJulian Elischer	{ 0x210, 11, 2, 0xcd000},
28087e78fdfSJulian Elischer	{ 0x310, 12, 3, 0xdd000},
28187e78fdfSJulian Elischer	{ 0x320, 9, 6, 0xd4000},
28287e78fdfSJulian Elischer	{0,0,0,0}
28387e78fdfSJulian Elischer};
28445b4f5afSJulian Elischer
28587e78fdfSJulian Elischer#define MAXHINTS 10 /* just an arbitrary safty limit */
28687e78fdfSJulian Elischer/*
2874a3a6ee4SJulian Elischer * Called once when the driver is somehow connected with the bus,
2884a3a6ee4SJulian Elischer * (Either linked in and the bus is started, or loaded as a module).
2894a3a6ee4SJulian Elischer *
2904a3a6ee4SJulian Elischer * The aim of this routine in an ISA driver is to add child entries to
2914a3a6ee4SJulian Elischer * the parent bus so that it looks as if the devices were detected by
2924a3a6ee4SJulian Elischer * some pnp-like method, or at least mentionned in the hints.
2934a3a6ee4SJulian Elischer *
2944a3a6ee4SJulian Elischer * For NON-PNP "dumb" devices:
29587e78fdfSJulian Elischer * Add entries into the bus's list of likely devices, so that
29687e78fdfSJulian Elischer * our 'probe routine' will be called for them.
29787e78fdfSJulian Elischer * This is similar to what the 'hints' code achieves, except this is
29887e78fdfSJulian Elischer * loadable with the driver.
2994a3a6ee4SJulian Elischer * In the 'dumb' case we end up with more children than needed but
3004a3a6ee4SJulian Elischer * some (or all) of them will fail probe() and only waste a little memory.
3014a3a6ee4SJulian Elischer *
3024a3a6ee4SJulian Elischer * For NON-PNP "Smart" devices:
3034a3a6ee4SJulian Elischer * If the device has a NON-PNP way of being detected and setting/sensing
3044a3a6ee4SJulian Elischer * the card, then do that here and add a child for each set of
3054a3a6ee4SJulian Elischer * hardware found. 
3064a3a6ee4SJulian Elischer *
3074a3a6ee4SJulian Elischer * For PNP devices:
3084a3a6ee4SJulian Elischer * If the device is always PNP capable then this function can be removed.
3094a3a6ee4SJulian Elischer *
3104a3a6ee4SJulian Elischer * If the device is mentionned in the 'hints' file then this
3114a3a6ee4SJulian Elischer * function can be removed. All devices mentionned in the hints
3124a3a6ee4SJulian Elischer * file get added as children for probing, whether or not the
3134a3a6ee4SJulian Elischer * driver is linked in. So even as a module it MAY still be there.
3144a3a6ee4SJulian Elischer * See isa/isahint.c for hints being added in.
31587e78fdfSJulian Elischer */
31687e78fdfSJulian Elischerstatic void
31787e78fdfSJulian Elischer${1}_isa_identify (driver_t *driver, device_t parent)
31887e78fdfSJulian Elischer{
31987e78fdfSJulian Elischer	u_int32_t	irq=0;
32087e78fdfSJulian Elischer	u_int32_t	ioport;
32187e78fdfSJulian Elischer	device_t	child;
32287e78fdfSJulian Elischer	int i;
32387e78fdfSJulian Elischer
32487e78fdfSJulian Elischer
32587e78fdfSJulian Elischer	/*
32687e78fdfSJulian Elischer	 * If we've already got ${UPPER} attached somehow, don't try again.
3274a3a6ee4SJulian Elischer	 * Maybe it was in the hints file. or it was loaded before.
32887e78fdfSJulian Elischer	 */
32987e78fdfSJulian Elischer	if (device_find_child(parent, "${1}", 0)) {
33087e78fdfSJulian Elischer		printf("${UPPER}: already attached\n");
33187e78fdfSJulian Elischer		return;
33287e78fdfSJulian Elischer	}
33387e78fdfSJulian Elischer/* XXX look at dev/acpica/acpi_isa.c for use of ISA_ADD_CONFIG() macro */
33487e78fdfSJulian Elischer/* XXX What is ISA_SET_CONFIG_CALLBACK(parent, child, pnpbios_set_config, 0) ?*/
33587e78fdfSJulian Elischer	for (i = 0; i < MAXHINTS; i++) {
33687e78fdfSJulian Elischer		if (((ioport = res[i].ioport) == 0)
33787e78fdfSJulian Elischer		&&  ((irq = res[i].irq) == 0)) {
33887e78fdfSJulian Elischer			return; /* we've added all our local hints */
33987e78fdfSJulian Elischer		}
34087e78fdfSJulian Elischer
34187e78fdfSJulian Elischer		child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "${1}", -1);
34287e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_IOPORT,	0, ioport, NUMPORTS);
34387e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_IRQ,	0, irq, 1);
34487e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_DRQ,	0, res[i].drq, 1);
34587e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_MEMORY,	0, res[i].mem, MEMSIZE);
34687e78fdfSJulian Elischer
3474a3a6ee4SJulian Elischer
34887e78fdfSJulian Elischer#if 0
34987e78fdfSJulian Elischer		/*
35087e78fdfSJulian Elischer		 * If we wanted to pretend PNP found it
35187e78fdfSJulian Elischer		 * we could do this, and put matching entries
35287e78fdfSJulian Elischer		 * in the PNP table, but I think it's probably too hacky.
35387e78fdfSJulian Elischer		 * As you see, some people have done it though.
3544a3a6ee4SJulian Elischer		 * Basically EISA (remember that?) would do this I think
35587e78fdfSJulian Elischer		 */
35687e78fdfSJulian Elischer		isa_set_vendorid(child, PNP_EISAID("ESS1888"));
35787e78fdfSJulian Elischer		isa_set_logicalid(child, PNP_EISAID("ESS1888"));
35887e78fdfSJulian Elischer#endif
35987e78fdfSJulian Elischer	}
3604a3a6ee4SJulian Elischer#if 0
3614a3a6ee4SJulian Elischer	Do some smart probing (e.g. like the lnc driver)
3624a3a6ee4SJulian Elischer	and add a child for each one found.
3634a3a6ee4SJulian Elischer#endif
36487e78fdfSJulian Elischer
36587e78fdfSJulian Elischer	return;
36687e78fdfSJulian Elischer}
36745b4f5afSJulian Elischer/*
36845b4f5afSJulian Elischer * The ISA code calls this for each device it knows about,
36945b4f5afSJulian Elischer * whether via the PNP code or via the hints etc.
3704a3a6ee4SJulian Elischer * If the device nas no PNP capabilities, remove all the 
3714a3a6ee4SJulian Elischer * PNP entries, but keep the call to ISA_PNP_PROBE()
3724a3a6ee4SJulian Elischer * As it will guard against accidentally recognising
3734a3a6ee4SJulian Elischer * foreign hardware. This is because we will be called to check against
3744a3a6ee4SJulian Elischer * ALL PNP hardware.
37545b4f5afSJulian Elischer */
3765e176f9aSJulian Elischerstatic int
37745b4f5afSJulian Elischer${1}_isa_probe (device_t device)
3785e176f9aSJulian Elischer{
37945b4f5afSJulian Elischer	int error;
38087e78fdfSJulian Elischer	device_t parent = device_get_parent(device);
38145b4f5afSJulian Elischer	sc_p scp = device_get_softc(device);
38287e78fdfSJulian Elischer	u_long	port_start, port_count;
38387e78fdfSJulian Elischer
38445b4f5afSJulian Elischer
38545b4f5afSJulian Elischer	bzero(scp, sizeof(*scp));
38645b4f5afSJulian Elischer	scp->device = device;
3875e176f9aSJulian Elischer
3885e176f9aSJulian Elischer	/*
38987e78fdfSJulian Elischer	 * Check this device for a PNP match in our table..
39045b4f5afSJulian Elischer	 * There are several possible outcomes.
39187e78fdfSJulian Elischer	 * error == 0		We match a PNP ).
39287e78fdfSJulian Elischer	 * error == ENXIO,	It is a PNP device but not in out table.
39345b4f5afSJulian Elischer	 * error == ENOENT,	I is not a PNP device.. try heuristic probes.
39445b4f5afSJulian Elischer	 *    -- logic from if_ed_isa.c, added info from isa/isa_if.m:
3955e176f9aSJulian Elischer	 */
39687e78fdfSJulian Elischer	error = ISA_PNP_PROBE(parent, device, ${1}_ids);
39745b4f5afSJulian Elischer	switch (error) {
39845b4f5afSJulian Elischer	case 0:
39945b4f5afSJulian Elischer		/*
40045b4f5afSJulian Elischer		 * We found a PNP device.
40145ddd9afSJulian Elischer		 * Do nothing, as it's all done in attach()
40245b4f5afSJulian Elischer		 */
40345ddd9afSJulian Elischer		break;
40445b4f5afSJulian Elischer	case ENOENT:
40545b4f5afSJulian Elischer		/*
40645b4f5afSJulian Elischer		 * Well it didn't show up in the PNP tables
40745b4f5afSJulian Elischer		 * so look directly at known ports (if we have any)
40845b4f5afSJulian Elischer		 * in case we are looking for an old pre-PNP card.
40945b4f5afSJulian Elischer		 * 
41087e78fdfSJulian Elischer		 * Hopefully the  'identify' routine will have picked these
41187e78fdfSJulian Elischer		 * up for us first.
41287e78fdfSJulian Elischer		 *
4134a3a6ee4SJulian Elischer		 * The ports etc should come from a 'hints' section
41445b4f5afSJulian Elischer		 * which is read in by code in isa/isahint.c
4154a3a6ee4SJulian Elischer		 * and kern/subr_bus.c to create resource entries,
4164a3a6ee4SJulian Elischer		 * or have been added by the 'identify routine above.
4174a3a6ee4SJulian Elischer		 *
4184a3a6ee4SJulian Elischer		 * First make a temporary resource reservation.
4194a3a6ee4SJulian Elischer		 * If we can't get the resources we need then
4204a3a6ee4SJulian Elischer		 * we need to abort.  Possibly this indicates
4214a3a6ee4SJulian Elischer		 * the resources were used by another device.
42245b4f5afSJulian Elischer		 */
4234a3a6ee4SJulian Elischer		if ((error = (${1}_allocate_resources(device)))) {
4244a3a6ee4SJulian Elischer			error = ENXIO;
4254a3a6ee4SJulian Elischer			goto errexit;
42687e78fdfSJulian Elischer		}
42787e78fdfSJulian Elischer
4284a3a6ee4SJulian Elischer		/*
4294a3a6ee4SJulian Elischer		 * find out the values of any resources we
4304a3a6ee4SJulian Elischer		 * need for our dumb probe.
4314a3a6ee4SJulian Elischer		 */
43287e78fdfSJulian Elischer		error = bus_get_resource(device, SYS_RES_IOPORT, 0,
43387e78fdfSJulian Elischer			&port_start, &port_count);
43487e78fdfSJulian Elischer
4354a3a6ee4SJulian Elischer		/* dummy heuristic type probe */
4364a3a6ee4SJulian Elischer		if ( inb(port_start) != EXPECTED_VALUE) {
4375e176f9aSJulian Elischer			/* 
43887e78fdfSJulian Elischer			 * It isn't what we hoped, so quit looking for it.
4395e176f9aSJulian Elischer			 */
44045ddd9afSJulian Elischer			error = ENXIO;
44145ddd9afSJulian Elischer		} else {
4424a3a6ee4SJulian Elischer			u_long membase = bus_get_resource_start(device,
4434a3a6ee4SJulian Elischer					SYS_RES_MEMORY, 0 /*rid*/);
4444a3a6ee4SJulian Elischer			u_long memsize;
4454a3a6ee4SJulian Elischer			/*
4464a3a6ee4SJulian Elischer			 * If we discover in some way that the device has
4474a3a6ee4SJulian Elischer			 * XXX bytes of memory window, we can override
4484a3a6ee4SJulian Elischer			 * or set the memory size in the child resource list.
4494a3a6ee4SJulian Elischer			 */
4504a3a6ee4SJulian Elischer			memsize = inb(port_start + 1) * 1024; /* for example */
4514a3a6ee4SJulian Elischer			error = bus_set_resource(device, SYS_RES_MEMORY,
4524a3a6ee4SJulian Elischer				/*rid*/0, membase, memsize);
45345ddd9afSJulian Elischer			/*
45445ddd9afSJulian Elischer			 * We found one..
4554a3a6ee4SJulian Elischer			 * Return -2 if we would LIKE the device
4564a3a6ee4SJulian Elischer			 * Return -1 if we want it a lot
4574a3a6ee4SJulian Elischer			 * Return 0 if we MUST get the device
4584a3a6ee4SJulian Elischer			 * This allows drivers to 'bid' for a device.
45945ddd9afSJulian Elischer			 */
4604a3a6ee4SJulian Elischer			device_set_desc(device, "ACME Widget model 1234");
4614a3a6ee4SJulian Elischer			error = 0; /* we really want it */
46245ddd9afSJulian Elischer		}
4634a3a6ee4SJulian Elischer		/*
4644a3a6ee4SJulian Elischer		 * Unreserve the resources for now because
4654a3a6ee4SJulian Elischer		 * another driver may bid for device too.
4664a3a6ee4SJulian Elischer		 * If we lose the bid, but still hold the resouces, we will
4674a3a6ee4SJulian Elischer		 * effectively have diabled the other driver from getting them
4684a3a6ee4SJulian Elischer		 * which will result in neither driver getting the device.
4694a3a6ee4SJulian Elischer		 * We will ask for them again in attach if we win.
4704a3a6ee4SJulian Elischer		 */
4714a3a6ee4SJulian Elischer		${1}_deallocate_resources(device);
47245b4f5afSJulian Elischer		break;
47345b4f5afSJulian Elischer	case  ENXIO:
4744a3a6ee4SJulian Elischer		/* It was PNP but not ours, leave imediatly */
47545b4f5afSJulian Elischer	default:
47645b4f5afSJulian Elischer		error = ENXIO;
47745b4f5afSJulian Elischer	}
4784a3a6ee4SJulian Elischererrexit:
47945b4f5afSJulian Elischer	return (error);
4805e176f9aSJulian Elischer}
4815e176f9aSJulian Elischer
4825e176f9aSJulian Elischer/*
4834a3a6ee4SJulian Elischer * Called if the probe succeeded and our bid won the device.
4845e176f9aSJulian Elischer * We can be destructive here as we know we have the device.
4854a3a6ee4SJulian Elischer * This is the first place we can be sure we have a softc structure.
486e904636aSJulian Elischer * You would do ISA specific attach things here, but generically there aren't
487e904636aSJulian Elischer * any (yey new-bus!).
4885e176f9aSJulian Elischer */
4895e176f9aSJulian Elischerstatic int
49045b4f5afSJulian Elischer${1}_isa_attach (device_t device)
4915e176f9aSJulian Elischer{
49245b4f5afSJulian Elischer	sc_p	scp	= device_get_softc(device);
493e904636aSJulian Elischer        int	error;
494e904636aSJulian Elischer
495e904636aSJulian Elischer        error =  ${1}_attach(device, scp);
496e904636aSJulian Elischer        if (error) {
497e904636aSJulian Elischer                ${1}_isa_detach(device);
498e904636aSJulian Elischer        }
499e904636aSJulian Elischer        return (error);
500e904636aSJulian Elischer
501e904636aSJulian Elischer}
502e904636aSJulian Elischer
503e904636aSJulian Elischer/* 
504e904636aSJulian Elischer * detach the driver (e.g. module unload)
505e904636aSJulian Elischer * call the bus independent version
506e904636aSJulian Elischer * and undo anything we did in the ISA attach routine.
507e904636aSJulian Elischer */
508e904636aSJulian Elischerstatic int
509e904636aSJulian Elischer${1}_isa_detach (device_t device)
510e904636aSJulian Elischer{
511e904636aSJulian Elischer	sc_p	scp	= device_get_softc(device);
512e904636aSJulian Elischer        int	error;
513e904636aSJulian Elischer
514e904636aSJulian Elischer        error =  ${1}_detach(device, scp);
515e904636aSJulian Elischer        return (error);
516e904636aSJulian Elischer}
517e904636aSJulian Elischer
518e904636aSJulian Elischer/***************************************\
519e904636aSJulian Elischer* PCI Attachment structures and code	*
520e904636aSJulian Elischer\***************************************/
521e904636aSJulian Elischer
522e904636aSJulian Elischerstatic int	${1}_pci_probe	__P((device_t));
523e904636aSJulian Elischerstatic int	${1}_pci_attach	__P((device_t));
524e904636aSJulian Elischerstatic int	${1}_pci_detach	__P((device_t));
525e904636aSJulian Elischer
526e904636aSJulian Elischerstatic device_method_t ${1}_pci_methods[] = {
527e904636aSJulian Elischer	/* Device interface */
528e904636aSJulian Elischer	DEVMETHOD(device_probe,		${1}_pci_probe),
529e904636aSJulian Elischer	DEVMETHOD(device_attach,	${1}_pci_attach),
530e904636aSJulian Elischer	DEVMETHOD(device_detach,	${1}_pci_detach),
531e904636aSJulian Elischer	{ 0, 0 }
532e904636aSJulian Elischer};
533e904636aSJulian Elischer
534e904636aSJulian Elischerstatic driver_t ${1}_pci_driver = {
535e904636aSJulian Elischer	"${1}",
536e904636aSJulian Elischer	${1}_pci_methods,
537e904636aSJulian Elischer	sizeof(struct ${1}_softc),
538e904636aSJulian Elischer};
539e904636aSJulian Elischer
540e904636aSJulian Elischerstatic devclass_t ${1}_pci_devclass;
541e904636aSJulian Elischer
542e904636aSJulian ElischerDRIVER_MODULE(${1}, pci, ${1}_pci_driver, ${1}_pci_devclass, 0, 0);
543e904636aSJulian Elischer
544e904636aSJulian Elischerstatic struct _pcsid
545e904636aSJulian Elischer{
546e904636aSJulian Elischer	u_int32_t	type;
547e904636aSJulian Elischer	const char	*desc;
548e904636aSJulian Elischer} pci_ids[] = {
549e904636aSJulian Elischer	{ 0x1234abcd,	"ACME PCI Widgetplus"	},
550e904636aSJulian Elischer	{ 0x1234fedc,	"Happy moon brand RIPOFFplus"	},
551e904636aSJulian Elischer	{ 0x00000000,	NULL					}
552e904636aSJulian Elischer};
553e904636aSJulian Elischer
554e904636aSJulian Elischerstatic int
555e904636aSJulian Elischer${1}_pci_probe (device_t device)
556e904636aSJulian Elischer{
557e904636aSJulian Elischer	u_int32_t	type = pci_get_devid(device);
558e904636aSJulian Elischer	struct _pcsid	*ep =pci_ids;
559e904636aSJulian Elischer
560e904636aSJulian Elischer	while (ep->type && ep->type != type)
561e904636aSJulian Elischer		++ep;
562e904636aSJulian Elischer	if (ep->desc) {
563e904636aSJulian Elischer		device_set_desc(device, ep->desc);
564e904636aSJulian Elischer		return 0;
565e904636aSJulian Elischer	} else {
566e904636aSJulian Elischer		return ENXIO;
567e904636aSJulian Elischer	}
568e904636aSJulian Elischer}
569e904636aSJulian Elischer
570e904636aSJulian Elischerstatic int
571e904636aSJulian Elischer${1}_pci_attach(device_t device)
572e904636aSJulian Elischer{
573e904636aSJulian Elischer	sc_p	scp	= device_get_softc(device);
574e904636aSJulian Elischer        int	error;
575e904636aSJulian Elischer
576e904636aSJulian Elischer        error =  ${1}_attach(device, scp);
577e904636aSJulian Elischer        if (error) {
578e904636aSJulian Elischer                ${1}_pci_detach(device);
579e904636aSJulian Elischer        }
580e904636aSJulian Elischer        return (error);
581e904636aSJulian Elischer}
582e904636aSJulian Elischer
583e904636aSJulian Elischerstatic int
584e904636aSJulian Elischer${1}_pci_detach (device_t device)
585e904636aSJulian Elischer{
586e904636aSJulian Elischer	sc_p	scp	= device_get_softc(device);
587e904636aSJulian Elischer        int	error;
588e904636aSJulian Elischer
589e904636aSJulian Elischer        error =  ${1}_detach(device, scp);
590e904636aSJulian Elischer        return (error);
591e904636aSJulian Elischer}
592e904636aSJulian Elischer
593e904636aSJulian Elischer
594e904636aSJulian Elischer/****************************************\
595e904636aSJulian Elischer*  Common Attachment subfunctions	*
596e904636aSJulian Elischer\****************************************/
597e904636aSJulian Elischerstatic int
598e904636aSJulian Elischer${1}_attach(device_t device, sc_p scp)
599e904636aSJulian Elischer{
600e904636aSJulian Elischer	int	unit	= device_get_unit(device);
601d1d3a974SJulian Elischer	device_t parent	= device_get_parent(device);
6025e176f9aSJulian Elischer
60345ddd9afSJulian Elischer	scp->dev = make_dev(&${1}_cdevsw, 0,
60445ddd9afSJulian Elischer			UID_ROOT, GID_OPERATOR, 0600, "${1}%d", unit);
605e904636aSJulian Elischer	scp->dev->si_drv1 = scp;
60645ddd9afSJulian Elischer
60745ddd9afSJulian Elischer	if (${1}_allocate_resources(device)) {
60845ddd9afSJulian Elischer		goto errexit;
60945ddd9afSJulian Elischer	}
61045ddd9afSJulian Elischer
6114a3a6ee4SJulian Elischer	scp->bt = rman_get_bustag(scp->res_ioport);
6124a3a6ee4SJulian Elischer	scp->bh = rman_get_bushandle(scp->res_ioport);
61345ddd9afSJulian Elischer
61445ddd9afSJulian Elischer	/* register the interrupt handler */
6154a3a6ee4SJulian Elischer	/*
6164a3a6ee4SJulian Elischer	 * The type should be one of:
6174a3a6ee4SJulian Elischer	 *	INTR_TYPE_TTY
6184a3a6ee4SJulian Elischer	 *	(INTR_TYPE_TTY | INTR_TYPE_FAST) 
6194a3a6ee4SJulian Elischer	 *	INTR_TYPE_BIO 
6204a3a6ee4SJulian Elischer	 *	INTR_TYPE_CAM 
6214a3a6ee4SJulian Elischer	 *	INTR_TYPE_NET 
6224a3a6ee4SJulian Elischer	 *	INTR_TYPE_MISC 
6234a3a6ee4SJulian Elischer	 * This will probably change with SMPng.
6244a3a6ee4SJulian Elischer	 */
625d1d3a974SJulian Elischer	if (scp->res_irq) {
626d1d3a974SJulian Elischer		/* default to the tty mask for registration */  /* XXX */
627d1d3a974SJulian Elischer		if (BUS_SETUP_INTR(parent, device, scp->res_irq, INTR_TYPE_TTY,
62845ddd9afSJulian Elischer				${1}intr, scp, &scp->intr_cookie) == 0) {
629d1d3a974SJulian Elischer			/* do something if successfull */
630e904636aSJulian Elischer		} else {
631e904636aSJulian Elischer			goto errexit;
632d1d3a974SJulian Elischer		}
633d1d3a974SJulian Elischer	}
6344a3a6ee4SJulian Elischer
6354a3a6ee4SJulian Elischer	/*
6364a3a6ee4SJulian Elischer	 * If we want to access the memory we will need
6374a3a6ee4SJulian Elischer	 * to know where it was mapped.
6384a3a6ee4SJulian Elischer	 */
6394a3a6ee4SJulian Elischer	scp->vaddr = rman_get_virtual(scp->res_memory);
64045b4f5afSJulian Elischer	return 0;
64145ddd9afSJulian Elischer
64245ddd9afSJulian Elischererrexit:
64345ddd9afSJulian Elischer	/*
64445ddd9afSJulian Elischer	 * Undo anything we may have done
64545ddd9afSJulian Elischer	 */
646e904636aSJulian Elischer	${1}_detach(device, scp);
64745ddd9afSJulian Elischer	return (ENXIO);
64845b4f5afSJulian Elischer}
64964b2faf8SBruce Evans
65045b4f5afSJulian Elischerstatic int
651e904636aSJulian Elischer${1}_detach(device_t device, sc_p scp)
65245b4f5afSJulian Elischer{
653d1d3a974SJulian Elischer	device_t parent = device_get_parent(device);
65445b4f5afSJulian Elischer
65545ddd9afSJulian Elischer	/*
65645ddd9afSJulian Elischer	 * At this point stick a strong piece of wood into the device
65745ddd9afSJulian Elischer	 * to make sure it is stopped safely. The alternative is to 
65845ddd9afSJulian Elischer	 * simply REFUSE to detach if it's busy. What you do depends on 
65945ddd9afSJulian Elischer	 * your specific situation.
66045ddd9afSJulian Elischer	 */
66145ddd9afSJulian Elischer	/* ZAP some register */
66245ddd9afSJulian Elischer
66345ddd9afSJulian Elischer	/*
66445ddd9afSJulian Elischer	 * Take our interrupt handler out of the list of handlers
66545ddd9afSJulian Elischer	 * that can handle this irq.
66645ddd9afSJulian Elischer	 */
66745ddd9afSJulian Elischer	if (scp->intr_cookie != NULL) {
668d1d3a974SJulian Elischer		if (BUS_TEARDOWN_INTR(parent, device,
669d1d3a974SJulian Elischer			scp->res_irq, scp->intr_cookie) != 0) {
670d1d3a974SJulian Elischer				printf("intr teardown failed.. continuing\n");
671d1d3a974SJulian Elischer		}
67245ddd9afSJulian Elischer		scp->intr_cookie = NULL;
67345ddd9afSJulian Elischer	}
67445ddd9afSJulian Elischer
67545ddd9afSJulian Elischer	/*
67645ddd9afSJulian Elischer	 * deallocate any system resources we may have
67745ddd9afSJulian Elischer	 * allocated on behalf of this driver.
67845ddd9afSJulian Elischer	 */
6794a3a6ee4SJulian Elischer	scp->vaddr = NULL;
68045ddd9afSJulian Elischer	return ${1}_deallocate_resources(device);
68145ddd9afSJulian Elischer}
68245ddd9afSJulian Elischer
68345ddd9afSJulian Elischerstatic int
68445ddd9afSJulian Elischer${1}_allocate_resources(device_t device)
68545ddd9afSJulian Elischer{
68645ddd9afSJulian Elischer	int error;
68745ddd9afSJulian Elischer	sc_p scp = device_get_softc(device);
68845ddd9afSJulian Elischer	int	size = 16; /* SIZE of port range used */
68945ddd9afSJulian Elischer
69045ddd9afSJulian Elischer	scp->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT,
69145ddd9afSJulian Elischer			&scp->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE);
69245ddd9afSJulian Elischer	if (scp->res_ioport == NULL) {
69345ddd9afSJulian Elischer		goto errexit;
69445ddd9afSJulian Elischer	}
69545ddd9afSJulian Elischer
69645ddd9afSJulian Elischer	scp->res_irq = bus_alloc_resource(device, SYS_RES_IRQ,
6974a3a6ee4SJulian Elischer			&scp->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE|RF_ACTIVE);
69845ddd9afSJulian Elischer	if (scp->res_irq == NULL) {
69945ddd9afSJulian Elischer		goto errexit;
70045ddd9afSJulian Elischer	}
70145ddd9afSJulian Elischer
70245ddd9afSJulian Elischer	scp->res_drq = bus_alloc_resource(device, SYS_RES_DRQ,
70345ddd9afSJulian Elischer			&scp->rid_drq, 0ul, ~0ul, 1, RF_ACTIVE);
70445ddd9afSJulian Elischer	if (scp->res_drq == NULL) {
70545ddd9afSJulian Elischer		goto errexit;
70645ddd9afSJulian Elischer	}
70745ddd9afSJulian Elischer
70887e78fdfSJulian Elischer	scp->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
70945ddd9afSJulian Elischer			&scp->rid_memory, 0ul, ~0ul, MSIZE, RF_ACTIVE);
71045ddd9afSJulian Elischer	if (scp->res_memory == NULL) {
71145ddd9afSJulian Elischer		goto errexit;
71245ddd9afSJulian Elischer	}
71345ddd9afSJulian Elischer	return (0);
71445ddd9afSJulian Elischer
71545ddd9afSJulian Elischererrexit:
71645ddd9afSJulian Elischer	error = ENXIO;
71745ddd9afSJulian Elischer	/* cleanup anything we may have assigned. */
71845ddd9afSJulian Elischer	${1}_deallocate_resources(device);
71945ddd9afSJulian Elischer	return (ENXIO); /* for want of a better idea */
72045ddd9afSJulian Elischer}
72145ddd9afSJulian Elischer
72245ddd9afSJulian Elischerstatic int
72345ddd9afSJulian Elischer${1}_deallocate_resources(device_t device)
72445ddd9afSJulian Elischer{
72545ddd9afSJulian Elischer	sc_p scp = device_get_softc(device);
72645ddd9afSJulian Elischer
72745ddd9afSJulian Elischer	if (scp->res_irq != 0) {
728d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_IRQ,
729d1d3a974SJulian Elischer			scp->rid_irq, scp->res_irq);
730d1d3a974SJulian Elischer		bus_release_resource(device, SYS_RES_IRQ,
731d1d3a974SJulian Elischer			scp->rid_irq, scp->res_irq);
732d1d3a974SJulian Elischer		scp->res_irq = 0;
733d1d3a974SJulian Elischer	}
734d1d3a974SJulian Elischer	if (scp->res_ioport != 0) {
735d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_IOPORT,
736d1d3a974SJulian Elischer			scp->rid_ioport, scp->res_ioport);
73745b4f5afSJulian Elischer		bus_release_resource(device, SYS_RES_IOPORT,
738d1d3a974SJulian Elischer			scp->rid_ioport, scp->res_ioport);
739d1d3a974SJulian Elischer		scp->res_ioport = 0;
740d1d3a974SJulian Elischer	}
741d1d3a974SJulian Elischer	if (scp->res_ioport != 0) {
742d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_MEMORY,
743d1d3a974SJulian Elischer			scp->rid_memory, scp->res_memory);
744d1d3a974SJulian Elischer		bus_release_resource(device, SYS_RES_MEMORY,
745d1d3a974SJulian Elischer			scp->rid_memory, scp->res_memory);
746d1d3a974SJulian Elischer		scp->res_ioport = 0;
747d1d3a974SJulian Elischer	}
748d1d3a974SJulian Elischer	if (scp->res_drq != 0) {
749d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_DRQ,
750d1d3a974SJulian Elischer			scp->rid_drq, scp->res_drq);
751d1d3a974SJulian Elischer		bus_release_resource(device, SYS_RES_DRQ,
752d1d3a974SJulian Elischer			scp->rid_drq, scp->res_drq);
753d1d3a974SJulian Elischer		scp->res_drq = 0;
754d1d3a974SJulian Elischer	}
755d1d3a974SJulian Elischer	if (scp->dev) {
75645b4f5afSJulian Elischer		destroy_dev(scp->dev);
757d1d3a974SJulian Elischer	}
7585e176f9aSJulian Elischer	return (0);
7595e176f9aSJulian Elischer}
7605e176f9aSJulian Elischer
76164b2faf8SBruce Evansstatic void
76245b4f5afSJulian Elischer${1}intr(void *arg)
7635e176f9aSJulian Elischer{
76445ddd9afSJulian Elischer	sc_p scp	= arg;
7655e176f9aSJulian Elischer
7665e176f9aSJulian Elischer	/* 
7675e176f9aSJulian Elischer	 * well we got an interupt, now what?
7685e176f9aSJulian Elischer	 */
7695e176f9aSJulian Elischer	return;
7705e176f9aSJulian Elischer}
7715e176f9aSJulian Elischer
77245b4f5afSJulian Elischerstatic int
77345b4f5afSJulian Elischer${1}ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
7745e176f9aSJulian Elischer{
77587e78fdfSJulian Elischer	sc_p scp	= dev->si_drv1;
7765e176f9aSJulian Elischer
7775e176f9aSJulian Elischer	switch (cmd) {
7785e176f9aSJulian Elischer	case DHIOCRESET:
7795e176f9aSJulian Elischer		/* whatever resets it */
78087e78fdfSJulian Elischer#if 0
78145b4f5afSJulian Elischer		${UPPER}_OUTB(SOME_PORT, 0xff) ;
78287e78fdfSJulian Elischer#endif
7835e176f9aSJulian Elischer		break;
7845e176f9aSJulian Elischer	default:
7855e176f9aSJulian Elischer		return ENXIO;
7865e176f9aSJulian Elischer	}
7875e176f9aSJulian Elischer	return (0);
7885e176f9aSJulian Elischer}
7895e176f9aSJulian Elischer/*
7905e176f9aSJulian Elischer * You also need read, write, open, close routines.
7915e176f9aSJulian Elischer * This should get you started
7925e176f9aSJulian Elischer */
7935e176f9aSJulian Elischerstatic int
7945e176f9aSJulian Elischer${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
7955e176f9aSJulian Elischer{
79687e78fdfSJulian Elischer	sc_p scp	= dev->si_drv1;
7975e176f9aSJulian Elischer
7985e176f9aSJulian Elischer	/* 
7995e176f9aSJulian Elischer	 * Do processing
8005e176f9aSJulian Elischer	 */
8015e176f9aSJulian Elischer	return (0);
8025e176f9aSJulian Elischer}
8035e176f9aSJulian Elischer
8045e176f9aSJulian Elischerstatic int
8055e176f9aSJulian Elischer${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
8065e176f9aSJulian Elischer{
80787e78fdfSJulian Elischer	sc_p scp	= dev->si_drv1;
8085e176f9aSJulian Elischer
8095e176f9aSJulian Elischer	/* 
8105e176f9aSJulian Elischer	 * Do processing
8115e176f9aSJulian Elischer	 */
8125e176f9aSJulian Elischer	return (0);
8135e176f9aSJulian Elischer}
8145e176f9aSJulian Elischer
8155e176f9aSJulian Elischerstatic int
8165e176f9aSJulian Elischer${1}read(dev_t dev, struct uio *uio, int ioflag)
8175e176f9aSJulian Elischer{
81887e78fdfSJulian Elischer	sc_p scp	= dev->si_drv1;
8195e176f9aSJulian Elischer	int	 toread;
8205e176f9aSJulian Elischer
8215e176f9aSJulian Elischer
8225e176f9aSJulian Elischer	/* 
8235e176f9aSJulian Elischer	 * Do processing
8245e176f9aSJulian Elischer	 * read from buffer
8255e176f9aSJulian Elischer	 */
8265e176f9aSJulian Elischer	toread = (min(uio->uio_resid, sizeof(scp->buffer)));
8275e176f9aSJulian Elischer	return(uiomove(scp->buffer, toread, uio));
8285e176f9aSJulian Elischer}
8295e176f9aSJulian Elischer
8305e176f9aSJulian Elischerstatic int
8315e176f9aSJulian Elischer${1}write(dev_t dev, struct uio *uio, int ioflag)
8325e176f9aSJulian Elischer{
83387e78fdfSJulian Elischer	sc_p scp	= dev->si_drv1;
8345e176f9aSJulian Elischer	int	towrite;
8355e176f9aSJulian Elischer
8365e176f9aSJulian Elischer	/* 
8375e176f9aSJulian Elischer	 * Do processing
8385e176f9aSJulian Elischer	 * write to buffer
8395e176f9aSJulian Elischer	 */
8405e176f9aSJulian Elischer	towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
8415e176f9aSJulian Elischer	return(uiomove(scp->buffer, towrite, uio));
8425e176f9aSJulian Elischer}
8435e176f9aSJulian Elischer
8445e176f9aSJulian Elischerstatic int
84545b4f5afSJulian Elischer${1}mmap(dev_t dev, vm_offset_t offset, int nprot)
8465e176f9aSJulian Elischer{
84787e78fdfSJulian Elischer	sc_p scp	= dev->si_drv1;
8485e176f9aSJulian Elischer
8495e176f9aSJulian Elischer	/* 
85087e78fdfSJulian Elischer	 * Given a byte offset into your device, return the PHYSICAL
85187e78fdfSJulian Elischer	 * page number that it would map to.
8525e176f9aSJulian Elischer	 */
8535e176f9aSJulian Elischer#if 0	/* if we had a frame buffer or whatever.. do this */
8545e176f9aSJulian Elischer	if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
8555e176f9aSJulian Elischer		return (-1);
8565e176f9aSJulian Elischer	}
8575e176f9aSJulian Elischer	return i386_btop((FRAMEBASE + offset));
8585e176f9aSJulian Elischer#else
8595e176f9aSJulian Elischer	return (-1);
8605e176f9aSJulian Elischer#endif
8615e176f9aSJulian Elischer}
8625e176f9aSJulian Elischer
8635e176f9aSJulian Elischerstatic int
864f7fa6f64SJulian Elischer${1}poll(dev_t dev, int which, struct proc *p)
8655e176f9aSJulian Elischer{
86687e78fdfSJulian Elischer	sc_p scp	= dev->si_drv1;
8675e176f9aSJulian Elischer
8685e176f9aSJulian Elischer	/* 
8695e176f9aSJulian Elischer	 * Do processing
8705e176f9aSJulian Elischer	 */
8715e176f9aSJulian Elischer	return (0); /* this is the wrong value I'm sure */
8725e176f9aSJulian Elischer}
8735e176f9aSJulian Elischer
8745e176f9aSJulian ElischerDONE
8755e176f9aSJulian Elischer
87645b4f5afSJulian Elischercat >${TOP}/sys/${1}io.h <<DONE
8775e176f9aSJulian Elischer/*
8785e176f9aSJulian Elischer * Definitions needed to access the ${1} device (ioctls etc)
8795e176f9aSJulian Elischer * see mtio.h , ioctl.h as examples
8805e176f9aSJulian Elischer */
8815e176f9aSJulian Elischer#ifndef SYS_DHIO_H
8825e176f9aSJulian Elischer#define SYS_DHIO_H
8835e176f9aSJulian Elischer
8845e176f9aSJulian Elischer#ifndef KERNEL
8855e176f9aSJulian Elischer#include <sys/types.h>
8865e176f9aSJulian Elischer#endif
8875e176f9aSJulian Elischer#include <sys/ioccom.h>
8885e176f9aSJulian Elischer
8895e176f9aSJulian Elischer/*
8905e176f9aSJulian Elischer * define an ioctl here
8915e176f9aSJulian Elischer */
8925e176f9aSJulian Elischer#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
8935e176f9aSJulian Elischer#endif
8945e176f9aSJulian ElischerDONE
8955e176f9aSJulian Elischer
89645b4f5afSJulian Elischerif [ ! -d ${TOP}/modules/${1} ]
8974308b695SJulian Elischerthen
89845b4f5afSJulian Elischer	mkdir -p ${TOP}/modules/${1}
89945b4f5afSJulian Elischerfi
90045b4f5afSJulian Elischer
90145b4f5afSJulian Elischercat >${TOP}/modules/${1}/Makefile <<DONE
9024308b695SJulian Elischer#	${UPPER} Loadable Kernel Module
9034308b695SJulian Elischer#
90496305e8fSJulian Elischer# \$${RCS_KEYWORD}: $
9054308b695SJulian Elischer 
90645b4f5afSJulian Elischer.PATH:  \${.CURDIR}/../../dev/${1}
90745b4f5afSJulian ElischerKMOD    = ${1}
90845b4f5afSJulian ElischerSRCS    = ${1}.c
90945b4f5afSJulian ElischerSRCS    += opt_inet.h device_if.h bus_if.h pci_if.h isa_if.h
9104308b695SJulian Elischer  
91145b4f5afSJulian Elischer# you may need to do this is your device is an if_xxx driver
91245b4f5afSJulian Elischeropt_inet.h:
91345b4f5afSJulian Elischer	echo "#define INET 1" > opt_inet.h
9144308b695SJulian Elischer	   
9154308b695SJulian Elischer.include <bsd.kmod.mk>
9164308b695SJulian ElischerDONE
91745b4f5afSJulian Elischer
91845b4f5afSJulian Elischer(cd ${TOP}/modules/${1}; make depend; make )
91945b4f5afSJulian Elischerexit
9204308b695SJulian Elischer
9215e176f9aSJulian Elischerconfig ${UPPER}
9225e176f9aSJulian Elischercd ../../compile/${UPPER}
9235e176f9aSJulian Elischermake depend
9245e176f9aSJulian Elischermake ${1}.o
9255e176f9aSJulian Elischermake
9265e176f9aSJulian Elischerexit
9275e176f9aSJulian Elischer
9285e176f9aSJulian Elischer#--------------end of script---------------
9295e176f9aSJulian Elischer#
9305e176f9aSJulian Elischer#edit to your taste..
9315e176f9aSJulian Elischer#
9325e176f9aSJulian Elischer#
9335e176f9aSJulian Elischer
9345e176f9aSJulian Elischer
9355e176f9aSJulian Elischer
9365e176f9aSJulian Elischer
937