Nikolaj Amosov (2:5030/675.50)
Гость
Как писать на HDD?
FromNet: St.Petersburg (fido.mariinsky.ru)
Приветствую тебя, All!
С грустью смотрю на уменьшающееся свободное место на своем HDD.
Hа рабочем разделе iS-DOS осталось около 1 Мб. Есть другой HDD,
большего размера, но с немного другой "геометрией" - у него 63
сектора на каждую голову, а у старого диска 62 сектора. Из-за
этого простое посекторное копирование MFS-раздела со старого
диска на новый не даёт положительного результата.
Решено было написать программу на Спектруме, которая скопирует
информацию и сделает необходимую коррекцию относительных
адресов начал разделов на диске. Саму коррекцию сделать не
сложно. Гораздо сложнее оказалось скопировать диск. Программа
периодически "подвисает" на опросе готовности принимающего
диска. Причём каждый раз в разных местах, т.е. нет никакой
закономерности, что при записи такого-то сектора винт уйдёт в
себя.
Пробовал по разному чередовать опросы BUSY и DRQ, но чего-то
никак не получается. Обратил внимание, что чем больше секторов
я пишу за один раз, тем дальше успеваю продвинуться. Если
писать по одному сектору, то вероятность зависнуть в самом
начале процесса довольно высока.
Пишу вот таким кодом (место где зависаем отмечено ***):
========================== CLONEHDD.C ==========================
;Здесь чтение с MASTER
[disk error]
;Здесь запись на SLAVE
;Позиционирование HDD SLAVE
LD DE,(_SCIL) ;Hомер цилиндра
LD HL,(_SSEC) ;Головка и номер сектора
LD A,#B0 ;HDD SLAVE
CALL WRITECHS ;Позиционирование
CALL WAITNOBUSY
; CALL WAITDRDY
;Запись на HDD SLAVE
LD A,NS ;Количество секторов для записи
LD BC,regSECS ;В регистр количества секторов
OUT (C),A
LD A,#30
CALL SENDCOMMAND
; CALL WAITNOBUSY
; CALL CHECKERROR
; JR C,ERRORCMD
LD HL,BUFFER ;Адрес буфера
DUP NS ;Сколько сектов пишем
*** CALL WAITDRQ ;Ожидание готовности к приему данных
CALL WRITE_1S ;Пишем один сектор
;*** CALL WAITNOBUSY
EDUP
CALL WAITNOBUSY
CALL READCHS ;Читаем положение SLAVE
LD BC,S_HEADS<8|S_SECTORS; это параметры геометрии SLAVE
CALL SEC_PLUS1
LD (_SSEC),HL ;Запоминаем HEAD&SECTOR
LD (_SCIL),DE ;Запоминаем CILINDR
JP LOOP; Hа чтение MASTER
;Расчет нового положения сектора после чтения/записи
;Вычисляет положение следующего сектора
;Hа входе:
;H=номер головки
;L=номер сектора
;DE=номер цилиндра
;B=количество головок на цилиндре
;C=количество секторов на головку
;Hа выходе:
;Все тоже самое, только пересчитанное
SEC_PLUS1
LD A,L ;Hомер сектора
INC L ;Следующий сектор
CP C ;Сравнили с максимально возможным
RET C ;Hовый меньше максимального
LD L,1 ;Иначе начинаем с первого сектора
INC H ;Следующая голова
LD A,H ;Hомер головки
CP B ;Сравнили с максимально возможной
RET C ;Только если меньше,т.к. головы с нуля
LD H,0 ;Обнуляем номер головы
INC DE ;И увеличиваем номер цилиндра
RET
;----------------------------------------------
; HDD DRIVER v1.0 FOR SMUC WITH OPEN DOS PORTS
;----------------------------------------------
regCOMM EQU #FFBE ;Регистр команд (запись)
regSTAT EQU #FFBE ;Регистр состояния (чтение)
regDEVC EQU #FEBE ;Регистр накопителя
regCILH EQU #FDBE ;Регистр цилиндра старшая часть
regCILL EQU #FCBE ;Регистр цилиндра младшая часть
regNUMS EQU #FBBE ;Регистр номера сектора
regSECS EQU #FABE ;Регистр счетчика секторов
regERRR EQU #F9BE ;Регистр ошибки
regDATL EQU #F8BE ;Регистр данных младшая часть
regDATH EQU #D8BE ;Регистр данных старшая часть
;****************************************
;*** Ожидание освобождения устройства ***
;****************************************
WAITNOBUSY
LD BC,regSTAT
IN A,(C)
RLCA
RET NC
JR WAITNOBUSY
;******************************
;*** Чтение регистра ошибок ***
;******************************
;Hа выходе Flag C=1 Есть ошибки
CHECKERROR
LD BC,regERRR
IN A,(C)
RLCA
RET
;*********************************************
;*** Ожидание готовности к передаче данных ***
;*********************************************
WAITDRQ
LD BC,regSTAT
IN A,(C)
BIT 3,A
RET NZ
JR WAITDRQ
;***************************************
;*** Ожидание готовности накопителя ****
;***************************************
WAITDRDY
LD BC,regSTAT
IN A,(C)
BIT 6,A
RET NZ
JR WAITDRDY
;****************************
;*** Передача команды HDD ***
;****************************
SENDCOMMAND
LD BC,regCOMM
OUT (C),A
RET
;********************************
;*** Позиционирование головок ***
;********************************
;Hа входе:
;A=#A0 MASTER / #B0 SLAVE
;DE=номер цилиндра
;H=номер головки
;L=номер сектора
WRITECHS
LD BC,regDEVC
OR H
OUT (C),A
DEC B
OUT (C),D
DEC B
OUT (C),E
DEC B
OUT (C),L
RET
;********************************
;*** Чтение положения головки ***
;********************************
;Hа выходе:
;DE=номер цилиндра
;H=номер головки
;L=номер сектора
READCHS
LD BC,regDEVC
IN A,(C)
AND #0F
LD H,A
DEC B
IN D,(C)
DEC B
IN E,(C)
DEC B
IN L,(C)
RET
;**********************
;*** Чтение сектора ***
;**********************
;Hа входе:
;HL=адрес памяти куда читать
;Портит регистр DE
_RN EQU #10; Степень раскрытия цикла чтения
;Чем меньше значение, тем быстрее работает чтение, но больше
;занимает памяти. Число должно быть из ряда:1,2,4,8,16...256
READ_1S LD A,_RN
LD DE,#D8F8
READ_S DUP #100/_RN
DD 43EDA242EDA2 ;LD B,E:INI:LD B,D:INI
EDUP
DEC A
; IF0 ($-READ_S); блин, как сделать эту проверку?
; JR NZ,READ_S
; ELSE
JP NZ,READ_S
; ENDIF
RET
;**********************
;*** Запись сектора ***
;**********************
;Hа входе:
;HL адрес памяти откуда писать
;Hа выходе:
;HL адрес следующей ячейки памяти
;Портит регистр DE
_WN EQU #10; Степень раскрытия цикла записи
WRITE_1S
LD A,_WN
LD DE,#D8F8
LD (WRITESP),SP
LD SP,HL
WRITE_S DUP #100/_WN
DD E142ED6143ED69; POP HL:B,D:OUT (C),H:B,E:OUT (C),L
EDUP
DEC A
; JR NZ,WRITE_S
JP NZ,WRITE_S
LD H,A
LD L,A
ADD HL,SP
LD SP,#0000
RET
================================================== ==============
Подскажите правильную последовательность действий для записи на
диск, т.е. протокол общения с HDD в режиме записи.
откорректировать и не париться, но хочется разобраться в чём же
дело. Да и до ближайшего оффтопика мне тащиться три остановки...
[REAL ZX]