:: СОДЕРЖАНИЕ НОМЕРА
:: Газетные рубрики
:: АВТОРЫ
:: Поиск
:: Поддержка проекта
Webmoney:
|
:: №21 (14.10.2004) Просмотров: 8818
Автор: Влад Сотников. Рубрика: Читатель читателю. Номер: №21 (14.10.2004). Spectrum и винчестерПредисловие4 года назад в электронном журнале ZxNews (#54) я опубликовал статью о своем опыте программирования винчестера. Было получено множество откликов, из чего стало ясно, что представленная мной информация оказалась актуальной. Многие люди благодаря статье написали программы, которые используют скрытые (а потому более действенные) возможности винчестера. Сейчас, спустя несколько лет, я смотрю на статью несколько по-другому: что-то в ней оказалось не востребовано, чему-то нужно было уделить больше внимания. Поэтому это изложение является переработанной версией моей предыдущей статьи, в которой, в первую очередь, больше внимания будет уделено IDE-контроллеру фирмы (c) Nemo. 1. Работа с винчестером на Spectrum’е 1.1. Введение Данная статья посвящена программированию жесткого диска, называемого также «винчестер», на компьютере Spectrum. Винчестер - это неотъемлемая составляющая любого компьютера, особенно в настоящее время, когда размер информации в сотни, а то и в тысячи раз превышает размеры оперативной памяти компьютеров. Такие носители информации, как гибкие диски, теряют свою актуальность. Но, несмотря на это, Спектрум долгое время обходился без винчестера, и появился он на нем не так давно. К сожалению, адаптация винчестера к системе TR-DOS не позволяет использовать большую часть его возможностей и поэтому, работая с ним напрямую, через порты, можно не только в несколько раз увеличить скорость работы с жестким диском, но и превратить его в аналог оперативной памяти компьютера, как, собственно, и сделано на таком компьютере, как PC. 1.2. Обращение к винчестеру Итак, к винчестеру можно обращаться двояко. Первый вариант - обращение через драйвер. На PC это такая программка, которая позволяет видеть винчестер как склад для размещения файлов. На Sorpion’е таким драйвером можно назвать ПрофПЗУ 4.01, которое представляет винчестер как набор образов TR-DOS дискет. Образ подключается к диску A, B, C или D через теневой монитор, и далее программа работает с одним из этих носителей, не подозревая, что вместо гибкого диска она общается с винчестером. Такой подход имеет некоторые недостатки. В частности, поддерживается только обращение к TR-DOS через подгрограмму #3D13 (естественно!), а всяческие обращения типа #3D2F приводят к тому, что программа на TR-DOS образе винчестера не может работать. Но речь не об этом. Кроме контакта через #3D13 теневой монитор предлагает обращение к жесткому диску через команду RST 8. Я не буду ее здесь описывать, принципы ее работы можно найти в книге «SMUC, инструкция по подключению и работе, v1.2» или по адресу: http://scorpion.ru/spectrum/files/smuc.zip. Но второй вариант всего лишь увеличивает скорость чтения и записи данных, и поэтому полноценным быть назван не может. Производители другого (и более дешевого) IDE-контроллера (Nemo-контроллера) пошли по другому пути: в качестве основной операционной системы используется Is-Dos. Однако чтобы подключить хранящийся на винчестере TR-DOS образ к устройству A,B,C или D, нам опять-таки потребуется специальное ПЗУ. Другой способ обращения к винчестеру - прямая работа с секторами. Здесь мы не ограничены возможностями, предоставляемыми нам драйверами-программами, вшитыми в ПЗУ. Мы можем читать и писать любой сектор винчестера, включая и boot-сектор (MBR). Кроме того, мы можем работать с подразделами, содержащими собственную файловую структуру (FAT, NTFS), и получить, таким образом, доступ к разделам, созданным операционными системами других компьютеров (например, MS-DOS, WINDOWS, LINUX и прочими). Именно об этом способе и пойдет дальнейшая речь в нашей статье. 1.3. Устройство винчестерах Винчестер - это устройство, имеющее внутренний контроллер чтения, записи и обработки информации. Таким образом, компьютеру нет необходимости раскручивать диск и выполнять подобные процедуры - их берет на себя контроллер. Собственно программирование жесткого диска - это передача ему команд, а также передача/прием от него информации. Винчестер имеет следующую логическую внутреннюю структуру: на нем существует некоторое количество цилиндров. В каждом цилиндре имеется определенное количество головок. И каждая головка имеет некоторое количество секторов. Если перемножить все эти значения, то получим общее количество секторов (по 512 байт) на жестком диске. Разделив это число на 2, мы узнаем его объем. Само собой разумеется, что логическая структура винчестера не имеет ничего общего с его реальными физическими параметрами. То есть 16 головок вовсе не значит, что их в винчестере действительно 16. Обычно физических головок 3-4, а количество секторов на каждой дорожке варьируется, как и на компакт-диске. Тем не менее, общаться с жестким диском необходимо через его логические параметры, за исключением случая, когда адресация задается в режиме LBA (Logical Block Addressing), то есть винчестеру вместо цилиндра/головки/сектора сразу указывается относительный адрес. 1.4. Терминология Перед началом описания давайте договоримся о терминах, которые будут мной употребляться в этой статье. - Логический адрес: состоит из 3-х значений: номера цилиндра, номера головки и номера сектора. - Относительный адрес: 4-байтный адрес относительно н нача винчестера. Используется в LBA режиме. В режиме логической адресации преобразуется в логический адрес подпрограммой SET_. На Спектруме в пределах 1.9 Гигабайт используются только 3 байта. - Сектор: на винчестере он равен 512 байтам. Поэтому под любым сектором, упоминаемым мной в статье, необходимо понимать 512 байт. 1.5. Обращение к регистрам на Spectrum’e Управление контроллером происходит посредством регистров. Каждому регистру в IDE-контроллере соответствует порт. Он будет указываться рядом с названием регистра. В контроллере SMUC эти порты находятся в адресном пространстве TR-DOS, поэтому обращение к ним должно происходить с включенным ПЗУ TR-DOS. Поэтому запись значения в порт для этого контроллера будет выглядеть следующим образом: ;OUT register A. ;in: [BC] - номер порта ; [A] - значение, записываемое ; в порт. OUT_A LD IX,#3FF0 PUSH IX JP #3D2F Дело в том, что при обращении к этой области памяти автоматически включается ПЗУ TR-DOS и выполняется команда OUT (C),A. Соответственно, чтение: ;IN register A. ;in: [BC] - номер порта. ;out: [A] - значение, считанное ; из порта. IN_A LD IX,#3FF3 PUSH IX JP #3D2F Здесь то же самое, только выполняется команда IN A,(C). В случае с IDE-контроллером NEMO (и со Scorpion’ом с открытыми портами TR-DOS) все обстоит намного проще: эти же команды будут иметь следующий вид: ;OUT register A. ;in: [BC] - номер порта ; [A] - значение, записываемое ; в порт. OUT_A OUT (C),A RET ;IN register A. ;in: [BC] - номер порта. ;out: [A] - значение, считанное ; из порта. IN_A IN A,(C) RET В последующих примерах мы будем обращаться к этим подпрограммам. Зная их, можно производить чтение и запись в порты (регистры) винчестера. 1.6. Описание регистров Регистр Команд (#FFBE / #F0) Регистр только для записи. Этот регистр содержит код команды, посылаемой винчестеру. Выполнение команды начинается сразу после записи этого регистра. Так, известно, что команда #E6 останавливает жесткий диск. Пишем: LD A,#E6 LD BC,#FFBE ;#F0 для Nemo CALL OUT_A RET Ваш винчестер должен остановиться. Регистр Состояния (#FFBE / #F0) Этот регистр содержит состояние накопителя. Содержимое этого регистра обновляется после завершения каждой команды. Соответственно, биты этого регистра: - BSY (Занято). Этот бит устанавливается сразу после передачи команды винчестеру и сбрасывается только после того, как он эту команду выполнит. То есть установленный бит сигнализирует о том, что жесткий диск выполняет команду и вас не «слышит». - DRDY (Готовность Накопителя). Этот бит установлен в том случае, если винчестер готов принять команду. - DWF (Запрет Записи на Диск). Бит указывает текущее состояние запрета записи (?). - DSC (Установка Дисковода Завершена). Бит указывает, что головки дисковода установлены на дорожку. - DRQ (Запрос Данных). Бит указывает, что дисковод готов к передаче слова или байта данных между ЭВМ и накопителем. - CORR (Исправленные Данные). Бит указывает, что при чтении данных произошла коррекция и данные были исправлены. - IDX (Индекс). Бит устанавливается при каждом обороте диска. - ERR (Ошибка). Бит указывает, что в течение выполнения предыдущей команды произошла ошибка. Дополнительная информация относительно причины ошибки содержится в Регистре Ошибки. Самыми существенными для нас являются биты BSY, DRQ и ERR. При подаче команды на винчестер необходима следующая последовательность действий: 1. Подается команда (через Регистр Команд). 2. Ждем снятия сигнала BSY. 3. Смотрим бит ERR. Если он установлен - читаем Регистр ошибок и обрабатываем ошибку. Напишем подпрограмму, которая будет ожидать сброса сигнала BSY: ]NO_BSY LD BC,#FFBE ;#F0 для Nemo CALL IN_A RLCA RET NC JR NO_BSY Мы крутимся в цикле до тех пор, пока сигнал BSY не будет снят. Каждая команда должна завершаться обращением к этой подпрограмме. Подпрограмма проверки ошибки: ERR_ LD BC,#FFBE ;#F0 для Nemo CALL IN_A RRCA RET Если на выходе установлен флаг переноса, то команда была выполнена с ошибкой. И наш предыдущий пример, останавливающий винчестер, будет выглядеть следующим образом: LD A,#E6 LD BC,#FFBE ;#F0 для Nemo CALL OUT_A CALL NO_BSY CALL ERR_ JP C,ERROR RET Итак, теперь известно, как полноценно послать команду на винчестер. Ниже я привожу подпрограмму, которая это делает. ;HDD Send Command. ;IN: [A] - код команды. ;OUT: CY - Операция выполнена с ошибкой. HDSC LD BC,#FFBE ;#F0 для Nemo CALL OUT_A ;послали команду. CALL NO_BSY ;ждем выполнения. JP ERR_ ;смотрим, ;нет ли ошибок. Приведем также подпрограмму, которая будет необходима нам для чтения/записи данных на винчестер (она понадобится нам в следующих главах этой статьи). Выход из подпрограммы происходит тогда, когда винчестер готов считывать/записывать информацию: W_DRQ LD BC,#FFBE ;#F0 для Nemo CALL IN_A BIT 3,A RET NZ JR W_DRQ Следующие регистры указывают номера цилиндра, головки и сектора, с которыми происходит операция. Так, при чтении этих регистров мы узнаем место, где находится головка. При записи в эти регистры других значений головка не меняет своего положения, но при выполнении команды чтения/записи она позиционируется в соответствии со значениями, заданными в этих регистрах. Регистр Цилиндра (старшая часть) (#FDBE / #B0) Этот регистр содержит старшую часть начального номера цилиндра для любой дисковой операции. После выполнения команды этот регистр модифицируется, и всегда отражает текущий номер цилиндра. Старшие разряды номера цилиндра должны быть загружены в этот регистр. Регистр Цилиндра (младшая часть) (#FCBE / #90) Этот регистр содержит младшие 8 бит начального номера цилиндра для любой дисковой операции. После выполнения команды этот регистр модифицируется, и всегда отражает текущий номер цилиндра. Регистр Номера Сектора (#FBBE / #70) Этот регистр содержит начальный номер сектора для любой операции с данными. Номер сектора может быть от 1 до максимального числа секторов на дорожку. Регистр Накопителя/Головки (#FEBE / #D0) Этот регистр содержит номер головки и накопителя. Содержимое этого регистра задает номер накопителя и номер головки при выполнении команды Initialize Drive Parameters. - DRV - бит выбора накопителя. Если DRV=0, то выбран накопитель 0, если DRV=1, то выбран накопитель 1. Это очень интересный бит. Он задает устройство slave/master, с которым должен работать компьютер. Так, если мы хотим с основного винчестера переключиться на второй, параллельно подключенный, то нам необходимо лишь установить этот бит и записать число в регистр. И все последующие команды будут работать с выбранным устройством. - LBA - бит указывает, включен или выключен режим LBA. - HS3...HS0 содержат двоичный код номера головки (начиная с нуля), которая будет выбрана. Например, если HS3...HS0=%0011, то будет выбрана головка 3. HS3 - старший бит. После завершения команды этот регистр модифицируется и всегда содержит текущий номер выбранной головки. Регистр Счетчика Секторов (#FABE / #50) Этот регистр содержит число передаваемых секторов данных при операциях чтения/записи. Значение ноль соответствует 256 секторам. При выполнении команды считывания или записи секторов в этот регистр записывается количество секторов, которые необходимо принять или передать. Далее все выглядит следующим образом: мы передаем побайтно сектор, и читаем регистр счетчика секторов. Число в этом регистре будет показывать количество необработанных секторов. Число 0 указывает, что операция чтения/записи полностью завершена. Регистр Ошибки (#F9BE / #30) Этот регистр содержит состояние накопителя после выполнения последней команды или Диагностический Код. После завершения любой команды, за исключением Execute Drive Diagnostic, этот регистр содержит код ошибки, если бит ERR в Регистре Состояния установлен (ERR=1). - BBK (Встречен Плохой Блок). Бит указывает, что при выполнении операции был встречен сектор с неправильной меткой блока в заголовке сектора. - UNC (Неисправимая Ошибка в данных). Бит указывает, что в ходе операции была встречена неисправимая ошибка в зоне данных. - IDNF (Сектор не найден). Бит указывает, что заголовок указанного сектора не найден. - ABRT (Прерванная команда). Бит указывает, что выполнение заданной команды было прервано из-за ошибки состояния винчестера (Не готов, Запрет записи, и т. д.) или при недопустимом коде команды. - TK0NF (Дорожка 0 не найдена). Бит указывает, что при выполнении команды Recalibrate дорожка 0 не найдена. - AMNF (Не найден адресный маркер). Бит указывает, что адресный маркер не найден после нахождения правильного заголовка сектора. - Неиспользуемые биты очищаются. Регистр данных (Старшая часть) (#D8BE / #11), Регистр данных (Младшая часть) (#F8BE / #10). 1.7. Чтение данных с винчестера Через Регистр данных осуществляется обмен данными между компьютером и винчестером. Так, если мы хотим считать сектор с жесткого диска, то мы даем команду «чтение». Далее винчестер читает один 512-байтный сектор в свой буфер и ждет. Потом мы читаем младшую часть сектора, кладем в память. Затем старшую. И так 256 раз. Получается 512 байт. Затем мы читаем значение Регистра счетчика секторов. Если число не 0, то повторяем цикл заново. Таким образом происходит чтение секторов с винчестера. Ниже приводится эта подпрограмма. В HL должно быть указано место в памяти, куда читать, в A - количество 512-байтных секторов. ;читаем сектора, заданные 1.8. Позиционирование головок Я думаю, вы не забыли, что перед вызовом команды READ необходимо указать винчестеру место, откуда читать. Это можно сделать следующей подпрограммой: ;Write Cylinder, Head, Sector. ;Записать в регистры номера цилиндра/ ;головки/сектора. ;IN: DE-цилиндр, H-головка, L-сектор. W_CHS LD BC,#FEBE ;#D0 для Nemo LD A,#A0 ;#B0 - slave. XOR H CALL OUT_A LD BC,#FDBE ;#B0 для Nemo LD A,D CALL OUT_A LD BC,#FCBE ;#90 для Nemo LD A,E CALL OUT_A LD BC,#FBBE ;#70 для Nemo LD A,L JP OUT_A Подпрограмма, выполняющая противоположное действие, то есть определяющая положение головки винчестера, будет выглядеть следующим образом: ;Read Cylinder, Head, Sector. ;Считать текущие цилиндр/головку/сектор. ;OUT: DE-цилиндр, H-головка, L-сектор. R_CHS LD BC,#FEBE ;#D0 для Nemo CALL IN_A AND #0F LD H,A LD BC,#FDBE ;#B0 для Nemo CALL IN_A LD D,A LD BC,#FCBE ;#90 для Nemo CALL IN_A LD E,A LD BC,#FBBE ;#70 для Nemo CALL IN_A LD L,A RET Если же вам нужно указать относительный адрес, то воспользуйтесь подпрограммой SET_. Для ее работы необходимо, чтобы в ячейке SECTOR находилось количество секторов на винчестере, а в ячейке SH_SUM - произведение головок и секторов. ;Установить головку по D, H, L. ;АДРЕС СМЕЩЕНИЯ - CIL/HED/SEC ;IN : D,H,L - 24-разрядный адрес. ;OUT: заданная установка головки. SET_ LD (SET_3+1),HL LD HL,0 LD E,H LD A,D OR A JR Z,SET_1 LD D,L SET_2 PUSH HL PUSH DE LD HL,#FFFF LD DE,(SH_SUM) PUSH AF CALL DIV POP AF,DE INC HL ADD HL,DE EX DE,HL POP HL ADD HL,BC DEC A JR NZ,SET_2 SET_1 PUSH HL,DE SET_3 LD HL,#2121 LD DE,(SH_SUM) CALL DIV POP DE ADD HL,DE EX DE,HL POP HL ADD HL,BC PUSH HL EX DE,HL LD DE,(SH_SUM) CALL DIV EX DE,HL POP HL ADD HL,BC PUSH HL EX DE,HL LD A,(SECTOR) LD D,0 LD E,A CALL DIV LD H,C INC L POP DE CALL W_CHS RET ;Деление. < SH_SUM DB головки * сектора (произведение головок и секторов). SECTOR DB количество секторов на винчестере. 1.9. Запись данных на винчестер Чтобы записать информацию на винчестер, необходимо установить головку с помощью подпрограммы W_CHS или SET_ и выполнить следующую подпрограмму: ;Пишем сектора, заданные 1.10. Описание команд винчестера Ниже я приведу список команд, актуальных при работе с винчестером на Спектруме. Identify Drive (#EC) (Идентифицировать накопитель) После команды необходимо дождаться установки сигнала DRQ и выполнить подпрограмму READ_S, предварительно записав в ячейку (BUF) адрес в памяти, куда считывать информацию о винчестере. Вот наиболее важные значения: +2 - количество цилиндров (2 байта); +6 - количество головок (2 байта); +12 - количество секторов (2 байта); +20 - серийный номер (20 символов); +40 - тип буфера винчестера (2 байта); +42 - размер буфера в секторах (2 байта); +46 - версия прошивки (8 символов); +54 - название модели (40 символов). Указанные здесь количества головок, секторов и цилиндров в большинстве случаев оказываются ложными. Кроме того, вся текстовая информация имеет нестандартный формат. Сначала идет старший байт, затем младший. Для приведения ее в удобочитаемый вид нужно поменять первый байт со вторым, третий с четвертым и т.д. Весь текст выровнен по левому краю и дополнен пробелами. В случае, если первый байт текста - 0, то название не определено. Тип буфера винчестера: 0 - не определено. 1 - одиночная буферизация, винчестер не может производить одновременные операции чтения и записи. 2 - двойная буферизация. Винчестер может одновременно считывать и записывать информацию. 3 - двойная буферизация, кроме того чтение осуществляется с кэшированием. Ячейка размера буфера показывает, какой объем имеет внутренний буфер винчестера. Чем больше объем буфера, тем выше скорость обмена данными между винчестером и компьютером. Idle (#97, #E3, #95, #E1) (Переход в пассивный режим) Происходит остановка винчестера до выполнения следующей команды. Recalibrate (#1x) (Перекалибровка) Эта команда перемещает головки чтения/записи с любого места диска на цилиндр 0. Если дисковод не может установить головку на нулевой цилиндр, генерируется ошибка «Дорожка Не Найдена» (Track Not Found). Read Sector(s) (#20) (Чтение сектора(ов)) Write Sector(s) (#30) (Запись сектора(ов)) Работа команд описана выше. Sleep (#99, #E6) (Остановка) Винчестер полностью останавливается. Единственным способом вывести жесткий диск из режима Остановка без выключения питания и аппаратного сброса является программный сброс. Standby (#96, #E2, #94, #E0) (Дежурный режим) Эта команда переводит винчестер в Дежурный режим. Если диск уже остановлен, то последовательность остановки диска не выполняется. 2. Структура разметки винчестера на компьютере Scorpion Вся приведенная ниже информация относится только к контроллеру SMUC, поскольку представленная в нем эмуляция TR-DOS имеет ряд особенностей, которые необходимо знать, чтобы иметь возможность программно обробатывать представленную на винчестере информацию. При использовании контроллера SMUC Теневым Монитором ПрофПЗУ на винчестере создается последовательность TR-DOS образов дисков, и каждый из этих образов можно «подсоединить» к носителю A, B, C или D. Операционная система TR-DOS будет работать с этим образом (через #3D13), не подозревая, что это не реальный диск. Отсюда идет терминология: диск физический (гибкий флоппи-диск) и диск эмулированный (HDD-образ). 2.1. Файловая структура винчестера Структурная организация размещения на винчестере информации выглядит следующим образом. 1. Создастся глобальный подраздел, носящий всегда название MFS (MOA File System?). Теневой Монитор будет работать только с ним. Кроме этого подраздела на жестком диске могут находиться подразделы других операционных систем. Таким образом, один винчестер можно использовать как на Спектруме, так и на других компьютерах. 2. Внутри глобального подраздела создаются так называемые локальные подразделы. Они могут быть следующих видов: - TR-DOS. Этот подраздел содержит в себе последовательность TR-DOS образов дисков (от 1 до 51). - MicroDos. Как писал автор Теневого Монитора, этот подраздел зарезервирован для совместимости с ПК, использующими эту ОС, и программная поддержка этого подраздела планировалась написаться в дальнейшем. Но до настоящего времени так ничего написано и не было (и, возможно, не будет). - IS-DOS. Подраздел для ОС с одноименным названием. - BAD. С помощью этого подраздела на винчестере покрывается область, имеющая сбойные сектора. Способы работы с этой структурой винчестера через меню Теневого Монитора и подпрограмму RST 8 довольно разнообразны. Здесь же я приведу описание того, как эта структура выглядит «изнутри». 2.2. Структура описания подразделов Фактически, на одном диске может быть установлено несколько операционных систем. В терминологии Теневого Монитора они называются глобальными подразделами. Каждый из них имеет свою внутреннюю структуру. Глобальный подраздел, с которым работает Теневой Монитор (и, собственно, наш Скорпион) имеет название MFS. Список глобальных подразделов находится в 0 относительном секторе (Master Boot Record - 0 цилиндр, 0 головка, 1 сектор) и занимает последние 66 байт (64 байта + 2 байта сигнатуры) - #01BE от начала сектора. Таким образом, на диске может быть 4 глобальных подраздела (Теневой Монитор позволяет иметь только один подраздел MFS). На описание каждого такого подраздела отводится 16 байт, которые имеют следующий формат: по адресу #01BE, и занимает 16 байт, где: +0 - для MFS - 0. +1 - головка | +2 - сектор | начало +3 - цилиндр | подраздела. +4 - у MOA #53 - MFS. +5 - головка | +6 - сектор | конец +7 - цилиндр | подраздела +8 | +9 | относительный адрес +10 | подраздела. +11 | +12 | +13 | Размер подраздела +14 | (в секторах). +15 | Итак, 2-й и 3-й байты указывают местоположение списка локальных подразделов. Он занимает 2 сектора (1024 байта). Описание каждого подраздела занимает 16 байт и выглядит следующим образом. +0 - тип подраздела: 1 - TR-DOS. 2 - MicroDos. 3 - Is-DOS. 4 - BAD. +1 | +2 | относительный адрес +3 | подраздела. +4 | +6 | +7 | Длина подраздела +8 | (в секторах). +9 | +10 - имя подраздела (6 символов). С помощью 4-байтного относительного адреса мы можем обратиться к началу любого локального подраздела. 2.3. Внутренняя структура подразделов Подразделы MicroDos и BAD внутренней структуры не имеют. Подраздел IS-DOS такую структуру имеет, но определяется она целиком и полностью только этой операционной системой. Здесь я лишь расскажу, как запустить IS-DOS, находящуюся на винчестере. 2.4. Как запустить IS-DOS Запуск будет происходить с помощью подпрограммы RST 8. Для этого необходимо выполнить следующую подпрограмму: ] LD DE,имя подраздела LD A,15 ;подключаем к диску «D» LD H,A ;глюк MOA: SET 4,(HL) LD C,35 RST 8 DB #81 RET C ;ошибка LD HL,буфер для 1 сектора. PUSH HL LD BC,#0124 ;читать 1 сектор. LD DE,1 RST 8 DB #81 POP HL LD A,(HL) CP #18 ;jr $+... ? RET NZ ;незапускаемый IS-DOS LD SP,HL JP (HL) ;запустили 2.5. Структура подраздела TR-DOS Теперь рассмотрим подраздел TR-DOS. Он является одним из центральных подразделов на винчестере, поскольку большинство программ работают именно с этой операционной системой. Поэтому его мы рассмотрим наиболее подробно. Структура подраздела такова: в первых двух секторах находится описание TR-DOS образов дисков. Описание абсолютно аналогично по своей структуре описанию локальных дисков. Каждый диск описан 16 байтами, где +0 - всегда 1 (TR-DOS), +1 - адрес образа диска плюс 1, +6 - длина диска (всегда 1, 5, 0, 0 - поскольку длина TR-DOS образа строго фиксирована: 1280+1 512-байтных секторов), +10 - имя диска. Стандартное имя - Disk??, где ?? - порядковый номер диска, но его можно безболезненно для Теневого Монитора менять. Обратите внимание, что к адресу диска на винчестере необходимо прибавлять 1 сектор. Дело в том, что перед каждым диском непонятно зачем существует 512-байтная область, заполненная нулями. Хочу также обратить внимание на максимально допустимое количество образов дисков в TR-DOS подразделе. Мне доводилось встречать мнение, что их может быть больше, чем 51. Объясняю, в чем здесь заблуждение: дело в том, что Теневой Монитор для обращения к дискам внутри подраздела использует 16-разрядный регистр. Относительно начала подраздела адрес 51-го диска будет #FF33, а адрес 52-го диска был бы #010434. Именно поэтому максимальное количество дисков в подразделе - 51. 2.6. Структура сектора эмуляций Каждый подраздел или образ диска можно подключить к драйву A, B, C или D. Информация об эмуляции находится во 2-м относительном секторе, если Теневой Монитор работает не в LBA режиме, и в 3 относительном секторе, если флаг LBA включен. Ее длина - 1 сектор. Каждый диск описан 22-мя байтами: +0 - тип подраздела (0 - эмуляции нет). +1 | +2 | адрес диска/подраздела. +3 | +4 | +5 - тип подраздела. +6 | +7 | длина диска/подраздела. +8 | +9 | +10 - имя подраздела (6 байт). +16 - имя диска/подраздела (6 байт). В случае, если мы подключаем образ диска, то в +10 будет имя подраздела, а в +16 - имя образа диска (Disk01 и подобное). Если же подключен не TR-DOS подраздел, то в +16 будет имя подраздела (то есть то же, что и в +10). Чтобы полноценно подключить диск или подраздел, необходимо выполнить следующие действия: 1. Подключить эмуляцию через RST 8. Эмуляция пропишется в 8 страницу. 2. Считать сектор эмуляций с винчестера. 3. Изменить эмуляцию диска. 4. Записать CRC в сектор эмуляций. 5. Записать этот сектор на винчестер. Очень важно при изменении эмуляции просчитать контрольную сумму. Если при считывании этого сектора Теневым Монитором контрольная сумма не совпадет, то он снимет эмуляции со всех четырех дисков. Чтобы вычислить верную контрольную сумму, необходимо проделать следующее: LD DE,сектор в памяти. LD BC,508 CALL CRC LD HL,сектор + 508. LD (HL),E INC HL LD (HL),D RET 2.7. Расчет контрольной суммы Приведенный ниже код расчета CRC любезно предоставлен мне MOA и представляет из себя, как он мне объяснил, «гибрид» CRC-16 и CRC-32. ;Cyclic Redundancy Check. ;Подсчет контрольной суммы. ;IN: [DE] - START, [BC] - LENGHT ;OUT: [DE] - CRC-SUMM. CRC LD HL,#FFFF PUSH IX PUSH DE POP IX EX DE,HL CRC_1 LD HL,CRC_TAB LD A,(IX) INC IX XOR E ADD A,L LD L,A JR NC,CRC_2 INC H CRC_2 LD A,D XOR (HL) LD E,A INC HL XOR A XOR (HL) LD D,A DEC BC LD A,C OR B JR NZ,CRC_1 POP IX RET CRC_TAB DW #0000,#1021,#2042,#3063 DW #4084,#50A5,#60C6,#70E7 DW #8108,#9129,#A14A,#B16B DW #C18C,#D1AD,#E1CE,#F1EF DW #1231,#0210,#3273,#2252 DW #52B5,#4294,#72F7,#62D6 DW #9339,#8318,#B37B,#A35A DW #D3BD,#C39C,#F3FF,#E3DE DW #2462,#3443,#0420,#1401 DW #64E6,#74C7,#44A4,#5485 DW #A56A,#B54B,#8528,#9509 DW #E5EE,#F5CF,#C5AC,#D58D DW #3653,#2672,#1611,#0630 DW #76D7,#66F6,#5695,#46B4 DW #B75B,#A77A,#9719,#8738 DW #F7DF,#E7FE,#D79D,#C7BC DW #48C4,#58E5,#6886,#78A7 DW #0840,#1861,#2802,#3823 DW #C9CC,#D9ED,#E98E,#F9AF DW #8948,#9969,#A90A,#B92B DW #5AF5,#4AD4,#7AB7,#6A96 DW #1A71,#0A50,#3A33,#2A12 DW #DBFD,#CBDC,#FBBF,#EB9E DW #9B79,#8B58,#BB3B,#AB1A DW #6CA6,#7C87,#4CE4,#5CC5 DW #2C22,#3C03,#0C60,#1C41 DW #EDAE,#FD8F,#CDEC,#DDCD DW #AD2A,#BD0B,#8D68,#9D49 DW #7E97,#6EB6,#5ED5,#4EF4 DW #3E13,#2E32,#1E51,#0E70 DW #FF9F,#EFBE,#DFDD,#CFFC DW #BF1B,#AF3A,#9F59,#8F78 DW #9188,#81A9,#B1CA,#A1EB DW #D10C,#C12D,#F14E,#E16F DW #1080,#00A1,#30C2,#20E3 DW #5004,#4025,#7046,#6067 DW #83B9,#9398,#A3FB,#B3DA DW #C33D,#D31C,#E37F,#F35E DW #02B1,#1290,#22F3,#32D2 DW #4235,#5214,#6277,#7256 DW #B5EA,#A5CB,#95A8,#8589 DW #F56E,#E54F,#D52C,#C50D DW #34E2,#24C3,#14A0,#0481 DW #7466,#6447,#5424,#4405 DW #A7DB,#B7FA,#8799,#97B8 DW #E75F,#F77E,#C71D,#D73C DW #26D3,#36F2,#0691,#16B0 DW #6657,#7676,#4615,#5634 DW #D94C,#C96D,#F90E,#E92F DW #99C8,#89E9,#B98A,#A9AB DW #5844,#4865,#7806,#6827 DW #18C0,#08E1,#3882,#28A3 DW #CB7D,#DB5C,#EB3F,#FB1E DW #8BF9,#9BD8,#ABBB,#BB9A DW #4A75,#5A54,#6A37,#7A16 DW #0AF1,#1AD0,#2AB3,#3A92 DW #FD2E,#ED0F,#DD6C,#CD4D DW #BDAA,#AD8B,#9DE8,#8DC9 DW #7C26,#6C07,#5C64,#4C45 DW #3CA2,#2C83,#1CE0,#0CC1 DW #EF1F,#FF3E,#CF5D,#DF7C DW #AF9B,#BFBA,#8FD9,#9FF8 DW #6E17,#7E36,#4E55,#5E74 DW #2E93,#3EB2,#0ED1,#1EF0 3. Заключение. Я надеюсь, что в доступной форме изложил все свои знания о программировании винчестера на Спектруме. Вы можете изучить эти подпрограммы и написать на их основе свои, либо убрать текст и скомпилировать оставшиеся процедуры. Тогда вы получите полноценный (правда, упрощенный, без оптимизации по скорости) драйвер для работы с винчестером. |