Aleks69 писал(а): ↑04.05.2020,11:30
Биос - сделаю дамп, сегодня вечером или завтра уже точно. Есть Checkit, еще кое-какие утилиты по DOS - PCProbe, PCDR, TS.
У Вас там 1Mbit ПЗУ (128KB) - скорее всего основной BIOS + VGA. Сделайте дамп
приложенной утилитой (bios128.exe). Обязательно отключите все shadow и кеши
перед этим!
Теперь продолжение.
В ходе сравнения обработчиков обнаружилось, что BIOS-ы весьма схожи, но есть
отличие в обработчике команд чтения/длинного чтения (с ECC байтами)
Вот код обработчика команды чтения из проблемных BIOS, он абсолютно
идентичен у 286 (BIOS 09/15/89) и 386DX-20 (BIOS 09/15/89) плат:
======================================================
; 286 (BIOS 09/15/89) and 386DX-20 (BIOS 09/15/89)
ata_read:
call chk_num_of_hdd
jb ata_read_exit
call chk_ata_status
jb ata_read_exit
mov di, bx
mov si, es
call en_h3_hdpt
test byte ptr ds:76h, 0C0h
jz skip_dis_retry
inc ah
skip_dis_retry:
call tf_write
call wp_set ; write precomp set
mov al, ah
call ata_cmd ; execute ata command
ata_read_sec:
call chk_busy_set_fl
jb ata_read_exit
mov es, si
mov cx, 100h ; read 256 words (sector)
mov dx, 1F0h ; data reg in dx
cli
cld
rep ins word ptr es:[di], dx ; reading sector
sti
test byte ptr [bp+8], 2 ; normal or long read?
jz skip_ecc_read
call chk_drq_and_dly
jb ata_read_exit
mov cx, 4 ; read 4 ECC words
read_ecc_bytes:
in al, dx
mov es:[di], al
inc di
jmp short $+2
jmp short $+2
jmp short $+2
loop read_ecc_bytes
skip_ecc_read:
call chk_err_set_bda ; check status and error reg (if need)
; and set BDA bytes
jnb ata_r_no_err
cmp byte ptr ds:74h, 11h
jnz set_error_flag
ata_r_no_err:
dec byte ptr [bp+3] ; [bp+3] sectors count
jnz ata_read_sec
set_error_flag:
mov ah, ds:74h
or ah, ah
jz ata_read_exit
stc
ata_read_exit:
retn
======================================================
А вот код из 286 (BIOS 04/09/90 года) и 386 платы M321 (BIOS 06/06/92),
где с чтением CF все нормально, обработчики у этих BIOS почти идентичны:
======================================================
; 386 M321 (BIOS 06/06/92) and 286 (BIOS 04/09/90)
ata_read:
call chk_num_of_hdd
jb ata_read_exit
call chk_ata_status
jb ata_read_exit
mov di, bx
mov si, es
call en_h3_hdpt ; enable head 3 and set HDPT's
test byte ptr ds:76h, 0C0h
jz skip_dis_retry
inc ah
skip_dis_retry:
call tf_write
call wp_set ; write pre-cmpensation set
mov al, ah
call ata_cmd
ata_read_sec:
call chk_busy_set_fl
jb ata_read_exit
call chk_err_set_bda ; check status and error reg (if need)
; and set BDA bytes
jnb ata_r_no_error ; if no errors, processed
cmp byte ptr ds:74h, 11h
jnz set_ah_err_code ; if ECC corrected error, also processed
ata_r_no_error:
mov es, si
mov cx, 100h
mov dx, 1F0h
cli
cld
rep ins word ptr es:[di], dx
sti
test byte ptr [bp+8], 2
jz skip_ecc_read
call chk_drq_and_dly ; check DRQ and delay, set time-out flag
jb ata_read_exit
mov cx, 4
read_ecc_bytes:
in al, dx
mov es:[di], al
inc di
jcxz $+2 ; (BIOS D286 used <jmp short $+2> commands)
jcxz $+2
jcxz $+2
loop read_ecc_bytes
skip_ecc_read:
dec byte ptr [bp+3]
jnz ata_read_sec
set_ah_err_code:
mov ah, ds:74h
or ah, ah
jz ata_read_exit
stc
ata_read_exit:
retn
======================================================
Можно видеть что в проблемных BIOS-ах происходит проверка регистров состояния
и ошибок (и установка флагов BDA) почти сразу же после чтения сектора (rep insw),
это собственно процедура chk_err_set_bda
А в BIOS-ах, где с чтением CF все нормально процедура chk_err_set_bda вызывается
до первого чтения сектора и далее она вызывается после каждого чтения очередного
сектора, но после процедуры chk_busy_set_fl, в которой есть внутреняя процедура
задержки.
Текущее предположение - CF не всегда успевает вовремя выставить правильные
биты в регистрах состояния и (возможно) регистра ошибок при чтении с количеством
секторов более определенного (и соответственно наш код ошибается после
определенного сектора). Так ли это надо еще проверить. И если так, то проверить
какие именно биты устанавливаются неверно. Возможно это случается и с какими-то
HDD, ведь код не случайно же изменили, а CF в 90 году еще и в проекте не было.
Буду проверять.
А вот код процедуры chk_err_set_bda
======================================================
chk_err_set_bda proc near
push dx
push ax
mov dx, 1F7h
in al, dx ; AT hard disk
; status register bits:
; 0: 1=prev cmd error
; 2: Corrected data
; 3: Data Request. Buffer is busy
; 4: Seek completed
; 5: Write fault
; 6: Drive ready (unless bit 4=0)
; 7: Busy
mov ds:8Ch, al ; set in BDA status that controller return
mov ah, 11h
test al, 4
jnz exitchk_setbda ; ECC error?
mov ah, 0CCh
test al, 20h
jnz exitchk_setbda ; write fault error?
mov ah, 0AAh
test al, 40h
jz exitchk_setbda ; Drive not ready error?
mov ah, 40h
test al, 10h
jz exitchk_setbda ; No seek completed error?
mov ah, 0
test al, 1
jz exitchk_setbda ; No error?
mov dx, 1F1h
in al, dx ; AT hard disk controller
; Error register. Bits for last error:
; 0: Data Address Mark not found
; 1: Track 0 Error
; 2: Command aborted
; 4: Sector ID not found
; 6: ECC Error: Uncorrectable data error
; 7: Bad block
mov ds:8Dh, al ; set in BDA error that controller return
mov ah, 2
test al, 1
jnz exitchk_setbda ; AMNF error?
mov ah, 1
test al, 4
jnz exitchk_setbda ; bad command?
mov ah, 4
test al, 10h
jnz exitchk_setbda ; sector not found error?
mov ah, 10h
test al, 40h
jnz exitchk_setbda ; ECC uncorrectable error?
mov ah, 40h
test al, 2
jnz exitchk_setbda ; seek (track 0) failure error?
mov ah, 0Ah
test al, 80h
jnz exitchk_setbda ; bad sector found?
mov ah, 0BBh ; set undefined error
exitchk_setbda:
mov ds:74h, ah
pop dx
mov al, dl
pop dx
or ah, ah
jz no_set_carry
stc
no_set_carry:
retn
chk_err_set_bda endp
======================================================