![]()  | 
| 
    	 :: СОДЕРЖАНИЕ НОМЕРА 
	
:: Газетные рубрики 
	
:: АВТОРЫ 
	
:: Поиск 
	:: Поддержка проекта 
	  
		Webmoney:
		 
	
 | 
	
		 ::     №15 (26.02.2003) Просмотров: 11246
     
	Автор: Александр Юдин. Рубрика: В помощь разработчику. Номер: №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.  |