:: СОДЕРЖАНИЕ НОМЕРА
:: Газетные рубрики
:: АВТОРЫ
:: Поиск
:: Поддержка проекта
Webmoney:
|
:: №15 (26.02.2003) Просмотров: 10692
Автор: Александр Юдин. Рубрика: В помощь разработчику. Номер: №15 (26.02.2003). Укрощение TR-DOSПочему я решил написать эту статью? Во-первых, я знаю, что для многих программирование под TR-DOS до сих пор остается тайной за семью печатями. Во-вторых, практически нет нормальной документации по программированию TR-DOS. В-третьих, хочу поделится с вами той информацией, теми знаниями, которые у меня накоплены. Я постараюсь представить их в виде некоего пособия с простым и понятным содержанием для людей, которые практически не разбираются в работе дисковых устройств. Впрочем, здесь будет много интересного и для разбирающихся в этом деле... Кстати, моя гордость, это процедура программного определения типа дисковода 3.5” или 5.25” (правда в этом описании ее нет). А теперь, пожалуй, самое время перейти к самому интересному.TR-DOS TR-DOS - дисковая операционная система разработанная в Англии. До нашей страны «докатились» две версии: 5.01 и 5.03 - датированные 1986 годом. Очевидно Technology Research Ltd было необходимо как можно быстрее «выкинуть» в свет свое творение, поскольку я не могу найти другого объяснения тoму факту, что TR-DOS написана так ужасно, напичкана всевозможными ляпами, которые не были исправлены даже в третьей редакции пятой версии! Охарактеризовывая TR-DOS, лично я нахожу лишь один плюс (как для программиста), - это последовательное хранение информации на диске, что дало возможность написания процедур дающих максимальную скорость. Пожалуй далее идут одни недостатки. Например, по-моему, непомерно «раздута» область системных переменных, тяп-ляп написаны подпрограммы в ПЗУ, и самое главное, совершенно не предусмотрено возможности для самостоятельного низкого программирования микроконтроллера. Так же, слишком уж перестрахованные задержки в процедурах обмена данными между микроконтроллером и дисководом. Но, тем не менее, не все так уж и плохо. Используя обрывки подпрограмм в ПЗУ (ROM) TR-DOS, можно получить доступ к портам микроконтроллера. Порты Для управления интерфейсом BETA DISC используются следующие порты: #1f, #3f, #5f, #7f, #ff. регистр состояния #1f [in] регистр команд #1f [out] in a,(#1f) - выдает состояние контроллера, где A: out (#1f),a - выполнение команды, где A - код команды (см. раздел команды). Регистр дорожки #3f - in/out in a,(#3f) - выдает номер текущего физического трека. out (#3f),a - задание нового физического трека. Регистр сектора #5f - in/out in a,(#5f) - выдает номер текущего сектора. out (#5f),a - задание нового сектора (нумерация с 1!). Регистр данных #7f - in/out in a,(#7f) - чтение байта out (#7f),a - задание номера логического трека, для команды позиционирования или запись байта если была какая-либо команда на запись. ini - последовательное считывание данных. outi - последовательная запись данных. Регистр #ff состояния сигналов intrq и drq - [in] Системный регистр #ff - [out] in a,(#ff) - отражает состояние сигналов intrq (d7), drq (d6) контроллера, где A: bit 7 - intrq (сигнал окончания выполнения команды) 6 - drq (запрос данных микроконтроллером) 5 - x 4 - x 3 - x 2 - x 1 - x out (#ff),a - вспомогательные функции, где A: bit 7 - x 6 - метод записи (1 - fm, 0 - mfm) 5 - x 4 - выбор магнитной головки (0 - верх, 1 - низ) 3 - загрузка головки (всегда должен быть в 1) 2 - аппаратный сброс микроконтроллера (если 0) 1 - номер дисковода (00 - a, 01 - b, 10 - c, 11 - d) 0 - -/- Порты TR-DOS доступны только тогда, когда включено ПЗУ TR-DOS! Включить ПЗУ TR-DOS можно через специальные точки входа. Точки входа Аппаратное включение дискового интерфейса происходит в момент выполнения какой-либо команды, записаной по адресу в диапазоне #3d00 - #3dff. Проще говоря, чтобы попасть в ПЗУ TR-DOS нужно запомнить на стеке адрес подпрограммы в ПЗУ TR-DOS, куда вы хотите передать управление и выполнить команду RET, расположенную в этом диапазоне. Либо, если адрес подпрограммы лежит непосредственно в пределах #3d00 - #3dff, можно просто передать на нее управление, например, обычным CALL NN. Чаще всего в качестве точки входа используют две: самая распространенная точка входа: #3d2f nop ret Редко используемая точка входа (не «переваривается» некоторыми отечественными версиями интерфейса: GRM Pentagon и т.п.): #3d30 ret Но если хорошенько «покопаться» в ПЗУ TR-DOS, то можно найти еще несколько (недокументированных): #3d2c, #3d4b, #3d7f, #3d93, #3d96, #3d97, #3dac. По всем этим адресам находится команда ret, за исключением точки 3. Недокументированная точка входа и кроме меня никем неиспользуемая: #3d96 nop ret По идее, возможно использование любого адреса в качестве точки входа из выше перечисленных, но гарантию работоспособности на всяких «левых» интерфейсах я не даю! Поэтому я настоятельно рекомендую использовать либо первую, либо третью точку входа. Используя эти точки входа можно добраться до подпрограмм расположенных в ПЗУ TR-DOS. Подпрограммы С помощью обрывок подпрограмм TR-DOS можно писать свои собственные процедуры работы с диском. Для начала приведу адреса доступа к портам ввода данных: #2fc3 out (#1f),a ;регистр команд ret ..... #1e3a out (#3f),a ; регистр дорожки ret ..... #1ff3 out (#ff),a ; системный регистр ret ..... #2f0c out (#ff),a ; системный регистр ret ; (практически не используется) ..... #2a53 out (c),a ; универсальный адрес ret Тот же самый эффект можно получить воспользовавшись процедурой по адресу #20b8: #20b8 out (c),d djnz #20b1 ret Или процедурой по адресу #3fd1: #3fca in a,(#ff) ; ожидание intrq или drq and %11000000 ; bit7 - intrq/bit6 - drq jr z,#3fca ; для drq условие заведомо не выполнится ret m ; выход по intrq #3fd1 outi ; запись байта jr #3fca Как видите с вводом данных все просто и понятно, чего не скажешь об их получении. К сожалению в ПЗУ TR-DOS не предусмотрено такой возможности. Я не говорю о том, чтобы была такая же возможность считывать состояние каждого регистра в отдельности. В принципе, хватило бы одной простой команды типа in a,(c), но т.к. таковой нет, приходится прибегать к различного рода ухищрениям: Так, например, чтобы прочитать значения регистров можно воспользоваться следующей процедурой по адресу #3ef3: #3ef3 in h,(c) #3ef5 in a,(#ff) ; ожидание intrq или drq and %11000000 ; bit7 - intrq/bit6 - drq jr z,#3ef5 ; для drq условие заведомо не выполняется ei ; ! ret m ; выход по intrq На выходе в H будет значение состояния нужного вам регистра. Единственный недостаток в том, что на выходе разрешаются прерывания, что в некоторых случаях совсем не нужно. Можно воспользоваться другой процедурой по адресу #3fec: #3fe5 in a,(#ff) ; ожидание intrq или drq and %11000000 ; bit7 - intrq/bit6 - drq jr z,#3fe5 ; для drq условие заведомо не выполняется ret m ; выход по intrq #3fec ini ; чтение байта jr #3fe5 На выходе в (HL) будет значение состояния нужного вам регистра. Таким образом можно считать состояние всех регистров кроме регистра состояния #1f, т.к. произойдет зацикливание при чтении #ff. Поэтому чтобы все же заполучить значение регистра состояния, нужно выполнить следующие действия: ;(c) Andrew MOA Larchenko in_1f out (#3f),0 out (#5f),#a ld d,#01 jp #3f33 На выходе в B будет находиться значение регистра состояний #1f, т.е. таким способом мы проэмулировали команду in b,(#1f). Однако при выполнении данной процедуры были запорчены регистры дорожки и сектора, поэтому, при необходимости, следует восстановить в них исходные значения. Команды Прежде чем перейти непосредственно к командам, необходимо сказать, что выполнение каждой последующей команды возможно только тогда, когда завершена предыдущая, т.е. поступит сигнал intrq. Отследить этот сигнал можно воспользовавшись процедурой: #3fe5 in a,(#ff) ; ожидание intrq или drq and %11000000 ; bit7 - intrq/bit6 - drq jr z,#3fe5 ; для drq условие заведомо не выполнится ret m ; выход по intrq Или любой другой аналогичной процедурой по другим адресам... Также надо отметить, что выбор дисковода и др. для выполнения команд осуществляется с помощью инструкции out (#ff),a (см. раздел порты). Микроконтроллер может выполнять 11 команд: 1. Восстановление - %0000hvrr - + 2. Поиск/Позиционирование - %0001hvrr | 3. Шаг в предыдущем направлении - %001thvrr + - 4. Шаг вперед - %010thvrr | 5. Шаг назад - %011thvrr - + 6. Чтение сектора - %100mseca 7. Запись сектора - %101msec0 8. Чтение адреса - %11000e00 9. Чтение дорожки - %11100e00 10. Запись дорожки/форматир-е - %11110e00 11. Принудительное прерывание - %1101iiii где rr - скорость позиционирования головки: 00 - 6мс, 01 - 12мс, 10 - 20мс, 11 - 30мс (1Mhz). v - проверка номера дорожки после позиционирования. h - загрузка головки (всегда должен быть в 1!). t - изменение номера дорожки в регистре дорожки после каждого шага. a - тип адресной метки (0 - #fb, стирание сектора запрещено 1 - #F8, стирание сектора разрешено). c - проверка номера стороны диска при идентификации индексной области. e - задержка после загрузки головки на 30мс (1Mhz). s - сторона диска (0 - верх/1 - низ). m - мультисекторная операция. i - условие прерывания: i0 - после перехода сигнала cprdy из 0 в 1 (готов); i1 - после перехода сигнала cprdy из 1 в 0 (не готов); i2 - при поступлении индексного импульса; i3 - немедленное прерывание команды, при: i=0 - intrq не выдается i=1 - intrq выдается. Восстановление - осуществляет позиционирование головки на дорожку 0. Если через 256 импульсов сигнал tr00 не появится, то команда прекращает работу. Выполняется независимо от готовности дисковода. to_tr0 out (#1f),#8 ; %00001000 Поиск/позиционирование - перемещает головку на нужный трек. Перемещение происходит до тех пор, пока не совпадут номера физической дорожки в #3f и логической дорожки в #7f. Номер трека указывается без учета стороны (/2)! jump out (#7f),trk/2 ; номер нужного трека/2 out (#1f),#18 ; %00011000 jp #3fe5 ; ожидание выполнения команды Шаг (пункт 3) - двигает головку на один шаг в предыдущем направлении. step out (#1f),#38 ;%00111000 jp #3fe5 ; ожидание выполнения команды Шаг вперед - двигает головку на один шаг вперед. step_f out (#1f),#58 ; %01011000 jp #3fe5 ; ожидание выполнения команды Шаг назад - двигает головку на один шаг назад. step_b out (#1f),#78 ; %01111000 jp #3fe5 ; ожидание выполнения команды Чтение сектора - чтение сектора с текущей дорожки. При мультисекторной операции читаются все сектора с заданного до конца трека. load_s out (#5f),sec ; номер считанного сектора (нумерация с 1) out (#1f),#80 ; %10000000 ld hl,address ; адрес загрузки ld c,#7f jp #3fe5 ; чтение сектора Запись сектора - запись сектора на текущую дорожку. При мультисекторной операции записываются все сектора с заданного до конца трека. save_s out (#5f),sec ; номер записываемого сектора (нумерация с 1) out (#1f),#a0 ; %10100000 ld hl,address ; адрес записи ld c,#7f jp #3fca ; запись сектора Чтение адреса - считывает 6 байтов идентификатора сектора, включая crc (контрольная сумма). l_addr ld hl,buffer ; адрес загрузки идентификатора out (#1f),#c0 ; %11000000 jp #3fe5 ; чтение идентификатора сектора На выходе в (HL) по смещению: +0 - номер трека (0 - 128) +1 - номер стороны (0-верх, 1-низ) +2 - номер сектора (0 - 128) +3 - длина сектора (0-128b, 1-256b, 2-512b, 3-1024b) +4 - контрольная сумма (?) +5 - -/- Чтение дорожки - считывает всю дорожку целиком. Синхронизация отсутствует (crc не проверяются), т.е. нельзя отследить правильность считанной информации. load_t ld hl,address ; адрес загрузки трека out (#1f),#e0 ; %11100000 jp #3fe5 ; чтение трека (>6Kb) Запись дорожки/форматирование - форматирование дорожки. format ld hl,address ; адрес расположения данных дорожки out (#1f),#f0 ; %11110000 Принудительное прерывание - завершение выполняемой на данный момент команды. В отличие от других команд она может выдаваться в любой момент. inter out (#1f),i ; %1101iiii (значение i см. выше) Вот еще две подпрограммки из ПЗУ TR-DOS. #20af ld b,#01 #20b1 in a,(#ff) ; ожидание intrq или drq and %11000000 ; bit7 - intrq/bit6 - drq jr z,#20b1 ret m ; выход если intrq #20b8 out (c),d ; запись байта если drq djnz #20b1 ; повтор пока b<>0 ret #3ef3 in h,(c) #3ef5 in a,(#ff) ; ожидание intrq или drq and %11000000 ; bit7 - intrq/bit6 - drq jr z,#3ef5 ei ; ! ret m ; выход если intrq #3efd di ; ! #3efe in a,(#7f) ; чтение байта если drq jr #3ef5 ; повтор пока не поступит intrq Вот, собственно и все. Адрес для связи: Юдин Александр Владимирович (faster), 432044, г. Ульяновск, ул. Героев Свири 16а-24. |