Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5200 → Rev 5201

/kernel/branches/Kolibri-acpi/blkdev/cd_drv.inc
7,7 → 7,7
 
$Revision$
 
 
;-----------------------------------------------------------------------------
;**********************************************************
; Непосредственная работа с устройством СD (ATAPI)
;**********************************************************
37,16 → 37,17
xor edi, edi
add esi, 8
inc edi
;--------------------------------------
align 4
.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_CD_cache ; ret in edi
 
push edi
66,7 → 67,7
call cd_calculate_cache_1
lea esi, [edi*8+esi]
mov [esi], eax ; sector number
; mov dword [esi+4],1 ; hd read - mark as same as in hd
;--------------------------------------
.yeshdcache:
mov esi, edi
shl esi, 11;9
78,16 → 79,18
mov ecx, 512;/4
cld
rep movsd ; move data
;--------------------------------------
.exit:
popad
ret
 
;-----------------------------------------------------------------------------
ReadCDWRetr_1:
pushad
 
; Цикл, пока команда не выполнена успешно или не
; исчерпано количество попыток
mov ECX, MaxRetr
mov ecx, MaxRetr
;--------------------------------------
align 4
@@NextRetr:
; Подать команду
;*************************************************
103,9 → 106,6
;*************************************************
;ReadCD:
push ecx
; pusha
; Задать размер сектора
; mov [CDBlockSize],2048 ;2352
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать пакетную команду для считывания
113,79 → 113,67
; Задать код команды 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 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 [PacketCommand+8], byte 1
; Задать считывание данных в полном объеме
; mov [PacketCommand+9],byte 0xF8
; Подать команду
call SendPacketDatCommand
pop ecx
; ret
 
; cmp [DevErrorCode],0
test eax, eax
jz @@End_4
 
or ecx, ecx ;{SPraid.simba} (for cd load)
jz @@End_4
 
dec ecx
 
cmp [timer_ticks_enable], 0
jne @f
 
mov eax, NoTickWaitTime
;--------------------------------------
align 4
.wait:
dec eax
; test eax,eax
jz @@NextRetr
 
jmp .wait
;--------------------------------------
align 4
@@:
; Задержка на 2,5 секунды
; mov EAX,[timer_ticks]
; add EAX,50 ;250
;@@Wait:
; call change_task
; cmp EAX,[timer_ticks]
; ja @@Wait
loop @@NextRetr
;--------------------------------------
@@End_4:
mov dword [DevErrorCode], eax
popad
ret
 
 
;-----------------------------------------------------------------------------
; Универсальные процедуры, обеспечивающие выполнение
; пакетных команд в режиме PIO
 
; Максимально допустимое время ожидания реакции
; устройства на пакетную команду (в тиках)
 
;-----------------------------------------------------------------------------
MaxCDWaitTime equ 1000 ;200 ;10 секунд
uglobal
; Область памяти для формирования пакетной команды
PacketCommand:
rb 12 ;DB 12 DUP (?)
; Область памяти для приема данных от дисковода
;CDDataBuf DB 4096 DUP (0)
; Размер принимаемого блока данных в байтах
;CDBlockSize DW ?
; Адрес считываемого сектора данных
CDSectorAddress:
DD ?
CDSectorAddress: dd ?
; Время начала очередной операции с диском
TickCounter_1 DD 0
TickCounter_1 dd 0
; Время начала ожидания готовности устройства
WURStartTime DD 0
WURStartTime dd 0
; указатель буфера для считывания
CDDataBuf_pointer dd 0
endg
;-----------------------------------------------------------------------------
;****************************************************
;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
;* ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧУ ОДНОГО СЕКТОРА ДАННЫХ *
200,7 → 188,6
;****************************************************
SendPacketDatCommand:
xor eax, eax
; mov byte [DevErrorCode],al
; Задать режим CHS
mov byte [ATAAddressMode], al
; Послать ATA-команду передачи пакетной команды
209,125 → 196,134
mov byte [ATASectorNumber], al
; Загрузить размер передаваемого блока
mov [ATAHead], al
; mov AX,[CDBlockSize]
mov [ATACylinder], CDBlockSize
mov [ATACommand], 0A0h
mov [ATACommand], 0xA0
call SendCommandToHDD_1
test eax, eax
; cmp [DevErrorCode],0 ;проверить код ошибки
jnz @@End_8 ;закончить, сохранив код ошибки
 
; Ожидание готовности дисковода к приему
; пакетной команды
mov DX, [ATABasePortAddr]
add DX, 7 ;порт 1х7h
mov dx, [ATABasePortAddr]
add dx, 7 ;порт 1х7h
mov ecx, NoTickWaitTime
;--------------------------------------
align 4
@@WaitDevice0:
cmp [timer_ticks_enable], 0
jne @f
 
dec ecx
; test ecx,ecx
jz @@Err1_1
 
jmp .test
;--------------------------------------
align 4
@@:
call change_task
; Проверить время выполнения команды
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, BSYWaitTime
mov eax, [timer_ticks]
sub eax, [TickCounter_1]
cmp eax, BSYWaitTime
ja @@Err1_1 ;ошибка тайм-аута
; Проверить готовность
;--------------------------------------
align 4
.test:
in AL, DX
test AL, 80h ;состояние сигнала BSY
in al, dx
test al, 0x80 ;состояние сигнала BSY
jnz @@WaitDevice0
test AL, 1 ;состояние сигнала ERR
 
test al, 1 ;состояние сигнала ERR
jnz @@Err6
test AL, 08h ;состояние сигнала DRQ
 
test al, 0x8 ;состояние сигнала 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
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
mov dx, [ATABasePortAddr]
add dx, 7 ;порт 1х7h
mov ecx, NoTickWaitTime
;--------------------------------------
align 4
@@WaitDevice1:
cmp [timer_ticks_enable], 0
jne @f
 
dec ecx
; test ecx,ecx
jz @@Err1_1
 
jmp .test_1
;--------------------------------------
align 4
@@:
call change_task
; Проверить время выполнения команды
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, MaxCDWaitTime
mov eax, [timer_ticks]
sub eax, [TickCounter_1]
cmp eax, MaxCDWaitTime
ja @@Err1_1 ;ошибка тайм-аута
; Проверить готовность
;--------------------------------------
align 4
.test_1:
in AL, DX
test AL, 80h ;состояние сигнала BSY
in al, dx
test al, 0x80 ;состояние сигнала BSY
jnz @@WaitDevice1
test AL, 1 ;состояние сигнала ERR
 
test al, 1 ;состояние сигнала ERR
jnz @@Err6_temp
test AL, 08h ;состояние сигнала DRQ
 
test al, 0x8 ;состояние сигнала DRQ
jz @@WaitDevice1
; Принять блок данных от контроллера
mov EDI, [CDDataBuf_pointer];0x7000 ;CDDataBuf
mov edi, [CDDataBuf_pointer]
; Загрузить адрес регистра данных контроллера
mov DX, [ATABasePortAddr];порт 1x0h
mov dx, [ATABasePortAddr]
; Загрузить в счетчик размер блока в байтах
xor ecx, ecx
mov CX, CDBlockSize
mov cx, CDBlockSize
; Вычислить размер блока в 16-разрядных словах
shr CX, 1;разделить размер блока на 2
shr cx, 1 ;разделить размер блока на 2
; Принять блок данных
cli
cld
rep insw
sti
;--------------------------------------
; Успешное завершение приема данных
@@End_8:
xor eax, eax
ret
 
;--------------------------------------
; Записать код ошибки
@@Err1_1:
xor eax, eax
inc eax
ret
; mov [DevErrorCode],1
; ret
;--------------------------------------
@@Err6_temp:
mov eax, 7
ret
; mov [DevErrorCode],7
; ret
;--------------------------------------
@@Err6:
mov eax, 6
ret
; mov [DevErrorCode],6
;@@End_8:
; ret
 
 
 
;-----------------------------------------------------------------------------
;***********************************************
;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
;* НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ *
340,7 → 336,6
SendPacketNoDatCommand:
pushad
xor eax, eax
; mov byte [DevErrorCode],al
; Задать режим CHS
mov byte [ATAAddressMode], al
; Послать ATA-команду передачи пакетной команды
349,82 → 344,93
mov byte [ATASectorNumber], al
mov word [ATACylinder], ax
mov byte [ATAHead], al
mov [ATACommand], 0A0h
mov [ATACommand], 0xA0
call SendCommandToHDD_1
; cmp [DevErrorCode],0 ;проверить код ошибки
test eax, eax
jnz @@End_9 ;закончить, сохранив код ошибки
; Ожидание готовности дисковода к приему
; пакетной команды
mov DX, [ATABasePortAddr]
add DX, 7 ;порт 1х7h
mov dx, [ATABasePortAddr]
add dx, 7 ;порт 1х7h
;--------------------------------------
align 4
@@WaitDevice0_1:
call change_task
; Проверить время ожидания
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, BSYWaitTime
mov eax, [timer_ticks]
sub eax, [TickCounter_1]
cmp eax, BSYWaitTime
ja @@Err1_3 ;ошибка тайм-аута
; Проверить готовность
in AL, DX
test AL, 80h ;состояние сигнала BSY
in al, dx
test al, 0x80 ;состояние сигнала BSY
jnz @@WaitDevice0_1
test AL, 1 ;состояние сигнала ERR
 
test al, 1 ;состояние сигнала ERR
jnz @@Err6_1
test AL, 08h ;состояние сигнала DRQ
 
test al, 0x8 ;состояние сигнала 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
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
cmp [ignore_CD_eject_wait], 1
je @@clear_DEC
; Ожидание подтверждения приема команды
mov DX, [ATABasePortAddr]
add DX, 7 ;порт 1х7h
mov dx, [ATABasePortAddr]
add dx, 7 ;порт 1х7h
;--------------------------------------
align 4
@@WaitDevice1_1:
call change_task
; Проверить время выполнения команды
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, MaxCDWaitTime
mov eax, [timer_ticks]
sub eax, [TickCounter_1]
cmp eax, MaxCDWaitTime
ja @@Err1_3 ;ошибка тайм-аута
; Ожидать освобождения устройства
in AL, DX
test AL, 80h ;состояние сигнала BSY
in al, dx
test al, 0x80 ;состояние сигнала BSY
jnz @@WaitDevice1_1
test AL, 1 ;состояние сигнала ERR
 
test al, 1 ;состояние сигнала ERR
jnz @@Err6_1
test AL, 40h ;состояние сигнала DRDY
 
test al, 0x40 ;состояние сигнала DRDY
jz @@WaitDevice1_1
;--------------------------------------
@@clear_DEC:
and [DevErrorCode], 0
popad
ret
;--------------------------------------
; Записать код ошибки
@@Err1_3:
xor eax, eax
inc eax
jmp @@End_9
;--------------------------------------
@@Err6_1:
mov eax, 6
;--------------------------------------
@@End_9:
mov [DevErrorCode], eax
popad
ret
 
;-----------------------------------------------------------------------------
;****************************************************
;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ *
;* Входные параметры передаются через глобальные *
445,45 → 451,56
;* возвращен код ошибки в eax *
;****************************************************
SendCommandToHDD_1:
; pushad
; mov [DevErrorCode],0 not need
; Проверить значение кода режима
cmp [ATAAddressMode], 1
ja @@Err2_4
; Проверить корректность номера канала
mov BX, [ChannelNumber]
cmp BX, 1
mov bx, [ChannelNumber]
cmp bx, 1
jb @@Err3_4
cmp BX, 2
 
cmp bx, 2
ja @@Err3_4
; Установить базовый адрес
dec BX
shl BX, 1
dec bx
shl ebx, 2
movzx ebx, bx
mov AX, [ebx+StandardATABases]
mov [ATABasePortAddr], AX
mov eax, [cdpos]
dec eax
shr eax, 2
imul eax, sizeof.IDE_DATA
add eax, IDE_controller_1
add eax, ebx
mov ax, [eax+IDE_DATA.BAR0_val]
mov [ATABasePortAddr], ax
; Ожидание готовности HDD к приему команды
; Выбрать нужный диск
mov DX, [ATABasePortAddr]
add DX, 6 ;адрес регистра головок
mov AL, [DiskNumber]
cmp AL, 1 ;проверить номера диска
mov dx, [ATABasePortAddr]
add dx, 6 ;адрес регистра головок
mov al, [DiskNumber]
cmp al, 1 ;проверить номера диска
ja @@Err4_4
shl AL, 4
or AL, 10100000b
out DX, AL
 
shl al, 4
or al, 10100000b
out dx, al
; Ожидать, пока диск не будет готов
inc DX
inc dx
mov eax, [timer_ticks]
mov [TickCounter_1], eax
mov ecx, NoTickWaitTime
;--------------------------------------
align 4
@@WaitHDReady_2:
cmp [timer_ticks_enable], 0
jne @f
 
dec ecx
; test ecx,ecx
jz @@Err1_4
 
jmp .test
;--------------------------------------
align 4
@@:
call change_task
; Проверить время ожидания
491,81 → 508,78
sub eax, [TickCounter_1]
cmp eax, BSYWaitTime;300 ;ожидать 3 сек.
ja @@Err1_4 ;ошибка тайм-аута
; Прочитать регистр состояния
;--------------------------------------
align 4
.test:
in AL, DX
in al, dx ; Прочитать регистр состояния
; Проверить состояние сигнала BSY
test AL, 80h
test al, 0x80
jnz @@WaitHDReady_2
; Проверить состояние сигнала DRQ
test AL, 08h
test al, 0x8
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;проверить номер головки
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], 0xF ;проверить номер головки
ja @@Err5_4
or AL, [ATAHead]
or AL, 10100000b
mov AH, [ATAAddressMode]
shl AH, 6
or AL, AH
out DX, AL
 
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
mov al, [ATACommand]
inc dx ;регистр команд
out dx, al
sti
; Сбросить признак ошибки
; mov [DevErrorCode],0
;--------------------------------------
@@End_10:
xor eax, eax
ret
;--------------------------------------
; Записать код ошибки
@@Err1_4:
xor eax, eax
inc eax
; mov [DevErrorCode],1
ret
;--------------------------------------
@@Err2_4:
mov eax, 2
; mov [DevErrorCode],2
ret
;--------------------------------------
@@Err3_4:
mov eax, 3
; mov [DevErrorCode],3
ret
;--------------------------------------
@@Err4_4:
mov eax, 4
; mov [DevErrorCode],4
ret
;--------------------------------------
@@Err5_4:
mov eax, 5
; mov [DevErrorCode],5
; Завершение работы программы
ret
; sti
; popad
 
;-----------------------------------------------------------------------------
;*************************************************
;* ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ *
;* Входные параметры передаются через глобальные *
576,25 → 590,31
WaitUnitReady:
pusha
; Запомнить время начала операции
mov EAX, [timer_ticks]
mov [WURStartTime], EAX
mov eax, [timer_ticks]
mov [WURStartTime], eax
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать команду TEST UNIT READY
mov [PacketCommand], word 00h
mov [PacketCommand], word 0
; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА
mov ecx, NoTickWaitTime
;--------------------------------------
align 4
@@SendCommand:
; Подать команду проверки готовности
call SendPacketNoDatCommand
cmp [timer_ticks_enable], 0
jne @f
 
cmp [DevErrorCode], 0
je @@End_11
 
dec ecx
; cmp ecx,0
jz .Error
 
jmp @@SendCommand
;--------------------------------------
align 4
@@:
call change_task
; Проверить код ошибки
601,17 → 621,19
cmp [DevErrorCode], 0
je @@End_11
; Проверить время ожидания готовности
mov EAX, [timer_ticks]
sub EAX, [WURStartTime]
cmp EAX, MaxCDWaitTime
mov eax, [timer_ticks]
sub eax, [WURStartTime]
cmp eax, MaxCDWaitTime
jb @@SendCommand
;--------------------------------------
.Error:
; Ошибка тайм-аута
mov [DevErrorCode], 1
;--------------------------------------
@@End_11:
popa
ret
 
;-----------------------------------------------------------------------------
;*************************************************
;* ЗАПРЕТИТЬ СМЕНУ ДИСКА *
;* Входные параметры передаются через глобальные *
635,7 → 657,7
mov [eax], byte 1
popa
ret
 
;-----------------------------------------------------------------------------
;*************************************************
;* РАЗРЕШИТЬ СМЕНУ ДИСКА *
;* Входные параметры передаются через глобальные *
650,7 → 672,7
; Задать код команды
mov [PacketCommand], byte 0x1E
; Задать код запрета
mov [PacketCommand+4], byte 00b
mov [PacketCommand+4], byte 0
; Подать команду
call SendPacketNoDatCommand
mov eax, ATAPI_IDE0_lock
659,7 → 681,7
mov [eax], byte 0
popa
ret
 
;-----------------------------------------------------------------------------
;*************************************************
;* ЗАГРУЗИТЬ НОСИТЕЛЬ В ДИСКОВОД *
;* Входные параметры передаются через глобальные *
673,7 → 695,7
call clear_packet_buffer
; Сформировать команду START/STOP UNIT
; Задать код команды
mov [PacketCommand], word 1Bh
mov [PacketCommand], word 0x1B
; Задать операцию загрузки носителя
mov [PacketCommand+4], word 00000011b
; Подать команду
680,7 → 702,7
call SendPacketNoDatCommand
popa
ret
 
;-----------------------------------------------------------------------------
;*************************************************
;* ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА *
;* Входные параметры передаются через глобальные *
694,7 → 716,7
call clear_packet_buffer
; Сформировать команду START/STOP UNIT
; Задать код команды
mov [PacketCommand], word 1Bh
mov [PacketCommand], word 0x1B
; Задать операцию извлечения носителя
mov [PacketCommand+4], word 00000010b
; Подать команду
701,7 → 723,7
call SendPacketNoDatCommand
popa
ret
 
;-----------------------------------------------------------------------------
;*************************************************
;* Проверить событие нажатия кнопки извлечения *
;* диска *
715,15 → 737,16
sub eax, [timer_ATAPI_check]
cmp eax, 100
jb .no
.yes:
 
xor eax, eax
inc eax
ret
;--------------------------------------
.no:
xor eax, eax
ret
endp
 
;-----------------------------------------------------------------------------
align 4
check_ATAPI_device_event:
pusha
731,43 → 754,96
sub eax, [timer_ATAPI_check]
cmp eax, 100
jb .end_1
 
pushfd
mov al, [DRIVE_DATA+1]
and al, 11b
cmp al, 10b
jz .ide3
;--------------------------------------
.ide2_1:
mov al, [DRIVE_DATA+1]
and al, 1100b
cmp al, 1000b
jz .ide2
;--------------------------------------
.ide1_1:
mov al, [DRIVE_DATA+1]
and al, 110000b
cmp al, 100000b
jz .ide1
;--------------------------------------
.ide0_1:
mov al, [DRIVE_DATA+1]
and al, 11000000b
cmp al, 10000000b
jz .ide0
;--------------------------------------
.ide7_1:
mov al, [DRIVE_DATA+6]
and al, 11b
cmp al, 10b
jz .ide7
;--------------------------------------
.ide6_1:
mov al, [DRIVE_DATA+6]
and al, 1100b
cmp al, 1000b
jz .ide6
;--------------------------------------
.ide5_1:
mov al, [DRIVE_DATA+6]
and al, 110000b
cmp al, 100000b
jz .ide5
;--------------------------------------
.ide4_1:
mov al, [DRIVE_DATA+6]
and al, 11000000b
cmp al, 10000000b
jz .ide4
;--------------------------------------
.ide11_1:
mov al, [DRIVE_DATA+11]
and al, 11b
cmp al, 10b
jz .ide11
;--------------------------------------
.ide10_1:
mov al, [DRIVE_DATA+11]
and al, 1100b
cmp al, 1000b
jz .ide10
;--------------------------------------
.ide9_1:
mov al, [DRIVE_DATA+11]
and al, 110000b
cmp al, 100000b
jz .ide9
;--------------------------------------
.ide8_1:
mov al, [DRIVE_DATA+11]
and al, 11000000b
cmp al, 10000000b
jz .ide8
;--------------------------------------
.end:
 
sti
popfd
mov eax, [timer_ticks]
mov [timer_ATAPI_check], eax
;--------------------------------------
.end_1:
popa
ret
 
;-----------------------------------------------------------------------------
.ide3:
cli
cmp [ATAPI_IDE3_lock], 1
jne .ide2_1
cmp [IDE_Channel_2], 0
jne .ide1_1
 
cmp [cd_status], 0
jne .end
mov [IDE_Channel_2], 1
 
mov ecx, ide_channel2_mutex
call mutex_lock
call reserve_ok2
776,23 → 852,22
mov [cdpos], 4
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide3
call syscall_cdaudio.free
jmp .ide2_1
.eject_ide3:
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide2_1
 
;-----------------------------------------------------------------------------
.ide2:
cli
cmp [ATAPI_IDE2_lock], 1
jne .ide1_1
cmp [IDE_Channel_2], 0
jne .ide1_1
 
cmp [cd_status], 0
jne .end
mov [IDE_Channel_2], 1
 
mov ecx, ide_channel2_mutex
call mutex_lock
call reserve_ok2
801,23 → 876,22
mov [cdpos], 3
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide2
call syscall_cdaudio.free
jmp .ide1_1
.eject_ide2:
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide1_1
 
;-----------------------------------------------------------------------------
.ide1:
cli
cmp [ATAPI_IDE1_lock], 1
jne .ide0_1
cmp [IDE_Channel_1], 0
jne .end
 
cmp [cd_status], 0
jne .end
mov [IDE_Channel_1], 1
 
mov ecx, ide_channel1_mutex
call mutex_lock
call reserve_ok2
826,23 → 900,22
mov [cdpos], 2
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide1
call syscall_cdaudio.free
jmp .ide0_1
.eject_ide1:
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide0_1
 
;-----------------------------------------------------------------------------
.ide0:
cli
cmp [ATAPI_IDE0_lock], 1
jne .end
cmp [IDE_Channel_1], 0
jne .end
jne .ide7_1
 
cmp [cd_status], 0
jne .end
mov [IDE_Channel_1], 1
 
mov ecx, ide_channel1_mutex
call mutex_lock
call reserve_ok2
851,14 → 924,206
mov [cdpos], 1
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide0
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .end
.eject_ide0:
jmp .ide7_1
;-----------------------------------------------------------------------------
.ide7:
cli
cmp [ATAPI_IDE7_lock], 1
jne .ide6_1
 
cmp [cd_status], 0
jne .end
 
mov ecx, ide_channel4_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 2
mov [DiskNumber], 1
mov [cdpos], 8
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide6_1
;-----------------------------------------------------------------------------
.ide6:
cli
cmp [ATAPI_IDE6_lock], 1
jne .ide5_1
 
cmp [cd_status], 0
jne .end
 
mov ecx, ide_channel4_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 2
mov [DiskNumber], 0
mov [cdpos], 7
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide5_1
;-----------------------------------------------------------------------------
.ide5:
cli
cmp [ATAPI_IDE5_lock], 1
jne .ide4_1
 
cmp [cd_status], 0
jne .end
 
mov ecx, ide_channel3_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 1
mov [DiskNumber], 1
mov [cdpos], 6
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide4_1
;-----------------------------------------------------------------------------
.ide4:
cli
cmp [ATAPI_IDE4_lock], 1
jne .ide11_1
 
cmp [cd_status], 0
jne .end
 
mov ecx, ide_channel3_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 1
mov [DiskNumber], 0
mov [cdpos], 5
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide11_1
;-----------------------------------------------------------------------------
.ide11:
cli
cmp [ATAPI_IDE11_lock], 1
jne .ide10_1
 
cmp [cd_status], 0
jne .end
 
mov ecx, ide_channel6_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 2
mov [DiskNumber], 1
mov [cdpos], 12
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide10_1
;-----------------------------------------------------------------------------
.ide10:
cli
cmp [ATAPI_IDE10_lock], 1
jne .ide9_1
 
cmp [cd_status], 0
jne .end
 
mov ecx, ide_channel6_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 2
mov [DiskNumber], 0
mov [cdpos], 11
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide9_1
;-----------------------------------------------------------------------------
.ide9:
cli
cmp [ATAPI_IDE9_lock], 1
jne .ide8_1
 
cmp [cd_status], 0
jne .end
 
mov ecx, ide_channel5_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 1
mov [DiskNumber], 1
mov [cdpos], 10
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .ide8_1
;-----------------------------------------------------------------------------
.ide8:
cli
cmp [ATAPI_IDE8_lock], 1
jne .end
 
cmp [cd_status], 0
jne .end
 
mov ecx, ide_channel5_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 1
mov [DiskNumber], 0
mov [cdpos], 9
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
jne @f
 
call .eject
;--------------------------------------
@@:
call syscall_cdaudio.free
jmp .end
 
;-----------------------------------------------------------------------------
.eject:
call clear_CD_cache
call allow_medium_removal
866,6 → 1131,7
call EjectMedium
mov [ignore_CD_eject_wait], 0
ret
;-----------------------------------------------------------------------------
iglobal
timer_ATAPI_check dd 0
ATAPI_IDE0_lock db 0
872,8 → 1138,17
ATAPI_IDE1_lock db 0
ATAPI_IDE2_lock db 0
ATAPI_IDE3_lock db 0
ATAPI_IDE4_lock db 0
ATAPI_IDE5_lock db 0
ATAPI_IDE6_lock db 0
ATAPI_IDE7_lock db 0
ATAPI_IDE8_lock db 0
ATAPI_IDE9_lock db 0
ATAPI_IDE10_lock db 0
ATAPI_IDE11_lock db 0
ignore_CD_eject_wait db 0
endg
;-----------------------------------------------------------------------------
;*************************************************
;* Получить сообщение о событии или состоянии *
;* устройства *
899,7 → 1174,7
call SendPacketDatCommand
popa
ret
 
;-----------------------------------------------------------------------------
;*************************************************
; прочитать информацию из TOC
;* Входные параметры передаются через глобальные *
924,7 → 1199,7
call SendPacketDatCommand
popa
ret
 
;-----------------------------------------------------------------------------
;*************************************************
;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ *
;* Входные параметры передаются через глобальные *
944,7 → 1219,7
; call SendPacketDatCommand
; popa
; ret
 
;-----------------------------------------------------------------------------
clear_packet_buffer:
; Очистить буфер пакетной команды
and [PacketCommand], dword 0
951,3 → 1226,4
and [PacketCommand+4], dword 0
and [PacketCommand+8], dword 0
ret
;-----------------------------------------------------------------------------
/kernel/branches/Kolibri-acpi/blkdev/disk.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2011-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16,6 → 16,7
DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters
DISK_STATUS_NO_MEDIA = 2 ; no media present
DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data
DISK_STATUS_NO_MEMORY = 4 ; insufficient memory for driver operation
; Driver flags. Represent bits in DISK.DriverFlags.
DISK_NO_INSERT_NOTIFICATION = 1
; Media flags. Represent bits in DISKMEDIAINFO.Flags.
101,8 → 102,6
; there are two distinct caches for a disk, one for "system" data,and the other
; for "application" data.
struct DISKCACHE
mutex MUTEX
; Lock to protect the cache.
; The following fields are inherited from data32.inc:cache_ideX.
pointer dd ?
data_size dd ? ; unused
109,6 → 108,7
data dd ?
sad_size dd ?
search_start dd ?
sector_size_log dd ?
ends
 
; This structure represents a disk device and its media for the kernel.
169,6 → 169,8
; Pointer to array of .NumPartitions pointers to PARTITION structures.
cache_size dd ?
; inherited from cache_ideX_size
CacheLock MUTEX
; Lock to protect both caches.
SysCache DISKCACHE
AppCache DISKCACHE
; Two caches for the disk.
270,13 → 272,13
endg
 
iglobal
; The function 'disk_scan_partitions' needs three 512-byte buffers for
; The function 'disk_scan_partitions' needs three sector-sized buffers for
; MBR, bootsector and fs-temporary sector data. It can not use the static
; buffers always, since it can be called for two or more disks in parallel.
; However, this case is not typical. We reserve three static 512-byte buffers
; and a flag that these buffers are currently used. If 'disk_scan_partitions'
; detects that the buffers are currently used, it allocates buffers from the
; heap.
; heap. Also, the heap is used when sector size is other than 512.
; The flag is implemented as a global dword variable. When the static buffers
; are not used, the value is -1. When the static buffers are used, the value
; is normally 0 and temporarily can become greater. The function increments
637,21 → 639,18
; 1. Initialize .NumPartitions and .Partitions fields as zeros: empty list.
and [esi+DISK.NumPartitions], 0
and [esi+DISK.Partitions], 0
; 2. Currently we can work only with 512-bytes sectors. Check this restriction.
; The only exception is 2048-bytes CD/DVD, but they are not supported yet by
; this code.
cmp [esi+DISK.MediaInfo.SectorSize], 512
jz .doscan
DEBUGF 1,'K : sector size is %d, only 512 is supported\n',[esi+DISK.MediaInfo.SectorSize]
ret
.doscan:
; 3. Acquire the buffer for MBR and bootsector tests. See the comment before
; 2. Acquire the buffer for MBR and bootsector tests. See the comment before
; the 'partition_buffer_users' variable.
mov eax, [esi+DISK.MediaInfo.SectorSize]
cmp eax, 512
jnz @f
mov ebx, mbr_buffer ; assume the global buffer is free
lock inc [partition_buffer_users]
jz .buffer_acquired ; yes, it is free
lock dec [partition_buffer_users] ; no, we must allocate
stdcall kernel_alloc, 512*3
@@:
lea eax, [eax*3]
stdcall kernel_alloc, eax
test eax, eax
jz .nothing
xchg eax, ebx
658,7 → 657,7
.buffer_acquired:
; MBR/EBRs are organized in the chain. We use a loop over MBR/EBRs, but no
; more than MAX_NUM_PARTITION times.
; 4. Prepare things for the loop.
; 3. Prepare things for the loop.
; ebp will hold the sector number for current MBR/EBR.
; [esp] will hold the sector number for current extended partition, if there
; is one.
667,6 → 666,10
push MAX_NUM_PARTITIONS ; the counter of max MBRs to process
xor ebp, ebp ; start from sector zero
push ebp ; no extended partition yet
; 4. MBR is 512 bytes long. If sector size is less than 512 bytes,
; assume no MBR, no partitions and go to 10.
cmp [esi+DISK.MediaInfo.SectorSize], 512
jb .notmbr
.new_mbr:
; 5. Read the current sector.
; Note that 'read' callback operates with 64-bit sector numbers, so we must
985,7 → 988,7
; a three-sectors-sized buffer. This function saves ebx in the stack
; immediately before ebp.
mov ebx, [ebp-4] ; get buffer
add ebx, 512 ; advance over MBR data to bootsector data
add ebx, [esi+DISK.MediaInfo.SectorSize] ; advance over MBR data to bootsector data
add ebp, 8 ; ebp points to part of PARTITION structure
xor eax, eax ; first sector of the partition
call fs_read32_sys
996,7 → 999,7
; ebp -> first three fields of PARTITION structure, .start, .length, .disk;
; [esp] = error code after bootsector read: 0 = ok, otherwise = failed,
; ebx points to the buffer for bootsector,
; ebx+512 points to 512-bytes buffer that can be used for anything.
; ebx+[esi+DISK.MediaInfo.SectorSize] points to sector-sized buffer that can be used for anything.
call fat_create_partition
test eax, eax
jnz .success
/kernel/branches/Kolibri-acpi/blkdev/disk_cache.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2011-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7,6 → 7,515
 
$Revision: 3742 $
 
; Read/write functions try to do large operations,
; it is significantly faster than several small operations.
; This requires large buffers.
; We can't use input/output buffers directly - they can be controlled
; by user-mode application, so they can be modified between the operation
; and copying to/from cache, giving invalid data in cache.
; It is unclear how to use cache directly, currently cache items are
; allocated/freed sector-wise, so items for sequential sectors can be
; scattered over all the cache.
; So read/write functions allocate a temporary buffer which is
; 1) not greater than half of free memory and
; 2) not greater than the following constant.
CACHE_MAX_ALLOC_SIZE = 4 shl 20
 
; Legacy interface for filesystems fs_{read,write}32_{sys,app}
; gives only one sector for FS. However, per-sector reading is inefficient,
; so internally fs_read32_{sys,app} reads to the cache several sequential
; sectors, hoping that they will be useful.
; Total number of sectors is given by the following constant.
CACHE_LEGACY_READ_SIZE = 16
 
; This structure describes one item in the cache.
struct CACHE_ITEM
SectorLo dd ? ; low 32 bits of sector
SectorHi dd ? ; high 32 bits of sector
Status dd ? ; one of CACHE_ITEM_*
ends
 
; Possible values for CACHE_ITEM_*
CACHE_ITEM_EMPTY = 0
CACHE_ITEM_COPY = 1
CACHE_ITEM_MODIFIED = 2
 
; Read several sequential sectors using cache #1.
; in: edx:eax = start sector, relative to start of partition
; in: ecx = number of sectors to read
; in: ebx -> buffer
; in: ebp -> PARTITION
; out: eax = error code, 0 = ok
; out: ecx = number of sectors that were read
fs_read64_sys:
; Save ebx, set ebx to SysCache and let the common part do its work.
push ebx ebx
mov ebx, [ebp+PARTITION.Disk]
add ebx, DISK.SysCache
jmp fs_read64_common
 
; Read several sequential sectors using cache #2.
; in: edx:eax = start sector, relative to start of partition
; in: ecx = number of sectors to read
; in: edi -> buffer
; in: ebp -> PARTITION
; out: eax = error code, 0 = ok
; out: ecx = number of sectors that were read
fs_read64_app:
; Save ebx, set ebx to AppCache and let the common part do its work.
push ebx ebx
mov ebx, [ebp+PARTITION.Disk]
add ebx, DISK.AppCache
 
; Common part of fs_read64_{app,sys}:
; read several sequential sectors using the given cache.
fs_read64_common:
; 1. Setup stack frame.
push esi edi ; save used registers to be stdcall
push 0 ; initialize .error_code
push ebx edx eax ecx ecx ; initialize stack variables
virtual at esp
.local_vars:
.num_sectors_orig dd ?
; Number of sectors that should be read. Used to generate output value of ecx.
.num_sectors dd ?
; Number of sectors that remain to be read. Decreases from .num_sectors_orig to 0.
.sector_lo dd ? ; low 32 bits of the current sector
.sector_hi dd ? ; high 32 bits of the current sector
.cache dd ? ; pointer to DISKCACHE
.error_code dd ? ; current status
.local_vars_size = $ - .local_vars
.saved_regs rd 2
.buffer dd ? ; filled by fs_read64_{sys,app}
end virtual
; 2. Validate parameters against partition length:
; immediately return error if edx:eax are beyond partition end,
; decrease .num_sectors and .num_sectors_orig, if needed,
; so that the entire operation fits in the partition limits.
mov eax, dword [ebp+PARTITION.Length]
mov edx, dword [ebp+PARTITION.Length+4]
sub eax, [.sector_lo]
sbb edx, [.sector_hi]
jb .end_of_media
jnz .no_end_of_media
cmp ecx, eax
jbe .no_end_of_media
; If .num_sectors got decreased, set status to DISK_STATUS_END_OF_MEDIA;
; if all subsequent operations would be successful, this would become the final
; status, otherwise this would be rewritten by failed operation.
mov [.num_sectors], eax
mov [.num_sectors_orig], eax
mov [.error_code], DISK_STATUS_END_OF_MEDIA
.no_end_of_media:
; 3. If number of sectors to read is zero, either because zero-sectors operation
; was requested or because it got decreased to zero due to partition limits,
; just return the current status.
cmp [.num_sectors], 0
jz .return
; 4. Shift sector from partition-relative to absolute.
mov eax, dword [ebp+PARTITION.FirstSector]
mov edx, dword [ebp+PARTITION.FirstSector+4]
add [.sector_lo], eax
adc [.sector_hi], edx
; 5. If the cache is disabled, pass the request directly to the driver.
cmp [ebx+DISKCACHE.pointer], 0
jz .nocache
; 6. Look for sectors in the cache, sequentially from the beginning.
; Stop at the first sector that is not in the cache
; or when all sectors were read from the cache.
; 6a. Acquire the lock.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_lock
.lookup_in_cache_loop:
; 6b. For each sector, call the lookup function without adding to the cache.
mov eax, [.sector_lo]
mov edx, [.sector_hi]
call cache_lookup_read
; 6c. If it has failed, the sector is not in cache;
; release the lock and go to 7.
jc .not_found_in_cache
; The sector is found in cache.
; 6d. Copy data for the caller, advance [.buffer].
mov esi, edi
mov edi, [.buffer]
mov eax, 1
shl eax, cl
mov ecx, eax
shr ecx, 2
rep movsd
mov [.buffer], edi
; 6e. Advance the sector.
add [.sector_lo], 1
adc [.sector_hi], 0
; 6f. Decrement number of sectors left.
; If all sectors were read, release the lock and return.
dec [.num_sectors]
jnz .lookup_in_cache_loop
; Release the lock acquired at 6a.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_unlock
.return:
mov eax, [.error_code]
mov ecx, [.num_sectors_orig]
sub ecx, [.num_sectors]
.nothing:
add esp, .local_vars_size
pop edi esi ebx ebx ; restore used registers to be stdcall
ret
.not_found_in_cache:
; Release the lock acquired at 6a.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_unlock
; The current sector is not present in the cache.
; Ask the driver to read all requested not-yet-read sectors,
; put results in the cache.
; Also, see the comment before the definition of CACHE_MAX_ALLOC_SIZE.
; 7. Allocate buffer for operations.
; Normally, create buffer that is sufficient for all remaining data.
; However, for extra-large requests make an upper limit:
; do not use more than half of the free memory
; or more than CACHE_MAX_ALLOC_SIZE bytes.
mov ecx, [ebx+DISKCACHE.sector_size_log]
mov ebx, [pg_data.pages_free]
shr ebx, 1
jz .nomemory
cmp ebx, CACHE_MAX_ALLOC_SIZE shr 12
jbe @f
mov ebx, CACHE_MAX_ALLOC_SIZE shr 12
@@:
shl ebx, 12
shr ebx, cl
jz .nomemory
cmp ebx, [.num_sectors]
jbe @f
mov ebx, [.num_sectors]
@@:
mov eax, ebx
shl eax, cl
stdcall kernel_alloc, eax
; If failed, return the appropriate error code.
test eax, eax
jz .nomemory
mov esi, eax
; Split the request to chunks that fit in the allocated buffer.
.read_loop:
; 8. Get iteration size: either size of allocated buffer in sectors
; or number of sectors left, select what is smaller.
cmp ebx, [.num_sectors]
jbe @f
mov ebx, [.num_sectors]
@@:
; 9. Create second portion of local variables.
; Note that variables here and above are esp-relative;
; it means that all addresses should be corrected when esp is changing.
push ebx esi esi
push ebx
; In particular, num_sectors is now [.num_sectors+.local_vars2_size].
virtual at esp
.local_vars2:
.current_num_sectors dd ? ; number of sectors that were read
.current_buffer dd ?
; pointer inside .allocated_buffer that points
; to the beginning of not-processed data
.allocated_buffer dd ? ; saved in safe place
.iteration_size dd ? ; saved in safe place
.local_vars2_size = $ - .local_vars2
end virtual
; 10. Call the driver, reading the next chunk.
push esp ; numsectors
push [.sector_hi+.local_vars2_size+4] ; startsector
push [.sector_lo+.local_vars2_size+8] ; startsector
push esi ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read
call disk_call_driver
; If failed, save error code.
test eax, eax
jz @f
mov [.error_code+.local_vars2_size], eax
@@:
; 11. Copy data for the caller, advance .buffer.
cmp [.current_num_sectors], 0
jz .copy_done
mov ebx, [.cache+.local_vars2_size]
mov eax, [.current_num_sectors]
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl eax, cl
mov esi, [.allocated_buffer]
mov edi, [.buffer+.local_vars2_size]
mov ecx, eax
shr ecx, 2
rep movsd
mov [.buffer+.local_vars2_size], edi
; 12. Copy data to the cache.
; 12a. Acquire the lock.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_lock
; 12b. Prepare for the loop: create a local variable that
; stores number of sectors to be copied.
push [.current_num_sectors]
.store_to_cache:
; 12c. For each sector, call the lookup function with adding to the cache, if not yet.
mov eax, [.sector_lo+.local_vars2_size+4]
mov edx, [.sector_hi+.local_vars2_size+4]
call cache_lookup_write
test eax, eax
jnz .cache_error
; 12d. If the sector was already present in the cache as modified,
; data that were read at step 10 for this sector are obsolete,
; so rewrite data for the caller from the cache.
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jnz .not_modified
mov esi, edi
mov edi, [.buffer+.local_vars2_size+4]
mov eax, [esp]
shl eax, cl
sub edi, eax
mov eax, 1
shl eax, cl
mov ecx, eax
shr ecx, 2
rep movsd
add [.current_buffer+4], eax
jmp .sector_done
.not_modified:
; 12e. For each not-modified sector,
; copy data, mark the item as not-modified copy of the disk,
; advance .current_buffer and .sector_hi:.sector_lo to the next sector.
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
mov eax, 1
shl eax, cl
mov esi, [.current_buffer+4]
mov ecx, eax
shr ecx, 2
rep movsd
mov [.current_buffer+4], esi
.sector_done:
add [.sector_lo+.local_vars2_size+4], 1
adc [.sector_hi+.local_vars2_size+4], 0
; 12f. Continue the loop 12c-12e until all sectors are read.
dec dword [esp]
jnz .store_to_cache
.cache_error:
; 12g. Restore after the loop: pop the local variable.
pop ecx
; 12h. Release the lock.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_unlock
.copy_done:
; 13. Remove portion of local variables created at step 9.
pop ecx
pop esi esi ebx
; 14. Continue iterations while number of sectors read by the driver
; is equal to number of sectors requested and there are additional sectors.
cmp ecx, ebx
jnz @f
sub [.num_sectors], ebx
jnz .read_loop
@@:
; 15. Free the buffer allocated at step 7 and return.
stdcall kernel_free, esi
jmp .return
 
; Special branches:
.nomemory:
; memory allocation failed at step 7: return the corresponding error
mov [.error_code], DISK_STATUS_NO_MEMORY
jmp .return
.nocache:
; step 5, after correcting number of sectors to fit in partition limits
; and advancing partition-relative sector to absolute,
; sees that cache is disabled: pass corrected request to the driver
lea eax, [.num_sectors]
push eax ; numsectors
push [.sector_hi+4] ; startsector
push [.sector_lo+8] ; startsector
push [.buffer+12] ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read
call disk_call_driver
test eax, eax
jnz @f
mov eax, [.error_code]
@@:
mov ecx, [.num_sectors]
jmp .nothing
.end_of_media:
; requested sector is beyond the partition end: return the corresponding error
mov [.error_code], DISK_STATUS_END_OF_MEDIA
jmp .return
 
; Write several sequential sectors using cache #1.
; in: edx:eax = start sector
; in: ecx = number of sectors to write
; in: ebx -> buffer
; in: ebp -> PARTITION
; out: eax = error code, 0 = ok
; out: ecx = number of sectors that were written
fs_write64_sys:
; Save ebx, set ebx to SysCache and let the common part do its work.
push ebx
mov ebx, [ebp+PARTITION.Disk]
add ebx, DISK.SysCache
jmp fs_write64_common
 
; Write several sequential sectors using cache #2.
; in: edx:eax = start sector
; in: ecx = number of sectors to write
; in: ebx -> buffer
; in: ebp -> PARTITION
; out: eax = error code, 0 = ok
; out: ecx = number of sectors that were written
fs_write64_app:
; Save ebx, set ebx to AppCache and let the common part do its work.
push ebx
mov ebx, [ebp+PARTITION.Disk]
add ebx, DISK.AppCache
 
; Common part of fs_write64_{app,sys}:
; write several sequential sectors using the given cache.
fs_write64_common:
; 1. Setup stack frame.
push esi edi ; save used registers to be stdcall
push 0 ; initialize .error_code
push edx eax ecx ecx ; initialize stack variables
push [.buffer-4] ; copy [.buffer] to [.cur_buffer]
; -4 is due to esp-relative addressing
virtual at esp
.local_vars:
.cur_buffer dd ? ; pointer to data that are currently copying
.num_sectors_orig dd ?
; Number of sectors that should be written. Used to generate output value of ecx.
.num_sectors dd ?
; Number of sectors that remain to be written.
.sector_lo dd ? ; low 32 bits of the current sector
.sector_hi dd ? ; high 32 bits of the current sector
.error_code dd ? ; current status
.local_vars_size = $ - .local_vars
.saved_regs rd 2
.buffer dd ? ; filled by fs_write64_{sys,app}
end virtual
; 2. Validate parameters against partition length:
; immediately return error if edx:eax are beyond partition end,
; decrease .num_sectors and .num_sectors_orig, if needed,
; so that the entire operation fits in the partition limits.
mov eax, dword [ebp+PARTITION.Length]
mov edx, dword [ebp+PARTITION.Length+4]
sub eax, [.sector_lo]
sbb edx, [.sector_hi]
jb .end_of_media
jnz .no_end_of_media
cmp ecx, eax
jbe .no_end_of_media
; If .num_sectors got decreased, set status to DISK_STATUS_END_OF_MEDIA;
; if all subsequent operations would be successful, this would become the final
; status, otherwise this would be rewritten by failed operation.
mov [.num_sectors], eax
mov [.num_sectors_orig], eax
mov [.error_code], DISK_STATUS_END_OF_MEDIA
.no_end_of_media:
; 3. If number of sectors to write is zero, either because zero-sectors operation
; was requested or because it got decreased to zero due to partition limits,
; just return the current status.
cmp [.num_sectors], 0
jz .return
; 4. Shift sector from partition-relative to absolute.
mov eax, dword [ebp+PARTITION.FirstSector]
mov edx, dword [ebp+PARTITION.FirstSector+4]
add [.sector_lo], eax
adc [.sector_hi], edx
; 5. If the cache is disabled, pass the request directly to the driver.
cmp [ebx+DISKCACHE.pointer], 0
jz .nocache
; 6. Store sectors in the cache, sequentially from the beginning.
; 6a. Acquire the lock.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_lock
.lookup_in_cache_loop:
; 6b. For each sector, call the lookup function with adding to the cache, if not yet.
mov eax, [.sector_lo]
mov edx, [.sector_hi]
call cache_lookup_write
test eax, eax
jnz .cache_error
; 6c. For each sector, copy data, mark the item as modified and not saved,
; advance .current_buffer to the next sector.
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
mov eax, 1
shl eax, cl
mov esi, [.cur_buffer]
mov ecx, eax
shr ecx, 2
rep movsd
mov [.cur_buffer], esi
; 6d. Remove the sector from the other cache.
; Normally it should not be there, but prefetching could put to the app cache
; data that normally should belong to the sys cache and vice versa.
; Note: this requires that both caches must be protected by the same lock.
mov eax, [.sector_lo]
mov edx, [.sector_hi]
push ebx
sub ebx, [ebp+PARTITION.Disk]
xor ebx, DISK.SysCache xor DISK.AppCache
add ebx, [ebp+PARTITION.Disk]
call cache_lookup_read
jc @f
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_EMPTY
@@:
pop ebx
; 6e. Advance .sector_hi:.sector_lo to the next sector.
add [.sector_lo], 1
adc [.sector_hi], 0
; 6f. Continue the loop at 6b-6e until all sectors are processed.
dec [.num_sectors]
jnz .lookup_in_cache_loop
.unlock_return:
; 6g. Release the lock and return.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_unlock
.return:
mov eax, [.error_code]
mov ecx, [.num_sectors_orig]
sub ecx, [.num_sectors]
.nothing:
add esp, .local_vars_size
pop edi esi ebx
ret
 
; Special branches:
.cache_error:
; error at flushing the cache while adding sector to the cache:
; return the error from the lookup function
mov [.error_code], eax
jmp .unlock_return
.end_of_media:
; requested sector is beyond the partition end: return the corresponding error
mov eax, DISK_STATUS_END_OF_MEDIA
xor ecx, ecx
jmp .nothing
.nocache:
; step 5, after correcting number of sectors to fit in partition limits
; and advancing partition-relative sector to absolute,
; sees that cache is disabled: pass corrected request to the driver
lea eax, [.num_sectors]
push eax ; numsectors
push [.sector_hi+4] ; startsector
push [.sector_lo+8] ; startsector
push [.buffer+12] ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.write
call disk_call_driver
mov ecx, [.num_sectors]
jmp .nothing
 
; Legacy. Use fs_read64_sys instead.
; This function is intended to replace the old 'hd_read' function when
; [hdd_appl_data] = 0, so its input/output parameters are the same, except
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
14,12 → 523,13
; eax is relative to partition start
; out: eax = error code; 0 = ok
fs_read32_sys:
; Save ecx, set ecx to SysCache and let the common part do its work.
push ecx
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.SysCache
; Save ebx, set ebx to SysCache and let the common part do its work.
push ebx
mov ebx, [ebp+PARTITION.Disk]
add ebx, DISK.SysCache
jmp fs_read32_common
 
; Legacy. Use fs_read64_app instead.
; This function is intended to replace the old 'hd_read' function when
; [hdd_appl_data] = 1, so its input/output parameters are the same, except
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
27,10 → 537,10
; eax is relative to partition start
; out: eax = error code; 0 = ok
fs_read32_app:
; Save ecx, set ecx to AppCache and let the common part do its work.
push ecx
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.AppCache
; Save ebx, set ebx to AppCache and let the common part do its work.
push ebx
mov ebx, [ebp+PARTITION.Disk]
add ebx, DISK.AppCache
 
; This label is the common part of fs_read32_sys and fs_read32_app.
fs_read32_common:
41,119 → 551,224
cmp dword [ebp+PARTITION.Length], eax
ja @f
mov eax, DISK_STATUS_END_OF_MEDIA
pop ecx
pop ebx
ret
@@:
; 2. Get the absolute sector on the disk.
push edx esi
push ecx edx esi edi
xor edx, edx
add eax, dword [ebp+PARTITION.FirstSector]
adc edx, dword [ebp+PARTITION.FirstSector+4]
; 3. If there is no cache for this disk, just pass the request to the driver.
cmp [ecx+DISKCACHE.pointer], 0
cmp [ebx+DISKCACHE.pointer], 0
jnz .scancache
push 1
push esp ; numsectors
push edx ; startsector
push eax ; startsector
push ebx ; buffer
pushd [esp+32]; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read
call disk_call_driver
pop ecx
pop esi edx
pop ecx
pop edi esi edx ecx
pop ebx
ret
.scancache:
; 4. Scan the cache.
push edi ecx ; scan cache
push edx eax
push ebx edx eax
virtual at esp
.local_vars:
.sector_lo dd ?
.sector_hi dd ?
.cache dd ?
.local_vars_size = $ - .local_vars
.saved_regs rd 4
.buffer dd ?
end virtual
; The following code is inherited from hd_read. The differences are:
; all code is protected by the cache lock; instead of static calls
; to hd_read_dma/hd_read_pio/bd_read the dynamic call to DISKFUNC.read is used;
; sector is 64-bit, not 32-bit.
; 4. Scan for the requested sector in the cache.
; If found, copy the data and return.
; 4a. Acquire the lock.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_lock
; 4b. Call the lookup function without adding to the cache.
mov eax, [.sector_lo]
mov edx, [.sector_hi]
mov esi, [ecx+DISKCACHE.pointer]
mov ecx, [ecx+DISKCACHE.sad_size]
add esi, 12
 
mov edi, 1
 
.hdreadcache:
 
cmp dword [esi+8], 0 ; empty
je .nohdcache
 
cmp [esi], eax ; correct sector
jne .nohdcache
cmp [esi+4], edx ; correct sector
je .yeshdcache
 
.nohdcache:
 
add esi, 12
inc edi
dec ecx
jnz .hdreadcache
 
mov esi, [.cache]
call find_empty_slot64 ; ret in edi
call cache_lookup_read
; If not found, go to 5.
jc .not_found_in_cache
.found_in_cache:
; 4c. Copy the data.
mov esi, edi
mov edi, [.buffer]
mov eax, 1
shl eax, cl
mov ecx, eax
shr ecx, 2
rep movsd
; 4d. Release the lock and return success.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_unlock
.return:
xor eax, eax
.return_eax:
add esp, .local_vars_size
pop edi esi edx ecx
pop ebx
ret
.not_found_in_cache:
; 5. Decide whether we need to prefetch further sectors.
; If so, advance to 6. If not, go to 13.
; Assume that devices < 3MB are floppies which are slow
; (ramdisk does not have a cache, so we don't even get here for ramdisk).
; This is a dirty hack, but the entire function is somewhat hacky. Use fs_read64*.
mov ecx, [ebp+PARTITION.Disk]
cmp dword [ecx+DISK.MediaInfo.Capacity+4], 0
jnz @f
cmp dword [ecx+DISK.MediaInfo.Capacity], 3 shl (20-9)
jb .floppy
@@:
; We want to prefetch CACHE_LEGACY_READ_SIZE sectors.
; 6. Release the lock acquired at step 4a.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_unlock
; 7. Allocate buffer for CACHE_LEGACY_READ_SIZE sectors.
mov eax, CACHE_LEGACY_READ_SIZE
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl eax, cl
stdcall kernel_alloc, eax
; If failed, return the corresponding error code.
test eax, eax
jnz .read_done
jz .nomemory
; 8. Create second portion of local variables.
push eax eax
push CACHE_LEGACY_READ_SIZE
virtual at esp
.local_vars2:
.num_sectors dd ? ; number of sectors left
.current_buffer dd ? ; pointer to data that are currently copying
.allocated_buffer dd ? ; saved at safe place
.local_vars2_size = $ - .local_vars2
end virtual
; 9. Call the driver to read CACHE_LEGACY_READ_SIZE sectors.
push esp ; numsectors
push [.sector_hi+.local_vars2_size+4] ; startsector
push [.sector_lo+.local_vars2_size+8] ; startsector
push eax ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read
call disk_call_driver
; Note: we're ok if at least one sector is read,
; read error somewhere after that just limits data to be put in cache.
cmp [.num_sectors], 0
jz .read_error
; 10. Copy data for the caller.
mov esi, [.allocated_buffer]
mov edi, [.buffer+.local_vars2_size]
mov ecx, [ebx+DISKCACHE.sector_size_log]
mov eax, 1
shl eax, cl
mov ecx, eax
shr ecx, 2
rep movsd
; 11. Store all sectors that were successfully read to the cache.
; 11a. Acquire the lock.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_lock
.store_to_cache:
; 11b. For each sector, call the lookup function with adding to the cache, if not yet.
mov eax, [.sector_lo+.local_vars2_size]
mov edx, [.sector_hi+.local_vars2_size]
call cache_lookup_write
test eax, eax
jnz .cache_error
; 11c. Ignore sectors marked as modified: for them the cache is more recent that disk data.
mov eax, 1
shl eax, cl
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jnz .not_modified
add [.current_buffer], eax
jmp .sector_done
.not_modified:
; 11d. For each sector, copy data, mark the item as not-modified copy of the disk,
; advance .current_buffer and .sector_hi:.sector_lo to the next sector.
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
mov esi, [.current_buffer]
mov ecx, eax
shr ecx, 2
rep movsd
mov [.current_buffer], esi
.sector_done:
add [.sector_lo+.local_vars2_size], 1
adc [.sector_hi+.local_vars2_size], 0
; 11e. Continue the loop at 11b-11d until all sectors are processed.
dec [.num_sectors]
jnz .store_to_cache
.cache_error:
; 11f. Release the lock.
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
call mutex_unlock
.copy_done:
; 12. Remove portion of local variables created at step 8,
; free the buffer allocated at step 7 and return.
pop ecx ecx
stdcall kernel_free
jmp .return
.read_error:
; If no sectors were read, free the buffer allocated at step 7
; and pass the error to the caller.
push eax
stdcall kernel_free, [.allocated_buffer+4]
pop eax
add esp, .local_vars2_size
jmp .return_eax
.nomemory:
mov eax, DISK_STATUS_NO_MEMORY
jmp .return_eax
.floppy:
; We don't want to prefetch anything, just read one sector.
; We are still holding the lock acquired at step 4a.
; 13. Call the lookup function adding sector to the cache.
call cache_lookup_write
test eax, eax
jnz .floppy_cache_error
push esi
 
; 14. Call the driver to read one sector.
push 1
push esp
push edx
push [.sector_lo+12]
mov ecx, [.cache+16]
mov eax, edi
shl eax, 9
add eax, [ecx+DISKCACHE.data]
push eax
push [.sector_lo+16]
push edi
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read
call disk_call_driver
pop ecx
dec ecx
jnz .read_done
jnz .floppy_read_error
; 15. Get the slot and pointer to the cache item,
; change the status to not-modified copy of the disk
; and go to 4c.
pop esi
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
mov ecx, [ebx+DISKCACHE.sector_size_log]
jmp .found_in_cache
 
mov ecx, [.cache]
lea eax, [edi*3]
mov esi, [ecx+DISKCACHE.pointer]
lea esi, [eax*4+esi]
 
mov eax, [.sector_lo]
mov edx, [.sector_hi]
mov [esi], eax ; sector number
mov [esi+4], edx ; sector number
mov dword [esi+8], 1; hd read - mark as same as in hd
 
.yeshdcache:
 
mov esi, edi
mov ecx, [.cache]
shl esi, 9
add esi, [ecx+DISKCACHE.data]
 
mov edi, ebx
mov ecx, 512/4
rep movsd ; move data
xor eax, eax ; successful read
.read_done:
mov ecx, [.cache]
; On error at steps 13-14, release the lock
; and pass the error to the caller.
.floppy_read_error:
pop ecx
.floppy_cache_error:
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock
push eax
call mutex_unlock
pop eax
add esp, 12
pop edi esi edx ecx
ret
jmp .return_eax
 
; This function is intended to replace the old 'hd_write' function when
; [hdd_appl_data] = 0, so its input/output parameters are the same, except
162,11 → 777,13
; eax is relative to partition start
; out: eax = error code; 0 = ok
fs_write32_sys:
; Save ecx, set ecx to SysCache and let the common part do its work.
push ecx
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.SysCache
jmp fs_write32_common
; Just call the advanced function.
push ecx edx
xor edx, edx
mov ecx, 1
call fs_write64_sys
pop edx ecx
ret
 
; This function is intended to replace the old 'hd_write' function when
; [hdd_appl_data] = 1, so its input/output parameters are the same, except
175,144 → 792,93
; eax is relative to partition start
; out: eax = error code; 0 = ok
fs_write32_app:
; Save ecx, set ecx to AppCache and let the common part do its work.
push ecx
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.AppCache
 
; This label is the common part of fs_read32_sys and fs_read32_app.
fs_write32_common:
; 1. Check that the required sector is inside the partition. If no, return
; DISK_STATUS_END_OF_MEDIA.
cmp dword [ebp+PARTITION.Length+4], 0
jnz @f
cmp dword [ebp+PARTITION.Length], eax
ja @f
mov eax, DISK_STATUS_END_OF_MEDIA
pop ecx
ret
@@:
push edx esi
; 2. Get the absolute sector on the disk.
; Just call the advanced function.
push ecx edx
xor edx, edx
add eax, dword [ebp+PARTITION.FirstSector]
adc edx, dword [ebp+PARTITION.FirstSector+4]
; 3. If there is no cache for this disk, just pass request to the driver.
cmp [ecx+DISKCACHE.pointer], 0
jnz .scancache
push 1
push esp ; numsectors
push edx ; startsector
push eax ; startsector
push ebx ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.write
call disk_call_driver
pop ecx
pop esi edx
pop ecx
mov ecx, 1
call fs_write64_app
pop edx ecx
ret
.scancache:
; 4. Scan the cache.
push edi ecx ; scan cache
push edx eax
virtual at esp
.sector_lo dd ?
.sector_hi dd ?
.cache dd ?
end virtual
; The following code is inherited from hd_write. The differences are:
; all code is protected by the cache lock;
; sector is 64-bit, not 32-bit.
call mutex_lock
 
; check if the cache already has the sector and overwrite it
mov eax, [.sector_lo]
mov edx, [.sector_hi]
mov esi, [ecx+DISKCACHE.pointer]
mov ecx, [ecx+DISKCACHE.sad_size]
add esi, 12
; Lookup for the given sector in the given cache.
; If the sector is not present, return error.
; The caller must acquire the cache lock.
; in: edx:eax = sector
; in: ebx -> DISKCACHE structure
; out: CF set if sector is not in cache
; out: ecx = sector_size_log
; out: esi -> sector:status
; out: edi -> sector data
proc cache_lookup_read
mov esi, [ebx+DISKCACHE.pointer]
add esi, sizeof.CACHE_ITEM
 
mov edi, 1
 
.hdwritecache:
cmp dword [esi+8], 0 ; if cache slot is empty
je .not_in_cache_write
.hdreadcache:
 
cmp [esi], eax ; if the slot has the sector
jne .not_in_cache_write
cmp [esi+4], edx ; if the slot has the sector
je .yes_in_cache_write
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_EMPTY
je .nohdcache
 
.not_in_cache_write:
cmp [esi+CACHE_ITEM.SectorLo], eax
jne .nohdcache
cmp [esi+CACHE_ITEM.SectorHi], edx
jne .nohdcache
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl edi, cl
add edi, [ebx+DISKCACHE.data]
clc
ret
 
add esi, 12
.nohdcache:
 
add esi, sizeof.CACHE_ITEM
inc edi
dec ecx
jnz .hdwritecache
 
; sector not found in cache
; write the block to a new location
 
mov esi, [.cache]
call find_empty_slot64 ; ret in edi
test eax, eax
jne .hd_write_access_denied
 
mov ecx, [.cache]
lea eax, [edi*3]
mov esi, [ecx+DISKCACHE.pointer]
lea esi, [eax*4+esi]
 
mov eax, [.sector_lo]
mov edx, [.sector_hi]
mov [esi], eax ; sector number
mov [esi+4], edx ; sector number
 
.yes_in_cache_write:
 
mov dword [esi+8], 2 ; write - differs from hd
 
shl edi, 9
mov ecx, [.cache]
add edi, [ecx+DISKCACHE.data]
 
mov esi, ebx
mov ecx, 512/4
rep movsd ; move data
xor eax, eax ; success
.hd_write_access_denied:
mov ecx, [.cache]
push eax
call mutex_unlock
pop eax
add esp, 12
pop edi esi edx ecx
cmp edi, [ebx+DISKCACHE.sad_size]
jbe .hdreadcache
stc
ret
endp
 
; This internal function is called from fs_read32_* and fs_write32_*. It is the
; analogue of find_empty_slot for 64-bit sectors.
find_empty_slot64:
; Lookup for the given sector in the given cache.
; If the sector is not present, allocate space for it,
; possibly flushing data.
; in: edx:eax = sector
; in: ebx -> DISKCACHE structure
; in: ebp -> PARTITION structure
; out: eax = error code
; out: esi -> sector:status
; out: edi -> sector data
proc cache_lookup_write
call cache_lookup_read
jnc .return0
push edx eax
;-----------------------------------------------------------
; find empty or read slot, flush cache if next 12.5% is used by write
; output : edi = cache slot
; output : ecx = cache slot
;-----------------------------------------------------------
; Note: the code is essentially inherited, so probably
; no analysis of efficiency were done.
; However, it works.
.search_again:
mov ecx, [esi+DISKCACHE.sad_size]
mov edi, [esi+DISKCACHE.search_start]
shr ecx, 3
mov eax, [ebx+DISKCACHE.sad_size]
mov ecx, [ebx+DISKCACHE.search_start]
shr eax, 3
lea esi, [ecx*sizeof.CACHE_ITEM/4]
shl esi, 2
add esi, [ebx+DISKCACHE.pointer]
.search_for_empty:
inc edi
cmp edi, [esi+DISKCACHE.sad_size]
inc ecx
add esi, sizeof.CACHE_ITEM
cmp ecx, [ebx+DISKCACHE.sad_size]
jbe .inside_cache
mov edi, 1
mov ecx, 1
mov esi, [ebx+DISKCACHE.pointer]
add esi, sizeof.CACHE_ITEM
.inside_cache:
lea eax, [edi*3]
shl eax, 2
add eax, [esi+DISKCACHE.pointer]
cmp dword [eax+8], 2
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jb .found_slot ; it's empty or read
dec ecx
dec eax
jnz .search_for_empty
stdcall write_cache64, [ebp+PARTITION.Disk] ; no empty slots found, write all
test eax, eax
319,125 → 885,338
jne .found_slot_access_denied
jmp .search_again ; and start again
.found_slot:
mov [esi+DISKCACHE.search_start], edi
mov [ebx+DISKCACHE.search_start], ecx
popd [esi+CACHE_ITEM.SectorLo]
popd [esi+CACHE_ITEM.SectorHi]
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_EMPTY
mov edi, ecx
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl edi, cl
add edi, [ebx+DISKCACHE.data]
.return0:
xor eax, eax ; success
ret
.found_slot_access_denied:
add esp, 8
ret
endp
 
; This function is intended to replace the old 'write_cache' function.
proc write_cache64 uses ecx edx esi edi, disk:dword
locals
cache_chain_started dd 0
cache_chain_size dd ?
cache_chain_pos dd ?
cache_chain_ptr dd ?
endl
saved_esi_pos = 16+12 ; size of local variables + size of registers before esi
; If there is no cache for this disk, nothing to do.
cmp [esi+DISKCACHE.pointer], 0
jz .flush
;-----------------------------------------------------------
; write all changed sectors to disk
;-----------------------------------------------------------
 
; write difference ( 2 ) from cache to DISK
mov ecx, [esi+DISKCACHE.sad_size]
mov esi, [esi+DISKCACHE.pointer]
add esi, 12
; Flush the given cache.
; The caller must acquire the cache lock.
; in: ebx -> DISKCACHE
; in: first argument in stdcall convention -> PARTITION
proc write_cache64
; 1. Setup stack frame.
push esi edi ; save used registers to be stdcall
sub esp, .local_vars_size ; reserve space for local vars
virtual at esp
.local_vars:
.cache_end dd ? ; item past the end of the cache
.size_left dd ? ; items left to scan
.current_ptr dd ? ; pointer to the current item
;
; Write operations are coalesced in chains,
; one chain describes a sequential interval of sectors,
; they can be sequential or scattered in the cache.
.sequential dd ?
; boolean variable, 1 if the current chain is sequential in the cache,
; 0 if additional buffer is needed to perform the operation
.chain_start_pos dd ? ; data of chain start item
.chain_start_ptr dd ? ; pointer to chain start item
.chain_size dd ? ; chain size (thanks, C.O.)
.iteration_size dd ?
; If the chain size is too large, split the operation to several iterations.
; This is size in sectors for one iterations.
.iteration_buffer dd ? ; temporary buffer for non-sequential chains
.local_vars_size = $ - .local_vars
rd 2 ; saved registers
dd ? ; return address
.disk dd ? ; first argument
end virtual
; 1. If there is no cache for this disk, nothing to do, just return zero.
cmp [ebx+DISKCACHE.pointer], 0
jz .return0
; 2. Prepare for the loop: initialize current pointer and .size_left,
; calculate .cache_end.
mov ecx, [ebx+DISKCACHE.sad_size]
mov [.size_left], ecx
lea ecx, [ecx*sizeof.CACHE_ITEM/4]
shl ecx, 2
mov esi, [ebx+DISKCACHE.pointer]
add esi, sizeof.CACHE_ITEM
add ecx, esi
mov [.cache_end], ecx
; 3. Main loop: go over all items, go to 5 for every modified item.
.look:
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jz .begin_write
.look_next:
add esi, sizeof.CACHE_ITEM
dec [.size_left]
jnz .look
; 4. Return success.
.return0:
xor eax, eax
.return:
add esp, .local_vars_size
pop edi esi ; restore used registers to be stdcall
ret 4 ; return popping one argument
.begin_write:
; We have found a modified item.
; 5. Prepare for chain finding: save the current item, initialize chain variables.
mov [.current_ptr], esi
; Initialize chain as sequential zero-length starting at the current item.
mov [.chain_start_ptr], esi
mov eax, [ebx+DISKCACHE.sad_size]
sub eax, [.size_left]
inc eax
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl eax, cl
add eax, [ebx+DISKCACHE.data]
mov [.chain_start_pos], eax
mov [.chain_size], 0
mov [.sequential], 1
; 6. Expand the chain backward.
; Note: the main loop in step 2 looks for items sequentially,
; so the previous item is not modified. If the previous sector
; is present in the cache, it automatically makes the chain scattered.
; 6a. Calculate sector number: one before the sector for the current item.
mov eax, [esi+CACHE_ITEM.SectorLo]
mov edx, [esi+CACHE_ITEM.SectorHi]
sub eax, 1
sbb edx, 0
.find_chain_start:
; 6b. For each sector where the previous item does not expand the chain,
; call the lookup function without adding to the cache.
call cache_lookup_read
; 6c. If the sector is not found in cache or is not modified, stop expanding
; and advance to step 7.
jc .found_chain_start
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jnz .found_chain_start
; 6d. We have found a new block that expands the chain backwards.
; It makes the chain non-sequential.
; Normally, sectors come in sequential blocks, so try to look at previous items
; before returning to 6b; if there is a sequential block indeed, this saves some
; time instead of many full-fledged lookups.
mov [.sequential], 0
mov [.chain_start_pos], edi
.look_backward:
; 6e. For each sector, update chain start pos/ptr, decrement sector number,
; look at the previous item.
mov [.chain_start_ptr], esi
inc [.chain_size]
sub eax, 1
sbb edx, 0
sub esi, sizeof.CACHE_ITEM
; If the previous item exists...
cmp esi, [ebx+DISKCACHE.pointer]
jbe .find_chain_start
; ...describes the correct sector...
cmp [esi+CACHE_ITEM.SectorLo], eax
jnz .find_chain_start
cmp [esi+CACHE_ITEM.SectorHi], edx
jnz .find_chain_start
; ...and is modified...
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jnz .found_chain_start
; ...expand the chain one sector backwards and continue the loop at 6e.
; Otherwise, advance to step 7 if the previous item describes the correct sector
; but is not modified, and return to step 6b otherwise.
mov edi, 1
.write_cache_more:
cmp dword [esi+8], 2 ; if cache slot is not different
jne .write_chain
mov dword [esi+8], 1 ; same as in hd
mov eax, [esi]
mov edx, [esi+4] ; edx:eax = sector to write
; Объединяем запись цепочки последовательных секторов в одно обращение к диску
cmp ecx, 1
jz .nonext
cmp dword [esi+12+8], 2
jnz .nonext
push eax edx
shl edi, cl
sub [.chain_start_pos], edi
jmp .look_backward
.found_chain_start:
; 7. Expand the chain forward.
; 7a. Prepare for the loop at 7b:
; set esi = pointer to current item, edx:eax = current sector.
mov esi, [.current_ptr]
mov eax, [esi+CACHE_ITEM.SectorLo]
mov edx, [esi+CACHE_ITEM.SectorHi]
.look_forward:
; 7b. First, look at the next item. If it describes the next sector:
; if it is modified, expand the chain with that sector and continue this step,
; if it is not modified, the chain is completed, so advance to step 8.
inc [.chain_size]
add eax, 1
adc edx, 0
cmp eax, [esi+12]
jnz @f
cmp edx, [esi+12+4]
add esi, sizeof.CACHE_ITEM
cmp esi, [.cache_end]
jae .find_chain_end
cmp [esi+CACHE_ITEM.SectorLo], eax
jnz .find_chain_end
cmp [esi+CACHE_ITEM.SectorHi], edx
jnz .find_chain_end
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jnz .found_chain_end
jmp .look_forward
.find_chain_end:
; 7c. Otherwise, call the lookup function.
call cache_lookup_read
; 7d. If the next sector is present in the cache and is modified,
; mark the chain as non-sequential and continue to step 7b.
jc .found_chain_end
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jnz .found_chain_end
mov [.sequential], 0
jmp .look_forward
.found_chain_end:
; 8. Decide whether the chain is sequential or scattered.
; Advance to step 9 for sequential chains, go to step 10 for scattered chains.
cmp [.sequential], 0
jz .write_non_sequential
.write_sequential:
; 9. Write a sequential chain to disk.
; 9a. Pass the entire chain to the driver.
mov eax, [.chain_start_ptr]
lea ecx, [.chain_size]
push ecx ; numsectors
pushd [eax+CACHE_ITEM.SectorHi] ; startsector
pushd [eax+CACHE_ITEM.SectorLo] ; startsector
push [.chain_start_pos+12] ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.write
call disk_call_driver
; 9b. If failed, pass the error code to the driver.
test eax, eax
jnz .return
; 9c. If succeeded, mark all sectors in the chain as not-modified,
; advance current item and number of items left to skip the chain.
mov esi, [.current_ptr]
mov eax, [.chain_size]
sub [.size_left], eax
@@:
pop edx 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
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
add esi, sizeof.CACHE_ITEM
dec eax
jnz @b
; 9d. Continue the main loop at step 2 if there are more sectors.
; Return success otherwise.
cmp [.size_left], 0
jnz .look
jmp .return0
.write_non_sequential:
; Write a non-sequential chain to the disk.
; 10. Allocate a temporary buffer.
; Use [.chain_size] sectors, but
; not greater than CACHE_MAX_ALLOC_SIZE bytes
; and not greater than half of free memory.
mov eax, [pg_data.pages_free]
shr eax, 1
jz .nomemory
cmp eax, CACHE_MAX_ALLOC_SIZE shr 12
jbe @f
mov eax, CACHE_MAX_ALLOC_SIZE shr 12
@@:
inc [cache_chain_size]
cmp [cache_chain_size], 16
jnz .continue
jmp .write_chain
.nonext:
call .flush_cache_chain
shl eax, 12
shr eax, cl
jz .nomemory
cmp eax, [.chain_size]
jbe @f
mov eax, [.chain_size]
@@:
mov [.iteration_size], eax
shl eax, cl
stdcall kernel_alloc, eax
test eax, eax
jnz .nothing
mov [cache_chain_size], 1
mov [cache_chain_ptr], esi
call .write_cache_sector
test eax, eax
jnz .nothing
jmp .continue
.write_chain:
call .flush_cache_chain
test eax, eax
jnz .nothing
.continue:
add esi, 12
inc edi
dec ecx
jnz .write_cache_more
call .flush_cache_chain
test eax, eax
jnz .nothing
.flush:
mov esi, [disk]
mov al, DISKFUNC.flush
call disk_call_driver
.nothing:
ret
 
.flush_cache_chain:
xor eax, eax
cmp [cache_chain_started], eax
jz @f
call .write_cache_chain
mov [cache_chain_started], 0
jz .nomemory
mov [.iteration_buffer], eax
.write_non_sequential_iteration:
; 11. Split the chain so that each iteration fits in the allocated buffer.
; Iteration size is the minimum of chain size and allocated size.
mov eax, [.chain_size]
cmp eax, [.iteration_size]
jae @f
mov [.iteration_size], eax
@@:
retn
 
.write_cache_sector:
mov [cache_chain_size], 1
mov [cache_chain_pos], edi
.write_cache_chain:
pusha
mov edi, [cache_chain_pos]
mov ecx, [ebp-saved_esi_pos]
shl edi, 9
add edi, [ecx+DISKCACHE.data]
mov ecx, [cache_chain_size]
push ecx
; 12. Prepare arguments for the driver.
mov esi, [.chain_start_ptr]
mov edi, [.iteration_buffer]
push [.iteration_size]
push esp ; numsectors
mov eax, [cache_chain_ptr]
pushd [eax+4]
pushd [eax] ; startsector
push [esi+CACHE_ITEM.SectorHi] ; startsector
push [esi+CACHE_ITEM.SectorLo] ; startsector
push edi ; buffer
mov esi, [ebp]
mov esi, [esi+PARTITION.Disk]
; 13. Copy data from the cache to the temporary buffer,
; advancing chain_start pos/ptr and marking sectors as not-modified.
; 13a. Prepare for the loop: push number of sectors to process.
push [.iteration_size+20] ; temporary variable
.copy_loop:
; 13b. For each sector, copy the data.
; Note that edi is advanced automatically.
mov esi, [.chain_start_pos+24]
mov ecx, [ebx+DISKCACHE.sector_size_log]
mov eax, 1
shl eax, cl
mov ecx, eax
shr ecx, 2
rep movsd
mov ecx, eax ; keep for 13e
; 13c. Mark the item as not-modified.
mov esi, [.chain_start_ptr+24]
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
; 13d. Check whether the next sector continues the chain.
; If so, advance to 13e. Otherwise, go to 13f.
mov eax, [esi+CACHE_ITEM.SectorLo]
mov edx, [esi+CACHE_ITEM.SectorHi]
add esi, sizeof.CACHE_ITEM
add eax, 1
adc edx, 0
cmp esi, [.cache_end+24]
jae .no_forward
cmp [esi+CACHE_ITEM.SectorLo], eax
jnz .no_forward
cmp [esi+CACHE_ITEM.SectorHi], edx
jnz .no_forward
; 13e. Increment position/pointer to the chain and
; continue the loop.
add [.chain_start_pos+24], ecx
mov [.chain_start_ptr+24], esi
dec dword [esp]
jnz .copy_loop
jmp .copy_done
.no_forward:
; 13f. Call the lookup function without adding to the cache.
; Update position/pointer with returned value.
; Note: for the last sector in the chain, edi/esi may contain
; garbage; we are not going to use them in this case.
push edi
call cache_lookup_read
mov [.chain_start_pos+28], edi
mov [.chain_start_ptr+28], esi
pop edi
dec dword [esp]
jnz .copy_loop
.copy_done:
; 13g. Restore the stack after 13a.
pop ecx
; 14. Call the driver.
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.write
call disk_call_driver
pop ecx
mov [esp+28], eax
popa
retn
pop ecx ; numsectors
; 15. If the driver has returned an error, free the buffer allocated at step 10
; and pass the error to the caller.
; Otherwise, remove the processed part from the chain and continue iterations
; starting in step 11 if there are more data to process.
test eax, eax
jnz .nonsequential_error
sub [.chain_size], ecx
jnz .write_non_sequential_iteration
; 16. The chain is written. Free the temporary buffer
; and continue the loop at step 2.
stdcall kernel_free, [.iteration_buffer]
mov esi, [.current_ptr]
jmp .look_next
.nonsequential_error:
push eax
stdcall kernel_free, [.iteration_buffer+4]
pop eax
jmp .return
.nomemory:
mov eax, DISK_STATUS_NO_MEMORY
jmp .return
endp
 
; This internal function is called from disk_add to initialize the caching for
452,13 → 1231,32
; is most useful example of a non-trivial adjustment.
; esi = pointer to DISK structure
disk_init_cache:
; 1. Calculate the suggested cache size.
; 1a. Get the size of free physical memory in pages.
; 1. Verify sector size. The code requires it to be a power of 2 not less than 4.
; In the name of sanity check that sector size is not too small or too large.
bsf ecx, [esi+DISK.MediaInfo.SectorSize]
jz .invalid_sector_size
mov eax, 1
shl eax, cl
cmp eax, [esi+DISK.MediaInfo.SectorSize]
jnz .invalid_sector_size
cmp ecx, 6
jb .invalid_sector_size
cmp ecx, 14
jbe .normal_sector_size
.invalid_sector_size:
DEBUGF 1,'K : sector size %x is invalid\n',[esi+DISK.MediaInfo.SectorSize]
xor eax, eax
ret
.normal_sector_size:
mov [esi+DISK.SysCache.sector_size_log], ecx
mov [esi+DISK.AppCache.sector_size_log], ecx
; 2. Calculate the suggested cache size.
; 2a. Get the size of free physical memory in pages.
mov eax, [pg_data.pages_free]
; 1b. Use the value to calculate the size.
; 2b. Use the value to calculate the size.
shl eax, 12 - 5 ; 1/32 of it in bytes
and eax, -8*4096 ; round down to the multiple of 8 pages
; 1c. Force lower and upper limits.
; 2c. Force lower and upper limits.
cmp eax, 1024*1024
jb @f
mov eax, 1024*1024
467,7 → 1265,7
ja @f
mov eax, 128*1024
@@:
; 1d. Give a chance to the driver to adjust the size.
; 2d. Give a chance to the driver to adjust the size.
push eax
mov al, DISKFUNC.adjust_cache_size
call disk_call_driver
475,21 → 1273,19
mov [esi+DISK.cache_size], eax
test eax, eax
jz .nocache
; 2. Allocate memory for the cache.
; 2a. Call the allocator.
; 3. Allocate memory for the cache.
; 3a. Call the allocator.
stdcall kernel_alloc, eax
test eax, eax
jnz @f
; 2b. If it failed, say a message and return with eax = 0.
; 3b. If it failed, say a message and return with eax = 0.
dbgstr 'no memory for disk cache'
jmp .nothing
@@:
; 3. Fill two DISKCACHE structures.
; 4. Fill two DISKCACHE structures.
mov [esi+DISK.SysCache.pointer], eax
lea ecx, [esi+DISK.SysCache.mutex]
lea ecx, [esi+DISK.CacheLock]
call mutex_init
lea ecx, [esi+DISK.AppCache.mutex]
call mutex_init
; The following code is inherited from getcache.inc.
mov edx, [esi+DISK.SysCache.pointer]
and [esi+DISK.SysCache.search_start], 0
503,9 → 1299,7
mov [esi+DISK.AppCache.pointer], edx
 
mov eax, [esi+DISK.SysCache.data_size]
push ebx
call calculate_for_hd64
pop ebx
call calculate_cache_slots
add eax, [esi+DISK.SysCache.pointer]
mov [esi+DISK.SysCache.data], eax
mov [esi+DISK.SysCache.sad_size], ecx
518,9 → 1312,7
pop edi
 
mov eax, [esi+DISK.AppCache.data_size]
push ebx
call calculate_for_hd64
pop ebx
call calculate_cache_slots
add eax, [esi+DISK.AppCache.pointer]
mov [esi+DISK.AppCache.data], eax
mov [esi+DISK.AppCache.sad_size], ecx
532,9 → 1324,9
rep stosd
pop edi
 
; 4. Return with nonzero al.
; 5. Return with nonzero al.
mov al, 1
; 5. Return.
; 6. Return.
.nothing:
ret
; No caching is required for this driver. Zero cache pointers and return with
545,18 → 1337,16
mov al, 1
ret
 
calculate_for_hd64:
calculate_cache_slots:
push eax
mov ebx, eax
shr eax, 9
lea eax, [eax*3]
shl eax, 2
sub ebx, eax
shr ebx, 9
mov ecx, ebx
shl ebx, 9
mov ecx, [esi+DISK.MediaInfo.SectorSize]
add ecx, sizeof.CACHE_ITEM
xor edx, edx
div ecx
mov ecx, eax
imul eax, [esi+DISK.MediaInfo.SectorSize]
sub [esp], eax
pop eax
sub eax, ebx
dec ecx
ret
 
577,12 → 1367,21
; esi = pointer to DISK
disk_sync:
; The algorithm is straightforward.
push esi
cmp [esi+DISK.SysCache.pointer], 0
jz .nothing
lea ecx, [esi+DISK.CacheLock]
call mutex_lock
push ebx
push esi ; for second write_cache64
push esi ; for first write_cache64
add esi, DISK.SysCache
lea ebx, [esi+DISK.SysCache]
call write_cache64
add esi, DISK.AppCache - DISK.SysCache
add ebx, DISK.AppCache - DISK.SysCache
call write_cache64
pop esi
pop ebx
lea ecx, [esi+DISK.CacheLock]
call mutex_unlock
.nothing:
mov al, DISKFUNC.flush
call disk_call_driver
ret
/kernel/branches/Kolibri-acpi/blkdev/flp_drv.inc
379,10 → 379,16
mov al, 8
call FDCDataOutput
call FDCDataInput
push eax
; DEBUGF 1,' %x',al
call FDCDataInput
; DEBUGF 1,' %x',al
; DEBUGF 1,'\n'
pop eax
test al, 0xC0
jz @f
mov [FDC_Status], FDC_DiskNotFound
@@:
.fail:
call save_timer_fdd_motor
popa
/kernel/branches/Kolibri-acpi/blkdev/hd_drv.inc
17,7 → 17,7
hdid dd ?
hdpos dd ?
ends
 
;-----------------------------------------------------------------------------
iglobal
align 4
ide_callbacks:
35,18 → 35,34
hd1_data HD_DATA ?, 0x10, 2
hd2_data HD_DATA ?, 0, 3
hd3_data HD_DATA ?, 0x10, 4
hd4_data HD_DATA ?, 0, 5
hd5_data HD_DATA ?, 0x10, 6
hd6_data HD_DATA ?, 0, 7
hd7_data HD_DATA ?, 0x10, 8
hd8_data HD_DATA ?, 0, 9
hd9_data HD_DATA ?, 0x10, 10
hd10_data HD_DATA ?, 0, 11
hd11_data HD_DATA ?, 0x10, 12
 
hd_address_table:
dd 0x1f0, 0x00, 0x1f0, 0x10
dd 0x170, 0x00, 0x170, 0x10
ide_mutex_table:
dd ide_channel1_mutex
dd ide_channel2_mutex
dd ide_channel3_mutex
dd ide_channel4_mutex
dd ide_channel5_mutex
dd ide_channel6_mutex
endg
 
;-----------------------------------------------------------------------------
uglobal
ide_mutex MUTEX
ide_channel1_mutex MUTEX
ide_channel2_mutex MUTEX
ide_channel3_mutex MUTEX
ide_channel4_mutex MUTEX
ide_channel5_mutex MUTEX
ide_channel6_mutex MUTEX
endg
 
;-----------------------------------------------------------------------------
proc ide_read stdcall uses edi, \
hd_data, buffer, startsector:qword, numsectors
; hd_data = pointer to hd*_data
67,15 → 83,13
; 2. Acquire the global lock.
mov ecx, ide_mutex
call mutex_lock
mov ecx, ide_channel2_mutex
mov eax, [hd_data]
push ecx
mov ecx, [hd_address_table]
cmp [eax+HD_DATA.hdbase], ecx ; 0x1F0
pop ecx
jne .IDE_Channel_2
mov ecx, ide_channel1_mutex
.IDE_Channel_2:
 
mov ecx, [hd_data]
mov ecx, [ecx+HD_DATA.hdpos]
dec ecx
shr ecx, 1
shl ecx, 2
mov ecx, [ecx + ide_mutex_table]
mov [channel_lock], ecx
call mutex_lock
; 3. Convert parameters to the form suitable for worker procedures.
83,6 → 97,7
; Worker procedures use global variables and edi for [buffer].
cmp dword [startsector+4], 0
jnz .fail
 
and [hd_error], 0
mov ecx, [hd_data]
mov eax, [ecx+HD_DATA.hdbase]
98,55 → 113,65
; DMA read is permitted if [allow_dma_access]=1 or 2
cmp [allow_dma_access], 2
ja .nodma
cmp [dma_hdd], 1
jnz .nodma
;--------------------------------------
push eax
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
pop eax
jnz @f
 
test [DRIVE_DATA+1], byte 10100000b
push eax ecx
mov ecx, [hdpos]
dec ecx
shr ecx, 2
imul ecx, sizeof.IDE_DATA
add ecx, IDE_controller_1
mov [IDE_controller_pointer], ecx
 
mov eax, [hdpos]
dec eax
and eax, 11b
shr eax, 1
add eax, ecx
cmp [eax+IDE_DATA.dma_hdd_channel_1], 1
pop ecx eax
jnz .nodma
 
jmp .dma
@@:
test [DRIVE_DATA+1], byte 1010b
jnz .nodma
.dma:
;--------------------------------------
call hd_read_dma
jmp @f
;--------------------------------------
.nodma:
call hd_read_pio
;--------------------------------------
@@:
cmp [hd_error], 0
jnz .fail
 
mov ecx, [numsectors]
inc dword [ecx] ; one more sector is read
dec [sectors_todo]
jz .done
 
inc eax
jnz .sectors_loop
;--------------------------------------
; 5. Loop is done, either due to error or because everything is done.
; Release the global lock and return the corresponding status.
.fail:
mov ecx, [channel_lock]
call mutex_unlock
 
mov ecx, ide_mutex
call mutex_unlock
 
or eax, -1
ret
;--------------------------------------
.done:
mov ecx, [channel_lock]
call mutex_unlock
 
mov ecx, ide_mutex
call mutex_unlock
 
xor eax, eax
ret
endp
 
;-----------------------------------------------------------------------------
proc ide_write stdcall uses esi edi, \
hd_data, buffer, startsector:qword, numsectors
; hd_data = pointer to hd*_data
167,15 → 192,13
; 2. Acquire the global lock.
mov ecx, ide_mutex
call mutex_lock
mov ecx, ide_channel2_mutex
mov eax, [hd_data]
push ecx
mov ecx, [hd_address_table]
cmp [eax+HD_DATA.hdbase], ecx ; 0x1F0
pop ecx
jne .IDE_Channel_2
mov ecx, ide_channel1_mutex
.IDE_Channel_2:
 
mov ecx, [hd_data]
mov ecx, [ecx+HD_DATA.hdpos]
dec ecx
shr ecx, 1
shl ecx, 2
mov ecx, [ecx + ide_mutex_table]
mov [channel_lock], ecx
call mutex_lock
; 3. Convert parameters to the form suitable for worker procedures.
183,6 → 206,7
; Worker procedures use global variables and esi for [buffer].
cmp dword [startsector+4], 0
jnz .fail
 
and [hd_error], 0
mov ecx, [hd_data]
mov eax, [ecx+HD_DATA.hdbase]
200,66 → 224,79
mov ecx, 16
cmp ecx, [sectors_todo]
jbe @f
 
mov ecx, [sectors_todo]
;--------------------------------------
@@:
mov [cache_chain_size], cl
; DMA write is permitted only if [allow_dma_access]=1
cmp [allow_dma_access], 2
jae .nodma
cmp [dma_hdd], 1
jnz .nodma
;--------------------------------------
push eax
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
pop eax
jnz @f
 
test [DRIVE_DATA+1], byte 10100000b
push eax ecx
mov ecx, [hdpos]
dec ecx
shr ecx, 2
imul ecx, sizeof.IDE_DATA
add ecx, IDE_controller_1
mov [IDE_controller_pointer], ecx
 
mov eax, [hdpos]
dec eax
and eax, 11b
shr eax, 1
add eax, ecx
cmp [eax+IDE_DATA.dma_hdd_channel_1], 1
pop ecx eax
jnz .nodma
 
jmp .dma
@@:
test [DRIVE_DATA+1], byte 1010b
jnz .nodma
.dma:
;--------------------------------------
call cache_write_dma
jmp .common
;--------------------------------------
.nodma:
mov [cache_chain_size], 1
call cache_write_pio
;--------------------------------------
.common:
cmp [hd_error], 0
jnz .fail
 
movzx ecx, [cache_chain_size]
mov eax, [numsectors]
add [eax], ecx
sub [sectors_todo], ecx
jz .done
 
add [edi], ecx
jc .fail
 
shl ecx, 9
add esi, ecx
jmp .sectors_loop
;--------------------------------------
; 5. Loop is done, either due to error or because everything is done.
; Release the global lock and return the corresponding status.
.fail:
mov ecx, [channel_lock]
call mutex_unlock
 
mov ecx, ide_mutex
call mutex_unlock
 
or eax, -1
ret
;--------------------------------------
.done:
mov ecx, [channel_lock]
call mutex_unlock
 
mov ecx, ide_mutex
call mutex_unlock
 
xor eax, eax
ret
endp
 
;-----------------------------------------------------------------------------
; This is a stub.
proc ide_querymedia stdcall, hd_data, mediainfo
mov eax, [mediainfo]
270,7 → 307,6
xor eax, eax
ret
endp
 
;-----------------------------------------------------------------------------
align 4
; input: eax = sector, edi -> buffer
277,7 → 313,6
; output: edi = edi + 512
hd_read_pio:
push eax edx
 
; Select the desired drive
mov edx, [hdbase]
add edx, 6 ;адрес регистра головок
286,9 → 321,9
out dx, al; номер головки/номер диска
call wait_for_hd_idle
 
cmp [hd_error], 0
jne hd_read_error
; ATA with 28 or 48 bit for sector number?
mov eax, [esp+4]
cmp eax, 0x10000000
372,7 → 407,6
 
pushfd
cli
 
mov ecx, 256
mov edx, [hdbase]
cld
393,6 → 427,7
out dx, al ; номер головки/номер диска
 
call wait_for_hd_idle
 
cmp [hd_error], 0
jne hd_write_error
 
550,6 → 585,7
align 4
wfhil1:
call check_hd_wait_timeout
 
cmp [hd_error], 0
jne @f
 
556,7 → 592,7
in al, dx
test al, 128
jnz wfhil1
 
;--------------------------------------
@@:
pop edx eax
ret
573,6 → 609,7
align 4
hdwait_sbuf: ; wait for sector buffer to be ready
call check_hd_wait_timeout
 
cmp [hd_error], 0
jne @f
 
587,9 → 624,10
 
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
606,22 → 644,17
align 4
.wait:
call change_task
 
cmp [IDE_common_irq_param], 0
jz .done
 
call check_hd_wait_timeout
 
cmp [hd_error], 0
jz .wait
; clear Bus Master IDE Command register
pushfd
cli
 
mov [IDE_common_irq_param], 0
mov dx, [IDEContrRegsBaseAddr]
mov al, 0
out dx, al
popfd
;--------------------------------------
align 4
.done:
pop edx
pop eax
636,23 → 669,17
align 4
.wait:
call change_task
 
cmp [IDE_common_irq_param], 0
jz .done
 
call check_hd_wait_timeout
 
cmp [hd_error], 0
jz .wait
; clear Bus Master IDE Command register
pushfd
cli
 
mov [IDE_common_irq_param], 0
mov dx, [IDEContrRegsBaseAddr]
add dx, 8
mov al, 0
out dx, al
popfd
;--------------------------------------
align 4
.done:
pop edx
pop eax
660,7 → 687,8
;-----------------------------------------------------------------------------
iglobal
align 4
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
; note that IDE descriptor table must be 4-byte aligned
; and do not cross 4K boundary
IDE_descriptor_table:
dd IDE_DMA
dw 0x2000
673,19 → 701,14
;-----------------------------------------------------------------------------
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_access db 0
endg
;-----------------------------------------------------------------------------
align 4
IDE_irq_14_handler:
; DEBUGF 1, 'K : IDE_irq_14_handler %x\n', [IDE_common_irq_param]:2
cmp [IDE_common_irq_param], irq14_num
jne .exit
 
693,7 → 716,8
cli
pushad
mov [IDE_common_irq_param], 0
mov dx, [IDEContrRegsBaseAddr]
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
; test whether it is our interrupt?
add edx, 2
in al, dx
715,12 → 739,10
mov al, 1
ret
;--------------------------------------
align 4
@@:
popad
popfd
;--------------------------------------
align 4
.exit:
mov al, 0
ret
727,6 → 749,7
;-----------------------------------------------------------------------------
align 4
IDE_irq_15_handler:
; DEBUGF 1, 'K : IDE_irq_15_handler %x\n', [IDE_common_irq_param]:2
cmp [IDE_common_irq_param], irq15_num
jne .exit
 
734,7 → 757,8
cli
pushad
mov [IDE_common_irq_param], 0
mov dx, [IDEContrRegsBaseAddr]
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
add dx, 8
; test whether it is our interrupt?
add edx, 2
757,12 → 781,10
mov al, 1
ret
;--------------------------------------
align 4
@@:
popad
popfd
;--------------------------------------
align 4
.exit:
mov al, 0
ret
769,14 → 791,16
;-----------------------------------------------------------------------------
align 4
IDE_common_irq_handler:
; DEBUGF 1, 'K : IDE_common_irq_handler %x\n', [IDE_common_irq_param]:2
pushfd
cli
cmp [IDE_common_irq_param], 0
je .exit
 
pushfd
cli
pushad
xor ebx, ebx
mov dx, [IDEContrRegsBaseAddr]
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
mov eax, IDE_common_irq_param
cmp [eax], irq14_num
mov [eax], bl
784,7 → 808,6
 
add dx, 8
;--------------------------------------
align 4
@@:
; test whether it is our interrupt?
add edx, 2
807,13 → 830,11
mov al, 1
ret
;--------------------------------------
align 4
@@:
popad
popfd
;--------------------------------------
align 4
.exit:
popfd
mov al, 0
ret
;-----------------------------------------------------------------------------
824,26 → 845,31
mov edx, [dma_hdpos]
cmp edx, [hdpos]
jne .notread
 
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, (OS_BASE+IDE_DMA)
 
push ecx esi
mov esi, eax
 
mov ecx, 512/4
cld
rep movsd
pop esi ecx
 
pop edx
pop eax
ret
;--------------------------------------
.notread:
; set data for PRD Table
mov eax, IDE_descriptor_table
851,13 → 877,18
mov word [eax+4], 0x2000
sub eax, OS_BASE
; select controller Primary or Secondary
mov dx, [IDEContrRegsBaseAddr]
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
 
push eax
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
mov eax, [hdpos]
dec eax
test eax, 10b
pop eax
jz @f
 
add edx, 8
;--------------------------------------
@@:
push edx
; Bus Master IDE PRD Table Address
881,9 → 912,9
out dx, al ; номер головки/номер диска
 
call wait_for_hd_idle
 
cmp [hd_error], 0
jnz hd_read_error
 
; ATA with 28 or 48 bit for sector number?
mov eax, [esp+4]
; -10h because the PreCache hits the boundary between lba28 and lba48
961,47 → 992,55
;--------------------------------------
.continue:
; select controller Primary or Secondary
mov dx, [IDEContrRegsBaseAddr]
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
 
mov eax, [hdpos]
dec eax
test eax, 10b
jz @f
 
add dx, 8
;--------------------------------------
@@:
; set write to memory and Start Bus Master
mov al, 9
out dx, al
 
mov eax, [CURRENT_TASK]
mov [dma_process], eax
 
mov eax, [TASK_BASE]
mov [dma_slot_ptr], eax
 
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
mov eax, [hdpos]
dec eax
test eax, 10b
jnz .ide1
 
mov [IDE_common_irq_param], irq14_num
jmp @f
;--------------------------------------
.ide1:
mov [IDE_common_irq_param], irq15_num
;--------------------------------------
@@:
popfd
; wait for interrupt
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
mov eax, [hdpos]
dec eax
test eax, 10b
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
 
mov eax, [hdpos]
mov [dma_hdpos], eax
pop edx
pop eax
 
mov [dma_cur_sector], eax
jmp hd_read_dma
;-----------------------------------------------------------------------------
1011,6 → 1050,7
; set data for PRD Table
mov eax, IDE_descriptor_table
mov edx, eax
 
pusha
mov edi, (OS_BASE+IDE_DMA)
mov dword [edx], IDE_DMA
1021,15 → 1061,21
cld
rep movsd
popa
 
sub eax, OS_BASE
; select controller Primary or Secondary
mov dx, [IDEContrRegsBaseAddr]
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
 
push eax
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
mov eax, [hdpos]
dec eax
test eax, 10b
pop eax
jz @f
 
add edx, 8
;--------------------------------------
@@:
push edx
; Bus Master IDE PRD Table Address
1053,9 → 1099,9
out dx, al ; номер головки/номер диска
 
call wait_for_hd_idle
 
cmp [hd_error], 0
jnz hd_write_error_dma
 
; ATA with 28 or 48 bit for sector number?
mov esi, [cache_chain_ptr]
mov eax, [esi]
1134,38 → 1180,49
;--------------------------------------
.continue:
; select controller Primary or Secondary
mov dx, [IDEContrRegsBaseAddr]
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
 
mov eax, [hdpos]
dec eax
test eax, 10b
jz @f
 
add dx, 8
;--------------------------------------
@@:
; set write to device and Start Bus Master
mov al, 1
out dx, al
mov eax, [CURRENT_TASK]
mov [dma_process], eax
mov eax, [TASK_BASE]
mov [dma_slot_ptr], eax
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
 
mov eax, [hdpos]
dec eax
test eax, 10b
jnz .ide1
 
mov [IDE_common_irq_param], irq14_num
jmp @f
;--------------------------------------
.ide1:
mov [IDE_common_irq_param], irq15_num
;--------------------------------------
@@:
popfd
; wait for interrupt
mov [dma_cur_sector], not 0x40
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
 
mov eax, [hdpos]
dec eax
test eax, 10b
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
1172,14 → 1229,44
pop esi
ret
;-----------------------------------------------------------------------------
uglobal
proc clear_pci_ide_interrupts
mov esi, pcidev_list
;--------------------------------------
align 4
IDE_Interrupt dw ?
IDEContrRegsBaseAddr dw ?
IDEContrProgrammingInterface dw ?
IDE_BAR0_val dw ?
IDE_BAR1_val dw ?
IDE_BAR2_val dw ?
IDE_BAR3_val dw ?
endg
.loop:
mov esi, [esi+PCIDEV.fd]
cmp esi, pcidev_list
jz .done
 
; cmp [esi+PCIDEV.class], 0x01018F
mov eax, [esi+PCIDEV.class]
shr eax, 4
cmp eax, 0x01018
jnz .loop
 
mov ah, [esi+PCIDEV.bus]
mov al, 2
mov bh, [esi+PCIDEV.devfn]
mov bl, 0x20
call pci_read_reg
 
and eax, 0FFFCh
mov edx, eax
add edx, 2
in al, dx
DEBUGF 1,'K : clear_pci_ide_interrupts: port[%x] = %x ',dx,al
out dx, al
in al, dx
DEBUGF 1,'-> %x; ',al
add edx, 8
in al, dx
DEBUGF 1,'port[%x] = %x ',dx,al
out dx, al
in al, dx
DEBUGF 1,'-> %x\n',al
jmp .loop
;--------------------------------------
.done:
ret
endp
;-----------------------------------------------------------------------------
/kernel/branches/Kolibri-acpi/blkdev/ide_cache.inc
41,53 → 41,29
ret
;--------------------------------------------------------------------
clear_CD_cache:
DEBUGF 1, 'K : clear_CD_cache\n'
pusha
.ide0:
 
mov esi, [cdpos]
dec esi
imul esi, sizeof.IDE_CACHE
add esi, cache_ide0
 
xor eax, eax
cmp [cdpos], 1
jne .ide1
mov [cache_ide0_search_start], eax
mov ecx, [cache_ide0_system_sad_size]
mov edi, [cache_ide0_pointer]
 
mov [esi+IDE_CACHE.search_start], eax
mov ecx, [esi+IDE_CACHE.system_sad_size]
mov edi, [esi+IDE_CACHE.pointer]
call .clear
mov [cache_ide0_appl_search_start], eax
mov ecx, [cache_ide0_appl_sad_size]
mov edi, [cache_ide0_data_pointer]
jmp .continue
.ide1:
cmp [cdpos], 2
jne .ide2
mov [cache_ide1_search_start], eax
mov ecx, [cache_ide1_system_sad_size]
mov edi, [cache_ide1_pointer]
 
mov [esi+IDE_CACHE.appl_search_start], eax
mov ecx, [esi+IDE_CACHE.appl_sad_size]
mov edi, [esi+IDE_CACHE.data_pointer]
call .clear
mov [cache_ide1_appl_search_start], eax
mov ecx, [cache_ide1_appl_sad_size]
mov edi, [cache_ide1_data_pointer]
jmp .continue
.ide2:
cmp [cdpos], 3
jne .ide3
mov [cache_ide2_search_start], eax
mov ecx, [cache_ide2_system_sad_size]
mov edi, [cache_ide2_pointer]
call .clear
mov [cache_ide2_appl_search_start], eax
mov ecx, [cache_ide2_appl_sad_size]
mov edi, [cache_ide2_data_pointer]
jmp .continue
.ide3:
mov [cache_ide3_search_start], eax
mov ecx, [cache_ide3_system_sad_size]
mov edi, [cache_ide3_pointer]
call .clear
mov [cache_ide3_appl_search_start], eax
mov ecx, [cache_ide3_appl_sad_size]
mov edi, [cache_ide3_data_pointer]
.continue:
call .clear
 
popa
ret
;--------------------------------------
.clear:
shl ecx, 1
cld
96,272 → 72,131
;--------------------------------------------------------------------
align 4
cd_calculate_cache:
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
; 1 - IDE0 ... 12 - IDE11
push eax
 
mov eax, [cdpos]
dec eax
imul eax, sizeof.IDE_CACHE
add eax, cache_ide0
 
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov ecx, [cache_ide0_system_sad_size]
mov esi, [cache_ide0_pointer]
jne @f
 
mov ecx, [eax+IDE_CACHE.system_sad_size]
mov esi, [eax+IDE_CACHE.pointer]
pop eax
ret
.ide0_appl_data:
mov ecx, [cache_ide0_appl_sad_size]
mov esi, [cache_ide0_data_pointer]
;--------------------------------------
@@:
mov ecx, [eax+IDE_CACHE.appl_sad_size]
mov esi, [eax+IDE_CACHE.data_pointer]
pop eax
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov ecx, [cache_ide1_system_sad_size]
mov esi, [cache_ide1_pointer]
ret
.ide1_appl_data:
mov ecx, [cache_ide1_appl_sad_size]
mov esi, [cache_ide1_data_pointer]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov ecx, [cache_ide2_system_sad_size]
mov esi, [cache_ide2_pointer]
ret
.ide2_appl_data:
mov ecx, [cache_ide2_appl_sad_size]
mov esi, [cache_ide2_data_pointer]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov ecx, [cache_ide3_system_sad_size]
mov esi, [cache_ide3_pointer]
ret
.ide3_appl_data:
mov ecx, [cache_ide3_appl_sad_size]
mov esi, [cache_ide3_data_pointer]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_1:
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
; 1 - IDE0 ... 12 - IDE11
push eax
 
mov eax, [cdpos]
dec eax
imul eax, sizeof.IDE_CACHE
add eax, cache_ide0
 
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov esi, [cache_ide0_pointer]
jne @f
 
mov esi, [eax+IDE_CACHE.pointer]
pop eax
ret
.ide0_appl_data:
mov esi, [cache_ide0_data_pointer]
;--------------------------------------
@@:
mov esi, [eax+IDE_CACHE.data_pointer]
pop eax
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov esi, [cache_ide1_pointer]
ret
.ide1_appl_data:
mov esi, [cache_ide1_data_pointer]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov esi, [cache_ide2_pointer]
ret
.ide2_appl_data:
mov esi, [cache_ide2_data_pointer]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov esi, [cache_ide3_pointer]
ret
.ide3_appl_data:
mov esi, [cache_ide3_data_pointer]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_2:
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
; 1 - IDE0 ... 12 - IDE11
mov eax, [cdpos]
dec eax
imul eax, sizeof.IDE_CACHE
add eax, cache_ide0
 
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov eax, [cache_ide0_system_data]
jne @f
 
mov eax, [eax+IDE_CACHE.system_data]
ret
.ide0_appl_data:
mov eax, [cache_ide0_appl_data]
;--------------------------------------
@@:
mov eax, [eax+IDE_CACHE.appl_data]
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov eax, [cache_ide1_system_data]
ret
.ide1_appl_data:
mov eax, [cache_ide1_appl_data]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov eax, [cache_ide2_system_data]
ret
.ide2_appl_data:
mov eax, [cache_ide2_appl_data]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov eax, [cache_ide3_system_data]
ret
.ide3_appl_data:
mov eax, [cache_ide3_appl_data]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_3:
; mov ecx,cache_max*10/100
; mov edi,[cache_search_start]
; 1 - IDE0 ... 12 - IDE11
push eax
 
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
mov eax, [cdpos]
dec eax
imul eax, sizeof.IDE_CACHE
add eax, cache_ide0
 
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov edi, [cache_ide0_search_start]
jne @f
 
mov edi, [eax+IDE_CACHE.search_start]
pop eax
ret
.ide0_appl_data:
mov edi, [cache_ide0_appl_search_start]
;--------------------------------------
@@:
mov edi, [eax+IDE_CACHE.appl_search_start]
pop eax
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov edi, [cache_ide1_search_start]
ret
.ide1_appl_data:
mov edi, [cache_ide1_appl_search_start]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov edi, [cache_ide2_search_start]
ret
.ide2_appl_data:
mov edi, [cache_ide2_appl_search_start]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov edi, [cache_ide3_search_start]
ret
.ide3_appl_data:
mov edi, [cache_ide3_appl_search_start]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_4:
; cmp edi,cache_max
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
; 1 - IDE0 ... 12 - IDE11
push eax
 
mov eax, [cdpos]
dec eax
imul eax, sizeof.IDE_CACHE
add eax, cache_ide0
 
cmp [cd_appl_data], 0
jne .ide0_appl_data
cmp edi, [cache_ide0_system_sad_size]
jne @f
 
cmp edi, [eax+IDE_CACHE.system_sad_size]
pop eax
ret
.ide0_appl_data:
cmp edi, [cache_ide0_appl_sad_size]
;--------------------------------------
@@:
cmp edi, [eax+IDE_CACHE.appl_sad_size]
pop eax
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
cmp edi, [cache_ide1_system_sad_size]
ret
.ide1_appl_data:
cmp edi, [cache_ide1_appl_sad_size]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
cmp edi, [cache_ide2_system_sad_size]
ret
.ide2_appl_data:
cmp edi, [cache_ide2_appl_sad_size]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
cmp edi, [cache_ide3_system_sad_size]
ret
.ide3_appl_data:
cmp edi, [cache_ide3_appl_sad_size]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_5:
; mov [cache_search_start],edi
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
; 1 - IDE0 ... 12 - IDE11
push eax
 
mov eax, [cdpos]
dec eax
imul eax, sizeof.IDE_CACHE
add eax, cache_ide0
 
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov [cache_ide0_search_start], edi
jne @f
 
mov [eax+IDE_CACHE.search_start], edi
pop eax
ret
.ide0_appl_data:
mov [cache_ide0_appl_search_start], edi
;--------------------------------------
@@:
mov [eax+IDE_CACHE.appl_search_start], edi
pop eax
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov [cache_ide1_search_start], edi
ret
.ide1_appl_data:
mov [cache_ide1_appl_search_start], edi
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov [cache_ide2_search_start], edi
ret
.ide2_appl_data:
mov [cache_ide2_appl_search_start], edi
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov [cache_ide3_search_start], edi
ret
.ide3_appl_data:
mov [cache_ide3_appl_search_start], edi
ret
;--------------------------------------------------------------------
;align 4
;calculate_linear_to_real:
; shr eax, 12
; mov eax, [page_tabs+eax*4]
; and eax, 0xFFFFF000
; ret
/kernel/branches/Kolibri-acpi/blkdev/rd.inc
22,11 → 22,6
.size = $ - ramdisk_functions
endg
 
; See memmap.inc.
; Currently size of memory allocated for the ramdisk is fixed.
; This should be revisited when/if memory map would become more dynamic.
RAMDISK_CAPACITY = 2880 ; in sectors
 
iglobal
align 4
ramdisk_actual_size dd RAMDISK_CAPACITY