# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # FIRST AUTHOR , 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 \n" "Language-Team: LANGUAGE \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 \t\t/* defines used in kernel.h */\n" "#include \n" "#include \n" "#include \n" "#include \t\t/* types used in module initialization */\n" "#include \t\t/* cdevsw struct */\n" "#include \t\t/* uio struct */\n" "#include \n" "#include \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 \n" "#include \n" "#include \n" msgstr "" #. type: delimited block . 4 #: documentation/content/en/books/arch-handbook/pci/_index.adoc:84 #, no-wrap msgid "" "#include \t/* For pci_get macros! */\n" "#include \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\".\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 \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 \n" "#include \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 ""