mirror of
https://git.FreeBSD.org/src.git
synced 2024-10-19 02:29:40 +00:00
First effort at bringing these up-to-date.
This creates a skeleton ISA device driver. I don't pretend that it's fully correct or even opitimal but it at least creates (and compiles) a 'clean' ISA driver. Hopefully PCI/PCCARD/etc. support will be added when I understand it. Unlike the old version this just creates a module. The old one tried to create a new kernel with the driver to be tested.
This commit is contained in:
parent
85e427cc94
commit
45b4f5af9e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=67505
@ -6,41 +6,97 @@
|
||||
#loadable kernel modules, though without much use except for development.
|
||||
#
|
||||
# Trust me, RUN THIS SCRIPT :)
|
||||
# $FreeBSD$"
|
||||
#
|
||||
#-------cut here------------------
|
||||
cd /sys/i386/conf
|
||||
|
||||
if [ "${1}X" = "X" ]
|
||||
then
|
||||
echo "Hey , how about some help here.. give me a device name!"
|
||||
exit 1
|
||||
fi
|
||||
UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
|
||||
|
||||
if [ -d /usr/src/lkm ]
|
||||
HERE=`pwd`
|
||||
cd /sys
|
||||
TOP=`pwd`
|
||||
|
||||
echo ${TOP}/modules/${1}
|
||||
echo ${TOP}/i386/conf/files.${UPPER}
|
||||
echo ${TOP}/i386/conf/${UPPER}
|
||||
echo ${TOP}/dev/${1}
|
||||
echo ${TOP}/dev/${1}/${1}.c
|
||||
echo ${TOP}/sys/${1}io.h
|
||||
echo ${TOP}/modules/${1}
|
||||
echo ${TOP}/modules/${1}/Makefile
|
||||
|
||||
rm -rf ${TOP}/dev/${1}
|
||||
rm -rf ${TOP}/modules/${1}
|
||||
rm ${TOP}/i386/conf/files.${UPPER}
|
||||
rm ${TOP}/i386/conf/${UPPER}
|
||||
rm ${TOP}/sys/${1}io.h
|
||||
|
||||
if [ -d ${TOP}/modules/${1} ]
|
||||
then
|
||||
mkdir /usr/src/lkm/${1}
|
||||
echo "There appears to already be a module called ${1}"
|
||||
exit 1
|
||||
else
|
||||
mkdir ${TOP}/modules/${1}
|
||||
fi
|
||||
|
||||
UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
|
||||
cat >files.${UPPER} <<DONE
|
||||
i386/isa/${1}.c optional ${1} device-driver
|
||||
#######################################################################
|
||||
#######################################################################
|
||||
#
|
||||
# Create configuration information needed to create a kernel
|
||||
# containing this driver.
|
||||
#
|
||||
# Not really needed if we are going to do this as a module.
|
||||
#######################################################################
|
||||
# First add the file to a local file list.
|
||||
#######################################################################
|
||||
|
||||
cat >${TOP}/i386/conf/files.${UPPER} <<DONE
|
||||
i386/isa/${1}.c optional ${1} device-driver
|
||||
DONE
|
||||
|
||||
cat >${UPPER} <<DONE
|
||||
#######################################################################
|
||||
# Then create a configuration file for a kernel that contains this driver.
|
||||
#######################################################################
|
||||
cat >${TOP}/i386/conf/${UPPER} <<DONE
|
||||
# Configuration file for kernel type: ${UPPER}
|
||||
ident ${UPPER}
|
||||
# \$FreeBSD$"
|
||||
DONE
|
||||
|
||||
grep -v GENERIC < GENERIC >>${UPPER}
|
||||
grep -v GENERIC < /sys/i386/conf/GENERIC >>${TOP}/i386/conf/${UPPER}
|
||||
|
||||
cat >>${UPPER} <<DONE
|
||||
# trust me, you'll need this
|
||||
options DDB
|
||||
device ${1}0 at isa? port 0x234 bio irq 5
|
||||
cat >>${TOP}/i386/conf/${UPPER} <<DONE
|
||||
options DDB # trust me, you'll need this
|
||||
device ${1} at isa?
|
||||
DONE
|
||||
|
||||
cat >../isa/${1}.c <<DONE
|
||||
if [ ! -d ${TOP}/dev/${1} ]
|
||||
then
|
||||
mkdir -p ${TOP}/dev/${1}
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cat >${TOP}/dev/${1}/${1}.c <<DONE
|
||||
/*
|
||||
* Copyright ME
|
||||
*
|
||||
@ -49,222 +105,250 @@ cat >../isa/${1}.c <<DONE
|
||||
*/
|
||||
|
||||
|
||||
#include "${1}.h" /* generated file.. defines N${UPPER} */
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h> /* SYSINIT stuff */
|
||||
#include <sys/conf.h> /* cdevsw stuff */
|
||||
#include <sys/kernel.h> /* SYSINIT stuff */
|
||||
#include <sys/uio.h> /* SYSINIT stuff */
|
||||
#include <sys/malloc.h> /* malloc region definitions */
|
||||
#include <machine/clock.h> /* DELAY() */
|
||||
#include <i386/isa/isa.h> /* ISA bus port definitions etc. */
|
||||
#include <i386/isa/isa_device.h>/* ISA bus configuration structures */
|
||||
#include <sys/${1}io.h> /* ${1} IOCTL definitions */
|
||||
#ifdef DEVFS
|
||||
#include <sys/devfsext.h> /* DEVFS defintitions */
|
||||
#endif /* DEVFS */
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
#include "isa_if.h"
|
||||
#include <sys/${1}io.h> /* ${1} IOCTL definitions */
|
||||
|
||||
#define ${UPPER}DEV2SOFTC(dev) ((dev)->si_drv1)
|
||||
#define ${UPPER}_INB(port) bus_space_read_1( bt, bh, (port))
|
||||
#define ${UPPER}_OUTB(port, val) bus_space_write_1( bt, bh, (port), (val))
|
||||
#define SOME_PORT 123
|
||||
#define EXPECTED_VALUE 0x42
|
||||
|
||||
|
||||
/* Function prototypes (these should all be static) */
|
||||
static d_open_t ${1}open;
|
||||
static d_close_t ${1}close;
|
||||
static d_read_t ${1}read;
|
||||
static d_write_t ${1}write;
|
||||
static d_ioctl_t ${1}ioctl;
|
||||
static d_mmap_t ${1}mmap;
|
||||
static d_poll_t ${1}poll;
|
||||
static int ${1}probe (struct isa_device *);
|
||||
static int ${1}attach (struct isa_device *);
|
||||
static int ${1}_isa_probe (device_t);
|
||||
static int ${1}_isa_attach (device_t);
|
||||
static int ${1}_isa_detach (device_t);
|
||||
|
||||
static d_open_t ${1}open;
|
||||
static d_close_t ${1}close;
|
||||
static d_read_t ${1}read;
|
||||
static d_write_t ${1}write;
|
||||
static d_ioctl_t ${1}ioctl;
|
||||
static d_mmap_t ${1}mmap;
|
||||
static d_poll_t ${1}poll;
|
||||
#ifdef ${UPPER}_MODULE
|
||||
static ointhand2_t ${1}intr; /* should actually have type inthand2_t */
|
||||
#endif
|
||||
|
||||
#define CDEV_MAJOR 20
|
||||
static struct cdevsw ${1}_cdevsw = {
|
||||
${1}open,
|
||||
${1}close,
|
||||
${1}read,
|
||||
${1}write,
|
||||
${1}ioctl,
|
||||
nullstop,
|
||||
nullreset,
|
||||
nodevtotty,
|
||||
${1}poll,
|
||||
${1}mmap,
|
||||
NULL,
|
||||
"${1}",
|
||||
NULL,
|
||||
-1 };
|
||||
/* open */ ${1}open,
|
||||
/* close */ ${1}close,
|
||||
/* read */ ${1}read,
|
||||
/* write */ ${1}write,
|
||||
/* ioctl */ ${1}ioctl,
|
||||
/* poll */ ${1}poll,
|
||||
/* mmap */ ${1}mmap,
|
||||
/* strategy */ nostrategy, /* not a block type device */
|
||||
/* name */ "${1}",
|
||||
/* maj */ CDEV_MAJOR,
|
||||
/* dump */ nodump, /* not a block type device */
|
||||
/* psize */ nopsize, /* not a block type device */
|
||||
/* flags */ 0,
|
||||
/* bmaj */ -1
|
||||
};
|
||||
|
||||
struct isa_driver ${1}driver = {
|
||||
${1}probe,
|
||||
${1}attach,
|
||||
"${1}" };
|
||||
|
||||
/*
|
||||
* device specific Misc defines
|
||||
* device specific Misc defines
|
||||
*/
|
||||
#define BUFFERSIZE 1024
|
||||
#define NUMPORTS 4
|
||||
#define UNIT(dev) minor(dev) /* assume one minor number per unit */
|
||||
|
||||
/*
|
||||
* One of these per allocated device
|
||||
*/
|
||||
struct ${1}_softc {
|
||||
struct isa_device *dev;
|
||||
bus_space_tag_t bt;
|
||||
bus_space_handle_t bh;
|
||||
int port_rid;
|
||||
struct resource* port_res; /* resource for port range */
|
||||
dev_t dev;
|
||||
device_t device;
|
||||
char buffer[BUFFERSIZE];
|
||||
#ifdef DEVFS
|
||||
static void *devfs_token;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
typedef struct ${1}_softc *sc_p;
|
||||
|
||||
static sc_p sca[N${UPPER}];
|
||||
devclass_t ${1}_devclass;
|
||||
|
||||
/* add your own test to see if it exists */
|
||||
/* should return the number of ports needed */
|
||||
static struct isa_pnp_id ${1}_ids[] = {
|
||||
{0x12345678, "ABCco Widget"},
|
||||
{0xfedcba98, "shining moon Widget ripoff"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static device_method_t ${1}_methods[] = {
|
||||
DEVMETHOD(device_probe, ${1}_isa_probe),
|
||||
DEVMETHOD(device_attach, ${1}_isa_attach),
|
||||
DEVMETHOD(device_detach, ${1}_isa_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t ${1}_isa_driver = {
|
||||
"${1}",
|
||||
${1}_methods,
|
||||
sizeof (struct ${1}_softc)
|
||||
};
|
||||
|
||||
DRIVER_MODULE(${1}, isa, ${1}_isa_driver, ${1}_devclass, 0, 0);
|
||||
|
||||
|
||||
/*
|
||||
* The ISA code calls this for each device it knows about,
|
||||
* whether via the PNP code or via the hints etc.
|
||||
*/
|
||||
static int
|
||||
${1}probe (struct isa_device *dev)
|
||||
${1}_isa_probe (device_t device)
|
||||
{
|
||||
char val;
|
||||
int unit = dev->id_unit;
|
||||
sc_p scp = sca[unit];
|
||||
int error;
|
||||
sc_p scp = device_get_softc(device);
|
||||
bus_space_handle_t bh;
|
||||
bus_space_tag_t bt;
|
||||
struct resource *port_res;
|
||||
int rid = 0;
|
||||
int size = 16; /* SIZE of port range used */
|
||||
|
||||
|
||||
bzero(scp, sizeof(*scp));
|
||||
scp->device = device;
|
||||
|
||||
/*
|
||||
* Check the unit makes sense.
|
||||
* Check for a PNP match..
|
||||
* There are several possible outcomes.
|
||||
* error == 0 We match a PNP device (possibly several?).
|
||||
* error == ENXIO, It is a PNP device but not ours.
|
||||
* error == ENOENT, I is not a PNP device.. try heuristic probes.
|
||||
* -- logic from if_ed_isa.c, added info from isa/isa_if.m:
|
||||
*/
|
||||
if (unit > N${UPPER}) {
|
||||
printf("bad unit (%d)\n", unit);
|
||||
return (0);
|
||||
}
|
||||
if (scp) {
|
||||
printf("unit %d already attached\n", unit);
|
||||
return (0);
|
||||
}
|
||||
error = ISA_PNP_PROBE(device_get_parent(device), device, ${1}_ids);
|
||||
switch (error) {
|
||||
case 0:
|
||||
/*
|
||||
* We found a PNP device.
|
||||
* Fall through into the code that just looks
|
||||
* for a non PNP device as that should
|
||||
* act as a good filter for bad stuff.
|
||||
*/
|
||||
case ENOENT:
|
||||
/*
|
||||
* Well it didn't show up in the PNP tables
|
||||
* so look directly at known ports (if we have any)
|
||||
* in case we are looking for an old pre-PNP card.
|
||||
*
|
||||
* The ports etc should come from a 'hints' section
|
||||
* buried somewhere. XXX - still not figured out.
|
||||
* which is read in by code in isa/isahint.c
|
||||
*/
|
||||
|
||||
port_res = bus_alloc_resource(device, SYS_RES_IOPORT, &rid,
|
||||
0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (port_res == NULL) {
|
||||
error = ENXIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* try see if the device is there.
|
||||
*/
|
||||
val = inb (dev->id_iobase);
|
||||
if ( val != 42 ) {
|
||||
return (0);
|
||||
}
|
||||
scp->port_rid = rid;
|
||||
scp->port_res = port_res;
|
||||
scp->bt = bt = rman_get_bustag(port_res);
|
||||
scp->bh = bh = rman_get_bushandle(port_res);
|
||||
|
||||
/*
|
||||
* ok, we got one we think
|
||||
* do some further (this time possibly destructive) tests.
|
||||
*/
|
||||
outb (dev->id_iobase, 0xff);
|
||||
DELAY (10000); /* 10 ms delay */
|
||||
val = inb (dev->id_iobase) & 0x0f;
|
||||
return ((val & 0x0f) == 0x0f)? NUMPORTS : 0 ;
|
||||
if ( ${UPPER}_INB(SOME_PORT) != EXPECTED_VALUE) {
|
||||
/*
|
||||
* It isn't what we expected,
|
||||
* so release everything and quit looking for it.
|
||||
*/
|
||||
bus_release_resource(device, SYS_RES_IOPORT,
|
||||
rid, port_res);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = 0;
|
||||
break;
|
||||
case ENXIO:
|
||||
/* not ours, leave imediatly */
|
||||
default:
|
||||
error = ENXIO;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called if the probe succeeded.
|
||||
* We can be destructive here as we know we have the device.
|
||||
* we can also trust the unit number.
|
||||
*/
|
||||
static int
|
||||
${1}attach (struct isa_device *dev)
|
||||
${1}_isa_attach (device_t device)
|
||||
{
|
||||
int unit = dev->id_unit;
|
||||
sc_p scp = sca[unit];
|
||||
int unit = device_get_unit(device);
|
||||
sc_p scp = device_get_softc(device);
|
||||
|
||||
/*
|
||||
* Attach our interrupt handler to the device struct. Our caller
|
||||
* will attach it to the hardware soon after we return.
|
||||
*/
|
||||
dev->id_ointr = ${1}intr;
|
||||
|
||||
/*
|
||||
* Allocate storage for this instance .
|
||||
*/
|
||||
scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
|
||||
if( scp == NULL) {
|
||||
printf("${1}%d failed to allocage driver strorage\n", unit);
|
||||
return (0);
|
||||
}
|
||||
bzero(scp, sizeof(*scp));
|
||||
sca[unit] = scp;
|
||||
|
||||
/*
|
||||
* Store whatever seems wise.
|
||||
*/
|
||||
scp->dev = dev;
|
||||
#if DEVFS
|
||||
scp->devfs_token = devfs_add_devswf(&${1}_cdevsw, unit, DV_CHR,
|
||||
UID_ROOT, GID_KMEM, 0600, "${1}%d", unit);
|
||||
#endif
|
||||
return 1;
|
||||
scp->dev = make_dev(&${1}_cdevsw, 0, 0, 0, 0600, "${1}%d", unit);
|
||||
scp->dev->si_drv1 = scp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Macro to check that the unit number is valid
|
||||
* Often this isn't needed as once the open() is performed,
|
||||
* the unit number is pretty much safe.. The exception would be if we
|
||||
* implemented devices that could "go away". in which case all these routines
|
||||
* would be wise to check the number, DIAGNOSTIC or not.
|
||||
*/
|
||||
#define CHECKUNIT(RETVAL) \
|
||||
do { /* the do-while is a safe way to do this grouping */ \
|
||||
if (unit > N${UPPER}) { \
|
||||
printf(__FUNCTION__ ":bad unit %d\n", unit); \
|
||||
return (RETVAL); \
|
||||
} \
|
||||
if (scp == NULL) { \
|
||||
printf( __FUNCTION__ ": unit %d not attached\n", unit);\
|
||||
return (RETVAL); \
|
||||
} \
|
||||
} while (0)
|
||||
#ifdef DIAGNOSTIC
|
||||
#define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
|
||||
#else /* DIAGNOSTIC */
|
||||
#define CHECKUNIT_DIAG(RETVAL)
|
||||
#endif /* DIAGNOSTIC */
|
||||
static int
|
||||
${1}_isa_detach (device_t device)
|
||||
{
|
||||
sc_p scp = device_get_softc(device);
|
||||
|
||||
bus_release_resource(device, SYS_RES_IOPORT,
|
||||
scp->port_rid, scp->port_res);
|
||||
destroy_dev(scp->dev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
${1}intr(int unit)
|
||||
${1}intr(void *arg)
|
||||
{
|
||||
sc_p scp = sca[unit];
|
||||
|
||||
/*device_t dev = (device_t)arg;*/
|
||||
/* sc_p scp = device_get_softc(dev);*/
|
||||
|
||||
/*
|
||||
* well we got an interupt, now what?
|
||||
* Theoretically we don't need to check the unit.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
|
||||
static int
|
||||
${1}ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
|
||||
{
|
||||
int unit = UNIT (dev);
|
||||
sc_p scp = sca[unit];
|
||||
|
||||
CHECKUNIT_DIAG(ENXIO);
|
||||
|
||||
sc_p scp = ${UPPER}DEV2SOFTC(dev);
|
||||
bus_space_handle_t bh = scp->bh;
|
||||
bus_space_tag_t bt = scp->bt;
|
||||
|
||||
switch (cmd) {
|
||||
case DHIOCRESET:
|
||||
/* whatever resets it */
|
||||
outb(scp->dev->id_iobase, 0xff);
|
||||
case DHIOCRESET:
|
||||
/* whatever resets it */
|
||||
${UPPER}_OUTB(SOME_PORT, 0xff) ;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
return ENXIO;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* You also need read, write, open, close routines.
|
||||
* This should get you started
|
||||
*/
|
||||
static int
|
||||
static int
|
||||
${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
|
||||
{
|
||||
int unit = UNIT (dev);
|
||||
sc_p scp = sca[unit];
|
||||
|
||||
CHECKUNIT(ENXIO);
|
||||
sc_p scp = ${UPPER}DEV2SOFTC(dev);
|
||||
|
||||
/*
|
||||
* Do processing
|
||||
@ -272,13 +356,10 @@ ${1}open(dev_t dev, int oflags, int devtype, struct proc *p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
|
||||
{
|
||||
int unit = UNIT (dev);
|
||||
sc_p scp = sca[unit];
|
||||
|
||||
CHECKUNIT_DIAG(ENXIO);
|
||||
sc_p scp = ${UPPER}DEV2SOFTC(dev);
|
||||
|
||||
/*
|
||||
* Do processing
|
||||
@ -286,15 +367,12 @@ ${1}close(dev_t dev, int fflag, int devtype, struct proc *p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
${1}read(dev_t dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
int unit = UNIT (dev);
|
||||
sc_p scp = sca[unit];
|
||||
int toread;
|
||||
|
||||
|
||||
CHECKUNIT_DIAG(ENXIO);
|
||||
sc_p scp = ${UPPER}DEV2SOFTC(dev);
|
||||
int toread;
|
||||
|
||||
|
||||
/*
|
||||
* Do processing
|
||||
@ -304,14 +382,11 @@ ${1}read(dev_t dev, struct uio *uio, int ioflag)
|
||||
return(uiomove(scp->buffer, toread, uio));
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
${1}write(dev_t dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
int unit = UNIT (dev);
|
||||
sc_p scp = sca[unit];
|
||||
sc_p scp = ${UPPER}DEV2SOFTC(dev);
|
||||
int towrite;
|
||||
|
||||
CHECKUNIT_DIAG(ENXIO);
|
||||
|
||||
/*
|
||||
* Do processing
|
||||
@ -321,13 +396,10 @@ ${1}write(dev_t dev, struct uio *uio, int ioflag)
|
||||
return(uiomove(scp->buffer, towrite, uio));
|
||||
}
|
||||
|
||||
static int
|
||||
${1}mmap(dev_t dev, int offset, int nprot)
|
||||
static int
|
||||
${1}mmap(dev_t dev, vm_offset_t offset, int nprot)
|
||||
{
|
||||
int unit = UNIT (dev);
|
||||
sc_p scp = sca[unit];
|
||||
|
||||
CHECKUNIT_DIAG(-1);
|
||||
sc_p scp = ${UPPER}DEV2SOFTC(dev);
|
||||
|
||||
/*
|
||||
* Do processing
|
||||
@ -342,13 +414,10 @@ ${1}mmap(dev_t dev, int offset, int nprot)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
${1}poll(dev_t dev, int which, struct proc *p)
|
||||
{
|
||||
int unit = UNIT (dev);
|
||||
sc_p scp = sca[unit];
|
||||
|
||||
CHECKUNIT_DIAG(ENXIO);
|
||||
sc_p scp = ${UPPER}DEV2SOFTC(dev);
|
||||
|
||||
/*
|
||||
* Do processing
|
||||
@ -356,75 +425,9 @@ ${1}poll(dev_t dev, int which, struct proc *p)
|
||||
return (0); /* this is the wrong value I'm sure */
|
||||
}
|
||||
|
||||
#ifndef ${UPPER}_MODULE
|
||||
|
||||
/*
|
||||
* Now for some driver initialisation.
|
||||
* Occurs ONCE during boot (very early).
|
||||
* This is if we are NOT a loadable module.
|
||||
*/
|
||||
static void
|
||||
${1}_drvinit(void *unused)
|
||||
{
|
||||
dev_t dev;
|
||||
|
||||
dev = makedev(CDEV_MAJOR, 0);
|
||||
cdevsw_add(&dev, &${1}_cdevsw, NULL);
|
||||
}
|
||||
|
||||
SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
|
||||
${1}_drvinit, NULL)
|
||||
|
||||
#else /* ${UPPER}_MODULE */
|
||||
/* Here is the support for if we ARE a loadable kernel module */
|
||||
|
||||
#include <sys/exec.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/lkm.h>
|
||||
|
||||
MOD_DEV (${1}, LM_DT_CHAR, CDEV_MAJOR, &${1}_cdevsw);
|
||||
|
||||
static struct isa_device dev = {0, &${1}driver, BASE_IO, IRQ, DMA, (caddr_t) PHYS_IO, PHYS_IO_SIZE, INT_INT, 0, FLAGS, 0, 0, 0, 0, 1, 0, 0};
|
||||
|
||||
static int
|
||||
${1}_load (struct lkm_table *lkmtp, int cmd)
|
||||
{
|
||||
if (${1}probe (&dev)) {
|
||||
${1}attach (&dev);
|
||||
uprintf ("${1} driver loaded\n");
|
||||
uprintf ("${1}: interrupts not hooked\n");
|
||||
return 0;
|
||||
} else {
|
||||
uprintf ("${1} driver: probe failed\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
${1}_unload (struct lkm_table *lkmtp, int cmd)
|
||||
{
|
||||
uprintf ("${1} driver unloaded\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
${1}_stat (struct lkm_table *lkmtp, int cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
${1}_mod (struct lkm_table *lkmtp, int cmd, int ver)
|
||||
{
|
||||
MOD_DISPATCH(${1}, lkmtp, cmd, ver,
|
||||
${1}_load, ${1}_unload, ${1}_stat);
|
||||
}
|
||||
|
||||
#endif /* ${UPPER}_MODULE */
|
||||
|
||||
DONE
|
||||
|
||||
cat >../../sys/${1}io.h <<DONE
|
||||
cat >${TOP}/sys/${1}io.h <<DONE
|
||||
/*
|
||||
* Definitions needed to access the ${1} device (ioctls etc)
|
||||
* see mtio.h , ioctl.h as examples
|
||||
@ -440,48 +443,34 @@ cat >../../sys/${1}io.h <<DONE
|
||||
/*
|
||||
* define an ioctl here
|
||||
*/
|
||||
#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
|
||||
#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */
|
||||
#endif
|
||||
DONE
|
||||
|
||||
if [ -d /usr/src/lkm/${1} ]
|
||||
if [ ! -d ${TOP}/modules/${1} ]
|
||||
then
|
||||
cat >/usr/src/lkm/${1}/Makefile <<DONE
|
||||
mkdir -p ${TOP}/modules/${1}
|
||||
fi
|
||||
|
||||
cat >${TOP}/modules/${1}/Makefile <<DONE
|
||||
# ${UPPER} Loadable Kernel Module
|
||||
#
|
||||
# This happens not to work, actually. It's written for
|
||||
# a character ISA device driver, but they cannot be
|
||||
# be made into lkm's, because you have to hard code
|
||||
# everything you'll otherwise enter into the kernel
|
||||
# configuration file.
|
||||
|
||||
.PATH: \${.CURDIR}/../../sys/i386/isa
|
||||
KMOD = ${1}_mod
|
||||
SRCS = ${1}.c ${1}.h
|
||||
|
||||
CFLAGS += -I. -D${UPPER}_MODULE
|
||||
CLEANFILES += ${1}.h
|
||||
|
||||
BASE_IO=0 # Base IO address
|
||||
IRQ=0 # IRQ number
|
||||
DMA=-1 # DMA channel
|
||||
PHYS_IO=0 # Physical IO Memory base address
|
||||
PHYS_IO_SIZE=0 # Physical IO Memory size
|
||||
INT_INT=0 # Interrupt interface
|
||||
FLAGS=0 # Flags
|
||||
|
||||
CFLAGS+= -DBASE_IO=\${BASE_IO} -DIRQ=\${IRQ} -DDMA=\${DMA} -DPHYS_IO=\${PHYS_IO} -DPHYS_IO_SIZE=\${PHYS_IO_SIZE} -DINT_INT=\${INT_INT} -DFLAGS=\${FLAGS}
|
||||
|
||||
${1}.h:
|
||||
echo "#define N${UPPER} 1" > ${1}.h
|
||||
|
||||
afterinstall:
|
||||
\${INSTALL} -c -o \${BINOWN} -g \${BINGRP} -m \${BINMODE} \
|
||||
\${.CURDIR}/${1} \${DESTDIR}/usr/bin
|
||||
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: \${.CURDIR}/../../dev/${1}
|
||||
KMOD = ${1}
|
||||
SRCS = ${1}.c
|
||||
SRCS += opt_inet.h device_if.h bus_if.h pci_if.h isa_if.h
|
||||
|
||||
# you may need to do this is your device is an if_xxx driver
|
||||
opt_inet.h:
|
||||
echo "#define INET 1" > opt_inet.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
DONE
|
||||
fi
|
||||
|
||||
(cd ${TOP}/modules/${1}; make depend; make )
|
||||
exit
|
||||
|
||||
config ${UPPER}
|
||||
cd ../../compile/${UPPER}
|
||||
|
Loading…
Reference in New Issue
Block a user