xref: /freebsd/share/examples/drivers/make_device_driver.sh (revision 853fbff5f7e5eb0ebab1bf097baed640c3d811f1)
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"
154308b695SJulian Elischer#
165e176f9aSJulian Elischer# Trust me, RUN THIS SCRIPT :)
1787e78fdfSJulian Elischer#
186715fca9SWarner Losh# TODO:
196715fca9SWarner Losh#   o generate foo_isa.c, foo_pci.c, foo_pccard.c, foo_cardbus.c, and foovar.h
206715fca9SWarner Losh#   o Put pccard stuff in here.
216715fca9SWarner Losh#
2245b4f5afSJulian Elischer# $FreeBSD$"
235e176f9aSJulian Elischer#
24e904636aSJulian Elischer#
2511027719SBrian Somersif [ "X${1}" = "X" ]
265e176f9aSJulian Elischerthen
275e176f9aSJulian Elischer	echo "Hey , how about some help here.. give me a device name!"
285e176f9aSJulian Elischer	exit 1
295e176f9aSJulian Elischerfi
3045b4f5afSJulian ElischerUPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
315e176f9aSJulian Elischer
3245b4f5afSJulian ElischerHERE=`pwd`
3345b4f5afSJulian Elischercd /sys
3445b4f5afSJulian ElischerTOP=`pwd`
3545b4f5afSJulian Elischer
3696305e8fSJulian ElischerRCS_KEYWORD=FreeBSD
3796305e8fSJulian Elischer
3887e78fdfSJulian Elischerif [ -d ${TOP}/modules/${1} ]
3987e78fdfSJulian Elischerthen
4087e78fdfSJulian Elischer	echo "There appears to already be a module called ${1}"
4187e78fdfSJulian Elischer	echo -n "Should it be overwritten? [Y]"
4287e78fdfSJulian Elischer	read VAL
4387e78fdfSJulian Elischer	if [ "-z" "$VAL" ]
4487e78fdfSJulian Elischer	then
4587e78fdfSJulian Elischer	  VAL=YES
4687e78fdfSJulian Elischer	fi
4787e78fdfSJulian Elischer	case ${VAL} in
4887e78fdfSJulian Elischer	[yY]*)
4987e78fdfSJulian Elischer	  echo "Cleaning up from prior runs"
5087e78fdfSJulian Elischer	  rm -rf ${TOP}/dev/${1}
5187e78fdfSJulian Elischer	  rm -rf ${TOP}/modules/${1}
5287e78fdfSJulian Elischer	  rm ${TOP}/i386/conf/files.${UPPER}
5387e78fdfSJulian Elischer	  rm ${TOP}/i386/conf/${UPPER}
5487e78fdfSJulian Elischer	  rm ${TOP}/sys/${1}io.h
5587e78fdfSJulian Elischer	  ;;
5687e78fdfSJulian Elischer	*)
5787e78fdfSJulian Elischer	  exit 1
5887e78fdfSJulian Elischer	  ;;
5987e78fdfSJulian Elischer	esac
6087e78fdfSJulian Elischerfi
6187e78fdfSJulian Elischer
6287e78fdfSJulian Elischerecho "The following files will be created:"
6345b4f5afSJulian Elischerecho ${TOP}/modules/${1}
6445b4f5afSJulian Elischerecho ${TOP}/i386/conf/files.${UPPER}
6545b4f5afSJulian Elischerecho ${TOP}/i386/conf/${UPPER}
6645b4f5afSJulian Elischerecho ${TOP}/dev/${1}
6745b4f5afSJulian Elischerecho ${TOP}/dev/${1}/${1}.c
6845b4f5afSJulian Elischerecho ${TOP}/sys/${1}io.h
6945b4f5afSJulian Elischerecho ${TOP}/modules/${1}
7045b4f5afSJulian Elischerecho ${TOP}/modules/${1}/Makefile
7145b4f5afSJulian Elischer
7245b4f5afSJulian Elischer
7345b4f5afSJulian Elischer	mkdir ${TOP}/modules/${1}
744308b695SJulian Elischer
7545b4f5afSJulian Elischer#######################################################################
7645b4f5afSJulian Elischer#######################################################################
7745b4f5afSJulian Elischer#
7845b4f5afSJulian Elischer# Create configuration information needed to create a kernel
7945b4f5afSJulian Elischer# containing this driver.
8045b4f5afSJulian Elischer#
8145b4f5afSJulian Elischer# Not really needed if we are going to do this as a module.
8245b4f5afSJulian Elischer#######################################################################
8345b4f5afSJulian Elischer# First add the file to a local file list.
8445b4f5afSJulian Elischer#######################################################################
8545b4f5afSJulian Elischer
8645b4f5afSJulian Elischercat >${TOP}/i386/conf/files.${UPPER} <<DONE
8745ddd9afSJulian Elischerdev/${1}/${1}.c	 optional ${1}
885e176f9aSJulian ElischerDONE
895e176f9aSJulian Elischer
9045b4f5afSJulian Elischer#######################################################################
9145b4f5afSJulian Elischer# Then create a configuration file for a kernel that contains this driver.
9245b4f5afSJulian Elischer#######################################################################
9345b4f5afSJulian Elischercat >${TOP}/i386/conf/${UPPER} <<DONE
945e176f9aSJulian Elischer# Configuration file for kernel type: ${UPPER}
955e176f9aSJulian Elischerident	${UPPER}
9696305e8fSJulian Elischer# \$${RCS_KEYWORD}: $
975e176f9aSJulian ElischerDONE
985e176f9aSJulian Elischer
9945b4f5afSJulian Elischergrep -v GENERIC < /sys/i386/conf/GENERIC >>${TOP}/i386/conf/${UPPER}
1005e176f9aSJulian Elischer
10145b4f5afSJulian Elischercat >>${TOP}/i386/conf/${UPPER} <<DONE
10245b4f5afSJulian Elischeroptions		DDB		# trust me, you'll need this
10345ddd9afSJulian Elischerdevice		${1}
1045e176f9aSJulian ElischerDONE
1055e176f9aSJulian Elischer
10645b4f5afSJulian Elischerif [ ! -d ${TOP}/dev/${1} ]
10745b4f5afSJulian Elischerthen
10845b4f5afSJulian Elischer	mkdir -p ${TOP}/dev/${1}
10945b4f5afSJulian Elischerfi
11045b4f5afSJulian Elischer
11145b4f5afSJulian Elischer
11245b4f5afSJulian Elischer
11345b4f5afSJulian Elischer
11445b4f5afSJulian Elischercat >${TOP}/dev/${1}/${1}.c <<DONE
1155e176f9aSJulian Elischer/*
11696305e8fSJulian Elischer * Copyright (c) [year] [your name]
11796305e8fSJulian Elischer * All rights reserved.
11896305e8fSJulian Elischer *
11996305e8fSJulian Elischer * Redistribution and use in source and binary forms, with or without
12096305e8fSJulian Elischer * modification, are permitted provided that the following conditions
12196305e8fSJulian Elischer * are met:
12296305e8fSJulian Elischer * 1. Redistributions of source code must retain the above copyright
12396305e8fSJulian Elischer *    notice, this list of conditions and the following disclaimer.
12496305e8fSJulian Elischer * 2. Redistributions in binary form must reproduce the above copyright
12596305e8fSJulian Elischer *    notice, this list of conditions and the following disclaimer in the
12696305e8fSJulian Elischer *    documentation and/or other materials provided with the distribution.
12796305e8fSJulian Elischer *
12896305e8fSJulian Elischer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
12996305e8fSJulian Elischer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13096305e8fSJulian Elischer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13196305e8fSJulian Elischer * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
13296305e8fSJulian Elischer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13396305e8fSJulian Elischer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13496305e8fSJulian Elischer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13596305e8fSJulian Elischer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13696305e8fSJulian Elischer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13796305e8fSJulian Elischer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13896305e8fSJulian Elischer * SUCH DAMAGE.
13996305e8fSJulian Elischer *
1405e176f9aSJulian Elischer *
1415e176f9aSJulian Elischer * ${1} driver
14296305e8fSJulian Elischer * \$${RCS_KEYWORD}: $
1435e176f9aSJulian Elischer */
1445e176f9aSJulian Elischer
1454a3a6ee4SJulian Elischer/*
1464a3a6ee4SJulian Elischer * http://www.daemonnews.org/200008/isa.html is required reading.
1474a3a6ee4SJulian Elischer * hopefully it will make it's way into the handbook.
1484a3a6ee4SJulian Elischer */
1495e176f9aSJulian Elischer
1505e176f9aSJulian Elischer#include <sys/param.h>
1515e176f9aSJulian Elischer#include <sys/systm.h>
1525e176f9aSJulian Elischer#include <sys/conf.h>		/* cdevsw stuff */
15345b4f5afSJulian Elischer#include <sys/kernel.h>		/* SYSINIT stuff */
15445b4f5afSJulian Elischer#include <sys/uio.h>		/* SYSINIT stuff */
1555e176f9aSJulian Elischer#include <sys/malloc.h>		/* malloc region definitions */
15645b4f5afSJulian Elischer#include <sys/module.h>
15745b4f5afSJulian Elischer#include <sys/bus.h>
158853fbff5SAndrew R. Reiter#include <sys/proc.h>
15945b4f5afSJulian Elischer#include <machine/bus.h>
16045b4f5afSJulian Elischer#include <machine/resource.h>
161e904636aSJulian Elischer#include <machine/bus_pio.h>
162e904636aSJulian Elischer#include <machine/bus_memio.h>
16345b4f5afSJulian Elischer#include <sys/rman.h>
16445b4f5afSJulian Elischer#include <sys/time.h>
1655e176f9aSJulian Elischer
166e904636aSJulian Elischer#include <pci/pcireg.h>
167e904636aSJulian Elischer#include <pci/pcivar.h>
168e904636aSJulian Elischer
16945b4f5afSJulian Elischer#include <isa/isavar.h>
17045b4f5afSJulian Elischer#include "isa_if.h"
17145b4f5afSJulian Elischer#include <sys/${1}io.h>		/* ${1} IOCTL definitions */
17245b4f5afSJulian Elischer
17387e78fdfSJulian Elischer/* XXX These should be defined in terms of bus-space ops */
17487e78fdfSJulian Elischer#define ${UPPER}_INB(port) inb(port_start)
17587e78fdfSJulian Elischer#define ${UPPER}_OUTB(port, val) ( port_start, (val))
17645b4f5afSJulian Elischer#define SOME_PORT 123
17745b4f5afSJulian Elischer#define EXPECTED_VALUE 0x42
1785e176f9aSJulian Elischer
17911027719SBrian Somers/*
18011027719SBrian Somers * The softc is automatically allocated by the parent bus using the
18111027719SBrian Somers * size specified in the driver_t declaration below
18211027719SBrian Somers */
1836715fca9SWarner Losh#define DEV2SOFTC(dev)	((struct ${1}_softc *) (dev)->si_drv1)
1846715fca9SWarner Losh#define DEVICE2SOFTC(dev) ((struct ${1}_softc *) device_get_softc(dev))
1856715fca9SWarner Losh
1865e176f9aSJulian Elischer/* 
1875e176f9aSJulian Elischer * device specific Misc defines 
1885e176f9aSJulian Elischer */
1895e176f9aSJulian Elischer#define BUFFERSIZE	1024
1905e176f9aSJulian Elischer#define NUMPORTS	4
19187e78fdfSJulian Elischer#define MEMSIZE		(4 * 1024) /* imaginable h/w buffer size */
1925e176f9aSJulian Elischer
1935e176f9aSJulian Elischer/*
1945e176f9aSJulian Elischer * One of these per allocated device
1955e176f9aSJulian Elischer */
1965e176f9aSJulian Elischerstruct ${1}_softc {
19745b4f5afSJulian Elischer	bus_space_tag_t bt;
19845b4f5afSJulian Elischer	bus_space_handle_t bh;
199d1d3a974SJulian Elischer	int rid_ioport;
200d1d3a974SJulian Elischer	int rid_memory;
201d1d3a974SJulian Elischer	int rid_irq;
202d1d3a974SJulian Elischer	int rid_drq;
203d1d3a974SJulian Elischer	struct resource* res_ioport;	/* resource for port range */
204d1d3a974SJulian Elischer	struct resource* res_memory;	/* resource for mem range */
205d1d3a974SJulian Elischer	struct resource* res_irq;	/* resource for irq range */
206d1d3a974SJulian Elischer	struct resource* res_drq;	/* resource for dma channel */
20745b4f5afSJulian Elischer	device_t device;
208d1d3a974SJulian Elischer	dev_t dev;
209d1d3a974SJulian Elischer	void	*intr_cookie;
2104a3a6ee4SJulian Elischer	void	*vaddr;			/* Virtual address of mem resource */
21187e78fdfSJulian Elischer	char	buffer[BUFFERSIZE];	/* if we needed to buffer something */
2125e176f9aSJulian Elischer} ;
2135e176f9aSJulian Elischer
214e904636aSJulian Elischer/* Function prototypes (these should all be static) */
215e904636aSJulian Elischerstatic int ${1}_deallocate_resources(device_t device);
216e904636aSJulian Elischerstatic int ${1}_allocate_resources(device_t device);
2176715fca9SWarner Loshstatic int ${1}_attach(device_t device, struct ${1}_softc *scp);
2186715fca9SWarner Loshstatic int ${1}_detach(device_t device, struct ${1}_softc *scp);
219e904636aSJulian Elischer
220e904636aSJulian Elischerstatic d_open_t		${1}open;
221e904636aSJulian Elischerstatic d_close_t	${1}close;
222e904636aSJulian Elischerstatic d_read_t		${1}read;
223e904636aSJulian Elischerstatic d_write_t	${1}write;
224e904636aSJulian Elischerstatic d_ioctl_t	${1}ioctl;
225e904636aSJulian Elischerstatic d_mmap_t		${1}mmap;
226e904636aSJulian Elischerstatic d_poll_t		${1}poll;
227e904636aSJulian Elischerstatic	void		${1}intr(void *arg);
228e904636aSJulian Elischer 
229e904636aSJulian Elischer#define CDEV_MAJOR 20
230e904636aSJulian Elischerstatic struct cdevsw ${1}_cdevsw = {
231e904636aSJulian Elischer	/* open */	${1}open,
232e904636aSJulian Elischer	/* close */	${1}close,
233e904636aSJulian Elischer	/* read */	${1}read,
234e904636aSJulian Elischer	/* write */	${1}write,
235e904636aSJulian Elischer	/* ioctl */	${1}ioctl,
236e904636aSJulian Elischer	/* poll */	${1}poll,
237e904636aSJulian Elischer	/* mmap */	${1}mmap,
238e904636aSJulian Elischer	/* strategy */	nostrategy,	/* not a block type device */
239e904636aSJulian Elischer	/* name */	"${1}",
240e904636aSJulian Elischer	/* maj */	CDEV_MAJOR,
241e904636aSJulian Elischer	/* dump */	nodump,		/* not a block type device */
242e904636aSJulian Elischer	/* psize */	nopsize,	/* not a block type device */
243e904636aSJulian Elischer	/* flags */	0,
244e904636aSJulian Elischer	/* bmaj */	-1
245e904636aSJulian Elischer};
246e904636aSJulian Elischer
2477dd17df7SJulian Elischerstatic devclass_t ${1}_devclass;
2487dd17df7SJulian Elischer 
2496715fca9SWarner Losh/*
2506715fca9SWarner Losh *****************************************
251e904636aSJulian Elischer * ISA Attachment structures and functions
2526715fca9SWarner Losh *****************************************
2536715fca9SWarner Losh */
254e904636aSJulian Elischerstatic void ${1}_isa_identify (driver_t *, device_t);
255e904636aSJulian Elischerstatic int ${1}_isa_probe (device_t);
256e904636aSJulian Elischerstatic int ${1}_isa_attach (device_t);
257e904636aSJulian Elischerstatic int ${1}_isa_detach (device_t);
2585e176f9aSJulian Elischer
25945b4f5afSJulian Elischerstatic struct isa_pnp_id ${1}_ids[] = {
26045b4f5afSJulian Elischer	{0x12345678,	"ABCco Widget"},
26145b4f5afSJulian Elischer	{0xfedcba98,	"shining moon Widget ripoff"},
2624a3a6ee4SJulian Elischer	{0,		NULL}
26345b4f5afSJulian Elischer};
26445b4f5afSJulian Elischer
26545b4f5afSJulian Elischerstatic device_method_t ${1}_methods[] = {
26687e78fdfSJulian Elischer	DEVMETHOD(device_identify,	${1}_isa_identify),
26745b4f5afSJulian Elischer	DEVMETHOD(device_probe,		${1}_isa_probe),
26845b4f5afSJulian Elischer	DEVMETHOD(device_attach,	${1}_isa_attach),
26945b4f5afSJulian Elischer	DEVMETHOD(device_detach,	${1}_isa_detach),
27045b4f5afSJulian Elischer	{ 0, 0 }
27145b4f5afSJulian Elischer};
27245b4f5afSJulian Elischer
27345b4f5afSJulian Elischerstatic driver_t ${1}_isa_driver = {
27445b4f5afSJulian Elischer	"${1}",
27545b4f5afSJulian Elischer	${1}_methods,
27645b4f5afSJulian Elischer	sizeof (struct ${1}_softc)
27745b4f5afSJulian Elischer};
27845b4f5afSJulian Elischer
279e904636aSJulian Elischer
28045b4f5afSJulian ElischerDRIVER_MODULE(${1}, isa, ${1}_isa_driver, ${1}_devclass, 0, 0);
28145b4f5afSJulian Elischer
28287e78fdfSJulian Elischer/*
28387e78fdfSJulian Elischer * Here list some port addresses we might expect our widget to appear at:
2846715fca9SWarner Losh * This list should only be used for cards that have some non-destructive
2856715fca9SWarner Losh * (to other cards) way of probing these address.  Otherwise the driver
2866715fca9SWarner Losh * should not go looking for instances of itself, but instead rely on
2876715fca9SWarner Losh * the hints file.  Strange failures for people with other cards might
2886715fca9SWarner Losh * result.
28987e78fdfSJulian Elischer */
29087e78fdfSJulian Elischerstatic struct localhints {
29187e78fdfSJulian Elischer	int ioport;
29287e78fdfSJulian Elischer	int irq;
29387e78fdfSJulian Elischer	int drq;
29487e78fdfSJulian Elischer	int mem;
29587e78fdfSJulian Elischer} res[] = {
29687e78fdfSJulian Elischer	{ 0x210, 11, 2, 0xcd000},
29787e78fdfSJulian Elischer	{ 0x310, 12, 3, 0xdd000},
29887e78fdfSJulian Elischer	{ 0x320, 9, 6, 0xd4000},
29987e78fdfSJulian Elischer	{0,0,0,0}
30087e78fdfSJulian Elischer};
30145b4f5afSJulian Elischer
30211027719SBrian Somers#define MAXHINTS 10 /* just an arbitrary safety limit */
30387e78fdfSJulian Elischer/*
3044a3a6ee4SJulian Elischer * Called once when the driver is somehow connected with the bus,
3054a3a6ee4SJulian Elischer * (Either linked in and the bus is started, or loaded as a module).
3064a3a6ee4SJulian Elischer *
3074a3a6ee4SJulian Elischer * The aim of this routine in an ISA driver is to add child entries to
3084a3a6ee4SJulian Elischer * the parent bus so that it looks as if the devices were detected by
30911027719SBrian Somers * some pnp-like method, or at least mentioned in the hints.
3104a3a6ee4SJulian Elischer *
3114a3a6ee4SJulian Elischer * For NON-PNP "dumb" devices:
31287e78fdfSJulian Elischer * Add entries into the bus's list of likely devices, so that
31387e78fdfSJulian Elischer * our 'probe routine' will be called for them.
31487e78fdfSJulian Elischer * This is similar to what the 'hints' code achieves, except this is
31587e78fdfSJulian Elischer * loadable with the driver.
3164a3a6ee4SJulian Elischer * In the 'dumb' case we end up with more children than needed but
3174a3a6ee4SJulian Elischer * some (or all) of them will fail probe() and only waste a little memory.
3184a3a6ee4SJulian Elischer *
3194a3a6ee4SJulian Elischer * For NON-PNP "Smart" devices:
3204a3a6ee4SJulian Elischer * If the device has a NON-PNP way of being detected and setting/sensing
3214a3a6ee4SJulian Elischer * the card, then do that here and add a child for each set of
3224a3a6ee4SJulian Elischer * hardware found. 
3234a3a6ee4SJulian Elischer *
3244a3a6ee4SJulian Elischer * For PNP devices:
3254a3a6ee4SJulian Elischer * If the device is always PNP capable then this function can be removed.
3266715fca9SWarner Losh * The ISA PNP system will have automatically added it to the system and
3276715fca9SWarner Losh * so your identify routine needn't do anything.
3284a3a6ee4SJulian Elischer *
32911027719SBrian Somers * If the device is mentioned in the 'hints' file then this
33011027719SBrian Somers * function can be removed. All devices mentioned in the hints
3314a3a6ee4SJulian Elischer * file get added as children for probing, whether or not the
3324a3a6ee4SJulian Elischer * driver is linked in. So even as a module it MAY still be there.
3334a3a6ee4SJulian Elischer * See isa/isahint.c for hints being added in.
33487e78fdfSJulian Elischer */
33587e78fdfSJulian Elischerstatic void
33687e78fdfSJulian Elischer${1}_isa_identify (driver_t *driver, device_t parent)
33787e78fdfSJulian Elischer{
33887e78fdfSJulian Elischer	u_int32_t	irq=0;
33987e78fdfSJulian Elischer	u_int32_t	ioport;
34087e78fdfSJulian Elischer	device_t	child;
34187e78fdfSJulian Elischer	int i;
34287e78fdfSJulian Elischer
34387e78fdfSJulian Elischer
34487e78fdfSJulian Elischer	/*
34587e78fdfSJulian Elischer	 * If we've already got ${UPPER} attached somehow, don't try again.
3464a3a6ee4SJulian Elischer	 * Maybe it was in the hints file. or it was loaded before.
34787e78fdfSJulian Elischer	 */
34887e78fdfSJulian Elischer	if (device_find_child(parent, "${1}", 0)) {
34987e78fdfSJulian Elischer		printf("${UPPER}: already attached\n");
35087e78fdfSJulian Elischer		return;
35187e78fdfSJulian Elischer	}
35287e78fdfSJulian Elischer/* XXX look at dev/acpica/acpi_isa.c for use of ISA_ADD_CONFIG() macro */
35387e78fdfSJulian Elischer/* XXX What is ISA_SET_CONFIG_CALLBACK(parent, child, pnpbios_set_config, 0) ?*/
35487e78fdfSJulian Elischer	for (i = 0; i < MAXHINTS; i++) {
35599fcf983SJulian Elischer
35699fcf983SJulian Elischer		ioport = res[i].ioport;
35799fcf983SJulian Elischer		irq = res[i].irq;
35899fcf983SJulian Elischer		if ((ioport == 0) &&  (irq == 0)) {
35987e78fdfSJulian Elischer			return; /* we've added all our local hints */
36087e78fdfSJulian Elischer		}
36187e78fdfSJulian Elischer
36287e78fdfSJulian Elischer		child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "${1}", -1);
36387e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_IOPORT,	0, ioport, NUMPORTS);
36487e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_IRQ,	0, irq, 1);
36587e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_DRQ,	0, res[i].drq, 1);
36687e78fdfSJulian Elischer		bus_set_resource(child, SYS_RES_MEMORY,	0, res[i].mem, MEMSIZE);
36787e78fdfSJulian Elischer
3684a3a6ee4SJulian Elischer
36987e78fdfSJulian Elischer#if 0
37087e78fdfSJulian Elischer		/*
37187e78fdfSJulian Elischer		 * If we wanted to pretend PNP found it
37287e78fdfSJulian Elischer		 * we could do this, and put matching entries
37387e78fdfSJulian Elischer		 * in the PNP table, but I think it's probably too hacky.
37487e78fdfSJulian Elischer		 * As you see, some people have done it though.
3754a3a6ee4SJulian Elischer		 * Basically EISA (remember that?) would do this I think
37687e78fdfSJulian Elischer		 */
37787e78fdfSJulian Elischer		isa_set_vendorid(child, PNP_EISAID("ESS1888"));
37887e78fdfSJulian Elischer		isa_set_logicalid(child, PNP_EISAID("ESS1888"));
37987e78fdfSJulian Elischer#endif
38087e78fdfSJulian Elischer	}
3814a3a6ee4SJulian Elischer#if 0
3826715fca9SWarner Losh	/*
3836715fca9SWarner Losh	 * Do some smart probing (e.g. like the lnc driver)
3846715fca9SWarner Losh	 * and add a child for each one found.
3856715fca9SWarner Losh	 */
3864a3a6ee4SJulian Elischer#endif
38787e78fdfSJulian Elischer
38887e78fdfSJulian Elischer	return;
38987e78fdfSJulian Elischer}
39045b4f5afSJulian Elischer/*
39145b4f5afSJulian Elischer * The ISA code calls this for each device it knows about,
39245b4f5afSJulian Elischer * whether via the PNP code or via the hints etc.
3934a3a6ee4SJulian Elischer * If the device nas no PNP capabilities, remove all the 
3944a3a6ee4SJulian Elischer * PNP entries, but keep the call to ISA_PNP_PROBE()
3954a3a6ee4SJulian Elischer * As it will guard against accidentally recognising
3964a3a6ee4SJulian Elischer * foreign hardware. This is because we will be called to check against
3974a3a6ee4SJulian Elischer * ALL PNP hardware.
39845b4f5afSJulian Elischer */
3995e176f9aSJulian Elischerstatic int
40045b4f5afSJulian Elischer${1}_isa_probe (device_t device)
4015e176f9aSJulian Elischer{
40245b4f5afSJulian Elischer	int error;
40387e78fdfSJulian Elischer	device_t parent = device_get_parent(device);
4046715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
40587e78fdfSJulian Elischer	u_long	port_start, port_count;
40687e78fdfSJulian Elischer
40745b4f5afSJulian Elischer
40845b4f5afSJulian Elischer	bzero(scp, sizeof(*scp));
40945b4f5afSJulian Elischer	scp->device = device;
4105e176f9aSJulian Elischer
4115e176f9aSJulian Elischer	/*
41287e78fdfSJulian Elischer	 * Check this device for a PNP match in our table..
41345b4f5afSJulian Elischer	 * There are several possible outcomes.
41487e78fdfSJulian Elischer	 * error == 0		We match a PNP ).
41511027719SBrian Somers	 * error == ENXIO,	It is a PNP device but not in our table.
41611027719SBrian Somers	 * error == ENOENT,	It is not a PNP device.. try heuristic probes.
41745b4f5afSJulian Elischer	 *    -- logic from if_ed_isa.c, added info from isa/isa_if.m:
41899fcf983SJulian Elischer	 *
41999fcf983SJulian Elischer	 * If we had a list of devices that we could handle really well,
42099fcf983SJulian Elischer	 * and a list which we could handle only basic functions, then
42199fcf983SJulian Elischer	 * we would call this twice, once for each list,
42299fcf983SJulian Elischer	 * and return a value of '-2' or something if we could
42399fcf983SJulian Elischer	 * only handle basic functions. This would allow a specific
42499fcf983SJulian Elischer	 * Widgetplus driver to make a better offer if it knows how to
42599fcf983SJulian Elischer	 * do all the extended functions. (see non-pnp part for more info)
4265e176f9aSJulian Elischer	 */
42787e78fdfSJulian Elischer	error = ISA_PNP_PROBE(parent, device, ${1}_ids);
42845b4f5afSJulian Elischer	switch (error) {
42945b4f5afSJulian Elischer	case 0:
43045b4f5afSJulian Elischer		/*
43145b4f5afSJulian Elischer		 * We found a PNP device.
43245ddd9afSJulian Elischer		 * Do nothing, as it's all done in attach()
43345b4f5afSJulian Elischer		 */
43445ddd9afSJulian Elischer		break;
43545b4f5afSJulian Elischer	case ENOENT:
43645b4f5afSJulian Elischer		/*
43745b4f5afSJulian Elischer		 * Well it didn't show up in the PNP tables
43845b4f5afSJulian Elischer		 * so look directly at known ports (if we have any)
43945b4f5afSJulian Elischer		 * in case we are looking for an old pre-PNP card.
44045b4f5afSJulian Elischer		 * 
44187e78fdfSJulian Elischer		 * Hopefully the  'identify' routine will have picked these
44299fcf983SJulian Elischer		 * up for us first if they use some proprietary detection
44399fcf983SJulian Elischer		 * method.
44487e78fdfSJulian Elischer		 *
44599fcf983SJulian Elischer		 * The ports, irqs etc should come from a 'hints' section
44645b4f5afSJulian Elischer		 * which is read in by code in isa/isahint.c
4474a3a6ee4SJulian Elischer		 * and kern/subr_bus.c to create resource entries,
4484a3a6ee4SJulian Elischer		 * or have been added by the 'identify routine above.
44911027719SBrian Somers		 * Note that HINTS based resource requests have NO
45099fcf983SJulian Elischer		 * SIZE for the memory or ports requests  (just a base)
45199fcf983SJulian Elischer		 * so we may need to 'correct' this before we
45299fcf983SJulian Elischer		 * do any probing.
45399fcf983SJulian Elischer		 */
45499fcf983SJulian Elischer		/*
45599fcf983SJulian Elischer		 * find out the values of any resources we
45699fcf983SJulian Elischer		 * need for our dumb probe. Also check we have enough ports 
45799fcf983SJulian Elischer		 * in the request. (could be hints based). 
45899fcf983SJulian Elischer		 * Should probably do the same for memory regions too.
45999fcf983SJulian Elischer		 */
46099fcf983SJulian Elischer		error = bus_get_resource(device, SYS_RES_IOPORT, 0,
46199fcf983SJulian Elischer			&port_start, &port_count);
46299fcf983SJulian Elischer		if (port_count != NUMPORTS) {
46399fcf983SJulian Elischer			bus_set_resource(device, SYS_RES_IOPORT, 0,
46499fcf983SJulian Elischer			port_start, NUMPORTS);
46599fcf983SJulian Elischer		}
46699fcf983SJulian Elischer
46799fcf983SJulian Elischer		/*
46899fcf983SJulian Elischer		 * Make a temporary resource reservation.
4694a3a6ee4SJulian Elischer		 * If we can't get the resources we need then
4704a3a6ee4SJulian Elischer		 * we need to abort.  Possibly this indicates
47199fcf983SJulian Elischer		 * the resources were used by another device
47299fcf983SJulian Elischer		 * in which case the probe would have failed anyhow.
47345b4f5afSJulian Elischer		 */
4744a3a6ee4SJulian Elischer		if ((error = (${1}_allocate_resources(device)))) {
4754a3a6ee4SJulian Elischer			error = ENXIO;
4764a3a6ee4SJulian Elischer			goto errexit;
47787e78fdfSJulian Elischer		}
47887e78fdfSJulian Elischer
4794a3a6ee4SJulian Elischer		/* dummy heuristic type probe */
4804a3a6ee4SJulian Elischer		if ( inb(port_start) != EXPECTED_VALUE) {
4815e176f9aSJulian Elischer			/* 
48287e78fdfSJulian Elischer			 * It isn't what we hoped, so quit looking for it.
4835e176f9aSJulian Elischer			 */
48445ddd9afSJulian Elischer			error = ENXIO;
48545ddd9afSJulian Elischer		} else {
4864a3a6ee4SJulian Elischer			u_long membase = bus_get_resource_start(device,
4874a3a6ee4SJulian Elischer					SYS_RES_MEMORY, 0 /*rid*/);
4884a3a6ee4SJulian Elischer			u_long memsize;
4894a3a6ee4SJulian Elischer			/*
4904a3a6ee4SJulian Elischer			 * If we discover in some way that the device has
4914a3a6ee4SJulian Elischer			 * XXX bytes of memory window, we can override
4924a3a6ee4SJulian Elischer			 * or set the memory size in the child resource list.
4934a3a6ee4SJulian Elischer			 */
4944a3a6ee4SJulian Elischer			memsize = inb(port_start + 1) * 1024; /* for example */
4954a3a6ee4SJulian Elischer			error = bus_set_resource(device, SYS_RES_MEMORY,
4964a3a6ee4SJulian Elischer				/*rid*/0, membase, memsize);
49745ddd9afSJulian Elischer			/*
49899fcf983SJulian Elischer			 * We found one, return non-positive numbers..
49999fcf983SJulian Elischer			 * Return -N if we cant handle it, but not well.
5004a3a6ee4SJulian Elischer			 * Return -2 if we would LIKE the device
5014a3a6ee4SJulian Elischer			 * Return -1 if we want it a lot
5024a3a6ee4SJulian Elischer			 * Return 0 if we MUST get the device
5034a3a6ee4SJulian Elischer			 * This allows drivers to 'bid' for a device.
50445ddd9afSJulian Elischer			 */
5054a3a6ee4SJulian Elischer			device_set_desc(device, "ACME Widget model 1234");
50699fcf983SJulian Elischer			error = -1; /* we want it but someone else
50799fcf983SJulian Elischer					may be even better */
50845ddd9afSJulian Elischer		}
5094a3a6ee4SJulian Elischer		/*
5104a3a6ee4SJulian Elischer		 * Unreserve the resources for now because
5114a3a6ee4SJulian Elischer		 * another driver may bid for device too.
51211027719SBrian Somers		 * If we lose the bid, but still hold the resources, we will
51311027719SBrian Somers		 * effectively have disabled the other driver from getting them
5144a3a6ee4SJulian Elischer		 * which will result in neither driver getting the device.
5154a3a6ee4SJulian Elischer		 * We will ask for them again in attach if we win.
5164a3a6ee4SJulian Elischer		 */
5174a3a6ee4SJulian Elischer		${1}_deallocate_resources(device);
51845b4f5afSJulian Elischer		break;
51945b4f5afSJulian Elischer	case  ENXIO:
52011027719SBrian Somers		/* It was PNP but not ours, leave immediately */
52145b4f5afSJulian Elischer	default:
52245b4f5afSJulian Elischer		error = ENXIO;
52345b4f5afSJulian Elischer	}
5244a3a6ee4SJulian Elischererrexit:
52545b4f5afSJulian Elischer	return (error);
5265e176f9aSJulian Elischer}
5275e176f9aSJulian Elischer
5285e176f9aSJulian Elischer/*
5294a3a6ee4SJulian Elischer * Called if the probe succeeded and our bid won the device.
5305e176f9aSJulian Elischer * We can be destructive here as we know we have the device.
5314a3a6ee4SJulian Elischer * This is the first place we can be sure we have a softc structure.
532e904636aSJulian Elischer * You would do ISA specific attach things here, but generically there aren't
533e904636aSJulian Elischer * any (yey new-bus!).
5345e176f9aSJulian Elischer */
5355e176f9aSJulian Elischerstatic int
53645b4f5afSJulian Elischer${1}_isa_attach (device_t device)
5375e176f9aSJulian Elischer{
538e904636aSJulian Elischer        int	error;
5396715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
540e904636aSJulian Elischer
541e904636aSJulian Elischer        error =  ${1}_attach(device, scp);
542e904636aSJulian Elischer        if (error) {
543e904636aSJulian Elischer                ${1}_isa_detach(device);
544e904636aSJulian Elischer        }
545e904636aSJulian Elischer        return (error);
546e904636aSJulian Elischer
547e904636aSJulian Elischer}
548e904636aSJulian Elischer
549e904636aSJulian Elischer/* 
550e904636aSJulian Elischer * detach the driver (e.g. module unload)
551e904636aSJulian Elischer * call the bus independent version
552e904636aSJulian Elischer * and undo anything we did in the ISA attach routine.
553e904636aSJulian Elischer */
554e904636aSJulian Elischerstatic int
555e904636aSJulian Elischer${1}_isa_detach (device_t device)
556e904636aSJulian Elischer{
557e904636aSJulian Elischer        int	error;
5586715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
559e904636aSJulian Elischer
560e904636aSJulian Elischer        error =  ${1}_detach(device, scp);
561e904636aSJulian Elischer        return (error);
562e904636aSJulian Elischer}
563e904636aSJulian Elischer
5646715fca9SWarner Losh/*
5656715fca9SWarner Losh ***************************************
5666715fca9SWarner Losh * PCI Attachment structures and code
5676715fca9SWarner Losh ***************************************
5686715fca9SWarner Losh */
569e904636aSJulian Elischer
570e904636aSJulian Elischerstatic int	${1}_pci_probe	__P((device_t));
571e904636aSJulian Elischerstatic int	${1}_pci_attach	__P((device_t));
572e904636aSJulian Elischerstatic int	${1}_pci_detach	__P((device_t));
573e904636aSJulian Elischer
574e904636aSJulian Elischerstatic device_method_t ${1}_pci_methods[] = {
575e904636aSJulian Elischer	/* Device interface */
576e904636aSJulian Elischer	DEVMETHOD(device_probe,		${1}_pci_probe),
577e904636aSJulian Elischer	DEVMETHOD(device_attach,	${1}_pci_attach),
578e904636aSJulian Elischer	DEVMETHOD(device_detach,	${1}_pci_detach),
579e904636aSJulian Elischer	{ 0, 0 }
580e904636aSJulian Elischer};
581e904636aSJulian Elischer
582e904636aSJulian Elischerstatic driver_t ${1}_pci_driver = {
583e904636aSJulian Elischer	"${1}",
584e904636aSJulian Elischer	${1}_pci_methods,
585e904636aSJulian Elischer	sizeof(struct ${1}_softc),
586e904636aSJulian Elischer};
587e904636aSJulian Elischer
588e904636aSJulian Elischer
5897dd17df7SJulian ElischerDRIVER_MODULE(${1}, pci, ${1}_pci_driver, ${1}_devclass, 0, 0);
5906715fca9SWarner Losh/*
5916715fca9SWarner Losh * Cardbus is a pci bus plus extra, so use the pci driver unless special
5926715fca9SWarner Losh * things need to be done only in the cardbus case.
5936715fca9SWarner Losh */
5946715fca9SWarner LoshDRIVER_MODULE(${1}, cardbus, ${1}_pci_driver, ${1}_devclass, 0, 0);
595e904636aSJulian Elischer
596e904636aSJulian Elischerstatic struct _pcsid
597e904636aSJulian Elischer{
598e904636aSJulian Elischer	u_int32_t	type;
599e904636aSJulian Elischer	const char	*desc;
600e904636aSJulian Elischer} pci_ids[] = {
601e904636aSJulian Elischer	{ 0x1234abcd,	"ACME PCI Widgetplus"	},
6026715fca9SWarner Losh	{ 0x1243fedc,	"Happy moon brand RIPOFFplus"	},
603e904636aSJulian Elischer	{ 0x00000000,	NULL					}
604e904636aSJulian Elischer};
605e904636aSJulian Elischer
60699fcf983SJulian Elischer/*
60711027719SBrian Somers * See if this card is specifically mentioned in our list of known devices.
60899fcf983SJulian Elischer * Theoretically we might also put in a weak bid for some devices that
6096715fca9SWarner Losh * report themselves to be some generic type of device if we can handle
61099fcf983SJulian Elischer * that generic type. (other PCI_XXX calls give that info).
61199fcf983SJulian Elischer * This would allow a specific driver to over-ride us.
61299fcf983SJulian Elischer *
61399fcf983SJulian Elischer * See the comments in the ISA section regarding returning non-positive
61499fcf983SJulian Elischer * values from probe routines.
61599fcf983SJulian Elischer */
616e904636aSJulian Elischerstatic int
617e904636aSJulian Elischer${1}_pci_probe (device_t device)
618e904636aSJulian Elischer{
619e904636aSJulian Elischer	u_int32_t	type = pci_get_devid(device);
620e904636aSJulian Elischer	struct _pcsid	*ep =pci_ids;
621e904636aSJulian Elischer
622e904636aSJulian Elischer	while (ep->type && ep->type != type)
623e904636aSJulian Elischer		++ep;
624e904636aSJulian Elischer	if (ep->desc) {
625e904636aSJulian Elischer		device_set_desc(device, ep->desc);
6266715fca9SWarner Losh		return 0; /* If there might be a better driver, return -2 */
627e904636aSJulian Elischer	} else {
628e904636aSJulian Elischer		return ENXIO;
629e904636aSJulian Elischer	}
630e904636aSJulian Elischer}
631e904636aSJulian Elischer
632e904636aSJulian Elischerstatic int
633e904636aSJulian Elischer${1}_pci_attach(device_t device)
634e904636aSJulian Elischer{
635e904636aSJulian Elischer        int	error;
6366715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
637e904636aSJulian Elischer
638e904636aSJulian Elischer        error =  ${1}_attach(device, scp);
639e904636aSJulian Elischer        if (error) {
640e904636aSJulian Elischer                ${1}_pci_detach(device);
641e904636aSJulian Elischer        }
642e904636aSJulian Elischer        return (error);
643e904636aSJulian Elischer}
644e904636aSJulian Elischer
645e904636aSJulian Elischerstatic int
646e904636aSJulian Elischer${1}_pci_detach (device_t device)
647e904636aSJulian Elischer{
648e904636aSJulian Elischer        int	error;
6496715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
650e904636aSJulian Elischer
651e904636aSJulian Elischer        error =  ${1}_detach(device, scp);
652e904636aSJulian Elischer        return (error);
653e904636aSJulian Elischer}
654e904636aSJulian Elischer
655e904636aSJulian Elischer
6566715fca9SWarner Losh/*
6576715fca9SWarner Losh ****************************************
65811027719SBrian Somers *  Common Attachment sub-functions
6596715fca9SWarner Losh ****************************************
6606715fca9SWarner Losh */
661e904636aSJulian Elischerstatic int
6626715fca9SWarner Losh${1}_attach(device_t device, struct ${1}_softc * scp)
663e904636aSJulian Elischer{
664d1d3a974SJulian Elischer	device_t parent	= device_get_parent(device);
6656715fca9SWarner Losh	int	unit	= device_get_unit(device);
6665e176f9aSJulian Elischer
66745ddd9afSJulian Elischer	scp->dev = make_dev(&${1}_cdevsw, 0,
66845ddd9afSJulian Elischer			UID_ROOT, GID_OPERATOR, 0600, "${1}%d", unit);
669e904636aSJulian Elischer	scp->dev->si_drv1 = scp;
67045ddd9afSJulian Elischer
67145ddd9afSJulian Elischer	if (${1}_allocate_resources(device)) {
67245ddd9afSJulian Elischer		goto errexit;
67345ddd9afSJulian Elischer	}
67445ddd9afSJulian Elischer
6754a3a6ee4SJulian Elischer	scp->bt = rman_get_bustag(scp->res_ioport);
6764a3a6ee4SJulian Elischer	scp->bh = rman_get_bushandle(scp->res_ioport);
67745ddd9afSJulian Elischer
67845ddd9afSJulian Elischer	/* register the interrupt handler */
6794a3a6ee4SJulian Elischer	/*
6804a3a6ee4SJulian Elischer	 * The type should be one of:
6814a3a6ee4SJulian Elischer	 *	INTR_TYPE_TTY
6824a3a6ee4SJulian Elischer	 *	INTR_TYPE_BIO
6834a3a6ee4SJulian Elischer	 *	INTR_TYPE_CAM
6844a3a6ee4SJulian Elischer	 *	INTR_TYPE_NET
6854a3a6ee4SJulian Elischer	 *	INTR_TYPE_MISC
6866715fca9SWarner Losh	 * This will probably change with SMPng.  INTR_TYPE_FAST may be
68711027719SBrian Somers	 * OR'd into this type to mark the interrupt fast.  However, fast
6886715fca9SWarner Losh	 * interrupts cannot be shared at all so special precautions are
68911027719SBrian Somers	 * necessary when coding fast interrupt routines.
6904a3a6ee4SJulian Elischer	 */
691d1d3a974SJulian Elischer	if (scp->res_irq) {
692d1d3a974SJulian Elischer		/* default to the tty mask for registration */  /* XXX */
693d1d3a974SJulian Elischer		if (BUS_SETUP_INTR(parent, device, scp->res_irq, INTR_TYPE_TTY,
69445ddd9afSJulian Elischer				${1}intr, scp, &scp->intr_cookie) == 0) {
69511027719SBrian Somers			/* do something if successful */
696e904636aSJulian Elischer		} else {
697e904636aSJulian Elischer			goto errexit;
698d1d3a974SJulian Elischer		}
699d1d3a974SJulian Elischer	}
7004a3a6ee4SJulian Elischer
7014a3a6ee4SJulian Elischer	/*
7024a3a6ee4SJulian Elischer	 * If we want to access the memory we will need
7034a3a6ee4SJulian Elischer	 * to know where it was mapped.
7046715fca9SWarner Losh	 *
7056715fca9SWarner Losh	 * Use of this function is discouraged, however.  You should
7066715fca9SWarner Losh	 * be accessing the device with the bus_space API if at all
7076715fca9SWarner Losh	 * possible.
7084a3a6ee4SJulian Elischer	 */
7094a3a6ee4SJulian Elischer	scp->vaddr = rman_get_virtual(scp->res_memory);
71045b4f5afSJulian Elischer	return 0;
71145ddd9afSJulian Elischer
71245ddd9afSJulian Elischererrexit:
71345ddd9afSJulian Elischer	/*
71445ddd9afSJulian Elischer	 * Undo anything we may have done
71545ddd9afSJulian Elischer	 */
716e904636aSJulian Elischer	${1}_detach(device, scp);
71745ddd9afSJulian Elischer	return (ENXIO);
71845b4f5afSJulian Elischer}
71964b2faf8SBruce Evans
72045b4f5afSJulian Elischerstatic int
7216715fca9SWarner Losh${1}_detach(device_t device, struct ${1}_softc *scp)
72245b4f5afSJulian Elischer{
723d1d3a974SJulian Elischer	device_t parent = device_get_parent(device);
72445b4f5afSJulian Elischer
72545ddd9afSJulian Elischer	/*
72645ddd9afSJulian Elischer	 * At this point stick a strong piece of wood into the device
72745ddd9afSJulian Elischer	 * to make sure it is stopped safely. The alternative is to 
72845ddd9afSJulian Elischer	 * simply REFUSE to detach if it's busy. What you do depends on 
72945ddd9afSJulian Elischer	 * your specific situation.
7306715fca9SWarner Losh	 *
7316715fca9SWarner Losh	 * Sometimes the parent bus will detach you anyway, even if you
7326715fca9SWarner Losh	 * are busy.  You must cope with that possibility.  Your hardware
7336715fca9SWarner Losh	 * might even already be gone in the case of cardbus or pccard
7346715fca9SWarner Losh	 * devices.
73545ddd9afSJulian Elischer	 */
73645ddd9afSJulian Elischer	/* ZAP some register */
73745ddd9afSJulian Elischer
73845ddd9afSJulian Elischer	/*
73945ddd9afSJulian Elischer	 * Take our interrupt handler out of the list of handlers
74045ddd9afSJulian Elischer	 * that can handle this irq.
74145ddd9afSJulian Elischer	 */
74245ddd9afSJulian Elischer	if (scp->intr_cookie != NULL) {
743d1d3a974SJulian Elischer		if (BUS_TEARDOWN_INTR(parent, device,
744d1d3a974SJulian Elischer			scp->res_irq, scp->intr_cookie) != 0) {
745d1d3a974SJulian Elischer				printf("intr teardown failed.. continuing\n");
746d1d3a974SJulian Elischer		}
74745ddd9afSJulian Elischer		scp->intr_cookie = NULL;
74845ddd9afSJulian Elischer	}
74945ddd9afSJulian Elischer
75045ddd9afSJulian Elischer	/*
75145ddd9afSJulian Elischer	 * deallocate any system resources we may have
75245ddd9afSJulian Elischer	 * allocated on behalf of this driver.
75345ddd9afSJulian Elischer	 */
7544a3a6ee4SJulian Elischer	scp->vaddr = NULL;
75545ddd9afSJulian Elischer	return ${1}_deallocate_resources(device);
75645ddd9afSJulian Elischer}
75745ddd9afSJulian Elischer
75845ddd9afSJulian Elischerstatic int
75945ddd9afSJulian Elischer${1}_allocate_resources(device_t device)
76045ddd9afSJulian Elischer{
76145ddd9afSJulian Elischer	int error;
7626715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
76345ddd9afSJulian Elischer	int	size = 16; /* SIZE of port range used */
76445ddd9afSJulian Elischer
76545ddd9afSJulian Elischer	scp->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT,
76645ddd9afSJulian Elischer			&scp->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE);
76745ddd9afSJulian Elischer	if (scp->res_ioport == NULL) {
76845ddd9afSJulian Elischer		goto errexit;
76945ddd9afSJulian Elischer	}
77045ddd9afSJulian Elischer
77145ddd9afSJulian Elischer	scp->res_irq = bus_alloc_resource(device, SYS_RES_IRQ,
7724a3a6ee4SJulian Elischer			&scp->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE|RF_ACTIVE);
77345ddd9afSJulian Elischer	if (scp->res_irq == NULL) {
77445ddd9afSJulian Elischer		goto errexit;
77545ddd9afSJulian Elischer	}
77645ddd9afSJulian Elischer
77745ddd9afSJulian Elischer	scp->res_drq = bus_alloc_resource(device, SYS_RES_DRQ,
77845ddd9afSJulian Elischer			&scp->rid_drq, 0ul, ~0ul, 1, RF_ACTIVE);
77945ddd9afSJulian Elischer	if (scp->res_drq == NULL) {
78045ddd9afSJulian Elischer		goto errexit;
78145ddd9afSJulian Elischer	}
78245ddd9afSJulian Elischer
78387e78fdfSJulian Elischer	scp->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
78445ddd9afSJulian Elischer			&scp->rid_memory, 0ul, ~0ul, MSIZE, RF_ACTIVE);
78545ddd9afSJulian Elischer	if (scp->res_memory == NULL) {
78645ddd9afSJulian Elischer		goto errexit;
78745ddd9afSJulian Elischer	}
78845ddd9afSJulian Elischer	return (0);
78945ddd9afSJulian Elischer
79045ddd9afSJulian Elischererrexit:
79145ddd9afSJulian Elischer	error = ENXIO;
79245ddd9afSJulian Elischer	/* cleanup anything we may have assigned. */
79345ddd9afSJulian Elischer	${1}_deallocate_resources(device);
79445ddd9afSJulian Elischer	return (ENXIO); /* for want of a better idea */
79545ddd9afSJulian Elischer}
79645ddd9afSJulian Elischer
79745ddd9afSJulian Elischerstatic int
79845ddd9afSJulian Elischer${1}_deallocate_resources(device_t device)
79945ddd9afSJulian Elischer{
8006715fca9SWarner Losh	struct ${1}_softc *scp = DEVICE2SOFTC(device);
80145ddd9afSJulian Elischer
80245ddd9afSJulian Elischer	if (scp->res_irq != 0) {
803d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_IRQ,
804d1d3a974SJulian Elischer			scp->rid_irq, scp->res_irq);
805d1d3a974SJulian Elischer		bus_release_resource(device, SYS_RES_IRQ,
806d1d3a974SJulian Elischer			scp->rid_irq, scp->res_irq);
807d1d3a974SJulian Elischer		scp->res_irq = 0;
808d1d3a974SJulian Elischer	}
809d1d3a974SJulian Elischer	if (scp->res_ioport != 0) {
810d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_IOPORT,
811d1d3a974SJulian Elischer			scp->rid_ioport, scp->res_ioport);
81245b4f5afSJulian Elischer		bus_release_resource(device, SYS_RES_IOPORT,
813d1d3a974SJulian Elischer			scp->rid_ioport, scp->res_ioport);
814d1d3a974SJulian Elischer		scp->res_ioport = 0;
815d1d3a974SJulian Elischer	}
81699fcf983SJulian Elischer	if (scp->res_memory != 0) {
817d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_MEMORY,
818d1d3a974SJulian Elischer			scp->rid_memory, scp->res_memory);
819d1d3a974SJulian Elischer		bus_release_resource(device, SYS_RES_MEMORY,
820d1d3a974SJulian Elischer			scp->rid_memory, scp->res_memory);
82199fcf983SJulian Elischer		scp->res_memory = 0;
822d1d3a974SJulian Elischer	}
823d1d3a974SJulian Elischer	if (scp->res_drq != 0) {
824d1d3a974SJulian Elischer		bus_deactivate_resource(device, SYS_RES_DRQ,
825d1d3a974SJulian Elischer			scp->rid_drq, scp->res_drq);
826d1d3a974SJulian Elischer		bus_release_resource(device, SYS_RES_DRQ,
827d1d3a974SJulian Elischer			scp->rid_drq, scp->res_drq);
828d1d3a974SJulian Elischer		scp->res_drq = 0;
829d1d3a974SJulian Elischer	}
830d1d3a974SJulian Elischer	if (scp->dev) {
83145b4f5afSJulian Elischer		destroy_dev(scp->dev);
832d1d3a974SJulian Elischer	}
8335e176f9aSJulian Elischer	return (0);
8345e176f9aSJulian Elischer}
8355e176f9aSJulian Elischer
83664b2faf8SBruce Evansstatic void
83745b4f5afSJulian Elischer${1}intr(void *arg)
8385e176f9aSJulian Elischer{
8396715fca9SWarner Losh	struct ${1}_softc *scp = (struct ${1}_softc *) arg;
8405e176f9aSJulian Elischer
8415e176f9aSJulian Elischer	/* 
84211027719SBrian Somers	 * well we got an interrupt, now what?
8436715fca9SWarner Losh	 *
8446715fca9SWarner Losh	 * Make sure that the interrupt routine will always terminate,
8456715fca9SWarner Losh	 * even in the face of "bogus" data from the card.
8465e176f9aSJulian Elischer	 */
8475e176f9aSJulian Elischer	return;
8485e176f9aSJulian Elischer}
8495e176f9aSJulian Elischer
85045b4f5afSJulian Elischerstatic int
851853fbff5SAndrew R. Reiter${1}ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
8525e176f9aSJulian Elischer{
8536715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8545e176f9aSJulian Elischer
8555e176f9aSJulian Elischer	switch (cmd) {
8565e176f9aSJulian Elischer	case DHIOCRESET:
8575e176f9aSJulian Elischer		/* whatever resets it */
85887e78fdfSJulian Elischer#if 0
85945b4f5afSJulian Elischer		${UPPER}_OUTB(SOME_PORT, 0xff) ;
86087e78fdfSJulian Elischer#endif
8615e176f9aSJulian Elischer		break;
8625e176f9aSJulian Elischer	default:
8635e176f9aSJulian Elischer		return ENXIO;
8645e176f9aSJulian Elischer	}
8655e176f9aSJulian Elischer	return (0);
8665e176f9aSJulian Elischer}
8675e176f9aSJulian Elischer/*
8685e176f9aSJulian Elischer * You also need read, write, open, close routines.
8695e176f9aSJulian Elischer * This should get you started
8705e176f9aSJulian Elischer */
8715e176f9aSJulian Elischerstatic int
872853fbff5SAndrew R. Reiter${1}open(dev_t dev, int oflags, int devtype, struct thread *td)
8735e176f9aSJulian Elischer{
8746715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8755e176f9aSJulian Elischer
8765e176f9aSJulian Elischer	/* 
8775e176f9aSJulian Elischer	 * Do processing
8785e176f9aSJulian Elischer	 */
8795e176f9aSJulian Elischer	return (0);
8805e176f9aSJulian Elischer}
8815e176f9aSJulian Elischer
8825e176f9aSJulian Elischerstatic int
883853fbff5SAndrew R. Reiter${1}close(dev_t dev, int fflag, int devtype, struct thread *td)
8845e176f9aSJulian Elischer{
8856715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8865e176f9aSJulian Elischer
8875e176f9aSJulian Elischer	/* 
8885e176f9aSJulian Elischer	 * Do processing
8895e176f9aSJulian Elischer	 */
8905e176f9aSJulian Elischer	return (0);
8915e176f9aSJulian Elischer}
8925e176f9aSJulian Elischer
8935e176f9aSJulian Elischerstatic int
8945e176f9aSJulian Elischer${1}read(dev_t dev, struct uio *uio, int ioflag)
8955e176f9aSJulian Elischer{
8966715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
8975e176f9aSJulian Elischer	int	 toread;
8985e176f9aSJulian Elischer
8995e176f9aSJulian Elischer
9005e176f9aSJulian Elischer	/* 
9015e176f9aSJulian Elischer	 * Do processing
9025e176f9aSJulian Elischer	 * read from buffer
9035e176f9aSJulian Elischer	 */
9045e176f9aSJulian Elischer	toread = (min(uio->uio_resid, sizeof(scp->buffer)));
9055e176f9aSJulian Elischer	return(uiomove(scp->buffer, toread, uio));
9065e176f9aSJulian Elischer}
9075e176f9aSJulian Elischer
9085e176f9aSJulian Elischerstatic int
9095e176f9aSJulian Elischer${1}write(dev_t dev, struct uio *uio, int ioflag)
9105e176f9aSJulian Elischer{
9116715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
9125e176f9aSJulian Elischer	int	towrite;
9135e176f9aSJulian Elischer
9145e176f9aSJulian Elischer	/* 
9155e176f9aSJulian Elischer	 * Do processing
9165e176f9aSJulian Elischer	 * write to buffer
9175e176f9aSJulian Elischer	 */
9185e176f9aSJulian Elischer	towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
9195e176f9aSJulian Elischer	return(uiomove(scp->buffer, towrite, uio));
9205e176f9aSJulian Elischer}
9215e176f9aSJulian Elischer
9225e176f9aSJulian Elischerstatic int
92345b4f5afSJulian Elischer${1}mmap(dev_t dev, vm_offset_t offset, int nprot)
9245e176f9aSJulian Elischer{
9256715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
9265e176f9aSJulian Elischer
9275e176f9aSJulian Elischer	/* 
92887e78fdfSJulian Elischer	 * Given a byte offset into your device, return the PHYSICAL
92987e78fdfSJulian Elischer	 * page number that it would map to.
9305e176f9aSJulian Elischer	 */
9315e176f9aSJulian Elischer#if 0	/* if we had a frame buffer or whatever.. do this */
9325e176f9aSJulian Elischer	if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
9335e176f9aSJulian Elischer		return (-1);
9345e176f9aSJulian Elischer	}
9355e176f9aSJulian Elischer	return i386_btop((FRAMEBASE + offset));
9365e176f9aSJulian Elischer#else
9375e176f9aSJulian Elischer	return (-1);
9385e176f9aSJulian Elischer#endif
9395e176f9aSJulian Elischer}
9405e176f9aSJulian Elischer
9415e176f9aSJulian Elischerstatic int
942853fbff5SAndrew R. Reiter${1}poll(dev_t dev, int which, struct thread *td)
9435e176f9aSJulian Elischer{
9446715fca9SWarner Losh	struct ${1}_softc *scp = DEV2SOFTC(dev);
9455e176f9aSJulian Elischer
9465e176f9aSJulian Elischer	/* 
9475e176f9aSJulian Elischer	 * Do processing
9485e176f9aSJulian Elischer	 */
9495e176f9aSJulian Elischer	return (0); /* this is the wrong value I'm sure */
9505e176f9aSJulian Elischer}
9515e176f9aSJulian Elischer
9525e176f9aSJulian ElischerDONE
9535e176f9aSJulian Elischer
95445b4f5afSJulian Elischercat >${TOP}/sys/${1}io.h <<DONE
9555e176f9aSJulian Elischer/*
9565e176f9aSJulian Elischer * Definitions needed to access the ${1} device (ioctls etc)
9575e176f9aSJulian Elischer * see mtio.h , ioctl.h as examples
9585e176f9aSJulian Elischer */
9595e176f9aSJulian Elischer#ifndef SYS_DHIO_H
9605e176f9aSJulian Elischer#define SYS_DHIO_H
9615e176f9aSJulian Elischer
9625e176f9aSJulian Elischer#ifndef KERNEL
9635e176f9aSJulian Elischer#include <sys/types.h>
9645e176f9aSJulian Elischer#endif
9655e176f9aSJulian Elischer#include <sys/ioccom.h>
9665e176f9aSJulian Elischer
9675e176f9aSJulian Elischer/*
9685e176f9aSJulian Elischer * define an ioctl here
9695e176f9aSJulian Elischer */
9705e176f9aSJulian Elischer#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
9715e176f9aSJulian Elischer#endif
9725e176f9aSJulian ElischerDONE
9735e176f9aSJulian Elischer
97445b4f5afSJulian Elischerif [ ! -d ${TOP}/modules/${1} ]
9754308b695SJulian Elischerthen
97645b4f5afSJulian Elischer	mkdir -p ${TOP}/modules/${1}
97745b4f5afSJulian Elischerfi
97845b4f5afSJulian Elischer
97945b4f5afSJulian Elischercat >${TOP}/modules/${1}/Makefile <<DONE
9804308b695SJulian Elischer#	${UPPER} Loadable Kernel Module
9814308b695SJulian Elischer#
98296305e8fSJulian Elischer# \$${RCS_KEYWORD}: $
9834308b695SJulian Elischer 
98445b4f5afSJulian Elischer.PATH:  \${.CURDIR}/../../dev/${1}
98545b4f5afSJulian ElischerKMOD    = ${1}
98645b4f5afSJulian ElischerSRCS    = ${1}.c
98745b4f5afSJulian ElischerSRCS    += opt_inet.h device_if.h bus_if.h pci_if.h isa_if.h
9884308b695SJulian Elischer  
98945b4f5afSJulian Elischer# you may need to do this is your device is an if_xxx driver
99045b4f5afSJulian Elischeropt_inet.h:
99145b4f5afSJulian Elischer	echo "#define INET 1" > opt_inet.h
9924308b695SJulian Elischer	   
9934308b695SJulian Elischer.include <bsd.kmod.mk>
9944308b695SJulian ElischerDONE
99545b4f5afSJulian Elischer
99645b4f5afSJulian Elischer(cd ${TOP}/modules/${1}; make depend; make )
99745b4f5afSJulian Elischerexit
9984308b695SJulian Elischer
9995e176f9aSJulian Elischerconfig ${UPPER}
10005e176f9aSJulian Elischercd ../../compile/${UPPER}
10015e176f9aSJulian Elischermake depend
10025e176f9aSJulian Elischermake ${1}.o
10035e176f9aSJulian Elischermake
10045e176f9aSJulian Elischerexit
10055e176f9aSJulian Elischer
10065e176f9aSJulian Elischer#--------------end of script---------------
10075e176f9aSJulian Elischer#
10085e176f9aSJulian Elischer#edit to your taste..
10095e176f9aSJulian Elischer#
10105e176f9aSJulian Elischer#
10115e176f9aSJulian Elischer
10125e176f9aSJulian Elischer
10135e176f9aSJulian Elischer
10145e176f9aSJulian Elischer
1015