Главная страница Межпроцессное взаимодействие (состязание) ние контроллера диска, если считывать из него данные, а при записи в него данных передает команду контроллеру. Кроме того, часто сам факт записи данных в порт ввода/вывода приводит к выполнению некоторых действий, независимо от характера передаваемых данных. Например, это так для регистра команд АТ-совместимого контроллера. При работе с ним параметры заносятся в младшие регистры, а в регистр команд помещается код операции. Сигналом начала операции является факт записи данных в регистр команд. В дополнение, этот случай является иллюстрацией ситуации, когда назначение регистров зависит от режима работы. В приведенном в таблице примере режим выбирается шестым битом шестого регистра (см. табл. 3.7). Данные, записываемые или считываемые в регистры 3-5, а также младшие четыре бита регистра 6 по-разному интерпретируются в зависимости от значения бита LBA. Теперь рассмотрим, как при помощи com out команда передается контроллеру. Прежде чем менять какие-либо регистры, программа узнает, занят ли контроллер, считывая бит STATUS BSY. Здесь важна скорость, и так как контроллер обычно должен быть свободен или станет свободен скоро, здесь используется активное ожидание. Поэтому в начале кода функции вызывается команда waitfor, тестирующая значение бита STATUS BSY. Для повышения скорости эта команда реализована в виде макроса, который один раз проверяет значение бита, и только если контроллер занят, вызывает функцию ожидания. Это позволяет избежать накладных расходов на вызов функции в большинстве случаев. В тех редких ситуациях, когда контроллер занят, вызывается функция w waitfor, в цикле проверяющая значение бита занятости до тех пор, пока контроллер не освободится или не истечет заданный интервал времени. В результате, если контроллер свободен, будет возвращено значение истина с минимальной задержкой. Если контроллер занят, будет возвращено значение истина , когда удалось дождаться его освобождения, и ложь в другом случае. Подробнее мы расскажем об этом, когда займемся самой функцией w waitfor. Контроллер способен обслуживать более одного диска, поэтому, когда он освободится, в регистры записывается байт, выбирающий привод, головку и режим работы, и waitfor вызывается снова. Иногда приводу не удается выполнить команду или правильно вернуть код ошибки, в конце концов, это механическое устройство, которое может заесть или просто сломаться, и для страховки отправляется сообщение задаче таймера, с целью запланировать вызов подпрограммы, которая разблокирует драйвер. Следом за этим команда передается контроллеру, для чего сначала все параметры записываются в разные регистры, а затем в регистр команд кладется код самой команды. Последний шаг является критической секцией, поэтому он обрамлен вызовами процедур lock и unlock, которые, соответственно, запрещают и разрешают прерывания. Следующие несколько функций, которые мы рассмотрим, меньше по объему. Мы уже отмечали, что w finish вызывает w need reset, когда счетчик сбоев превышает половину от максимального числа попыток (MAX ERRORS). Кроме того, та же функция вызывается в том случае, когда приходится ожидать готовности или прерывания диска. Работа функции w need reset сводится к тому, чтобы устано- вить переменную state для каждого диска в массиве wini, чтобы при следующем обращении была повторена инициализация. Функция w do close в отношении обычного жесткого диска очень проста. Если необходима поддержка CD-ROM или других приводов со сменными носителями, подпрограмма должна быть усложнена, в нее следует добавить код, отпирающий дверцу привода или выбрасывающий носитель, в зависимости от того, какие действия поддерживает оборудование. Функция com simple отправляет команду контроллеру и немедленно завершается, не выполняя обмен данными. В эту категорию попадают команды, которые служат для идентификации диска, установки некоторых параметров и повторной калибровки привода. Когда com out подготавливает задачу таймера к возможному сбою, она передает адрес подпрограммы w timeout, чтобы задача таймера вызвала ее, когда истечет заданный период времени. Обычно диск успевает выполнить задание раньше, после чего присваивает переменной w command значение CMD IDLE. Обнаружив это значение, w timeout определяет, что команда выполнена, и завершается. Если команда чтения или записи не успела завершиться, имеет смысл уменьшить объем запросов на чтение или запись данных. Это делается в два этапа, для чего количество запрашиваемых секторов уменьшается сначала до 8, затем до 1. Во всех случаях истечения времени ожидания на экран выводится сообщение и для повторной инициализации всех приводов вызывается функция w need reset. Кроме того, вызывается функция interrupt, которая отправляет сообщение задаче жесткого диска, имитируя аппаратное прерывание, которое должно произойти по завершении дисковой операции. Когда требуется сброс, вызывается w reset. Эта подпрограмма использует одну из функций, входящих в драйвер часов, milli delay. Сначала w reset делает начальную задержку, чтобы дать приводу время вернуться в исходное состояние после предыдущих действий. Затем апробируется бит регистра управления контроллера диска, то есть сначала на заданное время бит устанавливается в 1, а затем возвращается в 0. Далее вызывается waitfor, чтобы позволить диску прийти в состояние готовности. Если сброс не завершился успехом, на экран выводится сообщение и возвращается код ошибки. Сделавшей вызов программе остается решить, как в этом случае поступить. Команды, затрагивающие обмен данными с диском, обычно завершаются генерацией прерывания, которое отправляет сообщение обратно драйверу. Фактически прерывание генерируется каждый раз, когда считывается или записывается сектор. Таким образом, после того как дана команда, всегда вызывается w intr wait. В свою очередь, эта подпрограмма в цикле обращается к receive, игнорируя содержимое сообщений. Цикл завершается, когда приходит сообщение, устанавливающее w status в значение не занято . По получении подобного сообщения проверяется состояние запроса. Это еще одна критическая секция, поэтому, чтобы гарантировать, что во время ее обработки не произойдут новые прерывания, используются команды lock и unlock. Мы встретили несколько мест с подставленным макросом waitfor, означающим активное ожидание определенного значения бита занятости регистра состояния контроллера диска. Этот макрос сначала проверяет бит и, если контроллер оказался занят, вызывает функцию w waitfor. В свою очередь, она устанавливает таймер при помощи milli start и входит в цикл, поочередно проверяющий регистр состояния и таймер. Если интервал времени истекает, вызывается w need reset, чтобы обеспечить сброс контроллера при следующем обращении к диску. Параметр TIMEOUT, используемый функцией w waitfor, равен 32 с. Аналогичный параметр, WAKEUP, нужный при планировании пробуждения драйвера по сигналу задачи часов, равен 31 с. Это очень большие периоды времени для активного ожидания, если сравнить их с обычным процессом, которому на работу дается 100 мс. Такие большие задержки обусловлены существующими стандартами для АТ-совместимых дисков. Согласно этим стандартам, диску может потребоваться до 31 с, чтобы разогнаться. Конечно, на практике такое время требуется только в самом худшем случае, а разгон диска в большинстве систем происходит при включении питания или после длительных периодов бездействия. MINIX - развивающаяся система. Возможно, когда будет добавлена поддержка CD-ROM (или других устройств, у которых раскрутка происходит часто), возникнет необходимость в новом способе обработки задержек. Функция w handler играет роль обработчика прерываний. Адрес этой функции записывается функцией wjdentify в таблицу дескрипторов прерываний (IDT) при первом запуске драйвера. Когда генерируется прерывание, регистр состояния контроллера диска копируется в переменную w status, после чего вызывается функция ядра interrupt, чтобы повторно запланировать задачу жесткого диска. Конечно, в тот момент, когда приходит прерывание от жесткого диска, его задача уже находится в приостановленном состоянии в результате предшествующего вызова receive, который сделала подпрограмма w intr wait после инициирования дисковой операции. Последняя функция в файле at wini.c это w geometry. Она возвращает максимальное значение номеров цилиндров, дорожек и секторов для выбранного жесткого диска. В отличие от RAM-диска, где эти значения имитировались, здесь в эти числа вложен реальный смысл. 3.7.5. Работа с дисководом для гибких дисков Драйвер флоппи-дисковода (для гибких дисков) сложнее, чем драйвер жесткого диска, а его код больше. Это на первый взгляд парадоксально, так как механизмы дисковода для гибких дисков должны быть проще, чем механизмы винчестера, но контроллер первого проще и требует к себе больше внимания от операционной системы. Помимо того, некоторые сложности вносит сменный носитель. В текущем разделе мы рассмотрим некоторые вопросы, которые могут оказаться полезными для программиста, имеющего дело с гибкими дисками. В основных деталях код драйвера сходен с кодом драйвера жесткого диска. Детально же разбирать код, ввиду его сложности, мы не будем. Одна из проблем, с которыми мы не столкнемся, работая с флоппи-приводами, - это необходимость поддерживать много типов контроллеров, что было
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |