В этом документе (перевод статьи [1]) описан функционал стандартного драйвера файловой системы (Generic File System Driver, FSD), удовлетворяющего спецификации службы файловой системы (File System Service, FSS) компании Analog Devices. Файловые системы, к которым относится этот документ, включают все системы, которые используют адресацию номерами секторов логических блоков (Logical Block Address, LBA), чтобы определить места расположения данных на физическом носителе (physical media).
Совместимый драйвер FSD должен удовлетворять следующим требованиям:
1. FSD должен предоставлять драйвер для нескольких экземпляров смонтированных разделов, к которым происходит обращение как к томам устройств.
2. Каждый экземпляр должен поддерживать концепцию текущей рабочей директории (current working directory, CWD), чтобы запросы к файловой системе (открытие, перемещение файлов и директорий) могли быть выполнены относительно CWD.
3. Внутренний дескриптор файла должен быть создан так, чтобы однозначно определить подходящие данные для каждого открытого файла. Указатель на соответствующую структуру должен быть назначен полю FSD_data_handle структуры ADI_FSS_FILE_DESCRIPTOR (структура файлового дескриптора FSS) при открытии файла.
4. Драйвер FSD должен возвратить FALSE в ответ на запрос ADI_DEV_CMD_GET_PERIPHERAL_DMA_SUPPORT.
5. Драйвер FSD должен возвратить либо ADI_FSS_RESULT_SUCCESS, либо ADI_FSS_RESULT_NOT_SUPPORTED в ответ на команду ADI_FSD_CMD_GET_FILE_SYSTEM_SUPPORT, запрашивающую информацию о том, поддерживает ли драйвер указанную файловую систему в списке типов файловых систем заголовка adi_fss.h (см. перечисление в разделе "Типы файловых систем").
6. Драйвер FSD должен поддерживать все команды, описанные в секции "Обязательные команды, относящиеся к драйверу FSD".
В последующих секциях, где должна быть возвращена строка идентификатора FSD, используется следующее соглашение именования для идентификаторов переменной данных или файла:
{ns} – представляет пространство имен, например adi. {iface} – представляет часть имени, относящееся к интерфейсу, например fat. {fsd-ident} = {ns}_{iface} – представляет строку в нижнем регистре, например adi_fat.
Если все упомянутое выше приводится в верхнем регистре, например {FSD-IDENT}, то строка будет та же самая, только большими буквами, например: ADI_FAT.
Драйвер FSD должен поддерживать как блоковый, так и произвольный (arbitrary) режимы работы, в зависимости от возможностей нижележащих драйверов PID [2] для выполнения фонового перемещения данных. Блочный режим предназначен для использования совместно с файловым кэшем FSS, когда должно подразумеваться, что операции чтения/записи запрашиваются блоками, размер которых диктуется самой малой поддерживаемой единицей данных файла. В этом режиме данные могут быть перемещены непосредственно между носителем данных (media) и буфером запроса, без промежуточного буфера, требуемого внутри драйвера FSD. С другой стороны, arbitrary-режим не будет использовать файловый кэш и драйвер FSD может ожидать запросы на произвольные количества данных (подробнее см. секцию "Определение структур конфигурации").
Если драйвер PID возвратил TRUE в ответ на команду ADI_FSS_CMD_GET_BACKGRND_XFER_SUPPORT, то драйвер FSD должен использовать блочный режим, иначе FSD должен использовать arbitrary (произвольный) режим. Драйвер FSD будет также подобным образом опрошен службой FSS при открытии файла, и при этом FSD должен вернуть то же самое значение, которое вернул драйвер PID.
Для использования драйвера FSD, скомпилированного для блочного режима, служба FSS делает вызов adi_dev_Control(), чтобы получить размер блока:
adi_dev_Control (< FSD Device Handle >, ADI_FSD_CMD_GET_BLOCK_SIZE, &BlockSize);
Подключаемые файлы. Исходный код драйвера FSD использует следующие подключаемые файлы:
services/services.h. Эти файлы содержат все определения, прототипы функций и т. д. для библиотеки Системных Служб (System Services Library, SSL) компании Analog Devices.
drivers/adi_dev.h. Этот файл содержит все определения, прототипы функций и т. д. для Менеджера Устройств [3] (Device Manager) и общей информации по драйверам устройств.
services/fss/adi_fss.h. Этот файл содержит все определения, прототипы функций и т. д. для службы файловой системы [2] (File System Service, FSS).
drivers/pid/{iface}/{pid-ident}.h. Этот файл содержит все определения, прототипы функций и т. д. для соответствующего драйвера физического интерфейса (Physical Interface Driver, PID).
string.h. Этот файл содержит все определения, прототипы функций и т. д. для строковых функций и функций копирования данных по памяти.
drivers/fsd/{iface}/{fsd-ident}.h. В этом файле содержатся определения, прототипы функций и т. д. для соответствующего драйвера FSD.
ctype.h. Этот файл содержит все определения, прототипы функций для функций языка C, связанных с типами.
Файлы исходного кода. Исходный код драйвера содержится в следующих файлах, размещенных в каталоге инсталляции VisualDSP++ по умолчанию: Blackfin / lib / src / drivers / fsd / {iface} / {fsd-ident}.c. Этот файл содержит весь исходный код для драйвера файловой системы (File System Device Driver). Весь исходный код написан на языке C, на этом уровне нет кода на языке ассемблера.
Драйверы нижнего уровня, драйвер PID. Драйвер периферийного устройства (peripheral device driver, PID), соответствующий аппаратной конфигурации, задействуется для перемещения данных из физического носителя данных (physical media) и в него. Хендл устройства для PID передается в драйвер FSD следующей парой команда-значение, например:
{ ADI_FSD_CMD_SET_PID_HANDLE, (void*)< PID-handle > }
Процесс выдачи запроса для PID должен придерживаться последовательности:
1. Запросить семафор блокировки от PID передачей пары команда-значение:
{ ADI_FSS_CMD_ACQUIRE_LOCK_SEMAPHORE, NULL },
2. Выполнить запрос LBA для первого буфера в цепочке, предоставленного для PID, передачей пары команда-значение:
{ ADI_PID_CMD_SEND_LBA_REQUEST, (void*)&pSuperBuffer->LBARequest },
3. Добавить callback-функцию, хендл callback-а и опциональный семафор (подсоединение семафора требуется только для внутренних запросов ввода/вывода. В случае, когда файловый кэш в работе семафора устанавливается модулем обслуживания кэша) для структуры супербуфера FSS (FSS Super Buffer structure) и очередь цепочки буферов с PID через вызов adi_dev_Read() или adi_dev_Write(), например:
adi_dev_Read{ ..., ADI_DEV_1D, (ADI_DEV_BUFFER*)pSuperBuffer },
4. Разрешить поток данных отправкой следующей команды драйверу PID:
{ ADI_PID_CMD_ENABLE_DATAFLOW, (void*)TRUE},
Семафор блокировки, который получен на шаге 1, освобождается драйвером FSD либо при поступлении вызова ADI_PID_EVENT_DEVICE_INTERRUPT callback для одиночного буфера (без цепочки), либо по завершению последнего подбуфера в цепочке.
Дополнительные подробности см. в документации с описанием драйвера PID [2].
[Ресурсы, требуемые для драйвера FSD]
Драйверы устройств обычно потребляют некоторое количество системных ресурсов. Эта секция описывает ресурсы, требуемые для драйвера FSD.
В описании ниже, если не указано нечто обратное, этот драйвер устройства использует Системные Службы для доступа к требуемой аппаратуре. Информация в этом разделе может быть полезной в определении ресурсов, которые требуются драйверу от Системных Служб, такие как количество обработчиков прерываний или количество каналов DMA и т. п.
Работа с памятью. Все требования к памяти, кроме структур данных, созданных в стеке, удовлетворяются динамически через вызовы функций централизованного API FSS: _adi_fss_malloc(), _adi_fss_realloc() и _adi_fss_free(). Эти функции являются обертками для либо для функций по умолчанию libc: heap_malloc(), heap_realloc() и heap_free(), или для функций, предоставленных приложением, как это определено в конфигурации службы FSS. Этим способом разработчик может предоставить функции управления памятью, чтобы организовать выделение памяти фиксированными, заранее известными блоками. Чтобы использовать эти функции в драйвере FSD, в его исходный код должны быть добавлены следующие определения:
extern void *_adi_fss_malloc( int id, size_t size );
extern void _adi_fss_free( int id, void *p );
extern void *_adi_fss_realloc( int id, void *p, size_t size );
Службой FSS поддерживается два типа куч: куча кэша (cache heap) для буферов данных, таких как источник данных или место назначения передач DMA, и общая куча (general heap) для хранения таких данных, как данные экземпляров объектов. При конфигурировании драйвера FSD, разработчики могут указать только индекс кучи для кучи кэша; FSD должен использовать общую кучу, которая была определена в службе FSS. Таким образом, для любого использования общей кучи FSD должен передать -1 в качестве аргумента идентификатора кучи (id), что FSS будет интерпретировать как запрос использовать индекс общей кучи, сохраненный службой FSS. Подобным образом значение по умолчанию для индекса кучи кэша FSD должно быть -1.
Значение индекса кучи устанавливается парой команда-значение:
{ ADI_FSS_CMD_SET_CACHE_HEAP_ID, (void*)CacheHeapIndex }
Здесь CacheHeapIndex это либо индекс массива heap_table_t heap_table array (см. файл < имя_проекта >_heaptab.c file), или значение, полученное из вызова heap_install:
static u8 myheap[1024];
#define MY_HEAP_ID 1234
...
int CacheHeapIndex = heap_install ((void *)&myheap, sizeof(myheap), MY_HEAP_ID);
Использование настраиваемых куч может зависеть от окружения разработки. Если выбранное окружение не поддерживает настраиваемые кучи, то подпрограммы FSS будут изменены, чтобы игнорировать аргумент индекса кучи.
Следующую таблицу следует заполнить информацией, касающейся требуемого количества выделяемой динамической памяти для связанной операции (при заполнении таблицы при необходимости добавьте в неё будущие операции).
Операция |
Размер (в байтах) |
Экземпляр устройства (один на на раздел) |
|
Открытый файл |
|
Открытая директория |
|
Прерывания. Драйвер FSD не использует специфических обработчиков прерываний. Нижележащие драйверы PID могут использовать специфические прерывания. За подробностями обратитесь к документации на соответствующий драйвер PID.
DMA. Драйвер FSD не поддерживает DMA напрямую. Нижележащие драйверы PID могут использовать DMA. За подробностями обратитесь к документации на соответствующий драйвер PID.
Таймеры. Драйвер FSD не использует специфические таймеры. Таймеры и callback-ки для них могут использоваться нижележащими драйверами PID. За подробностями обратитесь к документации на соответствующий драйвер PID.
Семафоры. Драйвер FSD требует 2 семафоров, один для семафора блокировки (Lock Semaphore), чтобы в любой момент времени обеспечить исключительный доступ к драйверу FSD только для одного процесса, и еще один для сигнализирования об окончании внутренних передач данных. Для создания всех семафоров и манипулирования ими должна использоваться Служба Семафоров.
Часы реального времени (Real-Time Clock, RTC). Драйвер FSD требует использования службы часов реального времени (RTC Service).
Программируемые флаги. Драйвером FSD не используются программируемые флаги. Нижележащие драйверы PID могут использовать программируемые флаги. За подробностями обратитесь к документации на соответствующий драйвер PID.
Выводы процессора. Драйвером FSD не используются программируемые флаги. Нижележащие драйверы PID могут использовать выводы для доступа к физическому носителю данных (media). За подробностями обратитесь к документации на соответствующий драйвер PID.
[Поддерживаемые функции драйвера устройства]
Направление данных. В таблице ниже перечислены направления данных, которые поддерживает драйвер.
Таблица 3. Поддерживаемые направления данных.
ADI_DEV_DIRECTION |
Описание |
ADI_DEV_DIRECTION_INBOUND |
Поддерживает прием данных в устройство. |
ADI_DEV_DIRECTION_BIDIRECTIONAL |
Поддерживаются оба направления данных. |
Методы потока. Драйвер поддерживает только один метод потока: цепочка буферов ADI_DEV_MODE_CHAINED.
Типы буферов. Драйвер FSD поддерживает только одномерный линейный буфер (ADI_DEV_1D_BUFFER). Он обернут структурой супербуфера FSS (FSS Super Buffer Structure). Поля структуры буфера ADI_DEV_1D_BUFFER:
CallbackParameter - здесь всегда содержится адрес структуры супербуфера FSS. ProcessedFlag - это поле не используется драйвером FSD. pAdditionalInfo - это поле не используется драйвером FSD.
Идентификаторы команд (Command ID). Здесь перечислены команды, которые поддерживаются драйвером FSD. Эти команды делятся на 3 секции. Первая секция описывает команды, которые напрямую поддерживаются Драйвером Устройств (Device Manager) [3]. Вторая описывает общие команды, которые драйвер поддерживает. Последняя секция описывает команды, специфические для драйвера FSD.
Команды отправляются драйверу устройства функцией adi_dev_Control(), которая принимает 3 аргумента:
DeviceHandle - параметр типа ADI_DEV_DEVICE_HANDLE, который уникально идентифицирует драйвер устройства. Этот хендл предоставляется для клиента на вызове при возврате из функции adi_dev_Open(). CommandID - параметр типа u32, который указывает идентификатор команды. Value - параметр типа void *, смысл которого зависит от значения CommandID.
Секции ниже перечисляют CommandID, поддерживаемые драйвером, и назначение параметра Value для каждого кода CommandID.
Команды, поддерживаемые Менеджером Устройств. Перечисленные ниже команды непосредственно обрабатываются Менеджером Устройств [3] (Device Manager). Таким образом, все драйверы поддерживают эти команды.
ADI_DEV_CMD_TABLE. Задает таблицу пар команда-значение, передаваемых драйверу. Параметр Value определяет адрес таблицы (ADI_DEV_CMD_VALUE_PAIR *).
ADI_DEV_CMD_END. Обозначает конец таблицы команд. Параметр Value игнорируется (может быть равен NULL).
ADI_DEV_CMD_PAIR. Передает одну пару команда-значение. Параметр Value определяет адрес этой пары (ADI_DEV_CMD_PAIR *).
ADI_DEV_CMD_SET_SYNCHRONOUS. Разрешает/запрещает синхронный режим для драйвера. Value: TRUE/FALSE.
ADI_DEV_CMD_GET_INBOUND_DMA_CHANNEL_ID. Вернет значение идентификатора канала DMA (DMA channel ID) для входящего потока данных драйвера. Value: указатель u32* (ячейка памяти, куда будет сохранен channel ID).
ADI_DEV_CMD_GET_OUTBOUND_DMA_CHANNEL_ID. Вернет значение идентификатора канала DMA (DMA channel ID) для исходящего потока данных драйвера. Value: указатель u32* (ячейка памяти, куда будет сохранен channel ID).
ADI_DEV_CMD_SET_INBOUND_DMA_CHANNEL_ID. Команда установит значение идентификатора канала DMA (DMA channel ID) для входящего потока данных драйвера. Value: ADI_DMA_CHANNEL_ID (DMA channel ID, идентификатор канала DMA).
ADI_DEV_CMD_SET_OUTBOUND_DMA_CHANNEL_ID. Команда установит значение идентификатора канала DMA (DMA channel ID) для исходящего потока данных драйвера. Value: ADI_DMA_CHANNEL_ID (DMA channel ID, идентификатор канала DMA).
ADI_DEV_CMD_SET_DATAFLOW_METHOD. Задает метод потока данных. Как уже упоминалось, поддерживается только один метод потока данных: ADI_DEV_MODE_CHAINED. Value: значение из перечисления ADI_DEV_MODE (поддерживается только значение ADI_DEV_MODE_CHAINED).
Общие команды. Идентификаторы команд, описанные в этой секции, являются общими для многих драйверов устройств. Ниже в списке приведены команды такого рода, поддерживаемые драйвером FSD.
ADI_DEV_CMD_SET_DATAFLOW. Разрешает/запрещает поток данных через устройство. Обязательная для использования команда. Value: TRUE/FALSE.
ADI_DEV_CMD_GET_PERIPHERAL_DMA_SUPPORT. Позволяет узнать, поддерживается ли драйвер устройства периферийным DMA. Команда имеет важное значение. Value: u32* (указывает на ячейку памяти, куда будет сохранено значение TRUE или FALSE).
Обязательные команды, относящиеся к драйверу FSD. Перечисленные ниже идентификаторы команд обязательно должны поддерживаться драйвером FSD. Однако для файловых систем, предназначенных только для чтения, не требуется реализовывать команды, относящиеся к операциям записи.
[Операции с файлами]
ADI_FSD_CMD_OPEN_FILE. Файл указывается полем pFullFileName структуры ADI_FSS_FILE_DESCRIPTOR, которое задает путь до открываемого файла. Драйвер FSD должен выделять память для своего внутреннего дескриптора файла, и добавлять его к своему списку открытых файлов. При возврате FSD должен записать в поле fsize размер файла, как он читается с носителя данных, и записать в поле FSD_data_handle адрес подходящей структуры данных внутри FSD, которая уникально идентифицирует открытый файл и его позицию на носителе данных. Если файл не может быть найден и установлен бит 8 флага режима дескриптора файла (File Descriptor), то тогда файл будет создан и будет считаться, что он существует. Если файл обнаружен, и установлен бит 9 флага режима, то файл открывается и его содержимое сбрасывается так, что файл оказывается пустым. Value: адрес структуры ADI_FSS_FILE_DESCRIPTOR, идентифицирующей открываемый файл.
ADI_FSD_CMD_CLOSE_FILE. Закрывает файл, который идентифицирован структурой ADI_FSS_FILE_DESCRIPTOR. Драйвер FSD должен освободить память, выделенную этим внутренним дескриптором, и удалить его из своего списка открытых файлов. При возврате FSD должен очистить поле FSD_data_handle структуры ADI_FSS_FSD_FILE_DEF. Value: адрес структуры ADI_FSS_FILE_DESCRIPTOR, идентифицирующей закрываемый файл.
ADI_FSD_CMD_SEEK_FILE. Драйвер выполнит позиционирование в определенное место файла, задаваемое значениями в структуре ADI_FSS_SEEK_REQUEST. Value: адрес структуры ADI_FSS_SEEK_REQUEST, идентифицирующую обрабатываемый файл и параметры позиционирования.
[Операции с директориями]
ADI_FSD_CMD_CHANGE_DIR. Настраивает текущую рабочую директорию так, как это указано в структуре связанного списка ADI_FSS_FULL_FNAME, переданной через аргумент Value. Value: адрес структуры ADI_FSS_FULL_FNAME, определяющей имя пути директории, в которую нужно перейти.
ADI_FSD_CMD_MAKE_DIR. Создает новую директорию в файловой системе по пути (pathname), указанном в в структуре связанного списка ADI_FSS_FULL_FNAME, переданной через аргумент Value. Текущая рабочая директория драйвера FSD остается неизменной. Value: адрес структуры ADI_FSS_FULL_FNAME, определяющей имя пути директории, в которую нужно создать.
ADI_FSD_CMD_REMOVE_DIR. Удаляет запись директории в файловой системе. Удаляемая директория задается через путь, указанный в структуре связанного списка ADI_FSS_FULL_FNAME, переданной через аргумент Value. Текущая рабочая директория драйвера FSD остается неизменной. Value: адрес структуры ADI_FSS_FULL_FNAME, определяющей имя пути директории, в которую нужно удалить.
ADI_FSD_CMD_OPEN_DIR. Открывает директорию, указанную полем pFullFileName структуры связанного списка ADI_FSS_FILE_DESCRIPTOR, где задан путь до открываемой директории. Драйвер FSD должен выделить память для своего внутреннего дескриптора файлов, и добавить его к своему списку открытых файлов. При возврате драйвер FSD должен присвоить полю fsize размер файла директории, как он читается с носителя данных, записать в поле FSD_data_handle адрес подходящей структуры данных внутри FSD, которая уникально идентифицирует открываемый файл и его позицию на носителе данных. Для работы с открытой директорией можно использовать команды доступа к директории; функцию adi_dev_Read использовать нельзя. Value: адрес структуры ADI_FSS_DIR_DEF, идентифицирующей открываемую директорию.
ADI_FSD_CMD_CLOSE_DIR. Закрывает директорию, идентифицируемую структурой ADI_FSS_DIR_DEF. Value: адрес структуры ADI_FSS_DIR_DEF идентифицирует директорию, которая должна быть закрыта.
ADI_FSD_CMD_READ_DIR. Читает следующую запись директории и заполняет структуру dirent, связанную со структурой ADI_FSS_DIR_DEF. Поле tellpos структуры ADI_FSS_DIR_DEF должно быть установлено в позицию файла текущей записи, и поле curpos связанной структуры ADI_FSS_FILE_DESCRIPTOR используется для указания на место в директории, находящейся сразу после последней прочитанной записи директории. Value: адрес структуры ADI_FSS_DIR_DEF, идентифицирующей читаемую директорию.
ADI_FSD_CMD_SEEK_DIR. Перемещает указатель текущей позиции внутри открытой директории в позицию, заданную полем tellpos структуры ADI_FSS_DIR_DEF, указанной через аргумент Value. При возврате поле curpos связанной структуры ADI_FSS_FILE_DESCRIPTOR указывает в то же место, что и поле tellpos. Value: задает структуру ADI_FSS_DIR_DEF, идентифицирующую директорию для обработки.
ADI_FSD_CMD_REWIND_DIR. Отматывает текущую позицию указателя открытой директории в её начало, сбрасывая оба поля: tellpos в структуре ADI_FSS_DIR_DEF (на которую указывает аргумент Value), и поле curpos связанной структуры ADI_FSS_FSD_FILE_DEF. Value: адрес структуры ADI_FSS_DIR_DEF, идентифицирующей отматываемую в начало директорию.
[Операции по обслуживанию файловой системы]
ADI_FSD_CMD_REMOVE. Удаляет файл и связанную запись директории в файловой системе. Файл определяется полем pathname структуры связанного списка ADI_FSS_FULL_FNAME, указанной через аргумент Value. Текущая рабочая директория FSD остается неизменной. Value: адрес структуры ADI_FSS_FULL_FNAME, определяющей путь до удаляемого файла.
ADI_FSD_CMD_RENAME. Переименовывает или перемещает в новое место по системе каталогов файл или директорию, идентифицируемую полем pSource указанной структуры ADI_FSS_RENAME_DEF. Новое имя целевой директории идентифицируется полем pTarget той же структуры. Value: адрес структуры ADI_FSS_RENAME_DEF, где определены имена переименовываемого файла и либо его новое имя, либо новое место, куда файл или директория должны быть перенесены.
ADI_FSD_CMD_GET_FILE_SYSTEM_SUPPORT. Возвратит ADI_FSS_RESULT_SUCCESS, если драйвер FSD поддерживает требуемую файловую системы, как указано в сопровождающем 32-битном слове; иначе будет возвращен код ADI_FSS_RESULT_NOT_SUPPORTED. Value: уникальный идентификатор, определяющий файловую систему. Допустимые идентификаторы предоставлены в заголовке adi_fss.h службы FSS.
ADI_FSD_CMD_MOUNT_VOLUME. Инструктирует драйвер FSD читать загрузочную запись (Boot Record) тома по заданному номеру сектора LBA, и переместиться в корневую директорию тома (root directory). Value: - номер сектора LBA, определяющий начало требуемого тома, в соответствии с таблицей разделов (Partition Table).
ADI_FSD_CMD_UNMOUNT_VOLUME. Инструктирует драйвер FSD размонтировать том. Value: недоступно.
ADI_FSD_CMD_SET_PID_HANDLE. Инструктирует драйвер FSD использовать драйвер устройства, определенный в параметре Value как ADI_DEV_DEVICE_HANDLE, чтобы читать/записывать данные физического носителя. Value: адрес ADI_DEV_DEVICE_HANDLE, идентифицирующий драйвер устройства, используемый для чтения/записи физического носителя данных (physical media).
ADI_FSS_CMD_GET_BACKGRND_XFER_SUPPORT. Запрашивает драйвер FSD вернуть TRUE или FALSE в зависимости от возможности для драйвера поддерживать фоновую передачу данных. Возвращенное значение зависит от нижележащего драйвера PID, которому должна быть передана эта команда. Value: предоставленное клиентом место для сохранения результата.
ADI_FSS_CMD_GET_DATA_ELEMENT_WIDTH. Запрашивает драйвер FSD вернуть ширину (в байтах), которая определяет каждый элемент данных. Возвращенное значение будет зависеть от нижележащего драйвера PID, которому должна быть передана эта команда. Value: предоставленное клиентом место для сохранения результата.
ADI_FSS_CMD_ACQUIRE_LOCK_SEMAPHORE. Запрос драйверу FSD предоставить семафор блокировки (Lock Semaphore), чтобы дать вызывающему модулю исключительный доступ к функциям перемещения данных драйвера PID. Value: NULL.
ADI_FSS_CMD_RELEASE_LOCK_SEMAPHORE. Запрос драйверу FSD освободить семафор блокировки, предоставленный в ответ на команду ADI_FSS_CMD_ACQUIRE_LOCK_SEMAPHORE. Value: NULL.
ADI_FSS_CMD_SET_CACHE_HEAP_ID. Инструктирует экземпляр FSD использовать предоставленный индекс кучи (Heap Index) для динамически выделяемых кэшей данных. Хотя использовать это и не обязательно, драйвер FSD должен вернуть ADI_FSS_RESULT_SUCCESS даже если команда игнорируется. Индекс кучи по умолчанию для таких кэшей должен быть по умолчанию -1, показывая этим, что должна использоваться общая куча службы FSS (FSS General Heap). Value: индекс требуемой кучи.
ADI_FSD_CMD_GET_BLOCK_SIZE. На выходе FSD вернет размер в байтах самой малой значимой единицы данных для файла. Для большинства файловых систем это будет размер кластера (Cluster size). Value: адрес ячейки памяти, куда при возврате будет записана информация размера.
ADI_FSD_CMD_GET_TYPE_STRING. Инструктирует драйвер FSD предоставить адрес строки, описывающей драйвер. Эта строка будет предоставлена в стандартной кодировке ASCII. Value: при возврате здесь будет адрес строки, завершающейся нулем (NULL terminated string, ASCIIZ-строка).
ADI_FSD_CMD_GET_LABEL. Инструктирует FSD предоставить адрес строки текста, где содержится метка из 11 символов. Эта метка будет предоставлена в стандартной кодировке ASCII. Value: при возврате здесь будет адрес строки метки.
Определение команд, специфичных для драйвера FSD. Можно задать дополнительные команды, удовлетворяющие специфическим требованиям FSD. Эти команды доступны только во время конфигурации, или когда драйвер FSD используется отдельно от службы FSS.
Эти команды должны быть определены в заголовочном файле, относящемся к драйверу PID (файл {fsd-ident}.h) следующим образом:
enum
{
{NS}_{IFACE}_CMD_START = ADI_FSD_CUSTOM_CMD_START, /* (0x000B6000) */
{NS}_{IFACE}_CMD_< описание-команды-1>,
{NS}_{IFACE}_CMD_< описание-команды-2 >,
{NS}_{IFACE}_CMD_< описание-команды-n >,
};
Семафоры блокировки. Драйвер FSD должен поддерживать как минимум один семафор блокировки (Lock Semaphore), чтобы предотвратить одновременный доступ со стороны нескольких потоков. Этот семафор блокировки предоставляется процессу при поступлении следующей пары команда-значение:
{ ADI_FSS_CMD_ACQUIRE_LOCK_SEMAPHORE, NULL },
И освобождается семафор при поступлении следующей пары команда-значение:
{ ADI_FSS_CMD_RELEASE_LOCK_SEMAPHORE, NULL },
Семафор блокировки должен быть создан с помощью Службы Семафоров в функции adi_pdd_Open() как двоичный семафор с начальным значением счетчика, равным единице:
adi_sem_Create ( 1, &pVolume->LockSemaphoreHandle, NULL );
Здесь pVolume это указатель на данные экземпляра драйвера FSD. Таким образом, когда поток запрашивает семафор блокировки, FSD будет ожидать на семафоре блокировки вызовом функции:
adi_sem_Pend (pVolume->LockSemaphoreHandle, ADI_SEM_TIMEOUT_FOREVER);
И первый поток, который выполнит это, продолжит свое выполнение. Другие потоки будут заблокированы, пока поток, удерживающий семафор блокировки, не освободит его публикацией этого семафора:
adi_sem_Post (pVolume->LockSemaphoreHandle);
Семафор блокировки должен быть удален в функции adi_pdd_Close():
adi_sem_Delete (pVolume->LockSemaphoreHandle);
Другие семафоры. Драйвер FSD должен поддерживать как минимум 1 семафор, показывающий завершение передачи данных. Он должен быть создан с помощью Службы Семафоров в функции adi_pdd_Open() как двоичный семафор с начальным значением счетчика, равным нулю:
adi_sem_Create ( 0, &pVolume->DataSemaphoreHandle, NULL );
Этот хендл семафора должен быть присвоен полю SemaphoreHandle в супербуфере службы FSS (FSS Super Buffer), когда инициируется передача данных внутри FSD. Как только буфер был поставлен в очередь с драйвером PID, драйвер FSD должен ожидать на этом семафоре завершения процесса передачи. При поступлении callback-события ADI_PID_EVENT_DEVICE_INTERRUPT драйвер FSD должен проверить это значение на соответствие значению в супербуфере FSS, и при совпадении опубликовать семафор. Подробности см. в следующей секции "События callback".
События callback. Драйвер FSD не генерирует события callback, он просто обрабатывает буферы, предоставляемые службой FSS, и передает их драйверу PID, который будет генерировать событие callback при завершении обработки данных. Однако драйвер FSD должен предоставить callback-функцию, которая должна быть вызвана из FSS в ответ на события ADI_DEV_EVENT_BUFFER_PROCESSED и ADI_PID_EVENT_DEVICE_INTERRUPT. Дополнительно он предоставляет значимый хендл, чтобы передать его как первый аргумент в эту callback-функцию. Обычно этот хендл будет адресом данных экземпляра FSD. Эти значения должны быть назначены полям FSDCallbackFunction и FSDCallbackHandle в супербуфере FSS (FSS Super buffer) перед постановкой очереди цепочки буферов с драйвером PID.
Другие аргументы для callback-функции предоставляются так же, как и для всех функций типа ADI_DCB_CALLBACK_FN:
void FSDCallback (void* Handle, u32 Event, void *pArg);
Драйвер FSD может предположить, что значение pArg указывает на структуру супербуфера FSS (FSS Super Buffer) для подбуфера, у которого завершилась передача данных.
Если драйвер FSD владеет семафором, находящимся в супербуфере FSS, то он должен опубликовать его в ответ на событие ADI_PID_EVENT_DEVICE_INTERRUPT. Тогда в ответ на то же событие он должен либо предоставить следующий запрос LBA в цепочке (когда последующее значение SectorCount не равно 0), либо освободить семафор блокировки PID, если это конец цепочки. Для отдельного использования (без службы FSS) произойдет глухая блокировка (deadlock), если семафор был опубликован в отдельном callback, для которого освобождается семафор блокировки PID (это может изменяться в зависимости от использования в других RTOS, но должно оставаться безопасным, чтобы сохранить то же самое управление для каждого случая).
[Коды возврата]
Все API-функции драйвера устройства возвращают код состояния, показывающий успех или неудачу завершения функции. При неудаче возвращаемый код показывает причину ошибки. В этом разделе перечислены коды возврата, которые драйвер устройства может возвратить клиенту. Возвращаемое значение ADI_DEV_RESULT_SUCCESS или ADI_FSS_RESULT_SUCCESS означает успешное завершение, и все другие значения означает либо некую ошибку, либо какой-то другой информативный результат. Значения ADI_DEV_RESULT_SUCCESS и ADI_FSS_RESULT_SUCCESS всегда равны 0. Все другие значения не нулевые.
Коды возврата делятся на 2 секции. Первая описывает коды возврата, которые являются общими для многих драйверов устройств. Другая секция описывает коды возврата, относящиеся именно к драйверу FSD. Код клиента должен подготовить обработку каждого из кодов возврата, описанного в этих секциях.
Обычно приложение сразу проверяет код результата на равенство ADI_DEV_RESULT_SUCCESS, предпринимая отдельные корректирующие действия, когда возвращаемое значение не равно ADI_DEV_RESULT_SUCCESS. Например:
if (adi_dev_Xxxx(...) == ADI_DEV_RESULT_SUCCESS)
{
// Нормальная обработка, успешное завершение функции
...
}
else
{
// Здесь должна быть обработка ошибки
...
}
Общие коды возврата. Здесь описаны коды возврата, которые являются общими для многих драйверов устройств. Список ниже перечисляет все общие коды возврата, поддерживаемые драйвером FSD.
ADI_DEV_RESULT_SUCCESS. Функция завершилась успешно.
ADI_DEV_RESULT_NOT_SUPPORTED. Эта функция не поддерживается драйвером.
ADI_DEV_RESULT_DEVICE_IN_USE. Запрашиваемое устройство уже используется.
ADI_DEV_RESULT_NO_MEMORY. Недостаточно памяти.
ADI_DEV_RESULT_BAD_DEVICE_NUMBER. Недопустимый номер устройства.
ADI_DEV_RESULT_DIRECTION_NOT_SUPPORTED. Устройство не может быть открыто в указанном направлении.
ADI_DEV_RESULT_BAD_DEVICE_HANDLE. Недопустимый хендл драйвера устройства.
ADI_DEV_RESULT_BAD_MANAGER_HANDLE. Недопустимый хендл Менеджера Устройств.
ADI_DEV_RESULT_BAD_PDD_HANDLE. Недопустимый хендл физического драйвера.
ADI_DEV_RESULT_INVALID_SEQUENCE. Запрошенное действие не находится в правильной последовательности с другими действиями.
ADI_DEV_RESULT_ATTEMPTED_READ_ON_OUTBOUND_DEVICE. Клиент попытался предоставить входящий буфер для устройства, открытого только для исходящего трафика.
ADI_DEV_RESULT_ATTEMPTED_WRITE_ON_INBOUND_DEVICE. Клиент попытался предоставить исходящий буфер для устройства, открытого только для входящего трафика.
ADI_DEV_RESULT_DATAFLOW_UNDEFINED. Пока не был задан метод потока данных.
ADI_DEV_RESULT_DATAFLOW_INCOMPATIBLE. Этот метод потока не совместим с запрошенным действием.
ADI_DEV_RESULT_BUFFER_TYPE_INCOMPATIBLE. Это устройство не поддерживает тип предоставленного буфера.
ADI_DEV_RESULT_CANT_HOOK_INTERRUPT. Менеджер Прерываний (Interrupt Manager) [4] не смог подцепить обработчик прерывания (ISR).
ADI_DEV_RESULT_CANT_UNHOOK_INTERRUPT. Менеджер Прерываний не смог отцепить обработчик прерывания.
ADI_DEV_RESULT_NON_TERMINATED_LIST. Цепочка предоставленных буферов не завершена NULL.
ADI_DEV_RESULT_NO_CALLBACK_FUNCTION_SUPPLIED. Не была предоставлена callback-функция, когда это необходимо.
ADI_DEV_RESULT_REQUIRES_UNIDIRECTIONAL_DEVICE. Требуется открытие устройства либо только для входящего, либо только для исходящего трафика (т. е. только в одном направлении).
ADI_DEV_RESULT_REQUIRES_BIDIRECTIONAL_DEVICE. Требуется открытие устройства только для двунаправленного трафика.
Коды возврата, специфичные для драйвера FSD. Эти коды поддерживаются и обрабатываются драйвером FSD, они уникальны для этого драйвера.
ADI_FSS_RESULT_BAD_NAME. Недопустимое имя файла/директории.
ADI_FSS_RESULT_NOT_FOUND. Указанный файл/директория не найдены в файловой системе.
ADI_FSS_RESULT_OPEN_FAILED. Указанный файл не может быть открыт из-за ошибки.
ADI_FSS_RESULT_CLOSE_FAILED. Указанный файл не может быть закрыт.
ADI_FSS_RESULT_MEDIA_FULL. Операция не может быть завершена, потому что физический носитель данных переполнен.
ADI_FSS_RESULT_NO_MEMORY. Недостаточно свободной памяти кучи для удовлетворения запроса на динамическое выделение памяти.
[Структуры данных]
Следующие структуры данных используются совместно с вышеперечисленными командами. Все они, кроме одной, определены в заголовке FSS, файл < services/fss/adi_fss.h >.
Точки входа в драйвер (Device Driver Entry Points, ADI_DEV_PDD_ENTRY_POINT). Эта структура используется в общем для всех драйверов, удовлетворяющих модели драйвера устройств компании Analog Devices (ADI Device Driver model), чтобы определить точки входа для драйвера устройства. Это должно быть определено в модуле исходного кода FSD, файле {fsd-ident}.c, и декларировано как переменная extern в заголовочном файле FSD {fsd-ident}.h, где присутствие имени защищено от повторного включения св исходном коде FSD следующим образом:
• В модуле исходного кода и перед оператором #include для заголовочного файла определяется макрос __{FSD-IDENT}_C__.
• В файле заголовка применяется блок защитного включения, обрамляющий декларацию extern:
#if !defined(__{FSD-IDENT}_C__)
extern ADI_DEV_PDD_ENTRY_POINT {FSD_IDENT}_EntryPoint;
...
#endif
Пары команда-значение, ADI_DEV_CMD_VALUE_PAIR. Эта структура используется как общая для всех драйверов, удовлетворяющих модели ADI Device Driver, и она используется главным образом для начальной конфигурации драйвера. Драйвер FSD должен поддерживать все 3 метода передачи пар команда-значение:
adi_dev_control( ..., ADI_DEV_CMD_TABLE, (void*)< адрес-таблицы-пар-команда-значение > );
adi_dev_control( ..., ADI_DEV_CMD_PAIR, (void*)< адрес-пары-команда-значение > );
adi_dev_control( ..., < команда >, (void*)< связанное-с-командой-значение > );
Таблица по умолчанию должна быть декларирована в заголовке драйвера FSD, файле {fsd-ident}.h, и защищена от повторного включения в исходном коде FSD. Она должна быть подключена только в модуле приложения, если разработчик определил макрос _{FSD-IDENT}_DEFAULT_DEF_:
#if !defined(__{FSD-IDENT}_C__)
...
#if defined(_{FSD-IDENT}_DEFAULT_DEF_)
static ADI_DEV_CMD_VALUE_PAIR {FSD-IDENT}_ConfigurationTable[] = { ... };
...
#endif
...
#endif
Структура определения устройства (Device Definition Structure, ADI_FSS_DEVICE_DEF). Эта структура используется для инструктирования службы FSS о том, как открыть и конфигурировать драйвер FSD. Её содержимое в сущности это тот же объем элементов, переданных как аргументы в вызов adi_dev_Open(). Структура определена в заголовке службы FSS, файл adi_fss.h, следующим образом:
typedef struct
{
u32 DeviceNumber;
ADI_DEV_PDD_ENTRY_POINT *pEntryPoint;
ADI_DEV_CMD_VALUE_PAIR *pConfigTable;
void *pCriticalRegionData;
ADI_DEV_DIRECTION Direction;
ADI_DEV_DEVICE_HANDLE DeviceHandle;
ADI_FSS_VOLUME_IDENT DefaultMountPoint;
} ADI_FSS_DEVICE_DEF;
Значение полей этой структуры показано в следующей таблице:
DeviceNumber |
Определяет, какое периферийное устройство используется. Это значение равно аргументу DeviceNumber, который нужен для вызова adi_dev_Open(). Для большинства драйверов FSD это значение будет равно 0. |
pEntryPoint |
Это указатель на точку входа драйвера устройства, и сюда передается тот же аргумент pEntryPoint, который нужно передать в функцию adi_dev_Open(). Для драйвера FSD это значение должно быть назначено на &{FSD_IDENT}_EntryPoint. |
pConfigTable |
Это указатель на таблицу пар команда-значение для конфигурирования драйвера FSD, и это значение должно быть назначено на {FSD_IDENT}_ConfigurationTable. |
pCriticalRegionData |
Это указатель на аргумент, который должен быть передан Системным Службам через вызов функции adi_int_EnterCriticalRegion(). В настоящий момент эта фича не используется, и здесь должно быть передано значение NULL. |
Direction |
Это аргумент для определения направления передачи данных, требуемый для вызова adi_dev_Open(). Для большинства драйверов FSD это значение будет равно ADI_DEV_DIRECTION_BIDIRECTIONAL. |
DeviceHandle |
Это ячейка для внутреннего использования, чтобы сохранить хендл драйвера устройства, который был возвращен из вызова adi_dev_Open(). Перед инициализацией этот параметр должен быть установлен в NULL. |
DefaultMountPoint |
Буква по умолчанию диска для томов, управляемых драйвером FSD. |
Инстанциация по умолчанию этой структуры декларирована в заголовке драйвера FSD, файл {fsd-ident}.h, и защищена от повторного включения в исходном коде FSD. Она должна подключаться только в модуле приложения, если разработчик определил макрос _{FSD-IDENT}_DEFAULT_DEF_:
#if !defined(__{FSD-IDENT}_C__)
...
#if defined(_{FSD-IDENT}_DEFAULT_DEF_)
static ADI_FSS_DEVICE_DEF {FSD-IDENT}_Def = { ... };
...
#endif
...
#endif
Дескриптор файла (FSS File Descriptor, ADI_FSS_FILE_DESCRIPTOR). Эта структура передается драйверу FSD для всех операций по открытию файлов. Она определена в заголовке FSS, файл adi_fss.h, следующим образом:
typedef struct
{
ADI_FSS_FULL_FNAME *pFullFileName;
u32 curpos;
u32 fsize;
int mode;
ADI_FSS_FSD_DATA_HANDLE FSD_data_handle;
ADI_DEV_DEVICE_HANDLE FSD_device_handle;
void *pCriticalRegionData;
ADI_FSS_CACHE_DATA_HANDLE Cache_data_handle;
} ADI_FSS_FILE_DESCRIPTOR;
Значение полей этой структуры показано в следующей таблице:
pFullFileName |
Связанный список, содержащий полное имя файла. |
curpos |
Текущая байтовая позиция в открытом файле. |
fsize |
Общий размер файла в байтах. При открытии файла это значение должно быть установлено в значение, записанное в файловой записи директории. |
mode |
Режим доступа, в котором открывается файл. |
FSD_data_handle |
Драйвер FSD должен присвоить этому полю адрес внутренней структуры данных, которая уникально идентифицирует состояние открытого файла в соответствующих терминах файловой системы. |
FSD_device_handle |
Здесь должен быть хендл устройства (Device Handle), идентифицирующий драйвер FSD, и он должен быть тот же самый, что и третий аргумент вызова adi_pdd_Open(). |
pCriticalRegionData |
Указатель на данные критического региона. В настоящее время это не используется. |
Cache_data_handle |
Этот хендл зарезервирован для использования с модулем файлового кэша. |
Структура полного имени файла ADI_FSS_FULL_FNAME. Содержит связанный список, определяющий пут к файлу. Если путь абсолютный, то поле name первой записи связанного списка будет NULL, иначе путь будет интерпретирован как относительный к текущей рабочей директории. Структура определена в заголовке adi_fss.h следующим образом:
typedef struct ADI_FSS_FULL_FNAME
{
struct ADI_FSS_FULL_FNAME *pNext;
struct ADI_FSS_FULL_FNAME *pPrevious;
ADI_FSS_WCHAR *name;
u32 namelen;
} ADI_FSS_FULL_FNAME;
Значение полей этой структуры показано в следующей таблице:
pNext |
Следующий элемент в связанном списке. |
pPrevious |
Предыдущий элемент в связанном списке. |
name |
Имя элемента текущего пути (это имя директории или файла). |
namelen |
Длина имени элемента текущего пути. |
Структура супербуфера FSS (FSS Super Buffer Structure, ADI_FSS_SUPER_BUFFER). Супербуфер используется как обертка над структурой ADI_DEV_1D_BUFFER. Так что у структуры ADI_FSS_SUPER_BUFFER первым полем идет структура ADI_DEV_BUFFER, и эти две структуры имеют общий адрес. Поэтому адрес супербуфера может быть использован в вызовах adi_dev_Read/adi_dev_Write, и следует понимать, что указатель на супербуфер может быть разыменован, чтобы получить доступ к его содержимому.
На каждой стадии процесса обработки, от файлового кэша FSD до PID, супербуфер может на всем пути предоставить подходящую информацию. Поля структуры супербуфера описаны в таблице ниже, где красным цветом показаны поля, относящиеся к файловому кэшу, зеленым цветом показаны поля драйвера FSD, и синим цветом показаны поля, относящиеся к драйверу PID. Поле запроса LBA (LBA Request) устанавливается драйвером FSD для запросов, поступающих как от кэша, так и FSD, или в драйвере PID для его внутренних запросов.
Поля, показанные черным цветом, устанавливаются инициирующим модулем, который также должен обнулить поля, связанные с модулями, которые не используются в предоставлении буфера. Например, внутренний запрос FSD на чтение директории заполняет нулями красные и синие поля.
Вот определение этой структуры:
typedef struct ADI_FSS_SUPER_BUFFER
{
ADI_DEV_1D_BUFFER Buffer;
struct adi_cache_block *pBlock;
u8 LastInProcessFlag;
ADI_FSS_LBA_REQUEST LBARequest;
ADI_SEM_HANDLE SemaphoreHandle;
ADI_FSS_FILE_DESCRIPTOR *pFileDesc;
ADI_DCB_CALLBACK_FN FSDCallbackFunction;
void *FSDCallbackHandle;
ADI_DCB_CALLBACK_FN PIDCallbackFunction;
void *PIDCallbackHandle;
} ADI_FSS_SUPER_BUFFER;
Здесь поля определены следующим образом:
Buffer |
Структура ADI_DEV_BUFFER, требуемая для перемещения данных. Обратите внимание, что это не поле указателя. Это поле должно быть установлено драйвером FSD только в том случае, когда запрос на передачу данных предназначен ему. |
SemaphoreHandle |
Хендл семафора для публикации после завершения перемещения данных. Это должно быть установлено драйвером FSD, если запрос передачи данных предназначен ему, и сюда должно быть записано значение хендла семафора, сохранное в данных экземпляра драйвера FSD. См. секции ниже для описания работы семафоров. |
LBARequest |
Структура ADI_FSS_LBA_REQUEST для связанного буфера. Драйвер FSD отвечает за установку значений в этой структуре независимо от того, был ли запрос сгенерирован внутри драйвера FSD, или передан из модуля файлового кэша. Если буфер формирует часть цепочки, и он может быть показан как несколько следующих друг за другом подбуферов, то FSD может опционально комбинировать запросы LBA, чтобы покрыть некоторое количество подбуферов. В этом случае значение SectorCount каждого подбуфера, который является представленным запросом LBA предыдущего подбуфера, должен быть обнулен. |
pBlock |
Используется в файловом кэше FSS. Это значение не должно изменяться драйвером FSD. Для внутренних передач драйвера FSD это должно быть установлено в NULL. |
LastinProcessFlag |
Используется в файловом кэше FSS. Это значение не должно изменяться драйвером FSD. Для внутренних передач драйвера FSD это должно быть установлено в FALSE. |
pFileDesc |
Используется в файловом кэше FSS. Это значение не должно изменяться драйвером FSD. Для внутренних передач драйвера FSD это должно быть установлено в NULL. |
FSDCallbackFunction |
Это поле должно быть установлено драйвером FSD в адрес callback-функции, вызываемой при событии завершения передачи данных. |
FSDCallbackHandle |
Это поле должно быть установлено драйвером FSD в адрес подходящей структуры для передачи как первый аргумент в функцию, определенную полем FSDCallbackFunction. |
PIDCallbackFunction |
Эти поля зарезервированы для использования драйвером PID.
|
PIDCallbackHandle |
Структура запроса LBA (LBA Request, ADI_FSS_LBA_REQUEST). Эта структура используется для передачи запроса на некоторое количество секторов, которое должно быть прочитано из устройства. Адрес инстанциации этой структуры должен быть отправлен драйверу PID либо командой ADI_PID_CMD_SEND_LBA_READ_REQUEST, либо командой ADI_PID_CMD_SEND_LBA_WRITE_REQUEST перед разрешением потока данных в PID. Структура определена в хедере FSS, файл adi_fss.h, следующим образом:
typedef struct ADI_FSS_LBA_REQUEST
{
u32 SectorCount;
u32 StartSector;
u32 DeviceNumber;
u32 ReadFlag;
ADI_FSS_SUPER_BUFFER *pBuffer;
} ADI_FSS_LBA_REQUEST;
Значение полей этой структуры показано в следующей таблице:
SectorCount |
Количество секторов в передаваемом блоке данных. |
StartSector |
Начальный сектор передаваемого блока в формате LBA. |
DeviceNumber |
Номер устройства в цепочке на шине. Эта информация доступна в момент монтирования драйвера FSD. |
ReadFlag |
Флаг, показывающий, что передаваемые данные относятся к операции чтения. Если это так, что значение этого поля должно быть равно 1. Если операция записи, то значение этого поля должно быть 0. |
pBuffer |
Адрес связанного подбуфера ADI_FSS_SUPER_BUFFER. |
Структура определения тома ADI_FSS_VOLUME_DEF. Эта структура содержит информацию, требуемую для монтирования подходящей файловой системы определенного тома. Она определена в хедере FSS, файл adi_fss.h, следующим образом:
typedef struct
{
u32 FileSystemType;
u32 StartAddress;
u32 VolumeSize;
u32 SectorSize;
u32 DeviceNumber;
} ADI_FSS_VOLUME_DEF;
Значение полей этой структуры показано в следующей таблице:
FileSystemType |
Уникальный идентификатор, определяющий тип файловой системы. Допустимые типы декларированы в анонимном перечислении заголовочного файла FSS (см. раздел "Типы файловых систем"). |
StartAddress |
Начальный сектор тома/раздела (volume/partition) в формате адресации секторов LBA. |
VolumeSize |
Количество секторов, содержащихся в томе. |
SectorSize |
Количество байт в секторе тома. |
DeviceNumber |
Количество устройств на шине. Например, драйвер Parallel ATA должен поддерживать 2 устройства в одной цепочке: Master (где DeviceNumber=0) и Slave (DeviceNumber=1). Это значение должно использоваться для заполнения поля DeviceNumber структуры запроса LBA. |
Структура запроса на позиционирование ADI_FSS_SEEK_REQUEST. Содержит параметры позиционирования и информацию о файле, в котором происходит позиционирование. Структура определена в заголовке FSS, файл adi_fss.h, следующим образом:
typedef struct
{
ADI_FSS_FILE_DESCRIPTOR *pFileDesc;
int whence;
long offset;
} ADI_FSS_SEEK_REQUEST;
Значение полей этой структуры показано в следующей таблице:
pFileDesc |
Указатель на файловый дескриптор FSS для файла, с которым происходит манипуляция. |
whence |
Флаг, определяющий начальную точку операции позиционирования: 0 позиционировать от начала файла, 1 позиционировать относительно текущей позиции, 2 позиционировать относительно конца файла. |
Offset |
Количество байт от начальной позиции позиционирования (смещение). |
Структура определения каталога ADI_FSS_DIR_DEF. Содержит информацию, относящуюся к открытой директории. Структура определена в заголовке FSS, файл adi_fss.h, следующим образом:
typedef struct
{
ADI_FSS_FILE_DESCRIPTOR *pFileDesc;
ADI_FSS_DIR_ENTRY entry;
u32 tellpos;
} ADI_FSS_DIR_DEF;
Значение полей этой структуры показано в следующей таблице:
pFileDesc |
Указатель на файловый дескриптор FSS для файла, с которым происходит манипуляция. |
entry |
Описание текущей записи. ADI_FSS_DIR_ENTRY это просто определение типа структуры dirent, который определен в заголовке dirent.h. FSD должен заполнить эту структуру данными, интерпретированными из специфики записи директории связанной файловой системы. |
tellpos |
Позиция файла текущей записи директории. |
Структура записи в каталоге ADI_FSS_DIR_ENTRY. Содержит информацию, относящуюся к текущей записи директории. Структура определена в заголовке FSS, файл adi_fss.h, следующим образом:
struct dirent
{
ino_t d_ino;
off_t d_off;
unsigned char d_namlen;
unsigned char d_type;
char d_name[256];
u32 d_size;
struct tm DateCreated;
struct tm DateModified;
struct tm DateLastAccess;
};
Значение полей этой структуры показано в следующей таблице:
d_ino |
Серийный номер файла (File Serial Number). |
d_off |
Смещение до следующей записи директории. |
d_namlen |
Длина имени записи минус завершающий символ \0. |
d_type |
Тип: DT_REG для обычного файла, или DT_DIR для подкаталога. |
d_name |
Имя записи, 256 символов максимум. |
d_size |
Размер файла в байтах. |
DateCreated |
Дата и время, когда был создан файл. |
DateModified |
Дата и время, когда файл был изменен последний раз. |
DateLastAccess |
Дата и время, когда к файлу был доступ последний раз. |
Структура для операции переименования ADI_FSS_RENAME_DEF. Определяет имена источника (source) и места назначения (target) операции переименования. Если источник это файл, и цель это директория, то файл просто перемещается в указанную директорию. Структура определена в заголовке FSS, файл adi_fss.h, следующим образом:
typedef struct
{
ADI_FSS_FULL_FNAME *pSource;
ADI_FSS_FULL_FNAME *pTarget;
} ADI_FSS_RENAME_DEF;
Значение полей этой структуры показано в следующей таблице:
pSource |
Указатель на связанный список, содержащий путь исходного файла/директории. |
pTarget |
Указатель на связанный список, содержащий путь места назначения файла/директории. |
[Типы файловых систем]
Следующее перечисление дает уникальные значения для использования в FSD, чтобы идентифицировать поддерживаемую им файловую систему:
enum
{
ADI_FSS_FSD_TYPE_UNKNOWN = 0,
ADI_FSS_FSD_TYPE_FAT = 1,
ADI_FSS_FSD_TYPE_CDDATA_MODE1 = 2,
ADI_FSS_FSD_TYPE_CDDATA_MODE2 = 3,
ADI_FSS_FSD_TYPE_CDAUDIO = 4,
ADI_FSS_FSD_TYPE_UDF = 5,
ADI_FSS_FSD_TYPE_YAFFS = 6,
};
Здесь перечислены следующие файловые системы:
ADI_FSS_FSD_TYPE_UNKNOWN |
Неизвестная файловая система. |
ADI_FSS_FSD_TYPE_FAT |
FAT12, FAT16, FAT32. |
ADI_FSS_FSD_TYPE_CDDATA_MODE1 |
Компакт-диск (CD) ISO 9660, формат желтая книга (Yellow Book Data) для Mode 1 и Mode 2 Form 1. |
ADI_FSS_FSD_TYPE_CDDATA_MODE2 |
Компакт-диск (CD) ISO 9660, формат желтая книга (Yellow Book Data) для Mode 2 Form 2. |
ADI_FSS_FSD_TYPE_CDAUDIO |
Компакт-диск (CD) ISO 9660, формат красная книга (Red Book Data) для данных CD Audio. |
ADI_FSS_FSD_TYPE_YAFFS |
"Немного другая" файловая система FLASH (Yet another Flash File System) от Aleph One для памяти NAND flash. |
[Открытие и конфигурирование драйвера FSD]
В этом разделе описаны настройки конфигурации по умолчанию для драйвера FSD и дополнительные конфигурационные настройки, которые должно сделать приложение клиента.
Процедура открытия драйвера. Служба файловой системы Analog Devices (File System Service, FSS) автоматически откроет подходящий драйвер FSD вызовом функции adi_dev_Open() при детектировании присутствия тома с данными. Аргументы для этого вызова предоставлены структурой ADI_FSS_DEVICE_DEF (см. выше описание этой структуры).
После этого драйвер FSD отправит команду ADI_FSD_CMD_GET_FILE_SYSTEM_SUPPORT с одним из значений из перечисления, чтобы определить тип файловой системы тома (см. выше секцию "Типы файловых систем"; для обычных дисков с возможностью чтения и записи это чаще всего будет значение ADI_FSS_FSD_TYPE_FAT). Драйвер FSD должен сравнить возвращенное значение со своим внутренним значением и возвратить при совпадении ADI_FSS_RESULT_SUCCESS.
Если вызов был не успешен, то драйвер FSD будет закрыт, иначе ему должны далее поступить команды в следующем порядке:
1. ADI_DEV_CMD_SET_DATAFLOW_METHOD. Для драйверов устройств такого рода важно установить метод потока ADI_DEV_MODE_CHAINED (драйвер FSD не поддерживает другие методы потока данных).
2. ADI_DEV_CMD_TABLE. Здесь передается адрес таблицы конфигурации, определенной пользователем, и этот адрес присваивается полю pConfigTable структуры ADI_FSS_DEVICE_DEF, переданной драйверу FSD для конфигурирования.
3. ADI_FSD_CMD_SET_PID_HANDLE. Хендл устройства (Device Handle) низкоуровневого драйвера PID передается драйверу FSD, чтобы позволить ему делать вызовы драйвера устройства PID. Драйвер FSD должен определить в этом месте поддерживаемую PID ширину элемента данных (Data Element Width), и информацию о том, поддерживает ли PID фоновую передачу данных (фактически это DMA).
4. ADI_FSD_CMD_MOUNT_VOLUME. В завершение адрес структуры ADI_VOLUME_DEF передается драйверу FSD вместе со всей требуемой информацией для монтирования подходящей файловой системы на носителе данных (media).
Определение структур конфигурации. Драйвер FSD должен определить значения по умолчанию для структуры ADI_FSS_DEVICE_DEF и таблицы конфигурации ADI_DEV_CMD_VALUE_PAIR в файле заголовка {fsd-ident}.h. Эти данные должны быть защищены макросом _{FSD-IDENT}_DEFAULT_DEF_ (если такой макрос не определен, то и определения отсутствуют). При определении таким способом структур конфигурации, если пользователь ничего не делает, то драйвер FSD должен определить эти структуры сам, и не должно быть проблем с дублированием символов. Например:
#if defined(_{FSD-IDENT}_DEFAULT_DEF_)
static ADI_FSS_DEVICE_DEF {FSD_IDENT}_Def =
{
0,
&ADI_FAT_EntryPoint,
NULL,
NULL,
ADI_DEV_DIRECTION_BIDIRECTIONAL,
NULL
};
#endif
В приведенном выше примере таблица конфигурации по умолчанию не требуется, так что её адрес установлен на NULL в структуре ADI_FSS_DEVICE_DEF.
Обратите внимание, что служба FSS будет пытаться применить заданную букву по умолчанию для точки монтирования диска для этого устройства, и сохранять эту букву при смене носителя данных. Если буква по умолчанию не требуется, то это значение можно установить в NULL. Если запрашиваемая буква недоступна на любой стадии, то служба FSS назначит следующую доступную букву диска, начиная с буквы "c".
Настройки по умолчанию. Для драйвера FSD нет настроек по умолчанию.
Дополнительные требуемые настройки конфигурации. В дополнение к параметрам, которые можно изменить, драйвер FSD требует от приложения указать дополнительную конфигурационную информацию, перечисленную в таблице ниже.
Элемент |
Возможные значения |
Command ID |
Метод потока данных |
Поддерживается только метод ADI_DEV_MODE_CHAINED (см. выше секцию "Методы потока данных"). |
ADI_DEV_CMD_SET_DATAFLOW_METHOD |
Файловая система |
Уникальный идентификатор файловой системы. |
ADI_FSD_CMD_GET_FILE_SYSTEM_SUPPORT |
Установка хендла драйвера PID |
Хендл устройства (Device Handle) драйвера физического интерфейса (Physical Interface Driver, PID). |
ADI_FSD_CMD_SET_PID_HANDLE |
Монтирование тома |
Номер сектора как начальная позиция требуемого раздела диска. |
ADI_FSD_CMD_MOUNT_VOLUME |
Получение размера блока |
Адрес переменной u32 для сохранения результата. |
ADI_FSD_CMD_GET_BLOCK_SIZE |
Получить callback-функцию |
Адрес ячейки памяти для сохранения адреса callback-функции. |
ADI_FSD_CMD_GET_CALLBACK_FUNCTION |
Замечания, касающиеся аппаратуры. Для драйвера FSD нет замечаний, связанных с аппаратной конфигурацией. Однако нижележащий драйвер физического интерфейса (Physical interface driver, PID) имеет определенные требования к аппаратуре. За подробностями обращайтесь к конфигурации на соответствующий драйвер PID.
[Ссылки]
1. GENERIC FSD DESIGN DOCUMENT site:analog.com. 2. Драйвер интерфейса (PID) для службы файловой системы (FSS). 3. VDK: менеджер драйверов устройств. 4. VDK: менеджер прерываний. 5. Служба файловой системы Blackfin. |