Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-doc
Path: blob/main/documentation/content/en/books/arch-handbook/pci/_index.po
18099 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/pci/_index.adoc:1
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:14
#, 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:52
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:54
#, no-wrap
msgid "Probe and Attach"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:57
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:58
#, no-wrap
msgid "Sample Driver Source ([.filename]#mypci.c#)"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:67
#, 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:77
#, 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:81
#, 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:84
#, 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:90
#, 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:96
#, 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:98
#, no-wrap
msgid "/* Character device entry points */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:107
#, 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:113
#, 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:118
#, 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:124
#, 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:129
#, 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:135
#, 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:140
#, 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:146
#, 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:151
#, 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:157
#, 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:159
#, no-wrap
msgid "/* PCI Support Functions */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:167
#, 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:170
#, 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:178
#, 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:180
#, 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:185
#, 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:187
#, 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:191
#, 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:204
#, 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:206
#, no-wrap
msgid "/* Detach device. */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:211
#, 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:218
#, 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:220
#, no-wrap
msgid "/* Called during system shutdown after sync. */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:224
#, 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:228
#, 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:235
#, 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:239
#, 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:246
#, 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:250
#, 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:259
#, 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:262
#, no-wrap
msgid ""
"\tDEVMETHOD_END\n"
"};\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:264
#, no-wrap
msgid "static devclass_t mypci_devclass;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:267
#, 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:269
#, no-wrap
msgid "[.filename]#Makefile# for Sample Driver"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:274
#, no-wrap
msgid "# Makefile for mypci driver\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:278
#, 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:280
#, no-wrap
msgid ".include <bsd.kmod.mk>\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:283
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:284
#, no-wrap
msgid "Additional Resources"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:287
msgid "http://www.pcisig.org/[PCI Special Interest Group]"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:288
msgid "PCI System Architecture, Fourth Edition by Tom Shanley, et al."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:290
#, no-wrap
msgid "Bus Resources"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:293
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:294
#, no-wrap
msgid "Base Address Registers"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:297
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:299
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:310
#, 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:323
#, 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:326
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:328
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:336
#, 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:339
msgid "Similarly, one could write to the registers with:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:347
#, 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:350
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:354
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:362
#, 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:366
#, no-wrap
msgid "Interrupts"
msgstr ""

#. type: delimited block = 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:369
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:371
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:375
#, no-wrap
msgid "/* Get the IRQ resource */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:384
#, 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:386
#, 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:393
#, 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:396
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:397
#, no-wrap
msgid "DMA"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:400
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:402
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:407
#, 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:409
#, no-wrap
msgid "#define vtophys(virtual_address) (...)\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/pci/_index.adoc:412
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:420
#, 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:422
#, no-wrap
msgid "Deallocating Resources"
msgstr ""

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