Разработка драйвера HBA

В этой главе описываются, как разработать пользовательский драйвер HBA.

Если Вы никогда не разрабатывали драйвер устройства в ядре для OS X, несомненно, считают документы, перечисленные во Введении в Руководство по программированию Драйвера устройства HBA для приобретения знаний о Наборе I/O и как использовать XCode для создания драйвера устройства.

Создайте соответствие словаря для Вашего драйвера

Гарантировать, чтобы Ваши соответствия драйвера и загрузки для Вашего устройства, Вы отредактировали свой водительский информационный список свойств (Info.plist файл). Набор I/O использует информацию в этом файле для соответствия устройства драйверу, подходящему лучше всего для управления им. Поскольку аппаратные средства HBA представлены один или больше IOPCIDevice куски, пользовательский драйвер HBA должен включать следующую пару ключ/значение в Info.plist файл:

<key>IOProviderClass</key>
<string>IOPCIDevice</string>

При разработке драйвера HBA для выполнения в основанном на PowerPC компьютере Macintosh, можно использовать, Открывать Firmware, соответствующий для соответствия на некоторой комбинации Открыть свойств устройства Firmware name, compatible, device_type, или model. Чтобы сделать это, используйте IONameMatch ключ и предоставление надлежащее свойство или свойства в строке (или массив строк) как значение, как в этом примере:

<key>IONameMatch</key>
<string>pci1000,626</string>

При разработке драйвера HBA для выполнения в основанном на Intel компьютере Macintosh, используйте стандартный PCI, соответствующий (Откройте, Firmware, соответствующий, не доступен в основанных на Intel компьютерах Macintosh). PCI, соответствующий, основывается на значениях в упомянутых ниже регистрах пространства конфигурации PCI (обратите внимание на то, что некоторые регистры, такие как версия ID и тип заголовка, не доступны для соответствия):

Семья PCI определяет четыре соответствующих ключа, которые можно использовать для указания комбинаций значений, на которых можно соответствовать. Таблица ниже шоу эти ключи и их связанное поведение.

Ключ

Поведение при сравнении

IOPCIMatch

Соответствия против основного поставщика и устройства ID регистрируются или поставщик подсистемы и устройство регистры ID. Значения основных регистров проверяются сначала; если там не идет ни в какое сравнение, то значения регистров подсистемы проверяются.

IOPCIPrimaryMatch

Соответствия против только основного поставщика и устройства регистры ID.

IOPCISecondaryMatch

Соответствия против только поставщика подсистемы и устройства регистры ID.

IOPCIClassMatch

Соответствия против кодового регистра класса.

Для нескольких примеров соответствия PCI посмотрите раздел «PCI Matching» в записи Драйвера для Устройства PCI. Для получения информации о других ключах соответствия, такой как kIOPropertyPhysicalInterconnectLocationKey, см. документацию для IOStorageProtocolCharacteristics.h в ссылке платформы ядра.

После того, как Ваш драйвер является соответствующим к Вашему устройству и запущен, у Вас есть возможность добавить к списку свойств другие свойства, содержащие информацию о самом устройстве HBA или о его целевых устройствах. Эти свойства (как все свойства в Info.plist файл), сохранены в Реестре I/O во время водительского времени жизни. Это позволяет другим объектам Набора I/O получать информацию о возможностях Вашего устройства. IOSCSIParallelInterfaceController класс обеспечивает методы, которые Ваш драйвер может вызвать, чтобы добавить или удалить свойства (эти методы описаны в Наборе и Удаляют HBA и Свойства Целевого устройства (Необязательно)). Важно использовать только эти методы, чтобы добавить или удалить свойства, потому что они защищают Вас от проблем синхронизации, которые могут возникнуть, когда различные объекты пытаются внести изменения в Реестре I/O одновременно.

Реализуйте подкласс IOSCSIParallelInterfaceController

Семья SCSI Parallel IOSCSIParallelInterfaceController класс содержит все методы, необходимо разработать пользовательский драйвер HBA. Важно подчеркнуть, что семья SCSI Parallel обрабатывает очень много подробных данных низшего уровня для Вас, таких как создание цикла работы и различных источников событий, основной обработки прерываний, и, при необходимости, создания и уничтожения объектов целевого устройства.

По большей части Ваше задание состоит из разделения на подклассы IOSCSIParallelInterfaceController класс и реализация его чистых виртуальных методов, чтобы обработать I/O и сообщить информацию, определенную для Ваших аппаратных средств. IOSCSIParallelInterfaceController класс также содержит методы, которые можно реализовать для выполнения задач, таких как управление целевыми устройствами и обработка прерываний и методов, которые можно вызвать, чтобы получить информацию и установить различные свойства. Следующие разделы описывают требуемые и дополнительные задачи, которые драйверы HBA выполняют и IOSCSIParallelInterfaceController методы связались с ними.

После того, как Вы преуспели в том, чтобы разработать драйвер, связывающийся с Вашим устройством, убедиться считать Улучшающуюся Производительность для приобретения знаний о способах улучшить водительскую производительность в OS X.

Инициализируйте свой (требуемый) драйвер устройства HBA

Пользовательские драйверы HBA не реализуют Набор I/O init метод. Вместо этого IOSCSIParallelInterfaceController объект выполняет некоторую работу начальной настройки (такую как получение цикла работы и обновление свойств I/O Registry), и затем это вызывает InitializeController метод на Вашем подклассе. В Вашей реализации этого метода необходимо выполнить любую требуемую инициализацию аппаратного обеспечения, распределение ресурсов и аппаратный опрос.

Поскольку Вы разрабатываете реализацию InitializeController метод, знать, что Вы не должны выделять память в своем подклассе для содержания информации на цель или на команду. Например, некоторые устройства HBA отслеживают отображение между глобальным именем узла и целевым устройством или информацией о скоростях согласования. Вместо того, чтобы выделить память для сдержания такой информации Ваш InitializeController метод, необходимо использовать методы отчета для сообщения IOSCSIParallelInterfaceController суперкласс, в каком количестве пространства Вы нуждаетесь. Затем когда IOSCSIParallelInterfaceController объект создает целевое устройство и объекты задачи, это также выделит достаточно памяти для содержания информации, которую необходимо хранить. (Для получения дополнительной информации о методах отчета посмотрите, Сообщают Специфичную для устройства (Требуемую) информацию.)

Если существует информация, необходимо сохранить, который является определенным для самого устройства HBA, однако, можно выделить память для него в InitializeController метод. Ваш драйвер, возможно, также должен был бы выделить мелкую сумму памяти для использования для связи незадачи с целевыми устройствами. Например, некоторые драйверы HBA отправляют к целевым устройствам вспомогательные запросы или запросы согласования, которые не могут инкапсулироваться в объектах запроса I/O.

В Вашей реализации InitializeController метод необходимо также запросить аппаратные средства для получения информации, в которой Вы нуждаетесь, такие как самое высокое поддерживаемое устройство ID и инициатор ID. Вашему драйверу, возможно, понадобились бы другие данные также, но это потребуется, чтобы сообщать об инициаторе ID и самое высокое поддерживаемое устройство ID и число логической единицы (LUN) к его суперклассу (см., Сообщают Специфичную для устройства информацию (Требуемую) для методов, которые Вы используете для снабжения этими данными).

Сообщите специфичную для устройства (требуемую) информацию

После инициализации устройства HBA, IOSCSIParallelInterfaceController объект запрашивает некоторую информацию от Вашего драйвера. Для предоставления этой информации драйвер должен реализовать следующие методы:

  • ReportInitiatorIdentifier

    IOSCSIParallelInterfaceController вызовы объектов этот метод для получения идентификатора SCSI инициатора (устройство HBA). Инициатор ID считают зарезервированным и никакие целевые устройства, может быть создан с тем ID.

  • ReportHighestSupportedDeviceID

    В этом методе Ваш драйвер HBA должен возвратить самое высокое устройство ID, который это поддерживает. IOSCSIParallelInterfaceController возразите использует значение, которое Вы возвращаете для определения последнего ID для обработки, когда, например, оно сканирует для целевых устройств.

  • ReportMaximumTaskCount

    В этом методе возвратите максимальное количество выдающихся задач, которые может обработать Ваше устройство HBA. IOSCSIParallelInterfaceController возразите использует это значение и чтобы выделить надлежащее число объектов задачи и избежать отправлять новую задачу, когда Ваш драйвер уже обрабатывает максимальное количество задач.

  • ReportHBASpecificTaskDataSize

    Если Ваш драйвер HBA должен отслеживать некоторые данные для каждой задачи, это обрабатывает, это может сказать ее суперклассу выделять площадь для тех данных в каждом объекте задачи. Это уменьшает Ваш драйвер от ответственности создания и поддержания памяти для содержания данных на задачу, таких как рассеяние - собирают список.

  • ReportHBASpecificDeviceDataSize

    Если Ваш драйвер HBA должен отслеживать некоторые данные для каждого целевого устройства, присоединенного к нему, это может сказать его суперклассу выделять площадь для тех данных в каждом IOSCSIParallelInterfaceDevice объект. Ваш драйвер мог бы хотеть хранить данные, такие как скорости согласования, глобальное имя порта или целевой ID.

  • DoesHBAPerformDeviceManagement

    Много HBAs, обычно Волоконно-оптический канал и SAS HBAs, способны к обнаружению и управлению устройствами, присоединенными к ним. Другие HBAs, такие как универсальный параллельный SCSI HBAs, знают, сколько устройств они могут поддерживать, но не управляют теми устройствами всегда. Все драйверы HBA должны реализовать DoesHBAPerformDeviceManagement метод, чтобы утвердить, намереваются ли они управлять целевыми устройствами, присоединенными к ним.

    Если возвращается Ваш драйвер HBA true в этом методе это означает, что объекты целевого устройства будут созданы (и уничтожены), только Вашим драйвером HBA, не суперклассом. Ваш драйвер HBA должен тогда вызвать IOSCSIParallelInterfaceController методы, создающие и уничтожающие объекты целевого устройства (описанный в Создают, Инициализируют и Уничтожают Объекты Целевого устройства (Необязательно)).

    Если Ваш HBA не выполняет управление устройствами, необходимо возвратиться false в DoesHBAPerformDeviceManagement метод, и Вы не должны вызывать методы, описанные в, Создают, Инициализируют и Уничтожают Объекты Целевого устройства (Необязательно). Для этих HBAs, IOSCSIParallelInterfaceController берет на себя ответственность за обнаружение и зондирование подключенных устройств во время начальной загрузки. Суперкласс создает объекты целевого устройства и присоединяет их к пользовательскому объекту драйвера HBA в Реестре I/O.

  • ReportHBAHighestLogicalUnitNumber

    В этом методе Ваш драйвер должен возвратить самое высокое число логической единицы, которое может адресовать Ваше устройство HBA.

  • DoesHBASupportSCSIParallelFeature

    Суперкласс вызывает этот метод, чтобы узнать, поддерживает ли Ваше устройство HBA определенную функцию SCSI Parallel Interface (как определено в SPI 3 и SPI 4 спецификации). Ваша реализация этого метода должна исследовать указанную функцию и возврат true если Вы поддерживаете его или false если Вы не делаете.

Создайте, инициализируйте и уничтожьте объекты целевого устройства (Необязательно)

Драйвер для устройства HBA, управляющего целевыми устройствами, присоединенными к нему, должен создать и уничтожить объекты Набора I/O, представляющие их в штабеле драйвера массового хранения. (Если Ваш драйвер управляет целевыми устройствами, убедиться возвратиться true в Вашей реализации требуемого DoesHBAPerformDeviceManagement метод, описанный в, Сообщает Специфичную для устройства (Требуемую) информацию.), Если Ваш драйвер не управляет целевыми устройствами, можно пропустить остальную часть этого раздела и продолжить к следующему разделу, Набору и Удалить HBA и Свойства Целевого устройства (Необязательно).

Для создания объектов целевого устройства драйвер должен вызвать один из вариантов CreateTargetForID метод. Вы не можете переопределить CreateTargetForID методы, потому что IOSCSIParallelInterfaceController объект использует их для выполнения многих низкоуровневых задач, таких как обновление внутренних состояний и структур.

IOSCSIParallelInterfaceController класс позволяет пользовательскому драйверу HBA создавать объект целевого устройства путем передачи или устройства ID целевого устройства и словаря его свойств или просто устройства ID. В целом, Волоконно-оптический канал, устройства HBA должны предоставить словарь свойств, описывающих целевое устройство, но большинство других устройств HBA не делает. Таблица 2-1 перечисляет ключи свойства и оценивает тот Волоконно-оптический канал, который устройства HBA могут обеспечить в CreateTargetForID метод. Для получения дополнительной информации об этих и других ключах, используемых для описания характеристик физических протоколов обмена, см. документацию для IOStorageProtocolCharacteristics.h в ссылке платформы ядра.

  Ключи Table 2-1 Property и значения для объектов устройства Волоконно-оптического канала

Ключ Property

Требуемый

Значение

Ввести

kIOPropertyFibreChannelNodeWorldWideNameKey

Да

Уникальное 64-разрядное глобальное имя для узла устройства

OSData

kIOPropertyFibreChannelPortWorldWideNameKey

Нет

Уникальное 64-разрядное глобальное имя для порта

OSData

kIOPropertyFibreChannelAddressIdentifierKey

Нет

24-разрядный идентификатор адреса, как определено в Волоконно-оптическом канале FS (FCFS) спецификация

OSData

kIOPropertyFibreChannelALPAKey

Нет

8-разрядное значение Физического адреса Шины с арбитражем

OSData

Когда Вы вызываете CreateTargetForID метод, IOSCSIParallelInterfaceController объект создает новое IOSCSIParallelInterfaceDevice объект представлять устройство. Этот объект устройства выполняет Набор I/O init, attach, и start подпрограммы. В штабеле драйвера массового хранения, IOSCSIParallelInterfaceDevice объектные переходы между объектами в семье SCSI Parallel и объектами в семье Model архитектуры SCSI.

Поскольку специфичные для устройства данные хранятся в объекте целевого устройства, память для этих данных не выделяется, пока объект целевого устройства не создается. Если Ваш драйвер HBA должен получить доступ к той памяти для выполнения задач установки для целевого объекта, это создает, это должно реализовать InitializeTargetForID метод. Этот метод вызывают IOSCSIParallelInterfaceDevice объект в start метод (прежде чем объект будет зарегистрирован для соответствия), когда специфичная для целевого устройства память доступна.

Если Ваш драйвер вызывает CreateTargetForID метод для создания объектов целевого устройства это должно также вызвать DestroyTargetForID метод для уничтожения их. Как с CreateTargetForID метод, Вы не можете переопределить DestroyTargetForID метод; иначе Вы могли бы вмешаться в задачи IOSCSIParallelInterfaceDevice объект выполняет в его реализации метода. Когда Вы вызываете DestroyTargetForID метод, указанное IOSCSIParallelInterfaceDevice объект завершается.

Запустите свой (требуемый) драйвер HBA

Для подготовки устройства HBA для принятия запросов I/O и команд SCSI необходимо реализовать StartController метод. Суперкласс вызывает StartController метод в его собственном start метод, после того, как это получило специфичную для HBA информацию от Вашего драйвера и выделило пул объектов задачи параллели SCSI.

В Вашем StartController метод, Вы, возможно, должны были бы включить порты на своих аппаратных средствах, ясных незаконченных прерываниях, и выполнить другие задачи, помещающие Ваше устройство в состояние выполнения. Если Ваш HBA выполняет управление устройствами, Вы могли бы также отсканировать для целевых устройств в StartController метод. Если Вы делаете это, знают, что суперкласс содержит логический элемент команды в то время как в start метод. Вы могли бы найти, что это препятствует тому, чтобы Вы получили асинхронные, основанные на прерывании уведомления обнаружения устройств. При испытании этого можно создать отдельный поток, на котором можно вызвать CreateTargetForID.

Самая важная вещь помнить о StartController метод - то, что Ваш драйвер должен быть подготовлен получить и обработать запросы I/O и команды, как только завершается метод.

Набор и удаляет HBA и свойства целевого устройства (Необязательно)

Во время инициализации и стартовых фаз Вашего драйвера, Вы, возможно, должны были бы установить или удалить свойства I/O Registry, связанные с целевыми устройствами или с самим устройством HBA. Вместо использования IORegistryEntry методы, чтобы сделать это непосредственно, необходимо использовать методы IOSCSIParallelInterfaceController класс обеспечивает. Одно преимущество использования специфичных для семьи методов состоит в том, что они выполняют некоторое подтверждение правильности данных на свойствах, в которых Вы передаете. Более важное преимущество состоит в том, что эти методы защищают Вас от проблем сериализации, которые могут произойти, когда различные объекты пытаются управлять свойствами в Реестре I/O одновременно.

Оба SetTargetProperty и SetHBAProperty методы ожидают строку, содержащую ключевое имя свойства и OSObject- производный объект, содержащий значение. Некоторые допустимые целевые ключи свойства перечислены в Таблице 2-1; список допустимых ключей свойства HBA находится в SetHBAProperty. Для получения дополнительной информации о значениях, подходящих для этих свойств, посмотрите заголовочные файлы IOStorageProtocolCharacteristics.h и IOStorageDeviceCharacteristics.h.

(Требуемые) задачи параллели процесса

Основная задача пользовательского драйвера HBA состоит в том, чтобы получить задачи параллели SCSI и передать их целевым устройствам. Чтобы сделать этот Ваш подкласс HBA должен реализовать ProcessParallelTask метод.

В ProcessParallelTask метод, Ваш драйвер HBA может вызвать IOSCSIParallelInterfaceController методы доступа извлечь информацию из SCSIParallelTask объект, представляющий задачу. Некоторые из этих методов доступа перечислены здесь:

  • GetCommandDescriptorBlock

  • GetDataBuffer

  • GetHBADataPointer

  • GetSCSIParallelFeatureNegotiationCount

После того, как Вы исследовали информацию в команде и обработали его как требуется, необходимо отослать команду на шине. Некоторые устройства HBA требуют строгой синхронизации между отсылкой команд на шине и обработкой прерываний, сгенерированных от завершенных команд; другие не делают. IOSCSIParallelInterfaceController класс поддерживает оба типа устройства HBA путем обеспечения механизмов, которые драйвер HBA может использовать для обеспечения уровня синхронизации его аппаратные потребности. Для получения дополнительной информации о том, как синхронизировать эти события, посмотрите, Синхронизируют Аппаратный Доступ.

Необходимо возвратить допустимое значение ответа службы SCSI из реализации ProcessParallelTask метод. Следующее является списком ответов службы SCSI (определенный в заголовочном файле SCSITask.h в платформе Ядра), можно возвратиться:

  • kSCSIServiceResponse_Request_In_Process

    Несмотря на то, что это не один из стандартных ответов службы, определенных в спецификации Модели архитектуры SCSI, это - ответ, который необходимо возвратить, когда еще не завершается асинхронная команда.

  • kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE

  • kSCSIServiceResponse_TASK_COMPLETE

  • kSCSIServiceResponse_LINK_COMMAND_COMPLETE

  • kSCSIServiceResponse_FUNCTION_COMPLETE

  • kSCSIServiceResponse_FUNCTION_REJECTED

Чтобы изучить, как обработать тайм-ауты, посмотрите Тайм-ауты Дескриптора (Необязательно).

Выполните (требуемое) управление задачами SCSI

Клиенты Вашего драйвера HBA используют функции управления задачами SCSI (определенный в спецификации Модели 2 архитектуры SCSI) для запроса определенных действий. IOSCSIParallelInterfaceController класс определяет следующие чистые виртуальные методы, которые Ваш подкласс должен реализовать для выполнения этих действий:

  • AbortTaskRequest

  • AbortTaskSetRequest

  • ClearACARequest

  • ClearTaskSetRequest

  • LogicalUnitResetRequest

  • TargetResetRequest

В Вашей реализации этих методов можно завершить их или синхронно или асинхронно. Если Вы принимаете решение завершить их синхронно, Ваша реализация должна возвратить надлежащий ответ службы SCSI. Можно возвратить любой из ответов службы, перечисленных в конце Задач Параллели Дескриптора (Требуемых) кроме kSCSIServiceResponse_Request_In_Process.

Если Вы решаете завершить эти функции асинхронно, Ваша реализация должна возвратиться только kSCSIServiceResponse_Request_In_Process ответ службы и затем вызывает надлежащий метод завершения. IOSCSIParallelInterfaceController класс определяет следующие методы завершения, которые должен реализовать Ваш драйвер, если это обрабатывает функции управления задачами SCSI асинхронно:

  • CompleteAbortTask

  • CompleteAbortTaskSet

  • CompleteClearACA

  • CompleteClearTaskSet

  • CompleteLogicalUnitReset

  • CompleteTargetReset

Поскольку и завершение команды и управление тайм-аутом сериализируются на потоке цикла работы, необходимо сериализировать управление задачами, которое драйвер выполняет на цикле работы, также. Один способ сделать это должно использовать объект логического элемента команды, связанный с циклом работы для взятия блокировки цикла работы, прежде чем Вы отправите запрос управления задачами к целевому устройству (можно выполнить это использование IOCommandGate::runAction функция). Таким образом можно избежать получать завершение команды или управления задачами одновременно, Вы отправляете запрос управления задачами. IOSCSIParallelInterfaceController класс обеспечивает удобный метод доступа GetCommandGate для получения команды пропускают объект, связанный с циклом работы.

(Рекомендуемые) тайм-ауты дескриптора

Команды SCSI обычно имеют значение тайм-аута, связанное с ними. Ваш драйвер не устанавливает значение тайм-аута команды (это установлено объектом, отправившим Вам команду), но это может включить таймер путем вызова SetTimeoutForTask метод. (Если Вы выбираете, можно также использовать SetTimeoutForTask метод для переопределения значения тайм-аута обеспечил в задаче.)

Несмотря на то, что некоторые драйверы HBA, возможно, не должны делать что-либо, когда команда испытывает таймаут, много драйверов должны выполнить некоторую очистку и связаться с аппаратными средствами. Если Ваш драйвер должен обработать тайм-ауты команды специфичным для аппаратных средств способом, можно реализовать HandleTimeout метод.

Когда задача испытывает таймаут, семья SCSI Parallel вызывает HandleTimeout метод. IOSCSIParallelInterfaceController реализация по умолчанию класса этого метода просто завершает команду с состоянием задачи SCSI kSCSITaskStatus_TaskTimeoutOccurred и ответ службы SCSI kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE. Если это не удовлетворяет Ваши водительские потребности, можно реализовать HandleTimeout метод к, например, очищает специфичные для HBA структуры данных, связанные с командой, и прерывает команду. Если команда уже отсутствует на шине, Вам, вероятно, придется отправить AbortTaskRequest команда; в противном случае можно быть в состоянии просто удалить его из очереди команд, ожидающих, чтобы быть отправленными в целевое устройство.

Обработайте (требуемые) запросы на прерывание

Как описано в Роли Устройства HBA в Поездке Запроса I/O, завершение запроса I/O инициировало прерывание, которое должен обработать драйвер HBA. Когда IOSCSIParallelInterfaceController объект инстанцируют, он создает цикл работы и регистрирует в нем источник события прерывания фильтра (среди других источников событий). Источник события прерывания включает подпрограмму действия, работающую на потоке цикла работы для обработки прерываний. Когда прерывание происходит, подпрограмма действия вызывает Ваш водительский HBA HandleInterruptRequest метод, в то время как во вторичном контексте прерывания (на цикле работы распараллеливают с сохраненной блокировкой). Ваш драйвер должен реализовать HandleInterruptRequest метод для обслуживания прерывания.

Ваша реализация HandleInterruptRequest метод должен быть максимально эффективным и никогда не блокировать неопределенно. В частности это означает, что Вы не должны выделять память или создавать объекты в Вашем HandleInterruptRequest метод (или любые методы, которые это вызывает), потому что выделение может блокировать в течение неограниченных промежутков времени. Обязательно вызовите CompleteParallelTask метод, когда Ваш драйвер завершает обработку параллельной задачи.

Остановите и завершите свой (требуемый) драйвер HBA

В Вашей реализации этого требуемого метода необходимо прекратить принимать команды, но Вы не должны высвобождать средства, которые Вы, возможно, получили. Это вызвано тем, что Вы можете быть призваны, чтобы продолжить принимать команды (с вызовом к Вашему StartController метод) в любое время.

Когда IOSCSIParallelInterfaceController вызовы объектов Ваш TerminateController метод, однако, это означает, что будет уничтожен Ваш объект подкласса. Необходимо реализовать этот метод, чтобы закрыть все аппаратные службы и высвободить все средства, которые Вы получили.