Главная страница Межпроцессное взаимодействие (состязание) 3.7.4. Реализация драйвера жесткого диска в MINIX Жесткие диски часто называют винчестерами . Существует несколько историй о том, как произошло это название. Такое кодовое название имел проект IBM, разрабатывавшей технологию, в которой магнитные головки парят над поверхностью вращающегося диска, опираясь на тонкую прослойку воздуха. Одно из толкований названия в том, что у первых моделей было два герметически закрытых корпуса - модуля данных, фиксированный (30 Мбайт) и сменный (тоже 30 Мбайт). Предположительно, это напомнило разработчикам винчестер 30-30 , который фигурирует во многих вестернах*. Каково бы ни было происхождение названия, основа технологии остается той же самой, хотя типичные жесткие диски современных микрокомпьютеров гораздо миниатюрнее и хранят намного большие объемы данных, чем их 14-дюймовый прототип начала 1970-х. Задача кода в файле wini.c в том, чтобы скрыть реальный драйвер жесткого диска от остального ядра. Это позволяет включать в ядро несколько драйверов, выбирая нужный при загрузке. Позже ядро можно перекомпилировать, оставив только тот драйвер, который необходим. В файле wini.c имеется только одно описание данных, задающее массив hdmap. Этот массив связывает имена драйверов с адресами функций. Он инициализируется компилятором и содержит столько элементов, сколько необходимо для драйверов жестких дисков, подсоединенных при компиляции в файле include/minix/config.h. Используется он в функции winchester task, имя которой помещается в массив task tab, необходимый при запуске ядра. Когда вызывается функция winchester task, она сначала пытается найти переменную окружения с именем hd при помощи системной функции, работающей так же, как и аналогичные механизмы в обычных программах на языке С, через считывание переменных, установленных монитором начальной загрузки. Если переменная hd не задана, используется первая запись из массива (то есть драйвер по умолчанию). Соответствующая выбранному драйверу функция вызывается косвенно, по адресу, хранящемуся в массиве. В последующем разделе мы будем рассматривать работу функции at winchester task, адрес которой в стандартной версии MINIX находится в первой ячейке массива hdmap. Код драйвера жесткого диска стандарта AT содержится в файле at wini.c. Это запутанный драйвер для такого же сложного устройства. Три страницы кода занимают макроопределения, необходимые для обращения к регистрам контроллера, битам состояния, структурам данных, а также прототипы функций. Как и в случае с драйверами других блочных устройств, в драйвере винчестера создается структура типа driver, хранящаяся в переменной w dtab. Эта структура заполняется адресами функций, которые и выполняют все основные задачи драйвера. Код большинства функций находится в файле at wini.c, но, так как для жесткого диска не нужны специальные действия для завершения работы, поле dr cleanup Согласно Microsoft Computer Dictionary, описываемый диск имел емкость 30 Мбайт и время доступа 30 мс (аналогия с патронами Winchecter .ЗО-.ЗО , калибром 0,3 дюйма - 7,62 мм и весом 30 гран - 1,9 г). - Примеч. ред. структуры содержит ссылку на функцию nop cleanup в файле driver.c. Последняя используется всеми драйверами, которые не нуждаются в особых действиях для завершения. Точка входа в драйвер - это функция at winchester task, которая выполняет аппаратно-зависимую инициализацию и передает управление в главный цикл (файл driver.c). Главный цикл исполняется бесконечно, обслуживая поступаюшие запросы, вызывая функции, адреса которых записаны в полях структуры w dtab. Итак, теперь мы имеем дело с реальным электромеханическим устройством хранения данных, поэтому для инициализации драйвера необходимо выполнить немало действий. Различные параметры, относящиеся к жесткому диску, хранятся в массиве wini. Как часть политики отложенной инициализации функция init params, вызываемая при инициализации ядра, не выполняет ничего такого, что может привести к сбою, то есть не делает никаких обращений к самому дисковому устройству. Основная ее задача - поместить в массив wini некоторую информацию о логической конфигурации жесткого диска. Эти сведения извлекаются при помощи BIOS из CMOS-памяти, которая используется некоторыми компьютерами для хранения основных параметров конфигурации. Код BIOS выполняется в самом начале работы компьютера, до того как начнется первый этап процесса загрузки MINIX. Невозможность получить сохраненные в CMOS параметры необязательно означает сбой. У некоторых современных дисков эта информация может быть получена от самого диска. После вызова главного цикла некоторое время ничего не происходит, до тех пор пока не будет сделана попытка обращения к жесткому диску. Затем драйвер получает запрос DEV OPEN и для его обработки косвенно вызывает функцию w do open. В свою очередь, она вызывает w prepare, чтобы определить, корректно ли указано устройство, а далее, чтобы выяснить тип устройства и инициализировать некоторые дополнительные параметры, вызывает wjdentify. Счетчик в массиве wini нужен для того, чтобы определить, является ли текущий вызов первым после запуска MINIX. После каждого вызова значение счетчика увеличивается. Если обнаружено, что это первая операция - DEV OPEN, вызывается функция partition. Следующая функция, w prepare, принимает один целочисленный аргумент, device, равный младшему номеру устройства, и возвращает указатель на структуру device, которая содержит информацию об адресе и размере устройства. (В языке С идентификаторы, означающие имя структуры, разрешено использовать в качестве имени переменной.) Тип устройства (является ли оно диском, разделом или подразделом) можно определить по его младшему номеру. После того как w prepare завершает свою работу, нет необходимости вызывать никакие записывающие или считывающие данные функции, связанные с разбиением на разделы. Как вы могли увидеть, w prepare вызывается в ответ на запрос DEV OPEN. Это также является одной из частей трехэтапного цикла подготовка/планирование/завершение, применяемого во всех операциях обмена данных. В этом контексте важно, чтобы переменная w count инициализировалась нулевым значением. Программно совместимые со стандартом АТ диски находятся в употреблении довольно давно, и функция wjdentify должна определить, какой из появившихся за годы вариантов жесткого диска используется. На первом шаге выясняется, доступны ли для чтения и записи порты ввода/вывода, которые должны существовать для всех дисковых контроллеров одного семейства. Если эта проверка завершилась успехом, адрес обработчика прерываний жесткого диска помещается в таблицу дескрипторов прерываний и контроллеру прерываний выдается инструкция отвечать на прерывания от устройства. Затем контроллеру диска дается команда ATAJDENTIFY. Если она завершилась успешно, извлекается различная информация, включая строку-идентификатор модели диска и параметры физических секторов, головок и цилиндров. (Заметьте, что физическая конфигурация в действительности может не совпадать с реальной физической структурой, но у нас нет другой альтернативы, кроме как верить в то, что заявляет диск.) Кроме того, эти сведения содержат информацию о том, поддерживает ли диск линейную адресацию блоков (Linear Block Addressing, LB А). Если данная функция поддерживается, драйвер вправе игнорировать цилиндры, дорожки и секторы и адресовать секторы диска просто по их абсолютным номерам, что намного проще. Как уже было упомянуто ранее, не исключена ситуация, когда init params окажется не в состоянии получить информацию о конфигурации диска из BIOS. Если такое случилось, код на следующих строках пытается сформировать подходящий набор параметров, основанных на тех данных, которые удалось прочитать с самого диска. Основная идея состоит в том, что номера цилиндра, дорожки и сектора не должны превышать соответственно 1023, 255 и 63, то есть учитывается заложенное в структуры данных BIOS ограничение на количество битов, выделяемых под эти параметры. Если команда ATAJDENTIFY возвращает отрицательный результат, это может просто означать, что вы столкнулись со старой моделью диска, который не поддерживает саму команду. В таком случае все, что мы имеем, - это параметры логической конфигурации, ранее прочитанные функцией init params. Если они корректны, то они и записываются в поля структуры wini, в противном случае сообщается об ошибке и система отказывается работать с диском. Наконец, чтобы считать адреса в байтах, в MINIX используется переменная u32 t. Максимальный объем устройства (в секторах), с которым умеет работать драйвер, ограничен произведением количества цилиндров, головок и секторов. На момент написания этой книги диски объемом 4 Гбайт мало распространены, но опыт показывает, что программное обеспечение должно проверять подобные ограничения, независимо от того, что на сегодняшний день такие тесты могут показаться излишними. Затем базовый адрес и размер всего диска записываются в массив wini и вызывается (дважды при необходимости) функция w specify, передающая обратно контроллеру его рабочие параметры. В завершение имя устройства и идентифицирующая его строка, определенная при помощи identify (для усовершенствованных устройств), или параметры цилиндров и головок, определенные BIOS (для старых устройств), выводятся на консоль. Функция w name возвращает указатель на строку, содержащую имя устройства: at-hdO , at-hd5 , at-hdlO или at-hdl5 . Функция w specify, в дополнение
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |