ZX Format
#05
11 декабря 1996 |
|
Программистам - TR-DOS для программистов.
TR-DOS для программистов. music by DNK (C) Макс Петров. ________________________________ Я не буду в этой статье повто- рять описания tr-dos различных изданий, показывать пример ис- пользования её из basica и пере- числять номера подпрограмм пзу '#3d13'. Моя цель состоит в опи- сании тонкостей и сложностей, с которыми я сам встретился, пыта- ясь раскрутить мотор дисковода, написать свой загрузчик и нако- нец свой командера. Я попытаюсь доходчиво объяснить 'как' рабо- тать с ВГ 93 и дисководом и при- веду примеры полезных процеду- рок. ВГ 93. Как Вам должно быть известно, общение с ВГ происходит через порты, обращаться к которым мож- но _только_ из пзу tr-dos (от- дельные экземпляры speccy позво- ляют выводить/читать из портов хоть из озу, но то является только нежеланием разработчика привести контроллер дисковода к стандарту). Порты (регистры) ВГ 93: чтение: #1f - содержит информацию о состоянии микросхемы в процессе выполнения команды или о наличии ошибок исполнения команды. #3f - содержит номер дорожки (физический), на которой, по мнению ВГ, стоит головка диско- вода. Если сдвинуть головку вручную, значение регистра не изменится! #5f - содержит номер сектора. #7f - информация, передаваемая микросхемой в процессе выполне- ния команды (очередной считанный с диска байт). #ff - бит 7 =1 означает конец выполнения команды, бит 6 =1 оз- начает просьбу ВГ передать ей следующий байт, например, при записи сектора, или взять прочи- танный ею с диска байт, который она поместила в регистр #7f. Практического применения чтение из портов #3f и #5f не имеет, да из них и невозможно прочитать (см. 'чтение из портов'). запись: #1f - код команды. #3f и #5f - тоже, что чтение. #7f - сюда следует записывать очередной байт после просьбы ВГ для записи его на диск, или но- мер дорожки для команды позицио- нирования. #ff - бит 6 - плотность записи (fm/mfm). В некоторых контролле- рах (а может и во всех) этот бит не подключен, поэтому не стоит пытаться им воспользоваться. бит 3 отвечает за остановку мотора. Если он =1, то мотор через неко- торое время после выполнения ко- манды остановится, иначе будет крутиться вечно (по-моему так). Бит 2 (небезизвестная книга Лар- ченко и Родионова даёт о нём не- верную информацию) - сбросив его в 0 Вы добьётесь мгновенного прекращения выполнения команды и остановки мотора. Порт #ff имеет ещё три бита, но внимание! ВГ об их существовании не знает! Они управляют непосредственно диско- водом и контроллером (в частнос- ти, ВГ не имеет понятия, с каким дисководом (a,b...) она работа- ет). Бит 4 - номер стороны дис- кеты (1 - нижняя), биты 1,0 - номер дисковода. Некоторые контроллеры (а может почти все) работают только с битом 0 и поз- воляют выбрать только 2 дисково- да. Как программировать ВГ 93. Как я уже сказал, в наших прог- раммах нельзя непосредственно обратиться к регистрам ВГ - для чтения/записи в порты контролле- ра необходимо использовать соот- ветствующие участки пзу DOS, ко- торые удобно искать с помощью sts 4.1 (следует заметить, что sts 4.1 неверно трассирует опе- рации ld r,(hl) в пзу tr-dos, где r<>a и 0<=hl<=#3fff). К най- денным участкам затем можно об- ращаться такой последова- тельностью команд (adr - адрес участка): ld hl,l01 push hl ld hl,adr push hl jp #3d2f l01 ... Удобнее так: ld ix,adr call dos ... dos push ix jp #3d2f Не следует вместо #3d2f ставить #3d30, т.к. существуют особо тормозные контроллеры (?), кото- рые не успевают подключить пзу tr-dos и требуют для этого нес- кольких тактов процессора. Полезные подпрограммы пзу DOS: запись в любой порт: #2a53 out (c),a ret запись на диск до конца опера- ции из hl: #3fca in a,(#ff) and #c0 jr z,#3fca ret m; bit 7,a=1 - конец outi jr #3fca чтение в hl с диска до конца операции: #3fe5 тоже, только ini вместо outi. ожидание выполнения команды (используется при позиционирова- нии): #3ef5 in a,(#ff) and #c0 jr z,#3ef5 ei ret m di in a,(#7f) jr #3ef5 Везде в статье адреса даны для tr-dos 5.03/04t. Для 5.01 адреса другие. Теперь у нас есть всё для того чтобы заставить ВГ выполнить ко- манду. Однако надо бы ещё прове- рить успешность этого выполне- ния, т.е. прочитать значение ре- гистра #1f. Разработчики tr-dos видимо не предполагали, что воз- можности их системы могут не удовлетворять программеров, от- части поэтому такой последова- тельности как in a,(#1f) или in r,(c): ret в пзу нет, поэтому прочитать значения регистров #3f и #5f невозможно (хотя и не нуж- но), а #1f - затруднительно. Есть несколько способов (2 или 3). На мой взгляд самый удобный и надёжный такой: сразу после выполнения команды необходимо выполнить следующие дейстия: ld d,номер дорожки, на кото- рой стоит головка дисковода (его надо знать) ld (#5cd8),не 0 ld ix,#2740 call dos ld a,(#5ccd) здесь a будет содержать значение регистра #1f. Следует учесть, что во время отработки процедуры #2740 осуществляется опрос кла- виши break, поэтому во избежание недоразумений следует перехваты- вать попытку выхода в пзу basic (см. ниже). Теперь средство есть, объясню наконец, как дать ВГ команду прочитать, например, группу сек- торов. Замечу, что команды чте- ния/записи не раскручивают мо- тор!, это делают команды позици- онирования. Команду можно пода- вать только когда микросхема не занята выполнением предыдущей команды. Позиционирование: (Объясню понятия физической и логической дорожек: физ. показы- вает только положение обеих го- ловок, вне зависимости от сторо- ны. Можно привести в соот- ветствие: номер !физ:0 0 1 1 ... 80 80 дорожки !лог:0 1 2 3 ... 160 161 Зачем это надо? дело в том, что ВГ 93 работает с физ. номерами дорожек, ведь она не знает номер стороны (см. порт #ff), а мы привыкли к лог. номеру. Т.о. лог=физ*2+номер стороны (0 - нижняя) di ld a,d ;d - логический но- ;мер дорожки srl a ; вычисляем физич. ; номер (a/2) ld c,#7f; сюда надо помес- ; тить номер до- ; рожки,на которую ; я хочу отьехать. call outc ld a,#3c; выбор стороны bit 0,d jr z,l01 ld a,#2c l01 ld c,#ff call outc; устанавливаем ; нужные для ; нормальной ра- ;боты биты порта #ff и номер ;стороны регистр #3f устанавли- ;вать не надо, он должен сам по ;себе содержать номер текущей ;дорожки ld a,#18; код команды пози- ;цион. call out1 ld ix,#3ef5 call dos; ожидание выполне- ;ния di ; команды. jp cont ... out1 ld c,#1f outc ld ix,#2a53 dos push ix jp #3d2f Что делает ВГ 93: при получении в регистр #1f кода #18, она дает сигнал на раскрутку диска. Затем сравнивает значения регистров #3f и #7f, определяет направле- ние и количество шагов головки и шагает, изменяя значение рег. #3f. При этом значение регистра #3f может и не совпадать с ре- альным положением головок. Но об этом поговорим потом. Когда зна- чения #7f и #3f совпали, ВГ ус- танавливает bit 7 порта #ff =1 и готова к приёму следующей коман- ды. За время позиционирования мо- тор, вращающий диск, мог не ус- петь раскрутиться до требуемой скорости 5 об/сек, поэтому тео- ретически следует после выдачи команды позиционирования и перед чтением/записью сделать паузу (паспортное время раскрутки мо- тора 0.7 сек.). Задержка также нужна на время успокоения голо- вок после позиционирования (по паспорту 15 мс). Однако опыт по- казывает, что перед чтением за- держку можно не делать вообще, перед записью же - тут Вам ре- шать, скажу лишь, что в уже два года существующем командере fpm задержка перед записью делается только при первом позиционирова- нии перед записью первого секто- ра из всей группы. Итак, ездить по диску мы уже умеем и мотор уже крутится. Те- перь можно читать сектора: - даём команду "чтение сектора" - читаем сектор - проверяем наличие ошибки затем повторяем для остальных секторов на данной дорожке. При переходе на следующую дорожку надо опять дать команду позицио- нирования. Надо сказать, что оп- ределение наличия ошибки по #2740 нерационально при работе с группой секторов. Существует другой способ. Процедура #2090 позволяет прочитать сектор, про- верив затем, была ли ошибка. Для её вызова необходимо: поместить в стек: 1) адрес возврата. 2) адрес,указывающий на байт #01 3) bc=#17f 4) в (#5cd6) записать число n (любое) 5) поместить в регистр #5f номер сектора 6) войти в пзу по адресу #2090 В hl должен быть адрес, куда читать или откуда писать сектор. cont ld bc,exit push hl push bc ld bc,cont; адрес, указыва- ;ющий на 1 push bc xor a ld (#5cd6),a ld a,номер сектора ld c,#5f call outc ld bc,#2090 push bc ld bc,#17f jp #3d2f exit di ; процедура #2090 разре- ; шает прерывания pop hl ld a,(#5cd6) Здесь a будет равно записанному ранее в (#5cd6) числу, если ошибки не было, или на 1 больше, если была. Если ошибка была, то следует либо повторить операцию, либо, если действия Вашей прог- раммы зависят от конкретной ошибки, то воспользоваться #2740 для определения кода ошибки. Ес- ли ошибок не было, то следует перерассчитать значения hl и 'номера сектора' для следующего сектора и повторить операцию. Подпрограмма для записи сектора выглядит несколько иначе: cont ld bc,exit push hl push bc ld bc,cont;адрес,указываю- ;щий на 1 push bc xor a ld (#5cd6),a ld a,номер сектора ld bc,#15f call outc push bc; в стек надо запи- ;сать #01xx ld bc,#2099 push bc ld bc,#3fca push bc ld a,#a0; команда 'запись ;сектора' call out1 ld bc,#17f jp #3d2f exit di ; процедура #2090 разре- ; шает прерывания pop hl ld a,(#5cd6) Дальше аналогично загрузке. Какие могут быть ошибки? (коды из #1f) При чтении: bit 7 =1 дисковод не готов (не крутится мотор. bit 5 =1 не обращайте на него внимания. На всех 'нормальных' дисках он =0. '& bit 4 =1 нет сектора. Обычно что-то где-то не читается. bit 3 =1 сектор читается с ошибкой. bit 0 =1 Вы дали ВГ команду в тот момент, когда она уже выпол- няла что-то (?). Вероятность такой ошибки практически равна нулю. При записи: bit 7 - аналогично чтению. bit 6 =1 на дискете заклеена прорезь 'защита записи'. bit 5 =1 ошибка записи. Не знаю, что сие означает. bit 4 и 0 - аналогично чтению. При корректном обращении к контроллеру вероятность появле- ния ошибок bit 2 и 1 также равна нулю. Ну вот, на сегодня всё. Ждите продолжения...
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября