create branch

git-svn-id: svn://kolibrios.org@387 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge)
2007-03-05 20:17:43 +00:00
parent dfb6c4b5a7
commit f591baba3e
120 changed files with 75908 additions and 0 deletions
@@ -0,0 +1,546 @@
;**********************************************************
; Непосредственная работа с устройством СD (ATAPI)
;**********************************************************
; Автор исходного текста Кулаков Владимир Геннадьевич.
; Адаптация и доработка Mario79
; Процедура для полного считывания всех
; данных из сектора компакт-диска
; Автор текста программы Кулаков Владимир Геннадьевич.
; Максимальное количество повторений операции чтения
MaxRetr equ 3
; Предельное время ожидания готовности к приему команды
; (в тиках)
BSYWaitTime equ 1000 ;2
;*************************************************
;* ПОЛНОЕ ЧТЕНИЕ СЕКТОРА КОМПАКТ-ДИСКА *
;* Считываются данные пользователя, информация *
;* субканала и контрольная информация *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале; *
;* CDSectorAddress - адрес считываемого сектора. *
;* Данные считывается в массив CDDataBuf. *
;*************************************************
ReadCD:
pusha
; Задать размер сектора
mov [CDBlockSize],2048 ;2352
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать пакетную команду для считывания
; сектора данных
; Задать код команды Read CD
mov [PacketCommand],byte 0x28 ;0xBE
; Задать адрес сектора
mov AX,word [CDSectorAddress+2]
xchg AL,AH
mov word [PacketCommand+2],AX
mov AX,word [CDSectorAddress]
xchg AL,AH
mov word [PacketCommand+4],AX
; mov eax,[CDSectorAddress]
; mov [PacketCommand+2],eax
; Задать количество считываемых секторов
mov [PacketCommand+8],byte 1
; Задать считывание данных в полном объеме
; mov [PacketCommand+9],byte 0xF8
; Подать команду
call SendPacketDatCommand
; call test_mario79
popa
ret
;********************************************
;* ЧТЕНИЕ СЕКТОРА С ПОВТОРАМИ *
;* Многократное повторение чтения при сбоях *
;********************************************
ReadCDWRetr:
pusha
; Цикл, пока команда не выполнена успешно или не
; исчерпано количество попыток
mov ECX,MaxRetr
@@NextRetr:
; Подать команду
call ReadCD
cmp [DevErrorCode],0
je @@End_4
; Задержка на 2,5 секунды
mov EAX,[timer_ticks]
add EAX,250 ;50
@@Wait:
call change_task
cmp EAX,[timer_ticks]
ja @@Wait
loop @@NextRetr
; call test_mario79
; Сообщение об ошибке
; mov SI,offset ErrS
; call FatalError
@@End_4:
popa
ret
; Универсальные процедуры, обеспечивающие выполнение
; пакетных команд в режиме PIO
;
; Автор текста программы Кулаков Владимир Геннадьевич.
; Максимально допустимое время ожидания реакции
; устройства на пакетную команду (в тиках)
MaxCDWaitTime equ 1000 ;200 ;10 секунд
; Область памяти для формирования пакетной команды
PacketCommand: rb 12 ;DB 12 DUP (?)
; Область памяти для приема данных от дисковода
;CDDataBuf DB 4096 DUP (0)
; Размер принимаемого блока данных в байтах
CDBlockSize DW ?
; Адрес считываемого сектора данных
CDSectorAddress: DD ?
; Время начала очередной операции с диском
TickCounter_1 DD 0
; Время начала ожидания готовности устройства
WURStartTime DD 0
; указатель буфера для считывания
CDDataBuf_pointer dd 0
;****************************************************
;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
;* ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧУ ОДНОГО СЕКТОРА ДАННЫХ *
;* РАЗМЕРОМ 2048 БАЙТ ОТ УСТРОЙСТВА К ХОСТУ *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале; *
;* PacketCommand - 12-байтный командный пакет; *
;* CDBlockSize - размер принимаемого блока данных. *
;****************************************************
SendPacketDatCommand:
pushad
; Задать режим CHS
mov [ATAAddressMode],0
; Послать ATA-команду передачи пакетной команды
mov [ATAFeatures],0
mov [ATASectorCount],0
mov [ATASectorNumber],0
; Загрузить размер передаваемого блока
mov AX,[CDBlockSize]
mov [ATACylinder],AX
mov [ATAHead],0
mov [ATACommand],0A0h
call SendCommandToHDD_1
; call test_mario79
cmp [DevErrorCode],0 ;проверить код ошибки
jne @@End_8 ;закончить, сохранив код ошибки
; Ожидание готовности дисковода к приему
; пакетной команды
mov DX,[ATABasePortAddr]
add DX,7 ;порт 1х7h
@@WaitDevice0:
call change_task
; Проверить время выполнения команды
mov EAX,[timer_ticks]
sub EAX,[TickCounter_1]
cmp EAX,BSYWaitTime
ja @@Err1_1 ;ошибка тайм-аута
; Проверить готовность
in AL,DX
test AL,80h ;состояние сигнала BSY
jnz @@WaitDevice0
test AL,1 ;состояние сигнала ERR
jnz @@Err6
test AL,08h ;состояние сигнала DRQ
jz @@WaitDevice0
; Послать пакетную команду
cli
mov DX,[ATABasePortAddr]
mov AX,[PacketCommand]
out DX,AX
mov AX,[PacketCommand+2]
out DX,AX
mov AX,[PacketCommand+4]
out DX,AX
mov AX,[PacketCommand+6]
out DX,AX
mov AX,[PacketCommand+8]
out DX,AX
mov AX,[PacketCommand+10]
out DX,AX
sti
; Ожидание готовности данных
mov DX,[ATABasePortAddr]
add DX,7 ;порт 1х7h
@@WaitDevice1:
call change_task
; Проверить время выполнения команды
mov EAX,[timer_ticks]
sub EAX,[TickCounter_1]
cmp EAX,MaxCDWaitTime
ja @@Err1_1 ;ошибка тайм-аута
; Проверить готовность
in AL,DX
test AL,80h ;состояние сигнала BSY
jnz @@WaitDevice1
test AL,1 ;состояние сигнала ERR
jnz @@Err6_temp
test AL,08h ;состояние сигнала DRQ
jz @@WaitDevice1
cli
; Принять блок данных от контроллера
mov EDI,[CDDataBuf_pointer] ;0x7000 ;CDDataBuf
; Загрузить адрес регистра данных контроллера
mov DX,[ATABasePortAddr] ;порт 1x0h
; Загрузить в счетчик размер блока в байтах
mov CX,[CDBlockSize]
; Вычислить размер блока в 16-разрядных словах
shr CX,1 ;разделить размер блока на 2
; Принять блок данных
cld
rep insw
sti
; Успешное завершение приема данных
jmp @@End_8
; Записать код ошибки
@@Err1_1:
mov [DevErrorCode],1
jmp @@End_8
@@Err6_temp:
mov [DevErrorCode],7
jmp @@End_8
@@Err6:
mov [DevErrorCode],6
@@End_8:
popad
ret
;***********************************************
;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
;* НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ *
;* Входные параметры передаются через *
;* глобальные перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале; *
;* PacketCommand - 12-байтный командный пакет. *
;***********************************************
SendPacketNoDatCommand:
pushad
; Задать режим CHS
mov [ATAAddressMode],0
; Послать ATA-команду передачи пакетной команды
mov [ATAFeatures],0
mov [ATASectorCount],0
mov [ATASectorNumber],0
mov [ATACylinder],0
mov [ATAHead],0
mov [ATACommand],0A0h
call SendCommandToHDD_1
cmp [DevErrorCode],0 ;проверить код ошибки
jne @@End_9 ;закончить, сохранив код ошибки
; Ожидание готовности дисковода к приему
; пакетной команды
mov DX,[ATABasePortAddr]
add DX,7 ;порт 1х7h
@@WaitDevice0_1:
call change_task
; Проверить время ожидания
mov EAX,[timer_ticks]
sub EAX,[TickCounter_1]
cmp EAX,BSYWaitTime
ja @@Err1_3 ;ошибка тайм-аута
; Проверить готовность
in AL,DX
test AL,80h ;состояние сигнала BSY
jnz @@WaitDevice0_1
test AL,1 ;состояние сигнала ERR
jnz @@Err6_1
test AL,08h ;состояние сигнала DRQ
jz @@WaitDevice0_1
; Послать пакетную команду
; cli
mov DX,[ATABasePortAddr]
mov AX,word [PacketCommand]
out DX,AX
mov AX,word [PacketCommand+2]
out DX,AX
mov AX,word [PacketCommand+4]
out DX,AX
mov AX,word [PacketCommand+6]
out DX,AX
mov AX,word [PacketCommand+8]
out DX,AX
mov AX,word [PacketCommand+10]
out DX,AX
; sti
; Ожидание подтверждения приема команды
mov DX,[ATABasePortAddr]
add DX,7 ;порт 1х7h
@@WaitDevice1_1:
call change_task
; Проверить время выполнения команды
mov EAX,[timer_ticks]
sub EAX,[TickCounter_1]
cmp EAX,MaxCDWaitTime
ja @@Err1_3 ;ошибка тайм-аута
; Ожидать освобождения устройства
in AL,DX
test AL,80h ;состояние сигнала BSY
jnz @@WaitDevice1_1
test AL,1 ;состояние сигнала ERR
jnz @@Err6_1
test AL,40h ;состояние сигнала DRDY
jz @@WaitDevice1_1
jmp @@End_9
; Записать код ошибки
@@Err1_3:
mov [DevErrorCode],1
jmp @@End_9
@@Err6_1:
mov [DevErrorCode],6
@@End_9:
popad
ret
;****************************************************
;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ *
;* Входные параметры передаются через глобальные *
;* переменные: *
;* ChannelNumber - номер канала (1 или 2); *
;* DiskNumber - номер диска (0 или 1); *
;* ATAFeatures - "особенности"; *
;* ATASectorCount - количество секторов; *
;* ATASectorNumber - номер начального сектора; *
;* ATACylinder - номер начального цилиндра; *
;* ATAHead - номер начальной головки; *
;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); *
;* ATACommand - код команды. *
;* После успешного выполнения функции: *
;* в ATABasePortAddr - базовый адрес HDD; *
;* в DevErrorCode - ноль. *
;* При возникновении ошибки в DevErrorCode будет *
;* возвращен код ошибки. *
;****************************************************
SendCommandToHDD_1:
pushad
; Проверить значение кода режима
cmp [ATAAddressMode],1
ja @@Err2_4
; Проверить корректность номера канала
mov BX,[ChannelNumber]
cmp BX,1
jb @@Err3_4
cmp BX,2
ja @@Err3_4
; Установить базовый адрес
dec BX
shl BX,1
movzx ebx,bx
mov AX,[ebx+StandardATABases]
mov [ATABasePortAddr],AX
; Ожидание готовности HDD к приему команды
; Выбрать нужный диск
mov DX,[ATABasePortAddr]
add DX,6 ;адрес регистра головок
mov AL,[DiskNumber]
cmp AL,1 ;проверить номера диска
ja @@Err4_4
shl AL,4
or AL,10100000b
out DX,AL
; Ожидать, пока диск не будет готов
inc DX
; mov ecx,0xfff
mov eax,[timer_ticks]
mov [TickCounter_1],eax
@@WaitHDReady_2:
call change_task
; Проверить время ожидания
; dec ecx
; cmp ecx,0
; je @@Err1
mov eax,[timer_ticks]
sub eax,[TickCounter_1]
cmp eax,BSYWaitTime ;300 ;ожидать 3 сек.
ja @@Err1_4 ;ошибка тайм-аута
; Прочитать регистр состояния
in AL,DX
; Проверить состояние сигнала BSY
test AL,80h
jnz @@WaitHDReady_2
; Проверить состояние сигнала DRQ
test AL,08h
jnz @@WaitHDReady_2
; Загрузить команду в регистры контроллера
cli
mov DX,[ATABasePortAddr]
inc DX ;регистр "особенностей"
mov AL,[ATAFeatures]
out DX,AL
inc DX ;счетчик секторов
mov AL,[ATASectorCount]
out DX,AL
inc DX ;регистр номера сектора
mov AL,[ATASectorNumber]
out DX,AL
inc DX ;номер цилиндра (младший байт)
mov AX,[ATACylinder]
out DX,AL
inc DX ;номер цилиндра (старший байт)
mov AL,AH
out DX,AL
inc DX ;номер головки/номер диска
mov AL,[DiskNumber]
shl AL,4
cmp [ATAHead],0Fh ;проверить номер головки
ja @@Err5_4
or AL,[ATAHead]
or AL,10100000b
mov AH,[ATAAddressMode]
shl AH,6
or AL,AH
out DX,AL
; Послать команду
mov AL,[ATACommand]
inc DX ;регистр команд
out DX,AL
sti
; Сбросить признак ошибки
mov [DevErrorCode],0
jmp @@End_10
; Записать код ошибки
@@Err1_4:
mov [DevErrorCode],1
jmp @@End_10
@@Err2_4:
mov [DevErrorCode],2
jmp @@End_10
@@Err3_4:
mov [DevErrorCode],3
jmp @@End_10
@@Err4_4:
mov [DevErrorCode],4
jmp @@End_10
@@Err5_4:
mov [DevErrorCode],5
; Завершение работы программы
@@End_10:
sti
popad
ret
;*************************************************
;* ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
WaitUnitReady:
pusha
; Запомнить время начала операции
mov EAX,[timer_ticks]
mov [WURStartTime],EAX
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать команду TEST UNIT READY
mov [PacketCommand],word 00h
; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА
@@SendCommand:
; Подать команду проверки готовности
call SendPacketNoDatCommand
call change_task
; Проверить код ошибки
cmp [DevErrorCode],0
je @@End_11
; Проверить время ожидания готовности
mov EAX,[timer_ticks]
sub EAX,[WURStartTime]
cmp EAX,MaxCDWaitTime
jb @@SendCommand
; Ошибка тайм-аута
mov [DevErrorCode],1
@@End_11:
popa
ret
;*************************************************
;* ЗАГРУЗИТЬ НОСИТЕЛЬ В ДИСКОВОД *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
LoadMedium:
pusha
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать команду START/STOP UNIT
; Задать код команды
mov [PacketCommand],word 1Bh
; Задать операцию загрузки носителя
mov [PacketCommand+4],word 00000011b
; Подать команду
call SendPacketNoDatCommand
popa
ret
;*************************************************
;* ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
UnloadMedium:
pusha
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать команду START/STOP UNIT
; Задать код команды
mov [PacketCommand],word 1Bh
; Задать операцию извлечения носителя
mov [PacketCommand+4],word 00000010b
; Подать команду
call SendPacketNoDatCommand
popa
ret
;*************************************************
;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ *
;* Входные параметры передаются через глобальные *
;* переменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
ReadCapacity:
pusha
; Очистить буфер пакетной команды
call clear_packet_buffer
; Задать размер буфера в байтах
mov [CDBlockSize],8
; Сформировать команду READ CAPACITY
mov [PacketCommand],word 25h
; Подать команду
call SendPacketDatCommand
popa
ret
clear_packet_buffer:
; Очистить буфер пакетной команды
mov [PacketCommand],dword 0
mov [PacketCommand+4],dword 0
mov [PacketCommand+8],dword 0
ret
@@ -0,0 +1,261 @@
sys_cd_audio:
cmp word [cdbase],word 0
jnz @f
mov eax,1
ret
@@:
; eax=1 cdplay at ebx 0x00FFSSMM
; eax=2 get tracklist size of ecx to [ebx]
; eax=3 stop/pause playing
cmp eax,1
jnz nocdp
call sys_cdplay
ret
nocdp:
cmp eax,2
jnz nocdtl
mov edi,[TASK_BASE]
add edi,TASKDATA.mem_start
add ebx,[edi]
call sys_cdtracklist
ret
nocdtl:
cmp eax,3
jnz nocdpause
call sys_cdpause
ret
nocdpause:
mov eax,0xffffff01
ret
sys_cd_atapi_command:
pushad
mov dx,word [cdbase]
add dx,6
mov ax,word [cdid]
out dx,al
mov esi,10
call delay_ms
mov dx,word [cdbase]
add dx,7
in al,dx
and al,0x80
cmp al,0
jnz res
jmp cdl6
res:
mov dx,word [cdbase]
add dx,7
mov al,0x8
out dx,al
mov dx,word [cdbase]
add dx,0x206
mov al,0xe
out dx,al
mov esi,1
call delay_ms
mov dx,word [cdbase]
add dx,0x206
mov al,0x8
out dx,al
mov esi,30
call delay_ms
xor cx,cx
cdl5:
inc cx
cmp cx,10
jz cdl6
mov dx,word [cdbase]
add dx,7
in al,dx
and al,0x88
cmp al,0x00
jz cdl5
mov esi,100
call delay_ms
jmp cdl5
cdl6:
mov dx,word [cdbase]
add dx,4
mov al,0
out dx,al
mov dx,word [cdbase]
add dx,5
mov al,0
out dx,al
mov dx,word [cdbase]
add dx,7
mov al,0xec
out dx,al
mov esi,5
call delay_ms
mov dx,word [cdbase]
add dx,1
mov al,0
out dx,al
add dx,1
mov al,0
out dx,al
add dx,1
mov al,0
out dx,al
add dx,1
mov al,0
out dx,al
add dx,1
mov al,128
out dx,al
add dx,2
mov al,0xa0
out dx,al
xor cx,cx
mov dx,word [cdbase]
add dx,7
cdl1:
inc cx
cmp cx,100
jz cdl2
in al,dx
and ax,0x88
cmp al,0x8
jz cdl2
mov esi,2
call delay_ms
jmp cdl1
cdl2:
popad
ret
sys_cdplay:
mov ax,5
push ax
push ebx
cdplay:
call sys_cd_atapi_command
cli
mov dx,word [cdbase]
mov ax,0x0047
out dx,ax
mov al,1
mov ah,[esp+0] ; min xx
out dx,ax
mov ax,[esp+1] ; fr sec
out dx,ax
mov ax,256+99
out dx,ax
mov ax,0x0001
out dx,ax
mov ax,0x0000
out dx,ax
mov esi,10
call delay_ms
sti
add dx,7
in al,dx
test al,1
jz cdplayok
mov ax,[esp+4]
dec ax
mov [esp+4],ax
cmp ax,0
jz cdplayfail
jmp cdplay
cdplayfail:
cdplayok:
pop ebx
pop ax
xor eax, eax
ret
sys_cdtracklist:
push ebx
tcdplay:
call sys_cd_atapi_command
mov dx,word [cdbase]
mov ax,0x43+2*256
out dx,ax
mov ax,0x0
out dx,ax
mov ax,0x0
out dx,ax
mov ax,0x0
out dx,ax
mov ax,200
out dx,ax
mov ax,0x0
out dx,ax
in al,dx
mov cx,1000
mov dx,word [cdbase]
add dx,7
cld
cdtrnwewait:
mov esi,10
call delay_ms
in al,dx
and al,128
cmp al,0
jz cdtrl1
loop cdtrnwewait
cdtrl1:
; read the result
mov ecx,[esp+0]
mov dx,word [cdbase]
cdtrread:
add dx,7
in al,dx
and al,8
cmp al,8
jnz cdtrdone
sub dx,7
in ax,dx
mov [ecx],ax
add ecx,2
jmp cdtrread
cdtrdone:
pop ecx
xor eax, eax
ret
sys_cdpause:
call sys_cd_atapi_command
mov dx,word [cdbase]
mov ax,0x004B
out dx,ax
mov ax,0
out dx,ax
mov ax,0
out dx,ax
mov ax,0
out dx,ax
mov ax,0
out dx,ax
mov ax,0
out dx,ax
mov esi,10
call delay_ms
add dx,7
in al,dx
xor eax, eax
ret
@@ -0,0 +1,73 @@
iglobal
;function pointers.
fdc_irq_func dd fdc_null
endg
uglobal
dmasize db 0x0
dmamode db 0x0
endg
fdc_init: ;start with clean tracks.
mov edi,0xD201
mov al,0
mov ecx,160
rep stosb
ret
fdc_filesave: ;ebx: cluster to be saved.
pusha ;returns immediately. does not trigger a write.
mov eax,ebx
add eax,31
mov bl,18
div bl
mov ah,0
add eax,0xD201
mov [eax],byte 1 ;This track is now dirty.
popa
ret
fdc_irq:
call [fdc_irq_func]
fdc_null:
ret
save_image:
call reserve_flp
call restorefatchain
pusha
call check_label
cmp [FDC_Status],0
jne unnecessary_save_image
mov [FDD_Track],0 ; Öèëèíäð
mov [FDD_Head],0 ; Ñòîðîíà
mov [FDD_Sector],1 ; Ñåêòîð
mov esi,RAMDISK
call SeekTrack
save_image_1:
push esi
call take_data_from_application_1
pop esi
add esi,512
call WriteSectWithRetr
; call WriteSector
cmp [FDC_Status],0
jne unnecessary_save_image
inc [FDD_Sector]
cmp [FDD_Sector],19
jne save_image_1
mov [FDD_Sector],1
inc [FDD_Head]
cmp [FDD_Head],2
jne save_image_1
mov [FDD_Head],0
inc [FDD_Track]
call SeekTrack
cmp [FDD_Track],80
jne save_image_1
unnecessary_save_image:
mov [fdc_irq_func],fdc_null
popa
mov [flp_status],0
ret
@@ -0,0 +1,615 @@
;**********************************************************
; Непосредственная работа с контроллером гибкого диска
;**********************************************************
; Автор исходного текста Кулаков Владимир Геннадьевич.
; Адаптация и доработка Mario79
give_back_application_data: ; переслать приложению
mov edi,[TASK_BASE]
mov edi,[edi+TASKDATA.mem_start]
add edi,ecx
give_back_application_data_1:
mov esi,FDD_BUFF ;FDD_DataBuffer ;0x40000
xor ecx,ecx
mov cx,128
cld
rep movsd
ret
take_data_from_application: ; взять из приложени
mov esi,[TASK_BASE]
mov esi,[esi+TASKDATA.mem_start]
add esi,ecx
take_data_from_application_1:
mov edi,FDD_BUFF ;FDD_DataBuffer ;0x40000
xor ecx,ecx
mov cx,128
cld
rep movsd
ret
; Коды завершения операции с контроллером (FDC_Status)
FDC_Normal equ 0 ;нормальное завершение
FDC_TimeOut equ 1 ;ошибка тайм-аута
FDC_DiskNotFound equ 2 ;в дисководе нет диска
FDC_TrackNotFound equ 3 ;дорожка не найдена
FDC_SectorNotFound equ 4 ;сектор не найден
; Максимальные значения координат сектора (заданные
; значения соответствуют параметрам стандартного
; трехдюймового гибкого диска объемом 1,44 Мб)
MAX_Track equ 79
MAX_Head equ 1
MAX_Sector equ 18
uglobal
; Счетчик тиков таймера
TickCounter dd ?
; Код завершения операции с контроллером НГМД
FDC_Status DB ?
; Флаг прерывания от НГМД
FDD_IntFlag DB ?
; Момент начала последней операции с НГМД
FDD_Time DD ?
; Номер дисковода
FDD_Type db 0
; Координаты сектора
FDD_Track DB ?
FDD_Head DB ?
FDD_Sector DB ?
; Блок результата операции
FDC_ST0 DB ?
FDC_ST1 DB ?
FDC_ST2 DB ?
FDC_C DB ?
FDC_H DB ?
FDC_R DB ?
FDC_N DB ?
; Счетчик повторения операции чтени
ReadRepCounter DB ?
; Счетчик повторения операции рекалибровки
RecalRepCounter DB ?
endg
; Область памяти для хранения прочитанного сектора
;FDD_DataBuffer: times 512 db 0 ;DB 512 DUP (?)
fdd_motor_status db 0
timer_fdd_motor dd 0
;*************************************
;* ИНИЦИАЛИЗАЦИЯ РЕЖИМА ПДП ДЛЯ НГМД *
;*************************************
Init_FDC_DMA:
pushad
mov al,0
out 0x0c,al ; reset the flip-flop to a known state.
mov al,6 ; mask channel 2 so we can reprogram it.
out 0x0a,al
mov al,[dmamode] ; 0x46 -> Read from floppy - 0x4A Write to floppy
out 0x0b,al
mov al,0
out 0x0c,al ; reset the flip-flop to a known state.
mov eax,0xD000
out 0x04,al ; set the channel 2 starting address to 0
shr eax,8
out 0x04,al
shr eax,8
out 0x81,al
mov al,0
out 0x0c, al ; reset flip-flop
mov al, 0xff ;set count (actual size -1)
out 0x5, al
mov al,0x1 ;[dmasize] ;(0x1ff = 511 / 0x23ff =9215)
out 0x5,al
mov al,2
out 0xa,al
popad
ret
;***********************************
;* ЗАПИСАТЬ БАЙТ В ПОРТ ДАННЫХ FDC *
;* Параметры: *
;* AL - выводимый байт. *
;***********************************
FDCDataOutput:
; pusha
push eax ecx edx
mov AH,AL ;запомнить байт в AH
; Сбросить переменную состояния контроллера
mov [FDC_Status],FDC_Normal
; Проверить готовность контроллера к приему данных
mov DX,3F4h ;(порт состояния FDC)
mov ecx, 0x10000 ;установить счетчик тайм-аута
@@TestRS:
in AL,DX ;прочитать регистр RS
and AL,0C0h ;выделить разряды 6 и 7
cmp AL,80h ;проверить разряды 6 и 7
je @@OutByteToFDC
loop @@TestRS
; Ошибка тайм-аута
mov [FDC_Status],FDC_TimeOut
jmp @@End_5
; Вывести байт в порт данных
@@OutByteToFDC:
inc DX
mov AL,AH
out DX,AL
@@End_5:
; popa
pop edx ecx eax
ret
;******************************************
;* ПРОЧИТАТЬ БАЙТ ИЗ ПОРТА ДАННЫХ FDC *
;* Процедура не имеет входных параметров. *
;* Выходные данные: *
;* AL - считанный байт. *
;******************************************
FDCDataInput:
push ECX
push DX
; Сбросить переменную состояния контроллера
mov [FDC_Status],FDC_Normal
; Проверить готовность контроллера к передаче данных
mov DX,3F4h ;(порт состояния FDC)
xor CX,CX ;установить счетчик тайм-аута
@@TestRS_1:
in AL,DX ;прочитать регистр RS
and AL,0C0h ;выдлить разряды 6 и 7
cmp AL,0C0h ;проверить разряды 6 и 7
je @@GetByteFromFDC
loop @@TestRS_1
; Ошибка тайм-аута
mov [FDC_Status],FDC_TimeOut
jmp @@End_6
; Ввести байт из порта данных
@@GetByteFromFDC:
inc DX
in AL,DX
@@End_6: pop DX
pop ECX
ret
;*********************************************
;* ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД *
;*********************************************
FDCInterrupt:
; Установить флаг прерывани
mov [FDD_IntFlag],1
ret
;******************************************
;* УСТАНОВИТЬ НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЙ *
;* НГМД *
;******************************************
SetUserInterrupts:
mov [fdc_irq_func],FDCInterrupt
ret
;*******************************************
;* ОЖИДАНИЕ ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД *
;*******************************************
WaitFDCInterrupt:
pusha
; Сбросить байт состояния операции
mov [FDC_Status],FDC_Normal
; Сбросить флаг прерывани
mov [FDD_IntFlag],0
; Обнулить счетчик тиков
mov eax,[timer_ticks]
mov [TickCounter],eax
; Ожидать установки флага прерывания НГМД
@@TestRS_2:
cmp [FDD_IntFlag],0
jnz @@End_7 ;прерывание произошло
call change_task
mov eax,[timer_ticks]
sub eax,[TickCounter]
cmp eax,50 ;25 ;5 ;ожидать 5 тиков
jb @@TestRS_2
; jl @@TestRS_2
; Ошибка тайм-аута
mov [FDC_Status],FDC_TimeOut
; mov [flp_status],0
@@End_7: popa
ret
;*********************************
;* ВКЛЮЧИТЬ МОТОР ДИСКОВОДА "A:" *
;*********************************
FDDMotorON:
pusha
; cmp [fdd_motor_status],1
; je fdd_motor_on
mov al,[flp_number]
cmp [fdd_motor_status],al
je fdd_motor_on
; Произвести сброс контроллера НГМД
mov DX,3F2h ;порт управления двигателями
mov AL,0
out DX,AL
; Выбрать и включить мотор дисковода
cmp [flp_number],1
jne FDDMotorON_B
; call FDDMotorOFF_B
mov AL,1Ch ; Floppy A
jmp FDDMotorON_1
FDDMotorON_B:
; call FDDMotorOFF_A
mov AL,2Dh ; Floppy B
FDDMotorON_1:
out DX,AL
; Обнулить счетчик тиков
mov eax,[timer_ticks]
mov [TickCounter],eax
; Ожидать 0,5 с
@@dT:
call change_task
mov eax,[timer_ticks]
sub eax,[TickCounter]
cmp eax,50 ;10
jb @@dT
cmp [flp_number],1
jne fdd_motor_on_B
mov [fdd_motor_status],1
jmp fdd_motor_on
fdd_motor_on_B:
mov [fdd_motor_status],2
fdd_motor_on:
call save_timer_fdd_motor
popa
ret
;*****************************************
;* СОХРАНЕНИЕ УКАЗАТЕЛЯ ВРЕМЕНИ *
;*****************************************
save_timer_fdd_motor:
mov eax,[timer_ticks]
mov [timer_fdd_motor],eax
ret
;*****************************************
;* ПРОВЕРКА ЗАДЕРЖКИ ВЫКЛЮЧЕНИЯ МОТОРА *
;*****************************************
check_fdd_motor_status:
cmp [fdd_motor_status],0
je end_check_fdd_motor_status_1
mov eax,[timer_ticks]
sub eax,[timer_fdd_motor]
cmp eax,500
jb end_check_fdd_motor_status
call FDDMotorOFF
mov [fdd_motor_status],0
end_check_fdd_motor_status_1:
mov [flp_status],0
end_check_fdd_motor_status:
ret
;**********************************
;* ВЫКЛЮЧИТЬ МОТОР ДИСКОВОДА *
;**********************************
FDDMotorOFF:
push AX
push DX
cmp [flp_number],1
jne FDDMotorOFF_1
call FDDMotorOFF_A
jmp FDDMotorOFF_2
FDDMotorOFF_1:
call FDDMotorOFF_B
FDDMotorOFF_2:
pop DX
pop AX
; сброс флагов кеширования в связи с устареванием информации
mov [root_read],0
mov [flp_fat],0
ret
FDDMotorOFF_A:
mov DX,3F2h ;порт управления двигателями
mov AL,0Ch ; Floppy A
out DX,AL
ret
FDDMotorOFF_B:
mov DX,3F2h ;порт управления двигателями
mov AL,5h ; Floppy B
out DX,AL
ret
;*******************************
;* РЕКАЛИБРОВКА ДИСКОВОДА "A:" *
;*******************************
RecalibrateFDD:
pusha
call save_timer_fdd_motor
; Подать команду "Рекалибровка"
mov AL,07h
call FDCDataOutput
mov AL,00h
call FDCDataOutput
; Ожидать завершения операции
call WaitFDCInterrupt
; cmp [FDC_Status],0
; je no_fdc_status_error
; mov [flp_status],0
;no_fdc_status_error:
call save_timer_fdd_motor
popa
ret
;*****************************************************
;* ПОИСК ДОРОЖКИ *
;* Параметры передаются через глобальные переменные: *
;* FDD_Track - номер дорожки (0-79); *
;* FDD_Head - номер головки (0-1). *
;* Результат операции заносится в FDC_Status. *
;*****************************************************
SeekTrack:
pusha
call save_timer_fdd_motor
; Подать команду "Поиск"
mov AL,0Fh
call FDCDataOutput
; Передать байт номера головки/накопител
mov AL,[FDD_Head]
shl AL,2
call FDCDataOutput
; Передать байт номера дорожки
mov AL,[FDD_Track]
call FDCDataOutput
; Ожидать завершения операции
call WaitFDCInterrupt
cmp [FDC_Status],FDC_Normal
jne @@Exit
; Сохранить результат поиска
mov AL,08h
call FDCDataOutput
call FDCDataInput
mov [FDC_ST0],AL
call FDCDataInput
mov [FDC_C],AL
; Проверить результат поиска
; Поиск завершен?
test [FDC_ST0],100000b
je @@Err
; Заданный трек найден?
mov AL,[FDC_C]
cmp AL,[FDD_Track]
jne @@Err
; Номер головки совпадает с заданным?
mov AL,[FDC_ST0]
and AL,100b
shr AL,2
cmp AL,[FDD_Head]
jne @@Err
; Операция завершена успешно
mov [FDC_Status],FDC_Normal
jmp @@Exit
@@Err: ; Трек не найден
mov [FDC_Status],FDC_TrackNotFound
; mov [flp_status],0
@@Exit:
call save_timer_fdd_motor
popa
ret
;*******************************************************
;* ЧТЕНИЕ СЕКТОРА ДАННЫХ *
;* Параметры передаются через глобальные переменные: *
;* FDD_Track - номер дорожки (0-79); *
;* FDD_Head - номер головки (0-1); *
;* FDD_Sector - номер сектора (1-18). *
;* Результат операции заносится в FDC_Status. *
;* В случае успешного выполнения операции чтения *
;* содержимое сектора будет занесено в FDD_DataBuffer. *
;*******************************************************
ReadSector:
pushad
call save_timer_fdd_motor
; Установить скорость передачи 500 Кбайт/с
mov AX,0
mov DX,03F7h
out DX,AL
; Инициализировать канал прямого доступа к памяти
mov [dmamode],0x46
call Init_FDC_DMA
; Подать команду "Чтение данных"
mov AL,0E6h ;чтение в мультитрековом режиме
call FDCDataOutput
mov AL,[FDD_Head]
shl AL,2
call FDCDataOutput
mov AL,[FDD_Track]
call FDCDataOutput
mov AL,[FDD_Head]
call FDCDataOutput
mov AL,[FDD_Sector]
call FDCDataOutput
mov AL,2 ;код размера сектора (512 байт)
call FDCDataOutput
mov AL,18 ;+1; 3Fh ;число секторов на дорожке
call FDCDataOutput
mov AL,1Bh ;значение GPL
call FDCDataOutput
mov AL,0FFh ;значение DTL
call FDCDataOutput
; Ожидаем прерывание по завершении операции
call WaitFDCInterrupt
cmp [FDC_Status],FDC_Normal
jne @@Exit_1
; Считываем статус завершения операции
call GetStatusInfo
test [FDC_ST0],11011000b
jnz @@Err_1
mov [FDC_Status],FDC_Normal
jmp @@Exit_1
@@Err_1: mov [FDC_Status],FDC_SectorNotFound
; mov [flp_status],0
@@Exit_1:
call save_timer_fdd_motor
popad
ret
;*******************************************************
;* ЧТЕНИЕ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ) *
;* Параметры передаются через глобальные переменные: *
;* FDD_Track - номер дорожки (0-79); *
;* FDD_Head - номер головки (0-1); *
;* FDD_Sector - номер сектора (1-18). *
;* Результат операции заносится в FDC_Status. *
;* В случае успешного выполнения операции чтения *
;* содержимое сектора будет занесено в FDD_DataBuffer. *
;*******************************************************
ReadSectWithRetr:
pusha
; Обнулить счетчик повторения операции рекалибровки
mov [RecalRepCounter],0
@@TryAgain:
; Обнулить счетчик повторения операции чтени
mov [ReadRepCounter],0
@@ReadSector_1:
call ReadSector
cmp [FDC_Status],0
je @@Exit_2
cmp [FDC_Status],1
je @@Err_3
; Троекратное повторение чтени
inc [ReadRepCounter]
cmp [ReadRepCounter],3
jb @@ReadSector_1
; Троекратное повторение рекалибровки
call RecalibrateFDD
call SeekTrack
inc [RecalRepCounter]
cmp [RecalRepCounter],3
jb @@TryAgain
; mov [flp_status],0
@@Exit_2:
popa
ret
@@Err_3:
mov [flp_status],0
popa
ret
;*******************************************************
;* ЗАПИСЬ СЕКТОРА ДАННЫХ *
;* Параметры передаются через глобальные переменные: *
;* FDD_Track - номер дорожки (0-79); *
;* FDD_Head - номер головки (0-1); *
;* FDD_Sector - номер сектора (1-18). *
;* Результат операции заносится в FDC_Status. *
;* В случае успешного выполнения операции записи *
;* содержимое FDD_DataBuffer будет занесено в сектор. *
;*******************************************************
WriteSector:
pushad
call save_timer_fdd_motor
; Установить скорость передачи 500 Кбайт/с
mov AX,0
mov DX,03F7h
out DX,AL
; Инициализировать канал прямого доступа к памяти
mov [dmamode],0x4A
call Init_FDC_DMA
; Подать команду "Запись данных"
mov AL,0xC5 ;0x45 ;запись в мультитрековом режиме
call FDCDataOutput
mov AL,[FDD_Head]
shl AL,2
call FDCDataOutput
mov AL,[FDD_Track]
call FDCDataOutput
mov AL,[FDD_Head]
call FDCDataOutput
mov AL,[FDD_Sector]
call FDCDataOutput
mov AL,2 ;код размера сектора (512 байт)
call FDCDataOutput
mov AL,18; 3Fh ;число секторов на дорожке
call FDCDataOutput
mov AL,1Bh ;значение GPL
call FDCDataOutput
mov AL,0FFh ;значение DTL
call FDCDataOutput
; Ожидаем прерывание по завершении операции
call WaitFDCInterrupt
cmp [FDC_Status],FDC_Normal
jne @@Exit_3
; Считываем статус завершения операции
call GetStatusInfo
test [FDC_ST0],11000000b ;11011000b
jnz @@Err_2
mov [FDC_Status],FDC_Normal
jmp @@Exit_3
@@Err_2: mov [FDC_Status],FDC_SectorNotFound
@@Exit_3:
call save_timer_fdd_motor
popad
ret
;*******************************************************
;* ЗАПИСЬ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ) *
;* Параметры передаются через глобальные переменные: *
;* FDD_Track - номер дорожки (0-79); *
;* FDD_Head - номер головки (0-1); *
;* FDD_Sector - номер сектора (1-18). *
;* Результат операции заносится в FDC_Status. *
;* В случае успешного выполнения операции записи *
;* содержимое FDD_DataBuffer будет занесено в сектор. *
;*******************************************************
WriteSectWithRetr:
pusha
; Обнулить счетчик повторения операции рекалибровки
mov [RecalRepCounter],0
@@TryAgain_1:
; Обнулить счетчик повторения операции чтени
mov [ReadRepCounter],0
@@WriteSector_1:
call WriteSector
cmp [FDC_Status],0
je @@Exit_4
cmp [FDC_Status],1
je @@Err_4
; Троекратное повторение чтени
inc [ReadRepCounter]
cmp [ReadRepCounter],3
jb @@WriteSector_1
; Троекратное повторение рекалибровки
call RecalibrateFDD
call SeekTrack
inc [RecalRepCounter]
cmp [RecalRepCounter],3
jb @@TryAgain_1
@@Exit_4:
popa
ret
@@Err_4:
mov [flp_status],0
popa
ret
;*********************************************
;* ПОЛУЧИТЬ ИНФОРМАЦИЮ О РЕЗУЛЬТАТЕ ОПЕРАЦИИ *
;*********************************************
GetStatusInfo:
push AX
call FDCDataInput
mov [FDC_ST0],AL
call FDCDataInput
mov [FDC_ST1],AL
call FDCDataInput
mov [FDC_ST2],AL
call FDCDataInput
mov [FDC_C],AL
call FDCDataInput
mov [FDC_H],AL
call FDCDataInput
mov [FDC_R],AL
call FDCDataInput
mov [FDC_N],AL
pop AX
ret
+863
View File
@@ -0,0 +1,863 @@
; Low-level driver for HDD access
; DMA support by Mario79
;**************************************************************************
;
; 0x600008 - first entry in cache list
;
; +0 - lba sector
; +4 - state of cache sector
; 0 = empty
; 1 = used for read ( same as in hd )
; 2 = used for write ( differs from hd )
;
; +65536 - cache entries
;
;**************************************************************************
align 4
hd_read:
;-----------------------------------------------------------
; input : eax = block to read
; ebx = destination
;-----------------------------------------------------------
and [hd_error], 0
push ecx esi edi ; scan cache
mov ecx,cache_max ; entries in cache
mov esi,0x600000+8
mov edi,1
hdreadcache:
cmp dword [esi+4],0 ; empty
je nohdcache
cmp [esi],eax ; correct sector
je yeshdcache
nohdcache:
add esi,8
inc edi
dec ecx
jnz hdreadcache
call find_empty_slot ; ret in edi
cmp [hd_error],0
jne return_01
cmp [dma_hdd], 1
jnz .nodma
call hd_read_dma
jmp @f
.nodma:
call hd_read_pio
@@:
lea esi,[edi*8+0x600000]
mov [esi],eax ; sector number
mov dword [esi+4],1 ; hd read - mark as same as in hd
yeshdcache:
mov esi,edi
shl esi,9
add esi,0x600000+65536
mov edi,ebx
mov ecx,512/4
cld
rep movsd ; move data
return_01:
pop edi esi ecx
ret
align 4
hd_read_pio:
push eax edx
call wait_for_hd_idle
cmp [hd_error],0
jne hd_read_error
cli
xor eax,eax
mov edx,[hdbase]
inc edx
out dx,al ; ATAFeatures ॣ¨áâà "®á®¡¥­­®á⥩"
inc edx
inc eax
out dx,al ; ATASectorCount áçñâ稪 ᥪâ®à®¢
inc edx
mov eax,[esp+4]
out dx,al ; ATASectorNumber ॣ¨áâà ­®¬¥à  ᥪâ®à 
shr eax,8
inc edx
out dx,al ; ATACylinder ­®¬¥à 樫¨­¤à  (¬« ¤è¨© ¡ ©â)
shr eax,8
inc edx
out dx,al ; ­®¬¥à 樫¨­¤à  (áâ à訩 ¡ ©â)
shr eax,8
inc edx
and al,1+2+4+8
add al,byte [hdid]
add al,128+64+32
out dx,al ; ­®¬¥à £®«®¢ª¨/­®¬¥à ¤¨áª 
inc edx
mov al,20h
out dx,al ; ATACommand ॣ¨áâà ª®¬ ­¤
sti
call wait_for_sector_buffer
cmp [hd_error],0
jne hd_read_error
cli
push edi
shl edi,9
add edi,0x600000+65536
mov ecx,256
mov edx,[hdbase]
cld
rep insw
pop edi
sti
pop edx eax
ret
disable_ide_int:
; mov edx,[hdbase]
; add edx,0x206
; mov al,2
; out dx,al
cli
ret
enable_ide_int:
; mov edx,[hdbase]
; add edx,0x206
; mov al,0
; out dx,al
sti
ret
align 4
hd_write:
;-----------------------------------------------------------
; input : eax = block
; ebx = pointer to memory
;-----------------------------------------------------------
push ecx esi edi
; check if the cache already has the sector and overwrite it
mov ecx,cache_max
mov esi,0x600000+8
mov edi,1
hdwritecache:
cmp dword [esi+4],0 ; if cache slot is empty
je not_in_cache_write
cmp [esi],eax ; if the slot has the sector
je yes_in_cache_write
not_in_cache_write:
add esi,8
inc edi
dec ecx
jnz hdwritecache
; sector not found in cache
; write the block to a new location
call find_empty_slot ; ret in edi
cmp [hd_error],0
jne hd_write_access_denied
lea esi,[edi*8+0x600000]
mov [esi],eax ; sector number
yes_in_cache_write:
mov dword [esi+4],2 ; write - differs from hd
shl edi,9
add edi,0x600000+65536
mov esi,ebx
mov ecx,512/4
cld
rep movsd ; move data
hd_write_access_denied:
pop edi esi ecx
ret
write_cache:
;-----------------------------------------------------------
; write all changed sectors to disk
;-----------------------------------------------------------
push eax ecx edx esi edi
; write difference ( 2 ) from cache to hd
mov ecx,cache_max
mov esi,0x600000+8
mov edi,1
write_cache_more:
cmp dword [esi+4],2 ; if cache slot is not different
jne .write_chain
mov dword [esi+4],1 ; same as in hd
mov eax,[esi] ; eax = sector to write
cmp eax,[PARTITION_START]
jb danger
cmp eax,[PARTITION_END]
ja danger
cmp [allow_dma_write], 1
jnz .nodma
cmp [dma_hdd], 1
jnz .nodma
; Ž¡ê¥¤¨­ï¥¬ § ¯¨áì æ¥¯®çª¨ ¯®á«¥¤®¢ â¥«ì­ëå ᥪâ®à®¢ ¢ ®¤­® ®¡à é¥­¨¥ ª ¤¨áªã
cmp ecx, 1
jz .nonext
cmp dword [esi+8+4], 2
jnz .nonext
push eax
inc eax
cmp eax, [esi+8]
pop eax
jnz .nonext
cmp [cache_chain_started], 1
jz @f
mov [cache_chain_started], 1
mov [cache_chain_size], 0
mov [cache_chain_pos], edi
mov [cache_chain_ptr], esi
@@:
inc [cache_chain_size]
cmp [cache_chain_size], 64
jnz .continue
jmp .write_chain
.nonext:
call flush_cache_chain
mov [cache_chain_size], 1
mov [cache_chain_ptr], esi
call write_cache_sector
jmp .continue
.nodma:
call cache_write_pio
.write_chain:
call flush_cache_chain
.continue:
danger:
add esi,8
inc edi
dec ecx
jnz write_cache_more
call flush_cache_chain
return_02:
pop edi esi edx ecx eax
ret
flush_cache_chain:
cmp [cache_chain_started], 0
jz @f
call write_cache_chain
mov [cache_chain_started], 0
@@:
ret
align 4
cache_write_pio:
call disable_ide_int
call wait_for_hd_idle
cmp [hd_error],0
jne hd_write_error
; cli
xor eax,eax
mov edx,[hdbase]
inc edx
out dx,al
inc edx
inc eax
out dx,al
inc edx
mov eax,[esi] ; eax = sector to write
out dx,al
shr eax,8
inc edx
out dx,al
shr eax,8
inc edx
out dx,al
shr eax,8
inc edx
and al,1+2+4+8
add al,byte [hdid]
add al,128+64+32
out dx,al
inc edx
mov al,30h
out dx,al
; sti
call wait_for_sector_buffer
cmp [hd_error],0
jne hd_write_error
push ecx esi
; cli
mov esi,edi
shl esi,9
add esi,0x600000+65536 ; esi = from memory position
mov ecx,256
mov edx,[hdbase]
cld
rep outsw
; sti
call enable_ide_int
pop esi ecx
ret
align 4
find_empty_slot:
;-----------------------------------------------------------
; find empty or read slot, flush cache if next 10% is used by write
; output : edi = cache slot
;-----------------------------------------------------------
; push ecx esi
search_again:
mov ecx,cache_max*10/100
mov edi,[cache_search_start]
search_for_empty:
inc edi
cmp edi,cache_max
jbe inside_cache
mov edi,1
inside_cache:
cmp dword [edi*8+0x600000+4],2 ; get cache slot info
jb found_slot ; it's empty or read
dec ecx
jnz search_for_empty
call write_cache ; no empty slots found, write all
cmp [hd_error],0
jne found_slot_access_denied
jmp search_again ; and start again
found_slot:
mov [cache_search_start],edi
found_slot_access_denied:
ret
align 4
clear_hd_cache:
push eax ecx edi
mov edi,0x600000
mov ecx,16384
xor eax,eax
cld
rep stosd ; clear hd cache with 0
mov [cache_search_start],eax
mov [fat_in_cache],-1
mov [fat_change],0
pop edi ecx eax
ret
save_hd_wait_timeout:
push eax
mov eax,[timer_ticks];[0xfdf0]
add eax,300 ; 3 sec timeout
mov [hd_wait_timeout],eax
pop eax
ret
align 4
check_hd_wait_timeout:
push eax
mov eax,[hd_wait_timeout]
cmp [timer_ticks], eax ;[0xfdf0],eax
jg hd_timeout_error
pop eax
mov [hd_error],0
ret
;iglobal
; hd_timeout_str db 'K : FS - HD timeout',0
; hd_read_str db 'K : FS - HD read error',0
; hd_write_str db 'K : FS - HD write error',0
; hd_lba_str db 'K : FS - HD LBA error',0
;endg
hd_timeout_error:
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_timeout_str
; call sys_msg_board_str
DEBUGF 1,"K : FS - HD timeout\n"
; jmp $
mov [hd_error],1
pop eax
ret
hd_read_error:
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_read_str
; call sys_msg_board_str
DEBUGF 1,"K : FS - HD read error\n"
pop edx eax
ret
hd_write_error:
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_write_str
; call sys_msg_board_str
DEBUGF 1,"K : FS - HD write error\n"
ret
hd_write_error_dma:
; call clear_hd_cache
; call clear_application_table_status
; mov esi, hd_write_str
; call sys_msg_board_str
DEBUGF 1,"K : FS - HD read error\n"
pop esi
ret
hd_lba_error:
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_lba_str
; call sys_msg_board_str
DEBUGF 1,"K : FS - HD LBA error\n"
jmp LBA_read_ret
align 4
wait_for_hd_idle:
push eax edx
call save_hd_wait_timeout
mov edx,[hdbase]
add edx,0x7
wfhil1:
call check_hd_wait_timeout
cmp [hd_error],0
jne @f
in al,dx
test al,128
jnz wfhil1
@@:
pop edx eax
ret
align 4
wait_for_sector_buffer:
push eax edx
mov edx,[hdbase]
add edx,0x7
call save_hd_wait_timeout
hdwait_sbuf: ; wait for sector buffer to be ready
call check_hd_wait_timeout
cmp [hd_error],0
jne @f
in al,dx
test al,8
jz hdwait_sbuf
mov [hd_error],0
cmp [hd_setup],1 ; do not mark error for setup request
je buf_wait_ok
test al,1 ; previous command ended up with an error
jz buf_wait_ok
@@:
mov [hd_error],1
buf_wait_ok:
pop edx eax
ret
; \begin{Mario79}
align 4
wait_for_sector_dma_ide0:
push eax
push edx
call save_hd_wait_timeout
.wait:
call change_task
cmp [irq14_func], hdd_irq14
jnz .done
call check_hd_wait_timeout
cmp [hd_error], 0
jz .wait
mov [irq14_func], hdd_irq_null
mov dx, [IDEContrRegsBaseAddr]
mov al, 0
out dx, al
.done:
pop edx
pop eax
ret
align 4
wait_for_sector_dma_ide1:
push eax
push edx
call save_hd_wait_timeout
.wait:
call change_task
cmp [irq15_func], hdd_irq15
jnz .done
call check_hd_wait_timeout
cmp [hd_error], 0
jz .wait
mov [irq15_func], hdd_irq_null
mov dx, [IDEContrRegsBaseAddr]
add dx, 8
mov al, 0
out dx, al
.done:
pop edx
pop eax
ret
iglobal
align 4
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
IDE_descriptor_table:
dd 284000h
dw 2000h
dw 8000h
dma_cur_sector dd not 40h
irq14_func dd hdd_irq_null
irq15_func dd hdd_irq_null
endg
uglobal
; all uglobals are zeroed at boot
dma_process dd 0
dma_slot_ptr dd 0
cache_chain_pos dd 0
cache_chain_ptr dd 0
cache_chain_size db 0
cache_chain_started db 0
dma_task_switched db 0
dma_hdd db 0
allow_dma_write db 0
endg
align 4
hdd_irq14:
pushfd
cli
pushad
mov [irq14_func], hdd_irq_null
mov dx, [IDEContrRegsBaseAddr]
mov al, 0
out dx, al
call update_counters
mov ebx, [dma_process]
cmp [0x3000], ebx
jz .noswitch
mov [dma_task_switched], 1
mov edi, [dma_slot_ptr]
mov eax, [0x3000]
mov [dma_process], eax
mov eax, [0x3010]
mov [dma_slot_ptr], eax
mov [0x3000], ebx
mov [0x3010], edi
mov byte [0xFFFF], 1
call do_change_task
.noswitch:
popad
popfd
align 4
hdd_irq_null:
ret
align 4
hdd_irq15:
pushfd
cli
pushad
mov [irq15_func], hdd_irq_null
mov dx, [IDEContrRegsBaseAddr]
add dx, 8
mov al, 0
out dx, al
call update_counters
mov ebx, [dma_process]
cmp [0x3000], ebx
jz .noswitch
mov [dma_task_switched], 1
mov edi, [dma_slot_ptr]
mov eax, [0x3000]
mov [dma_process], eax
mov eax, [0x3010]
mov [dma_slot_ptr], eax
mov [0x3000], ebx
mov [0x3010], edi
mov byte [0xFFFF], 1
call do_change_task
.noswitch:
popad
popfd
ret
align 4
hd_read_dma:
push eax
push edx
mov edx, [dma_cur_sector]
cmp eax, edx
jb .notread
add edx, 15
cmp [esp+4], edx
ja .notread
mov eax, [esp+4]
sub eax, [dma_cur_sector]
shl eax, 9
add eax, 0x284000
push ecx esi edi
mov esi, eax
shl edi, 9
add edi, 0x610000
mov ecx, 512/4
cld
rep movsd
pop edi esi ecx
pop edx
pop eax
ret
.notread:
mov eax, IDE_descriptor_table
mov dword [eax], 0x284000
mov word [eax+4], 0x2000
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
jz @f
add edx, 8
@@:
push edx
add edx, 4
out dx, eax
pop edx
mov al, 0
out dx, al
add edx, 2
mov al, 6
out dx, al
call wait_for_hd_idle
cmp [hd_error], 0
jnz hd_read_error
call disable_ide_int
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al
inc edx
mov eax, 10h
out dx, al
inc edx
mov eax, [esp+4]
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
and al, 0xF
add al, byte [hdid]
add al, 11100000b
out dx, al
inc edx
mov al, 0xC8
out dx, al
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
jz @f
add dx, 8
@@:
mov al, 9
out dx, al
mov eax, [0x3000]
mov [dma_process], eax
mov eax, [0x3010]
mov [dma_slot_ptr], eax
cmp [hdbase], 0x1F0
jnz .ide1
mov [irq14_func], hdd_irq14
jmp @f
.ide1:
mov [irq15_func], hdd_irq15
@@:
call enable_ide_int
cmp [hdbase], 0x1F0
jnz .wait_ide1
call wait_for_sector_dma_ide0
jmp @f
.wait_ide1:
call wait_for_sector_dma_ide1
@@:
cmp [hd_error], 0
jnz hd_read_error
pop edx
pop eax
mov [dma_cur_sector], eax
jmp hd_read_dma
align 4
write_cache_chain:
push esi
mov eax, IDE_descriptor_table
mov edx, [cache_chain_pos]
shl edx, 9
add edx, 0x610000
mov [eax], edx
movzx edx, [cache_chain_size]
shl edx, 9
mov [eax+4], dx
jmp do_write_dma
write_cache_sector:
push esi
mov eax, IDE_descriptor_table
mov edx, edi
shl edx, 9
add edx, 0x610000
mov [eax], edx
mov word [eax+4], 0x200
do_write_dma:
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
jz @f
add edx, 8
@@:
push edx
add edx, 4
out dx, eax
pop edx
mov al, 0
out dx, al
add edx, 2
mov al, 6
out dx, al
call wait_for_hd_idle
cmp [hd_error], 0
jnz hd_write_error_dma
call disable_ide_int
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al
inc edx
mov al, [cache_chain_size]
out dx, al
inc edx
mov esi, [cache_chain_ptr]
mov eax, [esi]
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
and al, 0xF
add al, byte [hdid]
add al, 11100000b
out dx, al
inc edx
mov al, 0xCA
out dx, al
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
jz @f
add dx, 8
@@:
mov al, 1
out dx, al
mov eax, [0x3000]
mov [dma_process], eax
mov eax, [0x3010]
mov [dma_slot_ptr], eax
cmp [hdbase], 0x1F0
jnz .ide1
mov [irq14_func], hdd_irq14
jmp @f
.ide1:
mov [irq15_func], hdd_irq15
@@:
call enable_ide_int
mov [dma_cur_sector], not 0x40
cmp [hdbase], 0x1F0
jnz .wait_ide1
call wait_for_sector_dma_ide0
jmp @f
.wait_ide1:
call wait_for_sector_dma_ide1
@@:
cmp [hd_error], 0
jnz hd_write_error_dma
pop esi
ret
uglobal
IDEContrRegsBaseAddr dw ?
endg
; \end{Mario79}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,22 @@
iglobal
saverd_fileinfo:
dd 2 ; subfunction: write
dd 0 ; (reserved)
dd 0 ; (reserved)
dd 1440*1024 ; size 1440 Kb
dd 0x100000 - std_application_base_address ; base address
db 0
.name:
dd ?
endg
sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only)
call restorefatchain
mov eax, saverd_fileinfo - std_application_base_address
mov [saverd_fileinfo.name], ebx
pushad
push eax
call file_system_lfn
pop eax
popad
mov [esp+36], eax
ret