Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-doc
Path: blob/main/documentation/content/en/books/arch-handbook/driverbasics/_index.po
18098 views
# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR The FreeBSD Project
# This file is distributed under the same license as the FreeBSD Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: FreeBSD Documentation VERSION\n"
"POT-Creation-Date: 2025-05-01 19:56-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#. type: Title =
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:1
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:14
#, no-wrap
msgid "Writing FreeBSD Device Drivers"
msgstr ""

#. type: YAML Front Matter: title
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:1
#, no-wrap
msgid "Chapter 9. Writing FreeBSD Device Drivers"
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:52
#, no-wrap
msgid "Introduction"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:55
msgid ""
"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 behavior 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'."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:57
msgid ""
"Most devices in a UNIX(R)-like operating system are accessed through device-"
"nodes, sometimes also called special files. These files are usually located "
"under the directory [.filename]#/dev# in the filesystem hierarchy."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:59
msgid ""
"Device drivers can roughly be broken down into two categories; character and "
"network device drivers."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:61
#, no-wrap
msgid "Dynamic Kernel Linker Facility - KLD"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:64
msgid ""
"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."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:66
msgid "The kld interface is used through:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:68
msgid "`kldload` - loads a new kernel module"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:69
msgid "`kldunload` - unloads a kernel module"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:70
msgid "`kldstat` - lists loaded modules"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:72
msgid "Skeleton Layout of a kernel module"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:79
#, no-wrap
msgid ""
"/*\n"
" * KLD Skeleton\n"
" * Inspired by Andrew Reiter's Daemonnews article\n"
" */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:86
#, no-wrap
msgid ""
"#include <sys/types.h>\n"
"#include <sys/systm.h>  /* uprintf */\n"
"#include <sys/errno.h>\n"
"#include <sys/param.h>  /* defines used in kernel.h */\n"
"#include <sys/module.h>\n"
"#include <sys/kernel.h> /* types used in module initialization */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:90
#, no-wrap
msgid ""
"/*\n"
" * Load handler that deals with the loading and unloading of a KLD.\n"
" */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:95
#, no-wrap
msgid ""
"static int\n"
"skel_loader(struct module *m, int what, void *arg)\n"
"{\n"
"\tint err = 0;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:109
#, no-wrap
msgid ""
"\tswitch (what) {\n"
"\tcase MOD_LOAD:                /* kldload */\n"
"\t\tuprintf(\"Skeleton KLD loaded.\\n\");\n"
"\t\tbreak;\n"
"\tcase MOD_UNLOAD:\n"
"\t\tuprintf(\"Skeleton KLD unloaded.\\n\");\n"
"\t\tbreak;\n"
"\tdefault:\n"
"\t\terr = EOPNOTSUPP;\n"
"\t\tbreak;\n"
"\t}\n"
"\treturn(err);\n"
"}\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:111
#, no-wrap
msgid "/* Declare this module to the rest of the kernel */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:117
#, no-wrap
msgid ""
"static moduledata_t skel_mod = {\n"
"\t\"skel\",\n"
"\tskel_loader,\n"
"\tNULL\n"
"};\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:119
#, no-wrap
msgid "DECLARE_MODULE(skeleton, skel_mod, SI_SUB_KLD, SI_ORDER_ANY);\n"
msgstr ""

#. type: Title ===
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:121
#, no-wrap
msgid "Makefile"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:124
msgid ""
"FreeBSD provides a system makefile to simplify compiling a kernel module."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:129
#, no-wrap
msgid ""
"SRCS=skeleton.c\n"
"KMOD=skeleton\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:131
#, no-wrap
msgid ".include <bsd.kmod.mk>\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:134
msgid ""
"Running `make` with this makefile will create a file "
"[.filename]#skeleton.ko# that can be loaded into the kernel by typing:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:138
#, no-wrap
msgid "# kldload -v ./skeleton.ko\n"
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:141
#, no-wrap
msgid "Character Devices"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:144
msgid ""
"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."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:146
msgid ""
"This simple example pseudo-device remembers whatever values are written to "
"it and can then echo them back when read."
msgstr ""

#. type: Block title
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:147
#, no-wrap
msgid "Example of a Sample Echo Pseudo-Device Driver for FreeBSD 10.X - 12.X"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:159
#, no-wrap
msgid ""
"/*\n"
" * Simple Echo pseudo-device KLD\n"
" *\n"
" * Murray Stokely\n"
" * Søren (Xride) Straarup\n"
" * Eitan Adler\n"
" */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:168
#, no-wrap
msgid ""
"#include <sys/types.h>\n"
"#include <sys/systm.h>  /* uprintf */\n"
"#include <sys/param.h>  /* defines used in kernel.h */\n"
"#include <sys/module.h>\n"
"#include <sys/kernel.h> /* types used in module initialization */\n"
"#include <sys/conf.h>   /* cdevsw struct */\n"
"#include <sys/uio.h>    /* uio struct */\n"
"#include <sys/malloc.h>\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:170
#, no-wrap
msgid "#define BUFFERSIZE 255\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:176
#, no-wrap
msgid ""
"/* Function prototypes */\n"
"static d_open_t      echo_open;\n"
"static d_close_t     echo_close;\n"
"static d_read_t      echo_read;\n"
"static d_write_t     echo_write;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:186
#, no-wrap
msgid ""
"/* Character device entry points */\n"
"static struct cdevsw echo_cdevsw = {\n"
"\t.d_version = D_VERSION,\n"
"\t.d_open = echo_open,\n"
"\t.d_close = echo_close,\n"
"\t.d_read = echo_read,\n"
"\t.d_write = echo_write,\n"
"\t.d_name = \"echo\",\n"
"};\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:191
#, no-wrap
msgid ""
"struct s_echo {\n"
"\tchar msg[BUFFERSIZE + 1];\n"
"\tint len;\n"
"};\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:195
#, no-wrap
msgid ""
"/* vars */\n"
"static struct cdev *echo_dev;\n"
"static struct s_echo *echomsg;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:198
#, no-wrap
msgid ""
"MALLOC_DECLARE(M_ECHOBUF);\n"
"MALLOC_DEFINE(M_ECHOBUF, \"echobuffer\", \"buffer for echo module\");\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:207
#, no-wrap
msgid ""
"/*\n"
" * This function is called by the kld[un]load(2) system calls to\n"
" * determine what actions to take when a module is loaded or unloaded.\n"
" */\n"
"static int\n"
"echo_loader(struct module *m __unused, int what, void *arg __unused)\n"
"{\n"
"\tint error = 0;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:220
#, no-wrap
msgid ""
"\tswitch (what) {\n"
"\tcase MOD_LOAD:                /* kldload */\n"
"\t\terror = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,\n"
"\t\t    &echo_dev,\n"
"\t\t    &echo_cdevsw,\n"
"\t\t    0,\n"
"\t\t    UID_ROOT,\n"
"\t\t    GID_WHEEL,\n"
"\t\t    0600,\n"
"\t\t    \"echo\");\n"
"\t\tif (error != 0)\n"
"\t\t\tbreak;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:236
#, no-wrap
msgid ""
"\t\techomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK |\n"
"\t\t    M_ZERO);\n"
"\t\tprintf(\"Echo device loaded.\\n\");\n"
"\t\tbreak;\n"
"\tcase MOD_UNLOAD:\n"
"\t\tdestroy_dev(echo_dev);\n"
"\t\tfree(echomsg, M_ECHOBUF);\n"
"\t\tprintf(\"Echo device unloaded.\\n\");\n"
"\t\tbreak;\n"
"\tdefault:\n"
"\t\terror = EOPNOTSUPP;\n"
"\t\tbreak;\n"
"\t}\n"
"\treturn (error);\n"
"}\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:242
#, no-wrap
msgid ""
"static int\n"
"echo_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused,\n"
"    struct thread *td __unused)\n"
"{\n"
"\tint error = 0;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:246
#, no-wrap
msgid ""
"\tuprintf(\"Opened device \\\"echo\\\" successfully.\\n\");\n"
"\treturn (error);\n"
"}\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:251
#, no-wrap
msgid ""
"static int\n"
"echo_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused,\n"
"    struct thread *td __unused)\n"
"{\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:255
#, no-wrap
msgid ""
"\tuprintf(\"Closing device \\\"echo\\\".\\n\");\n"
"\treturn (0);\n"
"}\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:266
#, no-wrap
msgid ""
"/*\n"
" * The read function just takes the buf that was saved via\n"
" * echo_write() and returns it to userland for accessing.\n"
" * uio(9)\n"
" */\n"
"static int\n"
"echo_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)\n"
"{\n"
"\tsize_t amt;\n"
"\tint error;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:274
#, no-wrap
msgid ""
"\t/*\n"
"\t * How big is this read operation?  Either as big as the user wants,\n"
"\t * or as big as the remaining data.  Note that the 'len' does not\n"
"\t * include the trailing null character.\n"
"\t */\n"
"\tamt = MIN(uio->uio_resid, uio->uio_offset >= echomsg->len + 1 ? 0 :\n"
"\t    echomsg->len + 1 - uio->uio_offset);\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:277
#, no-wrap
msgid ""
"\tif ((error = uiomove(echomsg->msg, amt, uio)) != 0)\n"
"\t\tuprintf(\"uiomove failed!\\n\");\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:280
#, no-wrap
msgid ""
"\treturn (error);\n"
"}\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:290
#, no-wrap
msgid ""
"/*\n"
" * echo_write takes in a character string and saves it\n"
" * to buf for later accessing.\n"
" */\n"
"static int\n"
"echo_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)\n"
"{\n"
"\tsize_t amt;\n"
"\tint error;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:297
#, no-wrap
msgid ""
"\t/*\n"
"\t * We either write from the beginning or are appending -- do\n"
"\t * not allow random access.\n"
"\t */\n"
"\tif (uio->uio_offset != 0 && (uio->uio_offset != echomsg->len))\n"
"\t\treturn (EINVAL);\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:301
#, no-wrap
msgid ""
"\t/* This is a new message, reset length */\n"
"\tif (uio->uio_offset == 0)\n"
"\t\techomsg->len = 0;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:304
#, no-wrap
msgid ""
"\t/* Copy the string in from user memory to kernel memory */\n"
"\tamt = MIN(uio->uio_resid, (BUFFERSIZE - echomsg->len));\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:306
#, no-wrap
msgid "\terror = uiomove(echomsg->msg + uio->uio_offset, amt, uio);\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:310
#, no-wrap
msgid ""
"\t/* Now we need to null terminate and record the length */\n"
"\techomsg->len = uio->uio_offset;\n"
"\techomsg->msg[echomsg->len] = 0;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:315
#, no-wrap
msgid ""
"\tif (error != 0)\n"
"\t\tuprintf(\"Write failed: bad address!\\n\");\n"
"\treturn (error);\n"
"}\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:317
#, no-wrap
msgid "DEV_MODULE(echo, echo_loader, NULL);\n"
msgstr ""

#. type: delimited block = 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:321
msgid "With this driver loaded try:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:329
#, no-wrap
msgid ""
"# echo -n \"Test Data\" > /dev/echo\n"
"# cat /dev/echo\n"
"Opened device \"echo\" successfully.\n"
"Test Data\n"
"Closing device \"echo\".\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:332
msgid "Real hardware devices are described in the next chapter."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:334
#, no-wrap
msgid "Block Devices (Are Gone)"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:337
msgid ""
"Other UNIX(R) systems may support a second type of disk device known as "
"block devices. Block devices are disk devices for which the kernel provides "
"caching. This caching makes block-devices almost unusable, or at least "
"dangerously unreliable. The caching will reorder the sequence of write "
"operations, depriving the application of the ability to know the exact disk "
"contents at any one instant in time."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:339
msgid ""
"This makes predictable and reliable crash recovery of on-disk data "
"structures (filesystems, databases, etc.) impossible. Since writes may be "
"delayed, there is no way the kernel can report to the application which "
"particular write operation encountered a write error, this further compounds "
"the consistency problem."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:341
msgid ""
"For this reason, no serious applications rely on block devices, and in fact, "
"almost all applications which access disks directly take great pains to "
"specify that character (or \"raw\") devices should always be used. As the "
"implementation of the aliasing of each disk (partition) to two devices with "
"different semantics significantly complicated the relevant kernel code, "
"FreeBSD dropped support for cached disk devices as part of the modernization "
"of the disk I/O infrastructure."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:343
#, no-wrap
msgid "Network Drivers"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:346
msgid ""
"Drivers for network devices do not use device nodes in order 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)."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:347
msgid "For more information see ifnet(9), the source of the loopback device."
msgstr ""