Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-doc
Path: blob/main/documentation/content/ru/books/arch-handbook/scsi/_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.
# Vladlen Popolitov <[email protected]>, 2025, 2026.
msgid ""
msgstr ""
"Project-Id-Version: FreeBSD Documentation VERSION\n"
"POT-Creation-Date: 2025-05-01 19:56-0300\n"
"PO-Revision-Date: 2026-04-05 04:45+0000\n"
"Last-Translator: Vladlen Popolitov <[email protected]>\n"
"Language-Team: Russian <https://translate-dev.freebsd.org/projects/"
"documentation/booksarch-handbookscsi_index/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.17\n"

#. type: Title =
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:14
#, no-wrap
msgid "Common Access Method SCSI Controllers"
msgstr "Контроллеры SCSI с общим методом доступа (CAM)"

#. type: YAML Front Matter: title
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1
#, no-wrap
msgid "Chapter 12. Common Access Method SCSI Controllers"
msgstr "Глава 12. Контроллеры SCSI с общим методом доступа (CAM)"

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:52
#, no-wrap
msgid "Synopsis"
msgstr "Обзор"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:56
msgid ""
"This document assumes that the reader has a general understanding of device "
"drivers in FreeBSD and of the SCSI protocol.  Much of the information in "
"this document was extracted from the drivers:"
msgstr ""
"Этот документ предполагает, что читатель имеет общее представление о "
"драйверах устройств в FreeBSD и о протоколе SCSI. Большая часть информации в "
"этом документе была извлечена из драйверов:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:58
msgid ""
"ncr ([.filename]#/sys/pci/ncr.c#) by Wolfgang Stanglmeier and Stefan Esser"
msgstr ""
"ncr ([.filename]#/sys/pci/ncr.c#) от Wolfgang Stanglmeier и Stefan Esser"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:59
msgid "sym ([.filename]#/sys/dev/sym/sym_hipd.c#) by Gerard Roudier"
msgstr "sym ([.filename]#/sys/dev/sym/sym_hipd.c#) от Gerard Roudier"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:60
msgid "aic7xxx ([.filename]#/sys/dev/aic7xxx/aic7xxx.c#) by Justin T. Gibbs"
msgstr "aic7xxx ([.filename]#/sys/dev/aic7xxx/aic7xxx.c#) от Justin T. Gibbs"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:63
msgid ""
"and from the CAM code itself (by Justin T. Gibbs, see [.filename]#/sys/cam/"
"*#).  When some solution looked the most logical and was essentially "
"verbatim extracted from the code by Justin T. Gibbs, I marked it as "
"\"recommended\"."
msgstr ""
"и из самого кода CAM (автор Justin T. Gibbs, см. [.filename]#/sys/cam/*#). "
"Когда какое-то решение выглядело наиболее логичным и было практически "
"дословно взято из кода Justin T. Gibbs, я отмечал его как \"рекомендуемое\"."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:71
msgid ""
"The document is illustrated with examples in pseudo-code.  Although "
"sometimes the examples have many details and look like real code, it is "
"still pseudo-code.  It was written to demonstrate the concepts in an "
"understandable way.  For a real driver other approaches may be more modular "
"and efficient.  It also abstracts from the hardware details, as well as "
"issues that would cloud the demonstrated concepts or that are supposed to be "
"described in the other chapters of the developers handbook.  Such details "
"are commonly shown as calls to functions with descriptive names, comments or "
"pseudo-statements.  Fortunately real life full-size examples with all the "
"details can be found in the real drivers."
msgstr ""
"Документ иллюстрирован примерами на псевдокоде. Хотя иногда примеры содержат "
"много деталей и выглядят как настоящий код, это всё ещё псевдокод. Он был "
"написан, чтобы продемонстрировать концепции в понятной форме. Для реального "
"драйвера могут быть более модульные и эффективные подходы. Также он "
"абстрагируется от деталей оборудования, а также от вопросов, которые могли "
"бы затмить демонстрируемые концепции или которые предполагается описать в "
"других главах руководства разработчика. Такие детали обычно показаны в виде "
"вызовов функций с описательными именами, комментариев или псевдооператоров. "
"К счастью, полные примеры из реальной жизни со всеми деталями можно найти в "
"реальных драйверах."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:73
#, no-wrap
msgid "General Architecture"
msgstr "Общая архитектура"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:79
msgid ""
"CAM stands for Common Access Method.  It is a generic way to address the I/O "
"buses in a SCSI-like way.  This allows a separation of the generic device "
"drivers from the drivers controlling the I/O bus: for example the disk "
"driver becomes able to control disks on both SCSI, IDE, and/or any other bus "
"so the disk driver portion does not have to be rewritten (or copied and "
"modified) for every new I/O bus.  Thus the two most important active "
"entities are:"
msgstr ""
"CAM означает Common Access Method (Общий Метод Доступа). Это универсальный "
"способ адресации шин ввода-вывода в стиле SCSI. Это позволяет отделить общие "
"драйверы устройств от драйверов, управляющих шиной ввода-вывода: например, "
"драйвер диска получает возможность управлять дисками как на SCSI, IDE, так и "
"на любой другой шине, так что часть драйвера диска не нужно переписывать ("
"или копировать и изменять) для каждой новой шины ввода-вывода. Таким "
"образом, двумя наиболее важными активными сущностями являются:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:81
msgid ""
"_Peripheral Modules_ - a driver for peripheral devices (disk, tape, CD-ROM, "
"etc.)"
msgstr ""
"_Модули периферийных устройств_ - драйвер для периферийных устройств (диски, "
"ленты, CD-ROM и т.д.)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:82
msgid ""
"_SCSI Interface Modules_ (SIM) - a Host Bus Adapter drivers for connecting "
"to an I/O bus such as SCSI or IDE."
msgstr ""
"_Модули интерфейса SCSI_ (SIM) - драйверы адаптеров шины для подключения к "
"шине ввода-вывода, такой как SCSI или IDE."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:85
msgid ""
"A peripheral driver receives requests from the OS, converts them to a "
"sequence of SCSI commands and passes these SCSI commands to a SCSI Interface "
"Module.  The SCSI Interface Module is responsible for passing these commands "
"to the actual hardware (or if the actual hardware is not SCSI but, for "
"example, IDE then also converting the SCSI commands to the native commands "
"of the hardware)."
msgstr ""
"Периферийный драйвер получает запросы от ОС, преобразует их в "
"последовательность команд SCSI и передаёт эти команды SCSI модулю интерфейса "
"SCSI. Модуль интерфейса SCSI отвечает за передачу этих команд реальному "
"оборудованию (или, если оборудование не поддерживает SCSI, а использует, "
"например, IDE, также преобразует команды SCSI в собственные команды "
"оборудования)."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:87
msgid ""
"As we are interested in writing a SCSI adapter driver here, from this point "
"on we will consider everything from the SIM standpoint."
msgstr ""
"Так как мы заинтересованы в написании драйвера адаптера SCSI, с этого "
"момента мы будем рассматривать всё с точки зрения модуля SCSI-интерфейса "
"(SIM)."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:88
#, no-wrap
msgid "Globals and Boilerplate"
msgstr "Глобальные переменные и Шаблонный код"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:91
msgid ""
"A typical SIM driver needs to include the following CAM-related header files:"
msgstr ""
"Типичный драйвер SIM должен включать следующие заголовочные файлы, связанные "
"с CAM:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:100
#, no-wrap
msgid ""
"#include <cam/cam.h>\n"
"#include <cam/cam_ccb.h>\n"
"#include <cam/cam_sim.h>\n"
"#include <cam/cam_xpt_sim.h>\n"
"#include <cam/cam_debug.h>\n"
"#include <cam/scsi/scsi_all.h>\n"
msgstr ""
"#include <cam/cam.h>\n"
"#include <cam/cam_ccb.h>\n"
"#include <cam/cam_sim.h>\n"
"#include <cam/cam_xpt_sim.h>\n"
"#include <cam/cam_debug.h>\n"
"#include <cam/scsi/scsi_all.h>\n"

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:102
#, no-wrap
msgid "Device configuration: xxx_attach"
msgstr "Конфигурация устройства: xxx_attach"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:107
msgid ""
"The first thing each SIM driver must do is register itself with the CAM "
"subsystem.  This is done during the driver's `xxx_attach()` function (here "
"and further xxx_ is used to denote the unique driver name prefix).  The "
"`xxx_attach()` function itself is called by the system bus auto-"
"configuration code which we do not describe here."
msgstr ""
"Первое, что должен сделать каждый драйвер SIM, — это зарегистрироваться в "
"подсистеме CAM. Это выполняется в функции `xxx_attach()` драйвера (здесь и "
"далее xxx_ используется для обозначения уникального префикса имени драйвера)"
". Сама функция `xxx_attach()` вызывается кодом автонастройки системной шины, "
"который мы здесь не описываем."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:109
msgid ""
"This is achieved in multiple steps: first it is necessary to allocate the "
"queue of requests associated with this SIM:"
msgstr ""
"Это достигается в несколько этапов: сначала необходимо выделить очередь "
"запросов, связанных с этой SIM:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:113
#, no-wrap
msgid "    struct cam_devq *devq;\n"
msgstr "    struct cam_devq *devq;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:117
#, no-wrap
msgid ""
"    if ((devq = cam_simq_alloc(SIZE)) == NULL) {\n"
"        error; /* some code to handle the error */\n"
"    }\n"
msgstr ""
"    if ((devq = cam_simq_alloc(SIZE)) == NULL) {\n"
"        error; /* some code to handle the error */\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:122
msgid ""
"Here `SIZE` is the size of the queue to be allocated, maximal number of "
"requests it could contain.  It is the number of requests that the SIM driver "
"can handle in parallel on one SCSI card.  Commonly it can be calculated as:"
msgstr ""
"Вот `SIZE` — это размер выделяемой очереди, максимальное количество "
"запросов, которые она может содержать. Это количество запросов, которые "
"драйвер SIM может обрабатывать параллельно на одной SCSI-карте. Обычно его "
"можно вычислить как:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:126
#, no-wrap
msgid "SIZE = NUMBER_OF_SUPPORTED_TARGETS * MAX_SIMULTANEOUS_COMMANDS_PER_TARGET\n"
msgstr ""
"SIZE = NUMBER_OF_SUPPORTED_TARGETS * MAX_SIMULTANEOUS_COMMANDS_PER_TARGET\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:129
msgid "Next we create a descriptor of our SIM:"
msgstr "Далее мы создаем описание нашего SIM:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:133
#, no-wrap
msgid "    struct cam_sim *sim;\n"
msgstr "    struct cam_sim *sim;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:140
#, no-wrap
msgid ""
"    if ((sim = cam_sim_alloc(action_func, poll_func, driver_name,\n"
"            softc, unit, mtx, max_dev_transactions,\n"
"            max_tagged_dev_transactions, devq)) == NULL) {\n"
"        cam_simq_free(devq);\n"
"        error; /* some code to handle the error */\n"
"    }\n"
msgstr ""
"    if ((sim = cam_sim_alloc(action_func, poll_func, driver_name,\n"
"            softc, unit, mtx, max_dev_transactions,\n"
"            max_tagged_dev_transactions, devq)) == NULL) {\n"
"        cam_simq_free(devq);\n"
"        error; /* some code to handle the error */\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:143
msgid ""
"Note that if we are not able to create a SIM descriptor we free the `devq` "
"also because we can do nothing else with it and we want to conserve memory."
msgstr ""
"Обратите внимание, что если мы не сможем создать дескриптор SIM, мы также "
"освобождаем `devq`, потому что больше ничего не можем с ним сделать и хотим "
"сэкономить память."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:145
msgid ""
"If a SCSI card has multiple SCSI buses on it then each bus requires its own "
"`cam_sim` structure."
msgstr ""
"Если SCSI-карта имеет несколько шин SCSI, то каждой шине требуется "
"собственная структура `cam_sim`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:148
msgid ""
"An interesting question is what to do if a SCSI card has more than one SCSI "
"bus, do we need one `devq` structure per card or per SCSI bus? The answer "
"given in the comments to the CAM code is: either way, as the driver's author "
"prefers."
msgstr ""
"Интересный вопрос: что делать, если SCSI-карта имеет более одной SCSI-шины, "
"нужна ли одна структура `devq` на карту или на SCSI-шину? Ответ, приведённый "
"в комментариях к коду CAM, таков: как угодно, на усмотрение автора драйвера."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:150
msgid "The arguments are:"
msgstr "Аргументы:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:152
msgid "`action_func` - pointer to the driver's `xxx_action` function."
msgstr "`action_func` - указатель на функцию `xxx_action` драйвера."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:156
#, no-wrap
msgid "static void xxx_action(struct cam_sim *, union ccb *);\n"
msgstr "static void xxx_action(struct cam_sim *, union ccb *);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:158
msgid "`poll_func` - pointer to the driver's `xxx_poll()`"
msgstr "`poll_func` - указатель на функцию `xxx_poll()` драйвера"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:162
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1020
#, no-wrap
msgid "static void xxx_poll(struct cam_sim *);\n"
msgstr "static void xxx_poll(struct cam_sim *);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:164
msgid ""
"driver_name - the name of the actual driver, such as \"ncr\" or \"wds\"."
msgstr "`driver_name` — имя фактического драйвера, например `ncr` или `wds`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:166
msgid ""
"`softc` - pointer to the driver's internal descriptor for this SCSI card.  "
"This pointer will be used by the driver in future to get private data."
msgstr ""
"`softc` — указатель на внутренний дескриптор драйвера для данной SCSI-карты. "
"Этот указатель будет использоваться драйвером в дальнейшем для получения "
"приватных данных."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:167
msgid ""
"unit - the controller unit number, for example for controller \"mps0\" this "
"number will be 0"
msgstr ""
"unit - номер управляющего устройства, например, для контроллера \"mps0\" это "
"число будет 0"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:171
msgid ""
"mtx - Lock associated with this SIM.  For SIMs that don't know about "
"locking, pass in Giant.  For SIMs that do, pass in the lock used to guard "
"this SIM's data structures.  This lock will be held when xxx_action and "
"xxx_poll are called."
msgstr ""
"mtx - Блокировка, связанная с данной SIM. Для SIM, которые не поддерживают "
"блокировку, передаётся Giant. Для SIM, которые поддерживают, передаётся "
"блокировка, используемая для защиты структур данных этой SIM. Эта блокировка "
"будет удерживаться при вызовах xxx_action и xxx_poll."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:174
msgid ""
"max_dev_transactions - maximal number of simultaneous transactions per SCSI "
"target in the non-tagged mode.  This value will be almost universally equal "
"to 1, with possible exceptions only for the non-SCSI cards.  Also the "
"drivers that hope to take advantage by preparing one transaction while "
"another one is executed may set it to 2 but this does not seem to be worth "
"the complexity."
msgstr ""
"max_dev_transactions - максимальное количество одновременных транзакций на "
"целевом SCSI-устройстве в режиме без тегов. Это значение почти всегда равно "
"1, за исключением возможных исключений только для не-SCSI карт. Также "
"драйверы, которые надеются получить преимущество, подготавливая одну "
"транзакцию во время выполнения другой, могут установить его в 2, но это не "
"кажется оправданным из-за сложности."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:179
msgid ""
"max_tagged_dev_transactions - the same thing, but in the tagged mode.  Tags "
"are the SCSI way to initiate multiple transactions on a device: each "
"transaction is assigned a unique tag and the transaction is sent to the "
"device.  When the device completes some transaction it sends back the result "
"together with the tag so that the SCSI adapter (and the driver) can tell "
"which transaction was completed.  This argument is also known as the maximal "
"tag depth.  It depends on the abilities of the SCSI adapter."
msgstr ""
"max_tagged_dev_transactions - то же самое, но в режиме с тегами. Теги — это "
"способ в SCSI инициировать несколько транзакций на устройстве: каждая "
"транзакция получает уникальный тег и отправляется на устройство. Когда "
"устройство завершает транзакцию, оно возвращает результат вместе с тегом, "
"чтобы SCSI-адаптер (и драйвер) могли определить, какая транзакция была "
"завершена. Этот аргумент также известен как максимальная глубина тега. Он "
"зависит от возможностей SCSI-адаптера."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:181
msgid "Finally we register the SCSI buses associated with our SCSI adapter:"
msgstr "Наконец, мы регистрируем шины SCSI, связанные с нашим SCSI-адаптером:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:188
#, no-wrap
msgid ""
"    if (xpt_bus_register(sim, softc, bus_number) != CAM_SUCCESS) {\n"
"        cam_sim_free(sim, /*free_devq*/ TRUE);\n"
"        error; /* some code to handle the error */\n"
"    }\n"
msgstr ""
"    if (xpt_bus_register(sim, softc, bus_number) != CAM_SUCCESS) {\n"
"        cam_sim_free(sim, /*free_devq*/ TRUE);\n"
"        error; /* some code to handle the error */\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:192
msgid ""
"If there is one `devq` structure per SCSI bus (i.e., we consider a card with "
"multiple buses as multiple cards with one bus each) then the bus number will "
"always be 0, otherwise each bus on the SCSI card should be get a distinct "
"number.  Each bus needs its own separate structure cam_sim."
msgstr ""
"Если существует одна структура `devq` на каждую шину SCSI (т.е. мы "
"рассматриваем карту с несколькими шинами как несколько карт с одной шиной "
"каждая), то номер шины всегда будет 0, в противном случае каждая шина на "
"SCSI-карте должна получить уникальный номер. Каждой шине требуется своя "
"отдельная структура `cam_sim`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:195
msgid ""
"After that our controller is completely hooked to the CAM system.  The value "
"of `devq` can be discarded now: sim will be passed as an argument in all "
"further calls from CAM and devq can be derived from it."
msgstr ""
"После этого наш контроллер полностью подключён к системе CAM. Значение `devq`"
" теперь можно отбросить: sim будет передаваться в качестве аргумента во всех "
"последующих вызовах из CAM, а devq можно получить из него."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:199
msgid ""
"CAM provides the framework for such asynchronous events.  Some events "
"originate from the lower levels (the SIM drivers), some events originate "
"from the peripheral drivers, some events originate from the CAM subsystem "
"itself.  Any driver can register callbacks for some types of the "
"asynchronous events, so that it would be notified if these events occur."
msgstr ""
"CAM предоставляет инфраструктуру для подобных асинхронных событий. Некоторые "
"события возникают на нижних уровнях (драйверы SIM), некоторые — в драйверах "
"периферийных устройств, а некоторые — в самой подсистеме CAM. Любой драйвер "
"может зарегистрировать обработчики для определённых типов асинхронных "
"событий, чтобы получать уведомления при их возникновении."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:207
msgid ""
"A typical example of such an event is a device reset.  Each transaction and "
"event identifies the devices to which it applies by the means of \"path\".  "
"The target-specific events normally occur during a transaction with this "
"device.  So the path from that transaction may be re-used to report this "
"event (this is safe because the event path is copied in the event reporting "
"routine but not deallocated nor passed anywhere further).  Also it is safe "
"to allocate paths dynamically at any time including the interrupt routines, "
"although that incurs certain overhead, and a possible problem with this "
"approach is that there may be no free memory at that time.  For a bus reset "
"event we need to define a wildcard path including all devices on the bus.  "
"So we can create the path for the future bus reset events in advance and "
"avoid problems with the future memory shortage:"
msgstr ""
"Типичным примером такого события является сброс устройства. Каждая "
"транзакция и событие идентифицируют устройства, к которым они применяются, с "
"помощью \"пути\". Специфичные для целевого устройства события обычно "
"происходят во время транзакции с этим устройством. Таким образом, путь из "
"этой транзакции может быть повторно использован для сообщения о данном "
"событии (это безопасно, потому что путь события копируется в процедуре "
"сообщения о событии, но не освобождается и не передаётся дальше). Также "
"безопасно динамически выделять пути в любое время, включая процедуры "
"обработки прерываний, хотя это влечёт определённые накладные расходы, и "
"возможная проблема такого подхода заключается в том, что в этот момент может "
"не быть свободной памяти. Для события сброса шины нам необходимо определить "
"путь-шаблон, включающий все устройства на шине. Поэтому мы можем заранее "
"создать путь для будущих событий сброса шины и избежать проблем с возможной "
"нехваткой памяти в будущем:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:211
#, no-wrap
msgid "    struct cam_path *path;\n"
msgstr "    struct cam_path *path;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:219
#, no-wrap
msgid ""
"    if (xpt_create_path(&path, /*periph*/NULL,\n"
"                cam_sim_path(sim), CAM_TARGET_WILDCARD,\n"
"                CAM_LUN_WILDCARD) != CAM_REQ_CMP) {\n"
"        xpt_bus_deregister(cam_sim_path(sim));\n"
"        cam_sim_free(sim, /*free_devq*/TRUE);\n"
"        error; /* some code to handle the error */\n"
"    }\n"
msgstr ""
"    if (xpt_create_path(&path, /*periph*/NULL,\n"
"                cam_sim_path(sim), CAM_TARGET_WILDCARD,\n"
"                CAM_LUN_WILDCARD) != CAM_REQ_CMP) {\n"
"        xpt_bus_deregister(cam_sim_path(sim));\n"
"        cam_sim_free(sim, /*free_devq*/TRUE);\n"
"        error; /* some code to handle the error */\n"
"    }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:222
#, no-wrap
msgid ""
"    softc->wpath = path;\n"
"    softc->sim = sim;\n"
msgstr ""
"    softc->wpath = path;\n"
"    softc->sim = sim;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:225
msgid "As you can see the path includes:"
msgstr "Как вы можете видеть, путь включает:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:227
msgid "ID of the peripheral driver (NULL here because we have none)"
msgstr ""
"Идентификатор драйвера периферийного устройства (NULL здесь, так как у нас "
"его нет)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:228
msgid "ID of the SIM driver (`cam_sim_path(sim)`)"
msgstr "Идентификатор драйвера SIM (`cam_sim_path(sim)`)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:229
msgid ""
"SCSI target number of the device (CAM_TARGET_WILDCARD means \"all devices\")"
msgstr ""
"Номер целевого устройства SCSI (CAM_TARGET_WILDCARD означает \"все "
"устройства\")"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:230
msgid "SCSI LUN number of the subdevice (CAM_LUN_WILDCARD means \"all LUNs\")"
msgstr "Номер SCSI LUN подустройства (CAM_LUN_WILDCARD означает \"все LUN\")"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:232
msgid ""
"If the driver can not allocate this path it will not be able to work "
"normally, so in that case we dismantle that SCSI bus."
msgstr ""
"Если драйвер не может выделить этот путь, он не сможет нормально работать, "
"поэтому в таком случае мы демонтируем эту шину SCSI."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:235
msgid ""
"And we save the path pointer in the `softc` structure for future use.  After "
"that we save the value of sim (or we can also discard it on the exit from "
"`xxx_probe()` if we wish)."
msgstr ""
"И мы сохраняем указатель пути в структуре `softc` для дальнейшего "
"использования. После этого сохраняем значение sim (или можем также отбросить "
"его при выходе из `xxx_probe()`, если захотим)."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:238
msgid ""
"That is all for a minimalistic initialization.  To do things right there is "
"one more issue left."
msgstr ""
"Вот и всё для минималистичной инициализации. Чтобы сделать всё правильно, "
"остался ещё один вопрос."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:243
msgid ""
"For a SIM driver there is one particularly interesting event: when a target "
"device is considered lost.  In this case resetting the SCSI negotiations "
"with this device may be a good idea.  So we register a callback for this "
"event with CAM.  The request is passed to CAM by requesting CAM action on a "
"CAM control block for this type of request:"
msgstr ""
"Для драйвера SIM есть одно особенно важное событие: когда целевое устройство "
"считается потерянным. В этом случае может быть хорошей идеей сбросить SCSI-"
"переговоры с этим устройством. Поэтому мы регистрируем обратный вызов для "
"этого события в CAM. Запрос передаётся в CAM путём запроса действия CAM в "
"блоке управления CAM для этого типа запроса:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:247
#, no-wrap
msgid "    struct ccb_setasync csa;\n"
msgstr "    struct ccb_setasync csa;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:254
#, no-wrap
msgid ""
"    xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);\n"
"    csa.ccb_h.func_code = XPT_SASYNC_CB;\n"
"    csa.event_enable = AC_LOST_DEVICE;\n"
"    csa.callback = xxx_async;\n"
"    csa.callback_arg = sim;\n"
"    xpt_action((union ccb *)&csa);\n"
msgstr ""
"    xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);\n"
"    csa.ccb_h.func_code = XPT_SASYNC_CB;\n"
"    csa.event_enable = AC_LOST_DEVICE;\n"
"    csa.callback = xxx_async;\n"
"    csa.callback_arg = sim;\n"
"    xpt_action((union ccb *)&csa);\n"

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:256
#, no-wrap
msgid "Processing CAM messages: xxx_action"
msgstr "Обработка сообщений CAM: xxx_action"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:261
#, no-wrap
msgid "static void xxx_action(struct cam_sim *sim, union ccb *ccb);\n"
msgstr "static void xxx_action(struct cam_sim *sim, union ccb *ccb);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:268
msgid ""
"Do some action on request of the CAM subsystem.  Sim describes the SIM for "
"the request, CCB is the request itself.  CCB stands for \"CAM Control "
"Block\".  It is a union of many specific instances, each describing "
"arguments for some type of transactions.  All of these instances share the "
"CCB header where the common part of arguments is stored."
msgstr ""
"Выполнить некоторое действие по запросу подсистемы CAM.  Sim описывает SIM "
"для запроса, CCB — это сам запрос.  CCB расшифровывается как \"CAM Control "
"Block\" (блок управления CAM).  Это объединение множества конкретных "
"экземпляров, каждый из которых описывает аргументы для определённого типа "
"транзакций.  Все эти экземпляры имеют общий заголовок CCB, в котором "
"хранится общая часть аргументов."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:271
msgid ""
"CAM supports the SCSI controllers working in both initiator (\"normal\") "
"mode and target (simulating a SCSI device) mode.  Here we only consider the "
"part relevant to the initiator mode."
msgstr ""
"CAM поддерживает SCSI-контроллеры, работающие как в режиме инициатора "
"(«обычном»), так и в режиме цели (эмулирующем SCSI-устройство). Здесь мы "
"рассматриваем только часть, относящуюся к режиму инициатора."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:273
msgid ""
"There are a few function and macros (in other words, methods) defined to "
"access the public data in the struct sim:"
msgstr ""
"Существует несколько функций и макросов (другими словами, методов), "
"определённых для доступа к публичным данным в структуре sim:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:275
msgid "`cam_sim_path(sim)` - the path ID (see above)"
msgstr "`cam_sim_path(sim)` - идентификатор пути (см. выше)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:276
msgid "`cam_sim_name(sim)` - the name of the sim"
msgstr "`cam_sim_name(sim)` — имя sim"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:277
msgid ""
"`cam_sim_softc(sim)` - the pointer to the softc (driver private data) "
"structure"
msgstr ""
"`cam_sim_softc(sim)` - указатель на структуру softc (приватные данные "
"драйвера)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:278
msgid "`cam_sim_unit(sim)` - the unit number"
msgstr "`cam_sim_unit(sim)` - номер устройства"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:279
msgid "`cam_sim_bus(sim)` - the bus ID"
msgstr "`cam_sim_bus(sim)` - идентификатор шины"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:281
msgid ""
"To identify the device, `xxx_action()` can get the unit number and pointer "
"to its structure softc using these functions."
msgstr ""
"Для идентификации устройства `xxx_action()` может получить номер устройства "
"и указатель на его структуру softc, используя следующие функции."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:284
msgid ""
"The type of request is stored in `ccb->ccb_h.func_code`.  So generally "
"`xxx_action()` consists of a big switch:"
msgstr ""
"Тип запроса хранится в `ccb->ccb_h.func_code`. Поэтому, как правило, "
"`xxx_action()` состоит из большого оператора switch:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:291
#, no-wrap
msgid ""
"    struct xxx_softc *softc = (struct xxx_softc *) cam_sim_softc(sim);\n"
"    struct ccb_hdr *ccb_h = &ccb->ccb_h;\n"
"    int unit = cam_sim_unit(sim);\n"
"    int bus = cam_sim_bus(sim);\n"
msgstr ""
"    struct xxx_softc *softc = (struct xxx_softc *) cam_sim_softc(sim);\n"
"    struct ccb_hdr *ccb_h = &ccb->ccb_h;\n"
"    int unit = cam_sim_unit(sim);\n"
"    int bus = cam_sim_bus(sim);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:300
#, no-wrap
msgid ""
"    switch (ccb_h->func_code) {\n"
"    case ...:\n"
"        ...\n"
"    default:\n"
"        ccb_h->status = CAM_REQ_INVALID;\n"
"        xpt_done(ccb);\n"
"        break;\n"
"    }\n"
msgstr ""
"    switch (ccb_h->func_code) {\n"
"    case ...:\n"
"        ...\n"
"    default:\n"
"        ccb_h->status = CAM_REQ_INVALID;\n"
"        xpt_done(ccb);\n"
"        break;\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:303
msgid ""
"As can be seen from the default case (if an unknown command was received) "
"the return code of the command is set into `ccb->ccb_h.status` and the "
"completed CCB is returned back to CAM by calling `xpt_done(ccb)`."
msgstr ""
"Как видно из случая по умолчанию (если получена неизвестная команда) код "
"возврата команды устанавливается в `ccb->ccb_h.status`, а завершённый CCB "
"возвращается обратно в CAM вызовом `xpt_done(ccb)`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:306
msgid ""
"`xpt_done()` does not have to be called from `xxx_action()`: For example an "
"I/O request may be enqueued inside the SIM driver and/or its SCSI "
"controller.  Then when the device would post an interrupt signaling that the "
"processing of this request is complete `xpt_done()` may be called from the "
"interrupt handling routine."
msgstr ""
"`xpt_done()` не обязательно вызывать из `xxx_action()`: Например, запрос "
"ввода-вывода может быть поставлен в очередь внутри драйвера SIM и/или его "
"SCSI-контроллера. Затем, когда устройство пошлет прерывание, сигнализирующее "
"о завершении обработки этого запроса, `xpt_done()` может быть вызван из "
"процедуры обработки прерывания."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:314
msgid ""
"Actually, the CCB status is not only assigned as a return code but a CCB has "
"some status all the time.  Before CCB is passed to the `xxx_action()` "
"routine it gets the status CCB_REQ_INPROG meaning that it is in progress.  "
"There are a surprising number of status values defined in [.filename]#/sys/"
"cam/cam.h# which should be able to represent the status of a request in "
"great detail.  More interesting yet, the status is in fact a \"bitwise or\" "
"of an enumerated status value (the lower 6 bits) and possible additional "
"flag-like bits (the upper bits).  The enumerated values will be discussed "
"later in more detail.  The summary of them can be found in the Errors "
"Summary section.  The possible status flags are:"
msgstr ""
"На самом деле, статус CCB не только присваивается в качестве кода возврата, "
"но и CCB всегда имеет какой-то статус. Перед тем как CCB передаётся в "
"процедуру `xxx_action()`, он получает статус CCB_REQ_INPROG, означающий, что "
"запрос находится в процессе выполнения. В [.filename]#/sys/cam/cam.h# "
"определено удивительно большое количество значений статуса, которые должны "
"детально отражать состояние запроса. Что ещё интереснее, статус фактически "
"представляет собой \"побитовое ИЛИ\" перечисленного значения статуса ("
"младшие 6 бит) и возможных дополнительных флагов (старшие биты). "
"Перечисленные значения будут подробно рассмотрены далее. Их краткое описание "
"можно найти в разделе \"Сводка ошибок\". Возможные флаги статуса:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:317
msgid ""
"_CAM_DEV_QFRZN_ - if the SIM driver gets a serious error (for example, the "
"device does not respond to the selection or breaks the SCSI protocol) when "
"processing a CCB it should freeze the request queue by calling "
"`xpt_freeze_simq()`, return the other enqueued but not processed yet CCBs "
"for this device back to the CAM queue, then set this flag for the "
"troublesome CCB and call `xpt_done()`.  This flag causes the CAM subsystem "
"to unfreeze the queue after it handles the error."
msgstr ""
"_CAM_DEV_QFRZN_ - если драйвер SIM получает серьёзную ошибку (например, "
"устройство не отвечает на выборку или нарушает протокол SCSI) при обработке "
"CCB, он должен заморозить очередь запросов, вызвав `xpt_freeze_simq()`, "
"вернуть другие поставленные в очередь, но ещё не обработанные CCB для этого "
"устройства обратно в очередь CAM, затем установить этот флаг для проблемного "
"CCB и вызвать `xpt_done()`. Этот флаг заставляет подсистему CAM разморозить "
"очередь после обработки ошибки."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:319
msgid ""
"_CAM_AUTOSNS_VALID_ - if the device returned an error condition and the flag "
"CAM_DIS_AUTOSENSE is not set in CCB the SIM driver must execute the REQUEST "
"SENSE command automatically to extract the sense (extended error "
"information) data from the device.  If this attempt was successful the sense "
"data should be saved in the CCB and this flag set."
msgstr ""
"_CAM_AUTOSNS_VALID_ - если устройство вернуло состояние ошибки и флаг "
"CAM_DIS_AUTOSENSE не установлен в CCB, драйвер SIM должен автоматически "
"выполнить команду REQUEST SENSE, чтобы извлечь данные sense (расширенную "
"информацию об ошибке) из устройства. Если попытка была успешной, данные "
"sense должны быть сохранены в CCB, а этот флаг установлен."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:322
msgid ""
"_CAM_RELEASE_SIMQ_ - like CAM_DEV_QFRZN but used in case there is some "
"problem (or resource shortage) with the SCSI controller itself.  Then all "
"the future requests to the controller should be stopped by "
"`xpt_freeze_simq()`.  The controller queue will be restarted after the SIM "
"driver overcomes the shortage and informs CAM by returning some CCB with "
"this flag set."
msgstr ""
"_CAM_RELEASE_SIMQ_ - аналогично CAM_DEV_QFRZN, но используется в случае "
"возникновения проблем (или нехватки ресурсов) с самим SCSI-контроллером. В "
"этом случае все последующие запросы к контроллеру должны быть остановлены с "
"помощью `xpt_freeze_simq()`. Очередь контроллера будет возобновлена после "
"того, как драйвер SIM устранит нехватку и уведомит CAM, вернув некоторый CCB "
"с установленным этим флагом."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:324
msgid ""
"_CAM_SIM_QUEUED_ - when SIM puts a CCB into its request queue this flag "
"should be set (and removed when this CCB gets dequeued before being returned "
"back to CAM).  This flag is not used anywhere in the CAM code now, so its "
"purpose is purely diagnostic."
msgstr ""
"_CAM_SIM_QUEUED_ - этот флаг должен быть установлен, когда SIM помещает CCB "
"в свою очередь запросов (и снят, когда этот CCB извлекается из очереди перед "
"возвратом в CAM). В настоящее время этот флаг нигде не используется в коде "
"CAM, поэтому его назначение чисто диагностическое."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:325
msgid "_CAM_QOS_VALID_ - The QOS data is now valid."
msgstr "_CAM_QOS_VALID_ - Данные QOS теперь действительны."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:328
msgid ""
"The function `xxx_action()` is not allowed to sleep, so all the "
"synchronization for resource access must be done using SIM or device queue "
"freezing.  Besides the aforementioned flags the CAM subsystem provides "
"functions `xpt_release_simq()` and `xpt_release_devq()` to unfreeze the "
"queues directly, without passing a CCB to CAM."
msgstr ""
"Функция `xxx_action()` не может находиться в состоянии ожидания, поэтому вся "
"синхронизация доступа к ресурсам должна выполняться с использованием SIM или "
"заморозки очереди устройств. Помимо упомянутых флагов, подсистема CAM "
"предоставляет функции `xpt_release_simq()` и `xpt_release_devq()` для "
"разморозки очередей напрямую, без передачи CCB в CAM."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:330
msgid "The CCB header contains the following fields:"
msgstr "Заголовок CCB содержит следующие поля:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:332
msgid "_path_ - path ID for the request"
msgstr "_path_ - идентификатор пути для запроса"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:333
msgid "_target_id_ - target device ID for the request"
msgstr "_target_id_ - идентификатор целевого устройства для запроса"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:334
msgid "_target_lun_ - LUN ID of the target device"
msgstr "_target_lun_ - идентификатор LUN целевого устройства"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:335
msgid "_timeout_ - timeout interval for this command, in milliseconds"
msgstr "_timeout_ - интервал таймаута для этой команды, в миллисекундах"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:336
msgid ""
"_timeout_ch_ - a convenience place for the SIM driver to store the timeout "
"handle (the CAM subsystem itself does not make any assumptions about it)"
msgstr ""
"_timeout_ch_ - удобное место для драйвера SIM, чтобы хранить обработчик "
"таймаута (сама подсистема CAM не делает никаких предположений о нём)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:337
msgid ""
"_flags_ - various bits of information about the request spriv_ptr0, "
"spriv_ptr1 - fields reserved for private use by the SIM driver (such as "
"linking to the SIM queues or SIM private control blocks); actually, they "
"exist as unions: spriv_ptr0 and spriv_ptr1 have the type (void *), "
"spriv_field0 and spriv_field1 have the type unsigned long, "
"sim_priv.entries[0].bytes and sim_priv.entries[1].bytes are byte arrays of "
"the size consistent with the other incarnations of the union and "
"sim_priv.bytes is one array, twice bigger."
msgstr ""
"_flags_ - различные биты информации о запросе spriv_ptr0, spriv_ptr1 — поля, "
"зарезервированные для приватного использования драйвером SIM (например, для "
"связи с очередями SIM или приватными блоками управления SIM); фактически они "
"существуют как объединения: spriv_ptr0 и spriv_ptr1 имеют тип (void *), "
"spriv_field0 и spriv_field1 имеют тип unsigned long, sim_priv.entries[0]."
"bytes и sim_priv.entries[1].bytes - это байтовые массивы размера, "
"согласованного с другими вариантами объединения, а sim_priv.bytes - это один "
"массив, вдвое большего размера."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:339
msgid ""
"The recommended way of using the SIM private fields of CCB is to define some "
"meaningful names for them and use these meaningful names in the driver, like:"
msgstr ""
"Рекомендуемый способ использования приватных полей SIM в CCB — это "
"определить для них осмысленные имена и использовать эти осмысленные имена в "
"драйвере, например:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:344
#, no-wrap
msgid ""
"#define ccb_some_meaningful_name    sim_priv.entries[0].bytes\n"
"#define ccb_hcb spriv_ptr1 /* for hardware control block */\n"
msgstr ""
"#define ccb_some_meaningful_name    sim_priv.entries[0].bytes\n"
"#define ccb_hcb spriv_ptr1 /* for hardware control block */\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:347
msgid "The most common initiator mode requests are:"
msgstr "Наиболее распространённые запросы в режиме инициатора:"

#. type: Title ===
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:348
#, no-wrap
msgid "_XPT_SCSI_IO_ - execute an I/O transaction"
msgstr "_XPT_SCSI_IO_ — выполнить транзакцию ввода-вывода"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:352
msgid ""
"The instance \"struct ccb_scsiio csio\" of the union ccb is used to transfer "
"the arguments.  They are:"
msgstr ""
"Экземпляр \"struct ccb_scsiio csio\" объединения ccb используется для "
"передачи аргументов. Они включают:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:354
msgid "_cdb_io_ - pointer to the SCSI command buffer or the buffer itself"
msgstr "_cdb_io_ - указатель на буфер команды SCSI или сам буфер"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:355
msgid "_cdb_len_ - SCSI command length"
msgstr "_cdb_len_ - длина команды SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:356
msgid ""
"_data_ptr_ - pointer to the data buffer (gets a bit complicated if scatter/"
"gather is used)"
msgstr ""
"_data_ptr_ - указатель на буфер данных (усложняется, если используется "
"scatter/gather)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:357
msgid "_dxfer_len_ - length of the data to transfer"
msgstr "_dxfer_len_ - длина передаваемых данных"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:358
msgid "_sglist_cnt_ - counter of the scatter/gather segments"
msgstr "_sglist_cnt_ - счетчик сегментов scatter/gather"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:359
msgid "_scsi_status_ - place to return the SCSI status"
msgstr "_scsi_status_ - место для возврата статуса SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:360
msgid ""
"_sense_data_ - buffer for the SCSI sense information if the command returns "
"an error (the SIM driver is supposed to run the REQUEST SENSE command "
"automatically in this case if the CCB flag CAM_DIS_AUTOSENSE is not set)"
msgstr ""
"_sense_data_ - буфер для информации SCSI sense, если команда возвращает "
"ошибку (драйвер SIM должен автоматически выполнить команду REQUEST SENSE в "
"этом случае, если флаг CCB CAM_DIS_AUTOSENSE не установлен)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:361
msgid ""
"_sense_len_ - the length of that buffer (if it happens to be higher than "
"size of sense_data the SIM driver must silently assume the smaller value)"
msgstr ""
"_sense_len_ - длина этого буфера (если она окажется больше размера "
"sense_data, драйвер SIM должен без уведомления принять меньшее значение)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:364
msgid ""
"_resid_, _sense_resid_ - if the transfer of data or SCSI sense returned an "
"error these are the returned counters of the residual (not transferred) "
"data.  They do not seem to be especially meaningful, so in a case when they "
"are difficult to compute (say, counting bytes in the SCSI controller's FIFO "
"buffer) an approximate value will do as well.  For a successfully completed "
"transfer they must be set to zero."
msgstr ""
"_resid_, _sense_resid_ — если передача данных или SCSI sense вернула ошибку, "
"это счётчики остаточных (не переданных) данных. Они не кажутся особенно "
"значимыми, поэтому в случаях, когда их сложно вычислить (например, подсчёт "
"байтов в FIFO-буфере SCSI-контроллера), подойдёт и приблизительное значение. "
"Для успешно завершённой передачи они должны быть установлены в ноль."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:365
msgid "_tag_action_ - the kind of tag to use:"
msgstr "_tag_action_ - тип используемого тега:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:366
msgid "CAM_TAG_ACTION_NONE - do not use tags for this transaction"
msgstr "`CAM_TAG_ACTION_NONE` - не использовать теги для данной транзакции"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:367
msgid ""
"MSG_SIMPLE_Q_TAG, MSG_HEAD_OF_Q_TAG, MSG_ORDERED_Q_TAG - value equal to the "
"appropriate tag message (see /sys/cam/scsi/scsi_message.h); this gives only "
"the tag type, the SIM driver must assign the tag value itself"
msgstr ""
"MSG_SIMPLE_Q_TAG, MSG_HEAD_OF_Q_TAG, MSG_ORDERED_Q_TAG — значение, "
"соответствующее указанному теговому сообщению (см. /sys/cam/scsi/scsi_message"
".h); указывает только тип тега, значение тега должно быть назначено самим "
"драйвером SIM"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:369
msgid "The general logic of handling this request is the following:"
msgstr "Общая логика обработки этого запроса следующая:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:371
msgid ""
"The first thing to do is to check for possible races, to make sure that the "
"command did not get aborted when it was sitting in the queue:"
msgstr ""
"Первое, что нужно сделать, это проверить возможные состояния гонки, чтобы "
"убедиться, что команда не была прервана, пока находилась в очереди:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:375
#, no-wrap
msgid "    struct ccb_scsiio *csio = &ccb->csio;\n"
msgstr "    struct ccb_scsiio *csio = &ccb->csio;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:380
#, no-wrap
msgid ""
"    if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"
msgstr ""
"    if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:383
msgid "Also we check that the device is supported at all by our controller:"
msgstr ""
"Также мы проверяем, что устройство вообще поддерживается нашим контроллером:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:397
#, no-wrap
msgid ""
"    if (ccb_h->target_id > OUR_MAX_SUPPORTED_TARGET_ID\n"
"    || cch_h->target_id == OUR_SCSI_CONTROLLERS_OWN_ID) {\n"
"        ccb_h->status = CAM_TID_INVALID;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"
"    if (ccb_h->target_lun > OUR_MAX_SUPPORTED_LUN) {\n"
"        ccb_h->status = CAM_LUN_INVALID;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"
msgstr ""
"    if (ccb_h->target_id > OUR_MAX_SUPPORTED_TARGET_ID\n"
"    || cch_h->target_id == OUR_SCSI_CONTROLLERS_OWN_ID) {\n"
"        ccb_h->status = CAM_TID_INVALID;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"
"    if (ccb_h->target_lun > OUR_MAX_SUPPORTED_LUN) {\n"
"        ccb_h->status = CAM_LUN_INVALID;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:403
msgid ""
"Then allocate whatever data structures (such as card-dependent hardware "
"control block) we need to process this request.  If we can not then freeze "
"the SIM queue and remember that we have a pending operation, return the CCB "
"back and ask CAM to re-queue it.  Later when the resources become available "
"the SIM queue must be unfrozen by returning a ccb with the "
"`CAM_SIMQ_RELEASE` bit set in its status.  Otherwise, if all went well, link "
"the CCB with the hardware control block (HCB) and mark it as queued."
msgstr ""
"Затем выделяем все необходимые структуры данных (такие как зависящий от "
"карты блок управления оборудованием), которые нам нужны для обработки этого "
"запроса. Если мы не можем этого сделать, то замораживаем очередь SIM и "
"запоминаем, что у нас есть отложенная операция, возвращаем CCB обратно и "
"просим CAM поставить его в очередь снова. Позже, когда ресурсы станут "
"доступны, очередь SIM должна быть разморожена путём возврата CCB с "
"установленным битом `CAM_SIMQ_RELEASE` в его статусе. В противном случае, "
"если всё прошло успешно, связываем CCB с блоком управления оборудованием "
"(HCB) и помечаем его как поставленный в очередь."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:407
#, no-wrap
msgid "    struct xxx_hcb *hcb = allocate_hcb(softc, unit, bus);\n"
msgstr "    struct xxx_hcb *hcb = allocate_hcb(softc, unit, bus);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:415
#, no-wrap
msgid ""
"    if (hcb == NULL) {\n"
"        softc->flags |= RESOURCE_SHORTAGE;\n"
"        xpt_freeze_simq(sim, /*count*/1);\n"
"        ccb_h->status = CAM_REQUEUE_REQ;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"
msgstr ""
"    if (hcb == NULL) {\n"
"        softc->flags |= RESOURCE_SHORTAGE;\n"
"        xpt_freeze_simq(sim, /*count*/1);\n"
"        ccb_h->status = CAM_REQUEUE_REQ;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:418
#, no-wrap
msgid ""
"    hcb->ccb = ccb; ccb_h->ccb_hcb = (void *)hcb;\n"
"    ccb_h->status |= CAM_SIM_QUEUED;\n"
msgstr ""
"    hcb->ccb = ccb; ccb_h->ccb_hcb = (void *)hcb;\n"
"    ccb_h->status |= CAM_SIM_QUEUED;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:423
msgid ""
"Extract the target data from CCB into the hardware control block.  Check if "
"we are asked to assign a tag and if yes then generate an unique tag and "
"build the SCSI tag messages.  The SIM driver is also responsible for "
"negotiations with the devices to set the maximal mutually supported bus "
"width, synchronous rate and offset."
msgstr ""
"Извлечь целевые данные из CCB в аппаратный блок управления. Проверить, "
"запрошено ли назначение тега, и если да, то сгенерировать уникальный тег и "
"построить сообщения тега SCSI. Драйвер SIM также отвечает за согласование с "
"устройствами для установки максимальной взаимно поддерживаемой ширины шины, "
"синхронной скорости и смещения."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:432
#, no-wrap
msgid ""
"    hcb->target = ccb_h->target_id; hcb->lun = ccb_h->target_lun;\n"
"    generate_identify_message(hcb);\n"
"    if (ccb_h->tag_action != CAM_TAG_ACTION_NONE)\n"
"        generate_unique_tag_message(hcb, ccb_h->tag_action);\n"
"    if (!target_negotiated(hcb))\n"
"        generate_negotiation_messages(hcb);\n"
msgstr ""
"    hcb->target = ccb_h->target_id; hcb->lun = ccb_h->target_lun;\n"
"    generate_identify_message(hcb);\n"
"    if (ccb_h->tag_action != CAM_TAG_ACTION_NONE)\n"
"        generate_unique_tag_message(hcb, ccb_h->tag_action);\n"
"    if (!target_negotiated(hcb))\n"
"        generate_negotiation_messages(hcb);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:438
msgid ""
"Then set up the SCSI command.  The command storage may be specified in the "
"CCB in many interesting ways, specified by the CCB flags.  The command "
"buffer can be contained in CCB or pointed to, in the latter case the pointer "
"may be physical or virtual.  Since the hardware commonly needs physical "
"address we always convert the address to the physical one, typically using "
"the busdma API."
msgstr ""
"Затем настройте команду SCSI. Хранилище команды может быть указано в CCB "
"различными способами, определяемыми флагами CCB. Буфер команды может "
"содержаться в CCB или указываться на него; в последнем случае указатель "
"может быть физическим или виртуальным. Поскольку оборудованию обычно "
"требуется физический адрес, мы всегда преобразуем адрес в физический, как "
"правило, используя API busdma."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:441
msgid ""
"In case if a physical address is requested it is OK to return the CCB with "
"the status `CAM_REQ_INVALID`, the current drivers do that.  If necessary a "
"physical address can be also converted or mapped back to a virtual address "
"but with big pain, so we do not do that."
msgstr ""
"В случае, если запрашивается физический адрес, допустимо вернуть CCB со "
"статусом `CAM_REQ_INVALID`, текущие драйверы так и делают. При необходимости "
"физический адрес также может быть преобразован или отображён обратно в "
"виртуальный, но с большими трудностями, поэтому мы этого не делаем."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:458
#, no-wrap
msgid ""
"    if (ccb_h->flags & CAM_CDB_POINTER) {\n"
"        /* CDB is a pointer */\n"
"        if (!(ccb_h->flags & CAM_CDB_PHYS)) {\n"
"            /* CDB pointer is virtual */\n"
"            hcb->cmd = vtobus(csio->cdb_io.cdb_ptr);\n"
"        } else {\n"
"            /* CDB pointer is physical */\n"
"            hcb->cmd = csio->cdb_io.cdb_ptr ;\n"
"        }\n"
"    } else {\n"
"        /* CDB is in the ccb (buffer) */\n"
"        hcb->cmd = vtobus(csio->cdb_io.cdb_bytes);\n"
"    }\n"
"    hcb->cmdlen = csio->cdb_len;\n"
msgstr ""
"    if (ccb_h->flags & CAM_CDB_POINTER) {\n"
"        /* CDB is a pointer */\n"
"        if (!(ccb_h->flags & CAM_CDB_PHYS)) {\n"
"            /* CDB pointer is virtual */\n"
"            hcb->cmd = vtobus(csio->cdb_io.cdb_ptr);\n"
"        } else {\n"
"            /* CDB pointer is physical */\n"
"            hcb->cmd = csio->cdb_io.cdb_ptr ;\n"
"        }\n"
"    } else {\n"
"        /* CDB is in the ccb (buffer) */\n"
"        hcb->cmd = vtobus(csio->cdb_io.cdb_bytes);\n"
"    }\n"
"    hcb->cmdlen = csio->cdb_len;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:464
msgid ""
"Now it is time to set up the data.  Again, the data storage may be specified "
"in the CCB in many interesting ways, specified by the CCB flags.  First we "
"get the direction of the data transfer.  The simplest case is if there is no "
"data to transfer:"
msgstr ""
"Теперь настало время настроить данные. Опять же, хранилище данных может быть "
"указано в CCB различными интересными способами, определяемыми флагами CCB. "
"Сначала мы получаем направление передачи данных. Самый простой случай — если "
"нет данных для передачи:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:468
#, no-wrap
msgid "    int dir = (ccb_h->flags & CAM_DIR_MASK);\n"
msgstr "    int dir = (ccb_h->flags & CAM_DIR_MASK);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:471
#, no-wrap
msgid ""
"    if (dir == CAM_DIR_NONE)\n"
"        goto end_data;\n"
msgstr ""
"    if (dir == CAM_DIR_NONE)\n"
"        goto end_data;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:482
msgid ""
"Then we check if the data is in one chunk or in a scatter-gather list, and "
"the addresses are physical or virtual.  The SCSI controller may be able to "
"handle only a limited number of chunks of limited length.  If the request "
"hits this limitation we return an error.  We use a special function to "
"return the CCB to handle in one place the HCB resource shortages.  The "
"functions to add chunks are driver-dependent, and here we leave them without "
"detailed implementation.  See description of the SCSI command (CDB) handling "
"for the details on the address-translation issues.  If some variation is too "
"difficult or impossible to implement with a particular card it is OK to "
"return the status `CAM_REQ_INVALID`.  Actually, it seems like the scatter-"
"gather ability is not used anywhere in the CAM code now.  But at least the "
"case for a single non-scattered virtual buffer must be implemented, it is "
"actively used by CAM."
msgstr ""
"Затем мы проверяем, находятся ли данные в одном фрагменте или в списке "
"scatter-gather, а также являются ли адреса физическими или виртуальными. "
"SCSI-контроллер может обрабатывать только ограниченное количество фрагментов "
"ограниченной длины. Если запрос превышает это ограничение, мы возвращаем "
"ошибку. Мы используем специальную функцию для возврата CCB, чтобы в одном "
"месте обрабатывать нехватку ресурсов HCB. Функции для добавления фрагментов "
"зависят от драйвера, и здесь мы оставляем их без детальной реализации. "
"Подробности о проблемах трансляции адресов см. в описании обработки SCSI-"
"команд (CDB). Если какая-то вариация слишком сложна или невозможна для "
"реализации с конкретной картой, допустимо вернуть статус `CAM_REQ_INVALID`. "
"На самом деле, похоже, что возможность scatter-gather нигде в коде CAM "
"сейчас не используется. Но как минимум случай с единичным неразделённым "
"виртуальным буфером должен быть реализован, так как он активно используется "
"CAM."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:486
#, no-wrap
msgid "    int rv;\n"
msgstr "    int rv;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:488
#, no-wrap
msgid "    initialize_hcb_for_data(hcb);\n"
msgstr "    initialize_hcb_for_data(hcb);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:501
#, no-wrap
msgid ""
"    if ((!(ccb_h->flags & CAM_SCATTER_VALID)) {\n"
"        /* single buffer */\n"
"        if (!(ccb_h->flags & CAM_DATA_PHYS)) {\n"
"            rv = add_virtual_chunk(hcb, csio->data_ptr, csio->dxfer_len, dir);\n"
"            }\n"
"        } else {\n"
"            rv = add_physical_chunk(hcb, csio->data_ptr, csio->dxfer_len, dir);\n"
"        }\n"
"    } else {\n"
"        int i;\n"
"        struct bus_dma_segment *segs;\n"
"        segs = (struct bus_dma_segment *)csio->data_ptr;\n"
msgstr ""
"    if ((!(ccb_h->flags & CAM_SCATTER_VALID)) {\n"
"        /* single buffer */\n"
"        if (!(ccb_h->flags & CAM_DATA_PHYS)) {\n"
"            rv = add_virtual_chunk(hcb, csio->data_ptr, csio->dxfer_len, "
"dir);\n"
"            }\n"
"        } else {\n"
"            rv = add_physical_chunk(hcb, csio->data_ptr, csio->dxfer_len, "
"dir);\n"
"        }\n"
"    } else {\n"
"        int i;\n"
"        struct bus_dma_segment *segs;\n"
"        segs = (struct bus_dma_segment *)csio->data_ptr;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:533
#, no-wrap
msgid ""
"        if ((ccb_h->flags & CAM_SG_LIST_PHYS) != 0) {\n"
"            /* The SG list pointer is physical */\n"
"            rv = setup_hcb_for_physical_sg_list(hcb, segs, csio->sglist_cnt);\n"
"        } else if (!(ccb_h->flags & CAM_DATA_PHYS)) {\n"
"            /* SG buffer pointers are virtual */\n"
"            for (i = 0; i < csio->sglist_cnt; i++) {\n"
"                rv = add_virtual_chunk(hcb, segs[i].ds_addr,\n"
"                    segs[i].ds_len, dir);\n"
"                if (rv != CAM_REQ_CMP)\n"
"                    break;\n"
"            }\n"
"        } else {\n"
"            /* SG buffer pointers are physical */\n"
"            for (i = 0; i < csio->sglist_cnt; i++) {\n"
"                rv = add_physical_chunk(hcb, segs[i].ds_addr,\n"
"                    segs[i].ds_len, dir);\n"
"                if (rv != CAM_REQ_CMP)\n"
"                    break;\n"
"            }\n"
"        }\n"
"    }\n"
"    if (rv != CAM_REQ_CMP) {\n"
"        /* we expect that add_*_chunk() functions return CAM_REQ_CMP\n"
"         * if they added a chunk successfully, CAM_REQ_TOO_BIG if\n"
"         * the request is too big (too many bytes or too many chunks),\n"
"         * CAM_REQ_INVALID in case of other troubles\n"
"         */\n"
"        free_hcb_and_ccb_done(hcb, ccb, rv);\n"
"        return;\n"
"    }\n"
"    end_data:\n"
msgstr ""
"        if ((ccb_h->flags & CAM_SG_LIST_PHYS) != 0) {\n"
"            /* The SG list pointer is physical */\n"
"            rv = setup_hcb_for_physical_sg_list(hcb, segs, csio->sglist_cnt);"
"\n"
"        } else if (!(ccb_h->flags & CAM_DATA_PHYS)) {\n"
"            /* SG buffer pointers are virtual */\n"
"            for (i = 0; i < csio->sglist_cnt; i++) {\n"
"                rv = add_virtual_chunk(hcb, segs[i].ds_addr,\n"
"                    segs[i].ds_len, dir);\n"
"                if (rv != CAM_REQ_CMP)\n"
"                    break;\n"
"            }\n"
"        } else {\n"
"            /* SG buffer pointers are physical */\n"
"            for (i = 0; i < csio->sglist_cnt; i++) {\n"
"                rv = add_physical_chunk(hcb, segs[i].ds_addr,\n"
"                    segs[i].ds_len, dir);\n"
"                if (rv != CAM_REQ_CMP)\n"
"                    break;\n"
"            }\n"
"        }\n"
"    }\n"
"    if (rv != CAM_REQ_CMP) {\n"
"        /* we expect that add_*_chunk() functions return CAM_REQ_CMP\n"
"         * if they added a chunk successfully, CAM_REQ_TOO_BIG if\n"
"         * the request is too big (too many bytes or too many chunks),\n"
"         * CAM_REQ_INVALID in case of other troubles\n"
"         */\n"
"        free_hcb_and_ccb_done(hcb, ccb, rv);\n"
"        return;\n"
"    }\n"
"    end_data:\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:536
msgid ""
"If disconnection is disabled for this CCB we pass this information to the "
"hcb:"
msgstr ""
"Если отключение запрещено для этого CCB, мы передаем эту информацию в hcb:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:541
#, no-wrap
msgid ""
"    if (ccb_h->flags & CAM_DIS_DISCONNECT)\n"
"        hcb_disable_disconnect(hcb);\n"
msgstr ""
"    if (ccb_h->flags & CAM_DIS_DISCONNECT)\n"
"        hcb_disable_disconnect(hcb);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:544
msgid ""
"If the controller is able to run REQUEST SENSE command all by itself then "
"the value of the flag CAM_DIS_AUTOSENSE should also be passed to it, to "
"prevent automatic REQUEST SENSE if the CAM subsystem does not want it."
msgstr ""
"Если контроллер способен самостоятельно выполнять команду REQUEST SENSE, то "
"ему также следует передать значение флага CAM_DIS_AUTOSENSE, чтобы "
"предотвратить автоматическое выполнение REQUEST SENSE, если подсистема CAM "
"этого не требует."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:546
msgid ""
"The only thing left is to set up the timeout, pass our hcb to the hardware "
"and return, the rest will be done by the interrupt handler (or timeout "
"handler)."
msgstr ""
"Осталось только установить таймаут, передать наш hcb оборудованию и "
"вернуться, остальное будет сделано обработчиком прерывания (или обработчиком "
"таймаута)."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:553
#, no-wrap
msgid ""
"    ccb_h->timeout_ch = timeout(xxx_timeout, (caddr_t) hcb,\n"
"        (ccb_h->timeout * hz) / 1000); /* convert milliseconds to ticks */\n"
"    put_hcb_into_hardware_queue(hcb);\n"
"    return;\n"
msgstr ""
"    ccb_h->timeout_ch = timeout(xxx_timeout, (caddr_t) hcb,\n"
"        (ccb_h->timeout * hz) / 1000); /* convert milliseconds to ticks */\n"
"    put_hcb_into_hardware_queue(hcb);\n"
"    return;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:556
msgid "And here is a possible implementation of the function returning CCB:"
msgstr "И вот возможная реализация функции, возвращающей CCB:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:563
#, no-wrap
msgid ""
"    static void\n"
"    free_hcb_and_ccb_done(struct xxx_hcb *hcb, union ccb *ccb, u_int32_t status)\n"
"    {\n"
"        struct xxx_softc *softc = hcb->softc;\n"
msgstr ""
"    static void\n"
"    free_hcb_and_ccb_done(struct xxx_hcb *hcb, union ccb *ccb, u_int32_t "
"status)\n"
"    {\n"
"        struct xxx_softc *softc = hcb->softc;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:578
#, no-wrap
msgid ""
"        ccb->ccb_h.ccb_hcb = 0;\n"
"        if (hcb != NULL) {\n"
"            untimeout(xxx_timeout, (caddr_t) hcb, ccb->ccb_h.timeout_ch);\n"
"            /* we're about to free a hcb, so the shortage has ended */\n"
"            if (softc->flags & RESOURCE_SHORTAGE)  {\n"
"                softc->flags &= ~RESOURCE_SHORTAGE;\n"
"                status |= CAM_RELEASE_SIMQ;\n"
"            }\n"
"            free_hcb(hcb); /* also removes hcb from any internal lists */\n"
"        }\n"
"        ccb->ccb_h.status = status |\n"
"            (ccb->ccb_h.status & ~(CAM_STATUS_MASK|CAM_SIM_QUEUED));\n"
"        xpt_done(ccb);\n"
"    }\n"
msgstr ""
"        ccb->ccb_h.ccb_hcb = 0;\n"
"        if (hcb != NULL) {\n"
"            untimeout(xxx_timeout, (caddr_t) hcb, ccb->ccb_h.timeout_ch);\n"
"            /* we're about to free a hcb, so the shortage has ended */\n"
"            if (softc->flags & RESOURCE_SHORTAGE)  {\n"
"                softc->flags &= ~RESOURCE_SHORTAGE;\n"
"                status |= CAM_RELEASE_SIMQ;\n"
"            }\n"
"            free_hcb(hcb); /* also removes hcb from any internal lists */\n"
"        }\n"
"        ccb->ccb_h.status = status |\n"
"            (ccb->ccb_h.status & ~(CAM_STATUS_MASK|CAM_SIM_QUEUED));\n"
"        xpt_done(ccb);\n"
"    }\n"

#. type: Title ===
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:580
#, no-wrap
msgid "_XPT_RESET_DEV_ - send the SCSI \"BUS DEVICE RESET\" message to a device"
msgstr ""
"_XPT_RESET_DEV_ — отправить устройству сообщение SCSI \"BUS DEVICE RESET\""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:585
msgid ""
"There is no data transferred in CCB except the header and the most "
"interesting argument of it is target_id.  Depending on the controller "
"hardware a hardware control block just like for the XPT_SCSI_IO request may "
"be constructed (see XPT_SCSI_IO request description) and sent to the "
"controller or the SCSI controller may be immediately programmed to send this "
"RESET message to the device or this request may be just not supported (and "
"return the status `CAM_REQ_INVALID`).  Also on completion of the request all "
"the disconnected transactions for this target must be aborted (probably in "
"the interrupt routine)."
msgstr ""
"В CCB не передаются данные, кроме заголовка, и наиболее интересным "
"аргументом в нём является target_id. В зависимости от аппаратного "
"обеспечения контроллера может быть создан аппаратный блок управления (как "
"для запроса XPT_SCSI_IO, см. описание запроса XPT_SCSI_IO) и отправлен "
"контроллеру, или SCSI-контроллер может быть немедленно запрограммирован на "
"отправку этого сообщения RESET устройству, или этот запрос может просто не "
"поддерживаться (и возвращать статус `CAM_REQ_INVALID`). Также при завершении "
"запроса все отключенные транзакции для этого целевого устройства должны быть "
"прерваны (вероятно, в процедуре прерывания)."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:588
msgid ""
"Also all the current negotiations for the target are lost on reset, so they "
"might be cleaned too.  Or they clearing may be deferred, because anyway the "
"target would request re-negotiation on the next transaction."
msgstr ""
"Кроме того, все текущие переговоры для цели теряются при сбросе, поэтому они "
"также могут быть очищены. Или их очистка может быть отложена, так как в "
"любом случае цель запросит повторные переговоры при следующей транзакции."

#. type: Title ===
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:589
#, no-wrap
msgid "_XPT_RESET_BUS_ - send the RESET signal to the SCSI bus"
msgstr "_XPT_RESET_BUS_ — отправить сигнал RESET на шину SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:592
msgid ""
"No arguments are passed in the CCB, the only interesting argument is the "
"SCSI bus indicated by the struct sim pointer."
msgstr ""
"В CCB не передаются аргументы, единственный интересный аргумент — это шина "
"SCSI, указанная структурой sim."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:594
msgid ""
"A minimalistic implementation would forget the SCSI negotiations for all the "
"devices on the bus and return the status CAM_REQ_CMP."
msgstr ""
"Минималистичная реализация могла бы пропустить SCSI-переговоры для всех "
"устройств на шине и вернуть статус CAM_REQ_CMP."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:597
msgid ""
"The proper implementation would in addition actually reset the SCSI bus "
"(possible also reset the SCSI controller) and mark all the CCBs being "
"processed, both those in the hardware queue and those being disconnected, as "
"done with the status CAM_SCSI_BUS_RESET.  Like:"
msgstr ""
"Правильная реализация дополнительно должна фактически сбросить шину SCSI ("
"возможно, также сбросить контроллер SCSI) и пометить все обрабатываемые CCB, "
"как находящиеся в аппаратной очереди, так и отключенные, как завершенные со "
"статусом CAM_SCSI_BUS_RESET. Например:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:603
#, no-wrap
msgid ""
"    int targ, lun;\n"
"    struct xxx_hcb *h, *hh;\n"
"    struct ccb_trans_settings neg;\n"
"    struct cam_path *path;\n"
msgstr ""
"    int targ, lun;\n"
"    struct xxx_hcb *h, *hh;\n"
"    struct ccb_trans_settings neg;\n"
"    struct cam_path *path;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:609
#, no-wrap
msgid ""
"    /* The SCSI bus reset may take a long time, in this case its completion\n"
"     * should be checked by interrupt or timeout. But for simplicity\n"
"     * we assume here that it is really fast.\n"
"     */\n"
"    reset_scsi_bus(softc);\n"
msgstr ""
"    /* The SCSI bus reset may take a long time, in this case its completion\n"
"     * should be checked by interrupt or timeout. But for simplicity\n"
"     * we assume here that it is really fast.\n"
"     */\n"
"    reset_scsi_bus(softc);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:615
#, no-wrap
msgid ""
"    /* drop all enqueued CCBs */\n"
"    for (h = softc->first_queued_hcb; h != NULL; h = hh) {\n"
"        hh = h->next;\n"
"        free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n"
"    }\n"
msgstr ""
"    /* drop all enqueued CCBs */\n"
"    for (h = softc->first_queued_hcb; h != NULL; h = hh) {\n"
"        hh = h->next;\n"
"        free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n"
"    }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:621
#, no-wrap
msgid ""
"    /* the clean values of negotiations to report */\n"
"    neg.bus_width = 8;\n"
"    neg.sync_period = neg.sync_offset = 0;\n"
"    neg.valid = (CCB_TRANS_BUS_WIDTH_VALID\n"
"        | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);\n"
msgstr ""
"    /* the clean values of negotiations to report */\n"
"    neg.bus_width = 8;\n"
"    neg.sync_period = neg.sync_offset = 0;\n"
"    neg.valid = (CCB_TRANS_BUS_WIDTH_VALID\n"
"        | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:625
#, no-wrap
msgid ""
"    /* drop all disconnected CCBs and clean negotiations  */\n"
"    for (targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {\n"
"        clean_negotiations(softc, targ);\n"
msgstr ""
"    /* drop all disconnected CCBs and clean negotiations  */\n"
"    for (targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {\n"
"        clean_negotiations(softc, targ);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:633
#, no-wrap
msgid ""
"        /* report the event if possible */\n"
"        if (xpt_create_path(&path, /*periph*/NULL,\n"
"                cam_sim_path(sim), targ,\n"
"                CAM_LUN_WILDCARD) == CAM_REQ_CMP) {\n"
"            xpt_async(AC_TRANSFER_NEG, path, &neg);\n"
"            xpt_free_path(path);\n"
"        }\n"
msgstr ""
"        /* report the event if possible */\n"
"        if (xpt_create_path(&path, /*periph*/NULL,\n"
"                cam_sim_path(sim), targ,\n"
"                CAM_LUN_WILDCARD) == CAM_REQ_CMP) {\n"
"            xpt_async(AC_TRANSFER_NEG, path, &neg);\n"
"            xpt_free_path(path);\n"
"        }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:640
#, no-wrap
msgid ""
"        for (lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)\n"
"            for (h = softc->first_discon_hcb[targ][lun]; h != NULL; h = hh) {\n"
"                hh=h->next;\n"
"                free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n"
"            }\n"
"    }\n"
msgstr ""
"        for (lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)\n"
"            for (h = softc->first_discon_hcb[targ][lun]; h != NULL; h = hh) {"
"\n"
"                hh=h->next;\n"
"                free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n"
"            }\n"
"    }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:643
#, no-wrap
msgid ""
"    ccb->ccb_h.status = CAM_REQ_CMP;\n"
"    xpt_done(ccb);\n"
msgstr ""
"    ccb->ccb_h.status = CAM_REQ_CMP;\n"
"    xpt_done(ccb);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:647
#, no-wrap
msgid ""
"    /* report the event */\n"
"    xpt_async(AC_BUS_RESET, softc->wpath, NULL);\n"
"    return;\n"
msgstr ""
"    /* report the event */\n"
"    xpt_async(AC_BUS_RESET, softc->wpath, NULL);\n"
"    return;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:650
msgid ""
"Implementing the SCSI bus reset as a function may be a good idea because it "
"would be re-used by the timeout function as a last resort if the things go "
"wrong."
msgstr ""
"Реализация сброса шины SCSI в виде функции может быть хорошей идеей, так как "
"она может быть повторно использована функцией таймаута в качестве последнего "
"средства, если что-то пойдёт не так."

#. type: Title ===
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:651
#, no-wrap
msgid "_XPT_ABORT_ - abort the specified CCB"
msgstr "_XPT_ABORT_ — прервать указанный CCB"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:655
msgid ""
"The arguments are transferred in the instance \"struct ccb_abort cab\" of "
"the union ccb.  The only argument field in it is:"
msgstr ""
"Аргументы передаются в экземпляре \"struct ccb_abort cab\" объединения ccb. "
"Единственное поле аргумента в нём:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:657
msgid "_abort_ccb_ - pointer to the CCB to be aborted"
msgstr "_abort_ccb_ — указатель на CCB, который необходимо прервать"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:660
msgid ""
"If the abort is not supported just return the status CAM_UA_ABORT.  This is "
"also the easy way to minimally implement this call, return CAM_UA_ABORT in "
"any case."
msgstr ""
"Если прерывание не поддерживается, просто верните статус CAM_UA_ABORT. Это "
"также простой способ минимальной реализации этого вызова — в любом случае "
"возвращать CAM_UA_ABORT."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:663
msgid ""
"The hard way is to implement this request honestly.  First check that abort "
"applies to a SCSI transaction:"
msgstr ""
"Трудный путь — честно реализовать этот запрос. Сначала проверьте, что "
"прерывание применяется к SCSI-транзакции:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:668
#, no-wrap
msgid ""
"    struct ccb *abort_ccb;\n"
"    abort_ccb = ccb->cab.abort_ccb;\n"
msgstr ""
"    struct ccb *abort_ccb;\n"
"    abort_ccb = ccb->cab.abort_ccb;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:674
#, no-wrap
msgid ""
"    if (abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {\n"
"        ccb->ccb_h.status = CAM_UA_ABORT;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"
msgstr ""
"    if (abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {\n"
"        ccb->ccb_h.status = CAM_UA_ABORT;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:678
msgid ""
"Then it is necessary to find this CCB in our queue.  This can be done by "
"walking the list of all our hardware control blocks in search for one "
"associated with this CCB:"
msgstr ""
"Затем необходимо найти этот CCB в нашей очереди. Это можно сделать, пройдясь "
"по списку всех наших блоков управления оборудованием в поисках связанного с "
"этим CCB:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:682
#, no-wrap
msgid "    struct xxx_hcb *hcb, *h;\n"
msgstr "    struct xxx_hcb *hcb, *h;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:684
#, no-wrap
msgid "    hcb = NULL;\n"
msgstr "    hcb = NULL;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:695
#, no-wrap
msgid ""
"    /* We assume that softc->first_hcb is the head of the list of all\n"
"     * HCBs associated with this bus, including those enqueued for\n"
"     * processing, being processed by hardware and disconnected ones.\n"
"     */\n"
"    for (h = softc->first_hcb; h != NULL; h = h->next) {\n"
"        if (h->ccb == abort_ccb) {\n"
"            hcb = h;\n"
"            break;\n"
"        }\n"
"    }\n"
msgstr ""
"    /* We assume that softc->first_hcb is the head of the list of all\n"
"     * HCBs associated with this bus, including those enqueued for\n"
"     * processing, being processed by hardware and disconnected ones.\n"
"     */\n"
"    for (h = softc->first_hcb; h != NULL; h = h->next) {\n"
"        if (h->ccb == abort_ccb) {\n"
"            hcb = h;\n"
"            break;\n"
"        }\n"
"    }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:702
#, no-wrap
msgid ""
"    if (hcb == NULL) {\n"
"        /* no such CCB in our queue */\n"
"        ccb->ccb_h.status = CAM_PATH_INVALID;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"
msgstr ""
"    if (hcb == NULL) {\n"
"        /* no such CCB in our queue */\n"
"        ccb->ccb_h.status = CAM_PATH_INVALID;\n"
"        xpt_done(ccb);\n"
"        return;\n"
"    }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:704
#, no-wrap
msgid "    hcb=found_hcb;\n"
msgstr "    hcb=found_hcb;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:709
msgid ""
"Now we look at the current processing status of the HCB.  It may be either "
"sitting in the queue waiting to be sent to the SCSI bus, being transferred "
"right now, or disconnected and waiting for the result of the command, or "
"actually completed by hardware but not yet marked as done by software.  To "
"make sure that we do not get in any races with hardware we mark the HCB as "
"being aborted, so that if this HCB is about to be sent to the SCSI bus the "
"SCSI controller will see this flag and skip it."
msgstr ""
"Теперь мы рассмотрим текущее состояние обработки HCB. Он может находиться в "
"очереди, ожидая отправки на шину SCSI, передаваться в данный момент, быть "
"отключенным и ожидать результата команды, или фактически завершённым с точки "
"зрения аппаратуры, но ещё не отмеченным программным обеспечением, как "
"выполненный. Чтобы избежать состояний гонки с аппаратурой, мы помечаем HCB "
"как прерванный, так что если этот HCB вот-вот будет отправлен на шину SCSI, "
"контроллер SCSI увидит этот флаг и пропустит его."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:713
#, no-wrap
msgid "    int hstatus;\n"
msgstr "    int hstatus;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:718
#, no-wrap
msgid ""
"    /* shown as a function, in case special action is needed to make\n"
"     * this flag visible to hardware\n"
"     */\n"
"    set_hcb_flags(hcb, HCB_BEING_ABORTED);\n"
msgstr ""
"    /* shown as a function, in case special action is needed to make\n"
"     * this flag visible to hardware\n"
"     */\n"
"    set_hcb_flags(hcb, HCB_BEING_ABORTED);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:720
#, no-wrap
msgid "    abort_again:\n"
msgstr "    abort_again:\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:730
#, no-wrap
msgid ""
"    hstatus = get_hcb_status(hcb);\n"
"    switch (hstatus) {\n"
"    case HCB_SITTING_IN_QUEUE:\n"
"        remove_hcb_from_hardware_queue(hcb);\n"
"        /* FALLTHROUGH */\n"
"    case HCB_COMPLETED:\n"
"        /* this is an easy case */\n"
"        free_hcb_and_ccb_done(hcb, abort_ccb, CAM_REQ_ABORTED);\n"
"        break;\n"
msgstr ""
"    hstatus = get_hcb_status(hcb);\n"
"    switch (hstatus) {\n"
"    case HCB_SITTING_IN_QUEUE:\n"
"        remove_hcb_from_hardware_queue(hcb);\n"
"        /* FALLTHROUGH */\n"
"    case HCB_COMPLETED:\n"
"        /* this is an easy case */\n"
"        free_hcb_and_ccb_done(hcb, abort_ccb, CAM_REQ_ABORTED);\n"
"        break;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:737
msgid ""
"If the CCB is being transferred right now we would like to signal to the "
"SCSI controller in some hardware-dependent way that we want to abort the "
"current transfer.  The SCSI controller would set the SCSI ATTENTION signal "
"and when the target responds to it send an ABORT message.  We also reset the "
"timeout to make sure that the target is not sleeping forever.  If the "
"command would not get aborted in some reasonable time like 10 seconds the "
"timeout routine would go ahead and reset the whole SCSI bus.  Since the "
"command will be aborted in some reasonable time we can just return the abort "
"request now as successfully completed, and mark the aborted CCB as aborted "
"(but not mark it as done yet)."
msgstr ""
"Если CCB передаётся в данный момент, мы хотели бы сигнализировать "
"контроллеру SCSI аппаратно-зависимым способом, что хотим прервать текущую "
"передачу. Контроллер SCSI установит сигнал SCSI ATTENTION, и когда целевое "
"устройство ответит на него, отправит сообщение ABORT. Мы также сбрасываем "
"таймаут, чтобы убедиться, что целевое устройство не засыпает навсегда. Если "
"команда не будет прервана в разумное время, например, за 10 секунд, "
"процедура таймаута продолжит работу и сбросит всю шину SCSI. Поскольку "
"команда будет прервана в разумные сроки, мы можем просто вернуть запрос на "
"прерывание как успешно выполненный и пометить прерванный CCB как прерванный ("
"но пока не помечать его как завершённый)."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:753
#, no-wrap
msgid ""
"    case HCB_BEING_TRANSFERRED:\n"
"        untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h.timeout_ch);\n"
"        abort_ccb->ccb_h.timeout_ch =\n"
"            timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);\n"
"        abort_ccb->ccb_h.status = CAM_REQ_ABORTED;\n"
"        /* ask the controller to abort that HCB, then generate\n"
"         * an interrupt and stop\n"
"         */\n"
"        if (signal_hardware_to_abort_hcb_and_stop(hcb) < 0) {\n"
"            /* oops, we missed the race with hardware, this transaction\n"
"             * got off the bus before we aborted it, try again */\n"
"            goto abort_again;\n"
"        }\n"
msgstr ""
"    case HCB_BEING_TRANSFERRED:\n"
"        untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h.timeout_ch);\n"
"        abort_ccb->ccb_h.timeout_ch =\n"
"            timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);\n"
"        abort_ccb->ccb_h.status = CAM_REQ_ABORTED;\n"
"        /* ask the controller to abort that HCB, then generate\n"
"         * an interrupt and stop\n"
"         */\n"
"        if (signal_hardware_to_abort_hcb_and_stop(hcb) < 0) {\n"
"            /* oops, we missed the race with hardware, this transaction\n"
"             * got off the bus before we aborted it, try again */\n"
"            goto abort_again;\n"
"        }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:755
#, no-wrap
msgid "        break;\n"
msgstr "        break;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:759
msgid ""
"If the CCB is in the list of disconnected then set it up as an abort request "
"and re-queue it at the front of hardware queue.  Reset the timeout and "
"report the abort request to be completed."
msgstr ""
"Если CCB находится в списке отключенных, то настроить его как запрос "
"прерывания и повторно поставить в начало аппаратной очереди. Сбросить "
"таймаут и сообщить о завершении запроса прерывания."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:773
#, no-wrap
msgid ""
"    case HCB_DISCONNECTED:\n"
"        untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h.timeout_ch);\n"
"        abort_ccb->ccb_h.timeout_ch =\n"
"            timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);\n"
"        put_abort_message_into_hcb(hcb);\n"
"        put_hcb_at_the_front_of_hardware_queue(hcb);\n"
"        break;\n"
"    }\n"
"    ccb->ccb_h.status = CAM_REQ_CMP;\n"
"    xpt_done(ccb);\n"
"    return;\n"
msgstr ""
"    case HCB_DISCONNECTED:\n"
"        untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h.timeout_ch);\n"
"        abort_ccb->ccb_h.timeout_ch =\n"
"            timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);\n"
"        put_abort_message_into_hcb(hcb);\n"
"        put_hcb_at_the_front_of_hardware_queue(hcb);\n"
"        break;\n"
"    }\n"
"    ccb->ccb_h.status = CAM_REQ_CMP;\n"
"    xpt_done(ccb);\n"
"    return;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:778
msgid ""
"That is all for the ABORT request, although there is one more issue.  As the "
"ABORT message cleans all the ongoing transactions on a LUN we have to mark "
"all the other active transactions on this LUN as aborted.  That should be "
"done in the interrupt routine, after the transaction gets aborted."
msgstr ""
"Вот и все, что касается запроса ABORT, хотя есть ещё один момент. Поскольку "
"сообщение ABORT очищает все текущие транзакции на LUN, нам необходимо "
"пометить все остальные активные транзакции на этом LUN как прерванные. Это "
"должно быть выполнено в процедуре аппаратного прерывания после того, как "
"транзакция будет прервана."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:782
msgid ""
"Implementing the CCB abort as a function may be quite a good idea, this "
"function can be re-used if an I/O transaction times out.  The only "
"difference would be that the timed out transaction would return the status "
"CAM_CMD_TIMEOUT for the timed out request.  Then the case XPT_ABORT would be "
"small, like that:"
msgstr ""
"Реализация прерывания CCB в виде функции может быть довольно хорошей идеей, "
"эта функция может быть повторно использована, если транзакция ввода-вывода "
"превысит время ожидания. Единственное различие будет в том, что для "
"транзакции с истекшим временем ожидания будет возвращён статус "
"CAM_CMD_TIMEOUT. Тогда код в case XPT_ABORT будет небольшим, например:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:788
#, no-wrap
msgid ""
"    case XPT_ABORT:\n"
"        struct ccb *abort_ccb;\n"
"        abort_ccb = ccb->cab.abort_ccb;\n"
msgstr ""
"    case XPT_ABORT:\n"
"        struct ccb *abort_ccb;\n"
"        abort_ccb = ccb->cab.abort_ccb;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:801
#, no-wrap
msgid ""
"        if (abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {\n"
"            ccb->ccb_h.status = CAM_UA_ABORT;\n"
"            xpt_done(ccb);\n"
"            return;\n"
"        }\n"
"        if (xxx_abort_ccb(abort_ccb, CAM_REQ_ABORTED) < 0)\n"
"            /* no such CCB in our queue */\n"
"            ccb->ccb_h.status = CAM_PATH_INVALID;\n"
"        else\n"
"            ccb->ccb_h.status = CAM_REQ_CMP;\n"
"        xpt_done(ccb);\n"
"        return;\n"
msgstr ""
"        if (abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {\n"
"            ccb->ccb_h.status = CAM_UA_ABORT;\n"
"            xpt_done(ccb);\n"
"            return;\n"
"        }\n"
"        if (xxx_abort_ccb(abort_ccb, CAM_REQ_ABORTED) < 0)\n"
"            /* no such CCB in our queue */\n"
"            ccb->ccb_h.status = CAM_PATH_INVALID;\n"
"        else\n"
"            ccb->ccb_h.status = CAM_REQ_CMP;\n"
"        xpt_done(ccb);\n"
"        return;\n"

#. type: Title ===
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:803
#, no-wrap
msgid "_XPT_SET_TRAN_SETTINGS_ - explicitly set values of SCSI transfer settings"
msgstr ""
"_XPT_SET_TRAN_SETTINGS_ — явно установить значения настроек передачи SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:806
msgid ""
"The arguments are transferred in the instance \"struct ccb_trans_setting "
"cts\" of the union ccb:"
msgstr ""
"Аргументы передаются в экземпляре \"struct ccb_trans_setting cts\" "
"объединения ccb:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:808
msgid "_valid_ - a bitmask showing which settings should be updated:"
msgstr ""
"_valid_ - битовая маска, показывающая, какие настройки должны быть обновлены:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:809
msgid "_CCB_TRANS_SYNC_RATE_VALID_ - synchronous transfer rate"
msgstr "_CCB_TRANS_SYNC_RATE_VALID_ - скорость синхронной передачи"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:810
msgid "_CCB_TRANS_SYNC_OFFSET_VALID_ - synchronous offset"
msgstr "_CCB_TRANS_SYNC_OFFSET_VALID_ - синхронное смещение"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:811
msgid "_CCB_TRANS_BUS_WIDTH_VALID_ - bus width"
msgstr "_CCB_TRANS_BUS_WIDTH_VALID_ - ширина шины"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:812
msgid "_CCB_TRANS_DISC_VALID_ - set enable/disable disconnection"
msgstr "_CCB_TRANS_DISC_VALID_ - установить разрешение/запрет отключения"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:813
msgid "_CCB_TRANS_TQ_VALID_ - set enable/disable tagged queuing"
msgstr "_CCB_TRANS_TQ_VALID_ - установить разрешение/запрет очередей с тегами"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:815
msgid ""
"_flags_ - consists of two parts, binary arguments and identification of sub-"
"operations.  The binary arguments are:"
msgstr ""
"_flags_ - состоит из двух частей: бинарных аргументов и идентификации "
"подопераций. Бинарные аргументы:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:816
msgid "_CCB_TRANS_DISC_ENB_ - enable disconnection"
msgstr "_CCB_TRANS_DISC_ENB_ - разрешить отключение"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:817
msgid "_CCB_TRANS_TAG_ENB_ - enable tagged queuing"
msgstr "_CCB_TRANS_TAG_ENB_ - разрешить тегированную очередь"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:818
msgid "the sub-operations are:"
msgstr "подоперации:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:819
msgid "_CCB_TRANS_CURRENT_SETTINGS_ - change the current negotiations"
msgstr "_CCB_TRANS_CURRENT_SETTINGS_ - изменить текущие параметры согласования"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:820
msgid ""
"_CCB_TRANS_USER_SETTINGS_ - remember the desired user values sync_period, "
"sync_offset - self-explanatory, if sync_offset==0 then the asynchronous mode "
"is requested bus_width - bus width, in bits (not bytes)"
msgstr ""
"_CCB_TRANS_USER_SETTINGS_ - сохранять желаемые пользовательские значения "
"sync_period, sync_offset - самоочевидные параметры; если sync_offset==0, то "
"запрашивается асинхронный режим bus_width - ширина шины в битах (не в байтах)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:825
msgid ""
"Two sets of negotiated parameters are supported, the user settings and the "
"current settings.  The user settings are not really used much in the SIM "
"drivers, this is mostly just a piece of memory where the upper levels can "
"store (and later recall) its ideas about the parameters.  Setting the user "
"parameters does not cause re-negotiation of the transfer rates.  But when "
"the SCSI controller does a negotiation it must never set the values higher "
"than the user parameters, so it is essentially the top boundary."
msgstr ""
"Поддерживаются два набора согласованных параметров: пользовательские "
"настройки и текущие настройки. Пользовательские настройки не так часто "
"используются в драйверах SIM, это в основном просто область памяти, где "
"верхние уровни могут сохранять (и позже извлекать) свои представления о "
"параметрах. Установка пользовательских параметров не вызывает повторного "
"согласования скоростей передачи. Однако, когда SCSI-контроллер выполняет "
"согласование, он никогда не должен устанавливать значения выше "
"пользовательских параметров, так что они по сути являются верхней границей."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:830
msgid ""
"The current settings are, as the name says, current.  Changing them means "
"that the parameters must be re-negotiated on the next transfer.  Again, "
"these \"new current settings\" are not supposed to be forced on the device, "
"just they are used as the initial step of negotiations.  Also they must be "
"limited by actual capabilities of the SCSI controller: for example, if the "
"SCSI controller has 8-bit bus and the request asks to set 16-bit wide "
"transfers this parameter must be silently truncated to 8-bit transfers "
"before sending it to the device."
msgstr ""
"Текущие настройки, как следует из названия, являются текущими. Их изменение "
"означает, что параметры должны быть повторно согласованы при следующей "
"передаче. Опять же, эти «новые текущие настройки» не предназначены для "
"принудительного применения к устройству, они лишь используются в качестве "
"начального шага переговоров. Кроме того, они должны быть ограничены "
"реальными возможностями SCSI-контроллера: например, если SCSI-контроллер "
"имеет 8-битную шину, а запрос требует установки 16-битных передач, этот "
"параметр должен быть тихо усечён до 8-битных передач перед отправкой на "
"устройство."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:832
msgid ""
"One caveat is that the bus width and synchronous parameters are per target "
"while the disconnection and tag enabling parameters are per lun."
msgstr ""
"Один нюанс заключается в том, что ширина шины и синхронные параметры "
"относятся к цели, тогда как параметры отключения и включения тегов относятся "
"к логическому устройству LUN."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:834
msgid ""
"The recommended implementation is to keep 3 sets of negotiated (bus width "
"and synchronous transfer) parameters:"
msgstr ""
"Рекомендуемая реализация заключается в хранении 3 наборов согласованных "
"параметров (ширина шины и синхронная передача):"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:836
msgid "_user_ - the user set, as above"
msgstr "_user_ - пользовательский набор, как указано выше"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:837
msgid "_current_ - those actually in effect"
msgstr "_current_ - тот, который фактически действуют"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:838
msgid "_goal_ - those requested by setting of the \"current\" parameters"
msgstr ""
"_goal_ - тот набор, который запрошен для установки параметров в качестве "
"\"текущих\""

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:840
msgid "The code looks like:"
msgstr "Код выглядит следующим образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:846
#, no-wrap
msgid ""
"    struct ccb_trans_settings *cts;\n"
"    int targ, lun;\n"
"    int flags;\n"
msgstr ""
"    struct ccb_trans_settings *cts;\n"
"    int targ, lun;\n"
"    int flags;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:858
#, no-wrap
msgid ""
"    cts = &ccb->cts;\n"
"    targ = ccb_h->target_id;\n"
"    lun = ccb_h->target_lun;\n"
"    flags = cts->flags;\n"
"    if (flags & CCB_TRANS_USER_SETTINGS) {\n"
"        if (flags & CCB_TRANS_SYNC_RATE_VALID)\n"
"            softc->user_sync_period[targ] = cts->sync_period;\n"
"        if (flags & CCB_TRANS_SYNC_OFFSET_VALID)\n"
"            softc->user_sync_offset[targ] = cts->sync_offset;\n"
"        if (flags & CCB_TRANS_BUS_WIDTH_VALID)\n"
"            softc->user_bus_width[targ] = cts->bus_width;\n"
msgstr ""
"    cts = &ccb->cts;\n"
"    targ = ccb_h->target_id;\n"
"    lun = ccb_h->target_lun;\n"
"    flags = cts->flags;\n"
"    if (flags & CCB_TRANS_USER_SETTINGS) {\n"
"        if (flags & CCB_TRANS_SYNC_RATE_VALID)\n"
"            softc->user_sync_period[targ] = cts->sync_period;\n"
"        if (flags & CCB_TRANS_SYNC_OFFSET_VALID)\n"
"            softc->user_sync_offset[targ] = cts->sync_offset;\n"
"        if (flags & CCB_TRANS_BUS_WIDTH_VALID)\n"
"            softc->user_bus_width[targ] = cts->bus_width;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:877
#, no-wrap
msgid ""
"        if (flags & CCB_TRANS_DISC_VALID) {\n"
"            softc->user_tflags[targ][lun] &= ~CCB_TRANS_DISC_ENB;\n"
"            softc->user_tflags[targ][lun] |= flags & CCB_TRANS_DISC_ENB;\n"
"        }\n"
"        if (flags & CCB_TRANS_TQ_VALID) {\n"
"            softc->user_tflags[targ][lun] &= ~CCB_TRANS_TQ_ENB;\n"
"            softc->user_tflags[targ][lun] |= flags & CCB_TRANS_TQ_ENB;\n"
"        }\n"
"    }\n"
"    if (flags & CCB_TRANS_CURRENT_SETTINGS) {\n"
"        if (flags & CCB_TRANS_SYNC_RATE_VALID)\n"
"            softc->goal_sync_period[targ] =\n"
"                max(cts->sync_period, OUR_MIN_SUPPORTED_PERIOD);\n"
"        if (flags & CCB_TRANS_SYNC_OFFSET_VALID)\n"
"            softc->goal_sync_offset[targ] =\n"
"                min(cts->sync_offset, OUR_MAX_SUPPORTED_OFFSET);\n"
"        if (flags & CCB_TRANS_BUS_WIDTH_VALID)\n"
"            softc->goal_bus_width[targ] = min(cts->bus_width, OUR_BUS_WIDTH);\n"
msgstr ""
"        if (flags & CCB_TRANS_DISC_VALID) {\n"
"            softc->user_tflags[targ][lun] &= ~CCB_TRANS_DISC_ENB;\n"
"            softc->user_tflags[targ][lun] |= flags & CCB_TRANS_DISC_ENB;\n"
"        }\n"
"        if (flags & CCB_TRANS_TQ_VALID) {\n"
"            softc->user_tflags[targ][lun] &= ~CCB_TRANS_TQ_ENB;\n"
"            softc->user_tflags[targ][lun] |= flags & CCB_TRANS_TQ_ENB;\n"
"        }\n"
"    }\n"
"    if (flags & CCB_TRANS_CURRENT_SETTINGS) {\n"
"        if (flags & CCB_TRANS_SYNC_RATE_VALID)\n"
"            softc->goal_sync_period[targ] =\n"
"                max(cts->sync_period, OUR_MIN_SUPPORTED_PERIOD);\n"
"        if (flags & CCB_TRANS_SYNC_OFFSET_VALID)\n"
"            softc->goal_sync_offset[targ] =\n"
"                min(cts->sync_offset, OUR_MAX_SUPPORTED_OFFSET);\n"
"        if (flags & CCB_TRANS_BUS_WIDTH_VALID)\n"
"            softc->goal_bus_width[targ] = min(cts->bus_width, OUR_BUS_WIDTH);"
"\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:890
#, no-wrap
msgid ""
"        if (flags & CCB_TRANS_DISC_VALID) {\n"
"            softc->current_tflags[targ][lun] &= ~CCB_TRANS_DISC_ENB;\n"
"            softc->current_tflags[targ][lun] |= flags & CCB_TRANS_DISC_ENB;\n"
"        }\n"
"        if (flags & CCB_TRANS_TQ_VALID) {\n"
"            softc->current_tflags[targ][lun] &= ~CCB_TRANS_TQ_ENB;\n"
"            softc->current_tflags[targ][lun] |= flags & CCB_TRANS_TQ_ENB;\n"
"        }\n"
"    }\n"
"    ccb->ccb_h.status = CAM_REQ_CMP;\n"
"    xpt_done(ccb);\n"
"    return;\n"
msgstr ""
"        if (flags & CCB_TRANS_DISC_VALID) {\n"
"            softc->current_tflags[targ][lun] &= ~CCB_TRANS_DISC_ENB;\n"
"            softc->current_tflags[targ][lun] |= flags & CCB_TRANS_DISC_ENB;\n"
"        }\n"
"        if (flags & CCB_TRANS_TQ_VALID) {\n"
"            softc->current_tflags[targ][lun] &= ~CCB_TRANS_TQ_ENB;\n"
"            softc->current_tflags[targ][lun] |= flags & CCB_TRANS_TQ_ENB;\n"
"        }\n"
"    }\n"
"    ccb->ccb_h.status = CAM_REQ_CMP;\n"
"    xpt_done(ccb);\n"
"    return;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:894
msgid ""
"Then when the next I/O request will be processed it will check if it has to "
"re-negotiate, for example by calling the function target_negotiated(hcb).  "
"It can be implemented like this:"
msgstr ""
"Затем, когда следующий запрос ввода-вывода будет обработан, он проверит, "
"нужно ли повторное согласование, например, вызовом функции "
"target_negotiated(hcb). Это может быть реализовано следующим образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:902
#, no-wrap
msgid ""
"    int\n"
"    target_negotiated(struct xxx_hcb *hcb)\n"
"    {\n"
"        struct softc *softc = hcb->softc;\n"
"        int targ = hcb->targ;\n"
msgstr ""
"    int\n"
"    target_negotiated(struct xxx_hcb *hcb)\n"
"    {\n"
"        struct softc *softc = hcb->softc;\n"
"        int targ = hcb->targ;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:910
#, no-wrap
msgid ""
"        if (softc->current_sync_period[targ] != softc->goal_sync_period[targ]\n"
"        || softc->current_sync_offset[targ] != softc->goal_sync_offset[targ]\n"
"        || softc->current_bus_width[targ] != softc->goal_bus_width[targ])\n"
"            return 0; /* FALSE */\n"
"        else\n"
"            return 1; /* TRUE */\n"
"    }\n"
msgstr ""
"        if (softc->current_sync_period[targ] != softc->goal_sync_period[targ]"
"\n"
"        || softc->current_sync_offset[targ] != softc->goal_sync_offset[targ]"
"\n"
"        || softc->current_bus_width[targ] != softc->goal_bus_width[targ])\n"
"            return 0; /* FALSE */\n"
"        else\n"
"            return 1; /* TRUE */\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:914
msgid ""
"After the values are re-negotiated the resulting values must be assigned to "
"both current and goal parameters, so for future I/O transactions the current "
"and goal parameters would be the same and `target_negotiated()` would return "
"TRUE.  When the card is initialized (in `xxx_attach()`) the current "
"negotiation values must be initialized to narrow asynchronous mode, the goal "
"and current values must be initialized to the maximal values supported by "
"controller."
msgstr ""
"После пересогласования значений полученные значения должны быть присвоены "
"как текущим, так и целевым параметрам, чтобы для будущих операций ввода-"
"вывода текущие и целевые параметры совпадали, и функция `target_negotiated()`"
" возвращала TRUE. При инициализации карты (в `xxx_attach()`) текущие "
"параметры согласования должны быть инициализированы узким асинхронным "
"режимом, а целевые и текущие значения должны быть инициализированы "
"максимальными значениями, поддерживаемыми контроллером."

#. type: Title ===
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:915
#, no-wrap
msgid "_XPT_GET_TRAN_SETTINGS_ - get values of SCSI transfer settings"
msgstr "_XPT_GET_TRAN_SETTINGS_ — получить значения настроек передачи SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:920
msgid ""
"This operations is the reverse of XPT_SET_TRAN_SETTINGS.  Fill up the CCB "
"instance \"struct ccb_trans_setting cts\" with data as requested by the "
"flags CCB_TRANS_CURRENT_SETTINGS or CCB_TRANS_USER_SETTINGS (if both are set "
"then the existing drivers return the current settings).  Set all the bits in "
"the valid field."
msgstr ""
"Эта операция является обратной XPT_SET_TRAN_SETTINGS. Заполните экземпляр "
"CCB \"struct ccb_trans_setting cts\" данными, запрошенными флагами "
"CCB_TRANS_CURRENT_SETTINGS или CCB_TRANS_USER_SETTINGS (если установлены "
"оба, существующие драйверы возвращают текущие настройки). Установите все "
"биты в поле valid."

#. type: Title ===
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:921
#, no-wrap
msgid "_XPT_CALC_GEOMETRY_ - calculate logical (BIOS) geometry of the disk"
msgstr "_XPT_CALC_GEOMETRY_ — вычислить логическую (BIOS) геометрию диска"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:924
msgid ""
"The arguments are transferred in the instance \"struct ccb_calc_geometry "
"ccg\" of the union ccb:"
msgstr ""
"Аргументы передаются в экземпляре \"struct ccb_calc_geometry ccg\" "
"объединения ccb:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:926
msgid "_block_size_ - input, block (A.K.A sector) size in bytes"
msgstr "_block_size_ - вход, размер блока (также известный как сектор) в байтах"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:927
msgid "_volume_size_ - input, volume size in bytes"
msgstr "_volume_size_ - вход, размер тома в байтах"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:928
msgid "_cylinders_ - output, logical cylinders"
msgstr "_cylinders_ - выход, логические цилиндры"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:929
msgid "_heads_ - output, logical heads"
msgstr "_heads_ - выход, логические головки"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:930
msgid "_secs_per_track_ - output, logical sectors per track"
msgstr "_secs_per_track_ - выход, логических секторов на дорожку"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:933
msgid ""
"If the returned geometry differs much enough from what the SCSI controller "
"BIOS thinks and a disk on this SCSI controller is used as bootable the "
"system may not be able to boot.  The typical calculation example taken from "
"the aic7xxx driver is:"
msgstr ""
"Если возвращённая геометрия значительно отличается от той, которую "
"предполагает BIOS SCSI-контроллера, и диск на этом SCSI-контроллере "
"используется как загрузочный, система может не загрузиться. Типичный пример "
"расчёта, взятый из драйвера `aic7xxx`, выглядит следующим образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:940
#, no-wrap
msgid ""
"    struct    ccb_calc_geometry *ccg;\n"
"    u_int32_t size_mb;\n"
"    u_int32_t secs_per_cylinder;\n"
"    int   extended;\n"
msgstr ""
"    struct    ccb_calc_geometry *ccg;\n"
"    u_int32_t size_mb;\n"
"    u_int32_t secs_per_cylinder;\n"
"    int   extended;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:945
#, no-wrap
msgid ""
"    ccg = &ccb->ccg;\n"
"    size_mb = ccg->volume_size\n"
"        / ((1024L * 1024L) / ccg->block_size);\n"
"    extended = check_cards_EEPROM_for_extended_geometry(softc);\n"
msgstr ""
"    ccg = &ccb->ccg;\n"
"    size_mb = ccg->volume_size\n"
"        / ((1024L * 1024L) / ccg->block_size);\n"
"    extended = check_cards_EEPROM_for_extended_geometry(softc);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:958
#, no-wrap
msgid ""
"    if (size_mb > 1024 && extended) {\n"
"        ccg->heads = 255;\n"
"        ccg->secs_per_track = 63;\n"
"    } else {\n"
"        ccg->heads = 64;\n"
"        ccg->secs_per_track = 32;\n"
"    }\n"
"    secs_per_cylinder = ccg->heads * ccg->secs_per_track;\n"
"    ccg->cylinders = ccg->volume_size / secs_per_cylinder;\n"
"    ccb->ccb_h.status = CAM_REQ_CMP;\n"
"    xpt_done(ccb);\n"
"    return;\n"
msgstr ""
"    if (size_mb > 1024 && extended) {\n"
"        ccg->heads = 255;\n"
"        ccg->secs_per_track = 63;\n"
"    } else {\n"
"        ccg->heads = 64;\n"
"        ccg->secs_per_track = 32;\n"
"    }\n"
"    secs_per_cylinder = ccg->heads * ccg->secs_per_track;\n"
"    ccg->cylinders = ccg->volume_size / secs_per_cylinder;\n"
"    ccb->ccb_h.status = CAM_REQ_CMP;\n"
"    xpt_done(ccb);\n"
"    return;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:963
msgid ""
"This gives the general idea, the exact calculation depends on the quirks of "
"the particular BIOS.  If BIOS provides no way set the \"extended "
"translation\" flag in EEPROM this flag should normally be assumed equal to "
"1.  Other popular geometries are:"
msgstr ""
"Это даёт общее представление, точный расчет зависит от особенностей "
"конкретной BIOS. Если BIOS не предоставляет возможности установить флаг "
"\"расширенной трансляции\" в EEPROM, этот флаг обычно следует считать равным "
"1. Другие популярные геометрии:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:968
#, no-wrap
msgid ""
"    128 heads, 63 sectors - Symbios controllers\n"
"    16 heads, 63 sectors - old controllers\n"
msgstr ""
"    128 heads, 63 sectors - Symbios controllers\n"
"    16 heads, 63 sectors - old controllers\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:971
msgid ""
"Some system BIOSes and SCSI BIOSes fight with each other with variable "
"success, for example a combination of Symbios 875/895 SCSI and Phoenix BIOS "
"can give geometry 128/63 after power up and 255/63 after a hard reset or "
"soft reboot."
msgstr ""
"Некоторые системные BIOS и SCSI BIOS конфликтуют друг с другом с переменным "
"успехом. Например, комбинация Symbios 875/895 SCSI и Phoenix BIOS может "
"выдавать геометрию 128/63 после включения питания и 255/63 после жёсткого "
"сброса или мягкой перезагрузки."

#. type: Title ===
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:972
#, no-wrap
msgid "_XPT_PATH_INQ_ - path inquiry, in other words get the SIM driver and SCSI controller (also known as HBA - Host Bus Adapter) properties"
msgstr ""
"_XPT_PATH_INQ_ — запрос пути, другими словами, получение свойств драйвера "
"SIM и контроллера SCSI (также известного как HBA - Host Bus Adapter)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:975
msgid ""
"The properties are returned in the instance \"struct ccb_pathinq cpi\" of "
"the union ccb:"
msgstr ""
"Свойства возвращаются в экземпляре \"struct ccb_pathinq cpi\" объединения "
"ccb:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:977
msgid "version_num - the SIM driver version number, now all drivers use 1"
msgstr ""
"`version_num` - номер версии драйвера SIM, в настоящее время все драйверы "
"используют 1"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:978
msgid "hba_inquiry - bitmask of features supported by the controller:"
msgstr "hba_inquiry - битовая маска функций, поддерживаемых контроллером:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:979
msgid "PI_MDP_ABLE - supports MDP message (something from SCSI3?)"
msgstr "PI_MDP_ABLE - поддерживает сообщение MDP (что-то из SCSI3?)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:980
msgid "PI_WIDE_32 - supports 32 bit wide SCSI"
msgstr "PI_WIDE_32 — поддерживает 32-битную широкую SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:981
msgid "PI_WIDE_16 - supports 16 bit wide SCSI"
msgstr "PI_WIDE_16 — поддерживает 16-битную широкую SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:982
msgid "PI_SDTR_ABLE - can negotiate synchronous transfer rate"
msgstr "PI_SDTR_ABLE - может согласовать синхронную скорость передачи"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:983
msgid "PI_LINKED_CDB - supports linked commands"
msgstr "PI_LINKED_CDB - поддерживает связанные команды"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:984
msgid "PI_TAG_ABLE - supports tagged commands"
msgstr "PI_TAG_ABLE - поддерживает помеченные команды"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:985
msgid ""
"PI_SOFT_RST - supports soft reset alternative (hard reset and soft reset are "
"mutually exclusive within a SCSI bus)"
msgstr ""
"PI_SOFT_RST — поддерживает альтернативу мягкого сброса (жёсткий сброс и "
"мягкий сброс являются взаимоисключающими в пределах шины SCSI)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:986
msgid "target_sprt - flags for target mode support, 0 if unsupported"
msgstr "target_sprt - флаги поддержки целевого режима, 0 если не поддерживается"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:987
msgid "hba_misc - miscellaneous controller features:"
msgstr "hba_misc - различные функции контроллера:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:988
msgid "PIM_SCANHILO - bus scans from high ID to low ID"
msgstr "PIM_SCANHILO - сканирование шины от высокого ID к низкому ID"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:989
msgid "PIM_NOREMOVE - removable devices not included in scan"
msgstr "PIM_NOREMOVE - съемные устройства не включены в сканирование"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:990
msgid "PIM_NOINITIATOR - initiator role not supported"
msgstr "PIM_NOINITIATOR - роль инициатора не поддерживается"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:991
msgid "PIM_NOBUSRESET - user has disabled initial BUS RESET"
msgstr "PIM_NOBUSRESET - пользователь отключил начальный BUS RESET"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:992
msgid ""
"hba_eng_cnt - mysterious HBA engine count, something related to compression, "
"now is always set to 0"
msgstr ""
"hba_eng_cnt - загадочное количество движков HBA, что-то связанное со "
"сжатием, в настоящее время всегда устанавливается в 0"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:993
msgid "vuhba_flags - vendor-unique flags, unused now"
msgstr ""
"vuhba_flags - уникальные флаги производителя, в настоящее время не "
"используются"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:994
msgid ""
"max_target - maximal supported target ID (7 for 8-bit bus, 15 for 16-bit "
"bus, 127 for Fibre Channel)"
msgstr ""
"max_target - максимальный поддерживаемый идентификатор целевого устройства ("
"7 для 8-битной шины, 15 для 16-битной шины, 127 для Fibre Channel)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:995
msgid ""
"max_lun - maximal supported LUN ID (7 for older SCSI controllers, 63 for "
"newer ones)"
msgstr ""
"max_lun - максимально поддерживаемый идентификатор LUN (7 для старых SCSI-"
"контроллеров, 63 для новых)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:996
msgid "async_flags - bitmask of installed Async handler, unused now"
msgstr ""
"async_flags - битовая маска установленных обработчиков Async, в настоящее "
"время не используется"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:997
msgid "hpath_id - highest Path ID in the subsystem, unused now"
msgstr ""
"hpath_id - наивысший Path ID в подсистеме, в настоящее время не используется"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:998
msgid "unit_number - the controller unit number, cam_sim_unit(sim)"
msgstr "unit_number - номер контроллера, cam_sim_unit(sim)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:999
msgid "bus_id - the bus number, cam_sim_bus(sim)"
msgstr "bus_id - номер шины, cam_sim_bus(sim)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1000
msgid "initiator_id - the SCSI ID of the controller itself"
msgstr "initiator_id - SCSI ID самого контроллера"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1001
msgid ""
"base_transfer_speed - nominal transfer speed in KB/s for asynchronous narrow "
"transfers, equals to 3300 for SCSI"
msgstr ""
"base_transfer_speed - номинальная скорость передачи в КБ/с для асинхронных "
"узкополосных передач, равна 3300 для SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1002
msgid ""
"sim_vid - SIM driver's vendor id, a zero-terminated string of maximal length "
"SIM_IDLEN including the terminating zero"
msgstr ""
"sim_vid - идентификатор производителя драйвера SIM, строка с нулевым "
"окончанием максимальной длины SIM_IDLEN, включая завершающий ноль"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1003
msgid ""
"hba_vid - SCSI controller's vendor id, a zero-terminated string of maximal "
"length HBA_IDLEN including the terminating zero"
msgstr ""
"hba_vid - идентификатор производителя SCSI-контроллера, строка с нулевым "
"окончанием максимальной длины HBA_IDLEN, включая завершающий ноль"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1004
msgid ""
"dev_name - device driver name, a zero-terminated string of maximal length "
"DEV_IDLEN including the terminating zero, equal to cam_sim_name(sim)"
msgstr ""
"dev_name - имя драйвера устройства, строка с нулевым окончанием максимальной "
"длины DEV_IDLEN, включая завершающий ноль, эквивалентно cam_sim_name(sim)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1006
msgid ""
"The recommended way of setting the string fields is using strncpy, like:"
msgstr ""
"Рекомендуемый способ установки строковых полей — использование strncpy, "
"например:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1010
#, no-wrap
msgid "    strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);\n"
msgstr "    strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1013
msgid ""
"After setting the values set the status to CAM_REQ_CMP and mark the CCB as "
"done."
msgstr ""
"После установки значений установите статус в CAM_REQ_CMP и пометьте CCB как "
"завершённый."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1015
#, no-wrap
msgid "Polling xxx_poll"
msgstr "Опрос xxx_poll"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1029
msgid ""
"The poll function is used to simulate the interrupts when the interrupt "
"subsystem is not functioning (for example, when the system has crashed and "
"is creating the system dump).  The CAM subsystem sets the proper interrupt "
"level before calling the poll routine.  So all it needs to do is to call the "
"interrupt routine (or the other way around, the poll routine may be doing "
"the real action and the interrupt routine would just call the poll "
"routine).  Why bother about a separate function then? This has to do with "
"different calling conventions.  The `xxx_poll` routine gets the struct "
"cam_sim pointer as its argument while the PCI interrupt routine by common "
"convention gets pointer to the struct `xxx_softc` and the ISA interrupt "
"routine gets just the device unit number.  So the poll routine would "
"normally look as:"
msgstr ""
"Функция poll используется для имитации прерываний, когда подсистема "
"прерываний не функционирует (например, когда система аварийно завершила "
"работу и создаёт дамп памяти). Подсистема CAM устанавливает соответствующий "
"уровень прерывания перед вызовом процедуры poll. Таким образом, все, что ей "
"нужно сделать, — это вызвать процедуру прерывания (или наоборот, процедура "
"poll может выполнять реальные действия, а процедура прерывания просто "
"вызывает процедуру poll). Зачем тогда нужна отдельная функция? Это связано с "
"различными соглашениями о вызовах. Процедура `xxx_poll` получает указатель "
"на структуру cam_sim в качестве аргумента, в то время как процедура "
"прерывания PCI по общему соглашению получает указатель на структуру "
"`xxx_softc`, а процедура прерывания ISA получает только номер устройства. "
"Таким образом, процедура poll обычно выглядит следующим образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1037
#, no-wrap
msgid ""
"static void\n"
"xxx_poll(struct cam_sim *sim)\n"
"{\n"
"    xxx_intr((struct xxx_softc *)cam_sim_softc(sim)); /* for PCI device */\n"
"}\n"
msgstr ""
"static void\n"
"xxx_poll(struct cam_sim *sim)\n"
"{\n"
"    xxx_intr((struct xxx_softc *)cam_sim_softc(sim)); /* for PCI device */\n"
"}\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1040
msgid "or"
msgstr "или"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1048
#, no-wrap
msgid ""
"static void\n"
"xxx_poll(struct cam_sim *sim)\n"
"{\n"
"    xxx_intr(cam_sim_unit(sim)); /* for ISA device */\n"
"}\n"
msgstr ""
"static void\n"
"xxx_poll(struct cam_sim *sim)\n"
"{\n"
"    xxx_intr(cam_sim_unit(sim)); /* for ISA device */\n"
"}\n"

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1051
#, no-wrap
msgid "Asynchronous Events"
msgstr "Асинхронные события"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1054
msgid ""
"If an asynchronous event callback has been set up then the callback function "
"should be defined."
msgstr ""
"Если была настроена асинхронная callback-функция для события, то callback-"
"функция должна быть определена."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1059
#, no-wrap
msgid ""
"static void\n"
"ahc_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)\n"
msgstr ""
"static void\n"
"ahc_async(void *callback_arg, u_int32_t code, struct cam_path *path, void "
"*arg)\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1062
msgid "callback_arg - the value supplied when registering the callback"
msgstr "callback_arg - значение, переданное при регистрации callback"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1063
msgid "code - identifies the type of event"
msgstr "code - определяет тип события"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1064
msgid "path - identifies the devices to which the event applies"
msgstr "path - определяет устройства, к которым применяется событие"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1065
msgid "arg - event-specific argument"
msgstr "arg - аргумент, специфичный для события"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1067
msgid "Implementation for a single type of event, AC_LOST_DEVICE, looks like:"
msgstr ""
"Реализация для одного типа события, AC_LOST_DEVICE, выглядит следующим "
"образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1074
#, no-wrap
msgid ""
"    struct xxx_softc *softc;\n"
"    struct cam_sim *sim;\n"
"    int targ;\n"
"    struct ccb_trans_settings neg;\n"
msgstr ""
"    struct xxx_softc *softc;\n"
"    struct cam_sim *sim;\n"
"    int targ;\n"
"    struct ccb_trans_settings neg;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1093
#, no-wrap
msgid ""
"    sim = (struct cam_sim *)callback_arg;\n"
"    softc = (struct xxx_softc *)cam_sim_softc(sim);\n"
"    switch (code) {\n"
"    case AC_LOST_DEVICE:\n"
"        targ = xpt_path_target_id(path);\n"
"        if (targ <= OUR_MAX_SUPPORTED_TARGET) {\n"
"            clean_negotiations(softc, targ);\n"
"            /* send indication to CAM */\n"
"            neg.bus_width = 8;\n"
"            neg.sync_period = neg.sync_offset = 0;\n"
"            neg.valid = (CCB_TRANS_BUS_WIDTH_VALID\n"
"                | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);\n"
"            xpt_async(AC_TRANSFER_NEG, path, &neg);\n"
"        }\n"
"        break;\n"
"    default:\n"
"        break;\n"
"    }\n"
msgstr ""
"    sim = (struct cam_sim *)callback_arg;\n"
"    softc = (struct xxx_softc *)cam_sim_softc(sim);\n"
"    switch (code) {\n"
"    case AC_LOST_DEVICE:\n"
"        targ = xpt_path_target_id(path);\n"
"        if (targ <= OUR_MAX_SUPPORTED_TARGET) {\n"
"            clean_negotiations(softc, targ);\n"
"            /* send indication to CAM */\n"
"            neg.bus_width = 8;\n"
"            neg.sync_period = neg.sync_offset = 0;\n"
"            neg.valid = (CCB_TRANS_BUS_WIDTH_VALID\n"
"                | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);\n"
"            xpt_async(AC_TRANSFER_NEG, path, &neg);\n"
"        }\n"
"        break;\n"
"    default:\n"
"        break;\n"
"    }\n"

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1096
#, no-wrap
msgid "Interrupts"
msgstr "Прерывания"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1099
msgid ""
"The exact type of the interrupt routine depends on the type of the "
"peripheral bus (PCI, ISA and so on) to which the SCSI controller is "
"connected."
msgstr ""
"Точный тип процедуры прерывания зависит от типа периферийной шины (PCI, ISA "
"и так далее), к которой подключен SCSI-контроллер."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1106
msgid ""
"The interrupt routines of the SIM drivers run at the interrupt level "
"splcam.  So `splcam()` should be used in the driver to synchronize activity "
"between the interrupt routine and the rest of the driver (for a "
"multiprocessor-aware driver things get yet more interesting but we ignore "
"this case here).  The pseudo-code in this document happily ignores the "
"problems of synchronization.  The real code must not ignore them.  A simple-"
"minded approach is to set `splcam()` on the entry to the other routines and "
"reset it on return thus protecting them by one big critical section.  To "
"make sure that the interrupt level will be always restored a wrapper "
"function can be defined, like:"
msgstr ""
"Прерывания в драйверах SIM выполняются на уровне прерывания splcam. Поэтому "
"в драйвере следует использовать `splcam()` для синхронизации между "
"обработчиком прерывания и остальной частью драйвера (для драйверов, "
"учитывающих многопроцессорность, ситуация становится ещё сложнее, но здесь "
"мы этот случай не рассматриваем). Псевдокод в этом документе беззаботно "
"игнорирует проблемы синхронизации. Реальный код так делать не должен. "
"Простейший подход — установить `splcam()` при входе в другие функции и "
"сбросить при выходе, защищая их одной большой критической секцией. Чтобы "
"гарантировать восстановление уровня прерывания, можно определить обёрточную "
"функцию, например:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1117
#, no-wrap
msgid ""
"    static void\n"
"    xxx_action(struct cam_sim *sim, union ccb *ccb)\n"
"    {\n"
"        int s;\n"
"        s = splcam();\n"
"        xxx_action1(sim, ccb);\n"
"        splx(s);\n"
"    }\n"
msgstr ""
"    static void\n"
"    xxx_action(struct cam_sim *sim, union ccb *ccb)\n"
"    {\n"
"        int s;\n"
"        s = splcam();\n"
"        xxx_action1(sim, ccb);\n"
"        splx(s);\n"
"    }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1123
#, no-wrap
msgid ""
"    static void\n"
"    xxx_action1(struct cam_sim *sim, union ccb *ccb)\n"
"    {\n"
"        ... process the request ...\n"
"    }\n"
msgstr ""
"    static void\n"
"    xxx_action1(struct cam_sim *sim, union ccb *ccb)\n"
"    {\n"
"        ... process the request ...\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1127
msgid ""
"This approach is simple and robust but the problem with it is that "
"interrupts may get blocked for a relatively long time and this would "
"negatively affect the system's performance.  On the other hand the functions "
"of the `spl()` family have rather high overhead, so vast amount of tiny "
"critical sections may not be good either."
msgstr ""
"Этот подход прост и надежен, но проблема в том, что прерывания могут "
"блокироваться на относительно долгое время, что негативно скажется на "
"производительности системы. С другой стороны, функции семейства `spl()` "
"имеют довольно высокие накладные расходы, поэтому большое количество мелких "
"критических секций также может быть нежелательным."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1130
msgid ""
"The conditions handled by the interrupt routine and the details depend very "
"much on the hardware.  We consider the set of \"typical\" conditions."
msgstr ""
"Условия, обрабатываемые процедурой прерывания, и детали сильно зависят от "
"оборудования. Мы рассматриваем набор \"типичных\" условий."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1135
msgid ""
"First, we check if a SCSI reset was encountered on the bus (probably caused "
"by another SCSI controller on the same SCSI bus).  If so we drop all the "
"enqueued and disconnected requests, report the events and re-initialize our "
"SCSI controller.  It is important that during this initialization the "
"controller will not issue another reset or else two controllers on the same "
"SCSI bus could ping-pong resets forever.  The case of fatal controller error/"
"hang could be handled in the same place, but it will probably need also "
"sending RESET signal to the SCSI bus to reset the status of the connections "
"with the SCSI devices."
msgstr ""
"Сначала проверяем, было ли на шине событие SCSI сброса (вероятно, вызванное "
"другим SCSI-контроллером на той же SCSI-шине). Если это так, мы отменяем все "
"поставленные в очередь и отключенные запросы, сообщаем о событиях и повторно "
"инициализируем наш SCSI-контроллер. Важно, чтобы во время этой инициализации "
"контроллер не инициировал ещё один сброс, иначе два контроллера на одной "
"SCSI-шине могут бесконечно обмениваться сбросами. Случай фатальной ошибки/"
"зависания контроллера может быть обработан в том же месте, но, вероятно, "
"также потребуется отправка сигнала RESET на SCSI-шину для сброса состояния "
"соединений с SCSI-устройствами."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1141
#, no-wrap
msgid ""
"    int fatal=0;\n"
"    struct ccb_trans_settings neg;\n"
"    struct cam_path *path;\n"
msgstr ""
"    int fatal=0;\n"
"    struct ccb_trans_settings neg;\n"
"    struct cam_path *path;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1146
#, no-wrap
msgid ""
"    if (detected_scsi_reset(softc)\n"
"    || (fatal = detected_fatal_controller_error(softc))) {\n"
"        int targ, lun;\n"
"        struct xxx_hcb *h, *hh;\n"
msgstr ""
"    if (detected_scsi_reset(softc)\n"
"    || (fatal = detected_fatal_controller_error(softc))) {\n"
"        int targ, lun;\n"
"        struct xxx_hcb *h, *hh;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1152
#, no-wrap
msgid ""
"        /* drop all enqueued CCBs */\n"
"        for(h = softc->first_queued_hcb; h != NULL; h = hh) {\n"
"            hh = h->next;\n"
"            free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n"
"        }\n"
msgstr ""
"        /* drop all enqueued CCBs */\n"
"        for(h = softc->first_queued_hcb; h != NULL; h = hh) {\n"
"            hh = h->next;\n"
"            free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n"
"        }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1158
#, no-wrap
msgid ""
"        /* the clean values of negotiations to report */\n"
"        neg.bus_width = 8;\n"
"        neg.sync_period = neg.sync_offset = 0;\n"
"        neg.valid = (CCB_TRANS_BUS_WIDTH_VALID\n"
"            | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);\n"
msgstr ""
"        /* the clean values of negotiations to report */\n"
"        neg.bus_width = 8;\n"
"        neg.sync_period = neg.sync_offset = 0;\n"
"        neg.valid = (CCB_TRANS_BUS_WIDTH_VALID\n"
"            | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1162
#, no-wrap
msgid ""
"        /* drop all disconnected CCBs and clean negotiations  */\n"
"        for (targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {\n"
"            clean_negotiations(softc, targ);\n"
msgstr ""
"        /* drop all disconnected CCBs and clean negotiations  */\n"
"        for (targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {\n"
"            clean_negotiations(softc, targ);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1170
#, no-wrap
msgid ""
"            /* report the event if possible */\n"
"            if (xpt_create_path(&path, /*periph*/NULL,\n"
"                    cam_sim_path(sim), targ,\n"
"                    CAM_LUN_WILDCARD) == CAM_REQ_CMP) {\n"
"                xpt_async(AC_TRANSFER_NEG, path, &neg);\n"
"                xpt_free_path(path);\n"
"            }\n"
msgstr ""
"            /* report the event if possible */\n"
"            if (xpt_create_path(&path, /*periph*/NULL,\n"
"                    cam_sim_path(sim), targ,\n"
"                    CAM_LUN_WILDCARD) == CAM_REQ_CMP) {\n"
"                xpt_async(AC_TRANSFER_NEG, path, &neg);\n"
"                xpt_free_path(path);\n"
"            }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1180
#, no-wrap
msgid ""
"            for (lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)\n"
"                for (h = softc->first_discon_hcb[targ][lun]; h != NULL; h = hh) {\n"
"                    hh=h->next;\n"
"                    if (fatal)\n"
"                        free_hcb_and_ccb_done(h, h->ccb, CAM_UNREC_HBA_ERROR);\n"
"                    else\n"
"                        free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n"
"                }\n"
"        }\n"
msgstr ""
"            for (lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)\n"
"                for (h = softc->first_discon_hcb[targ][lun]; h != NULL; h = "
"hh) {\n"
"                    hh=h->next;\n"
"                    if (fatal)\n"
"                        free_hcb_and_ccb_done(h, h->ccb, "
"CAM_UNREC_HBA_ERROR);\n"
"                    else\n"
"                        free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);"
"\n"
"                }\n"
"        }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1183
#, no-wrap
msgid ""
"        /* report the event */\n"
"        xpt_async(AC_BUS_RESET, softc->wpath, NULL);\n"
msgstr ""
"        /* report the event */\n"
"        xpt_async(AC_BUS_RESET, softc->wpath, NULL);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1197
#, no-wrap
msgid ""
"        /* re-initialization may take a lot of time, in such case\n"
"         * its completion should be signaled by another interrupt or\n"
"         * checked on timeout - but for simplicity we assume here that\n"
"         * it is really fast\n"
"         */\n"
"        if (!fatal) {\n"
"            reinitialize_controller_without_scsi_reset(softc);\n"
"        } else {\n"
"            reinitialize_controller_with_scsi_reset(softc);\n"
"        }\n"
"        schedule_next_hcb(softc);\n"
"        return;\n"
"    }\n"
msgstr ""
"        /* re-initialization may take a lot of time, in such case\n"
"         * its completion should be signaled by another interrupt or\n"
"         * checked on timeout - but for simplicity we assume here that\n"
"         * it is really fast\n"
"         */\n"
"        if (!fatal) {\n"
"            reinitialize_controller_without_scsi_reset(softc);\n"
"        } else {\n"
"            reinitialize_controller_with_scsi_reset(softc);\n"
"        }\n"
"        schedule_next_hcb(softc);\n"
"        return;\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1202
msgid ""
"If interrupt is not caused by a controller-wide condition then probably "
"something has happened to the current hardware control block.  Depending on "
"the hardware there may be other non-HCB-related events, we just do not "
"consider them here.  Then we analyze what happened to this HCB:"
msgstr ""
"Если прерывание не вызвано условием, общим для всего контроллера, то, "
"вероятно, что-то произошло с текущим блоком управления аппаратным "
"обеспечением. В зависимости от оборудования могут быть и другие события, не "
"связанные с HCB, но мы их здесь не рассматриваем. Затем мы анализируем, что "
"произошло с этим HCB:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1210
#, no-wrap
msgid ""
"    struct xxx_hcb *hcb, *h, *hh;\n"
"    int hcb_status, scsi_status;\n"
"    int ccb_status;\n"
"    int targ;\n"
"    int lun_to_freeze;\n"
msgstr ""
"    struct xxx_hcb *hcb, *h, *hh;\n"
"    int hcb_status, scsi_status;\n"
"    int ccb_status;\n"
"    int targ;\n"
"    int lun_to_freeze;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1219
#, no-wrap
msgid ""
"    hcb = get_current_hcb(softc);\n"
"    if (hcb == NULL) {\n"
"        /* either stray interrupt or something went very wrong\n"
"         * or this is something hardware-dependent\n"
"         */\n"
"        handle as necessary;\n"
"        return;\n"
"    }\n"
msgstr ""
"    hcb = get_current_hcb(softc);\n"
"    if (hcb == NULL) {\n"
"        /* either stray interrupt or something went very wrong\n"
"         * or this is something hardware-dependent\n"
"         */\n"
"        handle as necessary;\n"
"        return;\n"
"    }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1222
#, no-wrap
msgid ""
"    targ = hcb->target;\n"
"    hcb_status = get_status_of_current_hcb(softc);\n"
msgstr ""
"    targ = hcb->target;\n"
"    hcb_status = get_status_of_current_hcb(softc);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1225
msgid ""
"First we check if the HCB has completed and if so we check the returned SCSI "
"status."
msgstr ""
"Сначала мы проверяем, завершился ли HCB, и если да, то проверяем "
"возвращённый статус SCSI."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1230
#, no-wrap
msgid ""
"    if (hcb_status == COMPLETED) {\n"
"        scsi_status = get_completion_status(hcb);\n"
msgstr ""
"    if (hcb_status == COMPLETED) {\n"
"        scsi_status = get_completion_status(hcb);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1233
msgid ""
"Then look if this status is related to the REQUEST SENSE command and if so "
"handle it in a simple way."
msgstr ""
"Затем проверьте, связан ли этот статус с командой REQUEST SENSE, и если да, "
"обработайте его простым способом."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1247
#, no-wrap
msgid ""
"        if (hcb->flags & DOING_AUTOSENSE) {\n"
"            if (scsi_status == GOOD) { /* autosense was successful */\n"
"                hcb->ccb->ccb_h.status |= CAM_AUTOSNS_VALID;\n"
"                free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_SCSI_STATUS_ERROR);\n"
"            } else {\n"
"        autosense_failed:\n"
"                free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_AUTOSENSE_FAIL);\n"
"            }\n"
"            schedule_next_hcb(softc);\n"
"            return;\n"
"        }\n"
msgstr ""
"        if (hcb->flags & DOING_AUTOSENSE) {\n"
"            if (scsi_status == GOOD) { /* autosense was successful */\n"
"                hcb->ccb->ccb_h.status |= CAM_AUTOSNS_VALID;\n"
"                free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_SCSI_STATUS_ERROR);"
"\n"
"            } else {\n"
"        autosense_failed:\n"
"                free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_AUTOSENSE_FAIL);\n"
"            }\n"
"            schedule_next_hcb(softc);\n"
"            return;\n"
"        }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1251
msgid ""
"Else the command itself has completed, pay more attention to details.  If "
"auto-sense is not disabled for this CCB and the command has failed with "
"sense data then run REQUEST SENSE command to receive that data."
msgstr ""
"Иначе сама команда завершена, уделяйте больше внимания деталям. Если "
"автоопределение не отключено для этого CCB и команда завершилась неудачно с "
"данными состояния, выполните команду REQUEST SENSE для получения этих данных."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1256
#, no-wrap
msgid ""
"        hcb->ccb->csio.scsi_status = scsi_status;\n"
"        calculate_residue(hcb);\n"
msgstr ""
"        hcb->ccb->csio.scsi_status = scsi_status;\n"
"        calculate_residue(hcb);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1273
#, no-wrap
msgid ""
"        if ((hcb->ccb->ccb_h.flags & CAM_DIS_AUTOSENSE)==0\n"
"        && (scsi_status == CHECK_CONDITION\n"
"                || scsi_status == COMMAND_TERMINATED)) {\n"
"            /* start auto-SENSE */\n"
"            hcb->flags |= DOING_AUTOSENSE;\n"
"            setup_autosense_command_in_hcb(hcb);\n"
"            restart_current_hcb(softc);\n"
"            return;\n"
"        }\n"
"        if (scsi_status == GOOD)\n"
"            free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_REQ_CMP);\n"
"        else\n"
"            free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_SCSI_STATUS_ERROR);\n"
"        schedule_next_hcb(softc);\n"
"        return;\n"
"    }\n"
msgstr ""
"        if ((hcb->ccb->ccb_h.flags & CAM_DIS_AUTOSENSE)==0\n"
"        && (scsi_status == CHECK_CONDITION\n"
"                || scsi_status == COMMAND_TERMINATED)) {\n"
"            /* start auto-SENSE */\n"
"            hcb->flags |= DOING_AUTOSENSE;\n"
"            setup_autosense_command_in_hcb(hcb);\n"
"            restart_current_hcb(softc);\n"
"            return;\n"
"        }\n"
"        if (scsi_status == GOOD)\n"
"            free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_REQ_CMP);\n"
"        else\n"
"            free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_SCSI_STATUS_ERROR);\n"
"        schedule_next_hcb(softc);\n"
"        return;\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1276
msgid ""
"One typical thing would be negotiation events: negotiation messages received "
"from a SCSI target (in answer to our negotiation attempt or by target's "
"initiative) or the target is unable to negotiate (rejects our negotiation "
"messages or does not answer them)."
msgstr ""
"Типичным примером могут быть события согласования: сообщения согласования, "
"полученные от цели SCSI (в ответ на нашу попытку согласования или по "
"инициативе цели), или если цель не может согласовать (отклоняет наши "
"сообщения согласования или не отвечает на них)."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1292
#, no-wrap
msgid ""
"    switch (hcb_status) {\n"
"    case TARGET_REJECTED_WIDE_NEG:\n"
"        /* revert to 8-bit bus */\n"
"        softc->current_bus_width[targ] = softc->goal_bus_width[targ] = 8;\n"
"        /* report the event */\n"
"        neg.bus_width = 8;\n"
"        neg.valid = CCB_TRANS_BUS_WIDTH_VALID;\n"
"        xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n"
"        continue_current_hcb(softc);\n"
"        return;\n"
"    case TARGET_ANSWERED_WIDE_NEG:\n"
"        {\n"
"            int wd;\n"
msgstr ""
"    switch (hcb_status) {\n"
"    case TARGET_REJECTED_WIDE_NEG:\n"
"        /* revert to 8-bit bus */\n"
"        softc->current_bus_width[targ] = softc->goal_bus_width[targ] = 8;\n"
"        /* report the event */\n"
"        neg.bus_width = 8;\n"
"        neg.valid = CCB_TRANS_BUS_WIDTH_VALID;\n"
"        xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n"
"        continue_current_hcb(softc);\n"
"        return;\n"
"    case TARGET_ANSWERED_WIDE_NEG:\n"
"        {\n"
"            int wd;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1298
#, no-wrap
msgid ""
"            wd = get_target_bus_width_request(softc);\n"
"            if (wd <= softc->goal_bus_width[targ]) {\n"
"                /* answer is acceptable */\n"
"                softc->current_bus_width[targ] =\n"
"                softc->goal_bus_width[targ] = neg.bus_width = wd;\n"
msgstr ""
"            wd = get_target_bus_width_request(softc);\n"
"            if (wd <= softc->goal_bus_width[targ]) {\n"
"                /* answer is acceptable */\n"
"                softc->current_bus_width[targ] =\n"
"                softc->goal_bus_width[targ] = neg.bus_width = wd;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1311
#, no-wrap
msgid ""
"                /* report the event */\n"
"                neg.valid = CCB_TRANS_BUS_WIDTH_VALID;\n"
"                xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n"
"            } else {\n"
"                prepare_reject_message(hcb);\n"
"            }\n"
"        }\n"
"        continue_current_hcb(softc);\n"
"        return;\n"
"    case TARGET_REQUESTED_WIDE_NEG:\n"
"        {\n"
"            int wd;\n"
msgstr ""
"                /* report the event */\n"
"                neg.valid = CCB_TRANS_BUS_WIDTH_VALID;\n"
"                xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n"
"            } else {\n"
"                prepare_reject_message(hcb);\n"
"            }\n"
"        }\n"
"        continue_current_hcb(softc);\n"
"        return;\n"
"    case TARGET_REQUESTED_WIDE_NEG:\n"
"        {\n"
"            int wd;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1315
#, no-wrap
msgid ""
"            wd = get_target_bus_width_request(softc);\n"
"            wd = min (wd, OUR_BUS_WIDTH);\n"
"            wd = min (wd, softc->user_bus_width[targ]);\n"
msgstr ""
"            wd = get_target_bus_width_request(softc);\n"
"            wd = min (wd, OUR_BUS_WIDTH);\n"
"            wd = min (wd, softc->user_bus_width[targ]);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1320
#, no-wrap
msgid ""
"            if (wd != softc->current_bus_width[targ]) {\n"
"                /* the bus width has changed */\n"
"                softc->current_bus_width[targ] =\n"
"                softc->goal_bus_width[targ] = neg.bus_width = wd;\n"
msgstr ""
"            if (wd != softc->current_bus_width[targ]) {\n"
"                /* the bus width has changed */\n"
"                softc->current_bus_width[targ] =\n"
"                softc->goal_bus_width[targ] = neg.bus_width = wd;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1330
#, no-wrap
msgid ""
"                /* report the event */\n"
"                neg.valid = CCB_TRANS_BUS_WIDTH_VALID;\n"
"                xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n"
"            }\n"
"            prepare_width_nego_rsponse(hcb, wd);\n"
"        }\n"
"        continue_current_hcb(softc);\n"
"        return;\n"
"    }\n"
msgstr ""
"                /* report the event */\n"
"                neg.valid = CCB_TRANS_BUS_WIDTH_VALID;\n"
"                xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n"
"            }\n"
"            prepare_width_nego_rsponse(hcb, wd);\n"
"        }\n"
"        continue_current_hcb(softc);\n"
"        return;\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1334
msgid ""
"Then we handle any errors that could have happened during auto-sense in the "
"same simple-minded way as before.  Otherwise we look closer at the details "
"again."
msgstr ""
"Затем мы обрабатываем любые ошибки, которые могли произойти во время "
"автоопределения, тем же простым способом, что и раньше. В противном случае "
"мы снова внимательно изучаем детали."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1339
#, no-wrap
msgid ""
"    if (hcb->flags & DOING_AUTOSENSE)\n"
"        goto autosense_failed;\n"
msgstr ""
"    if (hcb->flags & DOING_AUTOSENSE)\n"
"        goto autosense_failed;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1341
#, no-wrap
msgid "    switch (hcb_status) {\n"
msgstr "    switch (hcb_status) {\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1345
msgid ""
"The next event we consider is unexpected disconnect.  Which is considered "
"normal after an ABORT or BUS DEVICE RESET message and abnormal in other "
"cases."
msgstr ""
"Следующее событие, которое мы рассматриваем, — это неожиданное отключение. "
"Оно считается нормальным после сообщения ABORT или BUS DEVICE RESET и "
"аномальным в остальных случаях."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1361
#, no-wrap
msgid ""
"    case UNEXPECTED_DISCONNECT:\n"
"        if (requested_abort(hcb)) {\n"
"            /* abort affects all commands on that target+LUN, so\n"
"             * mark all disconnected HCBs on that target+LUN as aborted too\n"
"             */\n"
"            for (h = softc->first_discon_hcb[hcb->target][hcb->lun];\n"
"                    h != NULL; h = hh) {\n"
"                hh=h->next;\n"
"                free_hcb_and_ccb_done(h, h->ccb, CAM_REQ_ABORTED);\n"
"            }\n"
"            ccb_status = CAM_REQ_ABORTED;\n"
"        } else if (requested_bus_device_reset(hcb)) {\n"
"            int lun;\n"
msgstr ""
"    case UNEXPECTED_DISCONNECT:\n"
"        if (requested_abort(hcb)) {\n"
"            /* abort affects all commands on that target+LUN, so\n"
"             * mark all disconnected HCBs on that target+LUN as aborted too\n"
"             */\n"
"            for (h = softc->first_discon_hcb[hcb->target][hcb->lun];\n"
"                    h != NULL; h = hh) {\n"
"                hh=h->next;\n"
"                free_hcb_and_ccb_done(h, h->ccb, CAM_REQ_ABORTED);\n"
"            }\n"
"            ccb_status = CAM_REQ_ABORTED;\n"
"        } else if (requested_bus_device_reset(hcb)) {\n"
"            int lun;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1365
#, no-wrap
msgid ""
"            /* reset affects all commands on that target, so\n"
"             * mark all disconnected HCBs on that target+LUN as reset\n"
"             */\n"
msgstr ""
"            /* reset affects all commands on that target, so\n"
"             * mark all disconnected HCBs on that target+LUN as reset\n"
"             */\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1372
#, no-wrap
msgid ""
"            for (lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)\n"
"                for (h = softc->first_discon_hcb[hcb->target][lun];\n"
"                        h != NULL; h = hh) {\n"
"                    hh=h->next;\n"
"                    free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n"
"                }\n"
msgstr ""
"            for (lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)\n"
"                for (h = softc->first_discon_hcb[hcb->target][lun];\n"
"                        h != NULL; h = hh) {\n"
"                    hh=h->next;\n"
"                    free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n"
"                }\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1375
#, no-wrap
msgid ""
"            /* send event */\n"
"            xpt_async(AC_SENT_BDR, hcb->ccb->ccb_h.path_id, NULL);\n"
msgstr ""
"            /* send event */\n"
"            xpt_async(AC_SENT_BDR, hcb->ccb->ccb_h.path_id, NULL);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1386
#, no-wrap
msgid ""
"            /* this was the CAM_RESET_DEV request itself, it is completed */\n"
"            ccb_status = CAM_REQ_CMP;\n"
"        } else {\n"
"            calculate_residue(hcb);\n"
"            ccb_status = CAM_UNEXP_BUSFREE;\n"
"            /* request the further code to freeze the queue */\n"
"            hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n"
"            lun_to_freeze = hcb->lun;\n"
"        }\n"
"        break;\n"
msgstr ""
"            /* this was the CAM_RESET_DEV request itself, it is completed */"
"\n"
"            ccb_status = CAM_REQ_CMP;\n"
"        } else {\n"
"            calculate_residue(hcb);\n"
"            ccb_status = CAM_UNEXP_BUSFREE;\n"
"            /* request the further code to freeze the queue */\n"
"            hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n"
"            lun_to_freeze = hcb->lun;\n"
"        }\n"
"        break;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1389
msgid ""
"If the target refuses to accept tags we notify CAM about that and return "
"back all commands for this LUN:"
msgstr ""
"Если цель отказывается принимать теги, мы уведомляем CAM об этом и "
"возвращаем все команды для этого LUN:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1397
#, no-wrap
msgid ""
"    case TAGS_REJECTED:\n"
"        /* report the event */\n"
"        neg.flags = 0 & ~CCB_TRANS_TAG_ENB;\n"
"        neg.valid = CCB_TRANS_TQ_VALID;\n"
"        xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n"
msgstr ""
"    case TAGS_REJECTED:\n"
"        /* report the event */\n"
"        neg.flags = 0 & ~CCB_TRANS_TAG_ENB;\n"
"        neg.valid = CCB_TRANS_TQ_VALID;\n"
"        xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1403
#, no-wrap
msgid ""
"        ccb_status = CAM_MSG_REJECT_REC;\n"
"        /* request the further code to freeze the queue */\n"
"        hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n"
"        lun_to_freeze = hcb->lun;\n"
"        break;\n"
msgstr ""
"        ccb_status = CAM_MSG_REJECT_REC;\n"
"        /* request the further code to freeze the queue */\n"
"        hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n"
"        lun_to_freeze = hcb->lun;\n"
"        break;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1406
msgid ""
"Then we check a number of other conditions, with processing basically "
"limited to setting the CCB status:"
msgstr ""
"Затем мы проверяем ряд других условий, при этом обработка в основном "
"ограничивается установкой статуса CCB:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1430
#, no-wrap
msgid ""
"    case SELECTION_TIMEOUT:\n"
"        ccb_status = CAM_SEL_TIMEOUT;\n"
"        /* request the further code to freeze the queue */\n"
"        hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n"
"        lun_to_freeze = CAM_LUN_WILDCARD;\n"
"        break;\n"
"    case PARITY_ERROR:\n"
"        ccb_status = CAM_UNCOR_PARITY;\n"
"        break;\n"
"    case DATA_OVERRUN:\n"
"    case ODD_WIDE_TRANSFER:\n"
"        ccb_status = CAM_DATA_RUN_ERR;\n"
"        break;\n"
"    default:\n"
"        /* all other errors are handled in a generic way */\n"
"        ccb_status = CAM_REQ_CMP_ERR;\n"
"        /* request the further code to freeze the queue */\n"
"        hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n"
"        lun_to_freeze = CAM_LUN_WILDCARD;\n"
"        break;\n"
"    }\n"
msgstr ""
"    case SELECTION_TIMEOUT:\n"
"        ccb_status = CAM_SEL_TIMEOUT;\n"
"        /* request the further code to freeze the queue */\n"
"        hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n"
"        lun_to_freeze = CAM_LUN_WILDCARD;\n"
"        break;\n"
"    case PARITY_ERROR:\n"
"        ccb_status = CAM_UNCOR_PARITY;\n"
"        break;\n"
"    case DATA_OVERRUN:\n"
"    case ODD_WIDE_TRANSFER:\n"
"        ccb_status = CAM_DATA_RUN_ERR;\n"
"        break;\n"
"    default:\n"
"        /* all other errors are handled in a generic way */\n"
"        ccb_status = CAM_REQ_CMP_ERR;\n"
"        /* request the further code to freeze the queue */\n"
"        hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n"
"        lun_to_freeze = CAM_LUN_WILDCARD;\n"
"        break;\n"
"    }\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1433
msgid ""
"Then we check if the error was serious enough to freeze the input queue "
"until it gets proceeded and do so if it is:"
msgstr ""
"Затем мы проверяем, была ли ошибка достаточно серьёзной, чтобы заморозить "
"очередь ввода до её обработки, и если да, то делаем это:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1439
#, no-wrap
msgid ""
"    if (hcb->ccb->ccb_h.status & CAM_DEV_QFRZN) {\n"
"        /* freeze the queue */\n"
"        xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);\n"
msgstr ""
"    if (hcb->ccb->ccb_h.status & CAM_DEV_QFRZN) {\n"
"        /* freeze the queue */\n"
"        xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1441
#, no-wrap
msgid "        /* re-queue all commands for this target/LUN back to CAM */\n"
msgstr "        /* re-queue all commands for this target/LUN back to CAM */\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1444
#, no-wrap
msgid ""
"        for (h = softc->first_queued_hcb; h != NULL; h = hh) {\n"
"            hh = h->next;\n"
msgstr ""
"        for (h = softc->first_queued_hcb; h != NULL; h = hh) {\n"
"            hh = h->next;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1453
#, no-wrap
msgid ""
"            if (targ == h->targ\n"
"            && (lun_to_freeze == CAM_LUN_WILDCARD || lun_to_freeze == h->lun))\n"
"                free_hcb_and_ccb_done(h, h->ccb, CAM_REQUEUE_REQ);\n"
"        }\n"
"    }\n"
"    free_hcb_and_ccb_done(hcb, hcb->ccb, ccb_status);\n"
"    schedule_next_hcb(softc);\n"
"    return;\n"
msgstr ""
"            if (targ == h->targ\n"
"            && (lun_to_freeze == CAM_LUN_WILDCARD || lun_to_freeze == "
"h->lun))\n"
"                free_hcb_and_ccb_done(h, h->ccb, CAM_REQUEUE_REQ);\n"
"        }\n"
"    }\n"
"    free_hcb_and_ccb_done(hcb, hcb->ccb, ccb_status);\n"
"    schedule_next_hcb(softc);\n"
"    return;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1456
msgid ""
"This concludes the generic interrupt handling although specific controllers "
"may require some additions."
msgstr ""
"На этом общее описание обработки прерываний завершается, хотя для некоторых "
"контроллеров могут потребоваться дополнительные действия."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1458
#, no-wrap
msgid "Errors Summary"
msgstr "Сводка ошибок"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1464
msgid ""
"When executing an I/O request many things may go wrong.  The reason of error "
"can be reported in the CCB status with great detail.  Examples of use are "
"spread throughout this document.  For completeness here is the summary of "
"recommended responses for the typical error conditions:"
msgstr ""
"При выполнении запроса ввода-вывода может произойти множество ошибок. "
"Причина ошибки может быть указана в статусе CCB с большим количеством "
"деталей. Примеры использования разбросаны по всему документу. Для полноты "
"изложения приведём сводку рекомендуемых действий при типичных ошибках:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1467
msgid ""
"_CAM_RESRC_UNAVAIL_ - some resource is temporarily unavailable and the SIM "
"driver cannot generate an event when it will become available.  An example "
"of this resource would be some intra-controller hardware resource for which "
"the controller does not generate an interrupt when it becomes available."
msgstr ""
"_CAM_RESRC_UNAVAIL_ — некоторый ресурс временно недоступен, и драйвер SIM не "
"может сгенерировать событие, когда он станет доступен. Примером такого "
"ресурса может быть некоторый внутренний аппаратный ресурс контроллера, для "
"которого контроллер не генерирует прерывание при его доступности."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1468
msgid "_CAM_UNCOR_PARITY_ - unrecovered parity error occurred"
msgstr "_CAM_UNCOR_PARITY_ - произошла неисправимая ошибка чётности"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1469
msgid ""
"_CAM_DATA_RUN_ERR_ - data overrun or unexpected data phase (going in other "
"direction than specified in CAM_DIR_MASK) or odd transfer length for wide "
"transfer"
msgstr ""
"_CAM_DATA_RUN_ERR_ - переполнение данных или неожиданная фаза данных ("
"направление передачи не соответствует указанному в CAM_DIR_MASK) или "
"нечётная длина передачи для широкой передачи"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1470
msgid ""
"_CAM_SEL_TIMEOUT_ - selection timeout occurred (target does not respond)"
msgstr "_CAM_SEL_TIMEOUT_ - произошел таймаут выбора (цель не отвечает)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1471
msgid "_CAM_CMD_TIMEOUT_ - command timeout occurred (the timeout function ran)"
msgstr ""
"_CAM_CMD_TIMEOUT_ - произошло превышение времени ожидания команды (сработала "
"функция таймаута)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1472
msgid "_CAM_SCSI_STATUS_ERROR_ - the device returned error"
msgstr "_CAM_SCSI_STATUS_ERROR_ - устройство вернуло ошибку"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1473
msgid ""
"_CAM_AUTOSENSE_FAIL_ - the device returned error and the REQUEST SENSE "
"COMMAND failed"
msgstr ""
"_CAM_AUTOSENSE_FAIL_ - устройство вернуло ошибку и команда REQUEST SENSE "
"завершилась неудачно"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1474
msgid "_CAM_MSG_REJECT_REC_ - MESSAGE REJECT message was received"
msgstr "_CAM_MSG_REJECT_REC_ - получено сообщение MESSAGE REJECT"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1475
msgid "_CAM_SCSI_BUS_RESET_ - received SCSI bus reset"
msgstr "_CAM_SCSI_BUS_RESET_ - получен сброс шины SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1476
msgid ""
"_CAM_REQ_CMP_ERR_ - \"impossible\" SCSI phase occurred or something else as "
"weird or just a generic error if further detail is not available"
msgstr ""
"_CAM_REQ_CMP_ERR_ - произошла «невозможная» фаза SCSI или что-то столь же "
"странное, либо это просто общая ошибка, если дополнительная информация "
"недоступна"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1477
msgid "_CAM_UNEXP_BUSFREE_ - unexpected disconnect occurred"
msgstr "_CAM_UNEXP_BUSFREE_ - произошло неожиданное отключение"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1478
msgid "_CAM_BDR_SENT_ - BUS DEVICE RESET message was sent to the target"
msgstr ""
"_CAM_BDR_SENT_ - Сообщение BUS DEVICE RESET было отправлено целевому "
"устройству"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1479
msgid "_CAM_UNREC_HBA_ERROR_ - unrecoverable Host Bus Adapter Error"
msgstr "_CAM_UNREC_HBA_ERROR_ - невосстановимая ошибка адаптера шины хоста"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1480
msgid "_CAM_REQ_TOO_BIG_ - the request was too large for this controller"
msgstr "_CAM_REQ_TOO_BIG_ - запрос слишком велик для данного контроллера"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1484
msgid ""
"_CAM_REQUEUE_REQ_ - this request should be re-queued to preserve transaction "
"ordering.  This typically occurs when the SIM recognizes an error that "
"should freeze the queue and must place other queued requests for the target "
"at the sim level back into the XPT queue.  Typical cases of such errors are "
"selection timeouts, command timeouts and other like conditions.  In such "
"cases the troublesome command returns the status indicating the error, the "
"and the other commands which have not be sent to the bus yet get re-queued."
msgstr ""
"_CAM_REQUEUE_REQ_ - этот запрос должен быть повторно поставлен в очередь для "
"сохранения порядка транзакций. Обычно это происходит, когда SIM обнаруживает "
"ошибку, которая должна заморозить очередь, и необходимо поместить другие "
"запросы в очереди для цели на уровне SIM обратно в очередь XPT. Типичными "
"случаями таких ошибок являются тайм-ауты выбора, тайм-ауты команд и другие "
"подобные условия. В таких случаях проблемная команда возвращает статус, "
"указывающий на ошибку, а другие команды, которые ещё не были отправлены на "
"шину, повторно ставятся в очередь."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1485
msgid ""
"_CAM_LUN_INVALID_ - the LUN ID in the request is not supported by the SCSI "
"controller"
msgstr ""
"_CAM_LUN_INVALID_ - идентификатор LUN в запросе не поддерживается "
"контроллером SCSI"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1486
msgid ""
"_CAM_TID_INVALID_ - the target ID in the request is not supported by the "
"SCSI controller"
msgstr ""
"_CAM_TID_INVALID_ - идентификатор целевого устройства в запросе не "
"поддерживается контроллером SCSI"

#. type: Title ==
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1488
#, no-wrap
msgid "Timeout Handling"
msgstr "Обработка таймаутов"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1496
msgid ""
"When the timeout for an HCB expires that request should be aborted, just "
"like with an XPT_ABORT request.  The only difference is that the returned "
"status of aborted request should be CAM_CMD_TIMEOUT instead of "
"CAM_REQ_ABORTED (that is why implementation of the abort better be done as a "
"function).  But there is one more possible problem: what if the abort "
"request itself will get stuck? In this case the SCSI bus should be reset, "
"just like with an XPT_RESET_BUS request (and the idea about implementing it "
"as a function called from both places applies here too).  Also we should "
"reset the whole SCSI bus if a device reset request got stuck.  So after all "
"the timeout function would look like:"
msgstr ""
"Когда время ожидания для HCB истекает, этот запрос должен быть прерван, как "
"и в случае с запросом XPT_ABORT. Единственное отличие заключается в том, что "
"возвращаемый статус прерванного запроса должен быть CAM_CMD_TIMEOUT вместо "
"CAM_REQ_ABORTED (вот почему реализацию прерывания лучше сделать в виде "
"функции). Но есть ещё одна возможная проблема: что если сам запрос на "
"прерывание зависнет? В этом случае шина SCSI должна быть сброшена, как и при "
"запросе XPT_RESET_BUS (и идея о реализации этого в виде функции, вызываемой "
"из обоих мест, применима и здесь). Также мы должны сбросить всю шину SCSI, "
"если запрос на сброс устройства завис. В итоге функция обработки таймаута "
"будет выглядеть следующим образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1505
#, no-wrap
msgid ""
"static void\n"
"xxx_timeout(void *arg)\n"
"{\n"
"    struct xxx_hcb *hcb = (struct xxx_hcb *)arg;\n"
"    struct xxx_softc *softc;\n"
"    struct ccb_hdr *ccb_h;\n"
msgstr ""
"static void\n"
"xxx_timeout(void *arg)\n"
"{\n"
"    struct xxx_hcb *hcb = (struct xxx_hcb *)arg;\n"
"    struct xxx_softc *softc;\n"
"    struct ccb_hdr *ccb_h;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1508
#, no-wrap
msgid ""
"    softc = hcb->softc;\n"
"    ccb_h = &hcb->ccb->ccb_h;\n"
msgstr ""
"    softc = hcb->softc;\n"
"    ccb_h = &hcb->ccb->ccb_h;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1515
#, no-wrap
msgid ""
"    if (hcb->flags & HCB_BEING_ABORTED || ccb_h->func_code == XPT_RESET_DEV) {\n"
"        xxx_reset_bus(softc);\n"
"    } else {\n"
"        xxx_abort_ccb(hcb->ccb, CAM_CMD_TIMEOUT);\n"
"    }\n"
"}\n"
msgstr ""
"    if (hcb->flags & HCB_BEING_ABORTED || ccb_h->func_code == XPT_RESET_DEV) "
"{\n"
"        xxx_reset_bus(softc);\n"
"    } else {\n"
"        xxx_abort_ccb(hcb->ccb, CAM_CMD_TIMEOUT);\n"
"    }\n"
"}\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/scsi/_index.adoc:1520
msgid ""
"When we abort a request all the other disconnected requests to the same "
"target/LUN get aborted too.  So there appears a question, should we return "
"them with status CAM_REQ_ABORTED or CAM_CMD_TIMEOUT? The current drivers use "
"CAM_CMD_TIMEOUT.  This seems logical because if one request got timed out "
"then probably something really bad is happening to the device, so if they "
"would not be disturbed they would time out by themselves."
msgstr ""
"Когда мы прерываем запрос, все остальные отключенные запросы к тому же "
"целевому устройству/LUN также прерываются. Возникает вопрос: следует ли "
"возвращать их со статусом CAM_REQ_ABORTED или CAM_CMD_TIMEOUT? Текущие "
"драйверы используют CAM_CMD_TIMEOUT. Это кажется логичным, потому что если "
"один запрос превысил время ожидания, то, вероятно, с устройством происходит "
"что-то действительно плохое, и если их не трогать, они бы сами превысили "
"время ожидания."