xref: /freebsd/share/examples/drivers/make_device_driver.sh (revision 87e78fdf4c1fce754401b8edd6d67f85eedeeebf)
1#!/bin/sh
2# This writes a skeleton driver and puts it into the kernel tree for you.
3# It also adds FOO and files.FOO configuration files so you can compile
4# a kernel with your FOO driver linked in.
5# To do so:
6# cd /sys/i386/conf; config FOO; cd ../../compile/FOO; make depend; make
7#
8# More interestingly, it creates a modules/foo directory
9# which it populates, to allow you to compile a FOO module
10# which can be lonked with your presently running kernel (if you feel brave).
11# To do so:
12# cd /sys/modules/foo; make depend; make; make install; kldload foo
13#
14# arg1 to this script is expected to be lowercase "foo"
15#
16# Trust me, RUN THIS SCRIPT :)
17#
18# $FreeBSD$"
19#
20#-------cut here------------------
21if [ "${1}X" = "X" ]
22then
23	echo "Hey , how about some help here.. give me a device name!"
24	exit 1
25fi
26UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
27
28HERE=`pwd`
29cd /sys
30TOP=`pwd`
31
32RCS_KEYWORD=FreeBSD
33
34if [ -d ${TOP}/modules/${1} ]
35then
36	echo "There appears to already be a module called ${1}"
37	echo -n "Should it be overwritten? [Y]"
38	read VAL
39	if [ "-z" "$VAL" ]
40	then
41	  VAL=YES
42	fi
43	case ${VAL} in
44	[yY]*)
45	  echo "Cleaning up from prior runs"
46	  rm -rf ${TOP}/dev/${1}
47	  rm -rf ${TOP}/modules/${1}
48	  rm ${TOP}/i386/conf/files.${UPPER}
49	  rm ${TOP}/i386/conf/${UPPER}
50	  rm ${TOP}/sys/${1}io.h
51	  ;;
52	*)
53	  exit 1
54	  ;;
55	esac
56fi
57
58echo "The following files will be created:"
59echo ${TOP}/modules/${1}
60echo ${TOP}/i386/conf/files.${UPPER}
61echo ${TOP}/i386/conf/${UPPER}
62echo ${TOP}/dev/${1}
63echo ${TOP}/dev/${1}/${1}.c
64echo ${TOP}/sys/${1}io.h
65echo ${TOP}/modules/${1}
66echo ${TOP}/modules/${1}/Makefile
67
68
69	mkdir ${TOP}/modules/${1}
70
71#######################################################################
72#######################################################################
73#
74# Create configuration information needed to create a kernel
75# containing this driver.
76#
77# Not really needed if we are going to do this as a module.
78#######################################################################
79# First add the file to a local file list.
80#######################################################################
81
82cat >${TOP}/i386/conf/files.${UPPER} <<DONE
83dev/${1}/${1}.c	 optional ${1}
84DONE
85
86#######################################################################
87# Then create a configuration file for a kernel that contains this driver.
88#######################################################################
89cat >${TOP}/i386/conf/${UPPER} <<DONE
90# Configuration file for kernel type: ${UPPER}
91ident	${UPPER}
92# \$${RCS_KEYWORD}: $
93DONE
94
95grep -v GENERIC < /sys/i386/conf/GENERIC >>${TOP}/i386/conf/${UPPER}
96
97cat >>${TOP}/i386/conf/${UPPER} <<DONE
98options		DDB		# trust me, you'll need this
99device		${1}
100DONE
101
102if [ ! -d ${TOP}/dev/${1} ]
103then
104	mkdir -p ${TOP}/dev/${1}
105fi
106
107
108
109
110cat >${TOP}/dev/${1}/${1}.c <<DONE
111/*
112 * Copyright (c) [year] [your name]
113 * All rights reserved.
114 *
115 * Redistribution and use in source and binary forms, with or without
116 * modification, are permitted provided that the following conditions
117 * are met:
118 * 1. Redistributions of source code must retain the above copyright
119 *    notice, this list of conditions and the following disclaimer.
120 * 2. Redistributions in binary form must reproduce the above copyright
121 *    notice, this list of conditions and the following disclaimer in the
122 *    documentation and/or other materials provided with the distribution.
123 *
124 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
125 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
126 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
127 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
128 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
129 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
130 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
131 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
132 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
133 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
134 * SUCH DAMAGE.
135 *
136 *
137 * ${1} driver
138 * \$${RCS_KEYWORD}: $
139 */
140
141
142#include <sys/param.h>
143#include <sys/systm.h>
144#include <sys/conf.h>		/* cdevsw stuff */
145#include <sys/kernel.h>		/* SYSINIT stuff */
146#include <sys/uio.h>		/* SYSINIT stuff */
147#include <sys/malloc.h>		/* malloc region definitions */
148#include <sys/module.h>
149#include <sys/bus.h>
150#include <machine/bus.h>
151#include <machine/resource.h>
152#include <sys/rman.h>
153#include <sys/time.h>
154
155#include <isa/isavar.h>
156#include "isa_if.h"
157#include <sys/${1}io.h>		/* ${1} IOCTL definitions */
158
159/* XXX These should be defined in terms of bus-space ops */
160#define ${UPPER}_INB(port) inb(port_start)
161#define ${UPPER}_OUTB(port, val) ( port_start, (val))
162#define SOME_PORT 123
163#define EXPECTED_VALUE 0x42
164
165
166/* Function prototypes (these should all be static) */
167static void ${1}_isa_identify (driver_t *, device_t);
168static int ${1}_isa_probe (device_t);
169static int ${1}_isa_attach (device_t);
170static int ${1}_isa_detach (device_t);
171static int ${1}_deallocate_resources(device_t device);
172static int ${1}_allocate_resources(device_t device);
173
174static d_open_t		${1}open;
175static d_close_t	${1}close;
176static d_read_t		${1}read;
177static d_write_t	${1}write;
178static d_ioctl_t	${1}ioctl;
179static d_mmap_t		${1}mmap;
180static d_poll_t		${1}poll;
181static	void		${1}intr(void *arg);
182 
183#define CDEV_MAJOR 20
184static struct cdevsw ${1}_cdevsw = {
185	/* open */	${1}open,
186	/* close */	${1}close,
187	/* read */	${1}read,
188	/* write */	${1}write,
189	/* ioctl */	${1}ioctl,
190	/* poll */	${1}poll,
191	/* mmap */	${1}mmap,
192	/* strategy */	nostrategy,	/* not a block type device */
193	/* name */	"${1}",
194	/* maj */	CDEV_MAJOR,
195	/* dump */	nodump,		/* not a block type device */
196	/* psize */	nopsize,	/* not a block type device */
197	/* flags */	0,
198	/* bmaj */	-1
199};
200 
201/* 
202 * device specific Misc defines 
203 */
204#define BUFFERSIZE	1024
205#define NUMPORTS	4
206#define MEMSIZE		(4 * 1024) /* imaginable h/w buffer size */
207
208/*
209 * One of these per allocated device
210 */
211struct ${1}_softc {
212	bus_space_tag_t bt;
213	bus_space_handle_t bh;
214	int rid_ioport;
215	int rid_memory;
216	int rid_irq;
217	int rid_drq;
218	struct resource* res_ioport;	/* resource for port range */
219	struct resource* res_memory;	/* resource for mem range */
220	struct resource* res_irq;	/* resource for irq range */
221	struct resource* res_drq;	/* resource for dma channel */
222	device_t device;
223	dev_t dev;
224	void	*intr_cookie;
225	char	buffer[BUFFERSIZE];	/* if we needed to buffer something */
226} ;
227
228typedef	struct ${1}_softc *sc_p;
229
230static devclass_t ${1}_devclass;
231
232static struct isa_pnp_id ${1}_ids[] = {
233	{0x12345678, "ABCco Widget"},
234	{0xfedcba98, "shining moon Widget ripoff"},
235	{0}
236};
237
238static device_method_t ${1}_methods[] = {
239	DEVMETHOD(device_identify,	${1}_isa_identify),
240	DEVMETHOD(device_probe,		${1}_isa_probe),
241	DEVMETHOD(device_attach,	${1}_isa_attach),
242	DEVMETHOD(device_detach,	${1}_isa_detach),
243	{ 0, 0 }
244};
245
246static driver_t ${1}_isa_driver = {
247	"${1}",
248	${1}_methods,
249	sizeof (struct ${1}_softc)
250};
251
252DRIVER_MODULE(${1}, isa, ${1}_isa_driver, ${1}_devclass, 0, 0);
253
254/*
255 * Here list some port addresses we might expect our widget to appear at:
256 */
257static struct localhints {
258	int ioport;
259	int irq;
260	int drq;
261	int mem;
262} res[] = {
263	{ 0x210, 11, 2, 0xcd000},
264	{ 0x310, 12, 3, 0xdd000},
265	{ 0x320, 9, 6, 0xd4000},
266	{0,0,0,0}
267};
268
269#define MAXHINTS 10 /* just an arbitrary safty limit */
270/*
271 * Called once when the driver is somehow connected with the bus.
272 * Addentries into the bus's list of likely devices, so that
273 * our 'probe routine' will be called for them.
274 * This is similar to what the 'hints' code achieves, except this is
275 * loadable with the driver.
276 */
277static void
278${1}_isa_identify (driver_t *driver, device_t parent)
279{
280	u_int32_t	irq=0;
281	u_int32_t	ioport;
282	device_t	child;
283	int i;
284
285
286	/*
287	 * If we've already got ${UPPER} attached somehow, don't try again.
288	 */
289	if (device_find_child(parent, "${1}", 0)) {
290		printf("${UPPER}: already attached\n");
291		return;
292	}
293/* XXX look at dev/acpica/acpi_isa.c for use of ISA_ADD_CONFIG() macro */
294/* XXX What is ISA_SET_CONFIG_CALLBACK(parent, child, pnpbios_set_config, 0) ?*/
295	for (i = 0; i < MAXHINTS; i++) {
296		if (((ioport = res[i].ioport) == 0)
297		&&  ((irq = res[i].irq) == 0)) {
298			return; /* we've added all our local hints */
299		}
300
301		child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "${1}", -1);
302		bus_set_resource(child, SYS_RES_IOPORT,	0, ioport, NUMPORTS);
303		bus_set_resource(child, SYS_RES_IRQ,	0, irq, 1);
304		bus_set_resource(child, SYS_RES_DRQ,	0, res[i].drq, 1);
305		bus_set_resource(child, SYS_RES_MEMORY,	0, res[i].mem, MEMSIZE);
306
307#if 0
308		/*
309		 * If we wanted to pretend PNP found it
310		 * we could do this, and put matching entries
311		 * in the PNP table, but I think it's probably too hacky.
312		 * As you see, some people have done it though.
313		 */
314		isa_set_vendorid(child, PNP_EISAID("ESS1888"));
315		isa_set_logicalid(child, PNP_EISAID("ESS1888"));
316#endif
317		/* see isa/isahint.c for hints being added in */
318
319
320	}
321
322	return;
323}
324/*
325 * The ISA code calls this for each device it knows about,
326 * whether via the PNP code or via the hints etc.
327 */
328static int
329${1}_isa_probe (device_t device)
330{
331	int error;
332	device_t parent = device_get_parent(device);
333	sc_p scp = device_get_softc(device);
334	u_long	port_start, port_count;
335
336
337	bzero(scp, sizeof(*scp));
338	scp->device = device;
339
340	/*
341	 * Check this device for a PNP match in our table..
342	 * There are several possible outcomes.
343	 * error == 0		We match a PNP ).
344	 * error == ENXIO,	It is a PNP device but not in out table.
345	 * error == ENOENT,	I is not a PNP device.. try heuristic probes.
346	 *    -- logic from if_ed_isa.c, added info from isa/isa_if.m:
347	 */
348	error = ISA_PNP_PROBE(parent, device, ${1}_ids);
349	switch (error) {
350	case 0:
351		/*
352		 * We found a PNP device.
353		 * Do nothing, as it's all done in attach()
354		 */
355	        /*
356		 * If we don't have the resources we need then
357		 * we need to abort.
358		 * Possibly this indicates the device was already found
359		 * in a PCI or 'hints' based probe.
360		 * (remove any that do not apply to 'foo' devices)
361		 */
362		if ((bus_get_resource_start(device, SYS_RES_IOPORT, 0) == 0)
363		||  (bus_get_resource_start(device, SYS_RES_MEMORY, 0) == 0)
364		||  (bus_get_resource_start(device, SYS_RES_DRQ, 0) == 0)
365		||  (bus_get_resource_start(device, SYS_RES_IRQ, 0) == 0)) {
366			    return (ENOENT);
367		 }
368		break;
369	case ENOENT:
370		/*
371		 * Well it didn't show up in the PNP tables
372		 * so look directly at known ports (if we have any)
373		 * in case we are looking for an old pre-PNP card.
374		 * 
375		 * Hopefully the  'identify' routine will have picked these
376		 * up for us first.
377		 *
378		 * I think the ports etc should come from a 'hints' section
379		 * buried somewhere. XXX - still not figured out.
380		 * which is read in by code in isa/isahint.c
381		 * and kern/subr_bus.c to create resource entries.
382		 * Somehow we can get to those resource entries
383		 * from the device_t but I don't know how yet.
384		 * (looks like the 'identify' routine can do this)
385		 */
386	        /*
387		 * If we don't have the resources we need then
388		 * we need to abort.
389		 * Possibly this indicates the device was already found
390		 * in a PCI or 'hints' based probe.
391		 * Maybe it was mistakenly mentionned twice in the
392		 * hints or 'indentify' code.
393		 * (remove any that do not apply to 'foo' devices)
394		 */
395		if ((bus_get_resource_start(device, SYS_RES_IOPORT, 0) == 0)
396		||  (bus_get_resource_start(device, SYS_RES_MEMORY, 0) == 0)
397		||  (bus_get_resource_start(device, SYS_RES_DRQ, 0) == 0)
398		||  (bus_get_resource_start(device, SYS_RES_IRQ, 0) == 0)) {
399			    return (error);
400		}
401
402		 error = bus_get_resource(device, SYS_RES_IOPORT, 0,
403			&port_start, &port_count);
404
405
406		if ( ${UPPER}_INB(SOME_PORT) != EXPECTED_VALUE) {
407			/* 
408			 * It isn't what we hoped, so quit looking for it.
409			 */
410			error = ENXIO;
411		} else {
412			/*
413			 * We found one..
414			 */
415			error = 0;
416		}
417		break;
418	case  ENXIO:
419		/* not ours, leave imediatly */
420	default:
421		error = ENXIO;
422	}
423	return (error);
424}
425
426/*
427 * Called if the probe succeeded.
428 * We can be destructive here as we know we have the device.
429 */
430static int
431${1}_isa_attach (device_t device)
432{
433	int	unit	= device_get_unit(device);
434	sc_p	scp	= device_get_softc(device);
435	device_t parent	= device_get_parent(device);
436	bus_space_handle_t  bh;
437	bus_space_tag_t bt;
438
439	scp->dev->si_drv1 = scp;
440	scp->dev = make_dev(&${1}_cdevsw, 0,
441			UID_ROOT, GID_OPERATOR, 0600, "${1}%d", unit);
442
443	if (${1}_allocate_resources(device)) {
444		goto errexit;
445	}
446
447	scp->bt = bt = rman_get_bustag(scp->res_ioport);
448	scp->bh = bh = rman_get_bushandle(scp->res_ioport);
449
450	/* register the interrupt handler */
451	if (scp->res_irq) {
452		/* default to the tty mask for registration */  /* XXX */
453		if (BUS_SETUP_INTR(parent, device, scp->res_irq, INTR_TYPE_TTY,
454				${1}intr, scp, &scp->intr_cookie) == 0) {
455			/* do something if successfull */
456		}
457	}
458	return 0;
459
460errexit:
461	/*
462	 * Undo anything we may have done
463	 */
464	${1}_isa_detach(device);
465	return (ENXIO);
466}
467
468static int
469${1}_isa_detach (device_t device)
470{
471	sc_p scp = device_get_softc(device);
472	device_t parent = device_get_parent(device);
473
474	/*
475	 * At this point stick a strong piece of wood into the device
476	 * to make sure it is stopped safely. The alternative is to 
477	 * simply REFUSE to detach if it's busy. What you do depends on 
478	 * your specific situation.
479	 */
480	/* ZAP some register */
481
482	/*
483	 * Take our interrupt handler out of the list of handlers
484	 * that can handle this irq.
485	 */
486	if (scp->intr_cookie != NULL) {
487		if (BUS_TEARDOWN_INTR(parent, device,
488			scp->res_irq, scp->intr_cookie) != 0) {
489				printf("intr teardown failed.. continuing\n");
490		}
491		scp->intr_cookie = NULL;
492	}
493
494	/*
495	 * deallocate any system resources we may have
496	 * allocated on behalf of this driver.
497	 */
498	return ${1}_deallocate_resources(device);
499}
500
501static int
502${1}_allocate_resources(device_t device)
503{
504	int error;
505	sc_p scp = device_get_softc(device);
506	int	size = 16; /* SIZE of port range used */
507
508	scp->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT,
509			&scp->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE);
510	if (scp->res_ioport == NULL) {
511		goto errexit;
512	}
513
514	scp->res_irq = bus_alloc_resource(device, SYS_RES_IRQ,
515			&scp->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE);
516	if (scp->res_irq == NULL) {
517		goto errexit;
518	}
519
520	scp->res_drq = bus_alloc_resource(device, SYS_RES_DRQ,
521			&scp->rid_drq, 0ul, ~0ul, 1, RF_ACTIVE);
522	if (scp->res_drq == NULL) {
523		goto errexit;
524	}
525
526	scp->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
527			&scp->rid_memory, 0ul, ~0ul, MSIZE, RF_ACTIVE);
528	if (scp->res_memory == NULL) {
529		goto errexit;
530	}
531
532	return (0);
533
534errexit:
535	error = ENXIO;
536	/* cleanup anything we may have assigned. */
537	${1}_deallocate_resources(device);
538	return (ENXIO); /* for want of a better idea */
539}
540
541static int
542${1}_deallocate_resources(device_t device)
543{
544	sc_p scp = device_get_softc(device);
545
546	if (scp->res_irq != 0) {
547		bus_deactivate_resource(device, SYS_RES_IRQ,
548			scp->rid_irq, scp->res_irq);
549		bus_release_resource(device, SYS_RES_IRQ,
550			scp->rid_irq, scp->res_irq);
551		scp->res_irq = 0;
552	}
553	if (scp->res_ioport != 0) {
554		bus_deactivate_resource(device, SYS_RES_IOPORT,
555			scp->rid_ioport, scp->res_ioport);
556		bus_release_resource(device, SYS_RES_IOPORT,
557			scp->rid_ioport, scp->res_ioport);
558		scp->res_ioport = 0;
559	}
560	if (scp->res_ioport != 0) {
561		bus_deactivate_resource(device, SYS_RES_MEMORY,
562			scp->rid_memory, scp->res_memory);
563		bus_release_resource(device, SYS_RES_MEMORY,
564			scp->rid_memory, scp->res_memory);
565		scp->res_ioport = 0;
566	}
567	if (scp->res_drq != 0) {
568		bus_deactivate_resource(device, SYS_RES_DRQ,
569			scp->rid_drq, scp->res_drq);
570		bus_release_resource(device, SYS_RES_DRQ,
571			scp->rid_drq, scp->res_drq);
572		scp->res_drq = 0;
573	}
574	if (scp->dev) {
575		destroy_dev(scp->dev);
576	}
577	return (0);
578}
579
580static void
581${1}intr(void *arg)
582{
583	sc_p scp	= arg;
584
585	/* 
586	 * well we got an interupt, now what?
587	 */
588	return;
589}
590
591static int
592${1}ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
593{
594	sc_p scp	= dev->si_drv1;
595
596	switch (cmd) {
597	case DHIOCRESET:
598		/* whatever resets it */
599#if 0
600		${UPPER}_OUTB(SOME_PORT, 0xff) ;
601#endif
602		break;
603	default:
604		return ENXIO;
605	}
606	return (0);
607}
608/*
609 * You also need read, write, open, close routines.
610 * This should get you started
611 */
612static int
613${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
614{
615	sc_p scp	= dev->si_drv1;
616
617	/* 
618	 * Do processing
619	 */
620	return (0);
621}
622
623static int
624${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
625{
626	sc_p scp	= dev->si_drv1;
627
628	/* 
629	 * Do processing
630	 */
631	return (0);
632}
633
634static int
635${1}read(dev_t dev, struct uio *uio, int ioflag)
636{
637	sc_p scp	= dev->si_drv1;
638	int	 toread;
639
640
641	/* 
642	 * Do processing
643	 * read from buffer
644	 */
645	toread = (min(uio->uio_resid, sizeof(scp->buffer)));
646	return(uiomove(scp->buffer, toread, uio));
647}
648
649static int
650${1}write(dev_t dev, struct uio *uio, int ioflag)
651{
652	sc_p scp	= dev->si_drv1;
653	int	towrite;
654
655	/* 
656	 * Do processing
657	 * write to buffer
658	 */
659	towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
660	return(uiomove(scp->buffer, towrite, uio));
661}
662
663static int
664${1}mmap(dev_t dev, vm_offset_t offset, int nprot)
665{
666	sc_p scp	= dev->si_drv1;
667
668	/* 
669	 * Given a byte offset into your device, return the PHYSICAL
670	 * page number that it would map to.
671	 */
672#if 0	/* if we had a frame buffer or whatever.. do this */
673	if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) {
674		return (-1);
675	}
676	return i386_btop((FRAMEBASE + offset));
677#else
678	return (-1);
679#endif
680}
681
682static int
683${1}poll(dev_t dev, int which, struct proc *p)
684{
685	sc_p scp	= dev->si_drv1;
686
687	/* 
688	 * Do processing
689	 */
690	return (0); /* this is the wrong value I'm sure */
691}
692
693DONE
694
695cat >${TOP}/sys/${1}io.h <<DONE
696/*
697 * Definitions needed to access the ${1} device (ioctls etc)
698 * see mtio.h , ioctl.h as examples
699 */
700#ifndef SYS_DHIO_H
701#define SYS_DHIO_H
702
703#ifndef KERNEL
704#include <sys/types.h>
705#endif
706#include <sys/ioccom.h>
707
708/*
709 * define an ioctl here
710 */
711#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
712#endif
713DONE
714
715if [ ! -d ${TOP}/modules/${1} ]
716then
717	mkdir -p ${TOP}/modules/${1}
718fi
719
720cat >${TOP}/modules/${1}/Makefile <<DONE
721#	${UPPER} Loadable Kernel Module
722#
723# \$${RCS_KEYWORD}: $
724 
725.PATH:  \${.CURDIR}/../../dev/${1}
726KMOD    = ${1}
727SRCS    = ${1}.c
728SRCS    += opt_inet.h device_if.h bus_if.h pci_if.h isa_if.h
729  
730# you may need to do this is your device is an if_xxx driver
731opt_inet.h:
732	echo "#define INET 1" > opt_inet.h
733	   
734.include <bsd.kmod.mk>
735DONE
736
737(cd ${TOP}/modules/${1}; make depend; make )
738exit
739
740config ${UPPER}
741cd ../../compile/${UPPER}
742make depend
743make ${1}.o
744make
745exit
746
747#--------------end of script---------------
748#
749#edit to your taste..
750#
751#
752
753
754
755
756