aboutsummaryrefslogtreecommitdiff
path: root/documentation/content/en/books/arch-handbook/pci/_index.po
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/content/en/books/arch-handbook/pci/_index.po')
-rw-r--r--documentation/content/en/books/arch-handbook/pci/_index.po787
1 files changed, 787 insertions, 0 deletions
diff --git a/documentation/content/en/books/arch-handbook/pci/_index.po b/documentation/content/en/books/arch-handbook/pci/_index.po
new file mode 100644
index 0000000000..f80e3c3376
--- /dev/null
+++ b/documentation/content/en/books/arch-handbook/pci/_index.po
@@ -0,0 +1,787 @@
+# 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: 2022-02-01 09:20-0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\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/pci/_index.adoc:1
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:13
+#, no-wrap
+msgid "PCI Devices"
+msgstr ""
+
+#. type: YAML Front Matter: title
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:1
+#, no-wrap
+msgid "Chapter 11. PCI Devices"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:51
+msgid ""
+"This chapter will talk about the FreeBSD mechanisms for writing a device "
+"driver for a device on a PCI bus."
+msgstr ""
+
+#. type: Title ==
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:53
+#, no-wrap
+msgid "Probe and Attach"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:56
+msgid ""
+"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."
+msgstr ""
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:57
+#, no-wrap
+msgid "Sample Driver Source ([.filename]#mypci.c#)"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:66
+#, no-wrap
+msgid ""
+"/*\n"
+" * Simple KLD to play with the PCI functions.\n"
+" *\n"
+" * Murray Stokely\n"
+" */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:76
+#, no-wrap
+msgid ""
+"#include <sys/param.h>\t\t/* defines used in kernel.h */\n"
+"#include <sys/module.h>\n"
+"#include <sys/systm.h>\n"
+"#include <sys/errno.h>\n"
+"#include <sys/kernel.h>\t\t/* types used in module initialization */\n"
+"#include <sys/conf.h>\t\t/* cdevsw struct */\n"
+"#include <sys/uio.h>\t\t/* uio struct */\n"
+"#include <sys/malloc.h>\n"
+"#include <sys/bus.h>\t\t/* structs, prototypes for pci bus stuff and DEVMETHOD macros! */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:80
+#, no-wrap
+msgid ""
+"#include <machine/bus.h>\n"
+"#include <sys/rman.h>\n"
+"#include <machine/resource.h>\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:83
+#, no-wrap
+msgid ""
+"#include <dev/pci/pcivar.h>\t/* For pci_get macros! */\n"
+"#include <dev/pci/pcireg.h>\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:89
+#, no-wrap
+msgid ""
+"/* The softc holds our per-instance data. */\n"
+"struct mypci_softc {\n"
+"\tdevice_t\tmy_dev;\n"
+"\tstruct cdev\t*my_cdev;\n"
+"};\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:95
+#, no-wrap
+msgid ""
+"/* Function prototypes */\n"
+"static d_open_t\t\tmypci_open;\n"
+"static d_close_t\tmypci_close;\n"
+"static d_read_t\t\tmypci_read;\n"
+"static d_write_t\tmypci_write;\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:97
+#, no-wrap
+msgid "/* Character device entry points */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:106
+#, no-wrap
+msgid ""
+"static struct cdevsw mypci_cdevsw = {\n"
+"\t.d_version =\tD_VERSION,\n"
+"\t.d_open =\tmypci_open,\n"
+"\t.d_close =\tmypci_close,\n"
+"\t.d_read =\tmypci_read,\n"
+"\t.d_write =\tmypci_write,\n"
+"\t.d_name =\t\"mypci\",\n"
+"};\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:112
+#, no-wrap
+msgid ""
+"/*\n"
+" * In the cdevsw routines, we find our softc by using the si_drv1 member\n"
+" * of struct cdev. We set this variable to point to our softc in our\n"
+" * attach routine when we create the /dev entry.\n"
+" */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:117
+#, no-wrap
+msgid ""
+"int\n"
+"mypci_open(struct cdev *dev, int oflags, int devtype, struct thread *td)\n"
+"{\n"
+"\tstruct mypci_softc *sc;\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:123
+#, no-wrap
+msgid ""
+"\t/* Look up our softc. */\n"
+"\tsc = dev->si_drv1;\n"
+"\tdevice_printf(sc->my_dev, \"Opened successfully.\\n\");\n"
+"\treturn (0);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:128
+#, no-wrap
+msgid ""
+"int\n"
+"mypci_close(struct cdev *dev, int fflag, int devtype, struct thread *td)\n"
+"{\n"
+"\tstruct mypci_softc *sc;\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:134
+#, no-wrap
+msgid ""
+"\t/* Look up our softc. */\n"
+"\tsc = dev->si_drv1;\n"
+"\tdevice_printf(sc->my_dev, \"Closed.\\n\");\n"
+"\treturn (0);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:139
+#, no-wrap
+msgid ""
+"int\n"
+"mypci_read(struct cdev *dev, struct uio *uio, int ioflag)\n"
+"{\n"
+"\tstruct mypci_softc *sc;\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:145
+#, no-wrap
+msgid ""
+"\t/* Look up our softc. */\n"
+"\tsc = dev->si_drv1;\n"
+"\tdevice_printf(sc->my_dev, \"Asked to read %zd bytes.\\n\", uio->uio_resid);\n"
+"\treturn (0);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:150
+#, no-wrap
+msgid ""
+"int\n"
+"mypci_write(struct cdev *dev, struct uio *uio, int ioflag)\n"
+"{\n"
+"\tstruct mypci_softc *sc;\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:156
+#, no-wrap
+msgid ""
+"\t/* Look up our softc. */\n"
+"\tsc = dev->si_drv1;\n"
+"\tdevice_printf(sc->my_dev, \"Asked to write %zd bytes.\\n\", uio->uio_resid);\n"
+"\treturn (0);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:158
+#, no-wrap
+msgid "/* PCI Support Functions */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:166
+#, no-wrap
+msgid ""
+"/*\n"
+" * Compare the device ID of this device against the IDs that this driver\n"
+" * supports. If there is a match, set the description and return success.\n"
+" */\n"
+"static int\n"
+"mypci_probe(device_t dev)\n"
+"{\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:169
+#, no-wrap
+msgid ""
+"\tdevice_printf(dev, \"MyPCI Probe\\nVendor ID : 0x%x\\nDevice ID : 0x%x\\n\",\n"
+"\t pci_get_vendor(dev), pci_get_device(dev));\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:177
+#, no-wrap
+msgid ""
+"\tif (pci_get_vendor(dev) == 0x11c1) {\n"
+"\t\tprintf(\"We've got the Winmodem, probe successful!\\n\");\n"
+"\t\tdevice_set_desc(dev, \"WinModem\");\n"
+"\t\treturn (BUS_PROBE_DEFAULT);\n"
+"\t}\n"
+"\treturn (ENXIO);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:179
+#, no-wrap
+msgid "/* Attach function is only called if the probe is successful. */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:184
+#, no-wrap
+msgid ""
+"static int\n"
+"mypci_attach(device_t dev)\n"
+"{\n"
+"\tstruct mypci_softc *sc;\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:186
+#, no-wrap
+msgid "\tprintf(\"MyPCI Attach for : deviceID : 0x%x\\n\", pci_get_devid(dev));\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:190
+#, no-wrap
+msgid ""
+"\t/* Look up our softc and initialize its fields. */\n"
+"\tsc = device_get_softc(dev);\n"
+"\tsc->my_dev = dev;\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:203
+#, no-wrap
+msgid ""
+"\t/*\n"
+"\t * Create a /dev entry for this device. The kernel will assign us\n"
+"\t * a major number automatically. We use the unit number of this\n"
+"\t * device as the minor number and name the character device\n"
+"\t * \"mypci<unit>\".\n"
+"\t */\n"
+"\tsc->my_cdev = make_dev(&mypci_cdevsw, device_get_unit(dev),\n"
+"\t UID_ROOT, GID_WHEEL, 0600, \"mypci%u\", device_get_unit(dev));\n"
+"\tsc->my_cdev->si_drv1 = sc;\n"
+"\tprintf(\"Mypci device loaded.\\n\");\n"
+"\treturn (0);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:205
+#, no-wrap
+msgid "/* Detach device. */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:210
+#, no-wrap
+msgid ""
+"static int\n"
+"mypci_detach(device_t dev)\n"
+"{\n"
+"\tstruct mypci_softc *sc;\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:217
+#, no-wrap
+msgid ""
+"\t/* Teardown the state in our softc created in our attach routine. */\n"
+"\tsc = device_get_softc(dev);\n"
+"\tdestroy_dev(sc->my_cdev);\n"
+"\tprintf(\"Mypci detach!\\n\");\n"
+"\treturn (0);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:219
+#, no-wrap
+msgid "/* Called during system shutdown after sync. */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:223
+#, no-wrap
+msgid ""
+"static int\n"
+"mypci_shutdown(device_t dev)\n"
+"{\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:227
+#, no-wrap
+msgid ""
+"\tprintf(\"Mypci shutdown!\\n\");\n"
+"\treturn (0);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:234
+#, no-wrap
+msgid ""
+"/*\n"
+" * Device suspend routine.\n"
+" */\n"
+"static int\n"
+"mypci_suspend(device_t dev)\n"
+"{\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:238
+#, no-wrap
+msgid ""
+"\tprintf(\"Mypci suspend!\\n\");\n"
+"\treturn (0);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:245
+#, no-wrap
+msgid ""
+"/*\n"
+" * Device resume routine.\n"
+" */\n"
+"static int\n"
+"mypci_resume(device_t dev)\n"
+"{\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:249
+#, no-wrap
+msgid ""
+"\tprintf(\"Mypci resume!\\n\");\n"
+"\treturn (0);\n"
+"}\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:258
+#, no-wrap
+msgid ""
+"static device_method_t mypci_methods[] = {\n"
+"\t/* Device interface */\n"
+"\tDEVMETHOD(device_probe,\t\tmypci_probe),\n"
+"\tDEVMETHOD(device_attach,\tmypci_attach),\n"
+"\tDEVMETHOD(device_detach,\tmypci_detach),\n"
+"\tDEVMETHOD(device_shutdown,\tmypci_shutdown),\n"
+"\tDEVMETHOD(device_suspend,\tmypci_suspend),\n"
+"\tDEVMETHOD(device_resume,\tmypci_resume),\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:261
+#, no-wrap
+msgid ""
+"\tDEVMETHOD_END\n"
+"};\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:263
+#, no-wrap
+msgid "static devclass_t mypci_devclass;\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:266
+#, no-wrap
+msgid ""
+"DEFINE_CLASS_0(mypci, mypci_driver, mypci_methods, sizeof(struct mypci_softc));\n"
+"DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);\n"
+msgstr ""
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:268
+#, no-wrap
+msgid "[.filename]#Makefile# for Sample Driver"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:273
+#, no-wrap
+msgid "# Makefile for mypci driver\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:277
+#, no-wrap
+msgid ""
+"KMOD=\tmypci\n"
+"SRCS=\tmypci.c\n"
+"SRCS+=\tdevice_if.h bus_if.h pci_if.h\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:279
+#, no-wrap
+msgid ".include <bsd.kmod.mk>\n"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:282
+msgid ""
+"If you place the above source file and [.filename]#Makefile# into a "
+"directory, you may run `make` to compile the sample driver. Additionally, "
+"you may run `make load` to load the driver into the currently running kernel "
+"and `make unload` to unload the driver after it is loaded."
+msgstr ""
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:283
+#, no-wrap
+msgid "Additional Resources"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:286
+msgid "http://www.pcisig.org/[PCI Special Interest Group]"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:287
+msgid "PCI System Architecture, Fourth Edition by Tom Shanley, et al."
+msgstr ""
+
+#. type: Title ==
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:289
+#, no-wrap
+msgid "Bus Resources"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:292
+msgid ""
+"FreeBSD provides an object-oriented mechanism for requesting resources from "
+"a parent bus. Almost all devices will be a child member of some sort of bus "
+"(PCI, ISA, USB, SCSI, etc) and these devices need to acquire resources from "
+"their parent bus (such as memory segments, interrupt lines, or DMA channels)."
+msgstr ""
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:293
+#, no-wrap
+msgid "Base Address Registers"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:296
+msgid ""
+"To do anything particularly useful with a PCI device you will need to obtain "
+"the _Base Address Registers_ (BARs) from the PCI Configuration space. The "
+"PCI-specific details of obtaining the BAR are abstracted in the "
+"`bus_alloc_resource()` function."
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:298
+msgid ""
+"For example, a typical driver might have something similar to this in the "
+"`attach()` function:"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:309
+#, no-wrap
+msgid ""
+" sc->bar0id = PCIR_BAR(0);\n"
+" sc->bar0res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bar0id,\n"
+"\t\t\t\t 0, ~0, 1, RF_ACTIVE);\n"
+" if (sc->bar0res == NULL) {\n"
+" printf(\"Memory allocation of PCI base register 0 failed!\\n\");\n"
+" error = ENXIO;\n"
+" goto fail1;\n"
+" }\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:322
+#, no-wrap
+msgid ""
+" sc->bar1id = PCIR_BAR(1);\n"
+" sc->bar1res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bar1id,\n"
+"\t\t\t\t 0, ~0, 1, RF_ACTIVE);\n"
+" if (sc->bar1res == NULL) {\n"
+" printf(\"Memory allocation of PCI base register 1 failed!\\n\");\n"
+" error = ENXIO;\n"
+" goto fail2;\n"
+" }\n"
+" sc->bar0_bt = rman_get_bustag(sc->bar0res);\n"
+" sc->bar0_bh = rman_get_bushandle(sc->bar0res);\n"
+" sc->bar1_bt = rman_get_bustag(sc->bar1res);\n"
+" sc->bar1_bh = rman_get_bushandle(sc->bar1res);\n"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:325
+msgid ""
+"Handles for each base address register are kept in the `softc` structure so "
+"that they can be used to write to the device later."
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:327
+msgid ""
+"These handles can then be used to read or write from the device registers "
+"with the `bus_space_*` functions. For example, a driver might contain a "
+"shorthand function to read from a board specific register like this:"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:335
+#, no-wrap
+msgid ""
+"uint16_t\n"
+"board_read(struct ni_softc *sc, uint16_t address)\n"
+"{\n"
+" return bus_space_read_2(sc->bar1_bt, sc->bar1_bh, address);\n"
+"}\n"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:338
+msgid "Similarly, one could write to the registers with:"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:346
+#, no-wrap
+msgid ""
+"void\n"
+"board_write(struct ni_softc *sc, uint16_t address, uint16_t value)\n"
+"{\n"
+" bus_space_write_2(sc->bar1_bt, sc->bar1_bh, address, value);\n"
+"}\n"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:349
+msgid ""
+"These functions exist in 8bit, 16bit, and 32bit versions and you should use "
+"`bus_space_{read|write}_{1|2|4}` accordingly."
+msgstr ""
+
+#. type: delimited block = 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:353
+msgid ""
+"In FreeBSD 7.0 and later, you can use the `bus_*` functions instead of "
+"`bus_space_*`. The `bus_*` functions take a struct resource * pointer "
+"instead of a bus tag and handle. Thus, you could drop the bus tag and bus "
+"handle members from the `softc` and rewrite the `board_read()` function as:"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:361
+#, no-wrap
+msgid ""
+"uint16_t\n"
+"board_read(struct ni_softc *sc, uint16_t address)\n"
+"{\n"
+"\treturn (bus_read(sc->bar1res, address));\n"
+"}\n"
+msgstr ""
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:365
+#, no-wrap
+msgid "Interrupts"
+msgstr ""
+
+#. type: delimited block = 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:368
+msgid ""
+"Interrupts are allocated from the object-oriented bus code in a way similar "
+"to the memory resources. First an IRQ resource must be allocated from the "
+"parent bus, and then the interrupt handler must be set up to deal with this "
+"IRQ."
+msgstr ""
+
+#. type: delimited block = 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:370
+msgid "Again, a sample from a device `attach()` function says more than words."
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:374
+#, no-wrap
+msgid "/* Get the IRQ resource */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:383
+#, no-wrap
+msgid ""
+" sc->irqid = 0x0;\n"
+" sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &(sc->irqid),\n"
+"\t\t\t\t 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);\n"
+" if (sc->irqres == NULL) {\n"
+"\tprintf(\"IRQ allocation failed!\\n\");\n"
+"\terror = ENXIO;\n"
+"\tgoto fail3;\n"
+" }\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:385
+#, no-wrap
+msgid " /* Now we should set up the interrupt handler */\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:392
+#, no-wrap
+msgid ""
+" error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_MISC,\n"
+"\t\t\t my_handler, sc, &(sc->handler));\n"
+" if (error) {\n"
+"\tprintf(\"Couldn't set up irq\\n\");\n"
+"\tgoto fail4;\n"
+" }\n"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:395
+msgid ""
+"Some care must be taken in the detach routine of the driver. You must "
+"quiesce the device's interrupt stream, and remove the interrupt handler. "
+"Once `bus_teardown_intr()` has returned, you know that your interrupt "
+"handler will no longer be called and that all threads that might have been "
+"executing this interrupt handler have returned. Since this function can "
+"sleep, you must not hold any mutexes when calling this function."
+msgstr ""
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:396
+#, no-wrap
+msgid "DMA"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:399
+msgid ""
+"This section is obsolete, and present only for historical reasons. The "
+"proper methods for dealing with these issues is to use the "
+"`bus_space_dma*()` functions instead. This paragraph can be removed when "
+"this section is updated to reflect that usage. However, at the moment, the "
+"API is in a bit of flux, so once that settles down, it would be good to "
+"update this section to reflect that."
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:401
+msgid ""
+"On the PC, peripherals that want to do bus-mastering DMA must deal with "
+"physical addresses. This is a problem since FreeBSD uses virtual memory and "
+"deals almost exclusively with virtual addresses. Fortunately, there is a "
+"function, `vtophys()` to help."
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:406
+#, no-wrap
+msgid ""
+"#include <vm/vm.h>\n"
+"#include <vm/pmap.h>\n"
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:408
+#, no-wrap
+msgid "#define vtophys(virtual_address) (...)\n"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:411
+msgid ""
+"The solution is a bit different on the alpha however, and what we really "
+"want is a function called `vtobus()`."
+msgstr ""
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:419
+#, no-wrap
+msgid ""
+"#if defined(__alpha__)\n"
+"#define vtobus(va) alpha_XXX_dmamap((vm_offset_t)va)\n"
+"#else\n"
+"#define vtobus(va) vtophys(va)\n"
+"#endif\n"
+msgstr ""
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:421
+#, no-wrap
+msgid "Deallocating Resources"
+msgstr ""
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/pci/_index.adoc:423
+msgid ""
+"It is very important to deallocate all of the resources that were allocated "
+"during `attach()`. Care must be taken to deallocate the correct stuff even "
+"on a failure condition so that the system will remain usable while your "
+"driver dies."
+msgstr ""