Доступ к устройствам параллели SCSI

В версиях OS X до v10.2, если Вы хотели получить доступ к устройству Параллели SCSI, которое не было доступно с интерфейсами устройства семьи Model архитектуры SCSI, Вы использовали интерфейсы устройства семьи SCSI. Начиная с OS X v10.2, однако, Apple представил семью SCSI Parallel для поддержки контроллеров SCSI. Новая семья разработана, чтобы позволить семье Model архитектуры SCSI поддерживать устройства SCSI, присоединенные к тем контроллерам, что означает, что можно использовать интерфейсы устройства семьи Model архитектуры SCSI для доступа ко всем устройствам SCSI, не объявляющим тип периферийного устройства 00$, 05$, 07$ или 0$ E.

Поскольку сторонние разработчики выпускают новые драйверы контроллера SCSI, использующие семью SCSI Parallel и поскольку пользователи устанавливают эти новые драйверы, семья SCSI Parallel заменит семью SCSI. Во время перехода, однако, APIs обеих семей доступен. Это означает, что можно использовать API обеих семей, чтобы искать устройство и затем использовать API, успешно нашедший, что устройство связалось с ним. Если следующее является истиной, Вы, возможно, должны были бы использовать оба APIs в отдельном приложении:

Если эти операторы описывают Вашу ситуацию, можно использовать и APIs, чтобы найти и связаться с устройством. Таким образом, Ваше приложение будет в состоянии найти все устройства, которыми оно интересуется независимо от драйверов контроллера SCSI, которые установил пользователь. Что еще более важно Ваше приложение будет все еще работать, когда семья SCSI будет заменена, и все контроллеры SCSI поддерживаются семьей SCSI Parallel. (Отметьте, однако, что APIs осуждаемой семьи SCSI не будет работать в основанном на Intel Macintosh.)

Если, с другой стороны, совместимость с OS X v10.2.x или ранее не требуется, или Ваше приложение уже использует интерфейсы устройства семьи Model архитектуры SCSI для доступа к устройству, Вы не должны использовать семью SCSI API в Вашем приложении. Вместо этого посмотрите Устройства модели архитектуры SCSI Доступа для получения информации о том, как использовать интерфейсы устройства семьи Model архитектуры SCSI.

В этой главе описываются, как использовать осуждаемую семью SCSI API, чтобы найти и получить доступ к устройству Параллели SCSI, что Вы не можете получить доступ к использованию семьи Model архитектуры SCSI API. Для иллюстрирования этого это использует демонстрационный проект SCSIOldAndNew, использующий API обеих семей, чтобы найти и получить доступ к устройству Параллели SCSI. Поскольку интерфейсы устройства семьи Model архитектуры SCSI полностью покрыты Доступом к Устройствам модели архитектуры SCSI, эта глава внимание на поддержку прикладного уровня семьи SCSI устройств SCSI. Несмотря на то, что демонстрационный проект SCSIOldAndNew демонстрирует, как использовать APIs обеих семей, чтобы найти и получить доступ к устройству Параллели SCSI, эта глава не описывает использование проекта Модели архитектуры SCSI API. Если Вы незнакомы с семьей Model архитектуры SCSI, и Вы планируете использовать APIs обеих семей в Вашем приложении, несомненно, считают Устройства модели архитектуры SCSI Доступа в дополнение к чтению этой главы.

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

Поддержка семьи SCSI устройств параллели SCSI

SCSI (Интерфейс малых компьютерных систем), Параллельный Интерфейс является шиной данных параллели промышленного стандарта, обеспечивающей непротиворечивый метод соединяющихся компьютеров и периферийных устройств. Устройства Параллели SCSI используют технологию Параллели SCSI для передачи с компьютером.

На компьютерах, не имеющих новой Параллели SCSI поддерживаемыми семьей драйверами контроллера SCSI установленный, семья SCSI обеспечивает доступ прикладного уровня к устройствам Параллели SCSI с двумя интерфейсами устройства:

IOSCSIDeviceInterface определяется в IOSCSILib.h и IOCDBCommandInterface определяется в IOCDBLib.h, оба в платформе Набора I/O. Этот раздел предоставляет краткое описание производительности CDB и схему того, как получить доступ к устройству Параллели SCSI.

Производительность и распараллеливающий с командами CDB

Блок дескриптора команды определяется как структура до 16 байтов в длине, использующейся для передачи команды с клиента приложения на сервер устройства. Улучшить производительность, команды CDB очередей OS X, чтобы помочь заставить устройство Параллели SCSI напряженно трудиться. При использовании асинхронных команд можно создать больше чем один экземпляр команды CDB и выполнить последующие команды, как только Вы поставили первую команду в очередь (путем выполнения его). Фактически, для лучшей производительности, необходимо попытаться использовать по крайней мере две команды, когда это возможно.

Когда команда завершается, можно снова использовать экземпляр команды CDB для выполнения другой команды. В многократном использовании команд помните следующее:

  • Никакие данные в команде CDB не изменяются путем выполнения команды, так, чтобы при многократном использовании команды Вы сбросили любые значения, которые должны отличаться для следующей команды.

  • Когда Вы используете setAndExecuteCommand функционируйте, чтобы установить и выполнить команду CDB, она устанавливает каждую опцию CDB, таким образом, Вы не должны волноваться об очистке предыдущих данных.

  • Как только Вы выполнили команду, не безопасно изменить свое значение, пока не вызывают ее подпрограмму завершения.

Необходимо создать и связаться с командой CDB только от кода в единственном потоке. Однако у Вас могут быть многократные потоки, которые каждый создает, выполняет, и повторное использование многократные команды. Команды CDB выполняются в отправленном порядке, но если Вы используете многократные потоки для выполнения многократных команд, код ответственен за обеспечение любого требуемого упорядочивания команд.

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

Интерфейс устройства SCSI

Семья SCSI Набора I/O обеспечивает интерфейс устройства SCSI, который приложения могут использовать для доступа к устройствам Параллели SCSI на OS X. Для полного определения интерфейса устройства SCSI посмотрите IOSCSILib.h.

Вы, возможно, должны получить доступ к устройствам Параллели SCSI по ряду причин, таким как:

  • Ваше служебное приложение должно перечислить все в настоящее время доступные устройства Параллели SCSI, запросить их, и возможно выполнить операции на них (можно найти устройства и получить кэшируемую информацию об устройстве из Реестра I/O, не создавая интерфейс устройства, но запрашивать или управлять устройством, Вам действительно нужен интерфейс устройства).

  • Ваше приложение должно управлять сканером SCSI.

Рисунок 1-1 показывает приложение, использующее интерфейс устройства для действия как драйвер для сканера Параллели SCSI. Приложение вызывает функции интерфейса устройства, связывающегося с куском устройства SCSI (на основе класса IOSCSIDevice) в ядре.

Рисунок 1-1  приложение, связывающееся с устройством SCSI через интерфейс устройства
An application communicating with a SCSI device through a device interface

К приложению интерфейс устройства является просто сменным интерфейсом, обеспечивающим доступ к устройству через функции такой как open, close, и reset. К куску устройства интерфейс устройства похож просто на другой драйвер, с которым может связаться кусок.

Работа с интерфейсами устройства семьи SCSI

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

  1. Получите ведущий порт Набора I/O, позволяющий приложениям связываться с Набором I/O.

  2. Используйте семью, соответствующую информацию и функции Набора I/O для нахождения устройства.

  3. Получите надлежащий интерфейс устройства для устройства.

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

  5. Закройте устройство и выпустите любые интерфейсы устройства, которые Вы получили.

Этот раздел ведет Вас через эти шаги, с помощью кода из демонстрационного проекта SCSIOldAndNew проиллюстрировать реализацию в качестве примера. В интересах краткости этот раздел не воспроизводит демонстрационный проект полностью. Вместо этого этот раздел обеспечивает частичные списки из проекта проиллюстрировать методы, которые Вы используете для доступа к устройству Параллели SCSI с помощью API осуждаемой семьи SCSI. Для выполнения демонстрационного проекта с собственными устройствами загрузите проект с Примера кода> Аппаратные средства и Драйверы> SCSI и создайте его на компьютере.

Основной принцип проекта демонстрационного проекта SCSIOldAndNew является строгим разделением функций семьи SCSI от тех из семьи Model архитектуры SCSI. Несмотря на то, что Вы могли бы принять решение структурировать свой код по-другому, разделение проекта SCSIOldAndNew является полезной функцией для эмуляции. Если Ваши требования совместимости изменятся в будущем, например, то будет намного проще удалить код, использующий осуждаемую семью SCSI API, если это разделено от остальной части Вашего приложения. Демонстрационный проект делит свой код на три модуля:

Демонстрационный проект SCSIOldAndNew является приложением Углерода, определяющим обработчик события уровня приложения для обработки выбора устройства пользователя. Поскольку это - вопросы проектирования, не влияющие на базовую цель приложения, этот раздел заминает Связанные с углеродом подробные данные реализации, фокусируя вместо этого на использовании семьи I/O Kit и SCSI APIs, чтобы найти и получить доступ к устройству.

Получение Ведущего порта Набора I/O

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

Основной модуль проекта SCSIOldAndNew, вызванного SCSIOldAndNew.c, дает пользователю список типов периферийного устройства, из которых можно выбрать. Обработчик событий приложения, функция вызвана DoAppCommandProcess, передает выбор пользователя функции TestDevices. TestDevices (показанный в Перечислении 1-1), получает ведущий порт Набора I/O и затем пытается найти устройство с переданным - в типе периферийного устройства, сначала с семьей Model архитектуры SCSI API и затем с семьей SCSI API.

Перечисление 1-1  , Настраивающее поиск устройства для обеих семей

void TestDevices(int peripheralDeviceType)
{
    kern_return_t   kr;
    mach_port_t     masterPort = NULL;
    io_iterator_t   iterator = NULL;
 
    kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
    if (kr != kIOReturnSuccess) {
        fprintf(stderr, "Couldn't retrieve the master I/O Kit port.
                    (0x%08x)\n", kr);
        return;
    }
 
    // First try to find the device using the SCSI Architecture
    // Model family API:
    if (FindDevicesUsingSTUC(peripheralDeviceType, masterPort, &iterator)) {
        TestDevicesUsingSTUC(peripheralDeviceType, iterator);
    }
    else // Now try the SCSI family API:
        if (FindDevicesUsingOldMethod(peripheralDeviceType, masterPort,
                    &iterator)) {
        TestDevicesUsingOldMethod(iterator);
    }
    else {
        fprintf(stderr, "No devices with peripheral device type %02Xh
                    found.\n", peripheralDeviceType);
    }
 
    if (iterator) {
        IOObjectRelease(iterator);
    }
 
    if (masterPort) {
        mach_port_deallocate(mach_task_self(), masterPort);
    }
}

Несмотря на то, что Вы могли бы принять решение разработать свое приложение по-другому, необходимо рассмотреть тиражирование базовой структуры этой функции где-нибудь в коде. Если Вы требуете совместимости с OS X v10.2.x или ранее или Ваше устройство не было ранее доступным использованием семьи Model архитектуры SCSI API, необходимо сначала попытаться найти устройство с помощью Модели архитектуры SCSI API и если это перестало работать, то попытайтесь найти устройство с помощью семьи SCSI API. Необходимо тогда использовать, какой бы ни API успешно нашел, что устройство получило доступ к устройству.

Нахождение устройства

Для выполнения устройства, соответствующего (нахождение устройства путем определения местоположения его записи в Реестре I/O), Вы сначала создаете соответствующий словарь. Соответствующий словарь является словарем пар ключ/значение, описывающих свойства устройства или другой службы. Вспомните, что, когда устройство обнаружено в системе OS X, Набор I/O инстанцирует объекта куска, представляющего устройство, присоединяющего кусок к Реестру I/O и регистрирующего его. Семейство устройства публикует свойства в куске что использование Набора I/O для нахождения подходящего драйвера для устройства. Как только Вы создали соответствующий словарь, можно добавить ключи и значения, указывающие эти свойства для соответствия на.

Проект SCSIOldAndNew выполняет весь свой SCSI специфичные для семьи задачи соответствия и доступа к устройствам устройства в названном модуле OldMethod.c. Для нахождения устройства выбранного пользователями типа периферийного устройства основной модуль вызывает FindDevicesUsingOldMethod функция (показанный позже в Перечислении 1-3), передавая его тип периферийного устройства, ведущий порт Набора I/O и указатель на итератор. Итератор, объект типа io_iterator_t, будет содержать ссылку на первый объект устройства в списке объектов согласующего устройства, найденных в Реестре I/O, если таковые имеются.

Во-первых, однако, FindDevicesUsingOldMethod должен создать соответствующий словарь, описывающий устройство. Чтобы сделать это, это объявляет переменную типа CFMutableDictionaryRef и передает адрес этого словаря и типа периферийного устройства к функции CreateMatchingDictionaryForOldMethod, показанный в Перечислении 1-2.

Перечисление 1-2  , Создающее соответствующий словарь для устройства Параллели SCSI

void CreateMatchingDictionaryForOldMethod(SInt32 peripheralDeviceType,
                CFMutableDictionaryRef *matchingDict)
{
    SInt32  deviceTypeNumber = peripheralDeviceType;
    CFNumberRef deviceTypeRef = NULL;
 
    // Set up a matching dictionary to search the I/O Registry by class name
    // for all subclasses of IOSCSIDevice.
    *matchingDict = IOServiceMatching(kIOSCSIDeviceClassName);
 
    if (*matchingDict != NULL)
    {
        // Add key for device type to refine the matching dictionary.
        // First create a CFNumber to store in the dictionary.
        deviceTypeRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
                        &deviceTypeNumber);
        CFDictionarySetValue(*matchingDict, CFSTR(kSCSIPropertyDeviceTypeID),
                        deviceTypeRef);
    }
}

IOProviderClass- пара ключ/значение myDeviceClassName является общей в соответствии словарей. Функция в Перечислении 1-2 передает имя класса устройства к функции удобства Набора I/O IOServiceMatching, который создает соответствующий словарь и помещает в него эту пару ключ/значение. Поскольку получающийся словарь соответствовал бы на потенциально большом количестве устройств, однако, CreateMatchingDictionaryForOldMethod функция также добавляет другую пару ключ/значение для сужения поиска к устройствам, идентифицирующим себя как переданный - в типе периферийного устройства.

С соответствующим словарем от CreateMatchingDictionaryForOldMethod, FindDevicesUsingOldMethod функция выполняет поиск устройства, с помощью функции Набора I/O IOServiceGetMatchingServices. Этот Набор I/O функционирует взгляды в Реестре I/O для устройств, свойства которых соответствуют пары ключ/значение в соответствующем словаре. Это возвращается io_iterator_t объект можно думать как указатель на список согласующих устройств. Для доступа к каждому устройству Вы передаете объект итератора функции Набора I/O IOIteratorNext, который возвращается io_object_t объект, представляющий согласующее устройство и сброс итератор для “указания на” следующее согласующее устройство. Частичное перечисление FindDevicesUsingOldMethod показан в Перечислении 1-3.

Перечисление 1-3  , Находящее устройство

boolean_t FindDevicesUsingOldMethod(SInt32 peripheralDeviceType,
                mach_port_t masterPort, io_iterator_t *iterator)
{
    CFMutableDictionaryRef  matchingDict = NULL;
    boolean_t           result = false;
 
    CreateMatchingDictionaryForOldMethod(peripheralDeviceType,
                    &matchingDict);
    // ...
 
    // Now search I/O Registry for matching devices.
    kr = IOServiceGetMatchingServices(masterPort, matchingDict,
                            iterator);
 
    if (*iterator && kr == kIOReturnSuccess) {
        result = true;
    }
 
    // IOServiceGetMatchingServices consumes a reference to the matching
    // dictionary, so we don't need to release the dictionary reference.
 
    return result;
}

Результат FindDevicesUsingOldMethod возвраты говорят основной модуль, если он нашел какие-либо устройства указанного типа периферийного устройства, который поддерживает семья SCSI.

Получение интерфейса устройства

Интерфейс устройства обеспечивает функции, которые Ваше приложение или другой код, работающий на OS X, могут использовать для доступа к устройству. Интерфейсы устройства являются сменными интерфейсами, соответствующими Базовой модели плагина Основы (для получения дополнительной информации о Базовых плагинах Основы, посмотрите Ссылочную Библиотеку> Базовая Основа).

Семья I/O Kit, обеспечивающая интерфейс устройства, определяет тип, представляющий набор интерфейсов, которые это поддерживает и тип для каждого отдельного интерфейса. Семья дает этим типам UUIDs (универсально уникальные идентификаторы), которые идентифицируют их. Большинство семей также определяет понятные имена для этих идентификаторов, которые можно использовать вместо 128-разрядных значений UUID. Семья SCSI, например, определяет константу kIOSCSIUserClientTypeID как синоним для UUID B4291228 0F0F 11D4 9126 0050E4C6426F, идентифицирующего интерфейс устройства SCSI.

Прежде чем можно будет получить специфичный для семьи интерфейс устройства, однако, необходимо сначала создать интерфейс типа IOCFPlugInInterface. Этот интерфейс устанавливает функции, требуемые для всех интерфейсов на основе Базовой модели плагина Основы. Руководитель среди них QueryInterface функция, создающая экземпляры специфичных для семьи интерфейсов устройства.

Для получения интерфейса устройства семьи SCSI приложение выполняет следующие шаги:

  1. Получите промежуточный интерфейс типа IOCFPlugInInterface.

    Для получения этого интерфейса приложение вызывает IOCreatePlugInInterfaceForService функция, передавая io_object_t представление согласующего устройства (полученный из IOIteratorNext), значение kIOSCSIUserClientTypeID для сменного параметра типа и значения kIOCFPlugInInterfaceID для интерфейсного параметра типа. (kIOSCSIUserClientTypeID определяется в IOSCSILib.h и kIOCFPlugInInterfaceID и IOCreatePlugInInterfaceForService определяются в IOCFPlugIn.h.)

  2. Получите интерфейс устройства SCSI.

    Чтобы сделать это, приложение вызывает QueryInterface функция объекта IOCFPlugInInterface, передавая UUID желаемого интерфейса устройства. Для получения UUID от определенного семьей имени интерфейса устройства используйте следующий термин:

    CFUUIDGetUUIDBytes(kIOSCSIDeviceInterfaceID)

  3. Выпустите промежуточный объект IOCFPlugInInterface.

    Чтобы сделать это, приложение вызывает IODestroyPlugInInterface функция (определенный в IOCFPlugIn.h).

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

Проект SCSIOldAndNew выполняет, они вступают CreateDeviceInterfaceUsingOldMethod функция в OldMethod.c модуль. Перечисление 1-4 показывает часть этой функции, передающейся io_object_t представление согласующего устройства (полученный от вызова до IOIteratorNext) и указатель на интерфейс типа IOSCSIDeviceInterface.

Перечисление 1-4  , Создающее интерфейс устройства SCSI

void CreateDeviceInterfaceUsingOldMethod(io_object_t scsiDevice,
                    IOSCSIDeviceInterface ***interface)
{
    IOCFPlugInInterface **plugInInterface = NULL;
    HRESULT     plugInResult = S_OK;
    kern_return_t   kr = kIOReturnSuccess;
    SInt32      score = 0;
 
    // Create the base interface of type IOCFPlugInInterface.
    // This object will be used to create the SCSI device interface object.
    kr = IOCreatePlugInInterfaceForService( scsiDevice,
                          kIOSCSIUserClientTypeID, kIOCFPlugInInterfaceID,
                          &plugInInterface, &score);
 
    if (kr != kIOReturnSuccess) {
        fprintf(stderr, "Couldn't create a plug-in interface for the
                    io_service_t. (0x%08x)\n", kr);
    }
    else {
        // Query the base plug-in interface for an instance of the specific
        // SCSI device interface object.
        plugInResult = (*plugInInterface)->QueryInterface(plugInInterface,
                            CFUUIDGetUUIDBytes(kIOSCSIDeviceInterfaceID),
                            (LPVOID *) interface);
 
        if (plugInResult != S_OK) {
            fprintf(stderr, "Couldn't create SCSI device interface.
                        (%ld)\n", plugInResult);
        }
        // We're now finished with the instance of IOCFPlugInInterface.
        IODestroyPlugInInterface(plugInInterface);
    }
}

Открытие устройства и отправка команд

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

SCSIDeviceInterface определяет вызванную функцию getInquiryData это получает информацию об устройстве. В OldMethod.c модуль проекта SCSIOldAndNew, функции GetInquiryDataUsingOldMethod (показанный в Перечислении 1-5), демонстрирует, как вызвать эту функцию интерфейса устройства.

Перечисление 1-5  , Получающее кэшированные данные об устройстве Параллели SCSI

void GetInquiryDataUsingOldMethod(IOSCSIDeviceInterface **interface)
{
    UInt8       inquiryData[255];
    UInt32      inquiryDataSize = sizeof(inquiryData);
    kern_return_t   kr = kIOReturnSuccess;
 
    bzero(inquiryData, sizeof(inquiryData));    // Zero data block.
 
    // Call a function of the SCSI device interface that returns cached
    // information about the device.
    kr = (*interface)->getInquiryData(interface, (SCSIInquiry *) inquiryData,
                        sizeof(inquiryData), &inquiryDataSize);
 
    // If error, print message and hang (for debugging purposes).
    if (kr != kIOReturnSuccess) {
        fprintf(stderr, "Couldn't get inquiry data for device. (0x%08x)\n",
                    kr);
    }
    else {
        PrintSCSIInquiryDataUsingOldMethod((SCSIInquiry *) inquiryData,
                    inquiryDataSize);
    }
}

Функция PrintSCSIInquiryDataUsingOldMethod (не показанный здесь), просто форматирует и выводит на экран информацию об устройстве, включая:

  • Тип периферийного устройства

  • Идентификатор поставщика

  • Идентификатор продукта и уровень версии

  • Формат данных ответа

  • Сменяемость носителей

Несмотря на то, что можно получить эту информацию, не открывая устройство, если Вы хотите отправить команды в устройство Параллели SCSI, необходимо открыть устройство и создать дополнительный интерфейс, названный CDBCommandInterface.

SCSIDeviceInterface определяет open функция, открывающая устройство и, если это успешно выполняется, вызывает все другие вызовы к open перестать работать с kIOReturnExclusiveAccess ошибка. После открытия устройства Вы используете SCSIDeviceInterface QueryInterface функция (характерный для всех Базовых интерфейсов плагина Основы) для создания CDBCommandInterface. Можно использовать CDBCommandInterface для отправки к командам устройства Параллели SCSI, таким как:

  • ЗАПРОС

  • ТЕСТОВЫЙ ГОТОВЫЙ МОДУЛЬ

  • СЧИТАЙТЕ БУФЕР

  • БУФЕР ЗАПИСИ

  • СМЫСЛ ЗАПРОСА

Эти и другие команды определяются в SCSIPublic.h в платформе Набора I/O.

Функция TestADeviceUsingOldMethod (не показанный здесь), демонстрирует, как открыть устройство SCSI Parallel с помощью open функция переданного - в SCSIDeviceInterface:

(*interface)->open(interface);

Это тогда передает объект SCSIDeviceInterface функции CreateCommandInterfaceUsingOldMethod создать объект CDBCommandInterface. CreateCommandInterfaceUsingOldMethod показан в Перечислении 1-6.

Перечисление 1-6  , Получающее объект CDBCommandInterface

IOCDBCommandInterface **CreateCommandInterfaceUsingOldMethod
                            (IOSCSIDeviceInterface **interface)
{
    HRESULT         plugInResult = S_OK;
    IOCDBCommandInterface   **cdbCmdInterface = NULL;
 
    fprintf(stderr, "Opened device\n");
 
    // Use the constant kIOCDBCommandInterfaceID, defined in
    // IOCDBLib.h, to identify the CDBCommandInterface.
    plugInResult = (*interface)->QueryInterface(interface,
                        CFUUIDGetUUIDBytes(kIOCDBCommandInterfaceID),
                        (LPVOID *) &cdbCmdInterface);
 
    // If error, print message and hang (for debugging purposes).
    if (plugInResult != S_OK) {
        fprintf(stderr, "Couldn't create a CDB command. (%ld)\n",
                            plugInResult);
    }
 
    return cdbCmdInterface;
}

С CDBCommandInterface можно отправить команды SCSI в устройство. ExecuteInquiryUsingOldMethod функция в OldMethod.c модуль использует команду INQUIRY, чтобы проиллюстрировать, как установить структуру команды CDB (определенный в CDBCommand.h) и отправьте его в устройство. Сделать это, ExecuteInquiryUsingOldMethod функция выполняет следующие шаги:

  1. Это выделяет и инициализирует переменные штабеля (включая inquiryData, range, и cdb) указать команду INQUIRY и сохранить результаты.

  2. Это устанавливает переменную типа CDBInfo для указания команды, затем вызывает setAndExecuteCommand функция команды CDB взаимодействует через интерфейс, чтобы установить значения команды и выполнить команду.

    По возврату из setAndExecuteCommand функция, для асинхронной команды, seqNumber переменная содержит уникальный порядковый номер. Для синхронной команды порядковый номер всегда 0.

    setAndExecuteCommand функция (определенный в IOCDBLib.h) служебная функция, которую можно использовать вместо того, чтобы сделать множественные звонки, чтобы установить значения и затем вызвать execute функция.

  3. Это вызывает getResults функция команды CDB взаимодействует через интерфейс для получения результатов команды INQUIRY.

  4. Это вызывает MyPrintSCSIInquiryData служебная функция (не показанный здесь) для печати результатов.

  5. Поскольку это использует только переменные штабеля, это не имеет ничего для выпуска.

Перечисление 1-7 показывает ExecuteInquiryUsingOldMethod функция, минус ее код проверки ошибок.

Перечисление 1-7  Используя CDBCommandInterface возражает для отправки команд

void ExecuteInquiryUsingOldMethod(IOCDBCommandInterface
                        **cdbCommandInterface)
{
    UInt8           inquiryData[36 /* 255 */];
    IOVirtualRange  range[1];
    CDBInfo         cdb;
    CDBResults      results;
    UInt32          seqNumber;
    kern_return_t   kr = kIOReturnSuccess;
 
    bzero(inquiryData, sizeof(inquiryData));    // Zero data block.
 
    range[0].address = (IOVirtualAddress) inquiryData;
    range[0].length  = sizeof(inquiryData);
 
    bzero(&cdb, sizeof(cdb));
    cdb.cdbLength = 6;
    cdb.cdb[0] = kSCSICmdInquiry;
    cdb.cdb[4] = sizeof(inquiryData);
 
    kr = (*cdbCommandInterface)->setAndExecuteCommand(
                                    cdbCommandInterface,
                                    &cdb,
                                    sizeof(inquiryData),
                                    range,
                                    sizeof(range) / sizeof(range[0]),
                                    0, /* isWrite */
                                    0, /* timeoutMS */
                                    0, /* target */
                                    0, /* callback */
                                    0, /* refcon */
                                    &seqNumber);
 
    // Check to be sure the INQUIRY command executed correctly here.
 
    kr = (*cdbCommandInterface)->getResults(cdbCommandInterface, &results);
 
    // Check to be sure the getResults command executed correctly here.
 
    PrintSCSIInquiryDataUsingOldMethod((SCSIInquiry *) inquiryData,
                    results.bytesTransferred);
}

Закрытие устройства

То, когда Вы закончили отправлять команды в устройство Параллели SCSI, необходимо закрыть его и выпустить устройство, соединяет интерфейсом с Вами полученный. Функции в OldMethod.c модуль выполняет эти задачи в обратном порядке, начиная с последний раз полученного интерфейса. TestADeviceUsingOldMethod функционируйте выпускает объект CDBCommandInterface:

IOCDBCommandInterface **cdbCommandInterface;
(*cdbCommandInterface)->Release(cdbCommandInterface);

Затем, это закрывает устройство, с помощью функции SCSIDeviceInterface close:

IOSCSIDeviceInterface **interface;
(*interface)->close(interface);

Наконец, TestDevicesUsingOldMethod функционируйте выпускает объект SCSIDeviceInterface:

IOSCSIDeviceInterface **interface;
(*interface)->Release(interface);