diff --git a/en_US.ISO8859-1/books/arch-handbook/book.sgml b/en_US.ISO8859-1/books/arch-handbook/book.sgml
index af9c07821e..6cbec1dd1c 100644
--- a/en_US.ISO8859-1/books/arch-handbook/book.sgml
+++ b/en_US.ISO8859-1/books/arch-handbook/book.sgml
@@ -1,1101 +1,725 @@
%bookinfo;
%chapters;
]>
FreeBSD Developers' Handbook
The FreeBSD Documentation Project
doc@FreeBSD.org
August 2000
2000
The FreeBSD Documentation Project
&bookinfo.legalnotice;
Welcome to the Developers' Handbook.
Introduction
Developing on FreeBSD
This will need to discuss FreeBSD as a development
platform, the vision of BSD, architectural overview, layout of
/usr/src, history, etc.
Thank you for considering FreeBSD as your development
platform! We hope it will not let you down.
The BSD Vision
Architectural Overview
The Layout of /usr/src
The complete source code to FreeBSD is available from our
public CVS repository. The source code is normally installed in
/usr/src which contains the
following subdirectories.
Directory
Description
bin/
Source for files in
/bin
contrib/
Source for files from contribued software.
crypto/
DES source
etc/
Source for files in /etc
games/
Source for files in /usr/games
gnu/
Utilities covered by the GNU Public License
include/
Source for files in /usr/include
kerberosIV/
Source for Kerbereros version IV
kerberos5/
Source for Kerbereros version 5
lib/
Source for files in /usr/lib
libexec/
Source for files in /usr/libexec
release/
Files required to produce a FreeBSD release
sbin/
Source for files in /sbin
secure/
FreeSec sources
share/
Source for files in /sbin
sys/
Kernel source files
tools/
Tools used for maintenance and testing of
FreeBSD
usr.bin/
Source for files in /usr/bin
usr.sbin/
Source for files in /usr/sbin
Basics
&chap.tools;
&chap.secure;
Kernel
History of the Unix Kernel
Some history of the Unix/BSD kernel, system calls, how do
processes work, blocking, scheduling, threads (kernel),
context switching, signals, interrupts, modules, etc.
Memory and Virtual Memory
Virtual Memory
VM, paging, swapping, allocating memory, testing for
memory leaks, mmap, vnodes, etc.
I/O System
UFS
UFS, FFS, Ext2FS, JFS, inodes, buffer cache, labeling,
locking, metadata, soft-updates, LFS, portalfs, procfs,
vnodes, memory sharing, memory objects, TLBs, caching
Interprocess Communication
Signals
Signals, pipes, semaphores, message queues, shared memory,
ports, sockets, doors
Networking
Sockets
Sockets, bpf, IP, TCP, UDP, ICMP, OSI, bridging,
firewalling, NAT, switching, etc
Network Filesystems
AFS
AFS, NFS, SANs etc]
Terminal Handling
Syscons
Syscons, tty, PCVT, serial console, screen savers,
etc
Sound
OSS
OSS, waveforms, etc
Device Drivers
-
- Writing FreeBSD Device Drivers
-
- This chapter was written by Murray Stokely with selections from
- a variety of sources including the intro(4) man page by Joerg
- Wunsch.
-
-
- Introduction
-
- This chapter provides a brief introduction to writing device
- drivers for FreeBSD. A device in this context is a term used
- mostly for hardware-related stuff that belongs to the system,
- like disks, printers, or a graphics display with its keyboard.
- A device driver is the software component of the operating
- system that controls a specific device. There are also
- so-called pseudo-devices where a device driver emulates the
- behaviour of a device in software without any particular
- underlying hardware. Device drivers can be compiled into the
- system statically or loaded on demand through the dynamic
- kernel linker facility `kld'.
-
- Most devices in a Unix-like operating system are
- accessed through device-nodes, sometimes also called special
- files. These files are usually located under the directory
- /dev in the file system hierarchy. Until
- devfs is fully integrated into FreeBSD, each device node must
- be created statically and independent of the existence of the
- associated device driver. Most device nodes on the system are
- created by running MAKEDEV.
-
- Device drivers can roughly be broken down into three
- categories; character (unbuffered), block (buffered), and
- network drivers.
-
-
-
- Dynamic Kernel Linker Facility - KLD
- The kld interface allows system administrators to
- dynamically add and remove functionality from a running
- system. This allows device driver writers to load their new
- changes into a running kernel without constantly rebooting to
- test changes.
-
- The kld interface is used through the following
- administrator commands :
-
- kldload - loads a new kernel
- module
- kldunload - unloads a kernel
- module
- kldstat - lists the currently loadded
- modules
-
-
-
- Skeleton Layout of a kernel module
-
-/*
- * KLD Skeleton
- * Inspired by Andrew Reiter's Daemonnews article
- */
-
-#include <sys/types.h>
-#include <sys/module.h>
-#include <sys/systm.h> /* uprintf */
-#include <sys/errno.h>
-#include <sys/param.h> /* defines used in kernel.h */
-#include <sys/kernel.h> /* types used in module initialization */
-
-/*
- * Load handler that deals with the loading and unloading of a KLD.
- */
-
-static int
-skel_loader(struct module *m, int what, void *arg)
-{
- int err = 0;
-
- switch (what) {
- case MOD_LOAD: /* kldload */
- uprintf("Skeleton KLD loaded.\n");
- break;
- case MOD_UNLOAD:
- uprintf("Skeleton KLD unloaded.\n");
- break;
- default:
- err = EINVAL;
- break;
- }
- return(err);
-}
-
-/* Declare this module to the rest of the kernel */
-
-DECLARE_MODULE(skeleton, skel_loader, SI_SUB_KLD, SI_ORDER_ANY);
-
-
-
-
- Makefile
- FreeBSD provides a makefile include that you can use
- to quickly compile your kernel addition.
-
-SRCS=skeleton.c
-KMOD=skeleton
-
-.include <bsd.kmod.mk>
-
-
-
- Simply running make with
- this makefile will create a file
- skeleton.ko that can be loaded into
- your system by typing :
-
-&prompt.root kldload -v ./skeleton.ko
-
-
-
-
-
-
- Accessing a device driver
- Unix provides a common set of system calls for user
- applications to use. The upper layers of the kernel dispatch
- these calls to the corresponding device driver when a user
- accesses a device node. The /dev/MAKEDEV
- script makes most of the device nodes for your system but if
- you are doing your own driver development it may be necessary
- to create your own device nodes with mknod
-
-
-
- Creating static device nodes
- The mknod command requires four
- arguments to create a device node. You must specify the
- name of this device node, the type of device, the major number
- of the device, and the minor number of the device.
-
-
-
- Dynamic device nodes
- The device filesystem, or devfs, provides access to the
- kernel's device namespace in the global filesystem namespace.
- This eliminates the problems of potentially having a device
- driver without a static device node, or a device node without
- an installed device driver. Unfortunately, devfs is still a
- work in progress.
-
-
-
-
-
- Character Devices
- A character device driver is one that transfers data
- directly to and from a user process. This is the most common
- type of device driver and there are plenty of simple examples
- in the source tree.
- This simple example pseudo-device remembers whatever values you write
- to it and can then supply them back to you when you read from
- it.
-
-/*
- * Simple `echo' pseudo-device KLD
- *
- * Murray Stokely
- */
-
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-
-#include <sys/types.h>
-#include <sys/module.h>
-#include <sys/systm.h> /* uprintf */
-#include <sys/errno.h>
-#include <sys/param.h> /* defines used in kernel.h */
-#include <sys/kernel.h> /* types used in module initialization */
-#include <sys/conf.h> /* cdevsw struct */
-#include <sys/uio.h> /* uio struct */
-#include <sys/malloc.h>
-
-#define BUFFERSIZE 256
-
-/* Function prototypes */
-d_open_t echo_open;
-d_close_t echo_close;
-d_read_t echo_read;
-d_write_t echo_write;
-
-/* Character device entry points */
-static struct cdevsw echo_cdevsw = {
- echo_open,
- echo_close,
- echo_read,
- echo_write,
- noioctl,
- nopoll,
- nommap,
- nostrategy,
- "echo",
- 33, /* reserved for lkms - /usr/src/sys/conf/majors */
- nodump,
- nopsize,
- D_TTY,
- -1
-};
-
-typedef struct s_echo {
- char msg[BUFFERSIZE];
- int len;
-} t_echo;
-
-/* vars */
-static dev_t sdev;
-static int len;
-static int count;
-static t_echo *echomsg;
-
-MALLOC_DECLARE(M_ECHOBUF);
-MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
-
-/*
- * This function acts is called by the kld[un]load(2) system calls to
- * determine what actions to take when a module is loaded or unloaded.
- */
-
-static int
-echo_loader(struct module *m, int what, void *arg)
-{
- int err = 0;
-
- switch (what) {
- case MOD_LOAD: /* kldload */
- sdev = make_dev(&echo_cdevsw,
- 0,
- UID_ROOT,
- GID_WHEEL,
- 0600,
- "echo");
- /* kmalloc memory for use by this driver */
- /* malloc(256,M_ECHOBUF,M_WAITOK); */
- MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
- printf("Echo device loaded.\n");
- break;
- case MOD_UNLOAD:
- destroy_dev(sdev);
- FREE(echomsg,M_ECHOBUF);
- printf("Echo device unloaded.\n");
- break;
- default:
- err = EINVAL;
- break;
- }
- return(err);
-}
-
-int
-echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
-{
- int err = 0;
-
- uprintf("Opened device \"echo\" successfully.\n");
- return(err);
-}
-
-int
-echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
-{
- uprintf("Closing device \"echo.\"\n");
- return(0);
-}
-
-/*
- * The read function just takes the buf that was saved via
- * echo_write() and returns it to userland for accessing.
- * uio(9)
- */
-
-int
-echo_read(dev_t dev, struct uio *uio, int ioflag)
-{
- int err = 0;
- int amt;
-
- /* How big is this read operation? Either as big as the user wants,
- or as big as the remaining data */
- amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? echomsg->len - uio->uio_offset : 0);
- if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
- uprintf("uiomove failed!\n");
- }
-
- return err;
-}
-
-/*
- * echo_write takes in a character string and saves it
- * to buf for later accessing.
- */
-
-int
-echo_write(dev_t dev, struct uio *uio, int ioflag)
-{
- int err = 0;
-
- /* Copy the string in from user memory to kernel memory */
- err = copyin(uio->uio_iov->iov_base, echomsg->msg, MIN(uio->uio_iov->iov_len,BUFFERSIZE));
-
- /* Now we need to null terminate */
- *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
- /* Record the length */
- echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);
-
- if (err != 0) {
- uprintf("Write failed: bad address!\n");
- }
-
- count++;
- return(err);
-}
-
-DEV_MODULE(echo,echo_loader,NULL);
-
-
-To install this driver you will first need to make a node on
- your filesystem with a command such as :
-
- &prompt.root mknod /dev/echo c 33 0
-
-With this driver loaded you should now be able to type something
- like :
-
- &prompt.root echo -n "Test Data" > /dev/echo
- &prompt.root cat /dev/echo
- Test Data
-
- Real hardware devices in the next chapter..
-
- Additional Resources
-
- Dynamic
- Kernel Linker (KLD) Facility Programming Tutorial -
- Daemonnews October 2000
- How
- to Write Kernel Drivers with NEWBUS - Daemonnews July
- 2000
-
-
-
-
-
- Block Devices
- A block device driver transfers data to and from the
- operating system's buffer cache. They are solely intended to
- layer a file system on top of them. For this reason they are
- normally implemented for disks and disk-like devices only.
-
- Example test data generator ...
-
- Example ramdisk device ...
-
- Real hardware devices in the next chapter..
-
-
-
- Network Drivers
- Drivers for network devices do not use device nodes in
- ord to be accessed. Their selection is based on other
- decisions made inside the kernel and instead of calling
- open(), use of a network device is generally introduced by
- using the system call socket(2).
- man ifnet(), loopback device, Bill Pauls drivers, etc..
-
-
-
+ &chap.driverbasics;
PCI Devices
This chapter will talk about the FreeBSD mechanisms for
writing a device driver for a device on a PCI bus.
Probe and Attach
Information here about how the PCI bus code iterates
through the unattached devices and see if a newly loaded kld
will attach to any of them.
/*
* Simple KLD to play with the PCI functions.
*
* Murray Stokely
*/
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h> /* uprintf */
#include <sys/errno.h>
#include <sys/param.h> /* defines used in kernel.h */
#include <sys/kernel.h> /* types used in module initialization */
#include <sys/conf.h> /* cdevsw struct */
#include <sys/uio.h> /* uio struct */
#include <sys/malloc.h>
#include <sys/bus.h> /* structs, prototypes for pci bus stuff */
#include <pci/pcivar.h> /* For get_pci macros! */
/* Function prototypes */
d_open_t mypci_open;
d_close_t mypci_close;
d_read_t mypci_read;
d_write_t mypci_write;
/* Character device entry points */
static struct cdevsw mypci_cdevsw = {
mypci_open,
mypci_close,
mypci_read,
mypci_write,
noioctl,
nopoll,
nommap,
nostrategy,
"mypci",
36, /* reserved for lkms - /usr/src/sys/conf/majors */
nodump,
nopsize,
D_TTY,
-1
};
/* vars */
static dev_t sdev;
/* We're more interested in probe/attach than with
open/close/read/write at this point */
int
mypci_open(dev_t dev, int oflags, int devtype, struct proc *p)
{
int err = 0;
uprintf("Opened device \"mypci\" successfully.\n");
return(err);
}
int
mypci_close(dev_t dev, int fflag, int devtype, struct proc *p)
{
int err=0;
uprintf("Closing device \"mypci.\"\n");
return(err);
}
int
mypci_read(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
uprintf("mypci read!\n");
return err;
}
int
mypci_write(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
uprintf("mypci write!\n");
return(err);
}
/* PCI Support Functions */
/*
* Return identification string if this is device is ours.
*/
static int
mypci_probe(device_t dev)
{
uprintf("MyPCI Probe\n"
"Vendor ID : 0x%x\n"
"Device ID : 0x%x\n",pci_get_vendor(dev),pci_get_device(dev));
if (pci_get_vendor(dev) == 0x11c1) {
uprintf("We've got the Winmodem, probe successful!\n");
return 0;
}
return ENXIO;
}
/* Attach function is only called if the probe is successful */
static int
mypci_attach(device_t dev)
{
uprintf("MyPCI Attach for : deviceID : 0x%x\n",pci_get_vendor(dev));
sdev = make_dev(&mypci_cdevsw,
0,
UID_ROOT,
GID_WHEEL,
0600,
"mypci");
uprintf("Mypci device loaded.\n");
return ENXIO;
}
/* Detach device. */
static int
mypci_detach(device_t dev)
{
uprintf("Mypci detach!\n");
return 0;
}
/* Called during system shutdown after sync. */
static int
mypci_shutdown(device_t dev)
{
uprintf("Mypci shutdown!\n");
return 0;
}
/*
* Device suspend routine.
*/
static int
mypci_suspend(device_t dev)
{
uprintf("Mypci suspend!\n");
return 0;
}
/*
* Device resume routine.
*/
static int
mypci_resume(device_t dev)
{
uprintf("Mypci resume!\n");
return 0;
}
static device_method_t mypci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mypci_probe),
DEVMETHOD(device_attach, mypci_attach),
DEVMETHOD(device_detach, mypci_detach),
DEVMETHOD(device_shutdown, mypci_shutdown),
DEVMETHOD(device_suspend, mypci_suspend),
DEVMETHOD(device_resume, mypci_resume),
{ 0, 0 }
};
static driver_t mypci_driver = {
"mypci",
mypci_methods,
0,
/* sizeof(struct mypci_softc), */
};
static devclass_t mypci_devclass;
DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);
Additional Resources
PCI Special Interest
Group
PCI System Architecture, Fourth Edition by
Tom Shanley, et al.
USB Devices
This chapter will talk about the FreeBSD mechanisms for
writing a device driver for a device on a USB bus.
NewBus
This chapter will talk about the FreeBSD NewBus
architecture.
Architectures
IA-32
Talk about the architectural specifics of FreeBSD/x86.
Alpha
Talk about the architectural specifics of
FreeBSD/alpha.
Explanation of allignment errors, how to fix, how to
ignore.
Example assembly language code for FreeBSD/alpha.
IA-64
Talk about the architectural specifics of
FreeBSD/ia64.
Debugging
Truss
various descriptions on how to debug certain aspects of
the system using truss, ktrace, gdb, kgdb, etc
Compatibility Layers
Linux
Linux, SVR4, etc
Appendices
Dave
A
Patterson
John
L
Hennessy
1998Morgan Kaufmann Publishers,
Inc.
1-55860-428-6
Morgan Kaufmann Publishers, Inc.
Computer Organization and Design
The Hardware / Software Interface
1-2
W.
Richard
Stevens
1993Addison Wesley Longman,
Inc.
0-201-56317-7
Addison Wesley Longman, Inc.
Advanced Programming in the Unix Environment
1-2
Marshall
Kirk
McKusick
Keith
Bostic
Michael
J
Karels
John
S
Quarterman
1996Addison-Wesley Publishing Company,
Inc.
0-201-54979-4
Addison-Wesley Publishing Company, Inc.
The Design and Implementation of the 4.4 BSD Operating System
1-2
Aleph
One
Phrack 49; "Smashing the Stack for Fun and Profit"
Chrispin
Cowan
Calton
Pu
Dave
Maier
StackGuard; Automatic Adaptive Detection and Prevention of
Buffer-Overflow Attacks
Todd
Miller
Theo
de Raadt
strlcpy and strlcat -- consistent, safe string copy and
concatenation.
diff --git a/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.sgml b/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.sgml
new file mode 100644
index 0000000000..afee34e472
--- /dev/null
+++ b/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.sgml
@@ -0,0 +1,383 @@
+
+
+
+ Writing FreeBSD Device Drivers
+
+ This chapter was written by Murray Stokely with selections from
+ a variety of sources including the intro(4) man page by Joerg
+ Wunsch.
+
+
+ Introduction
+
+ This chapter provides a brief introduction to writing device
+ drivers for FreeBSD. A device in this context is a term used
+ mostly for hardware-related stuff that belongs to the system,
+ like disks, printers, or a graphics display with its keyboard.
+ A device driver is the software component of the operating
+ system that controls a specific device. There are also
+ so-called pseudo-devices where a device driver emulates the
+ behaviour of a device in software without any particular
+ underlying hardware. Device drivers can be compiled into the
+ system statically or loaded on demand through the dynamic
+ kernel linker facility `kld'.
+
+ Most devices in a Unix-like operating system are
+ accessed through device-nodes, sometimes also called special
+ files. These files are usually located under the directory
+ /dev in the file system hierarchy. Until
+ devfs is fully integrated into FreeBSD, each device node must
+ be created statically and independent of the existence of the
+ associated device driver. Most device nodes on the system are
+ created by running MAKEDEV.
+
+ Device drivers can roughly be broken down into three
+ categories; character (unbuffered), block (buffered), and
+ network drivers.
+
+
+
+ Dynamic Kernel Linker Facility - KLD
+ The kld interface allows system administrators to
+ dynamically add and remove functionality from a running
+ system. This allows device driver writers to load their new
+ changes into a running kernel without constantly rebooting to
+ test changes.
+
+ The kld interface is used through the following
+ administrator commands :
+
+ kldload - loads a new kernel
+ module
+ kldunload - unloads a kernel
+ module
+ kldstat - lists the currently loadded
+ modules
+
+
+
+ Skeleton Layout of a kernel module
+
+/*
+ * KLD Skeleton
+ * Inspired by Andrew Reiter's Daemonnews article
+ */
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h> /* uprintf */
+#include <sys/errno.h>
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/kernel.h> /* types used in module initialization */
+
+/*
+ * Load handler that deals with the loading and unloading of a KLD.
+ */
+
+static int
+skel_loader(struct module *m, int what, void *arg)
+{
+ int err = 0;
+
+ switch (what) {
+ case MOD_LOAD: /* kldload */
+ uprintf("Skeleton KLD loaded.\n");
+ break;
+ case MOD_UNLOAD:
+ uprintf("Skeleton KLD unloaded.\n");
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+/* Declare this module to the rest of the kernel */
+
+DECLARE_MODULE(skeleton, skel_loader, SI_SUB_KLD, SI_ORDER_ANY);
+
+
+
+
+ Makefile
+ FreeBSD provides a makefile include that you can use
+ to quickly compile your kernel addition.
+
+SRCS=skeleton.c
+KMOD=skeleton
+
+.include <bsd.kmod.mk>
+
+
+
+ Simply running make with
+ this makefile will create a file
+ skeleton.ko that can be loaded into
+ your system by typing :
+
+&prompt.root kldload -v ./skeleton.ko
+
+
+
+
+
+
+ Accessing a device driver
+ Unix provides a common set of system calls for user
+ applications to use. The upper layers of the kernel dispatch
+ these calls to the corresponding device driver when a user
+ accesses a device node. The /dev/MAKEDEV
+ script makes most of the device nodes for your system but if
+ you are doing your own driver development it may be necessary
+ to create your own device nodes with mknod
+
+
+
+ Creating static device nodes
+ The mknod command requires four
+ arguments to create a device node. You must specify the
+ name of this device node, the type of device, the major number
+ of the device, and the minor number of the device.
+
+
+
+ Dynamic device nodes
+ The device filesystem, or devfs, provides access to the
+ kernel's device namespace in the global filesystem namespace.
+ This eliminates the problems of potentially having a device
+ driver without a static device node, or a device node without
+ an installed device driver. Unfortunately, devfs is still a
+ work in progress.
+
+
+
+
+
+ Character Devices
+ A character device driver is one that transfers data
+ directly to and from a user process. This is the most common
+ type of device driver and there are plenty of simple examples
+ in the source tree.
+ This simple example pseudo-device remembers whatever values you write
+ to it and can then supply them back to you when you read from
+ it.
+
+/*
+ * Simple `echo' pseudo-device KLD
+ *
+ * Murray Stokely
+ */
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h> /* uprintf */
+#include <sys/errno.h>
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/kernel.h> /* types used in module initialization */
+#include <sys/conf.h> /* cdevsw struct */
+#include <sys/uio.h> /* uio struct */
+#include <sys/malloc.h>
+
+#define BUFFERSIZE 256
+
+/* Function prototypes */
+d_open_t echo_open;
+d_close_t echo_close;
+d_read_t echo_read;
+d_write_t echo_write;
+
+/* Character device entry points */
+static struct cdevsw echo_cdevsw = {
+ echo_open,
+ echo_close,
+ echo_read,
+ echo_write,
+ noioctl,
+ nopoll,
+ nommap,
+ nostrategy,
+ "echo",
+ 33, /* reserved for lkms - /usr/src/sys/conf/majors */
+ nodump,
+ nopsize,
+ D_TTY,
+ -1
+};
+
+typedef struct s_echo {
+ char msg[BUFFERSIZE];
+ int len;
+} t_echo;
+
+/* vars */
+static dev_t sdev;
+static int len;
+static int count;
+static t_echo *echomsg;
+
+MALLOC_DECLARE(M_ECHOBUF);
+MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
+
+/*
+ * This function acts is called by the kld[un]load(2) system calls to
+ * determine what actions to take when a module is loaded or unloaded.
+ */
+
+static int
+echo_loader(struct module *m, int what, void *arg)
+{
+ int err = 0;
+
+ switch (what) {
+ case MOD_LOAD: /* kldload */
+ sdev = make_dev(&echo_cdevsw,
+ 0,
+ UID_ROOT,
+ GID_WHEEL,
+ 0600,
+ "echo");
+ /* kmalloc memory for use by this driver */
+ /* malloc(256,M_ECHOBUF,M_WAITOK); */
+ MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
+ printf("Echo device loaded.\n");
+ break;
+ case MOD_UNLOAD:
+ destroy_dev(sdev);
+ FREE(echomsg,M_ECHOBUF);
+ printf("Echo device unloaded.\n");
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+int
+echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
+{
+ int err = 0;
+
+ uprintf("Opened device \"echo\" successfully.\n");
+ return(err);
+}
+
+int
+echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
+{
+ uprintf("Closing device \"echo.\"\n");
+ return(0);
+}
+
+/*
+ * The read function just takes the buf that was saved via
+ * echo_write() and returns it to userland for accessing.
+ * uio(9)
+ */
+
+int
+echo_read(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+ int amt;
+
+ /* How big is this read operation? Either as big as the user wants,
+ or as big as the remaining data */
+ amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? echomsg->len - uio->uio_offset : 0);
+ if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
+ uprintf("uiomove failed!\n");
+ }
+
+ return err;
+}
+
+/*
+ * echo_write takes in a character string and saves it
+ * to buf for later accessing.
+ */
+
+int
+echo_write(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+
+ /* Copy the string in from user memory to kernel memory */
+ err = copyin(uio->uio_iov->iov_base, echomsg->msg, MIN(uio->uio_iov->iov_len,BUFFERSIZE));
+
+ /* Now we need to null terminate */
+ *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
+ /* Record the length */
+ echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);
+
+ if (err != 0) {
+ uprintf("Write failed: bad address!\n");
+ }
+
+ count++;
+ return(err);
+}
+
+DEV_MODULE(echo,echo_loader,NULL);
+
+
+To install this driver you will first need to make a node on
+ your filesystem with a command such as :
+
+ &prompt.root mknod /dev/echo c 33 0
+
+With this driver loaded you should now be able to type something
+ like :
+
+ &prompt.root echo -n "Test Data" > /dev/echo
+ &prompt.root cat /dev/echo
+ Test Data
+
+ Real hardware devices in the next chapter..
+
+ Additional Resources
+
+ Dynamic
+ Kernel Linker (KLD) Facility Programming Tutorial -
+ Daemonnews October 2000
+ How
+ to Write Kernel Drivers with NEWBUS - Daemonnews July
+ 2000
+
+
+
+
+
+ Block Devices
+ A block device driver transfers data to and from the
+ operating system's buffer cache. They are solely intended to
+ layer a file system on top of them. For this reason they are
+ normally implemented for disks and disk-like devices only.
+
+ Example test data generator ...
+
+ Example ramdisk device ...
+
+ Real hardware devices in the next chapter..
+
+
+
+ Network Drivers
+ Drivers for network devices do not use device nodes in
+ ord to be accessed. Their selection is based on other
+ decisions made inside the kernel and instead of calling
+ open(), use of a network device is generally introduced by
+ using the system call socket(2).
+ man ifnet(), loopback device, Bill Pauls drivers, etc..
+
+
+
diff --git a/en_US.ISO8859-1/books/developers-handbook/book.sgml b/en_US.ISO8859-1/books/developers-handbook/book.sgml
index af9c07821e..6cbec1dd1c 100644
--- a/en_US.ISO8859-1/books/developers-handbook/book.sgml
+++ b/en_US.ISO8859-1/books/developers-handbook/book.sgml
@@ -1,1101 +1,725 @@
%bookinfo;
%chapters;
]>
FreeBSD Developers' Handbook
The FreeBSD Documentation Project
doc@FreeBSD.org
August 2000
2000
The FreeBSD Documentation Project
&bookinfo.legalnotice;
Welcome to the Developers' Handbook.
Introduction
Developing on FreeBSD
This will need to discuss FreeBSD as a development
platform, the vision of BSD, architectural overview, layout of
/usr/src, history, etc.
Thank you for considering FreeBSD as your development
platform! We hope it will not let you down.
The BSD Vision
Architectural Overview
The Layout of /usr/src
The complete source code to FreeBSD is available from our
public CVS repository. The source code is normally installed in
/usr/src which contains the
following subdirectories.
Directory
Description
bin/
Source for files in
/bin
contrib/
Source for files from contribued software.
crypto/
DES source
etc/
Source for files in /etc
games/
Source for files in /usr/games
gnu/
Utilities covered by the GNU Public License
include/
Source for files in /usr/include
kerberosIV/
Source for Kerbereros version IV
kerberos5/
Source for Kerbereros version 5
lib/
Source for files in /usr/lib
libexec/
Source for files in /usr/libexec
release/
Files required to produce a FreeBSD release
sbin/
Source for files in /sbin
secure/
FreeSec sources
share/
Source for files in /sbin
sys/
Kernel source files
tools/
Tools used for maintenance and testing of
FreeBSD
usr.bin/
Source for files in /usr/bin
usr.sbin/
Source for files in /usr/sbin
Basics
&chap.tools;
&chap.secure;
Kernel
History of the Unix Kernel
Some history of the Unix/BSD kernel, system calls, how do
processes work, blocking, scheduling, threads (kernel),
context switching, signals, interrupts, modules, etc.
Memory and Virtual Memory
Virtual Memory
VM, paging, swapping, allocating memory, testing for
memory leaks, mmap, vnodes, etc.
I/O System
UFS
UFS, FFS, Ext2FS, JFS, inodes, buffer cache, labeling,
locking, metadata, soft-updates, LFS, portalfs, procfs,
vnodes, memory sharing, memory objects, TLBs, caching
Interprocess Communication
Signals
Signals, pipes, semaphores, message queues, shared memory,
ports, sockets, doors
Networking
Sockets
Sockets, bpf, IP, TCP, UDP, ICMP, OSI, bridging,
firewalling, NAT, switching, etc
Network Filesystems
AFS
AFS, NFS, SANs etc]
Terminal Handling
Syscons
Syscons, tty, PCVT, serial console, screen savers,
etc
Sound
OSS
OSS, waveforms, etc
Device Drivers
-
- Writing FreeBSD Device Drivers
-
- This chapter was written by Murray Stokely with selections from
- a variety of sources including the intro(4) man page by Joerg
- Wunsch.
-
-
- Introduction
-
- This chapter provides a brief introduction to writing device
- drivers for FreeBSD. A device in this context is a term used
- mostly for hardware-related stuff that belongs to the system,
- like disks, printers, or a graphics display with its keyboard.
- A device driver is the software component of the operating
- system that controls a specific device. There are also
- so-called pseudo-devices where a device driver emulates the
- behaviour of a device in software without any particular
- underlying hardware. Device drivers can be compiled into the
- system statically or loaded on demand through the dynamic
- kernel linker facility `kld'.
-
- Most devices in a Unix-like operating system are
- accessed through device-nodes, sometimes also called special
- files. These files are usually located under the directory
- /dev in the file system hierarchy. Until
- devfs is fully integrated into FreeBSD, each device node must
- be created statically and independent of the existence of the
- associated device driver. Most device nodes on the system are
- created by running MAKEDEV.
-
- Device drivers can roughly be broken down into three
- categories; character (unbuffered), block (buffered), and
- network drivers.
-
-
-
- Dynamic Kernel Linker Facility - KLD
- The kld interface allows system administrators to
- dynamically add and remove functionality from a running
- system. This allows device driver writers to load their new
- changes into a running kernel without constantly rebooting to
- test changes.
-
- The kld interface is used through the following
- administrator commands :
-
- kldload - loads a new kernel
- module
- kldunload - unloads a kernel
- module
- kldstat - lists the currently loadded
- modules
-
-
-
- Skeleton Layout of a kernel module
-
-/*
- * KLD Skeleton
- * Inspired by Andrew Reiter's Daemonnews article
- */
-
-#include <sys/types.h>
-#include <sys/module.h>
-#include <sys/systm.h> /* uprintf */
-#include <sys/errno.h>
-#include <sys/param.h> /* defines used in kernel.h */
-#include <sys/kernel.h> /* types used in module initialization */
-
-/*
- * Load handler that deals with the loading and unloading of a KLD.
- */
-
-static int
-skel_loader(struct module *m, int what, void *arg)
-{
- int err = 0;
-
- switch (what) {
- case MOD_LOAD: /* kldload */
- uprintf("Skeleton KLD loaded.\n");
- break;
- case MOD_UNLOAD:
- uprintf("Skeleton KLD unloaded.\n");
- break;
- default:
- err = EINVAL;
- break;
- }
- return(err);
-}
-
-/* Declare this module to the rest of the kernel */
-
-DECLARE_MODULE(skeleton, skel_loader, SI_SUB_KLD, SI_ORDER_ANY);
-
-
-
-
- Makefile
- FreeBSD provides a makefile include that you can use
- to quickly compile your kernel addition.
-
-SRCS=skeleton.c
-KMOD=skeleton
-
-.include <bsd.kmod.mk>
-
-
-
- Simply running make with
- this makefile will create a file
- skeleton.ko that can be loaded into
- your system by typing :
-
-&prompt.root kldload -v ./skeleton.ko
-
-
-
-
-
-
- Accessing a device driver
- Unix provides a common set of system calls for user
- applications to use. The upper layers of the kernel dispatch
- these calls to the corresponding device driver when a user
- accesses a device node. The /dev/MAKEDEV
- script makes most of the device nodes for your system but if
- you are doing your own driver development it may be necessary
- to create your own device nodes with mknod
-
-
-
- Creating static device nodes
- The mknod command requires four
- arguments to create a device node. You must specify the
- name of this device node, the type of device, the major number
- of the device, and the minor number of the device.
-
-
-
- Dynamic device nodes
- The device filesystem, or devfs, provides access to the
- kernel's device namespace in the global filesystem namespace.
- This eliminates the problems of potentially having a device
- driver without a static device node, or a device node without
- an installed device driver. Unfortunately, devfs is still a
- work in progress.
-
-
-
-
-
- Character Devices
- A character device driver is one that transfers data
- directly to and from a user process. This is the most common
- type of device driver and there are plenty of simple examples
- in the source tree.
- This simple example pseudo-device remembers whatever values you write
- to it and can then supply them back to you when you read from
- it.
-
-/*
- * Simple `echo' pseudo-device KLD
- *
- * Murray Stokely
- */
-
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-
-#include <sys/types.h>
-#include <sys/module.h>
-#include <sys/systm.h> /* uprintf */
-#include <sys/errno.h>
-#include <sys/param.h> /* defines used in kernel.h */
-#include <sys/kernel.h> /* types used in module initialization */
-#include <sys/conf.h> /* cdevsw struct */
-#include <sys/uio.h> /* uio struct */
-#include <sys/malloc.h>
-
-#define BUFFERSIZE 256
-
-/* Function prototypes */
-d_open_t echo_open;
-d_close_t echo_close;
-d_read_t echo_read;
-d_write_t echo_write;
-
-/* Character device entry points */
-static struct cdevsw echo_cdevsw = {
- echo_open,
- echo_close,
- echo_read,
- echo_write,
- noioctl,
- nopoll,
- nommap,
- nostrategy,
- "echo",
- 33, /* reserved for lkms - /usr/src/sys/conf/majors */
- nodump,
- nopsize,
- D_TTY,
- -1
-};
-
-typedef struct s_echo {
- char msg[BUFFERSIZE];
- int len;
-} t_echo;
-
-/* vars */
-static dev_t sdev;
-static int len;
-static int count;
-static t_echo *echomsg;
-
-MALLOC_DECLARE(M_ECHOBUF);
-MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
-
-/*
- * This function acts is called by the kld[un]load(2) system calls to
- * determine what actions to take when a module is loaded or unloaded.
- */
-
-static int
-echo_loader(struct module *m, int what, void *arg)
-{
- int err = 0;
-
- switch (what) {
- case MOD_LOAD: /* kldload */
- sdev = make_dev(&echo_cdevsw,
- 0,
- UID_ROOT,
- GID_WHEEL,
- 0600,
- "echo");
- /* kmalloc memory for use by this driver */
- /* malloc(256,M_ECHOBUF,M_WAITOK); */
- MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
- printf("Echo device loaded.\n");
- break;
- case MOD_UNLOAD:
- destroy_dev(sdev);
- FREE(echomsg,M_ECHOBUF);
- printf("Echo device unloaded.\n");
- break;
- default:
- err = EINVAL;
- break;
- }
- return(err);
-}
-
-int
-echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
-{
- int err = 0;
-
- uprintf("Opened device \"echo\" successfully.\n");
- return(err);
-}
-
-int
-echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
-{
- uprintf("Closing device \"echo.\"\n");
- return(0);
-}
-
-/*
- * The read function just takes the buf that was saved via
- * echo_write() and returns it to userland for accessing.
- * uio(9)
- */
-
-int
-echo_read(dev_t dev, struct uio *uio, int ioflag)
-{
- int err = 0;
- int amt;
-
- /* How big is this read operation? Either as big as the user wants,
- or as big as the remaining data */
- amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? echomsg->len - uio->uio_offset : 0);
- if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
- uprintf("uiomove failed!\n");
- }
-
- return err;
-}
-
-/*
- * echo_write takes in a character string and saves it
- * to buf for later accessing.
- */
-
-int
-echo_write(dev_t dev, struct uio *uio, int ioflag)
-{
- int err = 0;
-
- /* Copy the string in from user memory to kernel memory */
- err = copyin(uio->uio_iov->iov_base, echomsg->msg, MIN(uio->uio_iov->iov_len,BUFFERSIZE));
-
- /* Now we need to null terminate */
- *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
- /* Record the length */
- echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);
-
- if (err != 0) {
- uprintf("Write failed: bad address!\n");
- }
-
- count++;
- return(err);
-}
-
-DEV_MODULE(echo,echo_loader,NULL);
-
-
-To install this driver you will first need to make a node on
- your filesystem with a command such as :
-
- &prompt.root mknod /dev/echo c 33 0
-
-With this driver loaded you should now be able to type something
- like :
-
- &prompt.root echo -n "Test Data" > /dev/echo
- &prompt.root cat /dev/echo
- Test Data
-
- Real hardware devices in the next chapter..
-
- Additional Resources
-
- Dynamic
- Kernel Linker (KLD) Facility Programming Tutorial -
- Daemonnews October 2000
- How
- to Write Kernel Drivers with NEWBUS - Daemonnews July
- 2000
-
-
-
-
-
- Block Devices
- A block device driver transfers data to and from the
- operating system's buffer cache. They are solely intended to
- layer a file system on top of them. For this reason they are
- normally implemented for disks and disk-like devices only.
-
- Example test data generator ...
-
- Example ramdisk device ...
-
- Real hardware devices in the next chapter..
-
-
-
- Network Drivers
- Drivers for network devices do not use device nodes in
- ord to be accessed. Their selection is based on other
- decisions made inside the kernel and instead of calling
- open(), use of a network device is generally introduced by
- using the system call socket(2).
- man ifnet(), loopback device, Bill Pauls drivers, etc..
-
-
-
+ &chap.driverbasics;
PCI Devices
This chapter will talk about the FreeBSD mechanisms for
writing a device driver for a device on a PCI bus.
Probe and Attach
Information here about how the PCI bus code iterates
through the unattached devices and see if a newly loaded kld
will attach to any of them.
/*
* Simple KLD to play with the PCI functions.
*
* Murray Stokely
*/
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h> /* uprintf */
#include <sys/errno.h>
#include <sys/param.h> /* defines used in kernel.h */
#include <sys/kernel.h> /* types used in module initialization */
#include <sys/conf.h> /* cdevsw struct */
#include <sys/uio.h> /* uio struct */
#include <sys/malloc.h>
#include <sys/bus.h> /* structs, prototypes for pci bus stuff */
#include <pci/pcivar.h> /* For get_pci macros! */
/* Function prototypes */
d_open_t mypci_open;
d_close_t mypci_close;
d_read_t mypci_read;
d_write_t mypci_write;
/* Character device entry points */
static struct cdevsw mypci_cdevsw = {
mypci_open,
mypci_close,
mypci_read,
mypci_write,
noioctl,
nopoll,
nommap,
nostrategy,
"mypci",
36, /* reserved for lkms - /usr/src/sys/conf/majors */
nodump,
nopsize,
D_TTY,
-1
};
/* vars */
static dev_t sdev;
/* We're more interested in probe/attach than with
open/close/read/write at this point */
int
mypci_open(dev_t dev, int oflags, int devtype, struct proc *p)
{
int err = 0;
uprintf("Opened device \"mypci\" successfully.\n");
return(err);
}
int
mypci_close(dev_t dev, int fflag, int devtype, struct proc *p)
{
int err=0;
uprintf("Closing device \"mypci.\"\n");
return(err);
}
int
mypci_read(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
uprintf("mypci read!\n");
return err;
}
int
mypci_write(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
uprintf("mypci write!\n");
return(err);
}
/* PCI Support Functions */
/*
* Return identification string if this is device is ours.
*/
static int
mypci_probe(device_t dev)
{
uprintf("MyPCI Probe\n"
"Vendor ID : 0x%x\n"
"Device ID : 0x%x\n",pci_get_vendor(dev),pci_get_device(dev));
if (pci_get_vendor(dev) == 0x11c1) {
uprintf("We've got the Winmodem, probe successful!\n");
return 0;
}
return ENXIO;
}
/* Attach function is only called if the probe is successful */
static int
mypci_attach(device_t dev)
{
uprintf("MyPCI Attach for : deviceID : 0x%x\n",pci_get_vendor(dev));
sdev = make_dev(&mypci_cdevsw,
0,
UID_ROOT,
GID_WHEEL,
0600,
"mypci");
uprintf("Mypci device loaded.\n");
return ENXIO;
}
/* Detach device. */
static int
mypci_detach(device_t dev)
{
uprintf("Mypci detach!\n");
return 0;
}
/* Called during system shutdown after sync. */
static int
mypci_shutdown(device_t dev)
{
uprintf("Mypci shutdown!\n");
return 0;
}
/*
* Device suspend routine.
*/
static int
mypci_suspend(device_t dev)
{
uprintf("Mypci suspend!\n");
return 0;
}
/*
* Device resume routine.
*/
static int
mypci_resume(device_t dev)
{
uprintf("Mypci resume!\n");
return 0;
}
static device_method_t mypci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mypci_probe),
DEVMETHOD(device_attach, mypci_attach),
DEVMETHOD(device_detach, mypci_detach),
DEVMETHOD(device_shutdown, mypci_shutdown),
DEVMETHOD(device_suspend, mypci_suspend),
DEVMETHOD(device_resume, mypci_resume),
{ 0, 0 }
};
static driver_t mypci_driver = {
"mypci",
mypci_methods,
0,
/* sizeof(struct mypci_softc), */
};
static devclass_t mypci_devclass;
DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);
Additional Resources
PCI Special Interest
Group
PCI System Architecture, Fourth Edition by
Tom Shanley, et al.
USB Devices
This chapter will talk about the FreeBSD mechanisms for
writing a device driver for a device on a USB bus.
NewBus
This chapter will talk about the FreeBSD NewBus
architecture.
Architectures
IA-32
Talk about the architectural specifics of FreeBSD/x86.
Alpha
Talk about the architectural specifics of
FreeBSD/alpha.
Explanation of allignment errors, how to fix, how to
ignore.
Example assembly language code for FreeBSD/alpha.
IA-64
Talk about the architectural specifics of
FreeBSD/ia64.
Debugging
Truss
various descriptions on how to debug certain aspects of
the system using truss, ktrace, gdb, kgdb, etc
Compatibility Layers
Linux
Linux, SVR4, etc
Appendices
Dave
A
Patterson
John
L
Hennessy
1998Morgan Kaufmann Publishers,
Inc.
1-55860-428-6
Morgan Kaufmann Publishers, Inc.
Computer Organization and Design
The Hardware / Software Interface
1-2
W.
Richard
Stevens
1993Addison Wesley Longman,
Inc.
0-201-56317-7
Addison Wesley Longman, Inc.
Advanced Programming in the Unix Environment
1-2
Marshall
Kirk
McKusick
Keith
Bostic
Michael
J
Karels
John
S
Quarterman
1996Addison-Wesley Publishing Company,
Inc.
0-201-54979-4
Addison-Wesley Publishing Company, Inc.
The Design and Implementation of the 4.4 BSD Operating System
1-2
Aleph
One
Phrack 49; "Smashing the Stack for Fun and Profit"
Chrispin
Cowan
Calton
Pu
Dave
Maier
StackGuard; Automatic Adaptive Detection and Prevention of
Buffer-Overflow Attacks
Todd
Miller
Theo
de Raadt
strlcpy and strlcat -- consistent, safe string copy and
concatenation.
diff --git a/en_US.ISO8859-1/books/developers-handbook/driverbasics/chapter.sgml b/en_US.ISO8859-1/books/developers-handbook/driverbasics/chapter.sgml
new file mode 100644
index 0000000000..afee34e472
--- /dev/null
+++ b/en_US.ISO8859-1/books/developers-handbook/driverbasics/chapter.sgml
@@ -0,0 +1,383 @@
+
+
+
+ Writing FreeBSD Device Drivers
+
+ This chapter was written by Murray Stokely with selections from
+ a variety of sources including the intro(4) man page by Joerg
+ Wunsch.
+
+
+ Introduction
+
+ This chapter provides a brief introduction to writing device
+ drivers for FreeBSD. A device in this context is a term used
+ mostly for hardware-related stuff that belongs to the system,
+ like disks, printers, or a graphics display with its keyboard.
+ A device driver is the software component of the operating
+ system that controls a specific device. There are also
+ so-called pseudo-devices where a device driver emulates the
+ behaviour of a device in software without any particular
+ underlying hardware. Device drivers can be compiled into the
+ system statically or loaded on demand through the dynamic
+ kernel linker facility `kld'.
+
+ Most devices in a Unix-like operating system are
+ accessed through device-nodes, sometimes also called special
+ files. These files are usually located under the directory
+ /dev in the file system hierarchy. Until
+ devfs is fully integrated into FreeBSD, each device node must
+ be created statically and independent of the existence of the
+ associated device driver. Most device nodes on the system are
+ created by running MAKEDEV.
+
+ Device drivers can roughly be broken down into three
+ categories; character (unbuffered), block (buffered), and
+ network drivers.
+
+
+
+ Dynamic Kernel Linker Facility - KLD
+ The kld interface allows system administrators to
+ dynamically add and remove functionality from a running
+ system. This allows device driver writers to load their new
+ changes into a running kernel without constantly rebooting to
+ test changes.
+
+ The kld interface is used through the following
+ administrator commands :
+
+ kldload - loads a new kernel
+ module
+ kldunload - unloads a kernel
+ module
+ kldstat - lists the currently loadded
+ modules
+
+
+
+ Skeleton Layout of a kernel module
+
+/*
+ * KLD Skeleton
+ * Inspired by Andrew Reiter's Daemonnews article
+ */
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h> /* uprintf */
+#include <sys/errno.h>
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/kernel.h> /* types used in module initialization */
+
+/*
+ * Load handler that deals with the loading and unloading of a KLD.
+ */
+
+static int
+skel_loader(struct module *m, int what, void *arg)
+{
+ int err = 0;
+
+ switch (what) {
+ case MOD_LOAD: /* kldload */
+ uprintf("Skeleton KLD loaded.\n");
+ break;
+ case MOD_UNLOAD:
+ uprintf("Skeleton KLD unloaded.\n");
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+/* Declare this module to the rest of the kernel */
+
+DECLARE_MODULE(skeleton, skel_loader, SI_SUB_KLD, SI_ORDER_ANY);
+
+
+
+
+ Makefile
+ FreeBSD provides a makefile include that you can use
+ to quickly compile your kernel addition.
+
+SRCS=skeleton.c
+KMOD=skeleton
+
+.include <bsd.kmod.mk>
+
+
+
+ Simply running make with
+ this makefile will create a file
+ skeleton.ko that can be loaded into
+ your system by typing :
+
+&prompt.root kldload -v ./skeleton.ko
+
+
+
+
+
+
+ Accessing a device driver
+ Unix provides a common set of system calls for user
+ applications to use. The upper layers of the kernel dispatch
+ these calls to the corresponding device driver when a user
+ accesses a device node. The /dev/MAKEDEV
+ script makes most of the device nodes for your system but if
+ you are doing your own driver development it may be necessary
+ to create your own device nodes with mknod
+
+
+
+ Creating static device nodes
+ The mknod command requires four
+ arguments to create a device node. You must specify the
+ name of this device node, the type of device, the major number
+ of the device, and the minor number of the device.
+
+
+
+ Dynamic device nodes
+ The device filesystem, or devfs, provides access to the
+ kernel's device namespace in the global filesystem namespace.
+ This eliminates the problems of potentially having a device
+ driver without a static device node, or a device node without
+ an installed device driver. Unfortunately, devfs is still a
+ work in progress.
+
+
+
+
+
+ Character Devices
+ A character device driver is one that transfers data
+ directly to and from a user process. This is the most common
+ type of device driver and there are plenty of simple examples
+ in the source tree.
+ This simple example pseudo-device remembers whatever values you write
+ to it and can then supply them back to you when you read from
+ it.
+
+/*
+ * Simple `echo' pseudo-device KLD
+ *
+ * Murray Stokely
+ */
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h> /* uprintf */
+#include <sys/errno.h>
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/kernel.h> /* types used in module initialization */
+#include <sys/conf.h> /* cdevsw struct */
+#include <sys/uio.h> /* uio struct */
+#include <sys/malloc.h>
+
+#define BUFFERSIZE 256
+
+/* Function prototypes */
+d_open_t echo_open;
+d_close_t echo_close;
+d_read_t echo_read;
+d_write_t echo_write;
+
+/* Character device entry points */
+static struct cdevsw echo_cdevsw = {
+ echo_open,
+ echo_close,
+ echo_read,
+ echo_write,
+ noioctl,
+ nopoll,
+ nommap,
+ nostrategy,
+ "echo",
+ 33, /* reserved for lkms - /usr/src/sys/conf/majors */
+ nodump,
+ nopsize,
+ D_TTY,
+ -1
+};
+
+typedef struct s_echo {
+ char msg[BUFFERSIZE];
+ int len;
+} t_echo;
+
+/* vars */
+static dev_t sdev;
+static int len;
+static int count;
+static t_echo *echomsg;
+
+MALLOC_DECLARE(M_ECHOBUF);
+MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
+
+/*
+ * This function acts is called by the kld[un]load(2) system calls to
+ * determine what actions to take when a module is loaded or unloaded.
+ */
+
+static int
+echo_loader(struct module *m, int what, void *arg)
+{
+ int err = 0;
+
+ switch (what) {
+ case MOD_LOAD: /* kldload */
+ sdev = make_dev(&echo_cdevsw,
+ 0,
+ UID_ROOT,
+ GID_WHEEL,
+ 0600,
+ "echo");
+ /* kmalloc memory for use by this driver */
+ /* malloc(256,M_ECHOBUF,M_WAITOK); */
+ MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
+ printf("Echo device loaded.\n");
+ break;
+ case MOD_UNLOAD:
+ destroy_dev(sdev);
+ FREE(echomsg,M_ECHOBUF);
+ printf("Echo device unloaded.\n");
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+int
+echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
+{
+ int err = 0;
+
+ uprintf("Opened device \"echo\" successfully.\n");
+ return(err);
+}
+
+int
+echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
+{
+ uprintf("Closing device \"echo.\"\n");
+ return(0);
+}
+
+/*
+ * The read function just takes the buf that was saved via
+ * echo_write() and returns it to userland for accessing.
+ * uio(9)
+ */
+
+int
+echo_read(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+ int amt;
+
+ /* How big is this read operation? Either as big as the user wants,
+ or as big as the remaining data */
+ amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? echomsg->len - uio->uio_offset : 0);
+ if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
+ uprintf("uiomove failed!\n");
+ }
+
+ return err;
+}
+
+/*
+ * echo_write takes in a character string and saves it
+ * to buf for later accessing.
+ */
+
+int
+echo_write(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+
+ /* Copy the string in from user memory to kernel memory */
+ err = copyin(uio->uio_iov->iov_base, echomsg->msg, MIN(uio->uio_iov->iov_len,BUFFERSIZE));
+
+ /* Now we need to null terminate */
+ *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
+ /* Record the length */
+ echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);
+
+ if (err != 0) {
+ uprintf("Write failed: bad address!\n");
+ }
+
+ count++;
+ return(err);
+}
+
+DEV_MODULE(echo,echo_loader,NULL);
+
+
+To install this driver you will first need to make a node on
+ your filesystem with a command such as :
+
+ &prompt.root mknod /dev/echo c 33 0
+
+With this driver loaded you should now be able to type something
+ like :
+
+ &prompt.root echo -n "Test Data" > /dev/echo
+ &prompt.root cat /dev/echo
+ Test Data
+
+ Real hardware devices in the next chapter..
+
+ Additional Resources
+
+ Dynamic
+ Kernel Linker (KLD) Facility Programming Tutorial -
+ Daemonnews October 2000
+ How
+ to Write Kernel Drivers with NEWBUS - Daemonnews July
+ 2000
+
+
+
+
+
+ Block Devices
+ A block device driver transfers data to and from the
+ operating system's buffer cache. They are solely intended to
+ layer a file system on top of them. For this reason they are
+ normally implemented for disks and disk-like devices only.
+
+ Example test data generator ...
+
+ Example ramdisk device ...
+
+ Real hardware devices in the next chapter..
+
+
+
+ Network Drivers
+ Drivers for network devices do not use device nodes in
+ ord to be accessed. Their selection is based on other
+ decisions made inside the kernel and instead of calling
+ open(), use of a network device is generally introduced by
+ using the system call socket(2).
+ man ifnet(), loopback device, Bill Pauls drivers, etc..
+
+
+
diff --git a/en_US.ISO_8859-1/books/developers-handbook/book.sgml b/en_US.ISO_8859-1/books/developers-handbook/book.sgml
index af9c07821e..6cbec1dd1c 100644
--- a/en_US.ISO_8859-1/books/developers-handbook/book.sgml
+++ b/en_US.ISO_8859-1/books/developers-handbook/book.sgml
@@ -1,1101 +1,725 @@
%bookinfo;
%chapters;
]>
FreeBSD Developers' Handbook
The FreeBSD Documentation Project
doc@FreeBSD.org
August 2000
2000
The FreeBSD Documentation Project
&bookinfo.legalnotice;
Welcome to the Developers' Handbook.
Introduction
Developing on FreeBSD
This will need to discuss FreeBSD as a development
platform, the vision of BSD, architectural overview, layout of
/usr/src, history, etc.
Thank you for considering FreeBSD as your development
platform! We hope it will not let you down.
The BSD Vision
Architectural Overview
The Layout of /usr/src
The complete source code to FreeBSD is available from our
public CVS repository. The source code is normally installed in
/usr/src which contains the
following subdirectories.
Directory
Description
bin/
Source for files in
/bin
contrib/
Source for files from contribued software.
crypto/
DES source
etc/
Source for files in /etc
games/
Source for files in /usr/games
gnu/
Utilities covered by the GNU Public License
include/
Source for files in /usr/include
kerberosIV/
Source for Kerbereros version IV
kerberos5/
Source for Kerbereros version 5
lib/
Source for files in /usr/lib
libexec/
Source for files in /usr/libexec
release/
Files required to produce a FreeBSD release
sbin/
Source for files in /sbin
secure/
FreeSec sources
share/
Source for files in /sbin
sys/
Kernel source files
tools/
Tools used for maintenance and testing of
FreeBSD
usr.bin/
Source for files in /usr/bin
usr.sbin/
Source for files in /usr/sbin
Basics
&chap.tools;
&chap.secure;
Kernel
History of the Unix Kernel
Some history of the Unix/BSD kernel, system calls, how do
processes work, blocking, scheduling, threads (kernel),
context switching, signals, interrupts, modules, etc.
Memory and Virtual Memory
Virtual Memory
VM, paging, swapping, allocating memory, testing for
memory leaks, mmap, vnodes, etc.
I/O System
UFS
UFS, FFS, Ext2FS, JFS, inodes, buffer cache, labeling,
locking, metadata, soft-updates, LFS, portalfs, procfs,
vnodes, memory sharing, memory objects, TLBs, caching
Interprocess Communication
Signals
Signals, pipes, semaphores, message queues, shared memory,
ports, sockets, doors
Networking
Sockets
Sockets, bpf, IP, TCP, UDP, ICMP, OSI, bridging,
firewalling, NAT, switching, etc
Network Filesystems
AFS
AFS, NFS, SANs etc]
Terminal Handling
Syscons
Syscons, tty, PCVT, serial console, screen savers,
etc
Sound
OSS
OSS, waveforms, etc
Device Drivers
-
- Writing FreeBSD Device Drivers
-
- This chapter was written by Murray Stokely with selections from
- a variety of sources including the intro(4) man page by Joerg
- Wunsch.
-
-
- Introduction
-
- This chapter provides a brief introduction to writing device
- drivers for FreeBSD. A device in this context is a term used
- mostly for hardware-related stuff that belongs to the system,
- like disks, printers, or a graphics display with its keyboard.
- A device driver is the software component of the operating
- system that controls a specific device. There are also
- so-called pseudo-devices where a device driver emulates the
- behaviour of a device in software without any particular
- underlying hardware. Device drivers can be compiled into the
- system statically or loaded on demand through the dynamic
- kernel linker facility `kld'.
-
- Most devices in a Unix-like operating system are
- accessed through device-nodes, sometimes also called special
- files. These files are usually located under the directory
- /dev in the file system hierarchy. Until
- devfs is fully integrated into FreeBSD, each device node must
- be created statically and independent of the existence of the
- associated device driver. Most device nodes on the system are
- created by running MAKEDEV.
-
- Device drivers can roughly be broken down into three
- categories; character (unbuffered), block (buffered), and
- network drivers.
-
-
-
- Dynamic Kernel Linker Facility - KLD
- The kld interface allows system administrators to
- dynamically add and remove functionality from a running
- system. This allows device driver writers to load their new
- changes into a running kernel without constantly rebooting to
- test changes.
-
- The kld interface is used through the following
- administrator commands :
-
- kldload - loads a new kernel
- module
- kldunload - unloads a kernel
- module
- kldstat - lists the currently loadded
- modules
-
-
-
- Skeleton Layout of a kernel module
-
-/*
- * KLD Skeleton
- * Inspired by Andrew Reiter's Daemonnews article
- */
-
-#include <sys/types.h>
-#include <sys/module.h>
-#include <sys/systm.h> /* uprintf */
-#include <sys/errno.h>
-#include <sys/param.h> /* defines used in kernel.h */
-#include <sys/kernel.h> /* types used in module initialization */
-
-/*
- * Load handler that deals with the loading and unloading of a KLD.
- */
-
-static int
-skel_loader(struct module *m, int what, void *arg)
-{
- int err = 0;
-
- switch (what) {
- case MOD_LOAD: /* kldload */
- uprintf("Skeleton KLD loaded.\n");
- break;
- case MOD_UNLOAD:
- uprintf("Skeleton KLD unloaded.\n");
- break;
- default:
- err = EINVAL;
- break;
- }
- return(err);
-}
-
-/* Declare this module to the rest of the kernel */
-
-DECLARE_MODULE(skeleton, skel_loader, SI_SUB_KLD, SI_ORDER_ANY);
-
-
-
-
- Makefile
- FreeBSD provides a makefile include that you can use
- to quickly compile your kernel addition.
-
-SRCS=skeleton.c
-KMOD=skeleton
-
-.include <bsd.kmod.mk>
-
-
-
- Simply running make with
- this makefile will create a file
- skeleton.ko that can be loaded into
- your system by typing :
-
-&prompt.root kldload -v ./skeleton.ko
-
-
-
-
-
-
- Accessing a device driver
- Unix provides a common set of system calls for user
- applications to use. The upper layers of the kernel dispatch
- these calls to the corresponding device driver when a user
- accesses a device node. The /dev/MAKEDEV
- script makes most of the device nodes for your system but if
- you are doing your own driver development it may be necessary
- to create your own device nodes with mknod
-
-
-
- Creating static device nodes
- The mknod command requires four
- arguments to create a device node. You must specify the
- name of this device node, the type of device, the major number
- of the device, and the minor number of the device.
-
-
-
- Dynamic device nodes
- The device filesystem, or devfs, provides access to the
- kernel's device namespace in the global filesystem namespace.
- This eliminates the problems of potentially having a device
- driver without a static device node, or a device node without
- an installed device driver. Unfortunately, devfs is still a
- work in progress.
-
-
-
-
-
- Character Devices
- A character device driver is one that transfers data
- directly to and from a user process. This is the most common
- type of device driver and there are plenty of simple examples
- in the source tree.
- This simple example pseudo-device remembers whatever values you write
- to it and can then supply them back to you when you read from
- it.
-
-/*
- * Simple `echo' pseudo-device KLD
- *
- * Murray Stokely
- */
-
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-
-#include <sys/types.h>
-#include <sys/module.h>
-#include <sys/systm.h> /* uprintf */
-#include <sys/errno.h>
-#include <sys/param.h> /* defines used in kernel.h */
-#include <sys/kernel.h> /* types used in module initialization */
-#include <sys/conf.h> /* cdevsw struct */
-#include <sys/uio.h> /* uio struct */
-#include <sys/malloc.h>
-
-#define BUFFERSIZE 256
-
-/* Function prototypes */
-d_open_t echo_open;
-d_close_t echo_close;
-d_read_t echo_read;
-d_write_t echo_write;
-
-/* Character device entry points */
-static struct cdevsw echo_cdevsw = {
- echo_open,
- echo_close,
- echo_read,
- echo_write,
- noioctl,
- nopoll,
- nommap,
- nostrategy,
- "echo",
- 33, /* reserved for lkms - /usr/src/sys/conf/majors */
- nodump,
- nopsize,
- D_TTY,
- -1
-};
-
-typedef struct s_echo {
- char msg[BUFFERSIZE];
- int len;
-} t_echo;
-
-/* vars */
-static dev_t sdev;
-static int len;
-static int count;
-static t_echo *echomsg;
-
-MALLOC_DECLARE(M_ECHOBUF);
-MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
-
-/*
- * This function acts is called by the kld[un]load(2) system calls to
- * determine what actions to take when a module is loaded or unloaded.
- */
-
-static int
-echo_loader(struct module *m, int what, void *arg)
-{
- int err = 0;
-
- switch (what) {
- case MOD_LOAD: /* kldload */
- sdev = make_dev(&echo_cdevsw,
- 0,
- UID_ROOT,
- GID_WHEEL,
- 0600,
- "echo");
- /* kmalloc memory for use by this driver */
- /* malloc(256,M_ECHOBUF,M_WAITOK); */
- MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
- printf("Echo device loaded.\n");
- break;
- case MOD_UNLOAD:
- destroy_dev(sdev);
- FREE(echomsg,M_ECHOBUF);
- printf("Echo device unloaded.\n");
- break;
- default:
- err = EINVAL;
- break;
- }
- return(err);
-}
-
-int
-echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
-{
- int err = 0;
-
- uprintf("Opened device \"echo\" successfully.\n");
- return(err);
-}
-
-int
-echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
-{
- uprintf("Closing device \"echo.\"\n");
- return(0);
-}
-
-/*
- * The read function just takes the buf that was saved via
- * echo_write() and returns it to userland for accessing.
- * uio(9)
- */
-
-int
-echo_read(dev_t dev, struct uio *uio, int ioflag)
-{
- int err = 0;
- int amt;
-
- /* How big is this read operation? Either as big as the user wants,
- or as big as the remaining data */
- amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? echomsg->len - uio->uio_offset : 0);
- if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
- uprintf("uiomove failed!\n");
- }
-
- return err;
-}
-
-/*
- * echo_write takes in a character string and saves it
- * to buf for later accessing.
- */
-
-int
-echo_write(dev_t dev, struct uio *uio, int ioflag)
-{
- int err = 0;
-
- /* Copy the string in from user memory to kernel memory */
- err = copyin(uio->uio_iov->iov_base, echomsg->msg, MIN(uio->uio_iov->iov_len,BUFFERSIZE));
-
- /* Now we need to null terminate */
- *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
- /* Record the length */
- echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);
-
- if (err != 0) {
- uprintf("Write failed: bad address!\n");
- }
-
- count++;
- return(err);
-}
-
-DEV_MODULE(echo,echo_loader,NULL);
-
-
-To install this driver you will first need to make a node on
- your filesystem with a command such as :
-
- &prompt.root mknod /dev/echo c 33 0
-
-With this driver loaded you should now be able to type something
- like :
-
- &prompt.root echo -n "Test Data" > /dev/echo
- &prompt.root cat /dev/echo
- Test Data
-
- Real hardware devices in the next chapter..
-
- Additional Resources
-
- Dynamic
- Kernel Linker (KLD) Facility Programming Tutorial -
- Daemonnews October 2000
- How
- to Write Kernel Drivers with NEWBUS - Daemonnews July
- 2000
-
-
-
-
-
- Block Devices
- A block device driver transfers data to and from the
- operating system's buffer cache. They are solely intended to
- layer a file system on top of them. For this reason they are
- normally implemented for disks and disk-like devices only.
-
- Example test data generator ...
-
- Example ramdisk device ...
-
- Real hardware devices in the next chapter..
-
-
-
- Network Drivers
- Drivers for network devices do not use device nodes in
- ord to be accessed. Their selection is based on other
- decisions made inside the kernel and instead of calling
- open(), use of a network device is generally introduced by
- using the system call socket(2).
- man ifnet(), loopback device, Bill Pauls drivers, etc..
-
-
-
+ &chap.driverbasics;
PCI Devices
This chapter will talk about the FreeBSD mechanisms for
writing a device driver for a device on a PCI bus.
Probe and Attach
Information here about how the PCI bus code iterates
through the unattached devices and see if a newly loaded kld
will attach to any of them.
/*
* Simple KLD to play with the PCI functions.
*
* Murray Stokely
*/
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h> /* uprintf */
#include <sys/errno.h>
#include <sys/param.h> /* defines used in kernel.h */
#include <sys/kernel.h> /* types used in module initialization */
#include <sys/conf.h> /* cdevsw struct */
#include <sys/uio.h> /* uio struct */
#include <sys/malloc.h>
#include <sys/bus.h> /* structs, prototypes for pci bus stuff */
#include <pci/pcivar.h> /* For get_pci macros! */
/* Function prototypes */
d_open_t mypci_open;
d_close_t mypci_close;
d_read_t mypci_read;
d_write_t mypci_write;
/* Character device entry points */
static struct cdevsw mypci_cdevsw = {
mypci_open,
mypci_close,
mypci_read,
mypci_write,
noioctl,
nopoll,
nommap,
nostrategy,
"mypci",
36, /* reserved for lkms - /usr/src/sys/conf/majors */
nodump,
nopsize,
D_TTY,
-1
};
/* vars */
static dev_t sdev;
/* We're more interested in probe/attach than with
open/close/read/write at this point */
int
mypci_open(dev_t dev, int oflags, int devtype, struct proc *p)
{
int err = 0;
uprintf("Opened device \"mypci\" successfully.\n");
return(err);
}
int
mypci_close(dev_t dev, int fflag, int devtype, struct proc *p)
{
int err=0;
uprintf("Closing device \"mypci.\"\n");
return(err);
}
int
mypci_read(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
uprintf("mypci read!\n");
return err;
}
int
mypci_write(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
uprintf("mypci write!\n");
return(err);
}
/* PCI Support Functions */
/*
* Return identification string if this is device is ours.
*/
static int
mypci_probe(device_t dev)
{
uprintf("MyPCI Probe\n"
"Vendor ID : 0x%x\n"
"Device ID : 0x%x\n",pci_get_vendor(dev),pci_get_device(dev));
if (pci_get_vendor(dev) == 0x11c1) {
uprintf("We've got the Winmodem, probe successful!\n");
return 0;
}
return ENXIO;
}
/* Attach function is only called if the probe is successful */
static int
mypci_attach(device_t dev)
{
uprintf("MyPCI Attach for : deviceID : 0x%x\n",pci_get_vendor(dev));
sdev = make_dev(&mypci_cdevsw,
0,
UID_ROOT,
GID_WHEEL,
0600,
"mypci");
uprintf("Mypci device loaded.\n");
return ENXIO;
}
/* Detach device. */
static int
mypci_detach(device_t dev)
{
uprintf("Mypci detach!\n");
return 0;
}
/* Called during system shutdown after sync. */
static int
mypci_shutdown(device_t dev)
{
uprintf("Mypci shutdown!\n");
return 0;
}
/*
* Device suspend routine.
*/
static int
mypci_suspend(device_t dev)
{
uprintf("Mypci suspend!\n");
return 0;
}
/*
* Device resume routine.
*/
static int
mypci_resume(device_t dev)
{
uprintf("Mypci resume!\n");
return 0;
}
static device_method_t mypci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mypci_probe),
DEVMETHOD(device_attach, mypci_attach),
DEVMETHOD(device_detach, mypci_detach),
DEVMETHOD(device_shutdown, mypci_shutdown),
DEVMETHOD(device_suspend, mypci_suspend),
DEVMETHOD(device_resume, mypci_resume),
{ 0, 0 }
};
static driver_t mypci_driver = {
"mypci",
mypci_methods,
0,
/* sizeof(struct mypci_softc), */
};
static devclass_t mypci_devclass;
DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);
Additional Resources
PCI Special Interest
Group
PCI System Architecture, Fourth Edition by
Tom Shanley, et al.
USB Devices
This chapter will talk about the FreeBSD mechanisms for
writing a device driver for a device on a USB bus.
NewBus
This chapter will talk about the FreeBSD NewBus
architecture.
Architectures
IA-32
Talk about the architectural specifics of FreeBSD/x86.
Alpha
Talk about the architectural specifics of
FreeBSD/alpha.
Explanation of allignment errors, how to fix, how to
ignore.
Example assembly language code for FreeBSD/alpha.
IA-64
Talk about the architectural specifics of
FreeBSD/ia64.
Debugging
Truss
various descriptions on how to debug certain aspects of
the system using truss, ktrace, gdb, kgdb, etc
Compatibility Layers
Linux
Linux, SVR4, etc
Appendices
Dave
A
Patterson
John
L
Hennessy
1998Morgan Kaufmann Publishers,
Inc.
1-55860-428-6
Morgan Kaufmann Publishers, Inc.
Computer Organization and Design
The Hardware / Software Interface
1-2
W.
Richard
Stevens
1993Addison Wesley Longman,
Inc.
0-201-56317-7
Addison Wesley Longman, Inc.
Advanced Programming in the Unix Environment
1-2
Marshall
Kirk
McKusick
Keith
Bostic
Michael
J
Karels
John
S
Quarterman
1996Addison-Wesley Publishing Company,
Inc.
0-201-54979-4
Addison-Wesley Publishing Company, Inc.
The Design and Implementation of the 4.4 BSD Operating System
1-2
Aleph
One
Phrack 49; "Smashing the Stack for Fun and Profit"
Chrispin
Cowan
Calton
Pu
Dave
Maier
StackGuard; Automatic Adaptive Detection and Prevention of
Buffer-Overflow Attacks
Todd
Miller
Theo
de Raadt
strlcpy and strlcat -- consistent, safe string copy and
concatenation.
diff --git a/en_US.ISO_8859-1/books/developers-handbook/driverbasics/chapter.sgml b/en_US.ISO_8859-1/books/developers-handbook/driverbasics/chapter.sgml
new file mode 100644
index 0000000000..afee34e472
--- /dev/null
+++ b/en_US.ISO_8859-1/books/developers-handbook/driverbasics/chapter.sgml
@@ -0,0 +1,383 @@
+
+
+
+ Writing FreeBSD Device Drivers
+
+ This chapter was written by Murray Stokely with selections from
+ a variety of sources including the intro(4) man page by Joerg
+ Wunsch.
+
+
+ Introduction
+
+ This chapter provides a brief introduction to writing device
+ drivers for FreeBSD. A device in this context is a term used
+ mostly for hardware-related stuff that belongs to the system,
+ like disks, printers, or a graphics display with its keyboard.
+ A device driver is the software component of the operating
+ system that controls a specific device. There are also
+ so-called pseudo-devices where a device driver emulates the
+ behaviour of a device in software without any particular
+ underlying hardware. Device drivers can be compiled into the
+ system statically or loaded on demand through the dynamic
+ kernel linker facility `kld'.
+
+ Most devices in a Unix-like operating system are
+ accessed through device-nodes, sometimes also called special
+ files. These files are usually located under the directory
+ /dev in the file system hierarchy. Until
+ devfs is fully integrated into FreeBSD, each device node must
+ be created statically and independent of the existence of the
+ associated device driver. Most device nodes on the system are
+ created by running MAKEDEV.
+
+ Device drivers can roughly be broken down into three
+ categories; character (unbuffered), block (buffered), and
+ network drivers.
+
+
+
+ Dynamic Kernel Linker Facility - KLD
+ The kld interface allows system administrators to
+ dynamically add and remove functionality from a running
+ system. This allows device driver writers to load their new
+ changes into a running kernel without constantly rebooting to
+ test changes.
+
+ The kld interface is used through the following
+ administrator commands :
+
+ kldload - loads a new kernel
+ module
+ kldunload - unloads a kernel
+ module
+ kldstat - lists the currently loadded
+ modules
+
+
+
+ Skeleton Layout of a kernel module
+
+/*
+ * KLD Skeleton
+ * Inspired by Andrew Reiter's Daemonnews article
+ */
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h> /* uprintf */
+#include <sys/errno.h>
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/kernel.h> /* types used in module initialization */
+
+/*
+ * Load handler that deals with the loading and unloading of a KLD.
+ */
+
+static int
+skel_loader(struct module *m, int what, void *arg)
+{
+ int err = 0;
+
+ switch (what) {
+ case MOD_LOAD: /* kldload */
+ uprintf("Skeleton KLD loaded.\n");
+ break;
+ case MOD_UNLOAD:
+ uprintf("Skeleton KLD unloaded.\n");
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+/* Declare this module to the rest of the kernel */
+
+DECLARE_MODULE(skeleton, skel_loader, SI_SUB_KLD, SI_ORDER_ANY);
+
+
+
+
+ Makefile
+ FreeBSD provides a makefile include that you can use
+ to quickly compile your kernel addition.
+
+SRCS=skeleton.c
+KMOD=skeleton
+
+.include <bsd.kmod.mk>
+
+
+
+ Simply running make with
+ this makefile will create a file
+ skeleton.ko that can be loaded into
+ your system by typing :
+
+&prompt.root kldload -v ./skeleton.ko
+
+
+
+
+
+
+ Accessing a device driver
+ Unix provides a common set of system calls for user
+ applications to use. The upper layers of the kernel dispatch
+ these calls to the corresponding device driver when a user
+ accesses a device node. The /dev/MAKEDEV
+ script makes most of the device nodes for your system but if
+ you are doing your own driver development it may be necessary
+ to create your own device nodes with mknod
+
+
+
+ Creating static device nodes
+ The mknod command requires four
+ arguments to create a device node. You must specify the
+ name of this device node, the type of device, the major number
+ of the device, and the minor number of the device.
+
+
+
+ Dynamic device nodes
+ The device filesystem, or devfs, provides access to the
+ kernel's device namespace in the global filesystem namespace.
+ This eliminates the problems of potentially having a device
+ driver without a static device node, or a device node without
+ an installed device driver. Unfortunately, devfs is still a
+ work in progress.
+
+
+
+
+
+ Character Devices
+ A character device driver is one that transfers data
+ directly to and from a user process. This is the most common
+ type of device driver and there are plenty of simple examples
+ in the source tree.
+ This simple example pseudo-device remembers whatever values you write
+ to it and can then supply them back to you when you read from
+ it.
+
+/*
+ * Simple `echo' pseudo-device KLD
+ *
+ * Murray Stokely
+ */
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h> /* uprintf */
+#include <sys/errno.h>
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/kernel.h> /* types used in module initialization */
+#include <sys/conf.h> /* cdevsw struct */
+#include <sys/uio.h> /* uio struct */
+#include <sys/malloc.h>
+
+#define BUFFERSIZE 256
+
+/* Function prototypes */
+d_open_t echo_open;
+d_close_t echo_close;
+d_read_t echo_read;
+d_write_t echo_write;
+
+/* Character device entry points */
+static struct cdevsw echo_cdevsw = {
+ echo_open,
+ echo_close,
+ echo_read,
+ echo_write,
+ noioctl,
+ nopoll,
+ nommap,
+ nostrategy,
+ "echo",
+ 33, /* reserved for lkms - /usr/src/sys/conf/majors */
+ nodump,
+ nopsize,
+ D_TTY,
+ -1
+};
+
+typedef struct s_echo {
+ char msg[BUFFERSIZE];
+ int len;
+} t_echo;
+
+/* vars */
+static dev_t sdev;
+static int len;
+static int count;
+static t_echo *echomsg;
+
+MALLOC_DECLARE(M_ECHOBUF);
+MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
+
+/*
+ * This function acts is called by the kld[un]load(2) system calls to
+ * determine what actions to take when a module is loaded or unloaded.
+ */
+
+static int
+echo_loader(struct module *m, int what, void *arg)
+{
+ int err = 0;
+
+ switch (what) {
+ case MOD_LOAD: /* kldload */
+ sdev = make_dev(&echo_cdevsw,
+ 0,
+ UID_ROOT,
+ GID_WHEEL,
+ 0600,
+ "echo");
+ /* kmalloc memory for use by this driver */
+ /* malloc(256,M_ECHOBUF,M_WAITOK); */
+ MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
+ printf("Echo device loaded.\n");
+ break;
+ case MOD_UNLOAD:
+ destroy_dev(sdev);
+ FREE(echomsg,M_ECHOBUF);
+ printf("Echo device unloaded.\n");
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+int
+echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
+{
+ int err = 0;
+
+ uprintf("Opened device \"echo\" successfully.\n");
+ return(err);
+}
+
+int
+echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
+{
+ uprintf("Closing device \"echo.\"\n");
+ return(0);
+}
+
+/*
+ * The read function just takes the buf that was saved via
+ * echo_write() and returns it to userland for accessing.
+ * uio(9)
+ */
+
+int
+echo_read(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+ int amt;
+
+ /* How big is this read operation? Either as big as the user wants,
+ or as big as the remaining data */
+ amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? echomsg->len - uio->uio_offset : 0);
+ if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
+ uprintf("uiomove failed!\n");
+ }
+
+ return err;
+}
+
+/*
+ * echo_write takes in a character string and saves it
+ * to buf for later accessing.
+ */
+
+int
+echo_write(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+
+ /* Copy the string in from user memory to kernel memory */
+ err = copyin(uio->uio_iov->iov_base, echomsg->msg, MIN(uio->uio_iov->iov_len,BUFFERSIZE));
+
+ /* Now we need to null terminate */
+ *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
+ /* Record the length */
+ echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);
+
+ if (err != 0) {
+ uprintf("Write failed: bad address!\n");
+ }
+
+ count++;
+ return(err);
+}
+
+DEV_MODULE(echo,echo_loader,NULL);
+
+
+To install this driver you will first need to make a node on
+ your filesystem with a command such as :
+
+ &prompt.root mknod /dev/echo c 33 0
+
+With this driver loaded you should now be able to type something
+ like :
+
+ &prompt.root echo -n "Test Data" > /dev/echo
+ &prompt.root cat /dev/echo
+ Test Data
+
+ Real hardware devices in the next chapter..
+
+ Additional Resources
+
+ Dynamic
+ Kernel Linker (KLD) Facility Programming Tutorial -
+ Daemonnews October 2000
+ How
+ to Write Kernel Drivers with NEWBUS - Daemonnews July
+ 2000
+
+
+
+
+
+ Block Devices
+ A block device driver transfers data to and from the
+ operating system's buffer cache. They are solely intended to
+ layer a file system on top of them. For this reason they are
+ normally implemented for disks and disk-like devices only.
+
+ Example test data generator ...
+
+ Example ramdisk device ...
+
+ Real hardware devices in the next chapter..
+
+
+
+ Network Drivers
+ Drivers for network devices do not use device nodes in
+ ord to be accessed. Their selection is based on other
+ decisions made inside the kernel and instead of calling
+ open(), use of a network device is generally introduced by
+ using the system call socket(2).
+ man ifnet(), loopback device, Bill Pauls drivers, etc..
+
+
+