Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-doc
Path: blob/main/documentation/content/en/books/arch-handbook/isa/_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/isa/_index.adoc:1
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:14
#, no-wrap
msgid "ISA Device Drivers"
msgstr ""

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

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

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:55
msgid ""
"This chapter introduces the issues relevant to writing a driver for an ISA "
"device. The pseudo-code presented here is rather detailed and reminiscent of "
"the real code but is still only pseudo-code. It avoids the details "
"irrelevant to the subject of the discussion. The real-life examples can be "
"found in the source code of real drivers. In particular the drivers `ep` and "
"`aha` are good sources of information."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:57
#, no-wrap
msgid "Basic Information"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:60
msgid "A typical ISA driver would need the following include files:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:68
#, no-wrap
msgid ""
"#include <sys/module.h>\n"
"#include <sys/bus.h>\n"
"#include <machine/bus.h>\n"
"#include <machine/resource.h>\n"
"#include <sys/rman.h>\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:71
#, no-wrap
msgid ""
"#include <isa/isavar.h>\n"
"#include <isa/pnpvar.h>\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:74
msgid "They describe the things specific to the ISA and generic bus subsystem."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:76
msgid ""
"The bus subsystem is implemented in an object-oriented fashion, its main "
"structures are accessed by associated method functions."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:78
msgid ""
"The list of bus methods implemented by an ISA driver is like one for any "
"other bus. For a hypothetical driver named \"xxx\" they would be:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:80
msgid ""
"`static void xxx_isa_identify (driver_t *, device_t);` Normally used for bus "
"drivers, not device drivers. But for ISA devices this method may have "
"special use: if the device provides some device-specific (non-PnP) way to "
"auto-detect devices this routine may implement it."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:81
msgid ""
"`static int xxx_isa_probe (device_t dev);` Probe for a device at a known (or "
"PnP) location. This routine can also accommodate device-specific auto-"
"detection of parameters for partially configured devices."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:82
msgid ""
"`static int xxx_isa_attach (device_t dev);` Attach and initialize device."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:83
msgid ""
"`static int xxx_isa_detach (device_t dev);` Detach device before unloading "
"the driver module."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:84
msgid ""
"`static int xxx_isa_shutdown (device_t dev);` Execute shutdown of the device "
"before system shutdown."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:85
msgid ""
"`static int xxx_isa_suspend (device_t dev);` Suspend the device before the "
"system goes to the power-save state. May also abort transition to the power-"
"save state."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:86
msgid ""
"`static int xxx_isa_resume (device_t dev);` Resume the device activity after "
"return from power-save state."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:88
msgid ""
"`xxx_isa_probe()` and `xxx_isa_attach()` are mandatory, the rest of the "
"routines are optional, depending on the device's needs."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:90
msgid ""
"The driver is linked to the system with the following set of descriptions."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:104
#, no-wrap
msgid ""
"    /* table of supported bus methods */\n"
"    static device_method_t xxx_isa_methods[] = {\n"
"        /* list all the bus method functions supported by the driver */\n"
"        /* omit the unsupported methods */\n"
"        DEVMETHOD(device_identify,  xxx_isa_identify),\n"
"        DEVMETHOD(device_probe,     xxx_isa_probe),\n"
"        DEVMETHOD(device_attach,    xxx_isa_attach),\n"
"        DEVMETHOD(device_detach,    xxx_isa_detach),\n"
"        DEVMETHOD(device_shutdown,  xxx_isa_shutdown),\n"
"        DEVMETHOD(device_suspend,   xxx_isa_suspend),\n"
"        DEVMETHOD(device_resume,    xxx_isa_resume),\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:107
#, no-wrap
msgid ""
"\tDEVMETHOD_END\n"
"    };\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:113
#, no-wrap
msgid ""
"    static driver_t xxx_isa_driver = {\n"
"        \"xxx\",\n"
"        xxx_isa_methods,\n"
"        sizeof(struct xxx_softc),\n"
"    };\n"
msgstr ""

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

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:118
#, no-wrap
msgid ""
"    DRIVER_MODULE(xxx, isa, xxx_isa_driver, xxx_devclass,\n"
"        load_function, load_argument);\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:121
msgid ""
"Here struct `xxx_softc` is a device-specific structure that contains private "
"driver data and descriptors for the driver's resources. The bus code "
"automatically allocates one softc descriptor per device as needed."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:123
msgid ""
"If the driver is implemented as a loadable module then `load_function()` is "
"called to do driver-specific initialization or clean-up when the driver is "
"loaded or unloaded and load_argument is passed as one of its arguments. If "
"the driver does not support dynamic loading (in other words it must always "
"be linked into the kernel) then these values should be set to 0 and the last "
"definition would look like:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:128
#, no-wrap
msgid ""
" DRIVER_MODULE(xxx, isa, xxx_isa_driver,\n"
"       xxx_devclass, 0, 0);\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:131
msgid ""
"If the driver is for a device which supports PnP then a table of supported "
"PnP IDs must be defined. The table consists of a list of PnP IDs supported "
"by this driver and human-readable descriptions of the hardware types and "
"models having these IDs. It looks like:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:140
#, no-wrap
msgid ""
"    static struct isa_pnp_id xxx_pnp_ids[] = {\n"
"        /* a line for each supported PnP ID */\n"
"        { 0x12345678,   \"Our device model 1234A\" },\n"
"        { 0x12345679,   \"Our device model 1234B\" },\n"
"        { 0,        NULL }, /* end of table */\n"
"    };\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:143
msgid ""
"If the driver does not support PnP devices it still needs an empty PnP ID "
"table, like:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:149
#, no-wrap
msgid ""
"    static struct isa_pnp_id xxx_pnp_ids[] = {\n"
"        { 0,        NULL }, /* end of table */\n"
"    };\n"
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:152
#, no-wrap
msgid "`device_t` Pointer"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:155
msgid ""
"`device_t` is the pointer type for the device structure. Here we consider "
"only the methods interesting from the device driver writer's standpoint. The "
"methods to manipulate values in the device structure are:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:157
msgid "`device_t device_get_parent(dev)` Get the parent bus of a device."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:158
msgid "`driver_t device_get_driver(dev)` Get pointer to its driver structure."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:159
msgid ""
"`char *device_get_name(dev)` Get the driver name, such as `\"xxx\"` for our "
"example."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:160
msgid ""
"`int device_get_unit(dev)` Get the unit number (units are numbered from 0 "
"for the devices associated with each driver)."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:161
msgid ""
"`char *device_get_nameunit(dev)` Get the device name including the unit "
"number, such as \"xxx0\", \"xxx1\" and so on."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:162
msgid ""
"`char *device_get_desc(dev)` Get the device description. Normally it "
"describes the exact model of device in human-readable form."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:163
msgid ""
"`device_set_desc(dev, desc)` Set the description. This makes the device "
"description point to the string desc which may not be deallocated or changed "
"after that."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:164
msgid ""
"`device_set_desc_copy(dev, desc)` Set the description. The description is "
"copied into an internal dynamically allocated buffer, so the string desc may "
"be changed afterwards without adverse effects."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:165
msgid ""
"`void *device_get_softc(dev)` Get pointer to the device descriptor (struct "
"`xxx_softc`) associated with this device."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:166
msgid ""
"`u_int32_t device_get_flags(dev)` Get the flags specified for the device in "
"the configuration file."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:168
msgid ""
"A convenience function `device_printf(dev, fmt, ...)` may be used to print "
"the messages from the device driver. It automatically prepends the unitname "
"and colon to the message."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:170
msgid ""
"The device_t methods are implemented in the file [.filename]#kern/"
"bus_subr.c#."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:172
#, no-wrap
msgid "Configuration File and the Order of Identifying and Probing During Auto-Configuration"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:175
msgid "The ISA devices are described in the kernel configuration file like:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:180
#, no-wrap
msgid ""
"device xxx0 at isa? port 0x300 irq 10 drq 5\n"
"       iomem 0xd0000 flags 0x1 sensitive\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:183
msgid ""
"The values of port, IRQ and so on are converted to the resource values "
"associated with the device. They are optional, depending on the device's "
"needs and abilities for auto-configuration. For example, some devices do not "
"need DRQ at all and some allow the driver to read the IRQ setting from the "
"device configuration ports. If a machine has multiple ISA buses the exact "
"bus may be specified in the configuration line, like `isa0` or `isa1`, "
"otherwise the device would be searched for on all the ISA buses."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:185
msgid ""
"`sensitive` is a resource requesting that this device must be probed before "
"all non-sensitive devices. It is supported but does not seem to be used in "
"any current driver."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:187
msgid ""
"For legacy ISA devices in many cases the drivers are still able to detect "
"the configuration parameters. But each device to be configured in the system "
"must have a config line. If two devices of some type are installed in the "
"system but there is only one configuration line for the corresponding "
"driver, ie:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:190
#, no-wrap
msgid "device xxx0 at isa?\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:192
#, no-wrap
msgid " then only one device will be configured.\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:194
msgid ""
"But for the devices supporting automatic identification by the means of Plug-"
"n-Play or some proprietary protocol one configuration line is enough to "
"configure all the devices in the system, like the one above or just simply:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:198
#, no-wrap
msgid "device xxx at isa?\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:201
msgid ""
"If a driver supports both auto-identified and legacy devices and both kinds "
"are installed at once in one machine then it is enough to describe in the "
"config file the legacy devices only. The auto-identified devices will be "
"added automatically."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:203
msgid "When an ISA bus is auto-configured the events happen as follows:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:205
msgid ""
"All the drivers' identify routines (including the PnP identify routine which "
"identifies all the PnP devices) are called in random order. As they identify "
"the devices they add them to the list on the ISA bus. Normally the drivers' "
"identify routines associate their drivers with the new devices. The PnP "
"identify routine does not know about the other drivers yet so it does not "
"associate any with the new devices it adds."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:207
msgid ""
"The PnP devices are put to sleep using the PnP protocol to prevent them from "
"being probed as legacy devices."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:209
msgid ""
"The probe routines of non-PnP devices marked as `sensitive` are called. If "
"probe for a device went successfully, the attach routine is called for it."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:211
msgid ""
"The probe and attach routines of all non-PNP devices are called likewise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:213
msgid ""
"The PnP devices are brought back from the sleep state and assigned the "
"resources they request: I/O and memory address ranges, IRQs and DRQs, all of "
"them not conflicting with the attached legacy devices."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:215
msgid ""
"Then for each PnP device the probe routines of all the present ISA drivers "
"are called. The first one that claims the device gets attached. It is "
"possible that multiple drivers would claim the device with different "
"priority; in this case, the highest-priority driver wins. The probe routines "
"must call `ISA_PNP_PROBE()` to compare the actual PnP ID with the list of "
"the IDs supported by the driver and if the ID is not in the table return "
"failure. That means that absolutely every driver, even the ones not "
"supporting any PnP devices must call `ISA_PNP_PROBE()`, at least with an "
"empty PnP ID table to return failure on unknown PnP devices."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:217
msgid ""
"The probe routine returns a positive value (the error code) on error, zero "
"or negative value on success."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:219
msgid ""
"The negative return values are used when a PnP device supports multiple "
"interfaces. For example, an older compatibility interface and a newer "
"advanced interface which are supported by different drivers. Then both "
"drivers would detect the device. The driver which returns a higher value in "
"the probe routine takes precedence (in other words, the driver returning 0 "
"has highest precedence, returning -1 is next, returning -2 is after it and "
"so on). In result the devices which support only the old interface will be "
"handled by the old driver (which should return -1 from the probe routine) "
"while the devices supporting the new interface as well will be handled by "
"the new driver (which should return 0 from the probe routine). If multiple "
"drivers return the same value then the one called first wins. So if a driver "
"returns value 0 it may be sure that it won the priority arbitration."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:221
msgid ""
"The device-specific identify routines can also assign not a driver but a "
"class of drivers to the device. Then all the drivers in the class are probed "
"for this device, like the case with PnP. This feature is not implemented in "
"any existing driver and is not considered further in this document."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:223
msgid ""
"As the PnP devices are disabled when probing the legacy devices they will "
"not be attached twice (once as legacy and once as PnP). But in case of "
"device-dependent identify routines it is the responsibility of the driver to "
"make sure that the same device will not be attached by the driver twice: "
"once as legacy user-configured and once as auto-identified."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:225
msgid ""
"Another practical consequence for the auto-identified devices (both PnP and "
"device-specific) is that the flags can not be passed to them from the kernel "
"configuration file. So they must either not use the flags at all or use the "
"flags from the device unit 0 for all the auto-identified devices or use the "
"sysctl interface instead of flags."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:227
msgid ""
"Other unusual configurations may be accommodated by accessing the "
"configuration resources directly with functions of families "
"`resource_query_*()` and `resource_*_value()`. Their implementations are "
"located in [.filename]#kern/subr_bus.c#. The old IDE disk driver "
"[.filename]#i386/isa/wd.c# contains examples of such use. But the standard "
"means of configuration must always be preferred. Leave parsing the "
"configuration resources to the bus configuration code."
msgstr ""

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

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:232
msgid ""
"The information that a user enters into the kernel configuration file is "
"processed and passed to the kernel as configuration resources. This "
"information is parsed by the bus configuration code and transformed into a "
"value of structure device_t and the bus resources associated with it. The "
"drivers may access the configuration resources directly using functions "
"`resource_*` for more complex cases of configuration. However, generally "
"this is neither needed nor recommended, so this issue is not discussed "
"further here."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:234
msgid ""
"The bus resources are associated with each device. They are identified by "
"type and number within the type. For the ISA bus the following types are "
"defined:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:236
msgid "_SYS_RES_IRQ_ - interrupt number"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:237
msgid "_SYS_RES_DRQ_ - ISA DMA channel number"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:238
msgid ""
"_SYS_RES_MEMORY_ - range of device memory mapped into the system memory space"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:239
msgid "_SYS_RES_IOPORT_ - range of device I/O registers"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:241
msgid ""
"The enumeration within types starts from 0, so if a device has two memory "
"regions it would have resources of type `SYS_RES_MEMORY` numbered 0 and 1. "
"The resource type has nothing to do with the C language type, all the "
"resource values have the C language type `unsigned long` and must be cast as "
"necessary. The resource numbers do not have to be contiguous, although for "
"ISA they normally would be. The permitted resource numbers for ISA devices "
"are:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:248
#, no-wrap
msgid ""
"          IRQ: 0-1\n"
"          DRQ: 0-1\n"
"          MEMORY: 0-3\n"
"          IOPORT: 0-7\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:251
msgid ""
"All the resources are represented as ranges, with a start value and count. "
"For IRQ and DRQ resources the count would normally be equal to 1. The values "
"for memory refer to the physical addresses."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:253
msgid "Three types of activities can be performed on resources:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:255
msgid "set/get"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:256
msgid "allocate/release"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:257
msgid "activate/deactivate"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:259
msgid ""
"Setting sets the range used by the resource. Allocation reserves the "
"requested range that no other driver would be able to reserve it (and "
"checking that no other driver reserved this range already). Activation makes "
"the resource accessible to the driver by doing whatever is necessary for "
"that (for example, for memory it would be mapping into the kernel virtual "
"address space)."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:261
msgid "The functions to manipulate resources are:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:263
msgid ""
"`int bus_set_resource(device_t dev, int type, int rid, u_long start, u_long "
"count)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:265
msgid ""
"Set a range for a resource. Returns 0 if successful, error code otherwise. "
"Normally, this function will return an error only if one of `type`, `rid`, "
"`start` or `count` has a value that falls out of the permitted range."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:267
msgid "dev - driver's device"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:268
msgid "type - type of resource, SYS_RES_*"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:269
msgid "rid - resource number (ID) within type"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:270
msgid "start, count - resource range"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:272
msgid ""
"`int bus_get_resource(device_t dev, int type, int rid, u_long *startp, "
"u_long *countp)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:274
msgid ""
"Get the range of resource. Returns 0 if successful, error code if the "
"resource is not defined yet."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:275
msgid ""
"`u_long bus_get_resource_start(device_t dev, int type, int rid) u_long "
"bus_get_resource_count (device_t dev, int type, int rid)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:277
msgid ""
"Convenience functions to get only the start or count. Return 0 in case of "
"error, so if the resource start has 0 among the legitimate values it would "
"be impossible to tell if the value is 0 or an error occurred. Luckily, no "
"ISA resources for add-on drivers may have a start value equal to 0."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:278
msgid "`void bus_delete_resource(device_t dev, int type, int rid)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:280
msgid "Delete a resource, make it undefined."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:281
msgid ""
"`struct resource * bus_alloc_resource(device_t dev, int type, int *rid, "
"u_long start, u_long end, u_long count, u_int flags)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:283
msgid ""
"Allocate a resource as a range of count values not allocated by anyone else, "
"somewhere between start and end. Alas, alignment is not supported. If the "
"resource was not set yet it is automatically created. The special values of "
"start 0 and end ~0 (all ones) means that the fixed values previously set by "
"`bus_set_resource()` must be used instead: start and count as themselves and "
"end=(start+count), in this case if the resource was not defined before then "
"an error is returned. Although rid is passed by reference it is not set "
"anywhere by the resource allocation code of the ISA bus. (The other buses "
"may use a different approach and modify it)."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:285
msgid "Flags are a bitmap, the flags interesting for the caller are:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:287
msgid ""
"_RF_ACTIVE_ - causes the resource to be automatically activated after "
"allocation."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:288
msgid ""
"_RF_SHAREABLE_ - resource may be shared at the same time by multiple drivers."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:289
msgid ""
"_RF_TIMESHARE_ - resource may be time-shared by multiple drivers, i.e., "
"allocated at the same time by many but activated only by one at any given "
"moment of time."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:290
msgid ""
"Returns 0 on error. The allocated values may be obtained from the returned "
"handle using methods `rhand_*()`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:291
msgid ""
"`int bus_release_resource(device_t dev, int type, int rid, struct resource "
"*r)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:292
msgid ""
"Release the resource, r is the handle returned by `bus_alloc_resource()`. "
"Returns 0 on success, error code otherwise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:293
msgid ""
"`int bus_activate_resource(device_t dev, int type, int rid, struct resource "
"*r) int bus_deactivate_resource(device_t dev, int type, int rid, struct "
"resource *r)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:294
msgid ""
"Activate or deactivate resource. Return 0 on success, error code otherwise. "
"If the resource is time-shared and currently activated by another driver "
"then `EBUSY` is returned."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:295
msgid ""
"`int bus_setup_intr(device_t dev, struct resource *r, int flags, "
"driver_intr_t *handler, void *arg, void **cookiep) int "
"bus_teardown_intr(device_t dev, struct resource *r, void *cookie)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:296
msgid ""
"Associate or de-associate the interrupt handler with a device. Return 0 on "
"success, error code otherwise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:297
msgid "r - the activated resource handler describing the IRQ"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:299
msgid "flags - the interrupt priority level, one of:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:301
msgid ""
"`INTR_TYPE_TTY` - terminals and other likewise character-type devices. To "
"mask them use `spltty()`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:302
msgid ""
"`(INTR_TYPE_TTY | INTR_TYPE_FAST)` - terminal type devices with small input "
"buffer, critical to the data loss on input (such as the old-fashioned serial "
"ports). To mask them use `spltty()`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:303
msgid ""
"`INTR_TYPE_BIO` - block-type devices, except those on the CAM controllers. "
"To mask them use `splbio()`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:304
msgid ""
"`INTR_TYPE_CAM` - CAM (Common Access Method) bus controllers. To mask them "
"use `splcam()`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:305
msgid ""
"`INTR_TYPE_NET` - network interface controllers. To mask them use `splimp()`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:306
msgid ""
"`INTR_TYPE_MISC` - miscellaneous devices. There is no other way to mask them "
"than by `splhigh()` which masks all interrupts."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:308
msgid ""
"When an interrupt handler executes all the other interrupts matching its "
"priority level will be masked. The only exception is the MISC level for "
"which no other interrupts are masked and which is not masked by any other "
"interrupt."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:310
msgid ""
"_handler_ - pointer to the handler function, the type driver_intr_t is "
"defined as `void driver_intr_t(void *)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:311
msgid ""
"_arg_ - the argument passed to the handler to identify this particular "
"device. It is cast from void* to any real type by the handler. The old "
"convention for the ISA interrupt handlers was to use the unit number as "
"argument, the new (recommended) convention is using a pointer to the device "
"softc structure."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:312
msgid ""
"_cookie[p]_ - the value received from `setup()` is used to identify the "
"handler when passed to `teardown()`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:314
msgid ""
"A number of methods are defined to operate on the resource handlers (struct "
"resource *). Those of interest to the device driver writers are:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:316
msgid ""
"`u_long rman_get_start(r) u_long rman_get_end(r)` Get the start and end of "
"allocated resource range."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:317
msgid ""
"`void *rman_get_virtual(r)` Get the virtual address of activated memory "
"resource."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:319
#, no-wrap
msgid "Bus Memory Mapping"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:322
msgid ""
"In many cases data is exchanged between the driver and the device through "
"the memory. Two variants are possible:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:324
msgid "(a) memory is located on the device card"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:326
msgid "(b) memory is the main memory of the computer"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:328
msgid ""
"In case (a) the driver always copies the data back and forth between the on-"
"card memory and the main memory as necessary. To map the on-card memory into "
"the kernel virtual address space the physical address and length of the on-"
"card memory must be defined as a `SYS_RES_MEMORY` resource. That resource "
"can then be allocated and activated, and its virtual address obtained using "
"`rman_get_virtual()`. The older drivers used the function `pmap_mapdev()` "
"for this purpose, which should not be used directly any more. Now it is one "
"of the internal steps of resource activation."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:330
msgid ""
"Most of the ISA cards will have their memory configured for physical "
"location somewhere in range 640KB-1MB. Some of the ISA cards require larger "
"memory ranges which should be placed somewhere under 16MB (because of the 24-"
"bit address limitation on the ISA bus). In that case if the machine has more "
"memory than the start address of the device memory (in other words, they "
"overlap) a memory hole must be configured at the address range used by "
"devices. Many BIOSes allow configuration of a memory hole of 1MB starting at "
"14MB or 15MB. FreeBSD can handle the memory holes properly if the BIOS "
"reports them properly (this feature may be broken on old BIOSes)."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:332
msgid ""
"In case (b) just the address of the data is sent to the device, and the "
"device uses DMA to actually access the data in the main memory. Two "
"limitations are present: First, ISA cards can only access memory below 16MB. "
"Second, the contiguous pages in virtual address space may not be contiguous "
"in physical address space, so the device may have to do scatter/gather "
"operations. The bus subsystem provides ready solutions for some of these "
"problems, the rest has to be done by the drivers themselves."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:334
msgid ""
"Two structures are used for DMA memory allocation, `bus_dma_tag_t` and "
"`bus_dmamap_t`. Tag describes the properties required for the DMA memory. "
"Map represents a memory block allocated according to these properties. "
"Multiple maps may be associated with the same tag."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:336
msgid ""
"Tags are organized into a tree-like hierarchy with inheritance of the "
"properties. A child tag inherits all the requirements of its parent tag, and "
"may make them more strict but never more loose."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:338
msgid ""
"Normally one top-level tag (with no parent) is created for each device unit. "
"If multiple memory areas with different requirements are needed for each "
"device then a tag for each of them may be created as a child of the parent "
"tag."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:340
msgid "The tags can be used to create a map in two ways."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:342
msgid ""
"First, a chunk of contiguous memory conformant with the tag requirements may "
"be allocated (and later may be freed). This is normally used to allocate "
"relatively long-living areas of memory for communication with the device. "
"Loading of such memory into a map is trivial: it is always considered as one "
"chunk in the appropriate physical memory range."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:344
msgid ""
"Second, an arbitrary area of virtual memory may be loaded into a map. Each "
"page of this memory will be checked for conformance to the map requirement. "
"If it conforms then it is left at its original location. If it is not then a "
"fresh conformant \"bounce page\" is allocated and used as intermediate "
"storage. When writing the data from the non-conformant original pages they "
"will be copied to their bounce pages first and then transferred from the "
"bounce pages to the device. When reading the data would go from the device "
"to the bounce pages and then copied to their non-conformant original pages. "
"The process of copying between the original and bounce pages is called "
"synchronization. This is normally used on a per-transfer basis: buffer for "
"each transfer would be loaded, transfer done and buffer unloaded."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:346
msgid "The functions working on the DMA memory are:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:348
msgid ""
"`int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, "
"bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, "
"bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, int "
"nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:350
msgid "Create a new tag. Returns 0 on success, the error code otherwise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:352
msgid "_parent_ - parent tag, or NULL to create a top-level tag."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:353
msgid ""
"_alignment_ - required physical alignment of the memory area to be allocated "
"for this tag. Use value 1 for \"no specific alignment\". Applies only to the "
"future `bus_dmamem_alloc()` but not `bus_dmamap_create()` calls."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:354
msgid ""
"_boundary_ - physical address boundary that must not be crossed when "
"allocating the memory. Use value 0 for \"no boundary\". Applies only to the "
"future `bus_dmamem_alloc()` but not `bus_dmamap_create()` calls. Must be "
"power of 2. If the memory is planned to be used in non-cascaded DMA mode "
"(i.e., the DMA addresses will be supplied not by the device itself but by "
"the ISA DMA controller) then the boundary must be no larger than 64KB "
"(64*1024) due to the limitations of the DMA hardware."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:355
msgid ""
"_lowaddr, highaddr_ - the names are slightly misleading; these values are "
"used to limit the permitted range of physical addresses used to allocate the "
"memory. The exact meaning varies depending on the planned future use:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:357
msgid ""
"For `bus_dmamem_alloc()` all the addresses from 0 to lowaddr-1 are "
"considered permitted, the higher ones are forbidden."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:358
msgid ""
"For `bus_dmamap_create()` all the addresses outside the inclusive range "
"[lowaddr; highaddr] are considered accessible. The addresses of pages inside "
"the range are passed to the filter function which decides if they are "
"accessible. If no filter function is supplied then all the range is "
"considered unaccessible."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:359
msgid "For the ISA devices the normal values (with no filter function) are:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:361
msgid "lowaddr = BUS_SPACE_MAXADDR_24BIT"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:363
msgid "highaddr = BUS_SPACE_MAXADDR"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:365
msgid ""
"_filter, filterarg_ - the filter function and its argument. If NULL is "
"passed for filter then the whole range [lowaddr, highaddr] is considered "
"unaccessible when doing `bus_dmamap_create()`. Otherwise the physical "
"address of each attempted page in range [lowaddr; highaddr] is passed to the "
"filter function which decides if it is accessible. The prototype of the "
"filter function is: `int filterfunc(void *arg, bus_addr_t paddr)`. It must "
"return 0 if the page is accessible, non-zero otherwise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:366
msgid ""
"_maxsize_ - the maximal size of memory (in bytes) that may be allocated "
"through this tag. In case it is difficult to estimate or could be "
"arbitrarily big, the value for ISA devices would be "
"`BUS_SPACE_MAXSIZE_24BIT`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:367
msgid ""
"_nsegments_ - maximal number of scatter-gather segments supported by the "
"device. If unrestricted then the value `BUS_SPACE_UNRESTRICTED` should be "
"used. This value is recommended for the parent tags, the actual restrictions "
"would then be specified for the descendant tags. Tags with nsegments equal "
"to `BUS_SPACE_UNRESTRICTED` may not be used to actually load maps, they may "
"be used only as parent tags. The practical limit for nsegments seems to be "
"about 250-300, higher values will cause kernel stack overflow (the hardware "
"can not normally support that many scatter-gather buffers anyway)."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:368
msgid ""
"_maxsegsz_ - maximal size of a scatter-gather segment supported by the "
"device. The maximal value for ISA device would be `BUS_SPACE_MAXSIZE_24BIT`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:369
msgid "_flags_ - a bitmap of flags. The only interesting flag is:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:371
msgid ""
"_BUS_DMA_ALLOCNOW_ - requests to allocate all the potentially needed bounce "
"pages when creating the tag."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:373
msgid "_dmat_ - pointer to the storage for the new tag to be returned."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:375
msgid "`int bus_dma_tag_destroy(bus_dma_tag_t dmat)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:377
msgid "Destroy a tag. Returns 0 on success, the error code otherwise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:379
msgid "dmat - the tag to be destroyed."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:380
msgid ""
"`int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, "
"bus_dmamap_t *mapp)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:382
msgid ""
"Allocate an area of contiguous memory described by the tag. The size of "
"memory to be allocated is tag's maxsize. Returns 0 on success, the error "
"code otherwise. The result still has to be loaded by `bus_dmamap_load()` "
"before being used to get the physical address of the memory."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:384
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:396
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:404
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:419
msgid "_dmat_ - the tag"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:385
msgid ""
"_vaddr_ - pointer to the storage for the kernel virtual address of the "
"allocated area to be returned."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:386
msgid "flags - a bitmap of flags. The only interesting flag is:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:388
msgid ""
"_BUS_DMA_NOWAIT_ - if the memory is not immediately available return the "
"error. If this flag is not set then the routine is allowed to sleep until "
"the memory becomes available."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:390
msgid "_mapp_ - pointer to the storage for the new map to be returned."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:392
msgid ""
"`void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:394
msgid ""
"Free the memory allocated by `bus_dmamem_alloc()`. At present, freeing of "
"the memory allocated with ISA restrictions is not implemented. Due to this "
"the recommended model of use is to keep and re-use the allocated areas for "
"as long as possible. Do not lightly free some area and then shortly allocate "
"it again. That does not mean that `bus_dmamem_free()` should not be used at "
"all: hopefully it will be properly implemented soon."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:397
msgid "_vaddr_ - the kernel virtual address of the memory"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:398
msgid "_map_ - the map of the memory (as returned from `bus_dmamem_alloc()`)"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:400
msgid ""
"`int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:402
msgid ""
"Create a map for the tag, to be used in `bus_dmamap_load()` later. Returns 0 "
"on success, the error code otherwise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:405
msgid ""
"_flags_ - theoretically, a bit map of flags. But no flags are defined yet, "
"so at present it will be always 0."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:406
msgid "_mapp_ - pointer to the storage for the new map to be returned"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:408
msgid "`int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:410
msgid "Destroy a map. Returns 0 on success, the error code otherwise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:412
msgid "dmat - the tag to which the map is associated"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:413
msgid "map - the map to be destroyed"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:415
msgid ""
"`int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, "
"bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, int "
"flags)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:417
msgid ""
"Load a buffer into the map (the map must be previously created by "
"`bus_dmamap_create()` or `bus_dmamem_alloc()`). All the pages of the buffer "
"are checked for conformance to the tag requirements and for those not "
"conformant the bounce pages are allocated. An array of physical segment "
"descriptors is built and passed to the callback routine. This callback "
"routine is then expected to handle it in some way. The number of bounce "
"buffers in the system is limited, so if the bounce buffers are needed but "
"not immediately available the request will be queued and the callback will "
"be called when the bounce buffers will become available. Returns 0 if the "
"callback was executed immediately or `EINPROGRESS` if the request was queued "
"for future execution. In the latter case the synchronization with queued "
"callback routine is the responsibility of the driver."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:420
msgid "_map_ - the map"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:421
msgid "_buf_ - kernel virtual address of the buffer"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:422
msgid "_buflen_ - length of the buffer"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:423
msgid "_callback_, `callback_arg` - the callback function and its argument"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:425
msgid ""
"The prototype of callback function is: `void callback(void *arg, "
"bus_dma_segment_t *seg, int nseg, int error)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:427
msgid "_arg_ - the same as callback_arg passed to `bus_dmamap_load()`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:428
msgid "_seg_ - array of the segment descriptors"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:429
msgid "_nseg_ - number of descriptors in array"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:430
msgid ""
"_error_ - indication of the segment number overflow: if it is set to `EFBIG` "
"then the buffer did not fit into the maximal number of segments permitted by "
"the tag. In this case only the permitted number of descriptors will be in "
"the array. Handling of this situation is up to the driver: depending on the "
"desired semantics it can either consider this an error or split the buffer "
"in two and handle the second part separately"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:432
msgid "Each entry in the segments array contains the fields:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:434
msgid "_ds_addr_ - physical bus address of the segment"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:435
msgid "_ds_len_ - length of the segment"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:437
msgid "`void bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:439
msgid "unload the map."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:441
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:448
msgid "_dmat_ - tag"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:442
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:449
msgid "_map_ - loaded map"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:444
msgid ""
"`void bus_dmamap_sync (bus_dma_tag_t dmat, bus_dmamap_t map, "
"bus_dmasync_op_t op)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:446
msgid ""
"Synchronise a loaded buffer with its bounce pages before and after physical "
"transfer to or from device. This is the function that does all the necessary "
"copying of data between the original buffer and its mapped version. The "
"buffers must be synchronized both before and after doing the transfer."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:450
msgid "_op_ - type of synchronization operation to perform:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:452
msgid "`BUS_DMASYNC_PREREAD` - before reading from device into buffer"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:453
msgid "`BUS_DMASYNC_POSTREAD` - after reading from device into buffer"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:454
msgid "`BUS_DMASYNC_PREWRITE` - before writing the buffer to device"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:455
msgid "`BUS_DMASYNC_POSTWRITE` - after writing the buffer to device"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:457
msgid ""
"As of now PREREAD and POSTWRITE are null operations but that may change in "
"the future, so they must not be ignored in the driver. Synchronization is "
"not needed for the memory obtained from `bus_dmamem_alloc()`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:459
msgid ""
"Before calling the callback function from `bus_dmamap_load()` the segment "
"array is stored in the stack. And it gets pre-allocated for the maximal "
"number of segments allowed by the tag. As a result of this the practical "
"limit for the number of segments on i386 architecture is about 250-300 (the "
"kernel stack is 4KB minus the size of the user structure, size of a segment "
"array entry is 8 bytes, and some space must be left). Since the array is "
"allocated based on the maximal number this value must not be set higher than "
"really needed. Fortunately, for most of hardware the maximal supported "
"number of segments is much lower. But if the driver wants to handle buffers "
"with a very large number of scatter-gather segments it should do that in "
"portions: load part of the buffer, transfer it to the device, load next part "
"of the buffer, and so on."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:461
msgid ""
"Another practical consequence is that the number of segments may limit the "
"size of the buffer. If all the pages in the buffer happen to be physically "
"non-contiguous then the maximal supported buffer size for that fragmented "
"case would be (nsegments * page_size). For example, if a maximal number of "
"10 segments is supported then on i386 maximal guaranteed supported buffer "
"size would be 40K. If a higher size is desired then special tricks should be "
"used in the driver."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:463
msgid ""
"If the hardware does not support scatter-gather at all or the driver wants "
"to support some buffer size even if it is heavily fragmented then the "
"solution is to allocate a contiguous buffer in the driver and use it as "
"intermediate storage if the original buffer does not fit."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:465
msgid ""
"Below are the typical call sequences when using a map depend on the use of "
"the map. The characters -> are used to show the flow of time."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:467
msgid ""
"For a buffer which stays practically fixed during all the time between "
"attachment and detachment of a device:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:469
msgid ""
"bus_dmamem_alloc -> bus_dmamap_load -> ...use buffer... -> -> "
"bus_dmamap_unload -> bus_dmamem_free"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:471
msgid ""
"For a buffer that changes frequently and is passed from outside the driver:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:480
#, no-wrap
msgid ""
"          bus_dmamap_create ->\n"
"          -> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->\n"
"          -> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->\n"
"          ...\n"
"          -> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->\n"
"          -> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->\n"
"          -> bus_dmamap_destroy\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:483
msgid ""
"When loading a map created by `bus_dmamem_alloc()` the passed address and "
"size of the buffer must be the same as used in `bus_dmamem_alloc()`. In this "
"case it is guaranteed that the whole buffer will be mapped as one segment "
"(so the callback may be based on this assumption) and the request will be "
"executed immediately (EINPROGRESS will never be returned). All the callback "
"needs to do in this case is to save the physical address."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:485
msgid "A typical example would be:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:493
#, no-wrap
msgid ""
"          static void\n"
"        alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)\n"
"        {\n"
"          *(bus_addr_t *)arg = seg[0].ds_addr;\n"
"        }\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:504
#, no-wrap
msgid ""
"          ...\n"
"          int error;\n"
"          struct somedata {\n"
"            ....\n"
"          };\n"
"          struct somedata *vsomedata; /* virtual address */\n"
"          bus_addr_t psomedata; /* physical bus-relative address */\n"
"          bus_dma_tag_t tag_somedata;\n"
"          bus_dmamap_t map_somedata;\n"
"          ...\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:512
#, no-wrap
msgid ""
"          error=bus_dma_tag_create(parent_tag, alignment,\n"
"           boundary, lowaddr, highaddr, /*filter*/ NULL, /*filterarg*/ NULL,\n"
"           /*maxsize*/ sizeof(struct somedata), /*nsegments*/ 1,\n"
"           /*maxsegsz*/ sizeof(struct somedata), /*flags*/ 0,\n"
"           &tag_somedata);\n"
"          if(error)\n"
"          return error;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:517
#, no-wrap
msgid ""
"          error = bus_dmamem_alloc(tag_somedata, &vsomedata, /* flags*/ 0,\n"
"             &map_somedata);\n"
"          if(error)\n"
"             return error;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:521
#, no-wrap
msgid ""
"          bus_dmamap_load(tag_somedata, map_somedata, (void *)vsomedata,\n"
"             sizeof (struct somedata), alloc_callback,\n"
"             (void *) &psomedata, /*flags*/0);\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:524
msgid ""
"Looks a bit long and complicated but that is the way to do it. The practical "
"consequence is: if multiple memory areas are allocated always together it "
"would be a really good idea to combine them all into one structure and "
"allocate as one (if the alignment and boundary limitations permit)."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:526
msgid ""
"When loading an arbitrary buffer into the map created by "
"`bus_dmamap_create()` special measures must be taken to synchronize with the "
"callback in case it would be delayed. The code would look like:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:532
#, no-wrap
msgid ""
"          {\n"
"           int s;\n"
"           int error;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:551
#, no-wrap
msgid ""
"           s = splsoftvm();\n"
"           error = bus_dmamap_load(\n"
"               dmat,\n"
"               dmamap,\n"
"               buffer_ptr,\n"
"               buffer_len,\n"
"               callback,\n"
"               /*callback_arg*/ buffer_descriptor,\n"
"               /*flags*/0);\n"
"           if (error == EINPROGRESS) {\n"
"               /*\n"
"                * Do whatever is needed to ensure synchronization\n"
"                * with callback. Callback is guaranteed not to be started\n"
"                * until we do splx() or tsleep().\n"
"                */\n"
"              }\n"
"           splx(s);\n"
"          }\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:554
msgid "Two possible approaches for the processing of requests are:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:556
msgid ""
"If requests are completed by marking them explicitly as done (such as the "
"CAM requests) then it would be simpler to put all the further processing "
"into the callback driver which would mark the request when it is done. Then "
"not much extra synchronization is needed. For the flow control reasons it "
"may be a good idea to freeze the request queue until this request gets "
"completed."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:558
msgid ""
"If requests are completed when the function returns (such as classic read or "
"write requests on character devices) then a synchronization flag should be "
"set in the buffer descriptor and `tsleep()` called. Later when the callback "
"gets called it will do its processing and check this synchronization flag. "
"If it is set then the callback should issue a wakeup. In this approach the "
"callback function could either do all the needed processing (just like the "
"previous case) or simply save the segments array in the buffer descriptor. "
"Then after callback completes the calling function could use this saved "
"segments array and do all the processing."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:560
#, no-wrap
msgid "DMA"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:563
msgid ""
"The Direct Memory Access (DMA) is implemented in the ISA bus through the DMA "
"controller (actually, two of them but that is an irrelevant detail). To make "
"the early ISA devices simple and cheap the logic of the bus control and "
"address generation was concentrated in the DMA controller. Fortunately, "
"FreeBSD provides a set of functions that mostly hide the annoying details of "
"the DMA controller from the device drivers."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:565
msgid ""
"The simplest case is for the fairly intelligent devices. Like the bus master "
"devices on PCI they can generate the bus cycles and memory addresses all by "
"themselves. The only thing they really need from the DMA controller is bus "
"arbitration. So for this purpose they pretend to be cascaded slave DMA "
"controllers. And the only thing needed from the system DMA controller is to "
"enable the cascaded mode on a DMA channel by calling the following function "
"when attaching the driver:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:567
msgid "`void isa_dmacascade(int channel_number)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:569
msgid ""
"All the further activity is done by programming the device. When detaching "
"the driver no DMA-related functions need to be called."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:571
msgid ""
"For the simpler devices things get more complicated. The functions used are:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:573
msgid "`int isa_dma_acquire(int chanel_number)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:575
msgid ""
"Reserve a DMA channel. Returns 0 on success or EBUSY if the channel was "
"already reserved by this or a different driver. Most of the ISA devices are "
"not able to share DMA channels anyway, so normally this function is called "
"when attaching a device. This reservation was made redundant by the modern "
"interface of bus resources but still must be used in addition to the latter. "
"If not used then later, other DMA routines will panic."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:576
msgid "`int isa_dma_release(int chanel_number)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:578
msgid ""
"Release a previously reserved DMA channel. No transfers must be in progress "
"when the channel is released (in addition the device must not try to "
"initiate transfer after the channel is released)."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:579
msgid "`void isa_dmainit(int chan, u_int bouncebufsize)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:581
msgid ""
"Allocate a bounce buffer for use with the specified channel. The requested "
"size of the buffer can not exceed 64KB. This bounce buffer will be "
"automatically used later if a transfer buffer happens to be not physically "
"contiguous or outside of the memory accessible by the ISA bus or crossing "
"the 64KB boundary. If the transfers will be always done from buffers which "
"conform to these conditions (such as those allocated by `bus_dmamem_alloc()` "
"with proper limitations) then `isa_dmainit()` does not have to be called. "
"But it is quite convenient to transfer arbitrary data using the DMA "
"controller. The bounce buffer will automatically care of the scatter-gather "
"issues."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:583
msgid "_chan_ - channel number"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:584
msgid "_bouncebufsize_ - size of the bounce buffer in bytes"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:586
msgid "`void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:588
msgid ""
"Prepare to start a DMA transfer. This function must be called to set up the "
"DMA controller before actually starting transfer on the device. It checks "
"that the buffer is contiguous and falls into the ISA memory range, if not "
"then the bounce buffer is automatically used. If bounce buffer is required "
"but not set up by `isa_dmainit()` or too small for the requested transfer "
"size then the system will panic. In case of a write request with bounce "
"buffer the data will be automatically copied to the bounce buffer."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:589
msgid ""
"flags - a bitmask determining the type of operation to be done. The "
"direction bits B_READ and B_WRITE are mutually exclusive."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:591
msgid "B_READ - read from the ISA bus into memory"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:592
msgid "B_WRITE - write from the memory to the ISA bus"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:593
msgid ""
"B_RAW - if set then the DMA controller will remember the buffer and after "
"the end of transfer will automatically re-initialize itself to repeat "
"transfer of the same buffer again (of course, the driver may change the data "
"in the buffer before initiating another transfer in the device). If not set "
"then the parameters will work only for one transfer, and `isa_dmastart()` "
"will have to be called again before initiating the next transfer. Using "
"B_RAW makes sense only if the bounce buffer is not used."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:595
msgid "addr - virtual address of the buffer"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:596
msgid ""
"nbytes - length of the buffer. Must be less or equal to 64KB. Length of 0 is "
"not allowed: the DMA controller will understand it as 64KB while the kernel "
"code will understand it as 0 and that would cause unpredictable effects. For "
"channels number 4 and higher the length must be even because these channels "
"transfer 2 bytes at a time. In case of an odd length the last byte will not "
"be transferred."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:597
msgid "chan - channel number"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:598
msgid "`void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:600
msgid ""
"Synchronize the memory after device reports that transfer is done. If that "
"was a read operation with a bounce buffer then the data will be copied from "
"the bounce buffer to the original buffer. Arguments are the same as for "
"`isa_dmastart()`. Flag B_RAW is permitted but it does not affect "
"`isa_dmadone()` in any way."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:601
msgid "`int isa_dmastatus(int channel_number)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:603
msgid ""
"Returns the number of bytes left in the current transfer to be transferred. "
"In case the flag B_READ was set in `isa_dmastart()` the number returned will "
"never be equal to zero. At the end of transfer it will be automatically "
"reset back to the length of buffer. The normal use is to check the number of "
"bytes left after the device signals that the transfer is completed. If the "
"number of bytes is not 0 then something probably went wrong with that "
"transfer."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:604
msgid "`int isa_dmastop(int channel_number)`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:606
msgid ""
"Aborts the current transfer and returns the number of bytes left "
"untransferred."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:608
#, no-wrap
msgid "xxx_isa_probe"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:611
msgid ""
"This function probes if a device is present. If the driver supports auto-"
"detection of some part of device configuration (such as interrupt vector or "
"memory address) this auto-detection must be done in this routine."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:613
msgid ""
"As for any other bus, if the device cannot be detected or is detected but "
"failed the self-test or some other problem happened then it returns a "
"positive value of error. The value `ENXIO` must be returned if the device is "
"not present. Other error values may mean other conditions. Zero or negative "
"values mean success. Most of the drivers return zero as success."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:615
msgid ""
"The negative return values are used when a PnP device supports multiple "
"interfaces. For example, an older compatibility interface and a newer "
"advanced interface which are supported by different drivers. Then both "
"drivers would detect the device. The driver which returns a higher value in "
"the probe routine takes precedence (in other words, the driver returning 0 "
"has highest precedence, one returning -1 is next, one returning -2 is after "
"it and so on). In result the devices which support only the old interface "
"will be handled by the old driver (which should return -1 from the probe "
"routine) while the devices supporting the new interface as well will be "
"handled by the new driver (which should return 0 from the probe routine)."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:617
msgid ""
"The device descriptor struct xxx_softc is allocated by the system before "
"calling the probe routine. If the probe routine returns an error the "
"descriptor will be automatically deallocated by the system. So if a probing "
"error occurs the driver must make sure that all the resources it used during "
"probe are deallocated and that nothing keeps the descriptor from being "
"safely deallocated. If the probe completes successfully the descriptor will "
"be preserved by the system and later passed to the routine "
"`xxx_isa_attach()`. If a driver returns a negative value it can not be sure "
"that it will have the highest priority and its attach routine will be "
"called. So in this case it also must release all the resources before "
"returning and if necessary allocate them again in the attach routine. When "
"`xxx_isa_probe()` returns 0 releasing the resources before returning is also "
"a good idea and a well-behaved driver should do so. But in cases where there "
"is some problem with releasing the resources the driver is allowed to keep "
"resources between returning 0 from the probe routine and execution of the "
"attach routine."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:619
msgid ""
"A typical probe routine starts with getting the device descriptor and unit:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:626
#, no-wrap
msgid ""
"         struct xxx_softc *sc = device_get_softc(dev);\n"
"          int unit = device_get_unit(dev);\n"
"          int pnperror;\n"
"          int error = 0;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:629
#, no-wrap
msgid ""
"          sc->dev = dev; /* link it back */\n"
"          sc->unit = unit;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:632
msgid ""
"Then check for the PnP devices. The check is carried out by a table "
"containing the list of PnP IDs supported by this driver and human-readable "
"descriptions of the device models corresponding to these IDs."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:638
#, no-wrap
msgid ""
"        pnperror=ISA_PNP_PROBE(device_get_parent(dev), dev,\n"
"        xxx_pnp_ids); if(pnperror == ENXIO) return ENXIO;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:641
msgid ""
"The logic of ISA_PNP_PROBE is the following: If this card (device unit) was "
"not detected as PnP then ENOENT will be returned. If it was detected as PnP "
"but its detected ID does not match any of the IDs in the table then ENXIO is "
"returned. Finally, if it has PnP support and it matches on of the IDs in the "
"table, 0 is returned and the appropriate description from the table is set "
"by `device_set_desc()`."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:643
msgid ""
"If a driver supports only PnP devices then the condition would look like:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:648
#, no-wrap
msgid ""
"          if(pnperror != 0)\n"
"              return pnperror;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:651
msgid ""
"No special treatment is required for the drivers which do not support PnP "
"because they pass an empty PnP ID table and will always get ENXIO if called "
"on a PnP card."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:653
msgid ""
"The probe routine normally needs at least some minimal set of resources, "
"such as I/O port number to find the card and probe it. Depending on the "
"hardware the driver may be able to discover the other necessary resources "
"automatically. The PnP devices have all the resources pre-set by the PnP "
"subsystem, so the driver does not need to discover them by itself."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:655
msgid ""
"Typically the minimal information required to get access to the device is "
"the I/O port number. Then some devices allow to get the rest of information "
"from the device configuration registers (though not all devices do that). So "
"first we try to get the port start value:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:660
#, no-wrap
msgid ""
" sc->port0 = bus_get_resource_start(dev,\n"
"        SYS_RES_IOPORT, 0 /*rid*/); if(sc->port0 == 0) return ENXIO;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:663
msgid ""
"The base port address is saved in the structure softc for future use. If it "
"will be used very often then calling the resource function each time would "
"be prohibitively slow. If we do not get a port we just return an error. Some "
"device drivers can instead be clever and try to probe all the possible "
"ports, like this:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:677
#, no-wrap
msgid ""
"          /* table of all possible base I/O port addresses for this device */\n"
"          static struct xxx_allports {\n"
"              u_short port; /* port address */\n"
"              short used; /* flag: if this port is already used by some unit */\n"
"          } xxx_allports = {\n"
"              { 0x300, 0 },\n"
"              { 0x320, 0 },\n"
"              { 0x340, 0 },\n"
"              { 0, 0 } /* end of table */\n"
"          };\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:681
#, no-wrap
msgid ""
"          ...\n"
"          int port, i;\n"
"          ...\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:687
#, no-wrap
msgid ""
"          port =  bus_get_resource_start(dev, SYS_RES_IOPORT, 0 /*rid*/);\n"
"          if(port !=0 ) {\n"
"              for(i=0; xxx_allports[i].port!=0; i++) {\n"
"                  if(xxx_allports[i].used || xxx_allports[i].port != port)\n"
"                      continue;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:695
#, no-wrap
msgid ""
"                  /* found it */\n"
"                  xxx_allports[i].used = 1;\n"
"                  /* do probe on a known port */\n"
"                  return xxx_really_probe(dev, port);\n"
"              }\n"
"              return ENXIO; /* port is unknown or already used */\n"
"          }\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:700
#, no-wrap
msgid ""
"          /* we get here only if we need to guess the port */\n"
"          for(i=0; xxx_allports[i].port!=0; i++) {\n"
"              if(xxx_allports[i].used)\n"
"                  continue;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:705
#, no-wrap
msgid ""
"              /* mark as used - even if we find nothing at this port\n"
"               * at least we won't probe it in future\n"
"               */\n"
"               xxx_allports[i].used = 1;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:712
#, no-wrap
msgid ""
"              error = xxx_really_probe(dev, xxx_allports[i].port);\n"
"              if(error == 0) /* found a device at that port */\n"
"                  return 0;\n"
"          }\n"
"          /* probed all possible addresses, none worked */\n"
"          return ENXIO;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:715
msgid ""
"Of course, normally the driver's `identify()` routine should be used for "
"such things. But there may be one valid reason why it may be better to be "
"done in `probe()`: if this probe would drive some other sensitive device "
"crazy. The probe routines are ordered with consideration of the `sensitive` "
"flag: the sensitive devices get probed first and the rest of the devices "
"later. But the `identify()` routines are called before any probes, so they "
"show no respect to the sensitive devices and may upset them."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:717
msgid ""
"Now, after we got the starting port we need to set the port count (except "
"for PnP devices) because the kernel does not have this information in the "
"configuration file."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:725
#, no-wrap
msgid ""
"         if(pnperror /* only for non-PnP devices */\n"
"         && bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->port0,\n"
"         XXX_PORT_COUNT)<0)\n"
"             return ENXIO;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:728
msgid ""
"Finally allocate and activate a piece of port address space (special values "
"of start and end mean \"use those we set by ``bus_set_resource()``\"):"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:736
#, no-wrap
msgid ""
"          sc->port0_rid = 0;\n"
"          sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT,\n"
"          &sc->port0_rid,\n"
"              /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:739
#, no-wrap
msgid ""
"          if(sc->port0_r == NULL)\n"
"              return ENXIO;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:742
msgid ""
"Now having access to the port-mapped registers we can poke the device in "
"some way and check if it reacts like it is expected to. If it does not then "
"there is probably some other device or no device at all at this address."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:744
msgid ""
"Normally drivers do not set up the interrupt handlers until the attach "
"routine. Instead they do probes in the polling mode using the `DELAY()` "
"function for timeout. The probe routine must never hang forever, all the "
"waits for the device must be done with timeouts. If the device does not "
"respond within the time it is probably broken or misconfigured and the "
"driver must return error. When determining the timeout interval give the "
"device some extra time to be on the safe side: although `DELAY()` is "
"supposed to delay for the same amount of time on any machine it has some "
"margin of error, depending on the exact CPU."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:746
msgid ""
"If the probe routine really wants to check that the interrupts really work "
"it may configure and probe the interrupts too. But that is not recommended."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:753
#, no-wrap
msgid ""
"          /* implemented in some very device-specific way */\n"
"          if(error = xxx_probe_ports(sc))\n"
"              goto bad; /* will deallocate the resources before returning */\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:756
msgid ""
"The function `xxx_probe_ports()` may also set the device description "
"depending on the exact model of device it discovers. But if there is only "
"one supported device model this can be as well done in a hardcoded way. Of "
"course, for the PnP devices the PnP support sets the description from the "
"table automatically."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:761
#, no-wrap
msgid ""
"          if(pnperror)\n"
"              device_set_desc(dev, \"Our device model 1234\");\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:764
msgid ""
"Then the probe routine should either discover the ranges of all the "
"resources by reading the device configuration registers or make sure that "
"they were set explicitly by the user. We will consider it with an example of "
"on-board memory. The probe routine should be as non-intrusive as possible, "
"so allocation and check of functionality of the rest of resources (besides "
"the ports) would be better left to the attach routine."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:766
msgid ""
"The memory address may be specified in the kernel configuration file or on "
"some devices it may be pre-configured in non-volatile configuration "
"registers. If both sources are available and different, which one should be "
"used? Probably if the user bothered to set the address explicitly in the "
"kernel configuration file they know what they are doing and this one should "
"take precedence. An example of implementation could be:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:774
#, no-wrap
msgid ""
"          /* try to find out the config address first */\n"
"          sc->mem0_p = bus_get_resource_start(dev, SYS_RES_MEMORY, 0 /*rid*/);\n"
"          if(sc->mem0_p == 0) { /* nope, not specified by user */\n"
"              sc->mem0_p = xxx_read_mem0_from_device_config(sc);\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:782
#, no-wrap
msgid ""
"          if(sc->mem0_p == 0)\n"
"                  /* can't get it from device config registers either */\n"
"                  goto bad;\n"
"          } else {\n"
"              if(xxx_set_mem0_address_on_device(sc) < 0)\n"
"                  goto bad; /* device does not support that address */\n"
"          }\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:794
#, no-wrap
msgid ""
"          /* just like the port, set the memory size,\n"
"           * for some devices the memory size would not be constant\n"
"           * but should be read from the device configuration registers instead\n"
"           * to accommodate different models of devices. Another option would\n"
"           * be to let the user set the memory size as \"msize\" configuration\n"
"           * resource which will be automatically handled by the ISA bus.\n"
"           */\n"
"           if(pnperror) { /* only for non-PnP devices */\n"
"              sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);\n"
"              if(sc->mem0_size == 0) /* not specified by user */\n"
"                  sc->mem0_size = xxx_read_mem0_size_from_device_config(sc);\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:803
#, no-wrap
msgid ""
"              if(sc->mem0_size == 0) {\n"
"                  /* suppose this is a very old model of device without\n"
"                   * auto-configuration features and the user gave no preference,\n"
"                   * so assume the minimalistic case\n"
"                   * (of course, the real value will vary with the driver)\n"
"                   */\n"
"                  sc->mem0_size = 8*1024;\n"
"              }\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:806
#, no-wrap
msgid ""
"              if(xxx_set_mem0_size_on_device(sc) < 0)\n"
"                  goto bad; /* device does not support that size */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:813
#, no-wrap
msgid ""
"              if(bus_set_resource(dev, SYS_RES_MEMORY, /*rid*/0,\n"
"                      sc->mem0_p, sc->mem0_size)<0)\n"
"                  goto bad;\n"
"          } else {\n"
"              sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);\n"
"          }\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:816
msgid "Resources for IRQ and DRQ are easy to check by analogy."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:818
msgid "If all went well then release all the resources and return success."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:823
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1086
#, no-wrap
msgid ""
"          xxx_free_resources(sc);\n"
"          return 0;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:826
msgid ""
"Finally, handle the troublesome situations. All the resources should be "
"deallocated before returning. We make use of the fact that before the "
"structure softc is passed to us it gets zeroed out, so we can find out if "
"some resource was allocated: then its descriptor is non-zero."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:830
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1047
#, no-wrap
msgid "          bad:\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:836
#, no-wrap
msgid ""
"          xxx_free_resources(sc);\n"
"          if(error)\n"
"                return error;\n"
"          else /* exact error is unknown */\n"
"              return ENXIO;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:839
msgid ""
"That would be all for the probe routine. Freeing of resources is done from "
"multiple places, so it is moved to a function which may look like:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:847
#, no-wrap
msgid ""
"static void\n"
"           xxx_free_resources(sc)\n"
"              struct xxx_softc *sc;\n"
"          {\n"
"              /* check every resource and free if not zero */\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:855
#, no-wrap
msgid ""
"              /* interrupt handler */\n"
"              if(sc->intr_r) {\n"
"                  bus_teardown_intr(sc->dev, sc->intr_r, sc->intr_cookie);\n"
"                  bus_release_resource(sc->dev, SYS_RES_IRQ, sc->intr_rid,\n"
"                      sc->intr_r);\n"
"                  sc->intr_r = 0;\n"
"              }\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:870
#, no-wrap
msgid ""
"              /* all kinds of memory maps we could have allocated */\n"
"              if(sc->data_p) {\n"
"                  bus_dmamap_unload(sc->data_tag, sc->data_map);\n"
"                  sc->data_p = 0;\n"
"              }\n"
"               if(sc->data) { /* sc->data_map may be legitimately equal to 0 */\n"
"                  /* the map will also be freed */\n"
"                  bus_dmamem_free(sc->data_tag, sc->data, sc->data_map);\n"
"                  sc->data = 0;\n"
"              }\n"
"              if(sc->data_tag) {\n"
"                  bus_dma_tag_destroy(sc->data_tag);\n"
"                  sc->data_tag = 0;\n"
"              }\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:872
#, no-wrap
msgid "              ... free other maps and tags if we have them ...\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:877
#, no-wrap
msgid ""
"              if(sc->parent_tag) {\n"
"                  bus_dma_tag_destroy(sc->parent_tag);\n"
"                  sc->parent_tag = 0;\n"
"              }\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:891
#, no-wrap
msgid ""
"              /* release all the bus resources */\n"
"              if(sc->mem0_r) {\n"
"                  bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->mem0_rid,\n"
"                      sc->mem0_r);\n"
"                  sc->mem0_r = 0;\n"
"              }\n"
"              ...\n"
"              if(sc->port0_r) {\n"
"                  bus_release_resource(sc->dev, SYS_RES_IOPORT, sc->port0_rid,\n"
"                      sc->port0_r);\n"
"                  sc->port0_r = 0;\n"
"              }\n"
"          }\n"
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:894
#, no-wrap
msgid "xxx_isa_attach"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:897
msgid ""
"The attach routine actually connects the driver to the system if the probe "
"routine returned success and the system had chosen to attach that driver. If "
"the probe routine returned 0 then the attach routine may expect to receive "
"the device structure softc intact, as it was set by the probe routine. Also "
"if the probe routine returns 0 it may expect that the attach routine for "
"this device shall be called at some point in the future. If the probe "
"routine returns a negative value then the driver may make none of these "
"assumptions."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:899
msgid ""
"The attach routine returns 0 if it completed successfully or error code "
"otherwise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:901
msgid ""
"The attach routine starts just like the probe routine, with getting some "
"frequently used data into more accessible variables."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:907
#, no-wrap
msgid ""
"          struct xxx_softc *sc = device_get_softc(dev);\n"
"          int unit = device_get_unit(dev);\n"
"          int error = 0;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:910
msgid ""
"Then allocate and activate all the necessary resources. As normally the port "
"range will be released before returning from probe, it has to be allocated "
"again. We expect that the probe routine had properly set all the resource "
"ranges, as well as saved them in the structure softc. If the probe routine "
"had left some resource allocated then it does not need to be allocated again "
"(which would be considered an error)."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:916
#, no-wrap
msgid ""
"          sc->port0_rid = 0;\n"
"          sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT,  &sc->port0_rid,\n"
"              /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:919
#, no-wrap
msgid ""
"          if(sc->port0_r == NULL)\n"
"               return ENXIO;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:924
#, no-wrap
msgid ""
"          /* on-board memory */\n"
"          sc->mem0_rid = 0;\n"
"          sc->mem0_r = bus_alloc_resource(dev, SYS_RES_MEMORY,  &sc->mem0_rid,\n"
"              /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:927
#, no-wrap
msgid ""
"          if(sc->mem0_r == NULL)\n"
"                goto bad;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:930
#, no-wrap
msgid ""
"          /* get its virtual address */\n"
"          sc->mem0_v = rman_get_virtual(sc->mem0_r);\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:933
msgid ""
"The DMA request channel (DRQ) is allocated likewise. To initialize it use "
"functions of the `isa_dma*()` family. For example:"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:935
msgid "`isa_dmacascade(sc->drq0);`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:937
msgid ""
"The interrupt request line (IRQ) is a bit special. Besides allocation the "
"driver's interrupt handler should be associated with it. Historically in the "
"old ISA drivers the argument passed by the system to the interrupt handler "
"was the device unit number. But in modern drivers the convention suggests "
"passing the pointer to structure softc. The important reason is that when "
"the structures softc are allocated dynamically then getting the unit number "
"from softc is easy while getting softc from the unit number is difficult. "
"Also this convention makes the drivers for different buses look more uniform "
"and allows them to share the code: each bus gets its own probe, attach, "
"detach and other bus-specific routines while the bulk of the driver code may "
"be shared among them."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:944
#, no-wrap
msgid ""
"          sc->intr_rid = 0;\n"
"          sc->intr_r = bus_alloc_resource(dev, SYS_RES_MEMORY,  &sc->intr_rid,\n"
"                /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:947
#, no-wrap
msgid ""
"          if(sc->intr_r == NULL)\n"
"              goto bad;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:956
#, no-wrap
msgid ""
"          /*\n"
"           * XXX_INTR_TYPE is supposed to be defined depending on the type of\n"
"           * the driver, for example as INTR_TYPE_CAM for a CAM driver\n"
"           */\n"
"          error = bus_setup_intr(dev, sc->intr_r, XXX_INTR_TYPE,\n"
"              (driver_intr_t *) xxx_intr, (void *) sc, &sc->intr_cookie);\n"
"          if(error)\n"
"              goto bad;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:959
msgid ""
"If the device needs to make DMA to the main memory then this memory should "
"be allocated like described before:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:971
#, no-wrap
msgid ""
"          error=bus_dma_tag_create(NULL, /*alignment*/ 4,\n"
"              /*boundary*/ 0, /*lowaddr*/ BUS_SPACE_MAXADDR_24BIT,\n"
"              /*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ NULL,\n"
"              /*maxsize*/ BUS_SPACE_MAXSIZE_24BIT,\n"
"              /*nsegments*/ BUS_SPACE_UNRESTRICTED,\n"
"              /*maxsegsz*/ BUS_SPACE_MAXSIZE_24BIT, /*flags*/ 0,\n"
"              &sc->parent_tag);\n"
"          if(error)\n"
"              goto bad;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:988
#, no-wrap
msgid ""
"          /* many things get inherited from the parent tag\n"
"           * sc->data is supposed to point to the structure with the shared data,\n"
"           * for example for a ring buffer it could be:\n"
"           * struct {\n"
"           *   u_short rd_pos;\n"
"           *   u_short wr_pos;\n"
"           *   char    bf[XXX_RING_BUFFER_SIZE]\n"
"           * } *data;\n"
"           */\n"
"          error=bus_dma_tag_create(sc->parent_tag, 1,\n"
"              0, BUS_SPACE_MAXADDR, 0, /*filter*/ NULL, /*filterarg*/ NULL,\n"
"              /*maxsize*/ sizeof(* sc->data), /*nsegments*/ 1,\n"
"              /*maxsegsz*/ sizeof(* sc->data), /*flags*/ 0,\n"
"              &sc->data_tag);\n"
"          if(error)\n"
"              goto bad;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:993
#, no-wrap
msgid ""
"          error = bus_dmamem_alloc(sc->data_tag, &sc->data, /* flags*/ 0,\n"
"              &sc->data_map);\n"
"          if(error)\n"
"               goto bad;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1009
#, no-wrap
msgid ""
"          /* xxx_alloc_callback() just saves the physical address at\n"
"           * the pointer passed as its argument, in this case &sc->data_p.\n"
"           * See details in the section on bus memory mapping.\n"
"           * It can be implemented like:\n"
"           *\n"
"           * static void\n"
"           * xxx_alloc_callback(void *arg, bus_dma_segment_t *seg,\n"
"           *     int nseg, int error)\n"
"           * {\n"
"           *    *(bus_addr_t *)arg = seg[0].ds_addr;\n"
"           * }\n"
"           */\n"
"          bus_dmamap_load(sc->data_tag, sc->data_map, (void *)sc->data,\n"
"              sizeof (* sc->data), xxx_alloc_callback, (void *) &sc->data_p,\n"
"              /*flags*/0);\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1012
msgid ""
"After all the necessary resources are allocated the device should be "
"initialized. The initialization may include testing that all the expected "
"features are functional."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1017
#, no-wrap
msgid ""
"          if(xxx_initialize(sc) < 0)\n"
"               goto bad;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1020
msgid ""
"The bus subsystem will automatically print on the console the device "
"description set by probe. But if the driver wants to print some extra "
"information about the device it may do so, for example:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1025
#, no-wrap
msgid "        device_printf(dev, \"has on-card FIFO buffer of %d bytes\\n\", sc->fifosize);\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1028
msgid ""
"If the initialization routine experiences any problems then printing "
"messages about them before returning error is also recommended."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1030
msgid ""
"The final step of the attach routine is attaching the device to its "
"functional subsystem in the kernel. The exact way to do it depends on the "
"type of the driver: a character device, a block device, a network device, a "
"CAM SCSI bus device and so on."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1032
msgid "If all went well then return success."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1038
#, no-wrap
msgid ""
"          error = xxx_attach_subsystem(sc);\n"
"          if(error)\n"
"              goto bad;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1040
#, no-wrap
msgid "          return 0;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1043
msgid ""
"Finally, handle the troublesome situations. All the resources should be "
"deallocated before returning an error. We make use of the fact that before "
"the structure softc is passed to us it gets zeroed out, so we can find out "
"if some resource was allocated: then its descriptor is non-zero."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1053
#, no-wrap
msgid ""
"          xxx_free_resources(sc);\n"
"          if(error)\n"
"              return error;\n"
"          else /* exact error is unknown */\n"
"              return ENXIO;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1056
msgid "That would be all for the attach routine."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1058
#, no-wrap
msgid "xxx_isa_detach"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1061
msgid ""
"If this function is present in the driver and the driver is compiled as a "
"loadable module then the driver gets the ability to be unloaded. This is an "
"important feature if the hardware supports hot plug. But the ISA bus does "
"not support hot plug, so this feature is not particularly important for the "
"ISA devices. The ability to unload a driver may be useful when debugging it, "
"but in many cases installation of the new version of the driver would be "
"required only after the old version somehow wedges the system and a reboot "
"will be needed anyway, so the efforts spent on writing the detach routine "
"may not be worth it. Another argument that unloading would allow upgrading "
"the drivers on a production machine seems to be mostly theoretical. "
"Installing a new version of a driver is a dangerous operation which should "
"never be performed on a production machine (and which is not permitted when "
"the system is running in secure mode). Still, the detach routine may be "
"provided for the sake of completeness."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1063
msgid ""
"The detach routine returns 0 if the driver was successfully detached or the "
"error code otherwise."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1065
msgid ""
"The logic of detach is a mirror of the attach. The first thing to do is to "
"detach the driver from its kernel subsystem. If the device is currently open "
"then the driver has two choices: refuse to be detached or forcibly close and "
"proceed with detach. The choice used depends on the ability of the "
"particular kernel subsystem to do a forced close and on the preferences of "
"the driver's author. Generally the forced close seems to be the preferred "
"alternative."
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1070
#, no-wrap
msgid ""
"          struct xxx_softc *sc = device_get_softc(dev);\n"
"          int error;\n"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1074
#, no-wrap
msgid ""
"          error = xxx_detach_subsystem(sc);\n"
"          if(error)\n"
"              return error;\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1077
msgid ""
"Next the driver may want to reset the hardware to some consistent state. "
"That includes stopping any ongoing transfers, disabling the DMA channels and "
"interrupts to avoid memory corruption by the device. For most of the drivers "
"this is exactly what the shutdown routine does, so if it is included in the "
"driver we can just call it."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1079
msgid "`xxx_isa_shutdown(dev);`"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1081
msgid "And finally release all the resources and return success."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1089
#, no-wrap
msgid "xxx_isa_shutdown"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1092
msgid ""
"This routine is called when the system is about to be shut down. It is "
"expected to bring the hardware to some consistent state. For most of the ISA "
"devices no special action is required, so the function is not really "
"necessary because the device will be re-initialized on reboot anyway. But "
"some devices have to be shut down with a special procedure, to make sure "
"that they will be properly detected after soft reboot (this is especially "
"true for many devices with proprietary identification protocols). In any "
"case disabling DMA and interrupts in the device registers and stopping any "
"ongoing transfers is a good idea. The exact action depends on the hardware, "
"so we do not consider it here in any detail."
msgstr ""

#. type: Title ==
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1094
#, no-wrap
msgid "xxx_intr"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1097
msgid ""
"The interrupt handler is called when an interrupt is received which may be "
"from this particular device. The ISA bus does not support interrupt sharing "
"(except in some special cases) so in practice if the interrupt handler is "
"called then the interrupt almost for sure came from its device. Still, the "
"interrupt handler must poll the device registers and make sure that the "
"interrupt was generated by its device. If not it should just return."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1099
msgid ""
"The old convention for the ISA drivers was getting the device unit number as "
"an argument. This is obsolete, and the new drivers receive whatever argument "
"was specified for them in the attach routine when calling "
"`bus_setup_intr()`. By the new convention it should be the pointer to the "
"structure softc. So the interrupt handler commonly starts as:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1106
#, no-wrap
msgid ""
"          static void\n"
"          xxx_intr(struct xxx_softc *sc)\n"
"          {\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1109
msgid ""
"It runs at the interrupt priority level specified by the interrupt type "
"parameter of `bus_setup_intr()`. That means that all the other interrupts of "
"the same type as well as all the software interrupts are disabled."
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1111
msgid "To avoid races it is commonly written as a loop:"
msgstr ""

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1119
#, no-wrap
msgid ""
"          while(xxx_interrupt_pending(sc)) {\n"
"              xxx_process_interrupt(sc);\n"
"              xxx_acknowledge_interrupt(sc);\n"
"          }\n"
msgstr ""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/isa/_index.adoc:1121
msgid ""
"The interrupt handler has to acknowledge interrupt to the device only but "
"not to the interrupt controller, the system takes care of the latter."
msgstr ""