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
/kernel/branches/Kolibri-acpi/boot/bootcode.inc
394,7 → 394,6
 
push 0
popf
sti
 
; set up esp
movzx esp, sp
401,138 → 400,21
 
push 0
pop es
xor ax, ax
and word [es:BOOT_IDE_BASE_ADDR], ax ;0
and word [es:BOOT_IDE_BAR0_16], ax ;0
and word [es:BOOT_IDE_BAR1_16], ax ;0
and word [es:BOOT_IDE_BAR2_16], ax ;0
and word [es:BOOT_IDE_BAR3_16], ax ;0
; \begin{Mario79}
; find HDD IDE DMA PCI device
; check for PCI BIOS
mov ax, 0xB101
int 0x1A
jc .nopci
cmp edx, 'PCI '
jnz .nopci
; find PCI class code
; class 1 = mass storage
; subclass 1 = IDE controller
; a) class 1, subclass 1, programming interface 0x80
; This is a Parallel IDE Controller which uses IRQs 14 and 15.
mov ax, 0xB103
mov ecx, 1*10000h + 1*100h + 0x80
mov [es:BOOT_IDE_PI_16], cx
xor si, si ; device index = 0
int 0x1A
jnc .found_1 ; Parallel IDE Controller
; b) class 1, subclass 1, programming interface 0x8f
mov ax, 0xB103
mov ecx, 1*10000h + 1*100h + 0x8f
mov [es:BOOT_IDE_PI_16], cx
xor si, si ; device index = 0
int 0x1A
jnc .found_1
; c) class 1, subclass 1, programming interface 0x85
mov ax, 0xB103
mov ecx, 1*10000h + 1*100h + 0x85
mov [es:BOOT_IDE_PI_16], cx
xor si, si ; device index = 0
int 0x1A
jnc .found_1
; d) class 1, subclass 1, programming interface 0x8A
; This is a Parallel IDE Controller which uses IRQs 14 and 15.
mov ax, 0xB103
mov ecx, 1*10000h + 1*100h + 0x8A
mov [es:BOOT_IDE_PI_16], cx
xor si, si ; device index = 0
int 0x1A
jnc .found_1 ; Parallel IDE Controller
; Controller not found!
xor ax, ax
mov [es:BOOT_IDE_PI_16], ax
jmp .nopci
;--------------------------------------
.found_1:
; get memory base BAR4
mov ax, 0xB10A
mov di, 0x20 ; memory base is config register at 0x20
push cx
int 0x1A
jc .no_BAR4 ;.nopci
and cx, 0xFFFC ; clear address decode type
mov [es:BOOT_IDE_BASE_ADDR], cx
.no_BAR4:
pop cx
;--------------------------------------
.found:
; get Interrupt Line
mov ax, 0xB10A
mov di, 0x3c ; memory base is config register at 0x3c
push cx
int 0x1A
jc .no_Interrupt ;.nopci
 
mov [es:BOOT_IDE_INTERR_16], cx
.no_Interrupt:
pop cx
;--------------------------------------
; get memory base BAR0
mov ax, 0xB10A
mov di, 0x10 ; memory base is config register at 0x10
push cx
int 0x1A
jc .no_BAR0 ;.nopci
xor cx, cx
@@:
in al, 64h
test al, 2
loopnz @b
 
mov [es:BOOT_IDE_BAR0_16], cx
.no_BAR0:
pop cx
;--------------------------------------
; get memory base BAR1
mov ax, 0xB10A
mov di, 0x14 ; memory base is config register at 0x14
push cx
int 0x1A
jc .no_BAR1 ;.nopci
 
mov [es:BOOT_IDE_BAR1_16], cx
.no_BAR1:
pop cx
;--------------------------------------
; get memory base BAR2
mov ax, 0xB10A
mov di, 0x18 ; memory base is config register at 0x18
push cx
int 0x1A
jc .no_BAR2 ;.nopci
 
mov [es:BOOT_IDE_BAR2_16], cx
.no_BAR2:
pop cx
;--------------------------------------
; get memory base BAR3
mov ax, 0xB10A
mov di, 0x1C ; memory base is config register at 0x1c
push cx
int 0x1A
jc .no_BAR3 ;.nopci
 
mov [es:BOOT_IDE_BAR3_16], cx
.no_BAR3:
pop cx
;--------------------------------------
.nopci:
; \end{Mario79}
 
mov al, 0xf6 ; Сброс клавиатуры, разрешить сканирование
out 0x60, al
xor cx, cx
wait_loop: ; variant 2
; reading state of port of 8042 controller
@@:
in al, 64h
and al, 00000010b ; ready flag
; wait until 8042 controller is ready
loopnz wait_loop
test al, 1
loopz @b
in al, 0x60
 
;;;/diamond today 5.02.2008
; set keyboard typematic rate & delay
541,16 → 423,19
xor cx, cx
@@:
in al, 64h
test al, 2
loopnz @b
test al, 1
loopz @b
in al, 0x60
mov al, 0
out 0x60, al
xor cx, cx
@@:
in al, 64h
test al, 2
loopnz @b
test al, 1
loopz @b
in al, 0x60
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sti
; --------------- APM ---------------------
and word [es:BOOT_APM_VERSION], 0 ; ver = 0.0 (APM not found)
mov ax, 0x5300
/kernel/branches/Kolibri-acpi/boot/booten.inc
55,7 → 55,7
start_msg db "Press [abcde] to change settings, press [Enter] to continue booting",13,10,0
time_msg db " or wait "
time_str db " 5 seconds"
db " before automatical continuation",13,10,0
db " to continue automatically",13,10,0
current_cfg_msg db "Current settings:",13,10,0
curvideo_msg db " [a] Videomode: ",0
 
/kernel/branches/Kolibri-acpi/boot/bootvesa.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
221,11 → 221,13
cmp [es:mi.BitsPerPixel], 32 ;It show only videomodes to have support 24 and 32 bpp
jb @f
 
; cmp [es:mi.BitsPerPixel],16
; jne .l0
; cmp [es:mi.GreenMaskSize],5
; jne .l0
; 16 bpp might actually be 15 bpp
cmp [es:mi.BitsPerPixel], 16
jne .l0
cmp [es:mi.GreenMaskSize], 5
jne .l0
; mov [es:mi.BitsPerPixel],15
jmp @f ; 15 bpp isnt supported ATM
 
 
.l0:
368,6 → 370,8
je .ok_found_mode
cmp word [es:si+8], 24
je .ok_found_mode
cmp word [es:si+8], 16
je .ok_found_mode
@@:
add si, size_of_step
cmp word [es:si], -1
392,7 → 396,8
; mov word [home_cursor],ax
; mov word [preboot_graph],ax
;SET default video of mode first probe will fined a move of work 1024x768@32
 
mov cx, 32
.find_mode:
mov ax, 1024
mov bx, 768
mov si, modes_table
411,6 → 416,8
call .loops
test ax, ax
jz .ok_found_mode
sub cx, 8
jnz .find_mode
 
mov si, modes_table
if ~ defined extended_primary_loader
474,18 → 481,15
jne .next
cmp bx, word [es:si+2]
jne .next
cmp word [es:si+8], 32
je .ok
cmp word [es:si+8], 24
je .ok
cmp cx, word [es:si+8]
jne .next
xor ax, ax
ret
.next:
add si, size_of_step
cmp word [es:si], -1
je .exit
jmp .loops
.ok:
xor ax, ax
ret
.exit:
or ax, -1
ret
/kernel/branches/Kolibri-acpi/boot/rdload.inc
9,10 → 9,10
 
 
read_ramdisk:
; READ RAMDISK IMAGE FROM HD
; READ RAMDISK IMAGE FROM HD (only for IDE0, IDE1, IDE2, IDE3)
 
cmp [boot_dev+OS_BASE+0x10000], 1
jne no_sys_on_hd
jne no_sys_on_hd.1
 
xor ebp, ebp
.hd_loop:
69,9 → 69,19
jb .hd_loop
jmp no_sys_on_hd
.yes:
DEBUGF 1, "K : RD found: %s\n", read_image_fsinfo.name
pop edi esi eax
 
call register_ramdisk
jmp yes_sys_on_hd
 
;-----------------------------------------------------------------------------
; Register ramdisk file system
register_ramdisk:
mov esi, boot_initramdisk
call boot_log
call ramdisk_init
ret
;-----------------------------------------------------------------------------
iglobal
align 4
read_image_fsinfo:
79,7 → 89,7
dq 0 ; offset: zero
dd 1474560 ; size
dd RAMDISK ; buffer
db '/hd'
.name db '/hd'
.name_digit db '0'
db '/'
.partition:
99,6 → 109,8
ret
 
no_sys_on_hd:
DEBUGF 1, "K : RD not found\n"
.1:
; test_to_format_ram_disk (need if not using ram disk)
cmp [boot_dev+OS_BASE+0x10000], 3
jne not_format_ram_disk
/kernel/branches/Kolibri-acpi/boot/shutdown.inc
13,8 → 13,24
 
$Revision$
 
use32
become_real:
cli
lgdt [realmode_gdt-OS_BASE]
jmp 8:@f
use16
@@:
mov ax, 10h
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, cr0
and eax, not 80000001h
mov cr0, eax
jmp 0x1000:pr_mode_exit
 
align 4
pr_mode_exit:
 
; setup stack
166,7 → 182,7
pop es
mov cx, 0x8000
push cx
push 0x7000
push 0x7100
pop ds
xor si, si
xor di, di
/kernel/branches/Kolibri-acpi/build.bat
1,11 → 1,10
@echo off
cls
set languages=en ru ge et sp
set drivers=com_mouse emu10k1x fm801 infinity sis sound viasound vt823x
set targets=all kernel drivers clean
set targets=kernel clean
 
call :Check_Target %1
for %%a in (all kernel) do if %%a==%target% call :Check_Lang %2
for %%a in (kernel) do if %%a==%target% call :Check_Lang %2
call :Target_%target%
 
if ERRORLEVEL 0 goto Exit_OK
56,51 → 55,6
goto :eof
 
 
:Target_all
call :Target_kernel
call :Target_drivers
goto :eof
 
 
:Target_drivers
echo *** building drivers ...
 
if not exist bin\drivers mkdir bin\drivers
cd drivers
for %%a in (%drivers%) do (
fasm -m 65536 %%a.asm ..\bin\drivers\%%a.obj
if not %errorlevel%==0 goto :Error_FasmFailed
)
cd ..
 
kpack >nul 2>&1
 
if %errorlevel%==9009 goto :Error_KpackFailed
 
echo *
echo ##############################################
echo *
echo Kpack KolibriOS drivers?
echo *
 
set /P res=[y/n]?
 
if "%res%"=="y" (
 
echo *
echo Compressing system
 
echo *
for %%a in (bin\drivers\*.obj) do (
echo ================== kpack %%a
kpack %%a
if not %errorlevel%==0 goto :Error_KpackFailed
)
 
)
goto :eof
 
 
:Target_clean
echo *** cleaning ...
rmdir /S /Q bin
114,14 → 68,6
pause
exit 1
 
:Error_KpackFailed
echo *** NOTICE ***
echo If you want to pack all applications you may
echo place "kpack" in accessible directory or system %PATH%.
echo You can get this tool from KolibriOS distribution kit.
pause
exit 1
 
:Exit_OK
echo.
echo all operations have been done
/kernel/branches/Kolibri-acpi/bus/usb/common.inc
6,7 → 6,7
; =============================================================================
; Version of all structures related to host controllers.
; Must be the same in kernel and *hci-drivers.
USBHC_VERSION = 1
USBHC_VERSION = 2
 
; USB device must have at least 100ms of stable power before initializing can
; proceed; one timer tick is 10ms, so enforce delay in 10 ticks
46,6 → 46,7
USB_STATUS_CLOSED = 16 ; pipe closed
; either explicitly with USBClosePipe
; or implicitly due to device disconnect
USB_STATUS_CANCELLED = 17 ; transfer cancelled with USBAbortPipe
 
; Possible speeds of USB devices
USB_SPEED_FS = 0 ; full-speed
63,6 → 64,9
USB_FLAG_EXTRA_WAIT = 4
; The pipe was in wait list, while another event occured;
; when the first wait will be done, reinsert the pipe to wait list
USB_FLAG_DISABLED = 8
; The pipe is temporarily disabled so that it is not visible to hardware
; but still remains in software list. Used for usb_abort_pipe.
USB_FLAG_CLOSED_BIT = 0 ; USB_FLAG_CLOSED = 1 shl USB_FLAG_CLOSED_BIT
 
; =============================================================================
136,6 → 140,14
; Initiate configuration of a new device (create pseudo-pipe describing that
; device and call usb_new_device).
; esi -> usb_controller, eax = speed (one of USB_SPEED_* constants).
DisablePipe dd ?
; This procedure temporarily removes the given pipe from hardware queue.
; esi -> usb_controller, ebx -> usb_pipe
EnablePipe dd ?
; This procedure reinserts the given pipe to hardware queue
; after DisablePipe, with clearing transfer queue.
; esi -> usb_controller, ebx -> usb_pipe
; edx -> current descriptor, eax -> new last descriptor
ends
 
; pointers to kernel API functions that are called from *HCI-drivers
307,6 → 319,8
PrevVirt dd ?
; Previous endpoint in the processing list.
; See also NextVirt field and the description before NextVirt field.
BaseList dd ?
; Pointer to head of the processing list.
;
; Every pipe has the associated transfer queue, that is, the double-linked
; list of Transfer Descriptors aka TD. For Control, Bulk and Interrupt
427,6 → 441,8
; Size of device descriptor.
Speed db ?
; Device speed, one of USB_SPEED_*.
Timer dd ?
; Handle of timer that handles request timeout.
NumInterfaces dd ?
; Number of interfaces.
ConfigDataSize dd ?
/kernel/branches/Kolibri-acpi/bus/usb/hccommon.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
; USB Host Controller support code: hardware-independent part,
; common for all controller types.
 
114,7 → 124,7
ret
endp
 
; Put the given control pipe in the wait list;
; Put the given control/bulk pipe in the wait list;
; called when the pipe structure is changed and a possible hardware cache
; needs to be synchronized. When it will be known that the cache is updated,
; usb_subscription_done procedure will be called.
128,6 → 138,17
ret
endp
 
; Same as usb_subscribe_control, but for interrupt/isochronous pipe.
proc usb_subscribe_periodic
cmp [ebx+usb_pipe.NextWait], -1
jnz @f
mov eax, [esi+usb_controller.WaitPipeListPeriodic]
mov [ebx+usb_pipe.NextWait], eax
mov [esi+usb_controller.WaitPipeListPeriodic], ebx
@@:
ret
endp
 
; Called after synchronization of hardware cache with software changes.
; Continues process of device enumeration based on when it was delayed
; due to call to usb_subscribe_control.
254,7 → 275,7
mov [esi+usb_controller.WaitPipeListAsync+edx], ebx
jmp .continue
.process:
; 7. Call the handler depending on USB_FLAG_CLOSED.
; 7. Call the handler depending on USB_FLAG_CLOSED and USB_FLAG_DISABLED.
or [ebx+usb_pipe.NextWait], -1
test [ebx+usb_pipe.Flags], USB_FLAG_CLOSED
jz .nodisconnect
261,6 → 282,11
call usb_pipe_closed
jmp .continue
.nodisconnect:
test [ebx+usb_pipe.Flags], USB_FLAG_DISABLED
jz .nodisabled
call usb_pipe_disabled
jmp .continue
.nodisabled:
call usb_subscription_done
.continue:
; 8. Restore edx and next pipe saved in step 5 and continue the loop.
/kernel/branches/Kolibri-acpi/bus/usb/hub.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
; Support for USB (non-root) hubs:
; powering up/resetting/disabling ports,
; watching for adding/removing devices.
/kernel/branches/Kolibri-acpi/bus/usb/init.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
; Initialization of the USB subsystem.
; Provides usb_init procedure, includes all needed files.
 
55,7 → 65,7
mov esi, pcidev_list
push 0
.kickoff:
mov esi, [esi+PCIDEV.list.next]
mov esi, [esi+PCIDEV.fd]
cmp esi, pcidev_list
jz .done_kickoff
cmp word [esi+PCIDEV.class+1], 0x0C03
108,7 → 118,7
; for all EHCI controllers.
mov eax, pcidev_list
.scan_ehci:
mov eax, [eax+PCIDEV.list.next]
mov eax, [eax+PCIDEV.fd]
cmp eax, pcidev_list
jz .done_ehci
cmp [eax+PCIDEV.class], 0x0C0320
120,7 → 130,7
; for all UHCI and OHCI controllers.
mov eax, pcidev_list
.scan_usb1:
mov eax, [eax+PCIDEV.list.next]
mov eax, [eax+PCIDEV.fd]
cmp eax, pcidev_list
jz .done_usb1
cmp [eax+PCIDEV.class], 0x0C0300
/kernel/branches/Kolibri-acpi/bus/usb/memory.inc
1,3 → 1,12
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
; Memory management for USB structures.
; Protocol layer uses the common kernel heap malloc/free.
; Hardware layer has special requirements:
/kernel/branches/Kolibri-acpi/bus/usb/pipe.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
; Functions for USB pipe manipulation: opening/closing, sending data etc.
;
USB_STDCALL_VERIFY = 1
13,6 → 23,11
stdcall arg
end if
}
if USB_STDCALL_VERIFY
STDCALL_VERIFY_EXTRA = 20h
else
STDCALL_VERIFY_EXTRA = 0
end if
 
; Initialization of usb_static_ep structure,
; called from controller-specific initialization; edi -> usb_static_ep
238,8 → 253,17
call mutex_lock
push ecx
; 3b. Let the controller-specific code do its job.
test [ebx+usb_pipe.Flags], USB_FLAG_DISABLED
jnz @f
mov eax, [esi+usb_controller.HardwareFunc]
call [eax+usb_hardware_func.DisablePipe]
@@:
mov eax, [esi+usb_controller.HardwareFunc]
call [eax+usb_hardware_func.UnlinkPipe]
mov edx, [ebx+usb_pipe.NextVirt]
mov eax, [ebx+usb_pipe.PrevVirt]
mov [edx+usb_pipe.PrevVirt], eax
mov [eax+usb_pipe.NextVirt], edx
; 3c. Release the corresponding lock.
pop ecx
call mutex_unlock
262,6 → 286,40
ret
endp
 
; This procedure is called when all transfers are aborted
; either due to call to usb_abort_pipe or due to pipe closing.
; It notifies all callbacks and frees all transfer descriptors.
; ebx -> usb_pipe, esi -> usb_controller, edi -> usb_hardware_func
; three stack parameters: status code for callback functions
; and descriptors where to start and stop.
proc usb_pipe_aborted
virtual at esp
dd ? ; return address
.status dd ? ; USB_STATUS_CLOSED or USB_STATUS_CANCELLED
.first_td dd ?
.last_td dd ?
end virtual
; Loop over all transfers, calling the driver with the given status
; and freeing all descriptors except the last one.
.loop:
mov edx, [.first_td]
cmp edx, [.last_td]
jz .done
mov ecx, [edx+usb_gtd.Callback]
test ecx, ecx
jz .no_callback
stdcall_verify ecx, ebx, [.status+12+STDCALL_VERIFY_EXTRA], \
[edx+usb_gtd.Buffer], 0, [edx+usb_gtd.UserData]
mov edx, [.first_td]
.no_callback:
mov eax, [edx+usb_gtd.NextVirt]
mov [.first_td], eax
stdcall [edi+usb_hardware_func.FreeTD], edx
jmp .loop
.done:
ret 12
endp
 
; This procedure is called when a pipe with USB_FLAG_CLOSED is removed from the
; corresponding wait list. It means that the hardware has fully forgot about it.
; ebx -> usb_pipe, esi -> usb_controller
268,30 → 326,26
proc usb_pipe_closed
push edi
mov edi, [esi+usb_controller.HardwareFunc]
; 1. Loop over all transfers, calling the driver with USB_STATUS_CLOSED
; and freeing all descriptors.
; 1. Notify all registered callbacks with status USB_STATUS_CLOSED, if any,
; and free all transfer descriptors, including the last one.
lea ecx, [ebx+usb_pipe.Lock]
call mutex_lock
mov edx, [ebx+usb_pipe.LastTD]
test edx, edx
jz .no_transfer
mov edx, [edx+usb_gtd.NextVirt]
.transfer_loop:
cmp edx, [ebx+usb_pipe.LastTD]
jz .transfer_done
mov ecx, [edx+usb_gtd.Callback]
test ecx, ecx
jz .no_callback
mov eax, [edx+usb_gtd.NextVirt]
push edx
stdcall_verify ecx, ebx, USB_STATUS_CLOSED, \
[edx+usb_gtd.Buffer], 0, [edx+usb_gtd.UserData]
pop edx
.no_callback:
push [edx+usb_gtd.NextVirt]
stdcall [edi+usb_hardware_func.FreeTD], edx
pop edx
jmp .transfer_loop
.transfer_done:
stdcall [edi+usb_hardware_func.FreeTD], edx
push eax
call mutex_unlock
push USB_STATUS_CLOSED
call usb_pipe_aborted
; It is safe to free LastTD here:
; usb_*_transfer_async do not enqueue new transfers if USB_FLAG_CLOSED is set.
stdcall [edi+usb_hardware_func.FreeTD], [ebx+usb_pipe.LastTD]
jmp @f
.no_transfer:
call mutex_unlock
@@:
; 2. Decrement number of pipes for the device.
; If this pipe is the last pipe, go to 5.
mov ecx, [ebx+usb_pipe.DeviceData]
342,7 → 396,16
dec eax
jnz .notify_loop
.notify_done:
; 6. Bus address, if assigned, can now be reused.
; 6. Kill the timer, if active.
; (Usually not; possible if device is disconnected
; while processing SET_ADDRESS request).
mov eax, [ebx+usb_pipe.DeviceData]
cmp [eax+usb_device_data.Timer], 0
jz @f
stdcall cancel_timer_hs, [eax+usb_device_data.Timer]
mov [eax+usb_device_data.Timer], 0
@@:
; 7. Bus address, if assigned, can now be reused.
call [edi+usb_hardware_func.GetDeviceAddress]
test eax, eax
jz @f
349,7 → 412,7
bts [esi+usb_controller.ExistingAddresses], eax
@@:
dbgstr 'USB device disconnected'
; 7. All drivers have returned from disconnect callback,
; 8. All drivers have returned from disconnect callback,
; so all drivers should not use any device-related pipes.
; Free the remaining pipes.
mov eax, [ebx+usb_pipe.DeviceData]
366,15 → 429,74
.free_done:
stdcall [edi+usb_hardware_func.FreePipe], ebx
pop eax
; 8. Free the usb_device_data structure.
; 9. Free the usb_device_data structure.
sub eax, usb_device_data.ClosedPipeList - usb_pipe.NextSibling
call free
; 9. Return.
; 10. Return.
.nothing:
pop edi
ret
endp
 
; This procedure is called when a pipe with USB_FLAG_DISABLED is removed from the
; corresponding wait list. It means that the hardware has fully forgot about it.
; ebx -> usb_pipe, esi -> usb_controller
proc usb_pipe_disabled
push edi
mov edi, [esi+usb_controller.HardwareFunc]
; 1. Acquire pipe lock.
lea ecx, [ebx+usb_pipe.Lock]
call mutex_lock
; 2. Clear USB_FLAG_DISABLED in pipe state.
and [ebx+usb_pipe.Flags], not USB_FLAG_DISABLED
; 3. Sanity check: ignore uninitialized pipes.
cmp [ebx+usb_pipe.LastTD], 0
jz .no_transfer
; 4. Acquire the first and last to-be-cancelled transfer descriptor,
; save them in stack for the step 6,
; ask the controller driver to enable the pipe for hardware,
; removing transfers between first and last to-be-cancelled descriptors.
lea ecx, [esi+usb_controller.ControlLock]
cmp [ebx+usb_pipe.Type], BULK_PIPE
jb @f ; control pipe
lea ecx, [esi+usb_controller.BulkLock]
jz @f ; bulk pipe
lea ecx, [esi+usb_controller.PeriodicLock]
@@:
call mutex_lock
mov eax, [ebx+usb_pipe.BaseList]
mov edx, [eax+usb_pipe.NextVirt]
mov [ebx+usb_pipe.NextVirt], edx
mov [ebx+usb_pipe.PrevVirt], eax
mov [edx+usb_pipe.PrevVirt], ebx
mov [eax+usb_pipe.NextVirt], ebx
mov eax, [ebx+usb_pipe.LastTD]
mov edx, [eax+usb_gtd.NextVirt]
mov [eax+usb_gtd.NextVirt], eax
mov [eax+usb_gtd.PrevVirt], eax
push eax
push edx
push ecx
call [edi+usb_hardware_func.EnablePipe]
pop ecx
call mutex_unlock
; 5. Release pipe lock acquired at step 1.
; Callbacks called at step 6 can insert new transfers,
; so we cannot call usb_pipe_aborted while holding pipe lock.
lea ecx, [ebx+usb_pipe.Lock]
call mutex_unlock
; 6. Notify all registered callbacks with status USB_STATUS_CANCELLED, if any.
; Two arguments describing transfers range were pushed at step 4.
push USB_STATUS_CANCELLED
call usb_pipe_aborted
pop edi
ret
.no_transfer:
call mutex_unlock
pop edi
ret
endp
 
; Part of API for drivers, see documentation for USBNormalTransferAsync.
proc usb_normal_transfer_async stdcall uses ebx edi,\
pipe:dword, buffer:dword, size:dword, callback:dword, calldata:dword, flags:dword
508,6 → 630,69
ret
endp
 
; Part of API for drivers, see documentation for USBAbortPipe.
proc usb_abort_pipe
push ebx esi ; save used registers to be stdcall
virtual at esp
rd 2 ; saved registers
dd ? ; return address
.pipe dd ?
end virtual
mov ebx, [.pipe]
; 1. Acquire pipe lock.
lea ecx, [ebx+usb_pipe.Lock]
call mutex_lock
; 2. If the pipe is already closed or abort is in progress,
; just release pipe lock and return.
test [ebx+usb_pipe.Flags], USB_FLAG_CLOSED + USB_FLAG_DISABLED
jnz .nothing
; 3. Mark the pipe as aborting.
or [ebx+usb_pipe.Flags], USB_FLAG_DISABLED
; 4. We cannot do anything except adding new transfers concurrently with hardware.
; Ask the controller driver to (temporarily) remove the pipe from hardware queue.
mov esi, [ebx+usb_pipe.Controller]
; 4a. Acquire queue lock.
lea ecx, [esi+usb_controller.ControlLock]
cmp [ebx+usb_pipe.Type], BULK_PIPE
jb @f ; control pipe
lea ecx, [esi+usb_controller.BulkLock]
jz @f ; bulk pipe
lea ecx, [esi+usb_controller.PeriodicLock]
@@:
call mutex_lock
push ecx
; 4b. Call the driver.
mov eax, [esi+usb_controller.HardwareFunc]
call [eax+usb_hardware_func.DisablePipe]
; 4c. Remove the pipe from software list.
mov eax, [ebx+usb_pipe.NextVirt]
mov edx, [ebx+usb_pipe.PrevVirt]
mov [eax+usb_pipe.PrevVirt], edx
mov [edx+usb_pipe.NextVirt], eax
; 4c. Register the pipe in corresponding wait list.
test [ebx+usb_pipe.Type], 1
jz .control_bulk
call usb_subscribe_periodic
jmp @f
.control_bulk:
call usb_subscribe_control
@@:
; 4d. Release queue lock.
pop ecx
call mutex_unlock
; 4e. Notify the USB thread about new work.
push ebx esi edi
call usb_wakeup
pop edi esi ebx
; That's all for now. To be continued in usb_pipe_disabled.
; 5. Release pipe lock acquired at step 1 and return.
.nothing:
lea ecx, [ebx+usb_pipe.Lock]
call mutex_unlock
pop esi ebx
ret 4
endp
 
; Part of API for drivers, see documentation for USBGetParam.
proc usb_get_param
virtual at esp
/kernel/branches/Kolibri-acpi/bus/usb/protocol.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 5177 $
 
 
; Implementation of the USB protocol for device enumeration.
; Manage a USB device when it becomes ready for USB commands:
; configure, enumerate, load the corresponding driver(s),
33,6 → 43,19
; read to the debug board.
USB_DUMP_DESCRIPTORS = 1
 
; According to the USB specification (9.2.6.3),
; any device must response to SET_ADDRESS in 50 ms, or 5 timer ticks.
; Of course, our world is far from ideal.
; I have seen devices that just NAK everything when being reset from working
; state, but start to work after second reset.
; Our strategy is as follows: give 2 seconds for the first attempt,
; this should be enough for normal devices and not too long to detect buggy ones.
; If the device continues NAKing, reset it and retry several times,
; doubling the interval: 2s -> 4s -> 8s -> 16s. Give up after that.
; Numbers are quite arbitrary.
TIMEOUT_SET_ADDRESS_INITIAL = 200
TIMEOUT_SET_ADDRESS_LAST = 1600
 
; =============================================================================
; ================================ Structures =================================
; =============================================================================
179,7 → 202,22
; out: eax = 0 <=> failed, the caller should disable the port.
proc usb_new_device
push ebx edi ; save used registers to be stdcall
; 1. Allocate resources. Any device uses the following resources:
; 1. Check whether we're here because we were trying to reset
; already-registered device in hope to fix something serious.
; If so, skip allocation and go to 6.
movzx eax, [esi+usb_controller.ResettingPort]
mov edx, [esi+usb_controller.ResettingHub]
test edx, edx
jz .test_roothub
mov edx, [edx+usb_hub.ConnectedDevicesPtr]
mov ebx, [edx+eax*4]
jmp @f
.test_roothub:
mov ebx, [esi+usb_controller.DevicesByPort+eax*4]
@@:
test ebx, ebx
jnz .try_set_address
; 2. Allocate resources. Any device uses the following resources:
; - device address in the bus
; - memory for device data
; - pipe for zero endpoint
186,14 → 224,14
; If some allocation fails, we must undo our actions. Closing the pipe
; is a hard task, so we avoid it and open the pipe as the last resource.
; The order for other two allocations is quite arbitrary.
; 1a. Allocate a bus address.
; 2a. Allocate a bus address.
push ecx
call usb_set_address_request
pop ecx
; 1b. If failed, just return zero.
; 2b. If failed, just return zero.
test eax, eax
jz .nothing
; 1c. Allocate memory for device data.
; 2c. Allocate memory for device data.
; For now, we need sizeof.usb_device_data and extra 8 bytes for GET_DESCRIPTOR
; input and output, see usb_after_set_address. Later we will reallocate it
; to actual size needed for descriptors.
201,10 → 239,10
push ecx
call malloc
pop ecx
; 1d. If failed, free the bus address and return zero.
; 2d. If failed, free the bus address and return zero.
test eax, eax
jz .nomemory
; 1e. Open pipe for endpoint zero.
; 2e. Open pipe for endpoint zero.
; For now, we do not know the actual maximum packet size;
; for full-speed devices it can be any of 8, 16, 32, 64 bytes,
; low-speed devices must have 8 bytes, high-speed devices must have 64 bytes.
227,12 → 265,14
; Put pointer to pipe into ebx. "xchg eax,reg" is one byte, mov is two bytes.
xchg eax, ebx
pop eax
; 1f. If failed, free the memory, the bus address and return zero.
; 2f. If failed, free the memory, the bus address and return zero.
test ebx, ebx
jz .freememory
; 2. Store pointer to device data in the pipe structure.
; 3. Store pointer to device data in the pipe structure.
mov [ebx+usb_pipe.DeviceData], eax
; 3. Init device data, using usb_controller.Resetting* variables.
; 4. Init device data, using usb_controller.Resetting* variables.
mov [eax+usb_device_data.Timer], edi
mov dword [eax+usb_device_data.DeviceDescriptor], TIMEOUT_SET_ADDRESS_INITIAL
mov [eax+usb_device_data.TTHub], edi
mov [eax+usb_device_data.TTPort], 0
mov [eax+usb_device_data.NumInterfaces], edi
268,7 → 308,7
mov [eax+usb_device_data.Port], cl
mov edx, [esi+usb_controller.ResettingHub]
mov [eax+usb_device_data.Hub], edx
; 4. Store pointer to the config pipe in the hub data.
; 5. Store pointer to the config pipe in the hub data.
; Config pipe serves as device identifier.
; Root hubs use the array inside usb_controller structure,
; non-root hubs use the array immediately after usb_hub structure.
281,16 → 321,29
mov [esi+usb_controller.DevicesByPort+ecx*4], ebx
@@:
call usb_reinit_pipe_list
; 5. Issue SET_ADDRESS control request, using buffer filled in step 1a.
; 6. Issue SET_ADDRESS control request, using buffer filled in step 2a.
; 6a. Configure timer to force reset after timeout.
; Note: we can't use self-destructing timer, because we need to be able to cancel it,
; and for self-destructing timer we could have race condition in cancelling/destructing.
; DEBUGF 1,'K : pipe %x\n',ebx
.try_set_address:
xor edi, edi
mov edx, [ebx+usb_pipe.DeviceData]
stdcall timer_hs, [edx+usb_device_data.DeviceDescriptor], 7FFFFFFFh, usb_abort_pipe, ebx
test eax, eax
jz .nothing
mov edx, [ebx+usb_pipe.DeviceData]
mov [edx+usb_device_data.Timer], eax
; 6b. If it succeeded, setup timer to configure wait timeout.
lea eax, [esi+usb_controller.SetAddressBuffer]
stdcall usb_control_async, ebx, eax, edi, edi, usb_set_address_callback, edi, edi
; Use the return value from usb_control_async as our return value;
; if it is zero, then something has failed.
lea eax, [esi+usb_controller.SetAddressBuffer]
stdcall usb_control_async, ebx, eax, edi, edi, usb_set_address_callback, edi, edi
.nothing:
; 6. Return.
; 7. Return.
pop edi ebx ; restore used registers to be stdcall
ret
; Handlers of failures in steps 1b, 1d, 1f.
; Handlers of failures in steps 2b, 2d, 2f.
.freememory:
call free
jmp .freeaddr
349,16 → 402,23
; Note that USB stack uses esi = pointer to usb_controller.
proc usb_set_address_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
push ebx ; save ebx to be stdcall
mov ebx, [pipe]
; 1. In any case, cancel the timer.
mov eax, [ebx+usb_pipe.DeviceData]
stdcall cancel_timer_hs, [eax+usb_device_data.Timer]
mov eax, [ebx+usb_pipe.DeviceData]
mov [eax+usb_device_data.Timer], 0
; Load data to registers for further references.
mov ebx, [pipe]
mov ecx, dword [esi+usb_controller.SetAddressBuffer+2]
mov eax, [esi+usb_controller.HardwareFunc]
; 1. Check whether the device has accepted new address. If so, proceed to 2.
; Otherwise, go to 3.
; 2. Check whether the device has accepted new address. If so, proceed to 3.
; Otherwise, go to 4 if killed by usb_set_address_timeout or to 5 otherwise.
cmp [status], USB_STATUS_CANCELLED
jz .timeout
cmp [status], 0
jnz .error
; 2. Address accepted.
; 2a. The controller-specific structure for the control pipe still uses
; 3. Address accepted.
; 3a. The controller-specific structure for the control pipe still uses
; zero address. Call the controller-specific function to change it to
; the actual address.
; Note that the hardware could cache the controller-specific structure,
367,25 → 427,49
; be safe to continue.
; dbgstr 'address set in device'
call [eax+usb_hardware_func.SetDeviceAddress]
; 2b. If the port is in non-root hub, clear 'reset in progress' flag.
; In any case, proceed to 4.
; 3b. If the port is in non-root hub, clear 'reset in progress' flag.
; In any case, proceed to 6.
mov eax, [esi+usb_controller.ResettingHub]
test eax, eax
jz .return
and [eax+usb_hub.Actions], not HUB_RESET_IN_PROGRESS
.return:
; 4. Address configuration done, we can proceed with other ports.
; 6. Address configuration done, we can proceed with other ports.
; Call the worker function for that.
call usb_test_pending_port
.wakeup:
push esi edi
call usb_wakeup
pop edi esi
.nothing:
pop ebx ; restore ebx to be stdcall
ret
.timeout:
; 4. Device continues to NAK the request. Reset it and retry.
mov edx, [ebx+usb_pipe.DeviceData]
mov ecx, [edx+usb_device_data.DeviceDescriptor]
add ecx, ecx
cmp ecx, TIMEOUT_SET_ADDRESS_LAST
ja .error
mov [edx+usb_device_data.DeviceDescriptor], ecx
dbgstr 'Timeout in USB device initialization, trying to reset...'
cmp [esi+usb_controller.ResettingHub], 0
jz .reset_roothub
push esi
mov esi, [esi+usb_controller.ResettingHub]
call usb_hub_initiate_reset
pop esi
jmp .nothing
.reset_roothub:
movzx ecx, [esi+usb_controller.ResettingPort]
call [eax+usb_hardware_func.InitiateReset]
jmp .wakeup
.error:
; 3. Device error: device not responding, disconnect etc.
; 5. Device error: device not responding, disconnect etc.
DEBUGF 1,'K : error %d in SET_ADDRESS, USB device disabled\n',[status]
; 3a. The address has not been accepted. Mark it as free.
; 5a. The address has not been accepted. Mark it as free.
bts dword [esi+usb_controller.ExistingAddresses], ecx
; 3b. Disable the port with bad device.
; 5b. Disable the port with bad device.
; For the root hub, call the controller-specific function and go to 6.
; For non-root hubs, let the hub code do its work and return (the request
; could take some time, the hub code is responsible for proceeding).
642,7 → 726,7
; 3d. Free old memory.
call free
pop eax
; 4. Issue control transfer GET_DESCRIPTOR(DEVICE) for full descriptor.
; 4. Issue control transfer GET_DESCRIPTOR(CONFIGURATION) for full descriptor.
movzx ecx, [eax+usb_device_data.DeviceDescrSize]
mov edx, [eax+usb_device_data.ConfigDataSize]
lea eax, [eax+ecx+sizeof.usb_device_data]
/kernel/branches/Kolibri-acpi/const.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
179,8 → 179,7
_io_map_1 rb 4096
ends
 
PARTITION_COUNT equ 64
DRIVE_DATA_SIZE equ (16+PARTITION_COUNT*100)
DRIVE_DATA_SIZE equ 16
 
OS_BASE equ 0x80000000
 
205,7 → 204,7
 
WIN_TEMP_XY equ (OS_BASE+0x000F300)
KEY_COUNT equ (OS_BASE+0x000F400)
KEY_BUFF equ (OS_BASE+0x000F401)
KEY_BUFF equ (OS_BASE+0x000F401) ; 120*2 + 2*2 = 244 bytes, actually 255 bytes
 
BTN_COUNT equ (OS_BASE+0x000F500)
BTN_BUFF equ (OS_BASE+0x000F501)
220,11 → 219,7
 
TMP_STACK_TOP equ 0x006CC00
 
sys_pgdir equ (OS_BASE+0x006F000)
lfb_pd_0 equ (OS_BASE+0x0070000)
lfb_pd_1 equ (OS_BASE+0x0071000)
lfb_pd_2 equ (OS_BASE+0x0072000)
lfb_pd_3 equ (OS_BASE+0x0073000)
sys_proc equ (OS_BASE+0x006F000)
 
SLOT_BASE equ (OS_BASE+0x0080000)
 
233,10 → 228,6
CLEAN_ZONE equ (_CLEAN_ZONE-OS_BASE)
IDE_DMA equ (_IDE_DMA-OS_BASE)
 
; unused?
SB16Buffer equ (OS_BASE+0x02A0000)
SB16_Status equ (OS_BASE+0x02B0000)
 
UPPER_KERNEL_PAGES equ (OS_BASE+0x0400000)
 
virtual at (OS_BASE+0x05FFF80)
252,8 → 243,8
master_tab equ (page_tabs+ (page_tabs shr 10)) ;0xFDFF70000
 
LFB_BASE equ 0xFE000000
LFB_SIZE equ 12*1024*1024
 
 
new_app_base equ 0;
 
twdw equ 0x2000 ;(CURRENT_TASK-window_data)
277,6 → 268,8
REG_RET equ (RING0_STACK_SIZE-56) ;irq0.return
 
 
PAGE_SIZE equ 4096
 
PG_UNMAP equ 0x000
PG_MAP equ 0x001
PG_WRITE equ 0x002
306,7 → 299,7
BOOT_DMA equ 0x901F ;
BOOT_PCI_DATA equ 0x9020 ;8bytes pci data
BOOT_VRR equ 0x9030 ;byte VRR start enabled 1, 2-no
BOOT_IDE_BASE_ADDR equ 0x9031 ;word IDEContrRegsBaseAddr
;BOOT_IDE_BASE_ADDR equ 0x9031 ;word IDEContrRegsBaseAddr ; now free and is not used
BOOT_MEM_AMOUNT equ 0x9034 ;dword memory amount
 
BOOT_APM_ENTRY equ 0x9040
315,12 → 308,12
BOOT_APM_CODE_32 equ 0x9050
BOOT_APM_CODE_16 equ 0x9052
BOOT_APM_DATA_16 equ 0x9054
BOOT_IDE_BAR0_16 equ 0x9056
BOOT_IDE_BAR1_16 equ 0x9058
BOOT_IDE_BAR2_16 equ 0x905A
BOOT_IDE_BAR3_16 equ 0x905C
BOOT_IDE_PI_16 equ 0x905E
BOOT_IDE_INTERR_16 equ 0x9060
;BOOT_IDE_BAR0_16 equ 0x9056 ; now free and is not used
;BOOT_IDE_BAR1_16 equ 0x9058 ; now free and is not used
;BOOT_IDE_BAR2_16 equ 0x905A ; now free and is not used
;BOOT_IDE_BAR3_16 equ 0x905C ; now free and is not used
;BOOT_IDE_PI_16 equ 0x905E ; now free and is not used
;BOOT_IDE_INTERR_16 equ 0x9060 ; now free and is not used
 
TMP_FILE_NAME equ 0
TMP_CMD_LINE equ 1024
437,7 → 430,7
y dd ?
width dd ?
height dd ?
bpp dd ?
bits_per_pixel dd ?
vrefresh dd ?
pitch dd ?
lfb dd ?
461,6 → 454,8
mask_seqno dd ?
check_mouse dd ?
check_m_pixel dd ?
 
bytes_per_pixel dd ?
ends
 
struct BOOT_DATA
507,14 → 502,13
ends
 
struct PCIDEV
list LHEAD
vid_did dd ?
bk dd ?
fd dd ?
vendor_device_id dd ?
class dd ?
svid_sdid dd ?
devfn db ?
bus db ?
irq_line db ?
rb 1
rb 2
owner dd ? ; pointer to SRV or 0
ends
 
625,6 → 619,28
NumAuxSymbols db ?
ends
 
struct STRIPPED_PE_HEADER
Signature dw ?
Characteristics dw ?
AddressOfEntryPoint dd ?
ImageBase dd ?
SectionAlignmentLog db ?
FileAlignmentLog db ?
MajorOSVersion db ?
MinorOSVersion db ?
SizeOfImage dd ?
SizeOfStackReserve dd ?
SizeOfHeapReserve dd ?
SizeOfHeaders dd ?
Subsystem db ?
NumberOfRvaAndSizes db ?
NumberOfSections dw ?
ends
STRIPPED_PE_SIGNATURE = 0x4503 ; 'PE' xor 'S'
SPE_DIRECTORY_IMPORT = 0
SPE_DIRECTORY_EXPORT = 1
SPE_DIRECTORY_BASERELOC = 2
 
struct IOCTL
handle dd ?
io_code dd ?
/kernel/branches/Kolibri-acpi/core/apic.inc
1,11 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
iglobal
IRQ_COUNT dd 24
endg
/kernel/branches/Kolibri-acpi/core/clipboard.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
;------------------------------------------------------------------------------
align 4
sys_clipboard:
/kernel/branches/Kolibri-acpi/core/conf_lib-sp.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
; Éste archivo debe ser editado con codificación CP866
 
ugui_mouse_speed cp850 'velocidad del ratón',0
/kernel/branches/Kolibri-acpi/core/debug.inc
136,9 → 136,18
; ecx=pid
; edx=sizeof(CONTEXT)
; esi->CONTEXT
; destroys eax,ecx,edx,esi,edi
cmp edx, 28h
jnz .ret
; destroys eax,ebx,ecx,edx,esi,edi
 
xor ebx, ebx ; 0 - get only gp regs
cmp edx, 40
je .std_ctx
 
cmp edx, 48+288
jne .ret
 
inc ebx ; 1 - get sse context
; TODO legacy 32-bit FPU/MMX context
.std_ctx:
; push ecx
; mov ecx, esi
call check_region
147,8 → 156,15
jnz .ret
call get_debuggee_slot
jc .ret
 
shr eax, 5
cmp eax, [fpu_owner]
jne @f
inc bh ; set swap context flag
@@:
shl eax, 8
mov edi, esi
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack]
mov eax, [eax+SLOT_BASE+APPDATA.pl0_stack]
lea esi, [eax+RING0_STACK_SIZE]
 
.ring0:
178,6 → 194,29
mov [edi+4], eax
lodsd ;esp
mov [edi+18h], eax
 
dec bl
js .ret
dec bl
jns .ret
 
test bh, bh ; check swap flag
jz @F
 
ffree st0 ; swap context
@@:
 
add esi, 4 ;top of ring0 stack
;fpu/sse context saved here
add edi, 40
mov eax, 1 ;sse context
stosd
xor eax, eax ;reserved dword
stosd
 
mov ecx, 288/4
rep movsd ;copy sse context
 
.ret:
sti
ret
/kernel/branches/Kolibri-acpi/core/dll.inc
123,13 → 123,13
 
stdcall strncmp, edx, [sz_name], 16
test eax, eax
je .ok
mov eax, edx
je .nothing
 
mov edx, [edx+SRV.fd]
jmp @B
.not_load:
mov eax, [sz_name]
; Try to load .dll driver first. If not, fallback to .obj.
push edi
sub esp, 36
mov edi, esp
150,12 → 150,6
stdcall load_pe_driver, edi, 0
add esp, 36
pop edi
test eax, eax
jnz .nothing
pop ebp
jmp load_driver
.ok:
mov eax, edx
.nothing:
ret
endp
794,177 → 788,6
ret
endp
 
align 4
proc load_driver stdcall, driver_name:dword
locals
coff dd ?
sym dd ?
strings dd ?
img_size dd ?
img_base dd ?
start dd ?
 
file_name rb 13+16+4+1 ; '/sys/drivers/<up-to-16-chars>.obj'
endl
 
lea edx, [file_name]
mov dword [edx], '/sys'
mov dword [edx+4], '/dri'
mov dword [edx+8], 'vers'
mov byte [edx+12], '/'
mov esi, [driver_name]
.redo:
lea edx, [file_name]
lea edi, [edx+13]
mov ecx, 16
@@:
lodsb
test al, al
jz @f
stosb
loop @b
@@:
mov dword [edi], '.obj'
mov byte [edi+4], 0
stdcall load_file, edx
 
test eax, eax
jz .exit
 
mov [coff], eax
 
movzx ecx, [eax+COFF_HEADER.nSections]
xor ebx, ebx
 
lea edx, [eax+20]
@@:
add ebx, [edx+COFF_SECTION.SizeOfRawData]
add ebx, 15
and ebx, not 15
add edx, sizeof.COFF_SECTION
dec ecx
jnz @B
mov [img_size], ebx
 
stdcall kernel_alloc, ebx
test eax, eax
jz .fail
mov [img_base], eax
 
mov edi, eax
xor eax, eax
mov ecx, [img_size]
add ecx, 4095
and ecx, not 4095
shr ecx, 2
cld
rep stosd
 
mov edx, [coff]
movzx ebx, [edx+COFF_HEADER.nSections]
mov edi, [img_base]
lea eax, [edx+20]
@@:
mov [eax+COFF_SECTION.VirtualAddress], edi
mov esi, [eax+COFF_SECTION.PtrRawData]
test esi, esi
jnz .copy
add edi, [eax+COFF_SECTION.SizeOfRawData]
jmp .next
.copy:
add esi, edx
mov ecx, [eax+COFF_SECTION.SizeOfRawData]
cld
rep movsb
.next:
add edi, 15
and edi, not 15
add eax, sizeof.COFF_SECTION
dec ebx
jnz @B
 
mov ebx, [edx+COFF_HEADER.pSymTable]
add ebx, edx
mov [sym], ebx
mov ecx, [edx+COFF_HEADER.nSymbols]
add ecx, ecx
lea ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE
add ecx, [sym]
mov [strings], ecx
 
lea eax, [edx+20]
 
stdcall fix_coff_symbols, eax, [sym], [edx+COFF_HEADER.nSymbols], \
[strings], __exports
test eax, eax
jz .link_fail
 
mov ebx, [coff]
stdcall fix_coff_relocs, ebx, [sym], 0
 
stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szVersion
test eax, eax
jz .link_fail
 
mov eax, [eax]
shr eax, 16
cmp eax, DRV_COMPAT
jb .ver_fail
 
cmp eax, DRV_CURRENT
ja .ver_fail
 
mov ebx, [coff]
stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szSTART
mov [start], eax
 
stdcall kernel_free, [coff]
 
mov ebx, [start]
stdcall ebx, DRV_ENTRY
test eax, eax
jnz .ok
 
stdcall kernel_free, [img_base]
 
xor eax, eax
ret
.ok:
mov ebx, [img_base]
mov [eax+SRV.base], ebx
mov ecx, [start]
mov [eax+SRV.entry], ecx
ret
 
.ver_fail:
mov esi, msg_CR
call sys_msg_board_str
mov esi, [driver_name]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
mov esi, msg_version
call sys_msg_board_str
mov esi, msg_www
call sys_msg_board_str
jmp .cleanup
 
.link_fail:
mov esi, msg_module
call sys_msg_board_str
mov esi, [driver_name]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
.cleanup:
stdcall kernel_free, [img_base]
.fail:
stdcall kernel_free, [coff]
.exit:
xor eax, eax
ret
endp
 
; in: edx -> COFF_SECTION struct
; out: eax = alignment as mask for bits to drop
coff_get_align:
1009,10 → 832,9
; ignore timestamp
cli
 
mov esi, [CURRENT_TASK]
shl esi, 8
mov esi, [current_process]
lea edi, [fullname]
mov ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr]
mov ebx, [esi+PROC.dlls_list_ptr]
test ebx, ebx
jz .not_in_process
mov esi, [ebx+HDLL.fd]
1372,28 → 1194,21
; out: eax = APPDATA.dlls_list_ptr if all is OK,
; NULL if memory allocation failed
init_dlls_in_thread:
mov ebx, [current_slot]
mov eax, [ebx+APPDATA.dlls_list_ptr]
mov ebx, [current_process]
mov eax, [ebx+PROC.dlls_list_ptr]
test eax, eax
jnz .ret
push [ebx+APPDATA.dir_table]
 
mov eax, 8
call malloc
pop edx
call malloc ; FIXME
test eax, eax
jz .ret
 
mov [eax], eax
mov [eax+4], eax
mov ecx, [TASK_COUNT]
mov ebx, SLOT_BASE+256
.set:
cmp [ebx+APPDATA.dir_table], edx
jnz @f
mov [ebx+APPDATA.dlls_list_ptr], eax
@@:
add ebx, 256
dec ecx
jnz .set
 
mov ebx, [current_process]
mov [ebx+PROC.dlls_list_ptr], eax
.ret:
ret
 
1414,60 → 1229,11
 
destroy_hdll:
push ebx ecx esi edi
push eax
mov ebx, [eax+HDLL.base]
mov esi, [eax+HDLL.parent]
mov edx, [esi+DLLDESCR.size]
; The following actions require the context of application where HDLL is mapped.
; However, destroy_hdll can be called in the context of OS thread when
; cleaning up objects created by the application which is destroyed.
; So remember current cr3 and set it to page table of target.
mov eax, [ecx+APPDATA.dir_table]
; Because we cheat with cr3, disable interrupts: task switch would restore
; page table from APPDATA of current thread.
; Also set [current_slot] because it is used by user_free.
pushf
cli
push [current_slot]
mov [current_slot], ecx
mov ecx, cr3
push ecx
mov cr3, eax
push ebx ; argument for user_free
mov eax, ebx
shr ebx, 12
push ebx
mov esi, [esi+DLLDESCR.data]
shr esi, 12
.unmap_loop:
 
push eax
mov eax, 2
xchg eax, [page_tabs+ebx*4]
mov ecx, [page_tabs+esi*4]
and eax, not 0xFFF
and ecx, not 0xFFF
cmp eax, ecx
jz @f
call free_page
@@:
pop eax
invlpg [eax]
add eax, 0x1000
inc ebx
inc esi
sub edx, 0x1000
ja .unmap_loop
pop ebx
and dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
call user_free
; Restore context.
pop eax
mov cr3, eax
pop [current_slot]
popf
; Ok, cheating is done.
pop eax
push eax
mov esi, [eax+HDLL.parent]
mov eax, [eax+HDLL.refcount]
call dereference_dll
/kernel/branches/Kolibri-acpi/core/exports.inc
7,11 → 7,6
 
$Revision$
 
iglobal
szKernel db 'KERNEL', 0
szVersion db 'version',0
endg
 
align 4
__exports:
export 'KERNEL', \
48,6 → 43,7
get_phys_addr, 'GetPhysAddr', \ ; eax
map_space, 'MapSpace', \
release_pages, 'ReleasePages', \
alloc_dma24, 'AllocDMA24', \ ; stdcall
\
mutex_init, 'MutexInit', \ ; gcc fastcall
mutex_lock, 'MutexLock', \ ; gcc fastcall
94,6 → 90,7
load_cursor, 'LoadCursor', \ ;stdcall
\
get_curr_task, 'GetCurrentTask', \
change_task, 'ChangeTask', \
load_file, 'LoadFile', \ ;retval eax, ebx
delay_ms, 'Sleep', \
\
105,6 → 102,7
strrchr, 'strrchr', \
\
timer_hs, 'TimerHS', \
timer_hs, 'TimerHs', \ ; shit happens
cancel_timer_hs, 'CancelTimerHS', \
\
reg_usb_driver, 'RegUSBDriver', \
121,6 → 119,8
NET_link_changed, 'NetLinkChanged', \
ETH_input, 'Eth_input', \
\
get_pcidev_list, 'GetPCIList', \
\
0, 'LFBAddress' ; must be the last one
load kernel_exports_count dword from __exports + 24
load kernel_exports_addresses dword from __exports + 28
/kernel/branches/Kolibri-acpi/core/heap.inc
129,15 → 129,11
loop @B
 
stdcall alloc_pages, dword 32
 
or eax, PG_SW
mov ebx, HEAP_BASE
mov ecx, 32
mov edx, eax
mov edi, HEAP_BASE
.l1:
stdcall map_page, edi, edx, PG_SW
add edi, 0x1000
add edx, 0x1000
dec ecx
jnz .l1
call commit_pages
 
mov edi, HEAP_BASE ;descriptors
mov ebx, HEAP_BASE+sizeof.MEM_BLOCK ;free space
480,46 → 476,39
mov [pages_count], ebx
 
stdcall alloc_kernel_space, eax
mov [lin_addr], eax
mov ebx, [pages_count]
test eax, eax
jz .err
mov [lin_addr], eax
 
mov ecx, [pages_count]
mov edx, eax
mov ebx, ecx
 
shr ecx, 3
jz .next
shr ebx, 3
jz .tail
 
and ebx, not 7
push ebx
shl ebx, 3
stdcall alloc_pages, ebx
pop ecx ; yes ecx!!!
and eax, eax
test eax, eax
jz .err
 
mov edi, eax
mov edx, [lin_addr]
@@:
stdcall map_page, edx, edi, dword PG_SW
add edx, 0x1000
add edi, 0x1000
dec ecx
jnz @B
.next:
mov ecx, [pages_count]
and ecx, 7
mov ecx, ebx
or eax, PG_SW
mov ebx, [lin_addr]
call commit_pages
 
mov edx, ebx ; this dirty hack
.tail:
mov ebx, [pages_count]
and ebx, 7
jz .end
@@:
push ecx
call alloc_page
pop ecx
test eax, eax
jz .err
 
stdcall map_page, edx, eax, dword PG_SW
add edx, 0x1000
dec ecx
dec ebx
jnz @B
.end:
mov eax, [lin_addr]
569,7 → 558,7
restore block_size
restore block_flags
 
;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;; USER HEAP ;;;;;;;;;;;;;;;;;
 
HEAP_TOP equ 0x80000000
 
576,26 → 565,29
align 4
proc init_heap
 
mov ebx, [current_slot]
mov eax, [ebx+APPDATA.heap_top]
mov ebx, [current_process]
mov eax, [ebx+PROC.heap_top]
test eax, eax
jz @F
sub eax, [ebx+APPDATA.heap_base]
sub eax, 4096
sub eax, [ebx+PROC.heap_base]
sub eax, PAGE_SIZE
ret
@@:
mov esi, [ebx+APPDATA.mem_size]
lea ecx, [ebx+PROC.heap_lock]
call mutex_init
 
mov esi, [ebx+PROC.mem_used]
add esi, 4095
and esi, not 4095
mov [ebx+APPDATA.mem_size], esi
mov [ebx+PROC.mem_used], esi
mov eax, HEAP_TOP
mov [ebx+APPDATA.heap_base], esi
mov [ebx+APPDATA.heap_top], eax
mov [ebx+PROC.heap_base], esi
mov [ebx+PROC.heap_top], eax
 
sub eax, esi
shr esi, 10
mov ecx, eax
sub eax, 4096
sub eax, PAGE_SIZE
or ecx, FREE_BLOCK
mov [page_tabs+esi], ecx
ret
608,25 → 600,28
push esi
push edi
 
mov ebx, [current_process]
lea ecx, [ebx+PROC.heap_lock]
call mutex_lock
 
mov ecx, [alloc_size]
add ecx, (4095+4096)
add ecx, (4095+PAGE_SIZE)
and ecx, not 4095
 
mov ebx, [current_slot]
mov esi, dword [ebx+APPDATA.heap_base] ; heap_base
mov edi, dword [ebx+APPDATA.heap_top] ; heap_top
l_0:
mov esi, dword [ebx+PROC.heap_base] ; heap_base
mov edi, dword [ebx+PROC.heap_top] ; heap_top
.scan:
cmp esi, edi
jae m_exit
jae .m_exit
 
mov ebx, esi
shr ebx, 12
mov eax, [page_tabs+ebx*4]
test al, FREE_BLOCK
jz test_used
jz .test_used
and eax, 0xFFFFF000
cmp eax, ecx ;alloc_size
jb m_next
jb .m_next
jz @f
 
lea edx, [esi+ecx]
648,13 → 643,15
jnz @B
.no:
 
mov edx, [current_slot]
mov edx, [current_process]
mov ebx, [alloc_size]
add ebx, 0xFFF
and ebx, not 0xFFF
add ebx, [edx+APPDATA.mem_size]
call update_mem_size
add [edx+PROC.mem_used], ebx
 
lea ecx, [edx+PROC.heap_lock]
call mutex_unlock
 
lea eax, [esi+4096]
 
pop edi
661,15 → 658,19
pop esi
pop ebx
ret
test_used:
.test_used:
test al, USED_BLOCK
jz m_exit
jz .m_exit
 
and eax, 0xFFFFF000
m_next:
.m_next:
add esi, eax
jmp l_0
m_exit:
jmp .scan
.m_exit:
mov ecx, [current_process]
lea ecx, [ecx+PROC.heap_lock]
call mutex_unlock
 
xor eax, eax
pop edi
pop esi
684,14 → 685,17
push esi
push edi
 
mov ebx, [current_slot]
mov ebx, [current_process]
lea ecx, [ebx+PROC.heap_lock]
call mutex_lock
 
mov edx, [address]
and edx, not 0xFFF
mov [address], edx
sub edx, 0x1000
jb .error
mov esi, [ebx+APPDATA.heap_base]
mov edi, [ebx+APPDATA.heap_top]
mov esi, [ebx+PROC.heap_base]
mov edi, [ebx+PROC.heap_top]
cmp edx, esi
jb .error
.scan:
708,6 → 712,10
mov esi, ecx
jmp .scan
.error:
mov ecx, [current_process]
lea ecx, [ecx+PROC.heap_lock]
call mutex_unlock
 
xor eax, eax
pop edi
pop esi
759,14 → 767,15
mov [page_tabs+ebx*4], ecx
 
.nothird:
 
mov edx, [current_slot]
mov edx, [current_process]
mov ebx, [alloc_size]
add ebx, 0xFFF
and ebx, not 0xFFF
add ebx, [edx+APPDATA.mem_size]
call update_mem_size
add [edx+PROC.mem_used], ebx
 
lea ecx, [edx+PROC.heap_lock]
call mutex_unlock
 
mov eax, [address]
 
pop edi
782,10 → 791,14
 
mov esi, [base]
test esi, esi
jz .exit
jz .fail
 
push ebx
 
mov ebx, [current_process]
lea ecx, [ebx+PROC.heap_lock]
call mutex_lock
 
xor ebx, ebx
shr esi, 12
mov eax, [page_tabs+(esi-1)*4]
821,25 → 834,30
.released:
push edi
 
mov edx, [current_slot]
mov esi, dword [edx+APPDATA.heap_base]
mov edi, dword [edx+APPDATA.heap_top]
sub ebx, [edx+APPDATA.mem_size]
mov edx, [current_process]
lea ecx, [edx+PROC.heap_lock]
mov esi, dword [edx+PROC.heap_base]
mov edi, dword [edx+PROC.heap_top]
sub ebx, [edx+PROC.mem_used]
neg ebx
call update_mem_size
mov [edx+PROC.mem_used], ebx
call user_normalize
pop edi
pop ebx
pop esi
ret
.exit:
call mutex_unlock
 
xor eax, eax
inc eax
pop ebx
pop esi
ret
 
.cantfree:
mov ecx, [current_process]
lea ecx, [ecx+PROC.heap_lock]
jmp .exit
.fail:
xor eax, eax
pop ebx
pop esi
ret
endp
968,6 → 986,13
ret
@@:
push ecx edx
 
push eax
mov ecx, [current_process]
lea ecx, [ecx+PROC.heap_lock]
call mutex_lock
pop eax
 
lea ecx, [eax - 0x1000]
shr ecx, 12
mov edx, [page_tabs+ecx*4]
975,6 → 1000,10
jnz @f
; attempt to realloc invalid pointer
.ret0:
mov ecx, [current_process]
lea ecx, [ecx+PROC.heap_lock]
call mutex_unlock
 
pop edx ecx
xor eax, eax
ret
1009,16 → 1038,16
jnz .nofreeall
mov eax, [page_tabs+ecx*4]
and eax, not 0xFFF
mov edx, [current_slot]
mov ebx, [APPDATA.mem_size+edx]
mov edx, [current_process]
mov ebx, [edx+PROC.mem_used]
sub ebx, eax
add ebx, 0x1000
or al, FREE_BLOCK
mov [page_tabs+ecx*4], eax
push esi edi
mov esi, [APPDATA.heap_base+edx]
mov edi, [APPDATA.heap_top+edx]
call update_mem_size
mov esi, [edx+PROC.heap_base]
mov edi, [edx+PROC.heap_top]
mov [edx+PROC.mem_used], ebx
call user_normalize
pop edi esi
jmp .ret0 ; all freed
1030,11 → 1059,11
shr ebx, 12
sub ebx, edx
push ebx ecx edx
mov edx, [current_slot]
mov edx, [current_process]
shl ebx, 12
sub ebx, [APPDATA.mem_size+edx]
sub ebx, [edx+PROC.mem_used]
neg ebx
call update_mem_size
mov [edx+PROC.mem_used], ebx
pop edx ecx ebx
lea eax, [ecx+1]
shl eax, 12
1044,8 → 1073,8
shl ebx, 12
jz .ret
push esi
mov esi, [current_slot]
mov esi, [APPDATA.heap_top+esi]
mov esi, [current_process]
mov esi, [esi+PROC.heap_top]
shr esi, 12
@@:
cmp edx, esi
1064,12 → 1093,16
or ebx, FREE_BLOCK
mov [page_tabs+ecx*4], ebx
.ret:
mov ecx, [current_process]
lea ecx, [ecx+PROC.heap_lock]
call mutex_unlock
pop eax edx ecx
ret
 
.realloc_add:
; get some additional memory
mov eax, [current_slot]
mov eax, [APPDATA.heap_top+eax]
mov eax, [current_process]
mov eax, [eax+PROC.heap_top]
shr eax, 12
cmp edx, eax
jae .cant_inplace
1101,17 → 1134,21
cld
rep stosd
pop edi
mov edx, [current_slot]
mov edx, [current_process]
shl ebx, 12
add ebx, [APPDATA.mem_size+edx]
call update_mem_size
add [edx+PROC.mem_used], ebx
 
mov ecx, [current_process]
lea ecx, [ecx+PROC.heap_lock]
call mutex_unlock
pop eax edx ecx
ret
 
.cant_inplace:
push esi edi
mov eax, [current_slot]
mov esi, [APPDATA.heap_base+eax]
mov edi, [APPDATA.heap_top+eax]
mov eax, [current_process]
mov esi, [eax+PROC.heap_base]
mov edi, [eax+PROC.heap_top]
shr esi, 12
shr edi, 12
sub ebx, ecx
1174,10 → 1211,9
jnz @b
.no:
push ebx
mov edx, [current_slot]
mov edx, [current_process]
shl ebx, 12
add ebx, [APPDATA.mem_size+edx]
call update_mem_size
add [edx+PROC.mem_used], ebx
pop ebx
@@:
mov dword [page_tabs+esi*4], 2
1184,50 → 1220,18
inc esi
dec ebx
jnz @b
 
mov ecx, [current_process]
lea ecx, [ecx+PROC.heap_lock]
call mutex_unlock
pop eax edi esi edx ecx
ret
 
if 0
align 4
proc alloc_dll
pushf
cli
bsf eax, [dll_map]
jnz .find
popf
xor eax, eax
ret
.find:
btr [dll_map], eax
popf
shl eax, 5
add eax, dll_tab
ret
endp
 
align 4
proc alloc_service
pushf
cli
bsf eax, [srv_map]
jnz .find
popf
xor eax, eax
ret
.find:
btr [srv_map], eax
popf
shl eax, 0x02
lea eax, [srv_tab+eax+eax*8] ;srv_tab+eax*36
ret
endp
 
end if
;;;;;;;;;;;;;; SHARED MEMORY ;;;;;;;;;;;;;;;;;
 
 
;;;;;;;;;;;;;; SHARED ;;;;;;;;;;;;;;;;;
 
 
; param
; eax= shm_map object
 
/kernel/branches/Kolibri-acpi/core/irq.inc
1,10 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
IRQ_RESERVED equ 24
 
IRQ_POOL_SIZE equ 48
/kernel/branches/Kolibri-acpi/core/memory.inc
123,19 → 123,19
endp
 
align 4
proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
;proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
map_page:
push ebx
mov eax, [phis_addr]
mov eax, [esp+12] ; phis_addr
and eax, not 0xFFF
or eax, [flags]
mov ebx, [lin_addr]
or eax, [esp+16] ; flags
mov ebx, [esp+8] ; lin_addr
shr ebx, 12
mov [page_tabs+ebx*4], eax
mov eax, [lin_addr]
mov eax, [esp+8] ; lin_addr
pop ebx
invlpg [eax]
pop ebx
ret
endp
ret 12
 
align 4
map_space: ;not implemented
350,9 → 350,64
ret
endp
 
uglobal
sb16_buffer_allocated db 0
endg
 
; Allocates [.size] bytes so that the target memory block
; is inside one 64K page for 24-bit DMA controller,
; that is, somewhere between 00xx0000h and 00xxFFFFh.
proc alloc_dma24
; Implementation note.
; The only user of that function is SB16 driver,
; so just return a statically allocated buffer.
virtual at esp
dd ? ; return address
.size dd ?
end virtual
cmp [sb16_buffer_allocated], 0
jnz .fail
inc [sb16_buffer_allocated]
mov eax, SB16Buffer
ret 4
.fail:
xor eax, eax
ret 4
endp
 
; Allocates a physical page for master page table
; that duplicates first Mb of OS_BASE at address 0;
; used for starting APs and for shutting down,
; where it is important to execute code in trivial-mapped pages.
; Returns eax = allocated physical page.
proc create_trampoline_pgmap
; The only non-trivial moment:
; we need a linear address to fill information,
; but we don't need it outside of this function,
; so we're returning physical address.
; Therefore, allocate memory with kernel_alloc,
; this will allocate physical page and a linear address somewhere,
; and deallocate only linear address with free_kernel_space.
stdcall kernel_alloc, 0x1000
mov edi, eax
mov esi, master_tab
mov ecx, 1024
rep movsd
mov ecx, [master_tab+(OS_BASE shr 20)]
mov [eax], ecx
mov edi, eax
call get_pg_addr
push eax
stdcall free_kernel_space, edi
pop eax
ret
endp
 
align 4
init_LFB:
xchg bx, bx
proc init_LFB
locals
pg_count dd ?
endl
 
cmp dword [LFBAddress], -1
jne @f
381,33 → 436,61
@@:
call init_mtrr
 
xor edx, edx
mov eax, [LFBAddress]
mov edx, LFB_BASE
mov esi, [LFBAddress]
mov edi, 0x00C00000
mov dword [exp_lfb+4], edx
 
shr edi, 12
mov [pg_count], edi
shr edi, 10
 
bt [cpu_caps], CAPS_PSE
jnc .map_page_tables
or esi, PG_LARGE+PG_UW
mov edx, sys_proc+PROC.pdt_0+(LFB_BASE shr 20)
@@:
mov [edx], esi
add edx, 4
add esi, 0x00400000
dec edi
jnz @B
 
bt [cpu_caps], CAPS_PGE
setc dh ;eliminate branch and
mov ecx, LFB_SIZE/4096
mov edi, lfb_pd_0
lea eax, [eax+edx+PG_UW] ;set PG_GLOBAL if supported
jnc @F
or dword [sys_proc+PROC.pdt_0+(LFB_BASE shr 20)], PG_GLOBAL
@@:
mov dword [LFBAddress], LFB_BASE
mov eax, cr3 ;flush TLB
mov cr3, eax
ret
 
.map_pte:
stosd
add eax, 0x1000
loop .map_pte
.map_page_tables:
 
mov ecx, (LFB_SIZE/4096)/1024
mov edi, sys_pgdir+(LFB_BASE shr 20)
lea eax, [(lfb_pd_0-OS_BASE)+PG_UW]
@@:
call alloc_page
stdcall map_page_table, edx, eax
add edx, 0x00400000
dec edi
jnz @B
 
.map_pde:
mov eax, [LFBAddress]
mov edi, page_tabs + (LFB_BASE shr 10)
or eax, PG_UW
mov ecx, [pg_count]
cld
@@:
stosd
add eax, 0x1000
loop .map_pde
dec ecx
jnz @B
 
mov dword [exp_lfb+4], LFB_BASE
mov dword [LFBAddress], LFB_BASE
mov eax, cr3 ;flush TLB
mov cr3, eax
 
ret
endp
 
align 4
proc new_mem_resize stdcall, new_size:dword
417,7 → 500,9
push edi
 
mov edx, [current_slot]
cmp [edx+APPDATA.heap_base], 0
mov ebx, [edx+APPDATA.process]
 
cmp [ebx+PROC.heap_base], 0
jne .exit
 
mov edi, [new_size]
425,7 → 510,7
and edi, not 4095
mov [new_size], edi
 
mov esi, [edx+APPDATA.mem_size]
mov esi, [ebx+PROC.mem_used]
add esi, 4095
and esi, not 4095
 
460,7 → 545,8
.update_size:
mov edx, [current_slot]
mov ebx, [new_size]
call update_mem_size
mov edx, [edx+APPDATA.process]
mov [edx+PROC.mem_used], ebx
.exit:
pop edi
pop esi
536,38 → 622,6
endp
 
 
align 4
update_mem_size:
; in: edx = slot base
; ebx = new memory size
; destroys eax,ecx,edx
 
mov [APPDATA.mem_size+edx], ebx
;search threads and update
;application memory size infomation
mov ecx, [APPDATA.dir_table+edx]
mov eax, 2
 
.search_threads:
;eax = current slot
;ebx = new memory size
;ecx = page directory
cmp eax, [TASK_COUNT]
jg .search_threads_end
mov edx, eax
shl edx, 5
cmp word [CURRENT_TASK+edx+TASKDATA.state], 9 ;if slot empty?
jz .search_threads_next
shl edx, 3
cmp [SLOT_BASE+edx+APPDATA.dir_table], ecx ;if it is our thread?
jnz .search_threads_next
mov [SLOT_BASE+edx+APPDATA.mem_size], ebx ;update memory size
.search_threads_next:
inc eax
jmp .search_threads
.search_threads_end:
ret
 
; param
; eax= linear address
;
624,11 → 678,6
pop ebx ;restore exception number (#PF)
ret
 
; xchg bx, bx
; add esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller
; restore_ring3_context
; iretd
 
.user_space:
test eax, PG_MAP
jnz .err_access ;Страница присутствует
668,9 → 717,8
; access denied? this may be a result of copy-on-write protection for DLL
; check list of HDLLs
and ebx, not 0xFFF
mov eax, [CURRENT_TASK]
shl eax, 8
mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
mov eax, [current_process]
mov eax, [eax+PROC.dlls_list_ptr]
test eax, eax
jz .fail
mov esi, [eax+HDLL.fd]
746,35 → 794,31
endp
 
; returns number of mapped bytes
proc map_mem stdcall, lin_addr:dword,slot:dword,\
proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
ofs:dword,buf_size:dword,req_access:dword
push 0 ; initialize number of mapped bytes
locals
count dd ?
process dd ?
endl
 
mov [count], 0
cmp [buf_size], 0
jz .exit
 
mov eax, [slot]
shl eax, 8
mov eax, [SLOT_BASE+eax+APPDATA.dir_table]
and eax, 0xFFFFF000
mov eax, [SLOT_BASE+eax+APPDATA.process]
test eax, eax
jz .exit
 
stdcall map_page, [ipc_pdir], eax, PG_UW
mov [process], eax
mov ebx, [ofs]
shr ebx, 22
mov esi, [ipc_pdir]
mov edi, [ipc_ptab]
mov eax, [esi+ebx*4]
mov eax, [eax+PROC.pdt_0+ebx*4] ;get page table
mov esi, [ipc_ptab]
and eax, 0xFFFFF000
jz .exit
stdcall map_page, edi, eax, PG_UW
; inc ebx
; add edi, 0x1000
; mov eax, [esi+ebx*4]
; test eax, eax
; jz @f
; and eax, 0xFFFFF000
; stdcall map_page, edi, eax
 
stdcall map_page, esi, eax, PG_SW
@@:
mov edi, [lin_addr]
and edi, 0xFFFFF000
781,61 → 825,63
mov ecx, [buf_size]
add ecx, 4095
shr ecx, 12
inc ecx
inc ecx ; ???????????
 
mov edx, [ofs]
shr edx, 12
and edx, 0x3FF
mov esi, [ipc_ptab]
 
.map:
stdcall safe_map_page, [slot], [req_access], [ofs]
jnc .exit
add dword [ebp-4], 4096
add [ofs], 4096
add [count], PAGE_SIZE
add [ofs], PAGE_SIZE
dec ecx
jz .exit
add edi, 0x1000
 
add edi, PAGE_SIZE
inc edx
cmp edx, 0x400
cmp edx, 1024
jnz .map
 
inc ebx
mov eax, [ipc_pdir]
mov eax, [eax+ebx*4]
mov eax, [process]
mov eax, [eax+PROC.pdt_0+ebx*4]
and eax, 0xFFFFF000
jz .exit
stdcall map_page, esi, eax, PG_UW
 
stdcall map_page, esi, eax, PG_SW
xor edx, edx
jmp .map
 
.exit:
pop eax
mov eax, [count]
ret
endp
 
proc map_memEx stdcall, lin_addr:dword,slot:dword,\
ofs:dword,buf_size:dword,req_access:dword
push 0 ; initialize number of mapped bytes
locals
count dd ?
process dd ?
endl
 
mov [count], 0
cmp [buf_size], 0
jz .exit
 
mov eax, [slot]
shl eax, 8
mov eax, [SLOT_BASE+eax+APPDATA.dir_table]
and eax, 0xFFFFF000
mov eax, [SLOT_BASE+eax+APPDATA.process]
test eax, eax
jz .exit
 
stdcall map_page, [proc_mem_pdir], eax, PG_UW
mov [process], eax
mov ebx, [ofs]
shr ebx, 22
mov esi, [proc_mem_pdir]
mov edi, [proc_mem_tab]
mov eax, [esi+ebx*4]
mov eax, [eax+PROC.pdt_0+ebx*4] ;get page table
mov esi, [proc_mem_tab]
and eax, 0xFFFFF000
test eax, eax
jz .exit
stdcall map_page, edi, eax, PG_UW
 
stdcall map_page, esi, eax, PG_SW
@@:
mov edi, [lin_addr]
and edi, 0xFFFFF000
842,24 → 888,35
mov ecx, [buf_size]
add ecx, 4095
shr ecx, 12
inc ecx
inc ecx ; ???????????
 
mov edx, [ofs]
shr edx, 12
and edx, 0x3FF
mov esi, [proc_mem_tab]
 
.map:
stdcall safe_map_page, [slot], [req_access], [ofs]
jnc .exit
add dword [ebp-4], 0x1000
add edi, 0x1000
add [ofs], 0x1000
add [count], PAGE_SIZE
add [ofs], PAGE_SIZE
dec ecx
jz .exit
 
add edi, PAGE_SIZE
inc edx
dec ecx
cmp edx, 1024
jnz .map
 
inc ebx
mov eax, [process]
mov eax, [eax+PROC.pdt_0+ebx*4]
and eax, 0xFFFFF000
jz .exit
 
stdcall map_page, esi, eax, PG_SW
xor edx, edx
jmp .map
.exit:
pop eax
mov eax, [count]
ret
endp
 
905,7 → 962,8
push ebx ecx
mov eax, [slot]
shl eax, 8
mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
mov eax, [SLOT_BASE+eax+APPDATA.process]
mov eax, [eax+PROC.dlls_list_ptr]
test eax, eax
jz .no_hdll
mov ecx, [eax+HDLL.fd]
992,29 → 1050,6
mov [esp+32], eax
ret
 
;align 4
;proc set_ipc_buff
 
; mov eax,[current_slot]
; pushf
; cli
; mov [eax+APPDATA.ipc_start],ebx ;set fields in extended information area
; mov [eax+APPDATA.ipc_size],ecx
;
; add ecx, ebx
; add ecx, 4095
; and ecx, not 4095
;
;.touch: mov eax, [ebx]
; add ebx, 0x1000
; cmp ebx, ecx
; jb .touch
;
; popf
; xor eax, eax
; ret
;endp
 
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
locals
dst_slot dd ?
1033,7 → 1068,7
 
mov [dst_slot], eax
shl eax, 8
mov edi, [eax+SLOT_BASE+0xa0] ;is ipc area defined?
mov edi, [eax+SLOT_BASE+APPDATA.ipc_start] ;is ipc area defined?
test edi, edi
jz .no_ipc_area
 
1041,7 → 1076,7
and ebx, 0xFFF
mov [dst_offset], ebx
 
mov esi, [eax+SLOT_BASE+0xa4]
mov esi, [eax+SLOT_BASE+APPDATA.ipc_size]
mov [buf_size], esi
 
mov ecx, [ipc_tmp]
1054,7 → 1089,7
pop edi esi
@@:
mov [used_buf], ecx
stdcall map_mem, ecx, [dst_slot], \
stdcall map_mem_ipc, ecx, [dst_slot], \
edi, esi, PG_SW
 
mov edi, [dst_offset]
1125,7 → 1160,7
.ret:
mov eax, [used_buf]
cmp eax, [ipc_tmp]
jz @f
je @f
stdcall free_kernel_space, eax
@@:
pop eax
1330,113 → 1365,6
endp
 
align 4
proc init_mtrr
 
cmp [BOOT_VARS+BOOT_MTRR], byte 2
je .exit
 
bt [cpu_caps], CAPS_MTRR
jnc .exit
 
mov eax, cr0
or eax, 0x60000000 ;disable caching
mov cr0, eax
wbinvd ;invalidate cache
 
mov ecx, 0x2FF
rdmsr ;
; has BIOS already initialized MTRRs?
test ah, 8
jnz .skip_init
; rarely needed, so mainly placeholder
; main memory - cached
push eax
 
mov eax, [MEM_AMOUNT]
; round eax up to next power of 2
dec eax
bsr ecx, eax
mov ebx, 2
shl ebx, cl
dec ebx
; base of memory range = 0, type of memory range = MEM_WB
xor edx, edx
mov eax, MEM_WB
mov ecx, 0x200
wrmsr
; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1
mov eax, 0xFFFFFFFF
mov edx, 0x0000000F
sub eax, ebx
sbb edx, 0
or eax, 0x800
inc ecx
wrmsr
; clear unused MTRRs
xor eax, eax
xor edx, edx
@@:
inc ecx
wrmsr
cmp ecx, 0x20F
jb @b
; enable MTRRs
pop eax
or ah, 8
and al, 0xF0; default memtype = UC
mov ecx, 0x2FF
wrmsr
.skip_init:
stdcall set_mtrr, [LFBAddress], [LFBSize], MEM_WC
 
wbinvd ;again invalidate
 
mov eax, cr0
and eax, not 0x60000000
mov cr0, eax ; enable caching
.exit:
ret
endp
 
align 4
proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword
; find unused register
mov ecx, 0x201
@@:
rdmsr
dec ecx
test ah, 8
jz .found
rdmsr
mov al, 0; clear memory type field
cmp eax, [base]
jz .ret
add ecx, 3
cmp ecx, 0x210
jb @b
; no free registers, ignore the call
.ret:
ret
.found:
; found, write values
xor edx, edx
mov eax, [base]
or eax, [mem_type]
wrmsr
 
mov ebx, [size]
dec ebx
mov eax, 0xFFFFFFFF
mov edx, 0x00000000
sub eax, ebx
sbb edx, 0
or eax, 0x800
inc ecx
wrmsr
ret
endp
 
align 4
proc create_ring_buffer stdcall, size:dword, flags:dword
locals
buf_ptr dd ?
/kernel/branches/Kolibri-acpi/core/mtrr.inc
0,0 → 1,881
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 5130 $
 
; Initializes MTRRs.
proc init_mtrr
 
cmp [BOOT_VARS+BOOT_MTRR], byte 2
je .exit
 
bt [cpu_caps], CAPS_MTRR
jnc .exit
 
call mtrr_reconfigure
stdcall set_mtrr, [LFBAddress], 0x1000000, MEM_WC
 
.exit:
ret
endp
 
; Helper procedure for mtrr_reconfigure and set_mtrr,
; called before changes in MTRRs.
proc mtrr_begin_change
mov eax, cr0
or eax, 0x60000000 ;disable caching
mov cr0, eax
wbinvd ;invalidate cache
ret
endp
 
; Helper procedure for mtrr_reconfigure and set_mtrr,
; called after changes in MTRRs.
proc mtrr_end_change
wbinvd ;again invalidate
mov eax, cr0
and eax, not 0x60000000
mov cr0, eax ; enable caching
ret
endp
 
; Some limits to number of structures located in the stack.
MAX_USEFUL_MTRRS = 16
MAX_RANGES = 16
 
; mtrr_reconfigure keeps a list of MEM_WB ranges.
; This structure describes one item in the list.
struct mtrr_range
next dd ? ; next item
start dq ? ; first byte
length dq ? ; length in bytes
ends
 
uglobal
align 4
num_variable_mtrrs dd 0 ; number of variable-range MTRRs
endg
 
; Helper procedure for MTRR initialization.
; Takes MTRR configured by BIOS and tries to recongifure them
; in order to allow non-UC data at top of 4G memory.
; Example: if low part of physical memory is 3.5G = 0xE0000000 bytes wide,
; BIOS can configure two MTRRs so that the first MTRR describes [0, 4G) as WB
; and the second MTRR describes [3.5G, 4G) as UC;
; WB+UC=UC, so the resulting memory map would be as needed,
; but in this configuration our attempts to map LFB at (say) 0xE8000000 as WC
; would be ignored, WB+UC+WC is still UC.
; So we must keep top of 4G memory not covered by MTRRs,
; using three WB MTRRs [0,2G) + [2G,3G) + [3G,3.5G),
; this gives the same memory map, but allows to add further entries.
; See mtrrtest.asm for detailed input/output from real hardware+BIOS.
proc mtrr_reconfigure
push ebp ; we're called from init_LFB, and it feels hurt when ebp is destroyed
; 1. Prepare local variables.
; 1a. Create list of MAX_RANGES free (aka not yet allocated) ranges.
xor eax, eax
lea ecx, [eax+MAX_RANGES]
.init_ranges:
sub esp, sizeof.mtrr_range - 4
push eax
mov eax, esp
dec ecx
jnz .init_ranges
mov eax, esp
; 1b. Fill individual local variables.
xor edx, edx
sub esp, MAX_USEFUL_MTRRS * 16 ; .mtrrs
push edx ; .mtrrs_end
push edx ; .num_used_mtrrs
push eax ; .first_free_range
push edx ; .first_range: no ranges yet
mov cl, [cpu_phys_addr_width]
or eax, -1
shl eax, cl ; note: this uses cl&31 = cl-32, not the entire cl
push eax ; .phys_reserved_mask
virtual at esp
.phys_reserved_mask dd ?
.first_range dd ?
.first_free_range dd ?
.num_used_mtrrs dd ?
.mtrrs_end dd ?
.mtrrs rq MAX_USEFUL_MTRRS * 2
.local_vars_size = $ - esp
end virtual
 
; 2. Get the number of variable-range MTRRs from MTRRCAP register.
; Abort if zero.
mov ecx, 0xFE
rdmsr
test al, al
jz .abort
mov byte [num_variable_mtrrs], al
; 3. Validate MTRR_DEF_TYPE register.
mov ecx, 0x2FF
rdmsr
; If BIOS has not initialized variable-range MTRRs, fallback to step 7.
test ah, 8
jz .fill_ranges_from_memory_map
; If the default memory type (not covered by MTRRs) is not UC,
; then probably BIOS did something strange, so it is better to exit immediately
; hoping for the best.
cmp al, MEM_UC
jnz .abort
; 4. Validate all variable-range MTRRs
; and copy configured MTRRs to the local array [.mtrrs].
; 4a. Prepare for the loop over existing variable-range MTRRs.
mov ecx, 0x200
lea edi, [.mtrrs]
.get_used_mtrrs_loop:
; 4b. For every MTRR, read PHYSBASEn and PHYSMASKn.
; In PHYSBASEn, clear upper bits and copy to ebp:ebx.
rdmsr
or edx, [.phys_reserved_mask]
xor edx, [.phys_reserved_mask]
mov ebp, edx
mov ebx, eax
inc ecx
; If PHYSMASKn is not active, ignore this MTRR.
rdmsr
inc ecx
test ah, 8
jz .get_used_mtrrs_next
; 4c. For every active MTRR, check that number of local entries is not too large.
inc [.num_used_mtrrs]
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
ja .abort
; 4d. For every active MTRR, store PHYSBASEn with upper bits cleared.
; This contains the MTRR base and the memory type in low byte.
mov [edi], ebx
mov [edi+4], ebp
; 4e. For every active MTRR, check that the range is continuous:
; PHYSMASKn with upper bits set must be negated power of two, and
; low bits of PHYSBASEn must be zeroes:
; PHYSMASKn = 1...10...0,
; PHYSBASEn = x...x0...0,
; this defines a continuous range from x...x0...0 to x...x1...1,
; length = 10...0 = negated PHYSMASKn.
; Store length in the local array.
and eax, not 0xFFF
or edx, [.phys_reserved_mask]
mov dword [edi+8], 0
mov dword [edi+12], 0
sub [edi+8], eax
sbb [edi+12], edx
; (x and -x) is the maximum power of two that divides x.
; Condition for powers of two: (x and -x) equals x.
and eax, [edi+8]
and edx, [edi+12]
cmp eax, [edi+8]
jnz .abort
cmp edx, [edi+12]
jnz .abort
sub eax, 1
sbb edx, 0
and eax, not 0xFFF
and eax, ebx
jnz .abort
and edx, ebp
jnz .abort
; 4f. For every active MTRR, validate memory type: it must be either WB or UC.
add edi, 16
cmp bl, MEM_UC
jz .get_used_mtrrs_next
cmp bl, MEM_WB
jnz .abort
.get_used_mtrrs_next:
; 4g. Repeat the loop at 4b-4f for all [num_variable_mtrrs] entries.
mov eax, [num_variable_mtrrs]
lea eax, [0x200+eax*2]
cmp ecx, eax
jb .get_used_mtrrs_loop
; 4h. If no active MTRRs were detected, fallback to step 7.
cmp [.num_used_mtrrs], 0
jz .fill_ranges_from_memory_map
mov [.mtrrs_end], edi
; 5. Generate sorted list of ranges marked as WB.
; 5a. Prepare for the loop over configured MTRRs filled at step 4.
lea ecx, [.mtrrs]
.fill_wb_ranges:
; 5b. Ignore non-WB MTRRs.
mov ebx, [ecx]
cmp bl, MEM_WB
jnz .next_wb_range
mov ebp, [ecx+4]
and ebx, not 0xFFF ; clear memory type and reserved bits
; ebp:ebx = start of the range described by the current MTRR.
; 5c. Find the first existing range containing a point greater than ebp:ebx.
lea esi, [.first_range]
.find_range_wb:
; If there is no next range or start of the next range is greater than ebp:ebx,
; exit the loop to 5d.
mov edi, [esi]
test edi, edi
jz .found_place_wb
mov eax, ebx
mov edx, ebp
sub eax, dword [edi+mtrr_range.start]
sbb edx, dword [edi+mtrr_range.start+4]
jb .found_place_wb
; Otherwise, if end of the next range is greater than or equal to ebp:ebx,
; exit the loop to 5e.
mov esi, edi
sub eax, dword [edi+mtrr_range.length]
sbb edx, dword [edi+mtrr_range.length+4]
jb .expand_wb
or eax, edx
jnz .find_range_wb
jmp .expand_wb
.found_place_wb:
; 5d. ebp:ebx is not within any existing range.
; Insert a new range between esi and edi.
; (Later, during 5e, it can be merged with the following ranges.)
mov eax, [.first_free_range]
test eax, eax
jz .abort
mov [esi], eax
mov edx, [eax+mtrr_range.next]
mov [.first_free_range], edx
mov dword [eax+mtrr_range.start], ebx
mov dword [eax+mtrr_range.start+4], ebp
; Don't fill [eax+mtrr_range.next] and [eax+mtrr_range.length] yet,
; they will be calculated including merges at step 5e.
mov esi, edi
mov edi, eax
.expand_wb:
; 5e. The range at edi contains ebp:ebx, and esi points to the first range
; to be checked for merge: esi=edi if ebp:ebx was found in an existing range,
; esi is next after edi if a new range with ebp:ebx was created.
; Merge it with following ranges while start of the next range is not greater
; than the end of the new range.
add ebx, [ecx+8]
adc ebp, [ecx+12]
; ebp:ebx = end of the range described by the current MTRR.
.expand_wb_loop:
; If there is no next range or start of the next range is greater than ebp:ebx,
; exit the loop to 5g.
test esi, esi
jz .expand_wb_done
mov eax, ebx
mov edx, ebp
sub eax, dword [esi+mtrr_range.start]
sbb edx, dword [esi+mtrr_range.start+4]
jb .expand_wb_done
; Otherwise, if end of the next range is greater than or equal to ebp:ebx,
; exit the loop to 5f.
sub eax, dword [esi+mtrr_range.length]
sbb edx, dword [esi+mtrr_range.length+4]
jb .expand_wb_last
; Otherwise, the current range is completely within the new range.
; Free it and continue the loop.
mov edx, [esi+mtrr_range.next]
cmp esi, edi
jz @f
mov eax, [.first_free_range]
mov [esi+mtrr_range.next], eax
mov [.first_free_range], esi
@@:
mov esi, edx
jmp .expand_wb_loop
.expand_wb_last:
; 5f. Start of the new range is inside range described by esi,
; end of the new range is inside range described by edi.
; If esi is equal to edi, the new range is completely within
; an existing range, so proceed to the next range.
cmp esi, edi
jz .next_wb_range
; Otherwise, set end of interval at esi to end of interval at edi
; and free range described by edi.
mov ebx, dword [esi+mtrr_range.start]
mov ebp, dword [esi+mtrr_range.start+4]
add ebx, dword [esi+mtrr_range.length]
adc ebp, dword [esi+mtrr_range.length+4]
mov edx, [esi+mtrr_range.next]
mov eax, [.first_free_range]
mov [esi+mtrr_range.next], eax
mov [.first_free_range], esi
mov esi, edx
.expand_wb_done:
; 5g. We have found the next range (maybe 0) after merging and
; the new end of range (maybe ebp:ebx from the new range
; or end of another existing interval calculated at step 5f).
; Write them to range at edi.
mov [edi+mtrr_range.next], esi
sub ebx, dword [edi+mtrr_range.start]
sbb ebp, dword [edi+mtrr_range.start+4]
mov dword [edi+mtrr_range.length], ebx
mov dword [edi+mtrr_range.length+4], ebp
.next_wb_range:
; 5h. Continue the loop 5b-5g over all configured MTRRs.
add ecx, 16
cmp ecx, [.mtrrs_end]
jb .fill_wb_ranges
; 6. Exclude all ranges marked as UC.
; 6a. Prepare for the loop over configured MTRRs filled at step 4.
lea ecx, [.mtrrs]
.fill_uc_ranges:
; 6b. Ignore non-UC MTRRs.
mov ebx, [ecx]
cmp bl, MEM_UC
jnz .next_uc_range
mov ebp, [ecx+4]
and ebx, not 0xFFF ; clear memory type and reserved bits
; ebp:ebx = start of the range described by the current MTRR.
lea esi, [.first_range]
; 6c. Find the first existing range containing a point greater than ebp:ebx.
.find_range_uc:
; If there is no next range, ignore this MTRR,
; exit the loop and continue to next MTRR.
mov edi, [esi]
test edi, edi
jz .next_uc_range
; If start of the next range is greater than or equal to ebp:ebx,
; exit the loop to 6e.
mov eax, dword [edi+mtrr_range.start]
mov edx, dword [edi+mtrr_range.start+4]
sub eax, ebx
sbb edx, ebp
jnb .truncate_uc
; Otherwise, continue the loop if end of the next range is less than ebp:ebx,
; exit the loop to 6d otherwise.
mov esi, edi
add eax, dword [edi+mtrr_range.length]
adc edx, dword [edi+mtrr_range.length+4]
jnb .find_range_uc
; 6d. ebp:ebx is inside (or at end of) an existing range.
; Split the range. (The second range, maybe containing completely within UC-range,
; maybe of zero length, can be removed at step 6e, if needed.)
mov edi, [.first_free_range]
test edi, edi
jz .abort
mov dword [edi+mtrr_range.start], ebx
mov dword [edi+mtrr_range.start+4], ebp
mov dword [edi+mtrr_range.length], eax
mov dword [edi+mtrr_range.length+4], edx
mov eax, [edi+mtrr_range.next]
mov [.first_free_range], eax
mov eax, [esi+mtrr_range.next]
mov [edi+mtrr_range.next], eax
; don't change [esi+mtrr_range.next] yet, it will be filled at step 6e
mov eax, ebx
mov edx, ebp
sub eax, dword [esi+mtrr_range.start]
sbb edx, dword [esi+mtrr_range.start+4]
mov dword [esi+mtrr_range.length], eax
mov dword [esi+mtrr_range.length+4], edx
.truncate_uc:
; 6e. edi is the first range after ebp:ebx, check it and next ranges
; for intersection with the new range, truncate heads.
add ebx, [ecx+8]
adc ebp, [ecx+12]
; ebp:ebx = end of the range described by the current MTRR.
.truncate_uc_loop:
; If start of the next range is greater than ebp:ebx,
; exit the loop to 6g.
mov eax, ebx
mov edx, ebp
sub eax, dword [edi+mtrr_range.start]
sbb edx, dword [edi+mtrr_range.start+4]
jb .truncate_uc_done
; Otherwise, if end of the next range is greater than ebp:ebx,
; exit the loop to 6f.
sub eax, dword [edi+mtrr_range.length]
sbb edx, dword [edi+mtrr_range.length+4]
jb .truncate_uc_last
; Otherwise, the current range is completely within the new range.
; Free it and continue the loop if there is a next range.
; If that was a last range, exit the loop to 6g.
mov edx, [edi+mtrr_range.next]
mov eax, [.first_free_range]
mov [.first_free_range], edi
mov [edi+mtrr_range.next], eax
mov edi, edx
test edi, edi
jnz .truncate_uc_loop
jmp .truncate_uc_done
.truncate_uc_last:
; 6f. The range at edi partially intersects with the UC-range described by MTRR.
; Truncate it from the head.
mov dword [edi+mtrr_range.start], ebx
mov dword [edi+mtrr_range.start+4], ebp
neg eax
adc edx, 0
neg edx
mov dword [edi+mtrr_range.length], eax
mov dword [edi+mtrr_range.length+4], edx
.truncate_uc_done:
; 6g. We have found the next range (maybe 0) after intersection.
; Write it to [esi+mtrr_range.next].
mov [esi+mtrr_range.next], edi
.next_uc_range:
; 6h. Continue the loop 6b-6g over all configured MTRRs.
add ecx, 16
cmp ecx, [.mtrrs_end]
jb .fill_uc_ranges
; Sanity check: if there are no ranges after steps 5-6,
; fallback to step 7. Otherwise, go to 8.
cmp [.first_range], 0
jnz .ranges_ok
.fill_ranges_from_memory_map:
; 7. BIOS has not configured variable-range MTRRs.
; Create one range from 0 to [MEM_AMOUNT].
mov eax, [.first_free_range]
mov edx, [eax+mtrr_range.next]
mov [.first_free_range], edx
mov [.first_range], eax
xor edx, edx
mov [eax+mtrr_range.next], edx
mov dword [eax+mtrr_range.start], edx
mov dword [eax+mtrr_range.start+4], edx
mov ecx, [MEM_AMOUNT]
mov dword [eax+mtrr_range.length], ecx
mov dword [eax+mtrr_range.length+4], edx
.ranges_ok:
; 8. We have calculated list of WB-ranges.
; Now we should calculate a list of MTRRs so that
; * every MTRR describes a range with length = power of 2 and start that is aligned,
; * every MTRR can be WB or UC
; * (sum of all WB ranges) minus (sum of all UC ranges) equals the calculated list
; * top of 4G memory must not be covered by any ranges
; Example: range [0,0xBC000000) can be converted to
; [0,0x80000000)+[0x80000000,0xC0000000)-[0xBC000000,0xC0000000)
; WB +WB -UC
; but not to [0,0x100000000)-[0xC0000000,0x100000000)-[0xBC000000,0xC0000000).
; 8a. Check that list of ranges is [0,something) plus, optionally, [4G,something).
; This holds in practice (see mtrrtest.asm for real-life examples)
; and significantly simplifies the code: ranges are independent, start of range
; is almost always aligned (the only exception >4G upper memory can be easily covered),
; there is no need to consider adding holes before start of range, only
; append them to end of range.
xor eax, eax
mov edi, [.first_range]
cmp dword [edi+mtrr_range.start], eax
jnz .abort
cmp dword [edi+mtrr_range.start+4], eax
jnz .abort
cmp dword [edi+mtrr_range.length+4], eax
jnz .abort
mov edx, [edi+mtrr_range.next]
test edx, edx
jz @f
cmp dword [edx+mtrr_range.start], eax
jnz .abort
cmp dword [edx+mtrr_range.start+4], 1
jnz .abort
cmp [edx+mtrr_range.next], eax
jnz .abort
@@:
; 8b. Initialize: no MTRRs filled.
mov [.num_used_mtrrs], eax
lea esi, [.mtrrs]
.range2mtrr_loop:
; 8c. If we are dealing with upper-memory range (after 4G)
; with length > start, create one WB MTRR with [start,2*start),
; reset start to 2*start and return to this step.
; Example: [4G,24G) -> [4G,8G) {returning} + [8G,16G) {returning}
; + [16G,24G) {advancing to ?}.
mov eax, dword [edi+mtrr_range.length+4]
test eax, eax
jz .less4G
mov edx, dword [edi+mtrr_range.start+4]
cmp eax, edx
jb .start_aligned
inc [.num_used_mtrrs]
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
ja .abort
mov dword [esi], MEM_WB
mov dword [esi+4], edx
mov dword [esi+8], 0
mov dword [esi+12], edx
add esi, 16
add dword [edi+mtrr_range.start+4], edx
sub dword [edi+mtrr_range.length+4], edx
jnz .range2mtrr_loop
cmp dword [edi+mtrr_range.length], 0
jz .range2mtrr_next
.less4G:
; 8d. If we are dealing with low-memory range (before 4G)
; and appending a maximal-size hole would create a range covering top of 4G,
; create a maximal-size WB range and return to this step.
; Example: for [0,0xBC000000) the following steps would consider
; variants [0,0x80000000)+(another range to be splitted) and
; [0,0x100000000)-(another range to be splitted); we forbid the last variant,
; so the first variant must be used.
bsr ecx, dword [edi+mtrr_range.length]
xor edx, edx
inc edx
shl edx, cl
lea eax, [edx*2]
add eax, dword [edi+mtrr_range.start]
jnz .start_aligned
inc [.num_used_mtrrs]
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
ja .abort
mov eax, dword [edi+mtrr_range.start]
mov dword [esi], eax
or dword [esi], MEM_WB
mov dword [esi+4], 0
mov dword [esi+8], edx
mov dword [esi+12], 0
add esi, 16
add dword [edi+mtrr_range.start], edx
sub dword [edi+mtrr_range.length], edx
jnz .less4G
jmp .range2mtrr_next
.start_aligned:
; Start is aligned for any allowed length, maximum-size hole is allowed.
; Select the best MTRR configuration for one range.
; length=...101101
; Without hole at the end, we need one WB MTRR for every 1-bit in length:
; length=...100000 + ...001000 + ...000100 + ...000001
; We can also append one hole at the end so that one 0-bit (selected by us)
; becomes 1 and all lower bits become 0 for WB-range:
; length=...110000 - (...00010 + ...00001)
; In this way, we need one WB MTRR for every 1-bit higher than the selected bit,
; one WB MTRR for the selected bit, one UC MTRR for every 0-bit between
; the selected bit and lowest 1-bit (they become 1-bits after negation)
; and one UC MTRR for lowest 1-bit.
; So we need to select 0-bit with the maximal difference
; (number of 0-bits) - (number of 1-bits) between selected and lowest 1-bit,
; this equals the gain from using a hole. If the difference is negative for
; all 0-bits, don't append hole.
; Note that lowest 1-bit is not included when counting, but selected 0-bit is.
; 8e. Find the optimal bit position for hole.
; eax = current difference, ebx = best difference,
; ecx = hole bit position, edx = current bit position.
xor eax, eax
xor ebx, ebx
xor ecx, ecx
bsf edx, dword [edi+mtrr_range.length]
jnz @f
bsf edx, dword [edi+mtrr_range.length+4]
add edx, 32
@@:
push edx ; save position of lowest 1-bit for step 8f
.calc_stat:
inc edx
cmp edx, 64
jae .stat_done
inc eax ; increment difference in hope for 1-bit
; Note: bt conveniently works with both .length and .length+4,
; depending on whether edx>=32.
bt dword [edi+mtrr_range.length], edx
jc .calc_stat
dec eax ; hope was wrong, decrement difference to correct 'inc'
dec eax ; and again, now getting the real difference
cmp eax, ebx
jle .calc_stat
mov ebx, eax
mov ecx, edx
jmp .calc_stat
.stat_done:
; 8f. If we decided to create a hole, flip all bits between lowest and selected.
pop edx ; restore position of lowest 1-bit saved at step 8e
test ecx, ecx
jz .fill_hi_init
@@:
inc edx
cmp edx, ecx
ja .fill_hi_init
btc dword [edi+mtrr_range.length], edx
jmp @b
.fill_hi_init:
; 8g. Create MTRR ranges corresponding to upper 32 bits.
sub ecx, 32
.fill_hi_loop:
bsr edx, dword [edi+mtrr_range.length+4]
jz .fill_hi_done
inc [.num_used_mtrrs]
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
ja .abort
mov eax, dword [edi+mtrr_range.start]
mov [esi], eax
mov eax, dword [edi+mtrr_range.start+4]
mov [esi+4], eax
xor eax, eax
mov [esi+8], eax
bts eax, edx
mov [esi+12], eax
cmp edx, ecx
jl .fill_hi_uc
or dword [esi], MEM_WB
add dword [edi+mtrr_range.start+4], eax
jmp @f
.fill_hi_uc:
sub dword [esi+4], eax
sub dword [edi+mtrr_range.start+4], eax
@@:
add esi, 16
sub dword [edi+mtrr_range.length], eax
jmp .fill_hi_loop
.fill_hi_done:
; 8h. Create MTRR ranges corresponding to lower 32 bits.
add ecx, 32
.fill_lo_loop:
bsr edx, dword [edi+mtrr_range.length]
jz .range2mtrr_next
inc [.num_used_mtrrs]
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
ja .abort
mov eax, dword [edi+mtrr_range.start]
mov [esi], eax
mov eax, dword [edi+mtrr_range.start+4]
mov [esi+4], eax
xor eax, eax
mov [esi+12], eax
bts eax, edx
mov [esi+8], eax
cmp edx, ecx
jl .fill_lo_uc
or dword [esi], MEM_WB
add dword [edi+mtrr_range.start], eax
jmp @f
.fill_lo_uc:
sub dword [esi], eax
sub dword [edi+mtrr_range.start], eax
@@:
add esi, 16
sub dword [edi+mtrr_range.length], eax
jmp .fill_lo_loop
.range2mtrr_next:
; 8i. Repeat the loop at 8c-8h for all ranges.
mov edi, [edi+mtrr_range.next]
test edi, edi
jnz .range2mtrr_loop
; 9. We have calculated needed MTRRs, now setup them in the CPU.
; 9a. Abort if number of MTRRs is too large.
mov eax, [num_variable_mtrrs]
cmp [.num_used_mtrrs], eax
ja .abort
 
; 9b. Prepare for changes.
call mtrr_begin_change
 
; 9c. Prepare for loop over MTRRs.
lea esi, [.mtrrs]
mov ecx, 0x200
@@:
; 9d. For every MTRR, copy PHYSBASEn as is: step 8 has configured
; start value and type bits as needed.
mov eax, [esi]
mov edx, [esi+4]
wrmsr
inc ecx
; 9e. For every MTRR, calculate PHYSMASKn = -(length) or 0x800
; with upper bits cleared, 0x800 = MTRR is valid.
xor eax, eax
xor edx, edx
sub eax, [esi+8]
sbb edx, [esi+12]
or eax, 0x800
or edx, [.phys_reserved_mask]
xor edx, [.phys_reserved_mask]
wrmsr
inc ecx
; 9f. Continue steps 9d and 9e for all MTRRs calculated at step 8.
add esi, 16
dec [.num_used_mtrrs]
jnz @b
; 9g. Zero other MTRRs.
xor eax, eax
xor edx, edx
mov ebx, [num_variable_mtrrs]
lea ebx, [0x200+ebx*2]
@@:
cmp ecx, ebx
jae @f
wrmsr
inc ecx
wrmsr
inc ecx
jmp @b
@@:
 
; 9i. Configure MTRR_DEF_TYPE.
mov ecx, 0x2FF
rdmsr
or ah, 8 ; enable variable-ranges MTRR
and al, 0xF0; default memtype = UC
wrmsr
 
; 9j. Changes are done.
call mtrr_end_change
 
.abort:
add esp, .local_vars_size + MAX_RANGES * sizeof.mtrr_range
pop ebp
ret
endp
 
; Allocate&set one MTRR for given range.
; size must be power of 2 that divides base.
proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword
; find unused register
mov ecx, 0x201
.scan:
rdmsr
dec ecx
test ah, 8
jz .found
rdmsr
test edx, edx
jnz @f
and eax, not 0xFFF ; clear reserved bits
cmp eax, [base]
jz .ret
@@:
add ecx, 3
mov eax, [num_variable_mtrrs]
lea eax, [0x200+eax*2]
cmp ecx, eax
jb .scan
; no free registers, ignore the call
.ret:
ret
.found:
; found, write values
call mtrr_begin_change
xor edx, edx
mov eax, [base]
or eax, [mem_type]
wrmsr
 
mov al, [cpu_phys_addr_width]
xor edx, edx
bts edx, eax
xor eax, eax
sub eax, [size]
sbb edx, 0
or eax, 0x800
inc ecx
wrmsr
call mtrr_end_change
ret
endp
 
; Helper procedure for mtrr_validate.
; Calculates memory type for given address according to variable-range MTRRs.
; Assumes that MTRRs are enabled.
; in: ebx = 32-bit physical address
; out: eax = memory type for ebx
proc mtrr_get_real_type
; 1. Initialize: we have not yet found any MTRRs covering ebx.
push 0
mov ecx, 0x201
.mtrr_loop:
; 2. For every MTRR, check whether it is valid; if not, continue to the next MTRR.
rdmsr
dec ecx
test ah, 8
jz .next
; 3. For every valid MTRR, check whether (ebx and PHYSMASKn) == PHYSBASEn,
; excluding low 12 bits.
and eax, ebx
push eax
rdmsr
test edx, edx
pop edx
jnz .next
xor edx, eax
and edx, not 0xFFF
jnz .next
; 4. If so, set the bit corresponding to memory type defined by this MTRR.
and eax, 7
bts [esp], eax
.next:
; 5. Continue loop at 2-4 for all variable-range MTRRs.
add ecx, 3
mov eax, [num_variable_mtrrs]
lea eax, [0x200+eax*2]
cmp ecx, eax
jb .mtrr_loop
; 6. If no MTRRs cover address in ebx, use default MTRR type from MTRR_DEF_CAP.
pop edx
test edx, edx
jz .default
; 7. Find&clear 1-bit in edx.
bsf eax, edx
btr edx, eax
; 8. If there was only one 1-bit, then all MTRRs are consistent, return that bit.
test edx, edx
jz .nothing
; Otherwise, return MEM_UC (e.g. WB+UC is UC).
xor eax, eax
.nothing:
ret
.default:
mov ecx, 0x2FF
rdmsr
movzx eax, al
ret
endp
 
; If MTRRs are configured improperly, this is not obvious to the user;
; everything works, but the performance can be horrible.
; Try to detect this and let the user know that the low performance
; is caused by some problem and is not a global property of the system.
; Let's hope he would report it to developers...
proc mtrr_validate
; 1. If MTRRs are not supported, they cannot be configured improperly.
; Note: VirtualBox claims MTRR support in cpuid, but emulates MTRRCAP=0,
; which is efficiently equivalent to absent MTRRs.
; So check [num_variable_mtrrs] instead of CAPS_MTRR in [cpu_caps].
cmp [num_variable_mtrrs], 0
jz .exit
; 2. If variable-range MTRRs are not configured, this is a problem.
mov ecx, 0x2FF
rdmsr
test ah, 8
jz .fail
; 3. Get the memory type for address somewhere inside working memory.
; It must be write-back.
mov ebx, 0x27FFFF
call mtrr_get_real_type
cmp al, MEM_WB
jnz .fail
; 4. If we're using a mode with LFB,
; get the memory type for last pixel of the framebuffer.
; It must be write-combined.
test word [SCR_MODE], 0x4000
jz .exit
mov eax, [_display.pitch]
mul [_display.height]
dec eax
; LFB is mapped to virtual address LFB_BASE,
; it uses global pages if supported by CPU.
mov ebx, [sys_proc+PROC.pdt_0+(LFB_BASE shr 20)]
test ebx, PG_LARGE
jnz @f
mov ebx, [page_tabs+(LFB_BASE shr 10)]
@@:
and ebx, not 0xFFF
add ebx, eax
call mtrr_get_real_type
cmp al, MEM_WC
jz .exit
; 5. The check at step 4 fails on Bochs:
; Bochs BIOS configures MTRRs in a strange way not respecting [cpu_phys_addr_width],
; so mtrr_reconfigure avoids to touch anything.
; However, Bochs core ignores MTRRs (keeping them only for rdmsr/wrmsr),
; so we don't care about proper setting for Bochs.
; Use northbridge PCI id to detect Bochs: it emulates either i440fx or i430fx
; depending on configuration file.
mov eax, [pcidev_list.fd]
cmp eax, pcidev_list ; sanity check: fail if no PCI devices
jz .fail
cmp [eax+PCIDEV.vendor_device_id], 0x12378086
jz .exit
cmp [eax+PCIDEV.vendor_device_id], 0x01228086
jnz .fail
.exit:
ret
.fail:
mov ebx, mtrr_user_message
mov ebp, notifyapp
call fs_execute_from_sysdir_param
ret
endp
/kernel/branches/Kolibri-acpi/core/peload.inc
24,15 → 24,30
 
mov [image], eax
 
mov edx, [eax+STRIPPED_PE_HEADER.SizeOfImage]
; mov cl, [eax+STRIPPED_PE_HEADER.Subsystem]
cmp word [eax], STRIPPED_PE_SIGNATURE
jz @f
 
mov edx, [eax+60]
; mov cl, [eax+5Ch+edx]
mov edx, [eax+80+edx]
 
stdcall kernel_alloc, [eax+80+edx]
@@:
mov [entry], 0
; cmp cl, 1
; jnz .cleanup
stdcall kernel_alloc, edx
test eax, eax
jz .cleanup
 
mov [base], eax
 
stdcall map_PE, eax, [image]
push ebx ebp
mov ebx, [image]
mov ebp, eax
call map_PE
pop ebp ebx
 
mov [entry], eax
test eax, eax
48,199 → 63,200
ret
endp
 
DWORD equ dword
PTR equ
 
align 4
map_PE: ;stdcall base:dword, image:dword
cld
push ebp
map_PE: ;ebp=base:dword, ebx=image:dword
push edi
push esi
push ebx
sub esp, 60
mov ebx, DWORD PTR [esp+84]
mov ebp, DWORD PTR [esp+80]
sub esp, .locals_size
virtual at esp
.numsections dd ?
.import_names dd ?
.import_targets dd ?
.peheader dd ?
.bad_import dd ?
.import_idx dd ?
.import_descr dd ?
.relocs_rva dd ?
.relocs_size dd ?
.section_header_size dd ?
.AddressOfEntryPoint dd ?
.ImageBase dd ?
.locals_size = $ - esp
end virtual
cmp word [ebx], STRIPPED_PE_SIGNATURE
jz .stripped
 
mov edx, ebx
add edx, [ebx+60]
movzx eax, word [edx+6]
mov [.numsections], eax
mov eax, [edx+40]
mov [.AddressOfEntryPoint], eax
mov eax, [edx+52]
mov [.ImageBase], eax
mov ecx, [edx+84]
mov [.section_header_size], 40
mov eax, [edx+128]
mov [.import_descr], eax
mov eax, [edx+160]
mov [.relocs_rva], eax
mov eax, [edx+164]
mov [.relocs_size], eax
add edx, 256
 
jmp .common
.stripped:
mov eax, [ebx+STRIPPED_PE_HEADER.AddressOfEntryPoint]
mov [.AddressOfEntryPoint], eax
mov eax, [ebx+STRIPPED_PE_HEADER.ImageBase]
mov [.ImageBase], eax
movzx eax, [ebx+STRIPPED_PE_HEADER.NumberOfSections]
mov [.numsections], eax
movzx ecx, [ebx+STRIPPED_PE_HEADER.NumberOfRvaAndSizes]
xor eax, eax
mov [.relocs_rva], eax
mov [.relocs_size], eax
test ecx, ecx
jz @f
mov eax, [ebx+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_IMPORT*8]
@@:
mov [.import_descr], eax
cmp ecx, SPE_DIRECTORY_BASERELOC
jbe @f
mov eax, [ebx+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_BASERELOC*8]
mov [.relocs_rva], eax
mov eax, [ebx+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_BASERELOC*8+4]
mov [.relocs_size], eax
@@:
mov [.section_header_size], 28
lea edx, [ebx+ecx*8+sizeof.STRIPPED_PE_HEADER+8]
mov ecx, [ebx+STRIPPED_PE_HEADER.SizeOfHeaders]
 
.common:
mov esi, ebx
add edx, DWORD PTR [ebx+60]
mov edi, ebp
mov DWORD PTR [esp+32], edx
mov ecx, DWORD PTR [edx+84]
 
shr ecx, 2
rep movsd
 
movzx eax, WORD PTR [edx+6]
mov DWORD PTR [esp+36], 0
mov DWORD PTR [esp+16], eax
jmp L2
L3:
mov eax, DWORD PTR [edx+264]
cmp [.numsections], 0
jz .nosections
.copy_sections:
mov eax, [edx+8]
test eax, eax
je L4
je .no_section_data
mov esi, ebx
mov edi, ebp
add esi, DWORD PTR [edx+268]
add esi, [edx+12]
mov ecx, eax
add edi, DWORD PTR [edx+260]
add edi, [edx+4]
 
add ecx, 3
shr ecx, 2
rep movsd
 
L4:
mov ecx, DWORD PTR [edx+256]
.no_section_data:
mov ecx, [edx]
cmp ecx, eax
jbe L6
jbe .no_section_fill
sub ecx, eax
add eax, DWORD PTR [edx+260]
add eax, [edx+4]
lea edi, [eax+ebp]
 
xor eax, eax
rep stosb
 
L6:
inc DWORD PTR [esp+36]
add edx, 40
L2:
mov esi, DWORD PTR [esp+16]
cmp DWORD PTR [esp+36], esi
jne L3
mov edi, DWORD PTR [esp+32]
cmp DWORD PTR [edi+164], 0
je L9
pushd [edi+164]
.no_section_fill:
add edx, [.section_header_size]
dec [.numsections]
jnz .copy_sections
.nosections:
cmp [.relocs_size], 0
je .no_relocations
mov esi, ebp
mov ecx, ebp
sub esi, DWORD PTR [edi+52]
add ecx, DWORD PTR [edi+160]
mov eax, esi
shr eax, 16
mov DWORD PTR [esp+16], eax
L12:
mov eax, [ecx+4]
sub [esp], eax
lea ebx, [eax-8]
xor edi, edi
sub esi, [.ImageBase]
add ecx, [.relocs_rva]
.relocs_block:
mov edi, [ecx]
add edi, ebp
mov ebx, [ecx+4]
add ecx, 8
sub [.relocs_size], ebx
sub ebx, 8
shr ebx, 1
jmp L13
L14:
movzx eax, WORD PTR [ecx+8+edi*2]
jz .relocs_next_block
.one_reloc:
movzx eax, word [ecx]
add ecx, 2
mov edx, eax
shr eax, 12
and edx, 4095
add edx, DWORD PTR [ecx]
cmp ax, 2
je L17
cmp ax, 3
je L18
dec ax
jne L15
mov eax, DWORD PTR [esp+16]
add WORD PTR [edx+ebp], ax
L17:
add WORD PTR [edx+ebp], si
L18:
add DWORD PTR [edx+ebp], esi
L15:
inc edi
L13:
cmp edi, ebx
jne L14
add ecx, DWORD PTR [ecx+4]
L11:
cmp dword [esp], 0
jg L12
pop eax
L9:
mov edx, DWORD PTR [esp+32]
cmp DWORD PTR [edx+132], 0
je L20
mov eax, ebp
add eax, DWORD PTR [edx+128]
mov DWORD PTR [esp+40], 0
add eax, 20
mov DWORD PTR [esp+56], eax
L22:
mov ecx, DWORD PTR [esp+56]
cmp DWORD PTR [ecx-16], 0
jne L23
cmp DWORD PTR [ecx-8], 0
je L25
L23:
mov edi, DWORD PTR [__exports+32]
mov esi, DWORD PTR [__exports+28]
mov eax, DWORD PTR [esp+56]
mov DWORD PTR [esp+20], edi
add edi, OS_BASE
add esi, OS_BASE
mov DWORD PTR [esp+44], esi
mov ecx, DWORD PTR [eax-4]
mov DWORD PTR [esp+48], edi
mov edx, DWORD PTR [eax-20]
cmp eax, 3
jne @f
add [edx+edi], esi
@@:
dec ebx
jnz .one_reloc
.relocs_next_block:
cmp [.relocs_size], 0
jg .relocs_block
.no_relocations:
cmp [.import_descr], 0
je .no_imports
add [.import_descr], ebp
mov [.bad_import], 0
.import_block:
mov ecx, [.import_descr]
cmp dword [ecx+4], 0
jne @f
cmp dword [ecx+12], 0
je .done_imports
@@:
mov edx, dword [ecx]
mov ecx, dword [ecx+16]
test edx, edx
jnz @f
mov edx, ecx
@@:
mov DWORD PTR [esp+52], 0
mov [.import_idx], 0
add ecx, ebp
add edx, ebp
mov DWORD PTR [esp+24], edx
mov DWORD PTR [esp+28], ecx
L26:
mov esi, DWORD PTR [esp+52]
mov edi, DWORD PTR [esp+24]
mov eax, DWORD PTR [edi+esi*4]
mov [.import_names], edx
mov [.import_targets], ecx
.import_func:
mov esi, [.import_idx]
mov edi, [.import_names]
mov eax, [edi+esi*4]
test eax, eax
je L27
test eax, eax
js L27
je .next_import_block
js .next_import_block
lea edi, [ebp+eax]
mov eax, DWORD PTR [esp+28]
mov DWORD PTR [eax+esi*4], 0
mov eax, [.import_targets]
mov dword [eax+esi*4], 0
lea esi, [edi+2]
push eax
movzx ebx, word [edi]
push 32
movzx eax, WORD PTR [edi]
mov edx, DWORD PTR [esp+56]
mov eax, DWORD PTR [edx+eax*4]
mov ecx, [__exports+32]
mov eax, [ecx+OS_BASE+ebx*4]
add eax, OS_BASE
push eax
push esi
call strncmp
pop ebx
test eax, eax
jz .import_func_found
xor ebx, ebx
test eax, eax
jne L32
jmp L30
L33:
push ecx
.import_func_candidate:
push 32
mov ecx, DWORD PTR [esp+28]
mov eax, DWORD PTR [ecx+OS_BASE+ebx*4]
mov ecx, [__exports+32]
mov eax, [ecx+OS_BASE+ebx*4]
add eax, OS_BASE
push eax
push esi
call strncmp
pop edx
test eax, eax
jne L34
mov esi, DWORD PTR [esp+44]
mov edx, DWORD PTR [esp+52]
mov ecx, DWORD PTR [esp+28]
mov eax, DWORD PTR [esi+ebx*4]
add eax, OS_BASE
mov DWORD PTR [ecx+edx*4], eax
jmp L36
L34:
je .import_func_found
inc ebx
L32:
cmp ebx, DWORD PTR [__exports+24]
jb L33
L36:
cmp ebx, DWORD PTR [__exports+24]
jne L37
cmp ebx, [__exports+24]
jb .import_func_candidate
 
mov esi, msg_unresolved
call sys_msg_board_str
249,34 → 265,30
mov esi, msg_CR
call sys_msg_board_str
 
mov DWORD PTR [esp+40], 1
jmp L37
L30:
movzx eax, WORD PTR [edi]
mov esi, DWORD PTR [esp+44]
mov edi, DWORD PTR [esp+52]
mov edx, DWORD PTR [esp+28]
mov eax, DWORD PTR [esi+eax*4]
mov [.bad_import], 1
jmp .next_import_func
.import_func_found:
mov esi, [__exports+28]
mov edx, [.import_idx]
mov ecx, [.import_targets]
mov eax, [esi+OS_BASE+ebx*4]
add eax, OS_BASE
mov DWORD PTR [edx+edi*4], eax
L37:
inc DWORD PTR [esp+52]
jmp L26
L27:
add DWORD PTR [esp+56], 20
jmp L22
L25:
mov [ecx+edx*4], eax
.next_import_func:
inc [.import_idx]
jmp .import_func
.next_import_block:
add [.import_descr], 20
jmp .import_block
.done_imports:
xor eax, eax
cmp DWORD PTR [esp+40], 0
jne L40
L20:
mov ecx, DWORD PTR [esp+32]
cmp [.bad_import], 0
jne @f
.no_imports:
mov eax, ebp
add eax, DWORD PTR [ecx+40]
L40:
add esp, 60
pop ebx
add eax, [.AddressOfEntryPoint]
@@:
add esp, .locals_size
pop esi
pop edi
pop ebp
ret 8
ret
/kernel/branches/Kolibri-acpi/core/sched.inc
29,8 → 29,7
.nocounter:
xor ecx, ecx ; send End Of Interrupt signal
call irq_eoi
; btr dword[DONT_SWITCH], 0
; jc .return
 
mov bl, SCHEDULE_ANY_PRIORITY
call find_next_task
jz .return ; if there is only one running process
44,26 → 43,10
pushfd
cli
pushad
if 0
; \begin{Mario79} ; <- must be refractoried, if used...
cmp [dma_task_switched], 1
jne .find_next_task
mov [dma_task_switched], 0
mov ebx, [dma_process]
cmp [CURRENT_TASK], ebx
je .return
mov edi, [dma_slot_ptr]
mov [CURRENT_TASK], ebx
mov [TASK_BASE], edi
jmp @f
.find_next_task:
; \end{Mario79}
end if
mov bl, SCHEDULE_ANY_PRIORITY
call find_next_task
jz .return ; the same task -> skip switch
@@:
; mov byte[DONT_SWITCH], 1
 
call do_change_task
.return:
popad
121,10 → 104,11
Mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map]
Mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4]
; set new thread memory-map
mov ecx, APPDATA.dir_table
mov eax, [ebx+ecx] ;offset>0x7F
cmp eax, [esi+ecx] ;offset>0x7F
mov eax, [ebx+APPDATA.process]
cmp eax, [current_process]
je @f
mov [current_process], eax
mov eax, [eax+PROC.pdt_0_phys]
mov cr3, eax
@@:
; set tss.esp0
159,7 → 143,7
jz @f
xor eax, eax
mov dr6, eax
lea esi, [ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table];offset>0x7F
lea esi, [ebx+APPDATA.dbg_regs]
cld
macro lodsReg [reg] {
lodsd
/kernel/branches/Kolibri-acpi/core/sys32-sp.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
; Éste archivo debe ser editado con codificación CP866
 
msg_sel_ker cp850 "núcleo", 0
/kernel/branches/Kolibri-acpi/core/sys32.inc
413,23 → 413,26
 
align 4
terminate: ; terminate application
destroy_thread:
 
.slot equ esp ;locals
.slot equ esp+4 ;locals
.process equ esp ;ptr to parent process
 
 
push esi ;save .slot
 
shl esi, 8
cmp [SLOT_BASE+esi+APPDATA.dir_table], 0
jne @F
mov edx, [SLOT_BASE+esi+APPDATA.process]
test edx, edx
jnz @F
pop esi
shl esi, 5
mov [CURRENT_TASK+esi+TASKDATA.state], 9
ret
@@:
push edx ;save .process
lea edx, [SLOT_BASE+esi]
call scheduler_remove_thread
;mov esi,process_terminating
;call sys_msg_board_str
call lock_application_table
 
; if the process is in V86 mode...
442,7 → 445,7
; ...it has page directory for V86 mode
mov esi, [eax+SLOT_BASE+APPDATA.saved_esp0]
mov ecx, [esi+4]
mov [eax+SLOT_BASE+APPDATA.dir_table], ecx
mov [eax+SLOT_BASE+APPDATA.process], ecx
; ...and I/O permission map for V86 mode
mov ecx, [esi+12]
mov [eax+SLOT_BASE+APPDATA.io_map], ecx
449,7 → 452,7
mov ecx, [esi+8]
mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx
.nov86:
 
;destroy per-thread kernel objects
mov esi, [.slot]
shl esi, 8
add esi, SLOT_BASE+APP_OBJ_OFFSET
467,11 → 470,6
pop esi
jmp @B
@@:
 
mov eax, [.slot]
shl eax, 8
stdcall destroy_app_space, [SLOT_BASE+eax+APPDATA.dir_table], [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
 
mov esi, [.slot]
cmp [fpu_owner], esi ; if user fpu last -> fpu user = 2
jne @F
630,6 → 628,9
je @F
call free_page
@@:
lea ebx, [edi+APPDATA.list]
list_del ebx ;destroys edx, ecx
 
mov eax, 0x20202020
stosd
stosd
745,7 → 746,17
add ecx, 0x100
jmp .xd0
.xd1:
; call systest
;release slot
 
bts [thr_slot_map], esi
 
mov ecx, [.process]
lea eax, [ecx+PROC.thr_list]
cmp eax, [eax+LHEAD.next]
jne @F
 
call destroy_process.internal
@@:
sti ; .. and life goes on
 
mov eax, [draw_limits.left]
760,19 → 771,11
call unlock_application_table
;mov esi,process_terminated
;call sys_msg_board_str
add esp, 4
add esp, 8
ret
restore .slot
restore .process
 
;build_scheduler:
; mov esi, boot_sched_1
; call boot_log
; call build_process_gdt_tss_pointer
 
; mov esi,boot_sched_2
; call boot_log
; ret
 
; Three following procedures are used to guarantee that
; some part of kernel code will not be terminated from outside
; while it is running.
/kernel/branches/Kolibri-acpi/core/taskman.inc
70,7 → 70,7
filename rd 256 ;1024/4
flags dd ?
 
save_cr3 dd ?
save_proc dd ?
slot dd ?
slot_base dd ?
file_base dd ?
215,7 → 215,7
 
call lock_application_table
 
call get_new_process_place
call alloc_thread_slot
test eax, eax
mov esi, -0x20 ; too many processes
jz .err
248,19 → 248,24
loop .copy_process_name_loop
.copy_process_name_done:
 
mov ebx, cr3
mov [save_cr3], ebx
mov ebx, [current_process]
mov [save_proc], ebx
 
stdcall create_app_space, [hdr_mem], [file_base], [file_size]
stdcall create_process, [hdr_mem], [file_base], [file_size]
mov esi, -30; no memory
test eax, eax
jz .failed
 
mov ebx, [hdr_mem]
mov [eax+PROC.mem_used], ebx
 
mov ebx, [slot_base]
mov [ebx+APPDATA.dir_table], eax
mov eax, [hdr_mem]
mov [ebx+APPDATA.mem_size], eax
mov [ebx+APPDATA.process], eax
 
lea edx, [ebx+APPDATA.list]
lea ecx, [eax+PROC.thr_list]
list_add_tail edx, ecx
 
xor edx, edx
cmp word [6], '02'
jne @f
292,7 → 297,7
lea ecx, [filename]
stdcall set_app_params , [slot], eax, ebx, ecx, [flags]
 
mov eax, [save_cr3]
mov eax, [save_proc]
call set_cr3
 
mov eax, [process_number];set result
301,7 → 306,7
jmp .final
 
.failed:
mov eax, [save_cr3]
mov eax, [save_proc]
call set_cr3
.err:
.err_hdr:
385,53 → 390,55
ret
 
align 4
proc get_new_process_place
alloc_thread_slot:
;input:
; none
;result:
; eax=[new_process_place]<>0 - ok
; eax=[new_thread_slot]<>0 - ok
; 0 - failed.
;This function find least empty slot.
;It doesn't increase [TASK_COUNT]!
mov eax, CURRENT_TASK
mov ebx, [TASK_COUNT]
inc ebx
shl ebx, 5
add ebx, eax ;ebx - address of process information for (last+1) slot
.newprocessplace:
;eax = address of process information for current slot
cmp eax, ebx
jz .endnewprocessplace ;empty slot after high boundary
add eax, 0x20
cmp word [eax+0xa], 9;check process state, 9 means that process slot is empty
jnz .newprocessplace
.endnewprocessplace:
mov ebx, eax
sub eax, CURRENT_TASK
shr eax, 5 ;calculate slot index
cmp eax, 256
jge .failed ;it should be <256
mov word [ebx+0xa], 9;set process state to 9 (for slot after hight boundary)
ret
.failed:
 
 
mov edx, thr_slot_map
pushfd
cli
.l1:
bsf eax, [edx]
jnz .found
add edx, 4
cmp edx, thr_slot_map+32
jb .l1
 
popfd
xor eax, eax
ret
endp
.found:
btr [edx], eax
sub edx, thr_slot_map
lea eax, [eax+edx*8]
popfd
ret
 
 
align 4
proc create_app_space stdcall, app_size:dword,img_base:dword,img_size:dword
proc create_process stdcall, app_size:dword,img_base:dword,img_size:dword
locals
app_pages dd ?
img_pages dd ?
dir_addr dd ?
process dd ?
app_tabs dd ?
endl
 
push ebx
push esi
push edi
 
mov ecx, pg_data.mutex
call mutex_lock
 
xor eax, eax
mov [dir_addr], eax
mov [process], eax
 
mov eax, [app_size]
add eax, 4095
454,39 → 461,59
shr ecx, 12
mov [img_pages], ecx
 
if GREEDY_KERNEL
lea eax, [ecx+ebx+2];only image size
else
lea eax, [eax+ebx+2];all requested memory
end if
 
cmp eax, [pg_data.pages_free]
ja .fail
 
call alloc_page
stdcall kernel_alloc, 0x2000
test eax, eax
jz .fail
mov [dir_addr], eax
stdcall map_page, [tmp_task_pdir], eax, dword PG_SW
mov [process], eax
 
mov edi, [tmp_task_pdir]
mov ecx, (OS_BASE shr 20)/4
lea edi, [eax+PROC.heap_lock]
mov ecx, (PROC.ht_next-PROC.heap_lock)/4
 
list_init eax
add eax, PROC.thr_list
list_init eax
 
xor eax, eax
cld
rep stosd
 
mov ecx, (PROC.pdt_0 - PROC.htab)/4
@@:
stosd
inc eax
cmp eax, ecx
jbe @B
 
mov [edi-4096+PROC.ht_next], 1 ;reserve handle 0
mov eax, edi
call get_pg_addr
mov [edi-4096+PROC.pdt_0_phys], eax
 
mov ecx, (OS_BASE shr 20)/4
mov esi, sys_pgdir+(OS_BASE shr 20)
xor eax, eax
rep stosd
 
mov ecx, (OS_BASE shr 20)/4
mov esi, sys_proc+PROC.pdt_0+(OS_BASE shr 20)
rep movsd
 
mov eax, [dir_addr]
mov eax, [edi-8192+PROC.pdt_0_phys]
or eax, PG_SW
mov [edi-4096+(page_tabs shr 20)], eax
 
and eax, -4096
lea eax, [edi-8192]
call set_cr3
 
mov edx, [app_tabs]
mov edi, new_app_base
mov ecx, [app_tabs]
test ecx, ecx
jz .done
 
xor edi, edi
@@:
call alloc_page
test eax, eax
494,12 → 521,9
 
stdcall map_page_table, edi, eax
add edi, 0x00400000
dec edx
jnz @B
loop @B
 
mov edi, new_app_base
shr edi, 10
add edi, page_tabs
mov edi, page_tabs
 
mov ecx, [app_tabs]
shl ecx, 10
506,15 → 530,17
xor eax, eax
rep stosd
 
xor edx, edx
mov ecx, [img_pages]
jcxz .bss
 
sub [app_pages], ecx
 
mov ebx, PG_UW
mov edx, new_app_base
mov esi, [img_base]
mov edi, new_app_base
shr esi, 10
shr edi, 10
add esi, page_tabs
add edi, page_tabs
mov edi, page_tabs
.remap:
lodsd
and eax, 0xFFFFF000
521,20 → 547,13
or eax, ebx; force user level r/w access
stosd
add edx, 0x1000
dec [app_pages]
dec ecx
jnz .remap
 
mov ecx, [app_pages]
test ecx, ecx
loop .remap
.bss:
mov ebx, [app_pages]
test ebx, ebx
jz .done
 
if GREEDY_KERNEL
mov eax, 0x02
rep stosd
else
 
.alloc:
.map_bss:
call alloc_page
test eax, eax
jz .fail
541,34 → 560,42
 
stdcall map_page, edx, eax, dword PG_UW
add edx, 0x1000
dec [app_pages]
jnz .alloc
end if
dec ebx
jnz .map_bss
 
.done:
stdcall map_page, [tmp_task_pdir], dword 0, dword PG_UNMAP
 
mov ecx, pg_data.mutex
call mutex_unlock
mov eax, [dir_addr]
mov eax, [process]
 
pop edi
pop esi
pop ebx
ret
.fail:
mov ecx, pg_data.mutex
call mutex_unlock
cmp [dir_addr], 0
cmp [process], 0
je @f
stdcall destroy_app_space, [dir_addr], 0
;; stdcall destroy_app_space, [dir_addr], 0
@@:
xor eax, eax
pop edi
pop esi
pop ebx
ret
endp
 
align 4
set_cr3:
 
pushfd
cli
mov ebx, [current_slot]
mov [ebx+APPDATA.dir_table], eax
mov [current_process], eax
mov [ebx+APPDATA.process], eax
mov eax, [eax+PROC.pdt_0_phys]
mov cr3, eax
popfd
ret
 
align 4
582,6 → 609,8
mov eax, [esi]
test eax, 1
jz .next
test eax, 2
jz .next
test eax, 1 shl 9
jnz .next ;skip shared pages
call free_page
594,46 → 623,25
endp
 
align 4
proc destroy_app_space stdcall, pg_dir:dword, dlls_list:dword
destroy_process: ;fastcall ecx= ptr to process
 
xor edx, edx
push edx
mov eax, 0x1
mov ebx, [pg_dir]
.loop:
;eax = current slot of process
mov ecx, eax
shl ecx, 5
cmp byte [CURRENT_TASK+ecx+0xa], 9;if process running?
jz @f ;skip empty slots
shl ecx, 3
add ecx, SLOT_BASE
cmp [ecx+APPDATA.dir_table], ebx;compare page directory addresses
jnz @f
mov [ebp-4], ecx
inc edx ;thread found
@@:
inc eax
cmp eax, [TASK_COUNT] ;exit loop if we look through all processes
jle .loop
lea eax, [ecx+PROC.thr_list]
cmp eax, [eax+LHEAD.next]
jne .exit
 
;edx = number of threads
;our process is zombi so it isn't counted
pop ecx
cmp edx, 1
jg .ret
;if there isn't threads then clear memory.
mov esi, [dlls_list]
call destroy_all_hdlls;ecx=APPDATA
align 4
.internal:
push ecx
 
mov ecx, pg_data.mutex
call mutex_lock
mov esi, [ecx+PROC.dlls_list_ptr]
call destroy_all_hdlls
 
mov eax, [pg_dir]
and eax, not 0xFFF
stdcall map_page, [tmp_task_pdir], eax, PG_SW
mov esi, [tmp_task_pdir]
mov edi, (OS_BASE shr 20)/4
; mov ecx, pg_data.mutex
; call mutex_lock
 
mov esi, [esp]
add esi, PROC.pdt_0
mov edi, (0x80000000 shr 20)/4
.destroy:
mov eax, [esi]
test eax, 1
648,16 → 656,13
dec edi
jnz .destroy
 
mov eax, [pg_dir]
call free_page
call kernel_free ;ecx still in stack
stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
; mov ecx, pg_data.mutex
; call mutex_unlock
 
.exit:
stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
stdcall map_page, [tmp_task_pdir], 0, PG_UNMAP
mov ecx, pg_data.mutex
call mutex_unlock
.ret:
ret
endp
 
align 4
get_pid:
708,6 → 713,10
;result:
; eax = 1 region lays in app memory
; eax = 0 region don't lays in app memory
 
mov eax, 1
ret
if 0
mov eax, [CURRENT_TASK]
; jmp check_process_region
;-----------------------------------------------------------------------------
732,57 → 741,13
 
mov eax, 1
ret
 
 
; call MEM_Get_Linear_Address
; push ebx
; push ecx
; push edx
; mov edx,ebx
; and edx,not (4096-1)
; sub ebx,edx
; add ecx,ebx
; mov ebx,edx
; add ecx,(4096-1)
; and ecx,not (4096-1)
;.loop:
;;eax - linear address of page directory
;;ebx - current page
;;ecx - current size
; mov edx,ebx
; shr edx,22
; mov edx,[eax+4*edx]
; and edx,not (4096-1)
; test edx,edx
; jz .failed1
; push eax
; mov eax,edx
; call MEM_Get_Linear_Address
; mov edx,ebx
; shr edx,12
; and edx,(1024-1)
; mov eax,[eax+4*edx]
; and eax,not (4096-1)
; test eax,eax
; pop eax
; jz .failed1
; add ebx,4096
; sub ecx,4096
; jg .loop
; pop edx
; pop ecx
; pop ebx
.ok:
mov eax, 1
ret
;
;.failed1:
; pop edx
; pop ecx
; pop ebx
.failed:
xor eax, eax
ret
end if
 
align 4
proc read_process_memory
954,7 → 919,7
 
call lock_application_table
 
call get_new_process_place
call alloc_thread_slot
test eax, eax
jz .failed
 
976,21 → 941,13
mov ecx, 11
rep movsb ;copy process name
 
mov eax, [ebx+APPDATA.heap_base]
mov [edx+APPDATA.heap_base], eax
mov eax, [ebx+APPDATA.process]
mov [edx+APPDATA.process], eax
 
mov ecx, [ebx+APPDATA.heap_top]
mov [edx+APPDATA.heap_top], ecx
lea ebx, [edx+APPDATA.list]
lea ecx, [eax+PROC.thr_list]
list_add_tail ebx, ecx ;add thread to process child's list
 
mov eax, [ebx+APPDATA.mem_size]
mov [edx+APPDATA.mem_size], eax
 
mov ecx, [ebx+APPDATA.dir_table]
mov [edx+APPDATA.dir_table], ecx;copy page directory
 
mov eax, [ebx+APPDATA.dlls_list_ptr]
mov [edx+APPDATA.dlls_list_ptr], eax
 
mov eax, [ebx+APPDATA.tls_base]
test eax, eax
jz @F
1118,8 → 1075,8
add eax, 256
jc @f
 
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8]
ja @f
; cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8]
; ja @f
 
mov eax, [cmd_line]
 
1158,8 → 1115,8
mov eax, edx
add eax, 1024
jc @f
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8]
ja @f
; cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8]
; ja @f
stdcall strncpy, edx, [app_path], 1024
@@:
mov ebx, [slot]
1188,9 → 1145,9
xor eax, eax
mov [ecx+0], dword eax
mov [ecx+4], dword eax
mov eax, [_display.width]
mov eax, [Screen_Max_X]
mov [ecx+8], eax
mov eax, [_display.height]
mov eax, [Screen_Max_Y]
mov [ecx+12], eax
 
mov ebx, [pl0_stack]
/kernel/branches/Kolibri-acpi/core/v86.inc
14,9 → 14,7
 
struct V86_machine
; page directory
pagedir dd ?
; translation table: V86 address -> flat linear address
pages dd ?
process dd ?
; mutex to protect all data from writing by multiple threads at one time
mutex dd ?
; i/o permission map
38,91 → 36,87
and dword [eax+V86_machine.mutex], 0
; allocate tables
mov ebx, eax
; We allocate 4 pages.
; First is main page directory for V86 mode.
; Second page:
; first half (0x800 bytes) is page table for addresses 0 - 0x100000,
; second half is for V86-to-linear translation.
; Third and fourth are for I/O permission map.
push 8000h ; blocks less than 8 pages are discontinuous
 
stdcall create_process, 4096, eax, 4096 ;FIXME
test eax, eax
jz .fail2
 
mov [eax+PROC.mem_used], 4096
mov [ebx+V86_machine.process], eax
 
push 2000h
call kernel_alloc
test eax, eax
jz .fail2
mov [ebx+V86_machine.pagedir], eax
push edi eax
 
mov [ebx+V86_machine.iopm], eax
 
 
; initialize tables
push edi
mov edi, eax
add eax, 1800h
mov [ebx+V86_machine.pages], eax
; initialize tables
mov eax, -1
mov ecx, 2000h/4
xor eax, eax
rep stosd
mov [ebx+V86_machine.iopm], edi
dec eax
mov ecx, 2000h/4
rep stosd
pop eax
; page directory: first entry is page table...
mov edi, eax
add eax, 1000h
push eax
call get_pg_addr
or al, PG_UW
stosd
; ...and also copy system page tables
; thx to Serge, system is located at high addresses
add edi, (OS_BASE shr 20) - 4
push esi
mov esi, (OS_BASE shr 20) + sys_pgdir
mov ecx, 0x80000000 shr 22
rep movsd
 
mov eax, [ebx+V86_machine.pagedir] ;root dir also is
call get_pg_addr ;used as page table
or al, PG_SW
mov [edi-4096+(page_tabs shr 20)], eax
mov eax, [ebx+V86_machine.process]
mov eax, [eax+PROC.pdt_0_phys]
 
pop esi
pushfd
cli
mov cr3, eax
 
 
; now V86 specific: initialize known addresses in first Mb
pop eax
 
; first page - BIOS data (shared between all machines!)
; physical address = 0
; linear address = OS_BASE
mov dword [eax], 111b
mov dword [eax+800h], OS_BASE
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
; physical address = 0x9C000
; linear address = 0x8009C000
; (I have seen one computer with EBDA segment = 0x9D80,
; all other computers use less memory)
mov ecx, 4
mov edx, 0x9C000
push eax
lea edi, [eax+0x9C*4]
 
mov eax, PG_UW
mov [page_tabs], eax
invlpg [eax]
 
mov byte [0x500], 0xCD
mov byte [0x501], 0x13
mov byte [0x502], 0xF4
mov byte [0x503], 0xCD
mov byte [0x504], 0x10
mov byte [0x505], 0xF4
 
mov eax, 0x99000+PG_UW
mov edi, page_tabs+0x99*4
mov edx, 0x1000
mov ecx, 7
@@:
lea eax, [edx + OS_BASE]
mov [edi+800h], eax
lea eax, [edx + 111b]
stosd
add edx, 0x1000
add eax, edx
loop @b
pop eax
pop edi
 
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
; physical address = 0xC0000
; linear address = 0x800C0000
mov ecx, 0xC0
 
mov eax, 0xC0000+PG_UW
mov edi, page_tabs+0xC0*4
mov ecx, 64
@@:
mov edx, ecx
shl edx, 12
push edx
or edx, 111b
mov [eax+ecx*4], edx
pop edx
add edx, OS_BASE
mov [eax+ecx*4+0x800], edx
inc cl
jnz @b
stosd
add eax, edx
loop @b
 
mov eax, sys_proc
push ebx
call set_cr3
pop ebx
popfd
 
pop edi
 
mov eax, ebx
ret
.fail2:
132,15 → 126,16
xor eax, eax
ret
 
;not used
; Destroy V86 machine
; in: eax = handle
; out: nothing
; destroys: eax, ebx, ecx, edx (due to free)
v86_destroy:
push eax
stdcall kernel_free, [eax+V86_machine.pagedir]
pop eax
jmp free
;v86_destroy:
; push eax
; stdcall kernel_free, [eax+V86_machine.pagedir]
; pop eax
; jmp free
 
; Translate V86-address to linear address
; in: eax=V86 address
150,13 → 145,15
v86_get_lin_addr:
push ecx edx
mov ecx, eax
mov edx, [esi+V86_machine.pages]
shr ecx, 12
mov edx, [page_tabs+ecx*4]
and eax, 0xFFF
add eax, [edx+ecx*4] ; atomic operation, no mutex needed
and edx, 0xFFFFF000
or eax, edx
pop edx ecx
ret
 
;not used
; Sets linear address for V86-page
; in: eax=linear address (must be page-aligned)
; ecx=V86 page (NOT address!)
163,15 → 160,15
; esi=handle
; out: nothing
; destroys: nothing
v86_set_page:
push eax ebx
mov ebx, [esi+V86_machine.pagedir]
mov [ebx+ecx*4+0x1800], eax
call get_pg_addr
or al, 111b
mov [ebx+ecx*4+0x1000], eax
pop ebx eax
ret
;v86_set_page:
; push eax ebx
; mov ebx, [esi+V86_machine.pagedir]
; mov [ebx+ecx*4+0x1800], eax
; call get_pg_addr
; or al, 111b
; mov [ebx+ecx*4+0x1000], eax
; pop ebx eax
; ret
 
; Allocate memory in V86 machine
; in: eax=size (in bytes)
214,21 → 211,7
mov [sys_v86_machine], eax
test eax, eax
jz .ret
mov byte [OS_BASE + 0x500], 0xCD
mov byte [OS_BASE + 0x501], 0x13
mov byte [OS_BASE + 0x502], 0xF4
mov byte [OS_BASE + 0x503], 0xCD
mov byte [OS_BASE + 0x504], 0x10
mov byte [OS_BASE + 0x505], 0xF4
mov esi, eax
mov ebx, [eax+V86_machine.pagedir]
; one page for stack, two pages for results (0x2000 bytes = 16 sectors)
mov dword [ebx+0x99*4+0x1000], 0x99000 or 111b
mov dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000
mov dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b
mov dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000
mov dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b
mov dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000
if ~DEBUG_SHOW_IO
; allow access to all ports
mov ecx, [esi+V86_machine.iopm]
272,37 → 255,39
; eax = 3 - IRQ is already hooked by another VM
; destroys: nothing
v86_start:
 
pushad
 
cli
 
mov ecx, [CURRENT_TASK]
shl ecx, 8
add ecx, SLOT_BASE
mov ecx, [current_slot]
 
push dword [ecx+APPDATA.io_map]
push dword [ecx+APPDATA.io_map+4]
push [ecx+APPDATA.process]
push [ecx+APPDATA.saved_esp0]
mov [ecx+APPDATA.saved_esp0], esp
mov [tss._esp0], esp
 
mov eax, [esi+V86_machine.iopm]
call get_pg_addr
inc eax
push dword [ecx+APPDATA.io_map]
push dword [ecx+APPDATA.io_map+4]
mov dword [ecx+APPDATA.io_map], eax
mov dword [page_tabs + (tss._io_map_0 shr 10)], eax
 
mov eax, [esi+V86_machine.iopm]
add eax, 0x1000
call get_pg_addr
inc eax
mov dword [ecx+APPDATA.io_map+4], eax
mov dword [page_tabs + (tss._io_map_1 shr 10)], eax
 
push [ecx+APPDATA.dir_table]
push [ecx+APPDATA.saved_esp0]
mov [ecx+APPDATA.saved_esp0], esp
mov [tss._esp0], esp
 
mov eax, [esi+V86_machine.pagedir]
call get_pg_addr
mov [ecx+APPDATA.dir_table], eax
mov eax, [esi+V86_machine.process]
mov [ecx+APPDATA.process], eax
mov [current_process], eax
mov eax, [eax+PROC.pdt_0_phys]
mov cr3, eax
 
; mov [irq_tab+5*4], my05
 
; We do not enable interrupts, because V86 IRQ redirector assumes that
; machine is running
; They will be enabled by IRET.
782,19 → 767,21
mov esp, esi
 
cli
mov ecx, [CURRENT_TASK]
shl ecx, 8
mov ecx, [current_slot]
pop eax
mov [SLOT_BASE+ecx+APPDATA.saved_esp0], eax
 
mov [ecx+APPDATA.saved_esp0], eax
mov [tss._esp0], eax
pop eax
mov [SLOT_BASE+ecx+APPDATA.dir_table], eax
mov [ecx+APPDATA.process], eax
mov [current_process], eax
pop ebx
mov dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx
mov dword [ecx+APPDATA.io_map+4], ebx
mov dword [page_tabs + (tss._io_map_1 shr 10)], ebx
pop ebx
mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx
mov dword [ecx+APPDATA.io_map], ebx
mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx
mov eax, [eax+PROC.pdt_0_phys]
mov cr3, eax
sti
 
843,11 → 830,10
pop eax
v86_irq2:
mov esi, [v86_irqhooks+edi*8] ; get VM handle
mov eax, [esi+V86_machine.pagedir]
call get_pg_addr
mov eax, [esi+V86_machine.process]
mov ecx, [CURRENT_TASK]
shl ecx, 8
cmp [SLOT_BASE+ecx+APPDATA.dir_table], eax
cmp [SLOT_BASE+ecx+APPDATA.process], eax
jnz .notcurrent
lea eax, [edi+8]
cmp al, 10h
860,7 → 846,7
mov ebx, SLOT_BASE + 0x100
mov ecx, [TASK_COUNT]
.scan:
cmp [ebx+APPDATA.dir_table], eax
cmp [ebx+APPDATA.process], eax
jnz .cont
push ecx
mov ecx, [ebx+APPDATA.saved_esp0]
895,6 → 881,7
popad
iretd
.found:
mov eax, [eax+PROC.pdt_0_phys]
mov cr3, eax
mov esi, [ebx+APPDATA.saved_esp0]
sub word [esi-sizeof.v86_regs+v86_regs.esp], 6
/kernel/branches/Kolibri-acpi/data32.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
140,24 → 140,20
start_not_enough_memory db 'K : New Process - not enough memory',13,10,0
 
msg_unresolved db 'unresolved ',0
msg_module db 'in module ',0
if ~ lang eq sp
msg_version db 'incompatible driver version',13,10,0
msg_www db 'please visit www.kolibrios.org',13,10,0
end if
;msg_module db 'in module ',0
;if ~ lang eq sp
;msg_version db 'incompatible driver version',13,10,0
;msg_www db 'please visit www.kolibrios.org',13,10,0
;end if
msg_CR db 13,10,0
 
intel_str db "GenuineIntel",0
AMD_str db "AuthenticAMD",0
 
szHwMouse db 'ATI2D',0
szPS2MDriver db 'PS2MOUSE',0
szPS2MDriver db '/rd/1/drivers/PS2MOUSE.SYS',0
;szCOM_MDriver db 'COM_MOUSE',0
szVidintel db 'vidintel',0
szVidintel db '/rd/1/drivers/vidintel.sys',0
szUSB db 'USB',0
szAtiHW db '/rd/1/drivers/ati2d.drv',0
 
szSTART db 'START',0
szEXPORTS db 'EXPORTS',0
sz_EXPORTS db '_EXPORTS',0
 
168,8 → 164,10
notifyapp db '@notify',0
if lang eq ru
ud_user_message cp866 'Ошибка: неподдерживаемая инструкция процессора',0
mtrr_user_message cp866 '"Обнаружена проблема с конфигурацией MTRR.\nПроизводительность может быть пониженной" -dW',0
else if ~ lang eq sp
ud_user_message db 'Error: unsupported processor instruction',0
mtrr_user_message db '"There is a problem with MTRR configuration.\nPerformance can be low" -dW',0
end if
 
vmode db '/sys/drivers/VMODE.MDR',0
179,7 → 177,7
dd 0 ; subfunction
dq 0 ; offset in file
dd 0x30000 ; number of bytes to read
dd OS_BASE + 0x70000 ; buffer for data
dd OS_BASE + 0x71000 ; buffer for data
db '/RD/1/KERNEL.MNT',0
 
dev_data_path db '/RD/1/DRIVERS/DEVICES.DAT',0
347,6 → 345,8
mem_used_list rd 64*2
mem_hash_cnt rd 64
 
thr_slot_map rd 8
 
cpu_freq rq 1
 
heap_mutex MUTEX
378,12 → 378,14
_WinMapAddress rd 1
_WinMapSize rd 1
 
LFBAddress rd 1
LFBAddress dd ?
Screen_Max_X dd ?
Screen_Max_Y dd ?
 
SCR_MODE rw 2
 
PUTPIXEL rd 1
GETPIXEL rd 1
PUTPIXEL dd ?
GETPIXEL dd ?
 
if VESA_1_2_VIDEO
BANK_SWITCH rd 1 reserved for vesa 1.2
399,7 → 401,7
 
mouseunder rd 16*24
 
MOUSE_PICTURE rd 1
MOUSE_PICTURE dd ?
 
MOUSE_SCROLL_H rw 1
MOUSE_X: rw 1
436,7 → 438,6
proc_mem_pdir rd 1
proc_mem_tab rd 1
 
tmp_task_pdir rd 1
tmp_task_ptab rd 1
 
default_io_map rd 1
443,8 → 444,10
 
LFBSize rd 1
 
current_slot rd 1
current_process rd 1
current_slot rd 1 ; i.e. cureent thread
 
 
; status
hd1_status rd 1 ; 0 - free : other - pid
application_table_owner rd 1 ; 0 - free : other - pid
460,8 → 463,6
hdbase rd 1 ; for boot 0x1f0
hdid rd 1
hdpos rd 1 ; for boot 0x1
label known_part dword
fat32part rd 1 ; for boot 0x1
cdpos rd 1
 
;CPUID information
494,63 → 495,12
 
skin_data rd 1
 
cache_ide0:
cache_ide0_pointer rd 1
cache_ide0_size rd 1 ; not use
cache_ide0_data_pointer rd 1
cache_ide0_system_data_size rd 1 ; not use
cache_ide0_appl_data_size rd 1 ; not use
cache_ide0_system_data rd 1
cache_ide0_appl_data rd 1
cache_ide0_system_sad_size rd 1
cache_ide0_appl_sad_size rd 1
cache_ide0_search_start rd 1
cache_ide0_appl_search_start rd 1
 
cache_ide1:
cache_ide1_pointer rd 1
cache_ide1_size rd 1 ; not use
cache_ide1_data_pointer rd 1
cache_ide1_system_data_size rd 1 ; not use
cache_ide1_appl_data_size rd 1 ; not use
cache_ide1_system_data rd 1
cache_ide1_appl_data rd 1
cache_ide1_system_sad_size rd 1
cache_ide1_appl_sad_size rd 1
cache_ide1_search_start rd 1
cache_ide1_appl_search_start rd 1
 
cache_ide2:
cache_ide2_pointer rd 1
cache_ide2_size rd 1 ; not use
cache_ide2_data_pointer rd 1
cache_ide2_system_data_size rd 1 ; not use
cache_ide2_appl_data_size rd 1 ; not use
cache_ide2_system_data rd 1
cache_ide2_appl_data rd 1
cache_ide2_system_sad_size rd 1
cache_ide2_appl_sad_size rd 1
cache_ide2_search_start rd 1
cache_ide2_appl_search_start rd 1
 
cache_ide3:
cache_ide3_pointer rd 1
cache_ide3_size rd 1 ; not use
cache_ide3_data_pointer rd 1
cache_ide3_system_data_size rd 1 ; not use
cache_ide3_appl_data_size rd 1 ; not use
cache_ide3_system_data rd 1
cache_ide3_appl_data rd 1
cache_ide3_system_sad_size rd 1
cache_ide3_appl_sad_size rd 1
cache_ide3_search_start rd 1
cache_ide3_appl_search_start rd 1
 
debug_step_pointer rd 1
 
lba_read_enabled rd 1 ; 0 = disabled , 1 = enabled
pci_access_enabled rd 1 ; 0 = disabled , 1 = enabled
 
cpu_phys_addr_width rb 1 ; also known as MAXPHYADDR in Intel manuals
hdd_appl_data rb 1 ; 0 = system cache, 1 - application cache
cd_appl_data rb 1 ; 0 = system cache, 1 - application cache
 
575,16 → 525,21
 
org (OS_BASE+0x0100000)
 
RAMDISK: rb 2880*512
rb 2856*4 ; not used
; 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
 
RAMDISK: rb RAMDISK_CAPACITY*512
 
_CLEAN_ZONE:
 
BgrAuxTable rb 32768
align 65536
SB16Buffer rb 65536
 
align 4096
_IDE_DMA rb 16*512
BgrAuxTable rb 32768
BUTTON_INFO rb 64*1024
RESERVED_PORTS: rb 64*1024
FLOPPY_BUFF: rb 18*512 ;one track
 
sys_pgmap: rb 1024*1024/8
/kernel/branches/Kolibri-acpi/data32et.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
boot_initirq latin1 'Algväärtustan IRQ',0
boot_picinit latin1 'Algväärtustan PIC',0
boot_v86machine latin1 'Algväärtustan süsteemi V86 masinat',0
/kernel/branches/Kolibri-acpi/data32sp.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 5088 $
 
 
boot_initirq: cp850 'Inicializar IRQ',0
boot_picinit: cp850 'Inicializar PIC',0
boot_v86machine: cp850 'Inicializar sistema V86',0
37,7 → 47,8
boot_tasking: cp850 'Todo configurado - presiona ESC para iniciar',0
end if
 
msg_version: cp850 'versión incompatible del controlador',13,10,0
msg_www: cp850 'por favor, visita www.kolibrios.org',13,10,0
;msg_version: cp850 'versión incompatible del controlador',13,10,0
;msg_www: cp850 'por favor, visita www.kolibrios.org',13,10,0
 
ud_user_message:cp850 'Error: instrucción no soportada por el procesador',0
mtrr_user_message cp850 '"There is a problem with MTRR configuration.\nPerformance can be low" -dW',0
/kernel/branches/Kolibri-acpi/detect/biosdisk.inc
1,10 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2008-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2008-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
; Detect all BIOS hard drives.
; diamond, 2008
; Do not include USB mass storages. CleverMouse, 2013
/kernel/branches/Kolibri-acpi/detect/biosmem.inc
1,10 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2009-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2009-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
; Query physical memory map from BIOS.
; diamond, 2009
 
/kernel/branches/Kolibri-acpi/detect/dev_hdcd.inc
17,93 → 17,192
;****************************************************
;* ПОИСК HDD и CD *
;****************************************************
cmp [IDEContrProgrammingInterface], 0
cmp [ecx+IDE_DATA.ProgrammingInterface], 0
je EndFindHDD
 
FindHDD:
push ecx
 
xor ebx, ebx
inc ebx
 
cmp ecx, IDE_controller_2
jne @f
 
add bl, 5
jmp .find
@@:
cmp ecx, IDE_controller_3
jne .find
 
add bl, 10
;--------------------------------------
.find:
 
mov [ChannelNumber], 1
mov [DiskNumber], 0
call FindHDD_3
; mov ax,[Sector512+176]
; mov [DRIVE_DATA+6],ax
; mov ax,[Sector512+126]
; mov [DRIVE_DATA+8],ax
; mov ax,[Sector512+128]
; mov [DRIVE_DATA+8],ax
call FindHDD_2
 
mov [DiskNumber], 1
call FindHDD_3
; mov al,[Sector512+176]
; mov [DRIVE_DATA+7],al
call FindHDD_2
 
inc [ChannelNumber]
 
mov [DiskNumber], 0
call FindHDD_3
; mov al,[Sector512+176]
; mov [DRIVE_DATA+8],al
call FindHDD_2
 
mov [DiskNumber], 1
call FindHDD_1
; mov al,[Sector512+176]
; mov [DRIVE_DATA+9],al
 
pop ecx
jmp EndFindHDD
 
;-----------------------------------------------------------------------------
FindHDD_2:
call FindHDD_1
shl byte [ebx+DRIVE_DATA], 2
ret
;-----------------------------------------------------------------------------
FindHDD_1:
DEBUGF 1, "K : Channel %d ",[ChannelNumber]:2
DEBUGF 1, "Disk %d\n",[DiskNumber]:1
push ebx ecx
call ReadHDD_ID
pop ecx ebx
cmp [DevErrorCode], 7
je .end
cmp [DevErrorCode], 0
jne FindHDD_2
jne .FindCD
 
cmp [Sector512+6], word 16
ja FindHDD_2
ja .FindCD
 
cmp [Sector512+12], word 255
ja FindHDD_2
inc byte [DRIVE_DATA+1]
jmp Print_Device_Name
FindHDD_2:
ja .FindCD
 
inc byte [ebx+DRIVE_DATA]
jmp .Print_Device_Name
;--------------------------------------
.FindCD:
push ebx ecx
call DeviceReset
pop ecx ebx
cmp [DevErrorCode], 0
jne FindHDD_2_2
jne .end
 
push ebx ecx
call ReadCD_ID
pop ecx ebx
cmp [DevErrorCode], 0
jne FindHDD_2_2
inc byte [DRIVE_DATA+1]
inc byte [DRIVE_DATA+1]
Print_Device_Name:
jne .end
 
add [ebx+DRIVE_DATA], byte 2
;--------------------------------------
.Print_Device_Name:
pushad
pushfd
 
xor ebx, ebx
mov bx, [ChannelNumber]
dec ebx
shl ebx, 1
add bl, [DiskNumber]
shl ebx, 1
 
call calculate_IDE_device_values_storage
;--------------------------------------
.copy_dev_name:
mov esi, Sector512+27*2
mov edi, dev_name
mov ecx, 20
cld
;--------------------------------------
@@:
lodsw
xchg ah, al
stosw
loop @b
popfd
popad
 
DEBUGF 1, "K : Dev: %s \n", dev_name
 
xor eax, eax
mov ax, [Sector512+64*2]
DEBUGF 1, "K : PIO mode %x\n", eax
DEBUGF 1, "K : PIO possible modes %x\n", al
 
mov ax, [Sector512+51*2]
mov al, ah
call convert_Sector512_value
DEBUGF 1, "K : PIO set mode %x\n", ah
 
mov ax, [Sector512+63*2]
DEBUGF 1, "K : Multiword DMA mode %x\n", eax
DEBUGF 1, "K : Multiword DMA possible modes %x\n", al
 
mov al, ah
call convert_Sector512_value
DEBUGF 1, "K : Multiword DMA set mode %x\n", ah
 
mov ax, [Sector512+88*2]
DEBUGF 1, "K : Ultra DMA mode %x\n", eax
FindHDD_2_2:
DEBUGF 1, "K : Ultra DMA possible modes %x\n", al
 
mov [ebx+IDE_DEVICE.UDMA_possible_modes], al
 
mov al, ah
call convert_Sector512_value
DEBUGF 1, "K : Ultra DMA set mode %x\n", ah
 
mov [ebx+IDE_DEVICE.UDMA_set_mode], ah
 
popfd
popad
ret
;--------------------------------------
.end:
DEBUGF 1, "K : Device not found\n"
ret
;-----------------------------------------------------------------------------
calculate_IDE_device_values_storage:
cmp ecx, IDE_controller_1
jne @f
 
FindHDD_3:
call FindHDD_1
shl byte [DRIVE_DATA+1], 2
add ebx, IDE_device_1
jmp .exit
;--------------------------------------
@@:
cmp ecx, IDE_controller_2
jne @f
 
add ebx, IDE_device_2
jmp .exit
;--------------------------------------
@@:
add ebx, IDE_device_3
;--------------------------------------
.exit:
ret
;-----------------------------------------------------------------------------
convert_Sector512_value:
mov ecx, 8
xor ah, ah
;--------------------------------------
@@:
test al, 1b
jnz .end
 
shr al, 1
inc ah
loop @b
 
xor ah, ah
;--------------------------------------
.end:
ret
;-----------------------------------------------------------------------------
; Адрес считываемого сектора в режиме LBA
uglobal
SectorAddress DD ?
SectorAddress dd ?
dev_name:
rb 41
endg
;-----------------------------------------------------------------------------
;*************************************************
;* ЧТЕНИЕ ИДЕНТИФИКАТОРА ЖЕСТКОГО ДИСКА *
;* Входные параметры передаются через глобальные *
119,32 → 218,32
; Послать команду идентификации устройства
mov [ATAFeatures], 0
mov [ATAHead], 0
mov [ATACommand], 0ECh
mov [ATACommand], 0xEC
call SendCommandToHDD
cmp [DevErrorCode], 0;проверить код ошибки
jne @@End ;закончить, сохранив код ошибки
mov DX, [ATABasePortAddr]
add DX, 7 ;адрес регистра состояни
 
mov dx, [ATABasePortAddr]
add dx, 7 ;адрес регистра состояни
mov ecx, 0xffff
@@WaitCompleet:
; Проверить время выполнения команды
dec ecx
; cmp ecx,0
jz @@Error1 ;ошибка тайм-аута
; Проверить готовность
in AL, DX
test AL, 80h ;состояние сигнала BSY
in al, dx
test al, 80h ;состояние сигнала BSY
jnz @@WaitCompleet
test AL, 1 ;состояние сигнала ERR
 
test al, 1 ;состояние сигнала ERR
jnz @@Error6
test AL, 08h ;состояние сигнала DRQ
 
test al, 08h ;состояние сигнала DRQ
jz @@WaitCompleet
; Принять блок данных от контроллера
; mov AX,DS
; mov ES,AX
mov EDI, Sector512 ;offset Sector512
mov DX, [ATABasePortAddr];регистр данных
mov CX, 256 ;число считываемых слов
mov edi, Sector512
mov dx, [ATABasePortAddr];регистр данных
mov cx, 256 ;число считываемых слов
rep insw ;принять блок данных
ret
; Записать код ошибки
155,34 → 254,32
mov [DevErrorCode], 6
@@End:
ret
 
 
iglobal
;-----------------------------------------------------------------------------
uglobal
; Стандартные базовые адреса каналов 1 и 2
StandardATABases DW 1F0h, 170h
endg
uglobal
StandardATABases dw ?, ? ; 1F0h, 170h
; Номер канала
ChannelNumber DW ?
ChannelNumber dw ?
; Номер диска
DiskNumber DB ?
DiskNumber db ?
; Базовый адрес группы портов контроллера ATA
ATABasePortAddr DW ?
ATABasePortAddr dw ?
; Параметры ATA-команды
ATAFeatures DB ? ;особенности
ATASectorCount DB ? ;количество обрабатываемых секторов
ATASectorNumber DB ? ;номер начального сектора
ATACylinder DW ? ;номер начального цилиндра
ATAHead DB ? ;номер начальной головки
ATAAddressMode DB ? ;режим адресации (0 - CHS, 1 - LBA)
ATACommand DB ? ;код команды, подлежащей выполнению
ATAFeatures db ? ;особенности
ATASectorCount db ? ;количество обрабатываемых секторов
ATASectorNumber db ? ;номер начального сектора
ATACylinder dw ? ;номер начального цилиндра
ATAHead db ? ;номер начальной головки
ATAAddressMode db ? ;режим адресации (0 - CHS, 1 - LBA)
ATACommand db ? ;код команды, подлежащей выполнению
; Код ошибки (0 - нет ошибок, 1 - превышен допустимый
; интервал ожидания, 2 - неверный код режима адресации,
; 3 - неверный номер канала, 4 - неверный номер диска,
; 5 - неверный номер головки, 6 - ошибка при выполнении
; команды)
; команды, 7 - таймаут при выборе канала)
DevErrorCode dd ?
endg
;-----------------------------------------------------------------------------
;****************************************************
;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ *
;* Входные параметры передаются через глобальные *
207,82 → 304,78
cmp [ATAAddressMode], 1
ja @@Err2
; Проверить корректность номера канала
mov BX, [ChannelNumber]
cmp BX, 1
mov bx, [ChannelNumber]
cmp bx, 1
jb @@Err3
cmp BX, 2
 
cmp bx, 2
ja @@Err3
; Установить базовый адрес
dec BX
shl BX, 1
dec bx
shl bx, 1
movzx ebx, bx
mov AX, [ebx+StandardATABases]
mov [ATABasePortAddr], AX
mov ax, [ebx+StandardATABases]
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
shl AL, 4
or AL, 10100000b
out DX, AL
 
shl al, 4
or al, 10100000b
out dx, al
; Ожидать, пока диск не будет готов
inc DX
inc dx
mov ecx, 0xfff
; mov eax,[timer_ticks]
; mov [TickCounter_1],eax
@@WaitHDReady:
; Проверить время ожидани
dec ecx
; cmp ecx,0
jz @@Err1
; mov eax,[timer_ticks]
; sub eax,[TickCounter_1]
; cmp eax,300 ;ожидать 300 тиков
; ja @@Err1 ;ошибка тайм-аута
; Прочитать регистр состояни
in AL, DX
in al, dx
; Проверить состояние сигнала BSY
test AL, 80h
test al, 80h
jnz @@WaitHDReady
; Проверить состояние сигнала DRQ
test AL, 08h
test al, 08h
jnz @@WaitHDReady
; Загрузить команду в регистры контроллера
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
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
289,7 → 382,7
ret
; Записать код ошибки
@@Err1:
mov [DevErrorCode], 1
mov [DevErrorCode], 7
ret
@@Err2:
mov [DevErrorCode], 2
304,7 → 397,7
mov [DevErrorCode], 5
; Завершение работы программы
ret
 
;-----------------------------------------------------------------------------
;*************************************************
;* ЧТЕНИЕ ИДЕНТИФИКАТОРА УСТРОЙСТВА ATAPI *
;* Входные параметры передаются через глобальные *
323,33 → 416,32
mov [ATASectorNumber], 0
mov [ATACylinder], 0
mov [ATAHead], 0
mov [ATACommand], 0A1h
mov [ATACommand], 0xA1
call SendCommandToHDD
cmp [DevErrorCode], 0;проверить код ошибки
jne @@End_1 ;закончить, сохранив код ошибки
; Ожидать готовность данных HDD
mov DX, [ATABasePortAddr]
add DX, 7 ;порт 1х7h
mov dx, [ATABasePortAddr]
add dx, 7 ;порт 1х7h
mov ecx, 0xffff
@@WaitCompleet_1:
; Проверить врем
dec ecx
; cmp ecx,0
jz @@Error1_1 ;ошибка тайм-аута
; Проверить готовность
in AL, DX
test AL, 80h ;состояние сигнала BSY
in al, dx
test al, 80h ;состояние сигнала BSY
jnz @@WaitCompleet_1
test AL, 1 ;состояние сигнала ERR
 
test al, 1 ;состояние сигнала ERR
jnz @@Error6_1
test AL, 08h ;состояние сигнала DRQ
 
test al, 08h ;состояние сигнала DRQ
jz @@WaitCompleet_1
; Принять блок данных от контроллера
; mov AX,DS
; mov ES,AX
mov EDI, Sector512 ;offset Sector512
mov DX, [ATABasePortAddr];порт 1x0h
mov CX, 256;число считываемых слов
mov edi, Sector512 ;offset Sector512
mov dx, [ATABasePortAddr];порт 1x0h
mov cx, 256;число считываемых слов
rep insw
ret
; Записать код ошибки
360,7 → 452,7
mov [DevErrorCode], 6
@@End_1:
ret
 
;-----------------------------------------------------------------------------
;*************************************************
;* СБРОС УСТРОЙСТВА *
;* Входные параметры передаются через глобальные *
370,39 → 462,40
;*************************************************
DeviceReset:
; Проверить корректность номера канала
mov BX, [ChannelNumber]
cmp BX, 1
mov bx, [ChannelNumber]
cmp bx, 1
jb @@Err3_2
cmp BX, 2
 
cmp bx, 2
ja @@Err3_2
; Установить базовый адрес
dec BX
shl BX, 1
dec bx
shl bx, 1
movzx ebx, bx
mov DX, [ebx+StandardATABases]
mov [ATABasePortAddr], DX
mov dx, [ebx+StandardATABases]
mov [ATABasePortAddr], dx
; Выбрать нужный диск
add DX, 6 ;адрес регистра головок
mov AL, [DiskNumber]
cmp AL, 1 ;проверить номера диска
add dx, 6 ;адрес регистра головок
mov al, [DiskNumber]
cmp al, 1 ;проверить номера диска
ja @@Err4_2
shl AL, 4
or AL, 10100000b
out DX, AL
 
shl al, 4
or al, 10100000b
out dx, al
; Послать команду "Сброс"
mov AL, 08h
inc DX ;регистр команд
out DX, AL
mov al, 0x8
inc dx ;регистр команд
out dx, al
mov ecx, 0x80000
@@WaitHDReady_1:
; Проверить время ожидани
dec ecx
; cmp ecx,0
je @@Err1_2 ;ошибка тайм-аута
; Прочитать регистр состояни
in AL, DX
in al, dx
; Проверить состояние сигнала BSY
test AL, 80h
test al, 80h
jnz @@WaitHDReady_1
; Сбросить признак ошибки
mov [DevErrorCode], 0
418,6 → 511,5
mov [DevErrorCode], 4
; Записать код ошибки
ret
 
;-----------------------------------------------------------------------------
EndFindHDD:
 
/kernel/branches/Kolibri-acpi/detect/getcache.inc
7,6 → 7,7
 
$Revision$
 
;-----------------------------------------------------------------------------
pusha
 
mov eax, [pg_data.pages_free]
20,89 → 21,167
; check a upper size of the cache, no more than 1 Mb on the physical device
cmp eax, 1024*1024
jbe @f
 
mov eax, 1024*1024
jmp .continue
;--------------------------------------
@@:
; check a lower size of the cache, not less than 128 Kb on the physical device
cmp eax, 128*1024
jae @f
jae .continue
 
mov eax, 128*1024
;--------------------------------------
.continue:
push ecx
mov ecx, 12
mov esi, cache_ide0+IDE_CACHE.size
cld
@@:
.continue:
mov [cache_ide0_size], eax
mov [cache_ide1_size], eax
mov [cache_ide2_size], eax
mov [cache_ide3_size], eax
mov [esi], eax
add esi, sizeof.IDE_CACHE
loop @b
 
pop ecx
 
xor eax, eax
mov [hdd_appl_data], 1;al
mov [cd_appl_data], 1
;--------------------------------------
test byte [DRIVE_DATA+1], 0x80
je @f
 
test byte [DRIVE_DATA+1], 2
je .ide2
mov esi, cache_ide3
mov esi, cache_ide0
call get_cache_ide
.ide2:
;--------------------------------------
@@:
test byte [DRIVE_DATA+1], 0x20
je @f
 
mov esi, cache_ide1
call get_cache_ide
;--------------------------------------
@@:
test byte [DRIVE_DATA+1], 8
je .ide1
je @f
 
mov esi, cache_ide2
call get_cache_ide
.ide1:
test byte [DRIVE_DATA+1], 0x20
je .ide0
mov esi, cache_ide1
;--------------------------------------
@@:
test byte [DRIVE_DATA+1], 2
je @f
 
mov esi, cache_ide3
call get_cache_ide
.ide0:
test byte [DRIVE_DATA+1], 0x80
;--------------------------------------
@@:
test byte [DRIVE_DATA+6], 0x80
je @f
mov esi, cache_ide0
 
mov esi, cache_ide4
call get_cache_ide
;--------------------------------------
@@:
test byte [DRIVE_DATA+6], 0x20
je @f
 
mov esi, cache_ide5
call get_cache_ide
;--------------------------------------
@@:
test byte [DRIVE_DATA+6], 8
je @f
 
mov esi, cache_ide6
call get_cache_ide
;--------------------------------------
@@:
test byte [DRIVE_DATA+6], 2
je @f
 
mov esi, cache_ide7
call get_cache_ide
;--------------------------------------
@@:
test byte [DRIVE_DATA+11], 0x80
je @f
 
mov esi, cache_ide8
call get_cache_ide
;--------------------------------------
@@:
test byte [DRIVE_DATA+11], 0x20
je @f
 
mov esi, cache_ide9
call get_cache_ide
;--------------------------------------
@@:
test byte [DRIVE_DATA+11], 8
je @f
 
mov esi, cache_ide10
call get_cache_ide
;--------------------------------------
@@:
test byte [DRIVE_DATA+11], 2
je end_get_cache
 
mov esi, cache_ide11
call get_cache_ide
 
jmp end_get_cache
;-----------------------------------------------------------------------------
get_cache_ide:
and [esi+IDE_CACHE.search_start], 0
and [esi+IDE_CACHE.appl_search_start], 0
 
get_cache_ide:
and [esi+cache_ide0_search_start-cache_ide0], 0
and [esi+cache_ide0_appl_search_start-cache_ide0], 0
push ecx
stdcall kernel_alloc, [esi+cache_ide0_size-cache_ide0]
mov [esi+cache_ide0_pointer-cache_ide0], eax
; DEBUGF 1, "K : IDE_CACHE.size %x\n", [esi+IDE_CACHE.size]
stdcall kernel_alloc, [esi+IDE_CACHE.size]
mov [esi+IDE_CACHE.pointer], eax
pop ecx
 
mov edx, eax
mov eax, [esi+cache_ide0_size-cache_ide0]
mov eax, [esi+IDE_CACHE.size]
shr eax, 3
mov [esi+cache_ide0_system_data_size-cache_ide0], eax
; DEBUGF 1, "K : IDE_CACHE.system_data_size %x\n", eax
mov [esi+IDE_CACHE.system_data_size], eax
mov ebx, eax
imul eax, 7
mov [esi+cache_ide0_appl_data_size-cache_ide0], eax
; DEBUGF 1, "K : IDE_CACHE.appl_data_size %x\n", eax
mov [esi+IDE_CACHE.appl_data_size], eax
add ebx, edx
mov [esi+cache_ide0_data_pointer-cache_ide0], ebx
mov [esi+IDE_CACHE.data_pointer], ebx
 
.cd:
push ecx
mov eax, [esi+cache_ide0_system_data_size-cache_ide0]
mov eax, [esi+IDE_CACHE.system_data_size]
call calculate_for_cd
add eax, [esi+cache_ide0_pointer-cache_ide0]
mov [esi+cache_ide0_system_data-cache_ide0], eax
mov [esi+cache_ide0_system_sad_size-cache_ide0], ecx
add eax, [esi+IDE_CACHE.pointer]
mov [esi+IDE_CACHE.system_data], eax
mov [esi+IDE_CACHE.system_sad_size], ecx
 
push edi
mov edi, [esi+cache_ide0_pointer-cache_ide0]
mov edi, [esi+IDE_CACHE.pointer]
call clear_ide_cache
pop edi
 
mov eax, [esi+cache_ide0_appl_data_size-cache_ide0]
mov eax, [esi+IDE_CACHE.appl_data_size]
call calculate_for_cd
add eax, [esi+cache_ide0_data_pointer-cache_ide0]
mov [esi+cache_ide0_appl_data-cache_ide0], eax
mov [esi+cache_ide0_appl_sad_size-cache_ide0], ecx
add eax, [esi+IDE_CACHE.data_pointer]
mov [esi+IDE_CACHE.appl_data], eax
mov [esi+IDE_CACHE.appl_sad_size], ecx
 
push edi
mov edi, [esi+cache_ide0_data_pointer-cache_ide0]
mov edi, [esi+IDE_CACHE.data_pointer]
call clear_ide_cache
pop edi
 
pop ecx
ret
 
;-----------------------------------------------------------------------------
calculate_for_cd:
push eax
mov ebx, eax
116,7 → 195,7
sub eax, ebx
dec ecx
ret
 
;-----------------------------------------------------------------------------
clear_ide_cache:
push eax
shl ecx, 1
125,6 → 204,6
rep stosd
pop eax
ret
 
;-----------------------------------------------------------------------------
end_get_cache:
popa
/kernel/branches/Kolibri-acpi/detect/init_ata.inc
0,0 → 1,464
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 5147 $
 
 
;-----------------------------------------------------------------------------
; find the IDE controller in the device list
;-----------------------------------------------------------------------------
mov ecx, IDE_controller_1
mov esi, pcidev_list
;--------------------------------------
align 4
.loop:
mov esi, [esi+PCIDEV.fd]
cmp esi, pcidev_list
jz find_IDE_controller_done
 
mov eax, [esi+PCIDEV.class]
; shr eax, 4
; cmp eax, 0x01018
shr eax, 7
cmp eax, 0x010180 shr 7
jnz .loop
;--------------------------------------
.found:
mov eax, [esi+PCIDEV.class]
DEBUGF 1, 'K : IDE controller programming interface %x\n', eax
mov [ecx+IDE_DATA.ProgrammingInterface], eax
 
mov ah, [esi+PCIDEV.bus]
mov al, 2
mov bh, [esi+PCIDEV.devfn]
;--------------------------------------
mov dx, 0x1F0
test byte [esi+PCIDEV.class], 1
jz @f
mov bl, 0x10
push eax
call pci_read_reg
and eax, 0xFFFC
mov edx, eax
pop eax
@@:
DEBUGF 1, 'K : BAR0 IDE base addr %x\n', dx
mov [StandardATABases], dx
mov [ecx+IDE_DATA.BAR0_val], dx
;--------------------------------------
mov dx, 0x3F4
test byte [esi+PCIDEV.class], 1
jz @f
mov bl, 0x14
push eax
call pci_read_reg
and eax, 0xFFFC
mov edx, eax
pop eax
@@:
DEBUGF 1, 'K : BAR1 IDE base addr %x\n', dx
mov [ecx+IDE_DATA.BAR1_val], dx
;--------------------------------------
mov dx, 0x170
test byte [esi+PCIDEV.class], 4
jz @f
mov bl, 0x18
push eax
call pci_read_reg
and eax, 0xFFFC
mov edx, eax
pop eax
@@:
DEBUGF 1, 'K : BAR2 IDE base addr %x\n', dx
mov [StandardATABases+2], dx
mov [ecx+IDE_DATA.BAR2_val], dx
;--------------------------------------
mov dx, 0x374
test byte [esi+PCIDEV.class], 4
jz @f
mov bl, 0x1C
push eax
call pci_read_reg
and eax, 0xFFFC
mov edx, eax
pop eax
@@:
DEBUGF 1, 'K : BAR3 IDE base addr %x\n', dx
mov [ecx+IDE_DATA.BAR3_val], dx
;--------------------------------------
mov bl, 0x20
push eax
call pci_read_reg
and eax, 0xFFFC
DEBUGF 1, 'K : BAR4 IDE controller register base addr %x\n', ax
mov [ecx+IDE_DATA.RegsBaseAddres], ax
pop eax
;--------------------------------------
mov bl, 0x3C
push eax
call pci_read_reg
and eax, 0xFF
DEBUGF 1, 'K : IDE Interrupt %x\n', al
mov [ecx+IDE_DATA.Interrupt], ax
pop eax
 
add ecx, sizeof.IDE_DATA
;--------------------------------------
jmp .loop
;-----------------------------------------------------------------------------
uglobal
align 4
;--------------------------------------
IDE_controller_pointer dd ?
;--------------------------------------
IDE_controller_1 IDE_DATA
IDE_controller_2 IDE_DATA
IDE_controller_3 IDE_DATA
;--------------------------------------
cache_ide0 IDE_CACHE
cache_ide1 IDE_CACHE
cache_ide2 IDE_CACHE
cache_ide3 IDE_CACHE
cache_ide4 IDE_CACHE
cache_ide5 IDE_CACHE
cache_ide6 IDE_CACHE
cache_ide7 IDE_CACHE
cache_ide8 IDE_CACHE
cache_ide9 IDE_CACHE
cache_ide10 IDE_CACHE
cache_ide11 IDE_CACHE
;--------------------------------------
IDE_device_1 rd 2
IDE_device_2 rd 2
IDE_device_3 rd 2
;--------------------------------------
endg
;-----------------------------------------------------------------------------
; START of initialisation IDE ATA code
;-----------------------------------------------------------------------------
Init_IDE_ATA_controller:
cmp [ecx+IDE_DATA.ProgrammingInterface], 0
jne @f
 
ret
;--------------------------------------
@@:
mov esi, boot_disabling_ide
call boot_log
;--------------------------------------
; Disable IDE interrupts, because the search
; for IDE partitions is in the PIO mode.
;--------------------------------------
.disable_IDE_interrupt:
; Disable interrupts in IDE controller for PIO
mov al, 2
mov dx, [ecx+IDE_DATA.BAR1_val] ;0x3F4
add dx, 2 ;0x3F6
out dx, al
mov dx, [ecx+IDE_DATA.BAR3_val] ;0x374
add dx, 2 ;0x376
out dx, al
;-----------------------------------------------------------------------------
; set current ata bases
@@:
mov ax, [ecx+IDE_DATA.BAR0_val]
mov [StandardATABases], ax
mov ax, [ecx+IDE_DATA.BAR2_val]
mov [StandardATABases+2], ax
 
mov esi, boot_detecthdcd
call boot_log
;--------------------------------------
include 'dev_hdcd.inc'
;--------------------------------------
ret
;-----------------------------------------------------------------------------
Init_IDE_ATA_controller_2:
cmp [ecx+IDE_DATA.ProgrammingInterface], 0
jne @f
 
ret
;--------------------------------------
@@:
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
; test whether it is our interrupt?
add dx, 2
in al, dx
test al, 100b
jz @f
; clear Bus Master IDE Status register
; clear Interrupt bit
out dx, al
;--------------------------------------
@@:
add dx, 8
; test whether it is our interrupt?
in al, dx
test al, 100b
jz @f
; clear Bus Master IDE Status register
; clear Interrupt bit
out dx, al
;--------------------------------------
@@:
; read status register and remove the interrupt request
mov dx, [ecx+IDE_DATA.BAR0_val] ;0x1F0
add dx, 0x7 ;0x1F7
in al, dx
mov dx, [ecx+IDE_DATA.BAR2_val] ;0x170
add dx, 0x7 ;0x177
in al, dx
;-----------------------------------------------------------------------------
; push eax edx
; mov dx, [ecx+IDE_DATA.RegsBaseAddres]
; xor eax, eax
; add dx, 2
; in al, dx
; DEBUGF 1, "K : Primary Bus Master IDE Status Register %x\n", eax
 
; add dx, 8
; in al, dx
; DEBUGF 1, "K : Secondary Bus Master IDE Status Register %x\n", eax
; pop edx eax
 
; cmp [ecx+IDE_DATA.RegsBaseAddres], 0
; setnz [ecx+IDE_DATA.dma_hdd]
;-----------------------------------------------------------------------------
; set interrupts for IDE Controller
;-----------------------------------------------------------------------------
pushfd
cli
.enable_IDE_interrupt:
mov esi, boot_enabling_ide
call boot_log
; Enable interrupts in IDE controller for DMA
xor ebx, ebx
cmp ecx, IDE_controller_2
jne @f
 
add ebx, 5
jmp .check_DRIVE_DATA
;--------------------------------------
@@:
cmp ecx, IDE_controller_3
jne .check_DRIVE_DATA
 
add ebx, 10
;--------------------------------------
.check_DRIVE_DATA:
mov al, 0
mov ah, [ebx+DRIVE_DATA+1]
test ah, 10100000b ; check for ATAPI devices
jz @f
;--------------------------------------
.ch1_pio_set_ATAPI:
DEBUGF 1, "K : IDE CH1 PIO, because ATAPI drive present\n"
jmp .ch1_pio_set_for_all
;--------------------------------------
.ch1_pio_set_no_devices:
DEBUGF 1, "K : IDE CH1 PIO because no devices\n"
jmp .ch1_pio_set_for_all
;-------------------------------------
.ch1_pio_set:
DEBUGF 1, "K : IDE CH1 PIO because device not support UDMA\n"
;-------------------------------------
.ch1_pio_set_for_all:
mov [ecx+IDE_DATA.dma_hdd_channel_1], al
jmp .ch2_check
;--------------------------------------
@@:
xor ebx, ebx
call calculate_IDE_device_values_storage
 
test ah, 1010000b
jz .ch1_pio_set_no_devices
 
test ah, 1000000b
jz @f
 
cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al
je .ch1_pio_set
 
cmp [ebx+IDE_DEVICE.UDMA_set_mode], al
je .ch1_pio_set
;--------------------------------------
@@:
test ah, 10000b
jz @f
 
add ebx, 2
 
cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al
je .ch1_pio_set
 
cmp [ebx+IDE_DEVICE.UDMA_set_mode], al
je .ch1_pio_set
;--------------------------------------
@@:
mov dx, [ecx+IDE_DATA.BAR1_val] ;0x3F4
add dx, 2 ;0x3F6
out dx, al
DEBUGF 1, "K : IDE CH1 DMA enabled\n"
mov [ecx+IDE_DATA.dma_hdd_channel_1], byte 1
;--------------------------------------
.ch2_check:
test ah, 1010b ; check for ATAPI devices
jz @f
;--------------------------------------
.ch2_pio_set_ATAPI:
DEBUGF 1, "K : IDE CH2 PIO, because ATAPI drive present\n"
jmp .ch2_pio_set_for_all
;--------------------------------------
.ch2_pio_set_no_devices:
DEBUGF 1, "K : IDE CH2 PIO because no devices\n"
jmp .ch2_pio_set_for_all
;--------------------------------------
.ch2_pio_set:
DEBUGF 1, "K : IDE CH2 PIO because device not support UDMA\n"
;--------------------------------------
.ch2_pio_set_for_all:
mov [ecx+IDE_DATA.dma_hdd_channel_2], al
jmp .set_interrupts_for_IDE_controllers
;--------------------------------------
@@:
mov ebx, 4
call calculate_IDE_device_values_storage
 
test ah, 101b
jz .ch2_pio_set_no_devices
 
test ah, 100b
jz @f
 
cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al
je .ch2_pio_set
 
cmp [ebx+IDE_DEVICE.UDMA_set_mode], al
je .ch2_pio_set
;--------------------------------------
@@:
test ah, 1b
jz @f
 
add ebx, 2
 
cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al
je .ch2_pio_set
 
cmp [ebx+IDE_DEVICE.UDMA_set_mode], al
je .ch2_pio_set
;--------------------------------------
@@:
mov dx, [ecx+IDE_DATA.BAR3_val] ;0x374
add dx, 2 ;0x376
out dx, al
DEBUGF 1, "K : IDE CH2 DMA enabled\n"
mov [ecx+IDE_DATA.dma_hdd_channel_2], byte 1
;--------------------------------------
.set_interrupts_for_IDE_controllers:
mov esi, boot_set_int_IDE
call boot_log
;--------------------------------------
mov eax, [ecx+IDE_DATA.ProgrammingInterface]
; cmp ax, 0x0180
; je .pata_ide
 
; cmp ax, 0x018a
; jne .sata_ide
 
test al, 1 ; 0 - legacy PCI mode, 1 - native PCI mode
jnz .sata_ide
;--------------------------------------
.pata_ide:
cmp [ecx+IDE_DATA.RegsBaseAddres], 0
je .end_set_interrupts
 
push ecx
stdcall attach_int_handler, 14, IDE_irq_14_handler, 0
DEBUGF 1, "K : Set IDE IRQ14 return code %x\n", eax
stdcall attach_int_handler, 15, IDE_irq_15_handler, 0
DEBUGF 1, "K : Set IDE IRQ15 return code %x\n", eax
pop ecx
 
jmp .end_set_interrupts
;--------------------------------------
.sata_ide:
; cmp ax, 0x0185
; je .sata_ide_1
 
; cmp ax, 0x018f
; jne .end_set_interrupts
;--------------------------------------
;.sata_ide_1:
; Some weird controllers generate an interrupt even if IDE interrupts
; are disabled and no IDE devices. For example, notebook ASUS K72F -
; IDE controller 010185 generates false interrupt when we work with
; the IDE controller 01018f. For this reason, the interrupt handler
; does not need to be installed if both channel IDE controller
; running in PIO mode.
cmp [ecx+IDE_DATA.RegsBaseAddres], 0
je .end_set_interrupts
 
cmp [ecx+IDE_DATA.dma_hdd_channel_1], 0
jne @f
 
cmp [ecx+IDE_DATA.dma_hdd_channel_2], 0
je .end_set_interrupts
;--------------------------------------
@@:
mov ax, [ecx+IDE_DATA.Interrupt]
movzx eax, al
push ecx
stdcall attach_int_handler, eax, IDE_common_irq_handler, 0
pop ecx
DEBUGF 1, "K : Set IDE IRQ%d return code %x\n", [ecx+IDE_DATA.Interrupt]:1, eax
;--------------------------------------
.end_set_interrupts:
popfd
ret
;-----------------------------------------------------------------------------
; END of initialisation IDE ATA code
;-----------------------------------------------------------------------------
find_IDE_controller_done:
mov ecx, IDE_controller_1
mov [IDE_controller_pointer], ecx
call Init_IDE_ATA_controller
mov ecx, IDE_controller_2
mov [IDE_controller_pointer], ecx
call Init_IDE_ATA_controller
mov ecx, IDE_controller_3
mov [IDE_controller_pointer], ecx
call Init_IDE_ATA_controller
;-----------------------------------------------------------------------------
mov esi, boot_getcache
call boot_log
include 'getcache.inc'
;-----------------------------------------------------------------------------
mov esi, boot_detectpart
call boot_log
include 'sear_par.inc'
;-----------------------------------------------------------------------------
mov esi, boot_init_sys
call boot_log
call Parser_params
 
if ~ defined extended_primary_loader
; ramdisk image should be loaded by extended primary loader if it exists
; READ RAMDISK IMAGE FROM HD
include '../boot/rdload.inc'
end if
;-----------------------------------------------------------------------------
mov ecx, IDE_controller_1
mov [IDE_controller_pointer], ecx
call Init_IDE_ATA_controller_2
mov ecx, IDE_controller_2
mov [IDE_controller_pointer], ecx
call Init_IDE_ATA_controller_2
mov ecx, IDE_controller_3
mov [IDE_controller_pointer], ecx
call Init_IDE_ATA_controller_2
;-----------------------------------------------------------------------------
/kernel/branches/Kolibri-acpi/detect/sear_par.inc
8,21 → 8,42
$Revision$
 
search_partitions:
push ecx
; 1. Fill missing parameters in HD_DATA structures.
mov eax, [hd_address_table]
mov [hd0_data.hdbase], eax ;0x1f0
xor eax, eax
mov edx, IDE_controller_1
mov ax, [edx + IDE_DATA.BAR0_val]
mov [hd0_data.hdbase], eax
mov [hd1_data.hdbase], eax
mov eax, [hd_address_table+16]
mov ax, [edx + IDE_DATA.BAR2_val]
mov [hd2_data.hdbase], eax
mov [hd3_data.hdbase], eax
 
mov edx, IDE_controller_2
mov ax, [edx + IDE_DATA.BAR0_val]
mov [hd4_data.hdbase], eax
mov [hd5_data.hdbase], eax
mov ax, [edx + IDE_DATA.BAR2_val]
mov [hd6_data.hdbase], eax
mov [hd7_data.hdbase], eax
 
mov edx, IDE_controller_3
mov ax, [edx + IDE_DATA.BAR0_val]
mov [hd8_data.hdbase], eax
mov [hd9_data.hdbase], eax
mov ax, [edx + IDE_DATA.BAR2_val]
mov [hd10_data.hdbase], eax
mov [hd11_data.hdbase], eax
; 2. Notify the system about /hd* disks.
; For every existing disk, call ide_disk_add with correct parameters.
; Generate name "hdN" on the stack; this is 4 bytes including terminating zero.
;-----------------------------------------------------------------------------
; 2a. /hd0: exists if mask 0x40 in [DRIVE_DATA+1] is set,
; data: hd0_data,
; number of partitions: [DRIVE_DATA+2]
test [DRIVE_DATA+1], byte 0x40
jz @f
 
push 'hd0'
mov eax, esp ; name
mov edx, hd0_data
29,6 → 50,7
call ide_disk_add
mov [DRIVE_DATA+2], al
pop ecx ; restore the stack
;-----------------------------------------------------------------------------
@@:
; 2b. /hd1: exists if mask 0x10 in [DRIVE_DATA+1] is set,
; data: hd1_data,
35,6 → 57,7
; number of partitions: [DRIVE_DATA+3]
test [DRIVE_DATA+1], byte 0x10
jz @f
 
push 'hd1'
mov eax, esp
mov edx, hd1_data
41,6 → 64,7
call ide_disk_add
mov [DRIVE_DATA+3], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2c. /hd2: exists if mask 4 in [DRIVE_DATA+1] is set,
; data: hd2_data,
47,6 → 71,7
; number of partitions: [DRIVE_DATA+4]
test [DRIVE_DATA+1], byte 4
jz @f
 
push 'hd2'
mov eax, esp
mov edx, hd2_data
53,6 → 78,7
call ide_disk_add
mov [DRIVE_DATA+4], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2d. /hd3: exists if mask 1 in [DRIVE_DATA+1] is set,
; data: hd3_data,
59,6 → 85,7
; number of partitions: [DRIVE_DATA+5]
test [DRIVE_DATA+1], byte 1
jz @f
 
push 'hd3'
mov eax, esp
mov edx, hd3_data
65,7 → 92,120
call ide_disk_add
mov [DRIVE_DATA+5], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2e. /hd4: exists if mask 0x40 in [DRIVE_DATA+6] is set,
; data: hd4_data,
; number of partitions: [DRIVE_DATA+7]
test [DRIVE_DATA+6], byte 0x40
jz @f
 
push 'hd4'
mov eax, esp ; name
mov edx, hd4_data
call ide_disk_add
mov [DRIVE_DATA+7], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2f. /hd5: exists if mask 0x10 in [DRIVE_DATA+6] is set,
; data: hd5_data,
; number of partitions: [DRIVE_DATA+8]
test [DRIVE_DATA+6], byte 0x10
jz @f
 
push 'hd5'
mov eax, esp
mov edx, hd5_data
call ide_disk_add
mov [DRIVE_DATA+8], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2g. /hd6: exists if mask 4 in [DRIVE_DATA+6] is set,
; data: hd6_data,
; number of partitions: [DRIVE_DATA+9]
test [DRIVE_DATA+6], byte 4
jz @f
 
push 'hd6'
mov eax, esp
mov edx, hd6_data
call ide_disk_add
mov [DRIVE_DATA+9], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2h. /hd7: exists if mask 1 in [DRIVE_DATA+6] is set,
; data: hd7_data,
; number of partitions: [DRIVE_DATA+10]
test [DRIVE_DATA+6], byte 1
jz @f
 
push 'hd7'
mov eax, esp
mov edx, hd7_data
call ide_disk_add
mov [DRIVE_DATA+10], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2i. /hd8: exists if mask 0x40 in [DRIVE_DATA+11] is set,
; data: hd8_data,
; number of partitions: [DRIVE_DATA+12]
test [DRIVE_DATA+11], byte 0x40
jz @f
 
push 'hd8'
mov eax, esp ; name
mov edx, hd8_data
call ide_disk_add
mov [DRIVE_DATA+12], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2j. /hd9: exists if mask 0x10 in [DRIVE_DATA+11] is set,
; data: hd9_data,
; number of partitions: [DRIVE_DATA+13]
test [DRIVE_DATA+11], byte 0x10
jz @f
 
push 'hd9'
mov eax, esp
mov edx, hd9_data
call ide_disk_add
mov [DRIVE_DATA+13], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2k. /hd10: exists if mask 4 in [DRIVE_DATA+11] is set,
; data: hd10_data,
; number of partitions: [DRIVE_DATA+14]
test [DRIVE_DATA+14], byte 4
jz @f
 
push 'hd10'
mov eax, esp
mov edx, hd10_data
call ide_disk_add
mov [DRIVE_DATA+9], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 2l. /hd11: exists if mask 1 in [DRIVE_DATA+11] is set,
; data: hd11_data,
; number of partitions: [DRIVE_DATA+15]
test [DRIVE_DATA+11], byte 1
jz @f
 
push 'hd11'
mov eax, esp
mov edx, hd11_data
call ide_disk_add
mov [DRIVE_DATA+15], al
pop ecx
;-----------------------------------------------------------------------------
@@:
; 3. Notify the system about /bd* disks.
; 3a. Check whether there are BIOS disks. If no, skip step 3.
xor esi, esi
115,10 → 255,10
pop ecx ecx ; restore stack after name
.nobd:
jmp end_search_partitions
 
;-----------------------------------------------------------------------------
; Helper procedure for search_partitions, adds one IDE disk.
; For compatibility, number of partitions for IDE disks is kept in a separate variable,
; so the procedure returns number of partitions.
; For compatibility, number of partitions for IDE disks is kept in a separate
; variable, so the procedure returns number of partitions.
; eax -> name, edx -> disk data
proc ide_disk_add
stdcall disk_add, ide_callbacks, eax, edx, 0
134,6 → 274,6
@@:
ret
endp
 
;-----------------------------------------------------------------------------
end_search_partitions:
 
pop ecx
/kernel/branches/Kolibri-acpi/docs/sysfuncr.txt
86,9 → 86,9
* рисуется внешняя рамка цвета, указанного в edi,
шириной 1 пиксель
* рисуется заголовок - прямоугольник с левым верхним углом (1,1)
и правым нижним (xsize-1,min(25,ysize)) цвета, указанного в esi
и правым нижним (xsize-1,min(20,ysize-1)) цвета, указанного в esi
(с учетом градиента)
* если ysize>=26, то закрашивается рабочая область окна -
* если ysize>21, то закрашивается рабочая область окна -
прямоугольник с левым верхним углом (1,21) и правым нижним
(xsize-1,ysize-1) (размерами (xsize-1)*(ysize-21)) - цветом,
указанным в edx (с учетом градиента)
151,7 → 151,9
Возвращаемое значение:
* если буфер пуст, возвращается eax=1
* если буфер непуст, то возвращается al=0, ah=код нажатой клавиши,
старшее слово регистра eax обнулено
биты 16-23 содержат сканкод нажатой клавиши в режиме ASCII,
в режме сканкодов биты обнулены.
биты 23-31 обнулены
* если есть "горячая клавиша", то возвращается
al=2, ah=сканкод нажатой клавиши (0 для управляющих клавиш),
старшее слово регистра eax содержит состояние управляющих клавиш
816,9 → 818,9
вызове, оно может измениться в последующих версиях ядра.
 
======================================================================
======== Функция 18, подфункция 10 - свернуть окно приложения. =======
========= Функция 18, подфункция 10 - свернуть активное окно. ========
======================================================================
Сворачивает собственное окно.
Сворачивает активное окно.
Параметры:
* eax = 18 - номер функции
* ebx = 10 - номер подфункции
843,8 → 845,7
* eax = 18 - номер функции
* ebx = 11 - номер подфункции
* ecx = тип таблицы:
* 1 = короткая версия, 10 байт
* 2 = полная версия, 65536 байт
* 1 = короткая версия, 16 байт
* edx = указатель на буфер (в приложении) для таблицы
Возвращаемое значение:
* функция не возвращает значения
861,6 → 862,8
Например, для стандартной конфигурации из одного 1.44-дисковода
здесь будет 40h, а для случая 1.2Mb на A: и 1.44Mb на B:
значение оказывается 24h.
 
Первый контроллер IDE:
* +1: byte: информация о жёстких дисках и CD-приводах, AABBCCDD,
где AA соответствует контроллеру IDE0, ..., DD - IDE3:
* 0 = устройство отсутствует
869,31 → 872,36
Например, в случае HD на IDE0 и CD на IDE2 здесь будет 48h.
* +2: 4 db: число найденных разделов на жёстких дисках с
соответственно IDE0,...,IDE3.
 
Второй контроллер IDE:
* +6: byte: информация о жёстких дисках и CD-приводах, AABBCCDD
где AA соответствует контроллеру IDE4, ..., DD - IDE7:
* 0 = устройство отсутствует
* 1 = жёсткий диск
* 2 = CD-привод
Например, в случае HD на IDE4 и CD на IDE6 здесь будет 48h.
* +7: 4 db: число найденных разделов на жёстких дисках с
соответственно IDE4,...,IDE7.
 
Третий контроллер IDE:
* +11: byte: информация о жёстких дисках и CD-приводах, AABBCCDD
где AA соответствует контроллеру IDE8, ..., DD - IDE11:
* 0 = устройство отсутствует
* 1 = жёсткий диск
* 2 = CD-привод
Например, в случае HD на IDE8 и CD на IDE10 здесь будет 48h.
* +12: 4 db: число найденных разделов на жёстких дисках с
соответственно IDE8,...,IDE11.
 
При отсутствии жёсткого диска на IDEx соответствующий байт
нулевой, при наличии показывает число распознанных разделов,
которых может и не быть (если носитель не отформатирован или
если файловая система не поддерживается). В текущей версии ядра
для жёстких дисков поддерживаются только FAT16, FAT32 и NTFS.
* +6: 4 db: зарезервировано
Формат таблицы: полная версия:
* +0: 10 db: такие же, как и в короткой версии
* +10: 100 db: данные для первого раздела
* +110: 100 db: данные для второго раздела
* ...
* +10+100*(n-1): 100 db: данные для последнего раздела
Разделы расположены в следующем порядке: сначала последовательно все
распознанные разделы на HD на IDE0 (если есть),
затем на HD на IDE1 (если есть) и т.д. до IDE3.
Формат информации о разделе:
* +0: dword: начальный физический сектор раздела
* +4: dword: последний физический сектор раздела
(принадлежит разделу)
* +8: byte: тип файловой системы:
16=FAT16, 32=FAT32, 1=NTFS
* формат дальнейших данных зависит от файловой системы,
может меняться с изменениями в ядре и поэтому не описывается
для жёстких дисков поддерживаются только FAT12/16/32, NTFS,
ext2/3/4 и XFS.
 
Замечания:
* Короткая таблица может быть использована для получения информации
* Таблица может быть использована для получения информации
об имеющихся устройствах.
 
======================================================================
1209,20 → 1217,6
* Приложение @panel переключает раскладки по запросу пользователя.
 
======================================================================
=========== Функция 21, подфункция 3 - установить базу CD. ===========
======================================================================
Параметры:
* eax = 21 - номер функции
* ebx = 3 - номер подфункции
* ecx = база CD: 1=IDE0, 2=IDE1, 3=IDE2, 4=IDE3
Возвращаемое значение:
* eax = 0
Замечания:
* База CD используется функцией 24.
* Получить установленную базу CD можно вызовом
подфункции 3 функции 26.
 
======================================================================
========= Функция 21, подфункция 5 - установить язык системы. ========
======================================================================
Параметры:
1240,52 → 1234,6
* Получить язык системы можно вызовом подфункции 5 функции 26.
 
======================================================================
=========== Функция 21, подфункция 7 - установить базу HD. ===========
======================================================================
База HD нужна для определения, на какой жёсткий диск писать, при
использовании устаревшего синтаксиса /HD в устаревшей функции 58;
при использовании современного синтаксиса /HD0,/HD1,/HD2,/HD3
база устанавливается автоматически.
Параметры:
* eax = 21 - номер функции
* ebx = 7 - номер подфункции
* ecx = база HD: 1=IDE0, 2=IDE1, 3=IDE2, 4=IDE3
Возвращаемое значение:
* eax = 0
Замечания:
* Любое приложение в любой момент времени может изменить базу.
* Не следует изменять базу, когда какое-нибудь приложение работает
с жёстким диском. Если не хотите глюков системы.
* Получить установленную базу можно вызовом подфункции 7 функции 26.
* Следует также определить используемый раздел жёсткого диска
подфункцией 8.
 
======================================================================
========== Функция 21, подфункция 8 - установить раздел HD. ==========
======================================================================
Раздел HD нужен для определения, на какой раздел жёсткого диска
писать, при использовании устаревшего синтаксиса /HD в устаревшей
функции 58; при использовании современного синтаксиса
/HD0,/HD1,/HD2,/HD3 база и раздел устанавливаются автоматически.
Параметры:
* eax = 21 - номер функции
* ebx = 8 - номер подфункции
* ecx = раздел HD (считая с 1)
Возвращаемое значение:
* eax = 0
Замечания:
* Любое приложение в любой момент времени может изменить раздел.
* Не следует изменять раздел, когда какое-нибудь приложение работает
с жёстким диском. Если не хотите глюков системы.
* Получить установленный раздел можно вызовом подфункции 8
функции 26.
* Проверок на корректность не делается.
* Узнать число разделов на жёстком диске можно вызовом
подфункции 11 функции 18.
* Следует также определить используемую базу жёсткого диска
подфункцией 7.
 
======================================================================
====================== Функция 21, подфункция 11 =====================
=========== Разрешить/запретить низкоуровневый доступ к HD. ==========
======================================================================
1316,122 → 1264,6
* Получить текущее состояние можно вызовом подфункции 12 функции 26.
 
======================================================================
============= Функция 21, подфункция 13, подподфункция 1 =============
==== Инициализировать + получить информацию о драйвере vmode.mdr. ====
======================================================================
Параметры:
* eax = 21 - номер функции
* ebx = 13 - номер подфункции
* ecx = 1 - номер функции драйвера
* edx = указатель на буфер размера 512 байт
Возвращаемое значение:
* если драйвер не загружен (никогда не бывает в текущей реализации):
* eax = -1
* ebx, ecx разрушаются
* если драйвер загружен:
* eax = 'MDAZ' (в стиле fasm'а, т.е. 'M' - младший байт,
'Z' - старший) - сигнатура
* ebx = текущая частота развёртки (в Гц)
* ecx разрушается
* буфер, на который указывает edx, заполнен
Формат буфера:
* +0: 32*byte: имя драйвера, "Trans VideoDriver" (без кавычек,
дополнено пробелами)
* +32 = +0x20: dword: версия драйвера (версия x.y кодируется как
y*65536+x), для текущей реализации 1 (1.0)
* +36 = +0x24: 7*dword: зарезервировано (0 в текущей реализации)
* +64 = +0x40: 32*word: список поддерживаемых видеорежимов (каждое
слово - номер видеорежима, после собственно списка идут нули)
* +128 = +0x80: 32*(5*word): список поддерживаемых частот развёрток
для видеорежимов: для каждого видеорежима, указанного в предыдущем
поле, указано до 5 поддерживаемых частот
(в неиспользуемых позициях записаны нули)
Замечания:
* Функция инициализирует драйвер (если он ещё не инициализирован)
и должна вызываться первой, перед остальными (иначе они будут
возвращать -1, ничего не делая).
* В текущей реализации поддерживается только одна частота развёртки
на видеорежим.
 
======================================================================
============= Функция 21, подфункция 13, подподфункция 2 =============
============= Получить информацию о текущем видеорежиме. =============
======================================================================
Параметры:
* eax = 21 - номер функции
* ebx = 13 - номер подфункции
* ecx = 2 - номер функции драйвера
Возвращаемое значение:
* eax = -1 - драйвер не загружен или не инициализирован;
ebx,ecx разрушаются
* eax = [ширина]*65536 + [высота]
* ebx = частота вертикальной развёртки (в Гц)
* ecx = номер текущего видеорежима
Замечания:
* Драйвер предварительно должен быть инициализирован вызовом
функции драйвера 1.
* Если нужны только размеры экрана, целесообразней использовать
функцию 14 с учётом того, что она возвращает размеры на 1 меньше.
 
======================================================================
= Функция 21, подфункция 13, подподфункция 3 - установить видеорежим.
======================================================================
Параметры:
* eax = 21 - номер функции
* ebx = 13 - номер подфункции
* ecx = 3 - номер функции драйвера
* edx = [частота развёртки]*65536 + [номер видеорежима]
Возвращаемое значение:
* eax = -1 - драйвер не загружен, не инициализирован или
произошла ошибка
* eax = 0 - успешно
* ebx, ecx разрушаются
Замечания:
* Драйвер предварительно должен быть инициализирован вызовом
функции драйвера 1.
* Номер видеорежима и частота должны быть в таблице, возвращаемой
функцией драйвера 1.
 
======================================================================
============= Функция 21, подфункция 13, подподфункция 4 =============
================= Вернуться к начальному видеорежиму. ================
======================================================================
Возвращает экран в видеорежим, установленный при загрузке системы.
Параметры:
* eax = 21 - номер функции
* ebx = 13 - номер подфункции
* ecx = 4 - номер функции драйвера
Возвращаемое значение:
* eax = -1 - драйвер не загружен или не инициализирован
* eax = 0 - успешно
* ebx, ecx разрушаются
Замечания:
* Драйвер предварительно должен быть инициализирован вызовом
функции драйвера 1.
 
======================================================================
============= Функция 21, подфункция 13, подподфункция 5 =============
======== Увеличить/уменьшить размер видимой области монитора. ========
======================================================================
Параметры:
* eax = 21 - номер функции
* ebx = 13 - номер подфункции
* ecx = 5 - номер функции драйвера
* edx = 0/1 - уменьшить/увеличить размер по горизонтали
на одну позицию
* edx = 2/3 - в текущей реализации не поддерживается; планируется
как уменьшение/увеличение размера по вертикали на одну позицию
Возвращаемое значение:
* eax = -1 - драйвер не загружен или не инициализирован
* eax = 0 - успешно
* ebx, ecx разрушаются
Замечания:
* Драйвер предварительно должен быть инициализирован вызовом
функции драйвера 1.
* Функция влияет только на физический размер изображения
на мониторе; логический размер (число пикселей) не меняется.
 
======================================================================
============ Функция 22 - установить системную дату/время. ===========
======================================================================
Параметры:
1494,59 → 1326,6
вызовет 32-битное переполнение.
 
======================================================================
======= Функция 24, подфункция 1 - начать проигрывать CD-audio. ======
======================================================================
Параметры:
* eax = 24 - номер функции
* ebx = 1 - номер подфункции
* ecx = 0x00FRSSMM, где
* MM = начальная минута
* SS = начальная секунда
* FR = начальный фрейм
Возвращаемое значение:
* eax = 0 - успешно
* eax = 1 - не определена база CD
Замечания:
* Предварительно нужно определить базовый порт CD вызовом
подфункции 3 функции 21.
* В секунде 75 фреймов, в минуте 60 секунд.
* Функция асинхронна (возвращает управление, когда началось
проигрывание).
 
======================================================================
===== Функция 24, подфункция 2 - получить информацию о дорожках. =====
======================================================================
Параметры:
* eax = 24 - номер функции
* ebx = 2 - номер подфункции
* ecx = указатель на буфер для таблицы
(максимум 8*64h+4 байт=100 дорожек)
Возвращаемое значение:
* eax = 0 - успешно
* eax = 1 - не определена база CD
Замечания:
* Формат таблицы с информацией о дорожках такой же, как и для
ATAPI-CD команды 43h (READ TOC), обычной таблицы (подкоманда 00h).
Адреса возвращаются в формате MSF.
* Предварительно нужно определить базовый порт CD вызовом
подфункции 3 функции 21.
* Функция возвращает информацию только о не более чем 100
первых дорожках. В большинстве случаев этого достаточно.
 
======================================================================
==== Функция 24, подфункция 3 - остановить проигрываемое CD-audio. ===
======================================================================
Параметры:
* eax = 24 - номер функции
* ebx = 1 - номер подфункции
Возвращаемое значение:
* eax = 0 - успешно
* eax = 1 - не определена база CD
Замечания:
* Предварительно нужно определить базовый порт CD вызовом
подфункции 3 функции 21.
 
======================================================================
======= Функция 24, подфункция 4 - извлечь лоток привода диска. ======
======================================================================
Параметры:
1553,7 → 1332,9
* eax = 24 - номер функции
* ebx = 4 - номер подфункции
* ecx = номер CD/DVD-диска
(от 0=Primary Master до 3=Secondary Slave)
от 0=Primary Master до 3=Secondary Slave для первого IDE контр.
от 4=Primary Master до 7=Secondary Slave для второго IDE контр.
от 8=Primary Master до 11=Secondary Slave для третьего IDE контр.
Возвращаемое значение:
* функция не возвращает значения
Замечания:
1571,7 → 1352,9
* eax = 24 - номер функции
* ebx = 5 - номер подфункции
* ecx = номер CD/DVD-диска
(от 0=Primary Master до 3=Secondary Slave)
от 0=Primary Master до 3=Secondary Slave для первого IDE контр.
от 4=Primary Master до 7=Secondary Slave для второго IDE контр.
от 8=Primary Master до 11=Secondary Slave для третьего IDE контр.
Возвращаемое значение:
* функция не возвращает значения
Замечания:
1649,18 → 1432,6
* Приложение @panel переключает раскладки по запросу пользователя.
 
======================================================================
============ Функция 26, подфункция 3 - получить базу CD. ============
======================================================================
Параметры:
* eax = 26 - номер функции
* ebx = 3 - номер подфункции
Возвращаемое значение:
* eax = база CD: 1=IDE0, 2=IDE1, 3=IDE2, 4=IDE3
Замечания:
* База CD используется функцией 24.
* Установить базу CD можно вызовом подфункции 3 функции 21.
 
======================================================================
========== Функция 26, подфункция 5 - получить язык системы. =========
======================================================================
Параметры:
1675,42 → 1446,6
* Установить язык системы можно вызовом подфункции 5 функции 21.
 
======================================================================
============ Функция 26, подфункция 7 - получить базу HD. ============
======================================================================
База HD нужна для определения, на какой жёсткий диск писать, при
использовании устаревшего синтаксиса /HD в устаревшей функции 58;
при использовании современного синтаксиса /HD0,/HD1,/HD2,/HD3
база устанавливается автоматически.
Параметры:
* eax = 26 - номер функции
* ebx = 7 - номер подфункции
Возвращаемое значение:
* eax = база HD: 1=IDE0, 2=IDE1, 3=IDE2, 4=IDE3
Замечания:
* Любое приложение в любой момент времени может изменить базу.
* Установить базу можно вызовом подфункции 7 функции 21.
* Получить используемый раздел жёсткого диска можно подфункцией 8.
 
======================================================================
=========== Функция 26, подфункция 8 - получить раздел HD. ===========
======================================================================
Раздел HD нужен для определения, на какой раздел жёсткого диска
писать, при использовании устаревшего синтаксиса /HD в устаревшей
функции 58; при использовании современного синтаксиса
/HD0,/HD1,/HD2,/HD3 база и раздел устанавливаются автоматически.
Параметры:
* eax = 26 - номер функции
* ebx = 8 - номер подфункции
Возвращаемое значение:
* eax = раздел HD (считая с 1)
Замечания:
* Любое приложение в любой момент времени может изменить раздел.
* Установить раздел можно вызовом подфункции 8 функции 21.
* Узнать число разделов на жёстком диске можно вызовом
подфункции 11 функции 18.
* Получить используемую базу жёсткого диска можно подфункцией 7.
 
======================================================================
=== Функция 26, подфункция 9 - получить значение счётчика времени. ===
======================================================================
Параметры:
2544,221 → 2279,6
эмулируется (через аналоги подфункций функции 62 режима ядра).
 
======================================================================
============== Функция 58 - работа с файловой системой. ==============
======================================================================
Параметры:
* eax = 58
* ebx = указатель на информационную структуру
Возвращаемое значение:
* eax = 0 - успешно; иначе код ошибки файловой системы
* в зависимости от подфункции может возвращаться значение и
в других регистрах
Общий формат информационной структуры:
* +0: dword: номер подфункции
* +4: dword: номер блока
* +8: dword: размер
* +12 = +0xC: dword: указатель на данные
* +16 = +0x10: dword: указатель на память для работы системы
(4096 байт)
* +20 = +0x14: n db: ASCIIZ-строка с именем файла
Уточнения - в документации на соответствующую подфункцию.
Имя файла нечувствительно к регистру латинских букв,
русские буквы должны быть заглавными.
Формат имени файла:
/base/number/dir1/dir2/.../dirn/file,
где /base/number идентифицирует устройство, на котором ищется файл:
одно из
* /RD/1 = /RAMDISK/1 для доступа к рамдиску
* /FD/1 = /FLOPPYDISK/1 для доступа к первому флоппи-дисководу,
/FD/2 = /FLOPPYDISK/2 для второго флоппи-дисковода
* /HD/x = /HARDDISK/x - устаревший вариант доступа к жёсткому диску
(в этом случае база определяется подфункцией 7 функции 21),
x - номер раздела (считая с 1)
* /HD0/x, /HD1/x, /HD2/x, /HD3/x для доступа соответственно
к устройствам IDE0 (Primary Master), IDE1 (Primary Slave),
IDE2 (Secondary Master), IDE3 (Secondary Slave);
x - номер раздела на выбранном винчестере, изменяется от 1 до 255
(на каждом из винчестеров нумерация начинается с 1)
Замечания:
* В первых двух случаях допускается использование FIRST вместо 1,
SECOND вместо 2, но использовать эту возможность
не рекомендуется для удобства перехода на будущие расширения.
* Накладывается ограничение n<=39.
* Имена папок и файла dir1,...,dirn,file должны быть в формате 8.3:
имя не более 8 символов, точка, расширение не более 3 символов.
Хвостовые пробелы игнорируются. Других пробелов быть не должно.
Если имя занимает ровно 8 символов, точку можно опустить
(хотя пользоваться этим не рекомендуется для удобства перехода
на будущие расширения).
* Функция не поддерживает папок на рамдиске.
Примеры:
* '/RAMDISK/FIRST/KERNEL.ASM',0
'/rd/1/kernel.asm',0
* '/HD0/1/kernel.asm',0
* '/hd0/1/menuet/pics/tanzania.bmp',0
Доступные подфункции:
* подфункция 0 - чтение файла/папки
* подфункция 8 - LBA-чтение с устройства
* подфункция 15 - получение информации о файловой системе
 
======================================================================
========== Функция 58, подфункция 0 - прочитать файл/папку. ==========
======================================================================
Параметры:
* eax = 58
* ebx = указатель на информационную структуру
Формат информационной структуры:
* +0: dword: 0 = номер подфункции
* +4: dword: номер блока для чтения (считая с 0)
* +8: dword: число блоков для чтения
* +12 = +0xC: dword: указатель на буфер, куда будут записаны данные
* +16 = +0x10: dword: указатель на буфер для работы системы
(4096 байт)
* +20 = +0x14: ASCIIZ-имя файла, правила формирования имён указаны в
общем описании
Возвращаемое значение:
* eax = 0 - успешно, иначе код ошибки файловой системы
* ebx = размер файла (в байтах) или
-1=0xffffffff, если файл не найден
Замечания:
* Размер блока - 512 байт.
* Эта функция устарела, для чтения файлов используйте подфункцию 0
функции 70, для чтения папок - подфункцию 1 функции 70.
* Функция позволяет читать содержимое папки. Из файловых систем
поддерживается только FAT. Формат FAT-папки описан в любой
документации по FAT.
* Размер папки определяется по размеру цепочки кластеров в FAT.
* Если файл кончился раньше, чем был прочитан последний запрошенный
блок, то функция прочитает, сколько сможет, после чего вернёт
eax=6 (EOF).
* Функция позволяет читать корневые папки /rd/1,/fd/x,/hd[n]/x, но
в первых двух случаях текущая реализация не следует
установленным правилам:
для /rd/1:
* если указано 0 блоков для чтения, считается,
что запрашивается 1;
* если запрашивается больше 14 блоков или начальный блок
не меньше 14-го, то возвращается eax=5 (not found) и ebx=-1;
* размер корневого каталога рамдиска = 14 блоков,
0x1C00=7168 байт; но возвращается ebx=0
(за исключением случая предыдущего пункта);
* как ни странно, можно прочитать 14-й блок (там, вообще говоря,
мусор - напоминаю, счёт ведётся с 0);
* если был запрошен хотя бы один блок с номером, не меньшим 14,
то возвращается eax=6(EOF); иначе eax=0.
Для /fd/x:
* если начальный блок не меньше 14-го, то возвращается
eax=5 (not found) и ebx=0;
* кстати говоря, формат FAT12 допускает дискеты с размером
корневого каталога меньше или больше 14 блоков;
* проверки длины не делается;
* если удалось прочитать данные с дискеты, возвращается
eax=0,ebx=0; в противном случае eax=10 (access denied), ebx=-1.
* Функция обрабатывает чтение специальных папок /,/rd,/fd,/hd[n];
но результат не соответствует ожидаемому
(по работе с обычными файлами/папками), не следует установленным
правилам, может измениться в следующих версиях ядра и потому
не описывается. Для получения информации об оборудовании
используйте подфункцию 11 функции 18 или
читайте соответствующие папки подфункцией 1 функции 70.
 
======================================================================
========= Функция 58, подфункция 8 - LBA-чтение с устройства. ========
======================================================================
Параметры:
* eax = 58 - номер функции
* ebx = указатель на информационную структуру
Формат информационной структуры:
* +0: dword: 8 = номер подфункции
* +4: dword: номер блока для чтения (считая с 0)
* +8: dword: игнорируется (устанавливайте в 1)
* +12 = +0xC: dword: указатель на буфер, куда будут записаны данные
(512 байт)
* +16 = +0x10: dword: указатель на буфер для работы системы
(4096 байт)
* +20 = +0x14: ASCIIZ-имя устройства: нечувствительно к регистру,
одно из /rd/1 = /RamDisk/1, /hd/n = /HardDisk/n,
1<=n<=4 - номер устройства: 1=IDE0, ..., 4=IDE3.
Вместо цифр допускается, хотя и не рекомендуется для удобства
перехода на будущие расширения,
использование 'first','second','third','fourth'.
Возвращаемое значение:
* если указано имя устройства /hd/xxx, где xxx не находится
в списке выше:
* eax = ebx = 1
* если указано неправильное имя устройства
(за исключением предыдущего случая):
* eax = 5
* ebx не меняется
* если LBA-доступ запрещён подфункцией 11 функции 21:
* eax = 2
* ebx разрушается
* для рамдиска: попытка чтения блока за пределами рамдиска
(18*2*80 блоков) приводит к
* eax = 3
* ebx = 0
* при успешном чтении:
* eax = ebx = 0
Замечания:
* Размер блока - 512 байт; читается один блок.
* Не следует полагаться на возвращаемое значение,
оно может измениться в следующих версиях.
* Требуется, чтобы был разрешён LBA-доступ к устройствам
подфункцией 11 функции 21. Узнать это можно вызовом
подфункцией 11 функции 26.
* LBA-чтение дискеты не поддерживается.
* Функция считывает данные физического жёсткого диска;
если по каким-то причинам нужны данные конкретного раздела,
придётся определять начальный сектор этого раздела
(либо напрямую через MBR, либо из расширенной структуры,
возвращаемой той же подфункцией 11 функции 18).
* Функция не проверяет код ошибки жёсткого диска, так что запрос
несуществующего сектора всё равно что-то прочитает
(вероятнее всего, нули, но это определяется устройством) и
это будет считаться успехом (eax=0).
 
======================================================================
= Функция 58, подфункция 15 - получить информацию о файловой системе.
======================================================================
Параметры:
* eax = 58 - номер функции
* ebx = указатель на информационную структуру
Формат информационной структуры:
* +0: dword: 15 = номер подфункции
* +4: dword: игнорируется
* +8: dword: игнорируется
* +12 = +0xC: dword: игнорируется
* +16 = +0x10: dword: игнорируется
* +20 = +0x14: (проверяется только второй символ, сразу после слэша)
/rd=/RAMDISK или /hd=/HARDDISK
Возвращаемое значение:
* если второй символ не принадлежит множеству {'r','R','h','H'}:
* eax = 3
* ebx = ecx = dword [fileinfo] = 0
* для рамдиска:
* eax = 0 (успех)
* ebx = общее число кластеров = 2847
* ecx = число свободных кластеров
* dword [fileinfo] = размер кластера = 512
* для жёсткого диска: база и раздел определяются подфункциями 7 и 8
функции 21:
* eax = 0 (успех)
* ebx = общее число кластеров
* ecx = число свободных кластеров
* dword [fileinfo] = размер кластера (в байтах)
Замечания:
* Не удивляйтесь странному расположению 4-го возвращаемого
параметра - когда писался этот код, при системных вызовах
приложению возвращались только регистры eax,ebx,ecx (из
pushad-структуры, передающейся как аргумент системной функции).
Теперь это исправлено, так что, возможно, имеет смысл возвращать
размер кластера в edx, пока эту функцию не начали использовать.
* Вообще-то ещё существует подфункция 11 функции 18, возвращающая
информацию о файловой системе. По расширенной таблице дисковой
подсистемы можно определить размер кластера (там он хранится
в секторах) и общее число кластеров для жёстких дисков.
 
======================================================================
=========== Функция 60 - Inter Process Communication (IPC). ==========
======================================================================
IPC применяется для посылок сообщений от одного процесса/потока
4544,13 → 4064,7
Возвращаемое значение:
* eax = socketnum1, -1 для ошибки
* ebx = socketnum2, код ошибки в случае ошибки
Замечания:
 
Optstruct: dd level
dd optionname
dd optlength
db options...
 
======================================================================
========== Функция -1 - завершить выполнение потока/процесса =========
======================================================================
/kernel/branches/Kolibri-acpi/docs/sysfuncs.txt
82,9 → 82,9
* The window of type I looks as follows:
* draw external frame of color indicated in edi, 1 pixel in width
* draw header - rectangle with the left upper corner (1,1) and
right lower (xsize-1,min(25,ysize)) color indicated in esi
right lower (xsize-1,min(20,ysize-1)) color indicated in esi
(taking a gradient into account)
* if ysize>=26, fill the working area of the window -
* if ysize>21, fill the working area of the window -
rectangle with the left upper corner (1,21) and right lower
(xsize-1,ysize-1) (sizes (xsize-1)*(ysize-21)) with color
indicated in edx (taking a gradient into account)
148,7 → 148,10
Returned value:
* if the buffer is empty, function returns eax=1
* if the buffer is not empty, function returns al=0,
ah=code of the pressed key, high word of eax is zero
ah=code of the pressed key,
bits 16-23 = contain scancode for pressed key in ASCII mode,
in the scancodes mode this bits cleared.
bits 23-31 = zero
* if there is "hotkey", function returns al=2,
ah=scancode of the pressed key (0 for control keys),
high word of eax contains a status of control keys at the moment
815,9 → 818,9
changed in future versions of the kernel.
 
======================================================================
===== Function 18, subfunction 10 - minimize application window. =====
======= Function 18, subfunction 10 - minimize topmost window. =======
======================================================================
Minimizes the own window.
Minimizes the topmost (active) window.
Parameters:
* eax = 18 - function number
* ebx = 10 - subfunction number
828,8 → 831,8
keeps position and sizes.
* Restoring of an application window occurs at its activation by
subfunction 3.
* Usually there is no necessity to minimize/restire a window
obviously: minimization of a window is carried out by the system
* Usually there is no necessity to minimize/restore a window
explicitly: minimization of a window is carried out by the system
at pressing the minimization button (for skinned windows
it is defined automatically by function 0,
for other windows it can be defined manually by function 8),
842,8 → 845,7
* eax = 18 - function number
* ebx = 11 - subfunction number
* ecx = type of the table:
* 1 = short version, 10 bytes
* 2 = full version, 65536 bytes
* 1 = short version, 16 bytes
* edx = pointer to the buffer (in the application) for the table
Returned value:
* function does not return value
860,9 → 862,11
For example, for the standard configuration from one 1.44-drive
here will be 40h, and for the case 1.2Mb on A: and 1.44Mb on B:
the value is 24h.
First IDE controller:
* +1: byte: information about hard disks and CD-drives, AABBCCDD,
where AA corresponds to the controller IDE0, ..., DD - IDE3:
* 0 = device is absent
* 0 = device not found
* 1 = hard drive
* 2 = CD-drive
For example, in the case HD on IDE0 and CD on IDE2
869,32 → 873,37
this field contains 48h.
* +2: 4 db: number of the retrieved partitions on hard disks
at accordingly IDE0,...,IDE3.
Second IDE controller:
* +6: byte: information about hard disks and CD-drives, AABBCCDD,
where AA corresponds to the controller IDE4, ..., DD - IDE7:
* 0 = device not found
* 1 = hard drive
* 2 = CD-drive
For example, in the case HD on IDE4 and CD on IDE6
this field contains 48h.
* +7: 4 db: number of the retrieved partitions on hard disks
at accordingly IDE4,...,IDE7.
 
Third IDE controller:
* +11: byte: information about hard disks and CD-drives, AABBCCDD,
where AA corresponds to the controller IDE8, ..., DD - IDE11:
* 0 = device not found
* 1 = hard drive
* 2 = CD-drive
For example, in the case HD on IDE8 and CD on IDE10
this field contains 48h.
* +12: 4 db: number of the retrieved partitions on hard disks
at accordingly IDE8,...,IDE11.
If the hard disk on IDEx is absent, appropriate byte is zero,
otherwise it shows number of the recognized partitions, which
can be not presented (if the drive is not formatted or if
the file system is not supported). Current version of the kernel
supports only FAT16, FAT32 and NTFS for hard disks.
* +6: 4 db: reserved
Format of the table: full version:
* +0: 10 db: same as for the short version
* +10: 100 db: data for the first partition
* +110: 100 db: data for the second partition
* ...
* +10+100*(n-1): 100 db: data for the last partition
The partitions are located as follows: at first sequentially all
recoginzed partitions on HD on IDE0 (if present),
then on HD on IDE1 (if present) and so on up to IDE3.
Format of the information about partition
(at moment only FAT is supported):
* +0: dword: first physical sector of the partition
* +4: dword: last physical sector of the partition
(belongs to the partition)
* +8: byte: file system type:
16=FAT16, 32=FAT32, 1=NTFS
* other data are dependent on file system, are modified with
kernel modifications and therefore are not described
supports only FAT12/16/32, NTFS, ext2/3/4 and XFS for hard disks.
 
Remarks:
* The short table can be used for obtaining the information about
* The table can be used for obtaining the information about
available devices.
 
======================================================================
1209,19 → 1218,6
* The application @panel switches layouts on user request.
 
======================================================================
============== Function 21, subfunction 3 - set CD base. =============
======================================================================
Parameters:
* eax = 21 - function number
* ebx = 3 - subfunction number
* ecx = CD base: 1=IDE0, 2=IDE1, 3=IDE2, 4=IDE3
Returned value:
* eax = 0
Remarks:
* CD base is used by function 24.
* To get CD base use subfunction 3 of function 26.
 
======================================================================
========== Function 21, subfunction 5 - set system language. =========
======================================================================
Parameters:
1239,49 → 1235,6
* To get system language use subfunction 5 of function 26.
 
======================================================================
============== Function 21, subfunction 7 - set HD base. =============
======================================================================
The HD base defines hard disk to write with usage of obsolete
syntax /HD in obsolete function 58; at usage of modern syntax
/HD0,/HD1,/HD2,/HD3 base is set automatically.
Parameters:
* eax = 21 - function number
* ebx = 7 - subfunction number
* ecx = HD base: 1=IDE0, 2=IDE1, 3=IDE2, 4=IDE3
Returned value:
* eax = 0
Remarks:
* Any application at any time can change the base.
* Do not change base, when any application works with hard disk.
If you do not want system bugs.
* To get HD base use subfunction 7 of function 26.
* It is also necessary to define used partition of hard disk by
subfunction 8.
 
======================================================================
========= Function 21, subfunction 8 - set used HD partition. ========
======================================================================
The HD partition defines partition of the hard disk to write with
usage of obsolete syntax /HD and obsolete function 58;
at usage of functions 58 and 70 and modern syntax /HD0,/HD1,/HD2,/HD3
base and partition are set automatically.
Parameters:
* eax = 21 - function number
* ebx = 8 - subfunction number
* ecx = HD partition (beginning from 1)
Return value:
* eax = 0
Remarks:
* Any application at any time can change partition.
* Do not change partition when any application works with hard disk.
If you do not want system bugs.
* To get used partition use subfunction 8 of function 26.
* There is no correctness checks.
* To get the number of partitions of a hard disk use
subfunction 11 of function 18.
* It is also necessary to define used HD base by subfunction 7.
 
======================================================================
Function 21, subfunction 11 - enable/disable low-level access to HD.
======================================================================
Parameters:
1310,120 → 1263,6
* To get current status use subfunction 12 of function 26.
 
======================================================================
============ Function 21, subfunction 13, subsubfunction 1 ===========
======== Initialize + get information on the driver vmode.mdr. =======
======================================================================
Parameters:
* eax = 21 - function number
* ebx = 13 - subfunction number
* ecx = 1 - number of the driver function
* edx = pointer to 512-bytes buffer
Returned value:
* if driver is not loaded
(never happens in the current implementation):
* eax = -1
* ebx, ecx destroyed
* if driver is loaded:
* eax = 'MDAZ' (in fasm style, that is 'M' - low byte, 'Z' - high)
- signature
* ebx = current frequency of the scanning (in Hz)
* ecx destroyed
* buffer pointed to by edx is filled
Format of the buffer:
* +0: 32*byte: driver name, "Trans VideoDriver"
(without quotes, supplemented by spaces)
* +32 = +0x20: dword: driver version (version x.y is encoded as
y*65536+x), for the current implementation is 1 (1.0)
* +36 = +0x24: 7*dword: reserved (0 in the current implementation)
* +64 = +0x40: 32*word: list of supported videomodes (each word
is number of a videomode, after list itself there are zeroes)
* +128 = +0x80: 32*(5*word): list of supported frequences of the
scannings for videomodes: for each videomode listed in the
previous field up to 5 supported frequences are given
(unused positions contain zeroes)
Remarks:
* Function initializes the driver (if it is not initialized yet)
and must be called first, before others (otherwise they will do
nothing and return -1).
* The current implementation supports only one frequency
of the scanning on videomode.
 
======================================================================
============ Function 21, subfunction 13, subsubfunction 2 ===========
================ Get information on current videomode. ===============
======================================================================
Parameters:
* eax = 21 - function number
* ebx = 13 - subfunction number
* ecx = 2 - number of the driver function
Returned value:
* eax = -1 - driver is not loaded or not initialized;
ebx,ecx are destroyed
* eax = [width]*65536 + [height]
* ebx = frequency of the vertical scanning (in Hz)
* ecx = number of current videomode
Remarks:
* Driver must be initialized by call to
driver function 1.
* If only screen sizes are required, it is more expedient to use
function 14 taking into account that it
returns sizes on 1 less.
 
======================================================================
=== Function 21, subfunction 13, subsubfunction 3 - set videomode. ===
======================================================================
Parameters:
* eax = 21 - function number
* ebx = 13 - subfunction number
* ecx = 3 - number of the driver function
* edx = [scanning frequency]*65536 + [videomode number]
Returned value:
* eax = -1 - driver is not loaded, not initialized or
an error has occured
* eax = 0 - success
* ebx, ecx destroyed
Remarks:
* Driver must be initialized by driver function 1.
* The videomode number and frequency must be in the table
returned by driver function 1.
 
======================================================================
============ Function 21, subfunction 13, subsubfunction 4 ===========
================== Return to the initial videomode. ==================
======================================================================
Returns the screen to the videomode set at system boot.
Parameters:
* eax = 21 - function number
* ebx = 13 - subfunction number
* ecx = 4 - number of the driver function
Returned value:
* eax = -1 - driver is not loaded or not initialized
* eax = 0 - success
* ebx, ecx destroyed
Remarks:
* Driver must be initialized by call to driver function 1.
 
======================================================================
============ Function 21, subfunction 13, subsubfunction 5 ===========
===== Increase/decrease the size of the visible area of monitor. =====
======================================================================
Parameters:
* eax = 21 - function number
* ebx = 13 - subfunction number
* ecx = 5 - number of the driver function
* edx = 0/1 - decrease/increase horizontal size on 1 position
* edx = 2/3 - is not supported in the current implementation;
is planned as decrease/increase vertical size on 1 position
Returned value:
* eax = -1 - driver is not loaded or not initialized
* eax = 0 - success
* ebx, ecx destroyed
Remarks:
* Driver must be initialized by call to driver function 1.
* Function influences only the physical size of the screen image;
the logical size (number of pixels) does not change.
 
======================================================================
================= Function 22 - set system date/time. ================
======================================================================
Parameters:
1485,58 → 1324,6
makes 32-bit overflow.
 
======================================================================
======== Function 24, subfunction 1 - begin to play CD-audio. ========
======================================================================
Parameters:
* eax = 24 - function number
* ebx = 1 - subfunction number
* ecx = 0x00FRSSMM, where
* MM = starting minute
* SS = starting second
* FR = starting frame
Returned value:
* eax = 0 - success
* eax = 1 - CD base is not defined
Remarks:
* Previously CD base must be defined by the call to
subfunction 3 of function 21.
* One second includes 75 frames, one minute includes 60 seconds.
* The function is asynchronous (returns control, when play begins).
 
======================================================================
======= Function 24, subfunction 2 - get information on tracks. ======
======================================================================
Parameters:
* eax = 24 - function number
* ebx = 2 - subfunction number
* ecx = pointer to the buffer for the table
(maximum 8*64h+4 bytes=100 tracks)
Returned value:
* eax = 0 - success
* eax = 1 - CD base is not defined
Remarks:
* The format of the table with tracks information is the same as
for ATAPI-CD command 43h (READ TOC), usual table (subcommand 00h).
Function returns addresses in MSF.
* Previously CD base port must be set by call to
subfunction 3 of function 21.
* Function returns information only about no more than 100
first tracks. In most cases it is enough.
 
======================================================================
========== Function 24, subfunction 3 - stop play CD-audio. ==========
======================================================================
Parameters:
* eax = 24 - function number
* ebx = 1 - subfunction number
Returned value:
* eax = 0 - success
* eax = 1 - CD base is not defined
Remarks:
* Previously CD base port must be defined by call to
subfunction 3 of function 21.
 
======================================================================
======= Function 24, subfunction 4 - eject tray of disk drive. =======
======================================================================
Parameters:
1543,7 → 1330,9
* eax = 24 - function number
* ebx = 4 - subfunction number
* ecx = position of CD/DVD-drive
(from 0=Primary Master to 3=Secondary Slave)
from 0=Primary Master to 3=Secondary Slave for first IDE contr.
from 4=Primary Master to 7=Secondary Slave for second IDE contr.
from 8=Primary Master to 11=Secondary Slave for third IDE contr.
Returned value:
* function does not return value
Remarks:
1561,7 → 1350,9
* eax = 24 - function number
* ebx = 5 - subfunction number
* ecx = position of CD/DVD-drive
(from 0=Primary Master to 3=Secondary Slave)
from 0=Primary Master to 3=Secondary Slave for first IDE contr.
from 4=Primary Master to 7=Secondary Slave for second IDE contr.
from 8=Primary Master to 11=Secondary Slave for third IDE contr.
Returned value:
* function does not return value
Remarks:
1636,18 → 1427,6
* The application @panel switches layouts on user request.
 
======================================================================
============== Function 26, subfunction 3 - get CD base. =============
======================================================================
Parameters:
* eax = 26 - function number
* ebx = 3 - subfunction number
Returned value:
* eax = CD base: 1=IDE0, 2=IDE1, 3=IDE2, 4=IDE3
Remarks:
* CD base is used by function 24.
* To set CD base use subfunction 3 of function 21.
 
======================================================================
========== Function 26, subfunction 5 - get system language. =========
======================================================================
Parameters:
1662,41 → 1441,6
* To set system language use subfunction 5 of function 21.
 
======================================================================
============== Function 26, subfunction 7 - get HD base. =============
======================================================================
The HD base defines hard disk to write with usage of obsolete
syntax /HD in obsolete function 58; at usage of modern syntax
/HD0,/HD1,/HD2,/HD3 base is set automatically.
Parameters:
* eax = 26 - function number
* ebx = 7 - subfunction number
Returned value:
* eax = HD base: 1=IDE0, 2=IDE1, 3=IDE2, 4=IDE3
Remarks:
* Any application in any time can change HD base.
* To set base use subfunction 7 of function 21.
* To get used partition of hard disk use subfunction 8.
 
======================================================================
========= Function 26, subfunction 8 - get used HD partition. ========
======================================================================
The HD partition defines partition of the hard disk to write with
usage of obsolete syntax /HD in obsolete function 58;
at usage of functions 58 and 70 and modern syntax /HD0,/HD1,/HD2,/HD3
base and partition are set automatically.
Parameters:
* eax = 26 - function number
* ebx = 8 - subfunction number
Returned value:
* eax = HD partition (beginning from 1)
Remarks:
* Any application in any time can change partition.
* To set partition use subfunction 8 of function 21.
* To get number of partitions on a hard disk use
subfunction 11 of function 18.
* To get base of used hard disk, use subfunction 7.
 
======================================================================
=== Function 26, subfunction 9 - get the value of the time counter. ==
======================================================================
Parameters:
2315,8 → 2059,7
Parameters:
* eax = 48 - function number
* ebx = 8 - subfunction number
* ecx = pointer to a block for function 58, in
which the fields of intermediate buffer and file name are filled
* ecx = pointer to filename of the skin
Returned value:
* eax = 0 - success
* otherwise eax = file system error code; if file does not
2527,219 → 2270,6
(through kernel-mode analogues of subfunctions of function 62).
 
======================================================================
================ Function 58 - work with file system. ================
======================================================================
Parameters:
* eax = 58
* ebx = pointer to the information structure
Returned value:
* eax = 0 - success; otherwise file system error code
* some subfunctions return value in other registers too
General format of the information structure:
* +0: dword: subfunction number
* +4: dword: number of block
* +8: dword: size
* +12 = +0xC: dword: pointer to data
* +16 = +0x10: dword: pointer to a memory for system operations
(4096 bytes)
* +20 = +0x14: n db: ASCIIZ-string with the file name
Specifications - in documentation on the appropriate subfunction.
Filename is case-insensitive for latin letters, russian letters
must be capital.
Format of filename:
/base/number/dir1/dir2/.../dirn/file,
where /base/number identifies device, on which file is located:
one of
* /RD/1 = /RAMDISK/1 to access ramdisk
* /FD/1 = /FLOPPYDISK/1 to access first floppy drive,
/FD/2 = /FLOPPYDISK/2 to access second one
* /HD/x = /HARDDISK/x - obsolete variant of access to hard disk
(in this case base is defined by subfunction 7 of function 21),
x - partition number (beginning from 1)
* /HD0/x, /HD1/x, /HD2/x, /HD3/x to access accordingly to devices
IDE0 (Primary Master), IDE1 (Primary Slave),
IDE2 (Secondary Master), IDE3 (Secondary Slave);
x - partition number on the selected hard drive, varies from 1
to 255 (on each hard drive the indexing starts from 1)
Remarks:
* In the first two cases it is also possible to use FIRST
instead of 1, SECOND instead of 2, but it is not recommended
for convenience of transition to the future extensions.
* Limitation n<=39 is imposed.
* Names of folders and file dir1,...,dirn,file must have the
format 8.3: name no more than 8 characters, dot, extension no
more than 3 characters. Trailing spaces are ignored, no other
spaces is allowed. If name occupies equally 8 characters,
dot may be omitted (though it is not recommended to use this
feature for convenience of transition to the future extensions).
* This function does not support folders on ramdisk.
Examples:
* '/RAMDISK/FIRST/KERNEL.ASM',0
'/rd/1/kernel.asm',0
* '/HD0/1/kernel.asm',0
* '/hd0/1/menuet/pics/tanzania.bmp',0
Existing subfunctions:
* subfunction 0 - read file/folder
* subfunction 8 - LBA-read from device
* subfunction 15 - get file system information
 
======================================================================
=========== Function 58, subfunction 0 - read file/folder. ===========
======================================================================
Parameters:
* eax = 58
* ebx = pointer to the information structure
Format of the information structure:
* +0: dword: 0 = subfunction number
* +4: dword: first block to read (beginning from 0)
* +8: dword: amount of blocks to read
* +12 = +0xC: dword: pointer to buffer for data
* +16 = +0x10: dword: pointer to buffer for system operations
(4096 bytes)
* +20 = +0x14: ASCIIZ-name of file, the rules of names forming are
given in the general description
Returned value:
* eax = 0 - success, otherwise file system error code
* ebx = file size (in bytes) or -1=0xffffffff, if file was not found
Remarks:
* Block size is 512 bytes.
* This function is obsolete, for reading files use subfunction 0
of function 70, for reading folders - subfunction 1 of
function 70.
* Function can read contents of a folder. Only FAT file system is
supported. The format of FAT-folder is described
in any FAT documentation.
* Size of a folder is determined by size of FAT clusters chain.
* If file was ended before last requested block was read,
the function will read as many as it can, and after that return
eax=6 (EOF).
* Function can read root folders /rd/1,/fd/x,/hd[n]/x, but
in the first two cases the current implementation does not follow
to the declared rules:
for /rd/1:
* if one want to read 0 blocks, function considers,
that he requested 1;
* if one requests more than 14 blocks or starting block is
not less than 14, function returns eax=5 (not found) and ebx=-1;
* size of ramdisk root folder is 14 blocks,
0x1C00=7168 bytes; but function returns ebx=0
(except of the case of previous item);
* strangely enough, it is possible to read 14th block (which
generally contains a garbage - I remind, the indexing begins
from 0);
* if some block with the number not less than 14 was requested,
function returns eax=6(EOF); otherwise eax=0.
For /fd/x:
* if the start block is not less than 14, function returns
eax=5 (not found) and ebx=0;
* note that format of FAT12 allows floppies with the root size
more or less than 14 blocks;
* check for length is not performed;
* if data was successful read, function returns
eax=0,ebx=0; otherwise eax=10 (access denied), ebx=-1.
* The function handles reading of special folders /,/rd,/fd,/hd[n];
but the result does not correspond to expected (on operations with
normal files/folders), does not follow the declared rules,
may be changed in future versions of the kernel and consequently
is not described. To obtain the information about the equipment
use subfunction 11 of function 18 or
read corresponding folder with subfunction 1 of function 70.
 
======================================================================
========= Function 58, subfunction 8 - LBA-read from device. =========
======================================================================
Parameters:
* eax = 58 - function number
* ebx = pointer to the information structure
Format of the information structure:
* +0: dword: 8 = subfunction number
* +4: dword: number of block to read (beginning from 0)
* +8: dword: ignored (set to 1)
* +12 = +0xC: dword: pointer to buffer for data (512 bytes)
* +16 = +0x10: dword: pointer to buffer for system operations
(4096 bytes)
* +20 = +0x14: ASCIIZ-name of device: case-insensitive, one of
/rd/1 = /RamDisk/1, /hd/n = /HardDisk/n,
1<=n<=4 - number of device: 1=IDE0, ..., 4=IDE3.
Instead of digits it is allowed, though not recommended for
convenience of transition to future extensions, to use
'first','second','third','fourth'.
Returned value:
* for device name /hd/xxx, where xxx is not in the list above:
* eax = ebx = 1
* for invalid device name (except for the previous case):
* eax = 5
* ebx does not change
* if LBA-access is disabled by subfunction 11 of function 21:
* eax = 2
* ebx destroyed
* for ramdisk: attempt to read block outside ramdisk
(18*2*80 blocks) results in
* eax = 3
* ebx = 0
* for successful read:
* eax = ebx = 0
Remarks:
* Block size is 512 bytes; function reads one block.
* Do not depend on returned value, it can be changed
in future versions.
* Function requires that LBA-access to devices is enabled by
subfunction 11 of function 21. To check this one can use
subfunction 11 of function 26.
* LBA-read of floppy is not supported.
* Function reads data on physical hard drive; if for any reason
data of the concrete partition are required, application must
define starting sector of this partition (either directly
through MBR, or from the full structure returned by
subfunction 11 of function 18).
* Function does not check error code of hard disk, so request of
nonexisting sector reads something (most probably it will be
zeroes, but this is defined by device) and this is considered
as success (eax=0).
 
======================================================================
==== Function 58, subfunction 15 - get information on file system. ===
======================================================================
Parameters:
* eax = 58 - function number
* ebx = pointer to the information structure
Format of the information structure:
* +0: dword: 15 = subfunction number
* +4: dword: ignored
* +8: dword: ignored
* +12 = +0xC: dword: ignored
* +16 = +0x10: dword: ignored
* +20 = +0x14: (only second character is checked)
/rd=/RAMDISK or /hd=/HARDDISK
Returned value:
* if the second character does not belong to set {'r','R','h','H'}:
* eax = 3
* ebx = ecx = dword [fileinfo] = 0
* for ramdisk:
* eax = 0 (success)
* ebx = total number of clusters = 2847
* ecx = number of free clusters
* dword [fileinfo] = cluster size = 512
* for hard disk: base and partition are defined by subfunctions
7 and 8 of function 21:
* eax = 0 (success)
* ebx = total number of clusters
* ecx = number of free clusters
* dword [fileinfo] = cluster size (in bytes)
Remarks:
* Be not surprised to strange layout of 4th returned parameter
- when this code was writing, at system calls application got
only registers eax,ebx,ecx (from pushad-structure transmitted
as argument to the system function). Now it is corrected, so,
probably, it is meaningful to return cluster size in edx, while
this function is not used yet.
* There exists also subfunction 11 of function 18,
which returns information on file system. From the full table
of disk subsystem it is possible to deduce cluster size (there
it is stored in sectors) and total number of clusters
for hard disks.
 
======================================================================
========== Function 60 - Inter Process Communication (IPC). ==========
======================================================================
IPC is used for message dispatching from one process/thread to
4502,13 → 4032,7
Returned value:
* eax = socketnum1, -1 on error
* ebx = socketnum2, errorcode on error
Remarks:
 
Optstruct: dd level
dd optionname
dd optlength
db options...
 
======================================================================
=============== Function -1 - terminate thread/process ===============
======================================================================
/kernel/branches/Kolibri-acpi/docs/usbapi.txt
186,6 → 186,7
USB_STATUS_BUFUNDERRUN = 13 ; underflow of internal controller buffer
USB_STATUS_CLOSED = 16 ; pipe closed, either explicitly with USBClosePipe
; or due to device disconnect
USB_STATUS_CANCELLED = 17 ; transfer cancelled with USBAbortPipe
 
If several transfers are queued for the same pipe, their callback functions
are called in the same order as they were queued.
194,6 → 195,11
with USB_STATUS_CLOSED. The call to DeviceDisconnected() occurs after
all callbacks.
 
void __stdcall USBAbortPipe(void* pipe);
Initiates cancellation of all active transfers for the given pipe. Asynchronous.
When a transfer will be cancelled, the associated callback function
will be called with USB_STATUS_CANCELLED.
 
void* __stdcall USBGetParam(void* pipe0, int param);
Returns miscellaneous parameters of the device.
pipe0 is the pointer to the config pipe.
/kernel/branches/Kolibri-acpi/encoding.inc
1,148 → 1,133
; fetch the UTF-8 character in string+offs to char
; common part for all encodings: translate pseudographics
; Pseudographics for the boot screen:
; 0x2500 -> 0xC4, 0x2502 -> 0xB3, 0x250C -> 0xDA, 0x2510 -> 0xBF,
; 0x2514 -> 0xC0, 0x2518 -> 0xD9, 0x252C -> 0xC2, 0x2534 -> 0xC1, 0x2551 -> 0xBA
macro fetch_utf8_char string, offs, char, graph
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 5082 $
 
; fetch the UTF-8 character in addrspace:offs to char
macro fetch_utf8_char addrspace, offs, char
{ local first_byte, b
virtual at 0
db string
if offs >= $
char = -1
else
; fetch first byte
load first_byte byte from offs
load first_byte byte from addrspace:offs
if first_byte < 0x80
char = first_byte
offs = offs + 1
else if first_byte < 0xC0
.err Invalid UTF-8 string
err Invalid UTF-8 string
else if first_byte < 0xE0
char = first_byte and 0x1F
load b byte from offs + 1
load b byte from addrspace:offs + 1
char = (char shl 6) + (b and 0x3F)
offs = offs + 2
else if first_byte < 0xF0
char = first_byte and 0xF
load b byte from offs + 1
load b byte from addrspace:offs + 1
char = (char shl 6) + (b and 0x3F)
load b byte from offs + 2
load b byte from addrspace:offs + 2
char = (char shl 6) + (b and 0x3F)
offs = offs + 3
else if first_byte < 0xF8
char = first_byte and 0x7
load b byte from offs + 1
load b byte from addrspace:offs + 1
char = (char shl 6) + (b and 0x3F)
load b byte from offs + 2
load b byte from addrspace:offs + 2
char = (char shl 6) + (b and 0x3F)
load b byte from offs + 3
load b byte from addrspace:offs + 3
char = (char shl 6) + (b and 0x3F)
offs = offs + 4
else
.err Invalid UTF-8 string
err Invalid UTF-8 string
end if
end if
}
 
; Worker macro for all encodings.
; Common part for all encodings: map characters 0-0x7F trivially,
; translate pseudographics.
; Pseudographics for the boot screen:
; 0x2500 -> 0xC4, 0x2502 -> 0xB3, 0x250C -> 0xDA, 0x2510 -> 0xBF,
; 0x2514 -> 0xC0, 0x2518 -> 0xD9, 0x252C -> 0xC2, 0x2534 -> 0xC1, 0x2551 -> 0xBA
macro convert_utf8 encoding, [arg]
{ common
local ..addrspace, offs, char
offs = 0
virtual at 0
..addrspace:: db arg
..addrspace#.size = $
end virtual
while offs < ..addrspace#.size
fetch_utf8_char ..addrspace, offs, char
if char = 0x2500
graph = 0xC4
db 0xC4
else if char = 0x2502
graph = 0xB3
db 0xB3
else if char = 0x250C
graph = 0xDA
db 0xDA
else if char = 0x2510
graph = 0xBF
db 0xBF
else if char = 0x2514
graph = 0xC0
db 0xC0
else if char = 0x2518
graph = 0xD9
db 0xD9
else if char = 0x252C
graph = 0xC2
db 0xC2
else if char = 0x2534
graph = 0xC1
db 0xC1
else if char = 0x2551
graph = 0xBA
db 0xBA
else if char < 0x80
db char
else
graph = 0
encoding char
end if
end while
}
 
macro declare_encoding encoding
{
macro encoding [arg]
\{ common convert_utf8 encoding#char, arg \}
struc encoding [arg]
\{ common convert_utf8 encoding#char, arg \}
macro encoding#char char
}
 
; Russian: use CP866.
; 0x00-0x7F - trivial map
; 0x410-0x43F -> 0x80-0xAF
; 0x440-0x44F -> 0xE0-0xEF
; 0x401 -> 0xF0, 0x451 -> 0xF1
macro cp866 [arg]
{ local offs, char, graph
offs = 0
while 1
fetch_utf8_char arg, offs, char, graph
if char = -1
break
end if
if graph
db graph
else if char < 0x80
db char
else if char = 0x401
declare_encoding cp866
{
if char = 0x401
db 0xF0
else if char = 0x451
db 0xF1
else if (char < 0x410) | (char > 0x44F)
.err Failed to convert to CP866
err Failed to convert to CP866
else if char < 0x440
db char - 0x410 + 0x80
else
db char - 0x440 + 0xE0
end if
end while
}
 
struc cp866 [arg]
{
common
cp866 arg
}
 
; Latin-1 encoding
; 0x00-0xFF - trivial map
macro latin1 [arg]
{ local offs, char, graph
offs = 0
while 1
fetch_utf8_char arg, offs, char, graph
if char = -1
break
end if
if graph
db graph
else if char < 0x100
declare_encoding latin1
{
if char < 0x100
db char
else
.err Failed to convert to Latin-1
err Failed to convert to Latin-1
end if
end while
}
 
struc latin1 [arg]
; CP850 encoding
declare_encoding cp850
{
common
latin1 arg
}
 
; CP850 encoding
macro cp850 [arg]
{ local offs, char, graph
offs = 0
while 1
fetch_utf8_char arg, offs, char, graph
if char = -1
break
end if
if graph
db graph
else if char < 0x80
db char
else if char = 0xBF
if char = 0xBF
db 0xA8
else if char = 0xE1
db 0xA0
157,11 → 142,4
else
err Failed to convert to CP850
end if
end while
}
 
struc cp850 [arg]
{
common
cp850 arg
}
/kernel/branches/Kolibri-acpi/fs/ext2/blocks.inc
2,11 → 2,14
;; ;;
;; Contains ext2 block handling code. ;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under the terms of the new BSD license. ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4891 $
 
 
;---------------------------------------------------------------------
; Write ext2 block from memory to disk.
; Input: eax = i_block (block number in ext2 terms);
/kernel/branches/Kolibri-acpi/fs/ext2/ext2.asm
2,11 → 2,14
;; ;;
;; Contains ext2 initialization, plus syscall handling code. ;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under the terms of the new BSD license. ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 5089 $
 
 
include 'ext2.inc'
include 'blocks.inc'
include 'inode.inc'
56,6 → 59,8
;---------------------------------------------------------------------
proc ext2_create_partition
push ebx
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .fail
 
mov eax, 2 ; Superblock starts at 1024-bytes.
add ebx, 512 ; Get pointer to fs-specific buffer.
/kernel/branches/Kolibri-acpi/fs/ext2/ext2.inc
2,11 → 2,14
;; ;;
;; Contains ext2 structures, and macros. ;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under the terms of the new BSD license. ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4891 $
 
 
; Future jobs for driver, in order of preference:
; * clean up existing extents support.
; * add b-tree directories support.
/kernel/branches/Kolibri-acpi/fs/ext2/inode.inc
2,11 → 2,14
;; ;;
;; Contains ext2 inode handling code. ;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under the terms of the new BSD license. ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4891 $
 
 
;---------------------------------------------------------------------
; Receives block number from extent-based inode.
; Input: ecx = number of block in inode
/kernel/branches/Kolibri-acpi/fs/ext2/resource.inc
2,11 → 2,14
;; ;;
;; Contains common resource allocation + freeing code. ;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under the terms of the new BSD license. ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4891 $
 
 
;---------------------------------------------------------------------
; Frees a resource (block/inode).
; Input: eax = resource ID.
/kernel/branches/Kolibri-acpi/fs/fat.inc
154,6 → 154,9
xor eax, eax
ret
fat_create_partition:
; sector size must be 512
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .return0
; bootsector must have been successfully read
cmp dword [esp+4], 0
jnz .return0
/kernel/branches/Kolibri-acpi/fs/fs_lfn.inc
43,6 → 43,30
db 3,'cd3'
dd fs_OnCd3
dd fs_NextCd
db 3,'cd4'
dd fs_OnCd4
dd fs_NextCd
db 3,'cd5'
dd fs_OnCd5
dd fs_NextCd
db 3,'cd6'
dd fs_OnCd6
dd fs_NextCd
db 3,'cd7'
dd fs_OnCd7
dd fs_NextCd
db 3,'cd8'
dd fs_OnCd8
dd fs_NextCd
db 3,'cd9'
dd fs_OnCd9
dd fs_NextCd
db 4,'cd10'
dd fs_OnCd10
dd fs_NextCd
db 4,'cd11'
dd fs_OnCd11
dd fs_NextCd
;***********************************************
db 0
 
57,6 → 81,22
db 'cd2',0
dd fs_HasCd3
db 'cd3',0
dd fs_HasCd4
db 'cd4',0
dd fs_HasCd5
db 'cd5',0
dd fs_HasCd6
db 'cd6',0
dd fs_HasCd7
db 'cd7',0
dd fs_HasCd8
db 'cd8',0
dd fs_HasCd9
db 'cd9',0
dd fs_HasCd10
db 'cd10',0
dd fs_HasCd11
db 'cd11',0
;**********************************************
dd 0
endg
149,8 → 189,8
cmp dword [ebx], 1
jnz .access_denied
xor eax, eax
mov ebp, [ebx+12] ;количество блоков для считывания
mov edx, [ebx+16] ;куда записывать рузельтат
mov ebp, [ebx+12] ;the number of blocks to read
mov edx, [ebx+16] ;where to write the result
; add edx, std_application_base_address
push dword [ebx+4] ; first block
mov ebx, [ebx+8] ; flags
404,8 → 444,7
fs_NotImplemented:
mov eax, 2
ret
 
;*******************************************************
;-----------------------------------------------------------------------------
fs_OnCd0:
call reserve_cd
mov [ChannelNumber], 1
413,6 → 452,7
push 6
push 1
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd1:
call reserve_cd
mov [ChannelNumber], 1
420,6 → 460,7
push 4
push 2
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd2:
call reserve_cd
mov [ChannelNumber], 2
427,6 → 468,7
push 2
push 3
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd3:
call reserve_cd
mov [ChannelNumber], 2
433,16 → 475,89
mov [DiskNumber], 1
push 0
push 4
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd4:
call reserve_cd
mov [ChannelNumber], 1
mov [DiskNumber], 0
push 6
push 5
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd5:
call reserve_cd
mov [ChannelNumber], 1
mov [DiskNumber], 1
push 4
push 6
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd6:
call reserve_cd
mov [ChannelNumber], 2
mov [DiskNumber], 0
push 2
push 7
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd7:
call reserve_cd
mov [ChannelNumber], 2
mov [DiskNumber], 1
push 0
push 8
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd8:
call reserve_cd
mov [ChannelNumber], 1
mov [DiskNumber], 0
push 6
push 9
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd9:
call reserve_cd
mov [ChannelNumber], 1
mov [DiskNumber], 1
push 4
push 10
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd10:
call reserve_cd
mov [ChannelNumber], 2
mov [DiskNumber], 0
push 2
push 11
jmp fs_OnCd
;-----------------------------------------------------------------------------
fs_OnCd11:
call reserve_cd
mov [ChannelNumber], 2
mov [DiskNumber], 1
push 0
push 12
;-----------------------------------------------------------------------------
fs_OnCd:
call reserve_cd_channel
pop eax
mov [cdpos], eax
call reserve_cd_channel
pop eax
cmp ecx, 0x100
jae .nf
push ecx ebx
mov cl, al
mov bl, [DRIVE_DATA+1]
 
push eax
mov eax, [cdpos]
dec eax
shr eax, 2
lea eax, [eax*5]
mov bl, [eax+DRIVE_DATA+1]
pop eax
 
shr bl, cl
test bl, 2
pop ebx ecx
472,7 → 587,7
and [cd_status], 0
mov dword [image_of_eax], 2 ; not implemented
ret
 
;-----------------------------------------------------------------------------
fs_CdServices:
dd fs_CdRead
dd fs_CdReadFolder
485,32 → 600,74
dd fs_NotImplemented
dd fs_NotImplemented
fs_NumCdServices = ($ - fs_CdServices)/4
 
;*******************************************************
;-----------------------------------------------------------------------------
fs_HasCd0:
test byte [DRIVE_DATA+1], 10000000b
setnz al
ret
;--------------------------------------
fs_HasCd1:
test byte [DRIVE_DATA+1], 00100000b
setnz al
ret
;--------------------------------------
fs_HasCd2:
test byte [DRIVE_DATA+1], 00001000b
setnz al
ret
;--------------------------------------
fs_HasCd3:
test byte [DRIVE_DATA+1], 00000010b
setnz al
ret
;*******************************************************
 
;--------------------------------------
fs_HasCd4:
test byte [DRIVE_DATA+6], 10000000b
setnz al
ret
;--------------------------------------
fs_HasCd5:
test byte [DRIVE_DATA+6], 00100000b
setnz al
ret
;--------------------------------------
fs_HasCd6:
test byte [DRIVE_DATA+6], 00001000b
setnz al
ret
;--------------------------------------
fs_HasCd7:
test byte [DRIVE_DATA+6], 00000010b
setnz al
ret
;--------------------------------------
fs_HasCd8:
test byte [DRIVE_DATA+11], 10000000b
setnz al
ret
;--------------------------------------
fs_HasCd9:
test byte [DRIVE_DATA+11], 00100000b
setnz al
ret
;--------------------------------------
fs_HasCd10:
test byte [DRIVE_DATA+11], 00001000b
setnz al
ret
;--------------------------------------
fs_HasCd11:
test byte [DRIVE_DATA+11], 00000010b
setnz al
ret
;-----------------------------------------------------------------------------
;
; fs_NextXXX functions:
; in: eax = partition number, from which start to scan
; out: CF=1 => no more partitions
; CF=0 => eax=next partition number
 
;*******************************************************
;
;-----------------------------------------------------------------------------
fs_NextCd:
; we always have /cdX/1
test eax, eax
520,8 → 677,6
clc
@@:
ret
;*******************************************************
 
;-----------------------------------------------------------------------------
process_replace_file_name:
; in
/kernel/branches/Kolibri-acpi/fs/iso9660.inc
7,18 → 7,15
 
$Revision$
 
 
;-----------------------------------------------------------------------------
uglobal
cd_current_pointer_of_input dd 0
cd_current_pointer_of_input_2 dd 0
cd_mem_location dd 0
cd_counter_block dd 0
IDE_Channel_1 db 0
IDE_Channel_2 db 0
endg
 
;-----------------------------------------------------------------------------
reserve_cd:
 
cli
cmp [cd_status], 0
je reserve_ok2
26,9 → 23,8
sti
call change_task
jmp reserve_cd
 
;-----------------------------------------------------------------------------
reserve_ok2:
 
push eax
mov eax, [CURRENT_TASK]
shl eax, 5
37,48 → 33,105
pop eax
sti
ret
;-----------------------------------------------------------------------------
reserve_cd_channel:
pushad
mov eax, [cdpos]
dec eax
shr eax, 2
 
reserve_cd_channel:
test eax, eax
jnz .1
 
cmp [ChannelNumber], 1
jne .IDE_Channel_2
.IDE_Channel_1:
pushad
jne @f
 
mov ecx, ide_channel1_mutex
jmp .mutex_lock
;--------------------------------------
@@:
mov ecx, ide_channel2_mutex
jmp .mutex_lock
;--------------------------------------
.1:
dec eax
jnz .2
 
cmp [ChannelNumber], 1
jne @f
 
mov ecx, ide_channel3_mutex
jmp .mutex_lock
;--------------------------------------
@@:
mov ecx, ide_channel4_mutex
jmp .mutex_lock
;--------------------------------------
.2:
cmp [ChannelNumber], 1
jne @f
 
mov ecx, ide_channel5_mutex
jmp .mutex_lock
;--------------------------------------
@@:
mov ecx, ide_channel6_mutex
.mutex_lock:
call mutex_lock
mov [IDE_Channel_1], 1
popad
ret
.IDE_Channel_2:
;-----------------------------------------------------------------------------
free_cd_channel:
pushad
mov ecx, ide_channel2_mutex
call mutex_lock
mov [IDE_Channel_2], 1
popad
ret
mov eax, [cdpos]
dec eax
shr eax, 2
 
free_cd_channel:
test eax, eax
jnz .1
 
cmp [ChannelNumber], 1
jne .IDE_Channel_2
.IDE_Channel_1:
mov [IDE_Channel_1], 0
pushad
jne @f
 
mov ecx, ide_channel1_mutex
call mutex_unlock
popad
ret
.IDE_Channel_2:
mov [IDE_Channel_2], 0
pushad
jmp .mutex_unlock
;--------------------------------------
@@:
mov ecx, ide_channel2_mutex
jmp .mutex_unlock
;--------------------------------------
.1:
dec eax
jnz .2
 
cmp [ChannelNumber], 1
jne @f
 
mov ecx, ide_channel3_mutex
jmp .mutex_unlock
;--------------------------------------
@@:
mov ecx, ide_channel4_mutex
jmp .mutex_unlock
;--------------------------------------
.2:
cmp [ChannelNumber], 1
jne @f
 
mov ecx, ide_channel5_mutex
jmp .mutex_unlock
;--------------------------------------
@@:
mov ecx, ide_channel6_mutex
.mutex_unlock:
call mutex_unlock
popad
ret
 
;-----------------------------------------------------------------------------
uglobal
cd_status dd 0
endg
 
;----------------------------------------------------------------
;-----------------------------------------------------------------------------
;
; fs_CdRead - LFN variant for reading CD disk
;
91,91 → 144,114
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
;-----------------------------------------------------------------------------
fs_CdRead:
push edi
cmp byte [esi], 0
jnz @f
;--------------------------------------
.noaccess:
pop edi
;--------------------------------------
.noaccess_2:
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
 
;--------------------------------------
.noaccess_3:
pop eax edx ecx edi
jmp .noaccess_2
 
;--------------------------------------
@@:
call cd_find_lfn
jnc .found
 
pop edi
cmp [DevErrorCode], 0
jne .noaccess_2
 
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
 
;--------------------------------------
.found:
mov edi, [cd_current_pointer_of_input]
test byte [edi+25], 10b; do not allow read directories
jnz .noaccess
 
test ebx, ebx
jz .l1
 
cmp dword [ebx+4], 0
jz @f
 
xor ebx, ebx
;--------------------------------------
.reteof:
mov eax, 6; end of file
pop edi
ret
;--------------------------------------
@@:
mov ebx, [ebx]
;--------------------------------------
.l1:
push ecx edx
push 0
mov eax, [edi+10] ; реальный размер файловой секции
mov eax, [edi+10] ; real size of the file section
sub eax, ebx
jb .eof
 
cmp eax, ecx
jae @f
 
mov ecx, eax
mov byte [esp], 6
;--------------------------------------
@@:
mov eax, [edi+2]
mov [CDSectorAddress], eax
;--------------------------------------
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
.new_sector:
test ecx, ecx
jz .done
 
sub ebx, 2048
jae .next
 
add ebx, 2048
jnz .incomplete_sector
 
cmp ecx, 2048
jb .incomplete_sector
; we may read and memmove complete sector
mov [CDDataBuf_pointer], edx
call ReadCDWRetr; читаем сектор файла
call ReadCDWRetr ; read sector of file
cmp [DevErrorCode], 0
jne .noaccess_3
 
add edx, 2048
sub ecx, 2048
;--------------------------------------
.next:
inc dword [CDSectorAddress]
jmp .new_sector
;--------------------------------------
.incomplete_sector:
; we must read and memmove incomplete sector
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr; читаем сектор файла
call ReadCDWRetr ; read sector of file
cmp [DevErrorCode], 0
jne .noaccess_3
 
push ecx
add ecx, ebx
cmp ecx, 2048
jbe @f
 
mov ecx, 2048
;--------------------------------------
@@:
sub ecx, ebx
push edi esi ecx
189,19 → 265,19
pop ecx
xor ebx, ebx
jmp .next
 
;--------------------------------------
.done:
mov ebx, edx
pop eax edx ecx edi
sub ebx, edx
ret
;--------------------------------------
.eof:
mov ebx, edx
pop eax edx ecx
sub ebx, edx
jmp .reteof
 
;----------------------------------------------------------------
;-----------------------------------------------------------------------------
;
; fs_CdReadFolder - LFN variant for reading CD disk folder
;
215,30 → 291,37
; ret ebx = blocks read or 0xffffffff folder not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
;-----------------------------------------------------------------------------
fs_CdReadFolder:
push edi
call cd_find_lfn
jnc .found
 
pop edi
cmp [DevErrorCode], 0
jne .noaccess_1
 
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
;--------------------------------------
.found:
mov edi, [cd_current_pointer_of_input]
test byte [edi+25], 10b ; do not allow read directories
jnz .found_dir
 
pop edi
;--------------------------------------
.noaccess_1:
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
;--------------------------------------
.found_dir:
mov eax, [edi+2] ; eax=cluster
mov [CDSectorAddress], eax
mov eax, [edi+10] ; размер директрории
mov eax, [edi+10] ; directory size
;--------------------------------------
.doit:
; init header
push eax ecx
250,21 → 333,23
mov byte [edx], 1 ; version
mov [cd_mem_location], edx
add [cd_mem_location], 32
; начинаем переброску БДВК в УСВК
;.mainloop:
mov [cd_counter_block], dword 0
dec dword [CDSectorAddress]
push ecx
;--------------------------------------
.read_to_buffer:
inc dword [CDSectorAddress]
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr ; читаем сектор директории
call ReadCDWRetr ; read sector of directory
cmp [DevErrorCode], 0
jne .noaccess_1
 
call .get_names_from_buffer
sub eax, 2048
; директория закончилась?
; directory is over?
ja .read_to_buffer
 
mov edi, [cd_counter_block]
mov [edx+8], edi
mov edi, [ebx]
272,24 → 357,30
xor eax, eax
dec ecx
js @f
 
mov al, ERROR_END_OF_FILE
;--------------------------------------
@@:
pop ecx edi
mov ebx, [edx+4]
ret
 
;--------------------------------------
.get_names_from_buffer:
mov [cd_current_pointer_of_input_2], CDDataBuf
push eax esi edi edx
;--------------------------------------
.get_names_from_buffer_1:
call cd_get_name
jc .end_buffer
 
inc dword [cd_counter_block]
mov eax, [cd_counter_block]
cmp [ebx], eax
jae .get_names_from_buffer_1
 
test ecx, ecx
jz .get_names_from_buffer_1
 
mov edi, [cd_counter_block]
mov [edx+4], edi
dec ecx
298,10 → 389,11
add edi, 40
test dword [ebx+4], 1; 0=ANSI, 1=UNICODE
jnz .unicode
; jmp .unicode
;--------------------------------------
.ansi:
cmp [cd_counter_block], 2
jbe .ansi_parent_directory
 
cld
lodsw
xchg ah, al
308,163 → 400,178
call uni2ansi_char
cld
stosb
; проверка конца файла
; check end of file
mov ax, [esi]
cmp ax, word 3B00h; сепаратор конца файла ';'
cmp ax, word 3B00h ; separator end of file ';'
je .cd_get_parameters_of_file_1
; проверка для файлов не заканчивающихся сепаратором
; check for files not ending with separator
movzx eax, byte [ebp-33]
add eax, ebp
sub eax, 34
cmp esi, eax
je .cd_get_parameters_of_file_1
; проверка конца папки
; check the end of the directory
movzx eax, byte [ebp-1]
add eax, ebp
cmp esi, eax
jb .ansi
;--------------------------------------
.cd_get_parameters_of_file_1:
mov [edi], byte 0
call cd_get_parameters_of_file
add [cd_mem_location], 304
jmp .get_names_from_buffer_1
 
;--------------------------------------
.ansi_parent_directory:
cmp [cd_counter_block], 2
je @f
 
mov [edi], byte '.'
inc edi
jmp .cd_get_parameters_of_file_1
;--------------------------------------
@@:
mov [edi], word '..'
add edi, 2
jmp .cd_get_parameters_of_file_1
 
;--------------------------------------
.unicode:
cmp [cd_counter_block], 2
jbe .unicode_parent_directory
 
cld
movsw
; проверка конца файла
; check end of file
mov ax, [esi]
cmp ax, word 3B00h; сепаратор конца файла ';'
cmp ax, word 3B00h; separator end of file ';'
je .cd_get_parameters_of_file_2
; проверка для файлов не заканчивающихся сепаратором
; check for files not ending with separator
movzx eax, byte [ebp-33]
add eax, ebp
sub eax, 34
cmp esi, eax
je .cd_get_parameters_of_file_2
; проверка конца папки
; check the end of the directory
movzx eax, byte [ebp-1]
add eax, ebp
cmp esi, eax
jb .unicode
;--------------------------------------
.cd_get_parameters_of_file_2:
mov [edi], word 0
call cd_get_parameters_of_file
add [cd_mem_location], 560
jmp .get_names_from_buffer_1
 
;--------------------------------------
.unicode_parent_directory:
cmp [cd_counter_block], 2
je @f
 
mov [edi], word 2E00h; '.'
add edi, 2
jmp .cd_get_parameters_of_file_2
;--------------------------------------
@@:
mov [edi], dword 2E002E00h; '..'
add edi, 4
jmp .cd_get_parameters_of_file_2
 
;--------------------------------------
.end_buffer:
pop edx edi esi eax
ret
 
;-----------------------------------------------------------------------------
cd_get_parameters_of_file:
mov edi, [cd_mem_location]
cd_get_parameters_of_file_1:
; получаем атрибуты файла
; get file attributes
xor eax, eax
; файл не архивировался
; file is not archived
inc eax
shl eax, 1
; это каталог?
; is a directory?
test [ebp-8], byte 2
jz .file
 
inc eax
;--------------------------------------
.file:
; метка тома не как в FAT, в этом виде отсутсвует
; файл не является системным
; not as a volume label in the FAT, in this form not available
; file is not a system
shl eax, 3
; файл является скрытым? (атрибут существование)
; file is hidden? (attribute of existence)
test [ebp-8], byte 1
jz .hidden
 
inc eax
;--------------------------------------
.hidden:
shl eax, 1
; файл всегда только для чтения, так как это CD
; file is always read-only, as this CD
inc eax
mov [edi], eax
; получаем время для файла
;час
; get the time to file
; hour
movzx eax, byte [ebp-12]
shl eax, 8
;минута
; minute
mov al, [ebp-11]
shl eax, 8
;секунда
; second
mov al, [ebp-10]
;время создания файла
; file creation time
mov [edi+8], eax
;время последнего доступа
; last access time
mov [edi+16], eax
;время последней записи
; last write time
mov [edi+24], eax
; получаем дату для файла
;год
; get date for file
; year
movzx eax, byte [ebp-15]
add eax, 1900
shl eax, 8
;месяц
; month
mov al, [ebp-14]
shl eax, 8
;день
; day
mov al, [ebp-13]
;дата создания файла
; file creation date
mov [edi+12], eax
;время последнего доступа
; last access date
mov [edi+20], eax
;время последней записи
; last write date
mov [edi+28], eax
; получаем тип данных имени
; get the data type of name
xor eax, eax
test dword [ebx+4], 1; 0=ANSI, 1=UNICODE
jnz .unicode_1
 
mov [edi+4], eax
jmp @f
;--------------------------------------
.unicode_1:
inc eax
mov [edi+4], eax
;--------------------------------------
@@:
; получаем размер файла в байтах
; get the file size in bytes
xor eax, eax
mov [edi+32+4], eax
mov eax, [ebp-23]
mov [edi+32], eax
ret
 
;----------------------------------------------------------------
;-----------------------------------------------------------------------------
;
; fs_CdGetFileInfo - LFN variant for CD
; get file/directory attributes structure
;
;----------------------------------------------------------------
;-----------------------------------------------------------------------------
fs_CdGetFileInfo:
cmp byte [esi], 0
jnz @f
 
mov eax, 2
ret
;--------------------------------------
@@:
push edi
call cd_find_lfn
471,16 → 578,20
pushfd
cmp [DevErrorCode], 0
jz @f
 
popfd
pop edi
mov eax, 11
ret
;--------------------------------------
@@:
popfd
jnc @f
 
pop edi
mov eax, ERROR_FILE_NOT_FOUND
ret
;--------------------------------------
@@:
 
mov edi, edx
493,8 → 604,7
pop edi
xor eax, eax
ret
 
;----------------------------------------------------------------
;-----------------------------------------------------------------------------
cd_find_lfn:
mov [cd_appl_data], 0
; in: esi+ebp -> name
501,14 → 611,13
; out: CF=1 - file not found
; else CF=0 and [cd_current_pointer_of_input] direntry
push eax esi
; 16 сектор начало набора дескрипторов томов
 
; Sector 16 - start set of volume descriptors
call WaitUnitReady
cmp [DevErrorCode], 0
jne .access_denied
 
call prevent_medium_removal
; тестовое чтение
; testing of reading
mov [CDSectorAddress], dword 16
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr;_1
515,10 → 624,11
cmp [DevErrorCode], 0
jne .access_denied
 
; вычисление последней сессии
; calculation of the last session
call WaitUnitReady
cmp [DevErrorCode], 0
jne .access_denied
 
call Read_TOC
mov ah, [CDDataBuf+4+4]
mov al, [CDDataBuf+4+5]
529,7 → 639,7
mov [CDSectorAddress], eax
; mov [CDSectorAddress],dword 15
mov [CDDataBuf_pointer], CDDataBuf
 
;--------------------------------------
.start:
inc dword [CDSectorAddress]
call ReadCDWRetr;_1
537,111 → 647,128
jne .access_denied
 
.start_check:
; проверка на вшивость
; checking for "lice"
cmp [CDDataBuf+1], dword 'CD00'
jne .access_denied
 
cmp [CDDataBuf+5], byte '1'
jne .access_denied
; сектор является терминатором набор дескрипторов томов?
; sector is the terminator of set of descriptors volumes?
cmp [CDDataBuf], byte 0xff
je .access_denied
; сектор является дополнительным и улучшенным дескриптором тома?
; sector is an additional and improved descriptor of volume?
cmp [CDDataBuf], byte 0x2
jne .start
; сектор является дополнительным дескриптором тома?
; sector is an additional descriptor of volume?
cmp [CDDataBuf+6], byte 0x1
jne .start
 
; параметры root директрории
mov eax, [CDDataBuf+0x9c+2]; начало root директрории
; parameters of root directory
mov eax, [CDDataBuf+0x9c+2]; start of root directory
mov [CDSectorAddress], eax
mov eax, [CDDataBuf+0x9c+10]; размер root директрории
mov eax, [CDDataBuf+0x9c+10]; size of root directory
cmp byte [esi], 0
jnz @f
 
mov [cd_current_pointer_of_input], CDDataBuf+0x9c
jmp .done
;--------------------------------------
@@:
; начинаем поиск
; start the search
.mainloop:
dec dword [CDSectorAddress]
;--------------------------------------
.read_to_buffer:
inc dword [CDSectorAddress]
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr ; читаем сектор директории
call ReadCDWRetr ; read sector of directory
cmp [DevErrorCode], 0
jne .access_denied
 
push ebp
call cd_find_name_in_buffer
pop ebp
jnc .found
 
sub eax, 2048
; директория закончилась?
; directory is over?
cmp eax, 0
ja .read_to_buffer
; нет искомого элемента цепочки
; desired element of chain is not found
.access_denied:
pop esi eax
mov [cd_appl_data], 1
stc
ret
; искомый элемент цепочки найден
;--------------------------------------
; desired element of chain found
.found:
; конец пути файла
; the end of the file path
cmp byte [esi-1], 0
jz .done
.nested:
mov eax, [cd_current_pointer_of_input]
push dword [eax+2]
pop dword [CDSectorAddress] ; начало директории
mov eax, [eax+2+8]; размер директории
pop dword [CDSectorAddress] ; beginning of the directory
mov eax, [eax+2+8] ; size of directory
jmp .mainloop
; указатель файла найден
;--------------------------------------
; file pointer found
.done:
test ebp, ebp
jz @f
 
mov esi, ebp
xor ebp, ebp
jmp .nested
;--------------------------------------
@@:
pop esi eax
mov [cd_appl_data], 1
clc
ret
 
;-----------------------------------------------------------------------------
cd_find_name_in_buffer:
mov [cd_current_pointer_of_input_2], CDDataBuf
;--------------------------------------
.start:
call cd_get_name
jc .not_found
 
call cd_compare_name
jc .start
;--------------------------------------
.found:
clc
ret
;--------------------------------------
.not_found:
stc
ret
 
;-----------------------------------------------------------------------------
cd_get_name:
push eax
mov ebp, [cd_current_pointer_of_input_2]
mov [cd_current_pointer_of_input], ebp
mov eax, [ebp]
test eax, eax ; входы закончились?
test eax, eax ; entry's is over?
jz .next_sector
cmp ebp, CDDataBuf+2048 ; буфер закончился?
 
cmp ebp, CDDataBuf+2048 ; buffer is over?
jae .next_sector
 
movzx eax, byte [ebp]
add [cd_current_pointer_of_input_2], eax; следующий вход каталога
add ebp, 33; указатель установлен на начало имени
add [cd_current_pointer_of_input_2], eax ; next entry of directory
add ebp, 33; pointer is set to the beginning of the name
pop eax
clc
ret
;--------------------------------------
.next_sector:
pop eax
stc
ret
 
;-----------------------------------------------------------------------------
cd_compare_name:
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
; in: esi->name, ebp->name
650,6 → 777,7
; destroys eax
push esi eax edi
mov edi, ebp
;--------------------------------------
.loop:
cld
lodsb
666,31 → 794,37
sub edi, 2
scasw
jne .name_not_coincide
;--------------------------------------
.coincides:
cmp [esi], byte '/'; разделитель пути, конец имени текущего элемента
cmp [esi], byte '/' ; path separator is end of current element
je .done
cmp [esi], byte 0; разделитель пути, конец имени текущего элемента
 
cmp [esi], byte 0 ; path separator end of name
je .done
 
jmp .loop
;--------------------------------------
.name_not_coincide:
pop edi eax esi
stc
ret
;--------------------------------------
.done:
; проверка конца файла
cmp [edi], word 3B00h; сепаратор конца файла ';'
; check end of file
cmp [edi], word 3B00h; separator end of file ';'
je .done_1
; проверка для файлов не заканчивающихся сепаратором
; check for files not ending with separator
movzx eax, byte [ebp-33]
add eax, ebp
sub eax, 34
cmp edi, eax
je .done_1
; проверка конца папки
; check the end of directory
movzx eax, byte [ebp-1]
add eax, ebp
cmp edi, eax
jne .name_not_coincide
;--------------------------------------
.done_1:
pop edi eax
add esp, 4
697,7 → 831,7
inc esi
clc
ret
 
;-----------------------------------------------------------------------------
char_todown:
; convert character to uppercase, using cp866 encoding
; in: al=symbol
704,24 → 838,30
; out: al=converted symbol
cmp al, 'A'
jb .ret
 
cmp al, 'Z'
jbe .az
 
cmp al, 0x80 ; 'А'
jb .ret
 
cmp al, 0x90 ; 'Р'
jb .rus1
 
cmp al, 0x9F ; 'Я'
ja .ret
; 0x90-0x9F -> 0xE0-0xEF
add al, 0xE0-0x90
;--------------------------------------
.ret:
ret
;--------------------------------------
.rus1:
; 0x80-0x8F -> 0xA0-0xAF
.az:
add al, 0x20
ret
 
;-----------------------------------------------------------------------------
uni2ansi_char:
; convert UNICODE character in al to ANSI character in ax, using cp866 encoding
; in: ax=UNICODE character
728,32 → 868,44
; out: al=converted ANSI character
cmp ax, 0x80
jb .ascii
 
cmp ax, 0x401
jz .yo1
 
cmp ax, 0x451
jz .yo2
 
cmp ax, 0x410
jb .unk
 
cmp ax, 0x440
jb .rus1
 
cmp ax, 0x450
jb .rus2
;--------------------------------------
.unk:
mov al, '_'
jmp .doit
;--------------------------------------
.yo1:
mov al, 0xF0 ; 'Ё' in cp866
jmp .doit
;--------------------------------------
.yo2:
mov al, 0xF1 ; 'ё' in cp866
jmp .doit
;--------------------------------------
.rus1:
; 0x410-0x43F -> 0x80-0xAF
add al, 0x70
jmp .doit
;--------------------------------------
.rus2:
; 0x440-0x44F -> 0xE0-0xEF
add al, 0xA0
;--------------------------------------
.ascii:
.doit:
ret
;-----------------------------------------------------------------------------
/kernel/branches/Kolibri-acpi/fs/ntfs.inc
152,6 → 152,8
ret
 
proc ntfs_create_partition
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .nope
mov edx, dword [ebp+PARTITION.Length]
cmp dword [esp+4], 0
jz .boot_read_ok
/kernel/branches/Kolibri-acpi/fs/xfs.asm
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 5089 $
 
 
include 'xfs.inc'
 
;
15,6 → 25,8
; returns 0 (not XFS or invalid) / pointer to partition structure
xfs_create_partition:
push ebx ecx edx esi edi
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .error
cmp dword[ebx + xfs_sb.sb_magicnum], XFS_SB_MAGIC ; signature
jne .error
 
/kernel/branches/Kolibri-acpi/fs/xfs.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
; from stat.h
; distinguish file types
S_IFMT = 0170000o ; These bits determine file type.
/kernel/branches/Kolibri-acpi/gui/event.inc
454,7 → 454,11
cmp al, 120
jae .result ;overflow
inc byte[KEY_COUNT]
mov [KEY_COUNT+1+eax], dl
mov [KEY_BUFF+eax], dl
; store empty scancode
add eax, 120+2
mov [KEY_BUFF+eax], byte 0
sub eax, 120+2
;--------------------------------------
align 4
.result:
/kernel/branches/Kolibri-acpi/gui/skincode.inc
11,7 → 11,7
include "skindata.inc"
 
;skin_data = 0x00778000
;------------------------------------------------------------------------------
;-----------------------------------------------------------------
align 4
read_skin_file:
stdcall load_file, ebx
121,7 → 121,7
lea esi, [ebx+SKIN_PARAMS.dtp.data]
mov edi, common_colours
mov ecx, [ebx+SKIN_PARAMS.dtp.size]
and ecx, 127
and ecx, 255
rep movsb
mov eax, dword[ebx+SKIN_PARAMS.margin.right]
mov dword[_skinmargins+0], eax
/kernel/branches/Kolibri-acpi/gui/skindata.inc
9,7 → 9,7
 
 
;
; WINDOW SKIN DATA
; WINDOW SKIN DATA.
;
 
iglobal
/kernel/branches/Kolibri-acpi/gui/window.inc
26,7 → 26,7
}
 
uglobal
common_colours rd 32
common_colours rd 48
draw_limits RECT
endg
 
34,7 → 34,7
;------------------------------------------------------------------------------
syscall_draw_window: ;///// system function 0 /////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;? <description>.
;------------------------------------------------------------------------------
mov eax, edx
shr eax, 24
173,7 → 173,10
syscall_display_settings.02:
dec ebx
mov esi, ecx
and edx, 127
cmp edx, 192
jnae @f
mov edx, 192 ; max size
@@:
mov edi, common_colours
mov ecx, edx
rep movsb
183,7 → 186,10
align 4
syscall_display_settings.03:
mov edi, ecx
and edx, 127
cmp edx, 192
jnae @f
mov edx, 192 ; max size
@@:
mov esi, common_colours
mov ecx, edx
rep movsb
209,7 → 215,7
syscall_display_settings.06:
xor esi, esi
 
mov edi, [_display.width]
mov edi, [Screen_Max_X]
mov eax, ecx
movsx ebx, ax
sar eax, 16
233,7 → 239,7
;--------------------------------------
align 4
.check_horizontal:
mov edi, [_display.height]
mov edi, [Screen_Max_Y]
mov eax, edx
movsx ebx, ax
sar eax, 16
294,8 → 300,8
syscall_display_settings._.calculate_whole_screen:
xor eax, eax
xor ebx, ebx
mov ecx, [_display.width]
mov edx, [_display.height]
mov ecx, [Screen_Max_X]
mov edx, [Screen_Max_Y]
jmp calculatescreen
;------------------------------------------------------------------------------
align 4
303,11 → 309,9
xor eax, eax
mov [draw_limits.left], eax
mov [draw_limits.top], eax
mov eax, [_display.width]
dec eax
mov eax, [Screen_Max_X]
mov [draw_limits.right], eax
mov eax, [_display.height]
dec eax
mov eax, [Screen_Max_Y]
mov [draw_limits.bottom], eax
mov eax, window_data
jmp redrawscreen
586,9 → 590,9
 
mov eax, [edi + WDATA.box.left]
add eax, [edi + WDATA.box.width]
mov ebx, [_display.width]
mov ebx, [Screen_Max_X]
cmp eax, ebx
jl .fix_vertical
jle .fix_vertical
mov eax, [edi + WDATA.box.width]
sub eax, ebx
jle @f
603,9 → 607,9
.fix_vertical:
mov eax, [edi + WDATA.box.top]
add eax, [edi + WDATA.box.height]
mov ebx, [_display.height]
mov ebx, [Screen_Max_Y]
cmp eax, ebx
jl .fix_client_box
jle .fix_client_box
mov eax, [edi + WDATA.box.height]
sub eax, ebx
jle @f
819,12 → 823,8
jnz .exit
 
; does client area have a positive size on screen?
mov edx, [esi + WDATA.box.top]
add edx, 21 + 5
mov ebx, [esi + WDATA.box.top]
add ebx, [esi + WDATA.box.height]
cmp edx, ebx
jg .exit
cmp [esi + WDATA.box.height], 21
jle .exit
 
; okay, let's draw it
mov eax, 1
1718,9 → 1718,9
mov ecx, [edi + WDATA.box.width]
mov edx, [edi + WDATA.box.height]
 
mov esi, [_display.width]
mov esi, [Screen_Max_X]
cmp ecx, esi
jae .fix_width_high
ja .fix_width_high
;--------------------------------------
align 4
.check_left:
1732,9 → 1732,9
;--------------------------------------
align 4
.check_height:
mov esi, [_display.height]
mov esi, [Screen_Max_Y]
cmp edx, esi
jae .fix_height_high
ja .fix_height_high
;--------------------------------------
align 4
.check_top:
1992,7 → 1992,7
 
sub ebp, [ff_xsz]
add ebp, [ff_x]
add ebp, [_display.width] ; screen.x
add ebp, [Screen_Max_X] ; screen.x
inc ebp
inc ebx
cmp ebx, [ff_ysz]
/kernel/branches/Kolibri-acpi/hid/keyboard.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25,8 → 25,6
VKEY_ALT = 0000000000110000b
 
uglobal
align 4
kb_state dd 0
ext_code db 0
 
keyboard_mode db 0
35,7 → 33,6
altmouseb db 0
ctrl_alt_del db 0
 
kb_lights db 0
old_kb_lights db 0
 
align 4
45,6 → 42,13
endg
 
iglobal
kb_lights db 2
align 4
kb_state dd VKEY_NUMLOCK
endg
 
iglobal
align 4
hotkey_tests dd hotkey_test0
dd hotkey_test1
dd hotkey_test2
457,19 → 461,40
test bl, bl
jz .exit.irq1
 
test [kb_state], VKEY_NUMLOCK
jz .dowrite
cmp cl, 0xE0 ; extended keycode
jne @f
cmp cl, 0xE0
jz .dowrite
cmp ch, 53
jne .dowrite
mov bl, '/'
jmp .dowrite
@@:
cmp ch, 55
jnz @f
jne @f
mov bl, 0x2A ;*
mov bl, '*'
jmp .dowrite
;--------------------------------------
@@:
 
cmp ch, 74
jne @f
mov bl, '-'
jmp .dowrite
@@:
 
cmp ch, 78
jne @f
mov bl, '+'
jmp .dowrite
@@:
 
test [kb_state], VKEY_NUMLOCK
jz .dowrite
 
cmp ch, 71
jb .dowrite
488,7 → 513,19
jae .exit.irq1
inc eax
mov [KEY_COUNT], al
mov [KEY_COUNT+eax], bl
; store ascii or scancode
mov [KEY_COUNT+eax], bl ; actually KEY_BUFF + EAX - 1
; store original scancode
add eax, 120+2
push ecx
cmp [keyboard_mode], 0; return from keymap
je @f
 
xor ch, ch
@@:
mov [KEY_COUNT+eax], ch ; actually KEY_BUFF + EAX - 1
pop ecx
sub eax, 120+2
.exit.irq1:
ret
;---------------------------------------------------------------------
518,9 → 555,9
ps2_set_lights:
stdcall disable_irq, 1
mov al, 0xED
call kb_write
call kb_write_wait_ack
mov al, [esp+8]
call kb_write
call kb_write_wait_ack
stdcall enable_irq, 1
ret 8
 
/kernel/branches/Kolibri-acpi/hid/mousedrv.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24,16 → 24,12
uglobal
;--------------------------------------
align 4
mousecount dd 0x0
mousedata dd 0x0
Y_UNDER_sub_CUR_hot_y_add_curh:
dw 0
Y_UNDER_subtraction_CUR_hot_y:
dw 0
X_UNDER_sub_CUR_hot_x_add_curh:
dw 0
X_UNDER_subtraction_CUR_hot_x:
dw 0
mousecount dd ?
mousedata dd ?
Y_UNDER_sub_CUR_hot_y_add_curh dw ?
Y_UNDER_subtraction_CUR_hot_y dw ?
X_UNDER_sub_CUR_hot_x_add_curh dw ?
X_UNDER_subtraction_CUR_hot_x dw ?
endg
 
iglobal
44,9 → 40,12
dd 3
mouse_timer_ticks dd 0
endg
 
;-----------------------------------------------------------------------------
 
align 4
draw_mouse_under:
 
; return old picture
cmp [_display.restore_cursor], 0
je @F
57,14 → 56,12
stdcall [_display.restore_cursor], eax, ebx
popad
ret
;--------------------------------------
align 4
 
@@:
pushad
xor ecx, ecx
xor edx, edx
;--------------------------------------
align 4
 
mres:
movzx eax, word [X_UNDER]
movzx ebx, word [Y_UNDER]
97,7 → 94,9
jnz mres
popad
ret
 
;-----------------------------------------------------------------------------
 
align 4
save_draw_mouse:
cmp [_display.move_cursor], 0
111,6 → 110,9
push eax
push ebx
 
; mov ecx, [Screen_Max_X]
; inc ecx
; mul ecx
mov eax, [d_width_calc_area + eax*4]
 
add eax, [_WinMapAddress]
174,7 → 176,9
add ebx, edx
push ecx
or ecx, 0x04000000 ; don't load to mouseunder area
call getpixel
push eax ebx edx edi
call [GETPIXEL]
pop edi edx ebx eax
mov [COLOR_TEMP], ecx
pop ecx
mov eax, edx
226,7 → 230,9
add esp, 8
popad
ret
 
;-----------------------------------------------------------------------------
 
align 4
combine_colors:
; in
241,7 → 247,7
push edx
push ecx
xor ecx, ecx
; byte 2
; byte 0
mov eax, 0xff
sub al, [esi+0]
mov ebx, [esp]
295,7 → 301,9
pop ebx
pop eax
ret
 
;-----------------------------------------------------------------------------
 
align 4
check_mouse_area_for_getpixel:
; in:
338,13 → 346,14
or ecx, 0xff000000
pop ebx eax
ret
;--------------------------------------
align 4
 
.no_mouse_area:
xor ecx, ecx
pop ebx eax
ret
 
;-----------------------------------------------------------------------------
 
align 4
check_mouse_area_for_putpixel:
; in:
364,7 → 373,7
sub cx, [Y_UNDER] ;[MOUSE_Y]
mov ax, cx
shl eax, 16
;--------------------------------------
 
; check for X
mov ax, [X_UNDER] ;[MOUSE_X]
shr ecx, 16
376,7 → 385,7
; offset X
sub cx, [X_UNDER] ;[MOUSE_X]
mov ax, cx
;--------------------------------------
 
; eax = (offset y) shl 16 + (offset x)
 
pop ecx
408,17 → 417,15
add esi, 16*24*3
call combine_colors
pop edi esi
;--------------------------------------
align 4
.end:
mov eax, ecx
ret
;--------------------------------------
align 4
 
.no_mouse_area:
pop eax
ret
 
;-----------------------------------------------------------------------------
 
align 4
__sys_draw_pointer:
pushad
430,14 → 437,14
je @f
mov [redrawmouse_unconditional], 0
jmp redrawmouse
;--------------------------------------
align 4
@@:
cmp eax, ecx
jne redrawmouse
cmp ebx, edx
je nodmp
 
;--------------------------------------
 
align 4
redrawmouse:
pushfd
465,62 → 472,62
mov [X_UNDER_subtraction_CUR_hot_x], ax
add eax, [cur.w]
mov [X_UNDER_sub_CUR_hot_x_add_curh], ax
;--------------------------------------
align 4
@@:
popfd
;--------------------------------------
align 4
nodmp:
popad
ret
 
;-----------------------------------------------------------------------------
 
align 4
proc set_mouse_data stdcall, BtnState:dword, XMoving:dword, YMoving:dword, VScroll:dword, HScroll:dword
proc set_mouse_data stdcall uses edx, BtnState:dword, XMoving:dword, YMoving:dword, VScroll:dword, HScroll:dword
 
mov eax, [BtnState]
and eax, 0x3FFFFFFF ; Top 2 bits are used to flag absolute movements
mov [BTN_DOWN], eax
 
;--------------------------------------
mov eax, [XMoving]
test [BtnState], 0x80000000
jnz .absolute_x
call mouse_acceleration
add ax, [MOUSE_X];[XCoordinate]
add ax, [MOUSE_X]
cmp ax, 0
jge @@M1
jge .check_x
mov eax, 0
jmp @@M2
jmp .set_x
.absolute_x:
mov edx, [_display.width]
mul edx
shr eax, 15
.check_x:
cmp ax, word[Screen_Max_X]
jl .set_x
mov ax, word[Screen_Max_X]
.set_x:
mov [MOUSE_X], ax
;--------------------------------------
align 4
@@M1:
cmp ax, word [_display.width]
jl @@M2
mov ax, word [_display.width]
dec ax
;--------------------------------------
align 4
@@M2:
mov [MOUSE_X], ax;[XCoordinate]
 
mov eax, [YMoving]
test [BtnState], 0x40000000
jnz .absolute_y
neg eax
call mouse_acceleration
 
add ax, [MOUSE_Y];[YCoordinate]
add ax, [MOUSE_Y]
cmp ax, 0
jge @@M3
jge .check_y
mov ax, 0
jmp @@M4
jmp .set_y
.absolute_y:
mov edx, [_display.height]
mul edx
shr eax, 15
.check_y:
cmp ax, word[Screen_Max_Y]
jl .set_y
mov ax, word[Screen_Max_Y]
.set_y:
mov [MOUSE_Y], ax
;--------------------------------------
align 4
@@M3:
cmp ax, word [_display.height]
jl @@M4
mov ax, word [_display.height]
dec ax
;--------------------------------------
align 4
@@M4:
mov [MOUSE_Y], ax;[YCoordinate]
 
mov eax, [VScroll]
add [MOUSE_SCROLL_V], ax
 
533,7 → 540,9
call wakeup_osloop
ret
endp
 
;-----------------------------------------------------------------------------
 
align 4
mouse_acceleration:
push eax
545,8 → 554,5
;push edx
imul eax, [mouse_speed_factor]
;pop edx
;--------------------------------------
align 4
@@:
ret
;-----------------------------------------------------------------------------
/kernel/branches/Kolibri-acpi/init.inc
128,12 → 128,12
mov [pg_data.kernel_tables-OS_BASE], edx
 
xor eax, eax
mov edi, sys_pgdir-OS_BASE
mov ecx, 4096/4
mov edi, sys_proc-OS_BASE
mov ecx, 8192/4
cld
rep stosd
 
mov edx, (sys_pgdir-OS_BASE)+ 0x800; (OS_BASE shr 20)
mov edx, (sys_proc-OS_BASE+PROC.pdt_0)+ 0x800; (OS_BASE shr 20)
bt [cpu_caps-OS_BASE], CAPS_PSE
jnc .no_PSE
 
177,9 → 177,9
dec ecx
jnz .map_kernel_tabs
 
mov dword [sys_pgdir-OS_BASE+(page_tabs shr 20)], sys_pgdir+PG_SW-OS_BASE
mov dword [sys_proc-OS_BASE+PROC.pdt_0+(page_tabs shr 20)], sys_proc+PROC.pdt_0+PG_SW-OS_BASE
 
mov edi, (sys_pgdir-OS_BASE)
mov edi, (sys_proc+PROC.pdt_0-OS_BASE)
lea esi, [edi+(OS_BASE shr 20)]
movsd
movsd
345,9 → 345,6
proc test_cpu
locals
cpu_type dd ?
cpu_id dd ?
cpu_Intel dd ?
cpu_AMD dd ?
endl
 
xor eax, eax
354,6 → 351,7
mov [cpu_type], eax
mov [cpu_caps-OS_BASE], eax
mov [cpu_caps+4-OS_BASE], eax
mov [cpu_phys_addr_width-OS_BASE], 32
 
pushfd
pop eax
378,7 → 376,6
pop eax
xor eax, ecx
je .end_cpuid
mov [cpu_id], 1
 
xor eax, eax
cpuid
386,13 → 383,7
mov [cpu_vendor-OS_BASE], ebx
mov [cpu_vendor+4-OS_BASE], edx
mov [cpu_vendor+8-OS_BASE], ecx
cmp ebx, dword [intel_str-OS_BASE]
jne .check_AMD
cmp edx, dword [intel_str+4-OS_BASE]
jne .check_AMD
cmp ecx, dword [intel_str+8-OS_BASE]
jne .check_AMD
mov [cpu_Intel], 1
 
cmp eax, 1
jl .end_cpuid
mov eax, 1
402,6 → 393,20
mov [cpu_caps-OS_BASE], edx
mov [cpu_caps+4-OS_BASE], ecx
 
bt edx, CAPS_PAE
jnc @f
mov [cpu_phys_addr_width-OS_BASE], 36
@@:
mov eax, 0x80000000
cpuid
cmp eax, 0x80000008
jb @f
mov eax, 0x80000008
cpuid
mov [cpu_phys_addr_width-OS_BASE], al
@@:
 
mov eax, [cpu_sign-OS_BASE]
shr eax, 8
and eax, 0x0f
ret
408,36 → 413,6
.end_cpuid:
mov eax, [cpu_type]
ret
 
.check_AMD:
cmp ebx, dword [AMD_str-OS_BASE]
jne .unknown
cmp edx, dword [AMD_str+4-OS_BASE]
jne .unknown
cmp ecx, dword [AMD_str+8-OS_BASE]
jne .unknown
mov [cpu_AMD], 1
cmp eax, 1
jl .unknown
mov eax, 1
cpuid
mov [cpu_sign-OS_BASE], eax
mov [cpu_info-OS_BASE], ebx
mov [cpu_caps-OS_BASE], edx
mov [cpu_caps+4-OS_BASE], ecx
shr eax, 8
and eax, 0x0f
ret
.unknown:
mov eax, 1
cpuid
mov [cpu_sign-OS_BASE], eax
mov [cpu_info-OS_BASE], ebx
mov [cpu_caps-OS_BASE], edx
mov [cpu_caps+4-OS_BASE], ecx
shr eax, 8
and eax, 0x0f
ret
endp
 
iglobal
/kernel/branches/Kolibri-acpi/kernel.asm
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved.
;; PROGRAMMING:
;; Ivan Poddubny
;; Marat Zakiyanov (Mario79)
291,7 → 291,7
 
; ENABLE PAGING
 
mov eax, sys_pgdir-OS_BASE
mov eax, sys_proc-OS_BASE+PROC.pdt_0
mov cr3, eax
 
mov eax, cr0
309,6 → 309,25
org $-0x10000
include "boot/shutdown.inc" ; shutdown or restart
org $+0x10000
 
ap_init16:
cli
lgdt [cs:gdts_ap-ap_init16]
mov eax, [cs:cr3_ap-ap_init16]
mov cr3, eax
mov eax, [cs:cr4_ap-ap_init16]
mov cr4, eax
mov eax, CR0_PE+CR0_PG+CR0_WP
mov cr0, eax
jmp pword os_code:ap_init_high
align 16
gdts_ap:
dw gdte-gdts-1
dd gdts
dw 0
cr3_ap dd ?
cr4_ap dd ?
ap_init16_size = $ - ap_init16
use32
 
__DEBUG__ fix 1
335,7 → 354,7
bt [cpu_caps], CAPS_PGE
jnc @F
 
or dword [sys_pgdir+(OS_BASE shr 20)], PG_GLOBAL
or dword [sys_proc+PROC.pdt_0+(OS_BASE shr 20)], PG_GLOBAL
 
mov ebx, cr4
or ebx, CR4_PGE
342,8 → 361,8
mov cr4, ebx
@@:
xor eax, eax
mov dword [sys_pgdir], eax
mov dword [sys_pgdir+4], eax
mov dword [sys_proc+PROC.pdt_0], eax
mov dword [sys_proc+PROC.pdt_0+4], eax
 
mov eax, cr3
mov cr3, eax ; flush TLB
369,78 → 388,17
call mutex_init
mov ecx, ide_channel2_mutex
call mutex_init
mov ecx, ide_channel3_mutex
call mutex_init
mov ecx, ide_channel4_mutex
call mutex_init
mov ecx, ide_channel5_mutex
call mutex_init
mov ecx, ide_channel6_mutex
call mutex_init
;-----------------------------------------------------------------------------
; SAVE REAL MODE VARIABLES
;-----------------------------------------------------------------------------
save_variables_IDE_controller:
xor eax, eax
mov ax, [BOOT_VARS + BOOT_IDE_INTERR_16]
mov [IDE_Interrupt], ax
;--------------------------------------
mov ax, [BOOT_VARS + BOOT_IDE_PI_16]
mov [IDEContrProgrammingInterface], ax
;--------------------------------------
mov ax, [BOOT_VARS + BOOT_IDE_BASE_ADDR]
mov [IDEContrRegsBaseAddr], ax
;--------------------------------------
mov ax, [BOOT_VARS + BOOT_IDE_BAR0_16]
cmp ax, 0
je @f
cmp ax, 1
jne .no_PATA_BAR0
@@:
mov ax, 0x1F0
jmp @f
.no_PATA_BAR0:
and ax, 0xFFFC
@@:
mov [StandardATABases], ax
mov [hd_address_table], eax
mov [hd_address_table+8], eax
mov [IDE_BAR0_val], ax
;--------------------------------------
mov ax, [BOOT_VARS + BOOT_IDE_BAR1_16]
cmp ax, 0
je @f
cmp ax, 1
jne .no_PATA_BAR1
@@:
mov ax, 0x3F4
jmp @f
.no_PATA_BAR1:
and ax, 0xFFFC
@@:
mov [IDE_BAR1_val], ax
;--------------------------------------
mov ax, [BOOT_VARS + BOOT_IDE_BAR2_16]
cmp ax, 0
je @f
cmp ax, 1
jne .no_PATA_BAR2
@@:
mov ax, 0x170
jmp @f
.no_PATA_BAR2:
and ax, 0xFFFC
@@:
mov [StandardATABases+2], ax
mov [hd_address_table+16], eax
mov [hd_address_table+24], eax
mov [IDE_BAR2_val], ax
;--------------------------------------
mov ax, [BOOT_VARS + BOOT_IDE_BAR3_16]
cmp ax, 0
je @f
cmp ax, 1
jne .no_PATA_BAR3
@@:
mov ax, 0x374
jmp @f
.no_PATA_BAR3:
and ax, 0xFFFC
@@:
mov [IDE_BAR3_val], ax
 
; --------------- APM ---------------------
 
; init selectors
476,7 → 434,7
mov al, [BOOT_VARS+BOOT_DMA] ; DMA access
mov [allow_dma_access], al
movzx eax, byte [BOOT_VARS+BOOT_BPP] ; bpp
mov [_display.bpp], eax
mov [_display.bits_per_pixel], eax
mov [_display.vrefresh], 60
mov al, [BOOT_VARS+BOOT_DEBUG_PRINT] ; If nonzero, duplicates debug output to the screen
mov [debug_direct_print], al
486,11 → 444,13
mov [_display.width], eax
mov [display_width_standard], eax
dec eax
mov [Screen_Max_X], eax
mov [screen_workarea.right], eax
movzx eax, word [BOOT_VARS+BOOT_Y_RES]; Y max
mov [_display.height], eax
mov [display_height_standard], eax
dec eax
mov [Screen_Max_Y], eax
mov [screen_workarea.bottom], eax
movzx eax, word [BOOT_VARS+BOOT_VESA_MODE] ; screen mode
mov dword [SCR_MODE], eax
520,34 → 480,56
mov edi, BiosDisksData
rep movsd
 
; GRAPHICS ADDRESSES
setvideomode:
 
mov eax, [BOOT_VARS+BOOT_LFB]
mov [LFBAddress], eax
 
cmp [SCR_MODE], word 0100000000000000b
jge setvesa20
cmp [SCR_MODE], word 0x13 ; EGA 320*200 256 colors
je v20ga32
jmp v20ga24
cmp word [SCR_MODE], 0x0012 ; VGA (640x480 16 colors)
je .vga
cmp word [SCR_MODE], 0x0013 ; MCGA (320*200 256 colors)
je .32bpp
cmp byte [_display.bits_per_pixel], 32
je .32bpp
cmp byte [_display.bits_per_pixel], 24
je .24bpp
cmp byte [_display.bits_per_pixel], 16
je .16bpp
; cmp byte [_display.bits_per_pixel], 15
; je .15bpp
 
setvesa20:
mov [PUTPIXEL], dword Vesa20_putpixel24 ; Vesa 2.0
mov [GETPIXEL], dword Vesa20_getpixel24
cmp byte [_display.bpp], 24
jz v20ga24
v20ga32:
mov [PUTPIXEL], dword Vesa20_putpixel32
mov [GETPIXEL], dword Vesa20_getpixel32
jmp no_mode_0x12
v20ga24:
cmp [SCR_MODE], word 0x12 ; 16 C VGA 640x480
jne no_mode_0x12
mov [PUTPIXEL], dword VGA_putpixel
mov [GETPIXEL], dword Vesa20_getpixel32
no_mode_0x12:
.vga:
mov [PUTPIXEL], VGA_putpixel
mov [GETPIXEL], Vesa20_getpixel32 ; Conversion buffer is 32 bpp
mov [_display.bytes_per_pixel], 4 ; Conversion buffer is 32 bpp
jmp .finish
 
mov [MOUSE_PICTURE], dword mousepointer
; .15bpp:
; mov [PUTPIXEL], Vesa20_putpixel15
; mov [GETPIXEL], Vesa20_getpixel15
; mov [_display.bytes_per_pixel], 2
; jmp .finish
 
.16bpp:
mov [PUTPIXEL], Vesa20_putpixel16
mov [GETPIXEL], Vesa20_getpixel16
mov [_display.bytes_per_pixel], 2
jmp .finish
 
.24bpp:
mov [PUTPIXEL], Vesa20_putpixel24
mov [GETPIXEL], Vesa20_getpixel24
mov [_display.bytes_per_pixel], 3
jmp .finish
 
.32bpp:
mov [PUTPIXEL], Vesa20_putpixel32
mov [GETPIXEL], Vesa20_getpixel32
mov [_display.bytes_per_pixel], 4
; jmp .finish
 
.finish:
mov [MOUSE_PICTURE], mousepointer
mov [_display.check_mouse], check_mouse_area_for_putpixel
mov [_display.check_m_pixel], check_mouse_area_for_getpixel
 
637,7 → 619,7
call init_fpu
call init_malloc
 
stdcall alloc_kernel_space, 0x51000
stdcall alloc_kernel_space, 0x50000 ; FIXME check size
mov [default_io_map], eax
 
add eax, 0x2000
654,9 → 636,6
mov [proc_mem_tab], eax
 
add eax, ebx
mov [tmp_task_pdir], eax
 
add eax, ebx
mov [tmp_task_ptab], eax
 
add eax, ebx
714,7 → 693,26
mov esi, boot_setostask
call boot_log
 
mov edx, SLOT_BASE+256
mov edi, sys_proc
list_init edi
lea ecx, [edi+PROC.thr_list]
list_init ecx
mov [edi+PROC.pdt_0_phys], sys_proc-OS_BASE+PROC.pdt_0
 
mov eax, -1
mov edi, thr_slot_map+4
mov [edi-4], dword 0xFFFFFFF8
stosd
stosd
stosd
stosd
stosd
stosd
stosd
 
mov [current_process], sys_proc
 
mov edx, SLOT_BASE+256*1
mov ebx, [os_stack_seg]
add ebx, 0x2000
call setup_os_slot
737,7 → 735,70
mov dword [current_slot], SLOT_BASE + 256*2
mov dword [TASK_BASE], CURRENT_TASK + 32*2
 
; Move other CPUs to deep sleep, if it is useful
uglobal
use_mwait_for_idle db 0
endg
cmp [cpu_vendor+8], 'ntel'
jnz .no_wake_cpus
bt [cpu_caps+4], CAPS_MONITOR-32
jnc .no_wake_cpus
dbgstr 'using mwait for idle loop'
inc [use_mwait_for_idle]
mov ebx, [cpu_count]
cmp ebx, 1
jbe .no_wake_cpus
call create_trampoline_pgmap
mov [cr3_ap+OS_BASE], eax
mov eax, cr4
mov [cr4_ap+OS_BASE], eax
mov esi, OS_BASE + ap_init16
mov edi, OS_BASE + 8000h
mov ecx, (ap_init16_size + 3) / 4
rep movsd
stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_SW+PG_NOCACHE
mov [LAPIC_BASE], eax
lea edi, [eax+300h]
mov esi, smpt+4
dec ebx
.wake_cpus_loop:
lodsd
push esi
xor esi, esi
inc esi
shl eax, 24
mov [edi+10h], eax
; assert INIT IPI
mov dword [edi], 0C500h
call delay_ms
@@:
test dword [edi], 1000h
jnz @b
; deassert INIT IPI
mov dword [edi], 8500h
call delay_ms
@@:
test dword [edi], 1000h
jnz @b
; send STARTUP IPI
mov dword [edi], 600h + (8000h shr 12)
call delay_ms
@@:
test dword [edi], 1000h
jnz @b
pop esi
dec ebx
jnz .wake_cpus_loop
mov eax, [cpu_count]
dec eax
@@:
cmp [ap_initialized], eax
jnz @b
mov eax, [cr3_ap+OS_BASE]
call free_page
.no_wake_cpus:
 
 
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f
mov esi, boot_initirq
call boot_log
758,10 → 819,12
call PIT_init
 
; Register ramdisk file system
mov esi, boot_initramdisk
call boot_log
call ramdisk_init
cmp [boot_dev+OS_BASE+0x10000], 1
je @f
 
call register_ramdisk
;--------------------------------------
@@:
mov esi, boot_initapic
call boot_log
; Try to Initialize APIC
775,58 → 838,77
stdcall enable_irq, 2 ; @#$%! PIC
stdcall enable_irq, 13 ; co-processor
 
cmp [IDEContrProgrammingInterface], 0
je @f
; Setup serial output console (if enabled)
if defined debug_com_base
 
mov esi, boot_disabling_ide
call boot_log
;--------------------------------------
; Disable IDE interrupts, because the search
; for IDE partitions is in the PIO mode.
;--------------------------------------
.disable_IDE_interrupt:
; Disable interrupts in IDE controller for PIO
mov al, 2
mov dx, [IDE_BAR1_val] ;0x3F4
add dx, 2 ;0x3F6
; reserve port so nobody else will use it
xor ebx, ebx
mov ecx, debug_com_base
mov edx, debug_com_base+7
call r_f_port_area
 
; enable Divisor latch
mov dx, debug_com_base+3
mov al, 1 shl 7
out dx, al
mov dx, [IDE_BAR3_val] ;0x374
add dx, 2 ;0x376
 
; Set speed to 115200 baud (max speed)
mov dx, debug_com_base
mov al, 0x01
out dx, al
 
mov dx, debug_com_base+1
mov al, 0x00
out dx, al
 
; No parity, 8bits words, one stop bit, dlab bit back to 0
mov dx, debug_com_base+3
mov al, 3
out dx, al
 
; disable interrupts
mov dx, debug_com_base+1
mov al, 0
out dx, al
 
; clear + enable fifo (64 bits)
mov dx, debug_com_base+2
mov al, 0x7 + 1 shl 5
out dx, al
 
end if
 
 
;-----------------------------------------------------------------------------
; show SVN version of kernel on the message board
;-----------------------------------------------------------------------------
mov eax, [version_inf.rev]
DEBUGF 1, "K : kernel SVN r%d\n", eax
;-----------------------------------------------------------------------------
; show CPU count on the message board
;-----------------------------------------------------------------------------
mov eax, [cpu_count]
test eax, eax
jnz @F
mov al, 1 ; at least one CPU
@@:
DEBUGF 1, "K : %d CPU detected\n", eax
;-----------------------------------------------------------------------------
;!!!!!!!!!!!!!!!!!!!!!!!!!!
; mov esi, boot_detectdisks
; call boot_log
;include 'detect/disks.inc'
; detect Floppy drives
;-----------------------------------------------------------------------------
mov esi, boot_detectfloppy
call boot_log
include 'detect/dev_fd.inc'
mov esi, boot_detecthdcd
call boot_log
include 'detect/dev_hdcd.inc'
mov esi, boot_getcache
call boot_log
include 'detect/getcache.inc'
mov esi, boot_detectpart
call boot_log
include 'detect/sear_par.inc'
;!!!!!!!!!!!!!!!!!!!!!!!!!!
 
mov esi, boot_init_sys
call boot_log
call Parser_params
 
if ~ defined extended_primary_loader
; ramdisk image should be loaded by extended primary loader if it exists
; READ RAMDISK IMAGE FROM HD
 
;!!!!!!!!!!!!!!!!!!!!!!!
include 'boot/rdload.inc'
;!!!!!!!!!!!!!!!!!!!!!!!
end if
; mov [dma_hdd],1
 
;-----------------------------------------------------------------------------
; create pci-devices list
;-----------------------------------------------------------------------------
mov [pci_access_enabled], 1
call pci_enum
;-----------------------------------------------------------------------------
; initialisation IDE ATA code
;-----------------------------------------------------------------------------
include 'detect/init_ata.inc'
;-----------------------------------------------------------------------------
if 0
mov ax, [OS_BASE+0x10000+bx_from_load]
cmp ax, 'r1'; if using not ram disk, then load librares and parameters {SPraid.simba}
877,11 → 959,12
; mov esi, boot_devices
; call boot_log
 
mov [pci_access_enabled], 1
call pci_enum
call clear_pci_ide_interrupts
 
stdcall load_driver, szVidintel
include "detect/vortex86.inc" ; Vortex86 SoC detection code
 
stdcall load_pe_driver, szVidintel, 0
 
call usb_init
 
; SET PRELIMINARY WINDOW STACK AND POSITIONS
919,6 → 1002,7
mov esi, 250 ; wait 1/4 a second
call delay_ms
rdtsc
sti
 
sub eax, ecx
xor edx, edx
986,39 → 1070,12
stdcall map_page, tss._io_map_1, \
[SLOT_BASE+256+APPDATA.io_map+4], PG_MAP
 
; LOAD FIRST APPLICATION
cmp byte [launcher_start], 1 ; Check if starting LAUNCHER is selected on blue screen (1 = yes)
jnz first_app_found
 
cli
mov ebp, firstapp
call fs_execute_from_sysdir
test eax, eax
jns first_app_found
 
mov esi, boot_failed
call boot_log
 
mov eax, 0xDEADBEEF ; otherwise halt
hlt
 
first_app_found:
 
cli
 
; SET KEYBOARD PARAMETERS
mov al, 0xf6 ; reset keyboard, scan enabled
call kb_write
call kb_write_wait_ack
test ah, ah
jnz .no_keyboard
 
; wait until 8042 is ready
xor ecx, ecx
@@:
in al, 64h
and al, 00000010b
loopnz @b
 
iglobal
align 4
ps2_keyboard_functions:
1029,94 → 1086,47
endg
stdcall register_keyboard, ps2_keyboard_functions, 0
; mov al, 0xED ; Keyboard LEDs - only for testing!
; call kb_write
; call kb_read
; call kb_write_wait_ack
; mov al, 111b
; call kb_write
; call kb_read
; call kb_write_wait_ack
 
mov al, 0xF3 ; set repeat rate & delay
call kb_write
; call kb_read
call kb_write_wait_ack
mov al, 0; 30 250 ;00100010b ; 24 500 ;00100100b ; 20 500
call kb_write
; call kb_read
call kb_write_wait_ack
;// mike.dld [
call set_lights
;// mike.dld ]
stdcall attach_int_handler, 1, irq1, 0
DEBUGF 1, "K : IRQ1 error code %x\n", eax
DEBUGF 1, "K : IRQ1 return code %x\n", eax
.no_keyboard:
 
; SET MOUSE
; Load PS/2 mouse driver
 
stdcall load_driver, szPS2MDriver
; stdcall load_driver, szCOM_MDriver
stdcall load_pe_driver, szPS2MDriver, 0
 
mov esi, boot_setmouse
call boot_log
call setmouse
 
; Setup serial output console (if enabled)
; LOAD FIRST APPLICATION
cmp byte [launcher_start], 1 ; Check if starting LAUNCHER is selected on blue screen (1 = yes)
jnz first_app_found
 
if defined debug_com_base
cli
mov ebp, firstapp
call fs_execute_from_sysdir
test eax, eax
jns first_app_found
 
; enable Divisor latch
mov esi, boot_failed
call boot_log
 
mov dx, debug_com_base+3
mov al, 1 shl 7
out dx, al
mov eax, 0xDEADBEEF ; otherwise halt
hlt
 
; Set speed to 115200 baud (max speed)
first_app_found:
 
mov dx, debug_com_base
mov al, 0x01
out dx, al
 
mov dx, debug_com_base+1
mov al, 0x00
out dx, al
 
; No parity, 8bits words, one stop bit, dlab bit back to 0
 
mov dx, debug_com_base+3
mov al, 3
out dx, al
 
; disable interrupts
 
mov dx, debug_com_base+1
mov al, 0
out dx, al
 
; clear + enable fifo (64 bits)
 
mov dx, debug_com_base+2
mov al, 0x7 + 1 shl 5
out dx, al
 
 
end if
mov eax, [version_inf.rev]
DEBUGF 1, "K : kernel SVN r%d\n", eax
 
mov eax, [cpu_count]
test eax, eax
jnz @F
mov al, 1 ; at least one CPU
@@:
DEBUGF 1, "K : %d CPU detected\n", eax
 
include "detect/vortex86.inc" ; Vortex86 SoC detection code
 
DEBUGF 1, "K : BAR0 %x \n", [IDE_BAR0_val]:4
DEBUGF 1, "K : BAR1 %x \n", [IDE_BAR1_val]:4
DEBUGF 1, "K : BAR2 %x \n", [IDE_BAR2_val]:4
DEBUGF 1, "K : BAR3 %x \n", [IDE_BAR3_val]:4
DEBUGF 1, "K : BAR4 %x \n", [IDEContrRegsBaseAddr]:4
DEBUGF 1, "K : IDEContrProgrammingInterface %x \n", [IDEContrProgrammingInterface]:4
DEBUGF 1, "K : IDE_Interrupt %x \n", [IDE_Interrupt]:4
 
; START MULTITASKING
 
; A 'All set - press ESC to start' messages if need
1129,104 → 1139,38
jne .bll1
end if
 
push eax edx
mov dx, [IDEContrRegsBaseAddr]
xor eax, eax
add dx, 2
in al, dx
DEBUGF 1, "K : Primary Bus Master IDE Status Register %x\n", eax
mov [timer_ticks_enable], 1 ; for cd driver
 
add dx, 8
in al, dx
DEBUGF 1, "K : Secondary Bus Master IDE Status Register %x\n", eax
pop edx eax
sti
 
cmp [IDEContrRegsBaseAddr], 0
setnz [dma_hdd]
call mtrr_validate
 
cmp [IDEContrProgrammingInterface], 0
je set_interrupts_for_IDE_controllers.continue
jmp osloop
 
mov ax, [IDE_Interrupt]
cmp al, 0xff
jne @f
 
mov [dma_hdd], 0
jmp set_interrupts_for_IDE_controllers.end_set_interrupts
@@:
;-----------------------------------------------------------------------------
; set interrupts for IDE Controller
;-----------------------------------------------------------------------------
mov esi, boot_set_int_IDE
call boot_log
set_interrupts_for_IDE_controllers:
mov ax, [IDEContrProgrammingInterface]
cmp ax, 0x0180
je .pata_ide
; Fly :)
 
cmp ax, 0x018a
jne .sata_ide
;--------------------------------------
.pata_ide:
cmp [IDEContrRegsBaseAddr], 0
je .end_set_interrupts
uglobal
align 4
ap_initialized dd 0
endg
 
stdcall attach_int_handler, 14, IDE_irq_14_handler, 0
DEBUGF 1, "K : Set IDE IRQ14 return code %x\n", eax
stdcall attach_int_handler, 15, IDE_irq_15_handler, 0
DEBUGF 1, "K : Set IDE IRQ15 return code %x\n", eax
jmp .enable_IDE_interrupt
;--------------------------------------
.sata_ide:
cmp ax, 0x0185
je .sata_ide_1
ap_init_high:
mov ax, os_stack
mov bx, app_data
mov cx, app_tls
mov ss, ax
mov ds, bx
mov es, bx
mov fs, cx
mov gs, bx
xor esp, esp
mov eax, sys_proc-OS_BASE+PROC.pdt_0
mov cr3, eax
lock inc [ap_initialized]
jmp idle_loop
 
cmp ax, 0x018f
jne .end_set_interrupts
;--------------------------------------
.sata_ide_1:
cmp [IDEContrRegsBaseAddr], 0
je .end_set_interrupts
 
mov ax, [IDE_Interrupt]
movzx eax, al
stdcall attach_int_handler, eax, IDE_common_irq_handler, 0
DEBUGF 1, "K : Set IDE IRQ%d return code %x\n", [IDE_Interrupt]:1, eax
;--------------------------------------
.enable_IDE_interrupt:
mov esi, boot_enabling_ide
call boot_log
; Enable interrupts in IDE controller for DMA
mov al, 0
mov dx, [IDE_BAR1_val] ;0x3F4
add dx, 2 ;0x3F6
out dx, al
mov dx, [IDE_BAR3_val] ;0x374
add dx, 2 ;0x376
out dx, al
;--------------------------------------
.end_set_interrupts:
;-----------------------------------------------------------------------------
cmp [dma_hdd], 0
je .print_pio
.print_dma:
DEBUGF 1, "K : IDE DMA mode\n"
jmp .continue
 
.print_pio:
DEBUGF 1, "K : IDE PIO mode\n"
.continue:
 
mov [timer_ticks_enable], 1 ; for cd driver
 
sti
; call change_task
 
jmp osloop
 
 
; Fly :)
 
include 'unpacker.inc'
 
align 4
1284,8 → 1228,12
 
mov dword [edx+APPDATA.cur_dir], sysdir_path
 
mov [edx + APPDATA.dir_table], sys_pgdir - OS_BASE
mov [edx + APPDATA.process], sys_proc
 
lea ebx, [edx+APPDATA.list]
lea ecx, [sys_proc+PROC.thr_list]
list_add_tail ebx, ecx
 
mov eax, edx
shr eax, 3
add eax, CURRENT_TASK - (SLOT_BASE shr 3)
1309,12 → 1257,13
xchg eax, [osloop_nonperiodic_work]
test eax, eax
jz .no_periodic
; call [draw_pointer]
 
call __sys_draw_pointer
call window_check_events
call mouse_check_events
call checkmisc
call checkVga_N13
;--------------------------------------
.no_periodic:
call stack_handler
call check_fdd_motor_status
1321,6 → 1270,7
call check_ATAPI_device_event
call check_lights_state
call check_timers
 
jmp osloop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
1359,13 → 1309,35
osloop_nonperiodic_work dd ?
endg
 
align 4
uglobal
align 64
idle_addr rb 64
endg
 
idle_thread:
sti
 
; The following code can be executed by all CPUs in the system.
; All other parts of the kernel do not expect multi-CPU.
; Also, APs don't even have a stack here.
; Beware. Don't do anything here. Anything at all.
idle_loop:
cmp [use_mwait_for_idle], 0
jnz idle_loop_mwait
 
idle_loop_hlt:
hlt
jmp idle_loop
jmp idle_loop_hlt
 
idle_loop_mwait:
mov eax, idle_addr
xor ecx, ecx
xor edx, edx
monitor
xor ecx, ecx
mov eax, 20h ; or 10h
mwait
jmp idle_loop_mwait
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1688,280 → 1660,231
mov eax, [esp+64+8] ; background color (if given)
mov edi, [esp+64+4]
jmp dtext
 
;-----------------------------------------------------------------------------
iglobal
midi_base dw 0
endg
;-----------------------------------------------------------------------------
align 4
 
sys_setup:
 
; 1=roland mpu midi base , base io address
; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus
; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave
; 3 = not used
; 4 = not used
; 5=system language, 1eng 2fi 3ger 4rus
; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave
; 8=fat32 partition in hd
; 9
; 10 = sound dma channel
; 6 = not used
; 7 = not used
; 8 = not used
; 9 = not used
; 10 = not used
; 11 = enable lba read
; 12 = enable pci access
;-----------------------------------------------------------------------------
and [esp+32], dword 0
; F.21.1 - set MPU MIDI base port
dec ebx
jnz @f
 
 
and [esp+32], dword 0
dec ebx ; MIDI
jnz nsyse1
cmp ecx, 0x100
jb @f
 
jb nsyse1
mov esi, 65535
cmp esi, ecx
jb @f
 
jb nsyse1
mov [midi_base], cx ;bx
mov word [mididp], cx;bx
inc cx ;bx
mov word [midisp], cx;bx
mov [midi_base], cx
mov word [mididp], cx
inc cx
mov word [midisp], cx
ret
;--------------------------------------
@@:
; F.21.2 - set keyboard layout
dec ebx
jnz @f
 
iglobal
midi_base dw 0
endg
 
nsyse1:
dec ebx ; KEYBOARD
jnz nsyse2
mov edi, [TASK_BASE]
mov eax, [edi+TASKDATA.mem_start]
add eax, edx
; 1 = normal layout
dec ecx
jnz .shift
 
dec ecx
jnz kbnobase
mov ebx, keymap
mov ecx, 128
call memmove
ret
kbnobase:
;--------------------------------------
.shift:
; 2 = layout at pressed Shift
dec ecx
jnz kbnoshift
jnz .alt
 
mov ebx, keymap_shift
mov ecx, 128
call memmove
ret
kbnoshift:
;--------------------------------------
.alt:
; 3 = layout at pressed Alt
dec ecx
jnz kbnoalt
jnz .country
 
mov ebx, keymap_alt
mov ecx, 128
call memmove
ret
kbnoalt:
;--------------------------------------
.country:
; country identifier
sub ecx, 6
jnz kbnocountry
jnz .error
 
mov word [keyboard], dx
ret
kbnocountry:
mov [esp+32], dword 1
ret
nsyse2:
dec ebx ; CD
jnz nsyse4
;--------------------------------------
@@:
; F.21.5 - set system language
sub ebx, 3
jnz @f
 
test ecx, ecx
jz nosesl
 
cmp ecx, 4
ja nosesl
mov [cd_base], cl
 
dec ecx
jnz noprma
mov eax, [hd_address_table]
mov [cdbase], eax ;0x1f0
mov [cdid], 0xa0
noprma:
 
dec ecx
jnz noprsl
mov eax, [hd_address_table]
mov [cdbase], eax ;0x1f0
mov [cdid], 0xb0
noprsl:
dec ecx
jnz nosema
mov eax, [hd_address_table+16]
mov [cdbase], eax ;0x170
mov [cdid], 0xa0
nosema:
dec ecx
jnz nosesl
mov eax, [hd_address_table+16]
mov [cdbase], eax ;0x170
mov [cdid], 0xb0
nosesl:
ret
 
iglobal
cd_base db 0
 
endg
nsyse4:
 
sub ebx, 2 ; SYSTEM LANGUAGE
jnz nsyse5
mov [syslang], ecx
ret
nsyse5:
;--------------------------------------
@@:
; F.21.11 - enable/disable low-level access to HD
and ecx, 1
sub ebx, 6
jnz @f
 
sub ebx, 2 ; HD BASE - obsolete
jnz nsyse7
 
nosethd:
mov [lba_read_enabled], ecx
ret
 
nsyse7:
 
; cmp eax,8 ; HD PARTITION - obsolete
;--------------------------------------
@@:
; F.21.12 - enable/disable low-level access to PCI
dec ebx
jnz nsyse8
ret
jnz .error
 
nsyse8:
; cmp eax,11 ; ENABLE LBA READ
and ecx, 1
sub ebx, 3
jnz no_set_lba_read
mov [lba_read_enabled], ecx
ret
 
no_set_lba_read:
; cmp eax,12 ; ENABLE PCI ACCESS
dec ebx
jnz sys_setup_err
mov [pci_access_enabled], ecx
ret
 
sys_setup_err:
;--------------------------------------
.error:
or [esp+32], dword -1
ret
 
;-----------------------------------------------------------------------------
align 4
 
sys_getsetup:
 
; 1=roland mpu midi base , base io address
; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus
; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave
; 3 = not used
; 4 = not used
; 5=system language, 1eng 2fi 3ger 4rus
; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave
; 8=fat32 partition in hd
; 6 = not used
; 7 = not used
; 8 = not used
; 9=get hs timer tic
; 10 = not used
; 11 = get the state "lba read"
; 12 = get the state "pci access"
;-----------------------------------------------------------------------------
; F.26.1 - get MPU MIDI base port
dec ebx
jnz @f
 
; cmp eax,1
dec ebx
jnz ngsyse1
movzx eax, [midi_base]
mov [esp+32], eax
ret
ngsyse1:
; cmp eax,2
;--------------------------------------
@@:
; F.26.2 - get keyboard layout
dec ebx
jnz ngsyse2
jnz @f
 
mov edi, [TASK_BASE]
mov ebx, [edi+TASKDATA.mem_start]
add ebx, edx
; 1 = normal layout
dec ecx
jnz .shift
 
; cmp ebx,1
dec ecx
jnz kbnobaseret
mov eax, keymap
mov ecx, 128
call memmove
ret
kbnobaseret:
; cmp ebx,2
;--------------------------------------
.shift:
; 2 = layout with pressed Shift
dec ecx
jnz kbnoshiftret
jnz .alt
 
mov eax, keymap_shift
mov ecx, 128
call memmove
ret
kbnoshiftret:
; cmp ebx,3
;--------------------------------------
.alt:
; 3 = layout with pressed Alt
dec ecx
jne kbnoaltret
jne .country
 
mov eax, keymap_alt
mov ecx, 128
call memmove
ret
kbnoaltret:
; cmp ebx,9
;--------------------------------------
.country:
; 9 = country identifier
sub ecx, 6
jnz ngsyse2
jnz .error
 
movzx eax, word [keyboard]
mov [esp+32], eax
ret
;--------------------------------------
@@:
; F.26.5 - get system language
sub ebx, 3
jnz @f
 
 
ngsyse2:
; cmp eax,3
dec ebx
jnz ngsyse3
movzx eax, [cd_base]
mov [esp+32], eax
ret
ngsyse3:
; cmp eax,5
sub ebx, 2
jnz ngsyse5
mov eax, [syslang]
mov [esp+32], eax
ret
ngsyse5:
; cmp eax,7
sub ebx, 2
jnz ngsyse7
xor eax, eax
;--------------------------------------
@@:
; F.26.9 - get the value of the time counter
sub ebx, 4
jnz @f
 
mov eax, [timer_ticks]
mov [esp+32], eax
ret
ngsyse7:
; cmp eax,8
dec ebx
jnz ngsyse8
mov eax, [fat32part]
mov [esp+32], eax
ret
ngsyse8:
; cmp eax,9
dec ebx
jnz ngsyse9
mov eax, [timer_ticks];[0xfdf0]
mov [esp+32], eax
ret
ngsyse9:
; cmp eax,11
;--------------------------------------
@@:
; F.26.11 - Find out whether low-level HD access is enabled
sub ebx, 2
jnz ngsyse11
jnz @f
 
mov eax, [lba_read_enabled]
mov [esp+32], eax
ret
ngsyse11:
; cmp eax,12
;--------------------------------------
@@:
; F.26.12 - Find out whether low-level PCI access is enabled
dec ebx
jnz ngsyse12
jnz .error
 
mov eax, [pci_access_enabled]
mov [esp+32], eax
ret
ngsyse12:
mov [esp+32], dword 1
;--------------------------------------
.error:
or [esp+32], dword -1
ret
 
 
;-----------------------------------------------------------------------------
get_timer_ticks:
mov eax, [timer_ticks]
ret
 
;-----------------------------------------------------------------------------
iglobal
align 4
mousefn dd msscreen, mswin, msbutton, msset
1970,7 → 1893,7
dd app_delete_cursor
dd msz
endg
 
;-----------------------------------------------------------------------------
readmousepos:
 
; eax=0 screen relative
2443,27 → 2366,15
;------------------------------------------------------------------------------
align 4
sysfn_getdiskinfo: ; 18.11 = get disk info table
; cmp ecx,1
dec ecx
jnz full_table
small_table:
call for_all_tables
mov ecx, 10
cld
rep movsb
ret
for_all_tables:
jnz .exit
.small_table:
mov edi, edx
mov esi, DRIVE_DATA
ret
full_table:
; cmp ecx,2
dec ecx
jnz exit_for_anyone
call for_all_tables
mov ecx, DRIVE_DATA_SIZE/4
mov ecx, DRIVE_DATA_SIZE ;10
cld
rep movsd
rep movsb
.exit:
ret
;------------------------------------------------------------------------------
sysfn_lastkey: ; 18.12 = return 0 (backward compatibility)
2495,10 → 2406,10
;* mouse centered - start code- Mario79
;mouse_centered:
; push eax
mov eax, [_display.width]
mov eax, [Screen_Max_X]
shr eax, 1
mov [MOUSE_X], ax
mov eax, [_display.height]
mov eax, [Screen_Max_Y]
shr eax, 1
mov [MOUSE_Y], ax
call wakeup_osloop
2540,12 → 2451,13
; cmp ecx,4 ; set mouse pointer position
dec ecx
jnz .set_mouse_button
cmp dx, word[_display.height]
jae .end
cmp dx, word[Screen_Max_Y]
ja .end
rol edx, 16
cmp dx, word[_display.width]
jae .end
cmp dx, word[Screen_Max_X]
ja .end
mov [MOUSE_X], edx
mov [mouse_active], 1
call wakeup_osloop
ret
.set_mouse_button:
2631,7 → 2543,9
mov eax, ecx
mov ecx, [_display.pitch]
mov [_display.width], eax
dec eax
mov [_display.height], edx
dec edx
; eax - new Screen_Max_X
; edx - new Screen_Max_Y
mov [do_not_touch_winmap], 1
2968,22 → 2882,22
jnz nosb9
; ecx = [left]*65536 + [right]
; edx = [top]*65536 + [bottom]
mov eax, [_display.width]
mov ebx, [_display.height]
mov eax, [Screen_Max_X]
mov ebx, [Screen_Max_Y]
; check [right]
cmp cx, ax
jae .exit
ja .exit
; check [left]
ror ecx, 16
cmp cx, ax
jae .exit
ja .exit
; check [bottom]
cmp dx, bx
jae .exit
ja .exit
; check [top]
ror edx, 16
cmp dx, bx
jae .exit
ja .exit
 
movzx eax, cx ; [left]
movzx ebx, dx ; [top]
3021,8 → 2935,8
and [draw_data+32 + RECT.left], 0
and [draw_data+32 + RECT.top], 0
push eax ebx
mov eax, [_display.width]
mov ebx, [_display.height]
mov eax, [Screen_Max_X]
mov ebx, [Screen_Max_Y]
mov [draw_data+32 + RECT.right], eax
mov [draw_data+32 + RECT.bottom], ebx
pop ebx eax
3096,8 → 3010,10
jne .finish
cmp [KEY_COUNT], byte 0
je .finish
movzx eax, byte [KEY_BUFF]
movzx ax, byte [KEY_BUFF + 120 + 2]
shl eax, 8
mov al, byte [KEY_BUFF]
shl eax, 8
push eax
dec byte [KEY_COUNT]
and byte [KEY_COUNT], 127
3106,6 → 3022,9
mov eax, KEY_BUFF + 1
mov ebx, KEY_BUFF
call memmove
add eax, 120 + 2
add ebx, 120 + 2
call memmove
pop eax
;--------------------------------------
align 4
3207,7 → 3126,8
mov edx, 0x100000*16
cmp ecx, 1 shl 5
je .os_mem
mov edx, [SLOT_BASE+ecx*8+APPDATA.mem_size]
mov edx, [SLOT_BASE+ecx*8+APPDATA.process]
mov edx, [edx+PROC.mem_used]
mov eax, std_application_base_address
.os_mem:
stosd
3378,9 → 3298,9
add edx, draw_data - CURRENT_TASK
mov [edx + RECT.left], 0
mov [edx + RECT.top], 0
mov eax, [_display.width]
mov eax, [Screen_Max_X]
mov [edx + RECT.right], eax
mov eax, [_display.height]
mov eax, [Screen_Max_Y]
mov [edx + RECT.bottom], eax
 
srl1:
3679,7 → 3599,7
cmp [edx+TASKDATA.state], 9
jz .nokill
lea edx, [(edx-(CURRENT_TASK and 1FFFFFFFh))*8+SLOT_BASE]
cmp [edx+APPDATA.dir_table], sys_pgdir - OS_BASE
cmp [edx+APPDATA.process], sys_proc
jz .nokill
call request_terminate
jmp .common
4703,114 → 4623,40
; ret
;-----------------------------------------------------------------------------
align 4
kb_read:
kb_write_wait_ack:
 
push ecx edx
 
mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's
kr_loop:
in al, 0x64
test al, 1
jnz kr_ready
loop kr_loop
mov ah, 1
jmp kr_exit
kr_ready:
push ecx
mov ecx, 32
kr_delay:
loop kr_delay
pop ecx
in al, 0x60
xor ah, ah
kr_exit:
 
pop edx ecx
 
ret
;-----------------------------------------------------------------------------
align 4
kb_write:
 
push ecx edx
 
mov dl, al
; mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
; kw_loop1:
; in al,0x64
; test al,0x20
; jz kw_ok1
; loop kw_loop1
; mov ah,1
; jmp kw_exit
; kw_ok1:
in al, 0x60
mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's
kw_loop:
.wait_output_ready:
in al, 0x64
test al, 2
jz kw_ok
loop kw_loop
jz @f
loop .wait_output_ready
mov ah, 1
jmp kw_exit
kw_ok:
jmp .nothing
@@:
mov al, dl
out 0x60, al
mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's
kw_loop3:
mov ecx, 0xfffff; last 0xffff, new value in view of fast CPU's
.wait_ack:
in al, 0x64
test al, 2
jz kw_ok3
loop kw_loop3
test al, 1
jnz @f
loop .wait_ack
mov ah, 1
jmp kw_exit
kw_ok3:
mov ah, 8
kw_loop4:
mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's
kw_loop5:
in al, 0x64
test al, 1
jnz kw_ok4
loop kw_loop5
dec ah
jnz kw_loop4
kw_ok4:
jmp .nothing
@@:
in al, 0x60
xor ah, ah
kw_exit:
 
.nothing:
pop edx ecx
 
ret
;-----------------------------------------------------------------------------
align 4
kb_cmd:
 
mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's
c_wait:
in al, 0x64
test al, 2
jz c_send
loop c_wait
jmp c_error
c_send:
mov al, bl
out 0x64, al
mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's
c_accept:
in al, 0x64
test al, 2
jz c_ok
loop c_accept
c_error:
mov ah, 1
jmp c_exit
c_ok:
xor ah, ah
c_exit:
ret
 
 
setmouse: ; set mousepicture -pointer
; ps2 mouse enable
 
4947,9 → 4793,9
jnz @f
mov word [msg_board_pos+2], (42*6)
add word [msg_board_pos], 10
mov ax, word [_display.height]
mov ax, word [Screen_Max_Y]
cmp word [msg_board_pos], ax
jb @f
jbe @f
mov word [msg_board_pos], 10
@@:
; // end if
5166,14 → 5012,14
 
 
.1: ; resolution
mov eax, [_display.width]
mov eax, [Screen_Max_X]
shl eax, 16
mov ax, word [_display.height]
mov ax, word [Screen_Max_Y]
add eax, 0x00010001
mov [esp+32], eax
ret
.2: ; bits per pixel
mov eax, [_display.bpp]
mov eax, [_display.bits_per_pixel]
mov [esp+32], eax
ret
.3: ; bytes per scanline
5254,43 → 5100,66
 
align 4
syscall_getscreensize: ; GetScreenSize
mov ax, word [_display.width]
mov ax, word [Screen_Max_X]
shl eax, 16
mov ax, word [_display.height]
mov ax, word [Screen_Max_Y]
mov [esp + 32], eax
ret
 
;-----------------------------------------------------------------------------
align 4
syscall_cdaudio:
; ECX - position of CD/DVD-drive
; from 0=Primary Master to 3=Secondary Slave for first IDE contr.
; from 4=Primary Master to 7=Secondary Slave for second IDE contr.
; from 8=Primary Master to 11=Secondary Slave for third IDE contr.
cmp ecx, 11
ja .exit
 
syscall_cdaudio: ; CD
mov eax, ecx
shr eax, 2
lea eax, [eax*5]
mov al, [eax+DRIVE_DATA+1]
 
push ecx ebx
mov ebx, ecx
and ebx, 11b
shl ebx, 1
mov cl, 6
sub cl, bl
shr al, cl
test al, 2 ; it's not an ATAPI device
pop ebx ecx
 
jz .exit
 
cmp ebx, 4
jb .audio
jz .eject
je .eject
 
cmp ebx, 5
jnz .ret
je .load
;--------------------------------------
.exit:
ret
;--------------------------------------
.load:
call .reserve
call LoadMedium
;call .free
jmp .free
; ret
;--------------------------------------
.eject:
call .reserve
call clear_CD_cache
call allow_medium_removal
call EjectMedium
; call .free
jmp .free
; ret
.audio:
call sys_cd_audio
mov [esp+36-4], eax
.ret:
ret
 
;--------------------------------------
.reserve:
call reserve_cd
 
mov ebx, ecx
inc ebx
mov [cdpos], ebx
 
mov eax, ecx
shr eax, 1
and eax, 1
5300,32 → 5169,19
and eax, 1
mov [DiskNumber], al
call reserve_cd_channel
and ebx, 3
inc ebx
mov [cdpos], ebx
add ebx, ebx
mov cl, 8
sub cl, bl
mov al, [DRIVE_DATA+1]
shr al, cl
test al, 2
jz .free;.err
ret
;--------------------------------------
.free:
call free_cd_channel
and [cd_status], 0
ret
.err:
call .free
; pop eax
ret
;-----------------------------------------------------------------------------
align 4
syscall_getpixel_WinMap: ; GetPixel WinMap
cmp ebx, [_display.width]
jb @f
cmp ecx, [_display.height]
jb @f
cmp ebx, [Screen_Max_X]
jbe @f
cmp ecx, [Screen_Max_Y]
jbe @f
xor eax, eax
jmp .store
;--------------------------------------
5342,7 → 5198,8
;-----------------------------------------------------------------------------
align 4
syscall_getpixel: ; GetPixel
mov ecx, [_display.width]
mov ecx, [Screen_Max_X]
inc ecx
xor edx, edx
mov eax, ebx
div ecx
5587,6 → 5444,8
pushfd
cli
 
mov [Screen_Max_X], eax
mov [Screen_Max_Y], edx
mov [_display.pitch], ecx
 
mov [screen_workarea.right], eax
5628,8 → 5487,8
call repos_windows
xor eax, eax
xor ebx, ebx
mov ecx, [_display.width]
mov edx, [_display.height]
mov ecx, [Screen_Max_X]
mov edx, [Screen_Max_Y]
call calculatescreen
pop edi
pop esi
5713,10 → 5572,41
ret
@@:
call stop_all_services
movi eax, 3
call sys_cd_audio
 
yes_shutdown_param:
; Shutdown other CPUs, if initialized
cmp [ap_initialized], 0
jz .no_shutdown_cpus
mov edi, [LAPIC_BASE]
add edi, 300h
mov esi, smpt+4
mov ebx, [cpu_count]
dec ebx
.shutdown_cpus_loop:
lodsd
push esi
xor esi, esi
inc esi
shl eax, 24
mov [edi+10h], eax
; assert INIT IPI
mov dword [edi], 0C500h
call delay_ms
@@:
test dword [edi], 1000h
jnz @b
; deassert INIT IPI
mov dword [edi], 8500h
call delay_ms
@@:
test dword [edi], 1000h
jnz @b
; don't send STARTUP IPI: let other CPUs be in wait-for-startup state
pop esi
dec ebx
jnz .shutdown_cpus_loop
.no_shutdown_cpus:
 
cli
 
if ~ defined extended_primary_loader
5740,22 → 5630,6
 
call IRQ_mask_all
 
if 0
mov word [OS_BASE+0x467+0], pr_mode_exit
mov word [OS_BASE+0x467+2], 0x1000
 
mov al, 0x0F
out 0x70, al
mov al, 0x05
out 0x71, al
 
mov al, 0xFE
out 0x64, al
 
hlt
jmp $-1
 
else
cmp byte [OS_BASE + 0x9030], 2
jnz no_acpi_power_off
 
5901,21 → 5775,6
jmp $
 
 
no_acpi_power_off:
mov word [OS_BASE+0x467+0], pr_mode_exit
mov word [OS_BASE+0x467+2], 0x1000
 
mov al, 0x0F
out 0x70, al
mov al, 0x05
out 0x71, al
 
mov al, 0xFE
out 0x64, al
 
hlt
jmp $-1
 
scan_rsdp:
add eax, OS_BASE
.s:
5938,8 → 5797,34
stc
.ok:
ret
end if
 
no_acpi_power_off:
call create_trampoline_pgmap
mov cr3, eax
jmp become_real+0x10000
iglobal
align 4
realmode_gdt:
; selector 0 - not used
dw 23
dd realmode_gdt-OS_BASE
dw 0
; selector 8 - code from 1000:0000 to 1000:FFFF
dw 0FFFFh
dw 0
db 1
db 10011011b
db 00000000b
db 0
; selector 10h - data from 1000:0000 to 1000:FFFF
dw 0FFFFh
dw 0
db 1
db 10010011b
db 00000000b
db 0
endg
 
if ~ lang eq sp
diff16 "end of .text segment",0,$
end if
/kernel/branches/Kolibri-acpi/kernel32.inc
98,17 → 98,35
dr7 dd ?
ends
 
struct PROC
list LHEAD
thr_list LHEAD
heap_lock MUTEX
heap_base rd 1
heap_top rd 1
mem_used rd 1
dlls_list_ptr rd 1
pdt_0_phys rd 1
pdt_1_phys rd 1
io_map_0 rd 1
io_map_1 rd 1
 
ht_lock rd 1
ht_next rd 1
htab rd (4096-$)/4
pdt_0 rd 1024
ends
 
struct APPDATA
app_name rb 11
rb 5
 
fpu_state dd ? ;+16
ev_count_ dd ? ;unused ;+20
exc_handler dd ? ;+24
except_mask dd ? ;+28
pl0_stack dd ? ;+32
heap_base dd ? ;+36
heap_top dd ? ;+40
list LHEAD ;+16
process dd ? ;+24
fpu_state dd ? ;+28
exc_handler dd ? ;+32
except_mask dd ? ;+36
pl0_stack dd ? ;+40
cursor dd ? ;+44
fd_ev dd ? ;+48
bk_ev dd ? ;+52
124,7 → 142,7
wait_test dd ? ;+96 +++
wait_param dd ? ;+100 +++
tls_base dd ? ;+104
dlls_list_ptr dd ? ;+108
dd ? ;+108
event_filter dd ? ;+112
draw_bgr_x dd ? ;+116
draw_bgr_y dd ? ;+120
133,7 → 151,7
wnd_shape dd ? ;+128
wnd_shape_scale dd ? ;+132
dd ? ;+136
mem_size dd ? ;+140
dd ? ;+140
saved_box BOX ;+144
ipc_start dd ? ;+160
ipc_size dd ? ;+164
142,7 → 160,7
terminate_protection dd ? ;+176
keyboard_mode db ? ;+180
rb 3
dir_table dd ? ;+184
dd ? ;+184
dbg_event_mem dd ? ;+188
dbg_regs DBG_REGS ;+192
wnd_caption dd ? ;+212
152,7 → 170,37
 
ends
 
struct IDE_DATA
ProgrammingInterface dd ?
Interrupt dw ?
RegsBaseAddres dw ?
BAR0_val dw ?
BAR1_val dw ?
BAR2_val dw ?
BAR3_val dw ?
dma_hdd_channel_1 db ?
dma_hdd_channel_2 db ?
ends
 
struct IDE_CACHE
pointer dd ?
size dd ? ; not use
data_pointer dd ?
system_data_size dd ? ; not use
appl_data_size dd ? ; not use
system_data dd ?
appl_data dd ?
system_sad_size dd ?
appl_sad_size dd ?
search_start dd ?
appl_search_start dd ?
ends
 
struct IDE_DEVICE
UDMA_possible_modes db ?
UDMA_set_mode db ?
ends
 
; Core functions
include "core/sync.inc" ; macros for synhronization objects
include "core/sys32.inc" ; process management
160,6 → 208,7
include "core/syscall.inc" ; system call
include "core/fpu.inc" ; all fpu/sse support
include "core/memory.inc"
include "core/mtrr.inc"
include "core/heap.inc" ; kernel and app heap
include "core/malloc.inc" ; small kernel heap
include "core/taskman.inc"
242,7 → 291,6
 
; CD drive controller
 
include "blkdev/cdrom.inc"
include "blkdev/cd_drv.inc"
 
; Character devices
/kernel/branches/Kolibri-acpi/kernelsp.inc
1,3 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
; Éste archivo debe ser editado con codificación CP866
 
version cp850 'Kolibri OS versión 0.7.7.0+ ',13,10,13,10,0
/kernel/branches/Kolibri-acpi/macros.inc
89,6 → 89,12
mov op1, op2
}
 
macro list_init head
{
mov [head+LHEAD.next], head
mov [head+LHEAD.prev], head
}
 
macro __list_add new, prev, next
{
mov [next+LHEAD.prev], new
111,10 → 117,10
 
macro list_del entry
{
mov edx, [entry+list_fd]
mov ecx, [entry+list_bk]
mov [edx+list_bk], ecx
mov [ecx+list_fd], edx
mov edx, [entry+LHEAD.next]
mov ecx, [entry+LHEAD.prev]
mov [edx+LHEAD.prev], ecx
mov [ecx+LHEAD.next], edx
}
 
; MOV Immediate.
/kernel/branches/Kolibri-acpi/makefile
1,11 → 1,10
FASM=fasm
FLAGS=-m 65536
languages=en|ru|ge|et|sp
drivers_src=com_mouse emu10k1x fm801 infinity sis sound vt823x
 
.PHONY: all kernel drivers bootloader clean
.PHONY: all kernel bootloader clean
 
all: kernel drivers bootloader
all: kernel bootloader
 
kernel: check_lang
@echo "*** building kernel with language '$(lang)' ..."
15,14 → 14,6
@$(FASM) $(FLAGS) kernel.asm bin/kernel.mnt
@rm -f lang.inc
 
drivers:
@echo "*** building drivers ..."
@mkdir -p bin/drivers
@cd drivers; for f in $(drivers_src); do \
echo "--- building 'bin/drivers/$${f}.obj' ..."; \
$(FASM) $(FLAGS) "$${f}.asm" "../bin/drivers/$${f}.obj" || exit $?; \
done
 
bootloader: check_lang
@echo "*** building bootloader with language '$(lang)' ..."
@mkdir -p bin
/kernel/branches/Kolibri-acpi/network/ARP.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ARP.INC ;;
318,10 → 318,9
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: ip=%u.%u.%u.%u device=0x%x\n",\
[esp]:1, [esp + 1]:1, [esp + 2]:1, [esp + 3]:1, ebx
 
lea eax, [ebx + ETH_DEVICE.mac] ; local device mac
mov ax, ETHER_PROTO_ARP
mov ecx, sizeof.ARP_header
mov edx, ETH_BROADCAST ; broadcast mac
mov ecx, sizeof.ARP_header
mov di, ETHER_PROTO_ARP
call ETH_output
jz .exit
 
/kernel/branches/Kolibri-acpi/network/IPv4.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IPv4.INC ;;
267,10 → 267,9
cmp eax, 224
je .ip_ok
 
; or a loopback address (127.0.0.0/8)
; maybe we just dont have an IP yet and should accept everything on the IP level
 
and eax, 0x00ffffff
cmp eax, 127
cmp [IP_LIST + edi], 0
je .ip_ok
 
; or it's just not meant for us.. :(
577,11 → 576,11
; edx = Source IP
; di = TTL shl 8 + protocol
;
; OUT: eax = pointer to buffer start
; ebx = pointer to device struct (needed for sending procedure)
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
; edi = pointer to start of data (0 on error)
; OUT: eax = pointer to buffer start / 0 on error
; ebx = device ptr (send packet through this device)
; ecx = data length
; edx = size of complete frame
; edi = start of IPv4 payload
;
;------------------------------------------------------------------
align 4
595,7 → 594,6
push ecx di eax
call IPv4_route ; outputs device number in edi, dest ip in eax, source IP in edx
push edx
 
test edi, edi
jz .loopback
 
607,12 → 605,11
 
inc [IPv4_packets_tx + edi] ; update stats
 
mov ax, ETHER_PROTO_IPv4
mov ebx, [NET_DRV_LIST + edi]
lea eax, [ebx + ETH_DEVICE.mac]
mov edx, esp
mov ecx, [esp + 6 + 8 + 2]
add ecx, sizeof.IPv4_header
mov di, ETHER_PROTO_IPv4
mov edx, esp
call ETH_output
jz .eth_error
add esp, 6 ; pop the mac out of the stack
642,18 → 639,18
.eth_error:
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: ethernet error\n"
add esp, 3*4+2+6
xor edi, edi
xor eax, eax
ret
 
.arp_error:
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax
add esp, 3*4+2
xor edi, edi
xor eax, eax
ret
 
.too_large:
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: Packet too large!\n"
xor edi, edi
xor eax, eax
ret
 
.loopback:
675,7 → 672,7
; ecx = data length
; esi = data ptr
;
; OUT: /
; OUT: eax = -1 on error
;
;------------------------------------------------------------------
align 4
699,15 → 696,13
push ax
 
inc [IPv4_packets_tx + 4*edi]
mov ax, ETHER_PROTO_IPv4
mov ebx, [NET_DRV_LIST + 4*edi]
lea eax, [ebx + ETH_DEVICE.mac]
mov edx, esp
mov ecx, [esp + 6 + 4]
add ecx, sizeof.IPv4_header
mov di, ETHER_PROTO_IPv4
mov edx, esp
call ETH_output
jz .error
 
add esp, 6 ; pop the mac
 
mov dword[esp+4+4], edx
746,7 → 741,7
add esp, 8+4+4
.too_large:
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n"
sub edi, edi
or eax, -1
ret
 
 
795,13 → 790,9
.new_fragment:
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
 
 
mov eax, [esp + 3*4]
mov ax, ETHER_PROTO_IPv4
lea ebx, [esp + 4*4]
mov di , ETHER_PROTO_IPv4
call ETH_output
 
cmp edi, -1
jz .err
 
; copy header
/kernel/branches/Kolibri-acpi/network/PPPoE.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2012-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2012-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; PPPoE.INC ;;
14,6 → 14,9
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 5015 $
 
 
struct PPPoE_frame
VersionAndType db ?
Code db ?
240,17 → 243,15
;
; PPPoE_output
;
; IN:
; IN: ax = protocol
; ebx = device ptr
; ecx = packet size
;
; di = protocol
;
; OUT: edi = 0 on error, pointer to buffer otherwise
; eax = buffer start
; ebx = to device structure
; ecx = unchanged (packet size of embedded data)
; OUT: eax = buffer start / 0 on error
; ebx = device ptr
; ecx = packet size
; edx = size of complete buffer
; edi = start of PPP payload
;
;-----------------------------------------------------------------
align 4
258,13 → 259,12
 
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: size=%u device=%x\n", ecx, ebx
 
pushw di
pushw ax
pushw [PPPoE_SID]
 
lea eax, [ebx + ETH_DEVICE.mac]
mov ax, ETHER_PROTO_PPP_SESSION
add ecx, PPPoE_frame.Payload + 2
lea edx, [PPPoE_MAC]
add ecx, PPPoE_frame.Payload + 2
mov di, ETHER_PROTO_PPP_SESSION
call ETH_output
jz .eth_error
 
287,8 → 287,7
 
.eth_error:
add esp, 4
xor edi, edi
 
xor eax, eax
ret
 
 
/kernel/branches/Kolibri-acpi/network/ethernet.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ETHERNET.INC ;;
86,11 → 86,7
push ebx
mov esi, esp
 
pushf
cli
add_to_queue ETH_queue, ETH_QUEUE_SIZE, sizeof.ETH_queue_entry, .fail
popf
 
add esp, sizeof.ETH_queue_entry
 
xor edx, edx
102,10 → 98,9
ret
 
.fail:
popf
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH incoming queue is full, discarding packet!\n"
DEBUGF DEBUG_NETWORK_ERROR, "ETH incoming queue is full, discarding packet!\n"
 
add esp, sizeof.ETH_queue_entry - 8
pop ebx
call NET_packet_free
add esp, 4
 
150,14 → 145,14
cmp ax, ETHER_PROTO_ARP
je ARP_input
 
cmp ax, ETHER_PROTO_IPv6
je IPv6_input
; cmp ax, ETHER_PROTO_IPv6
; je IPv6_input
 
cmp ax, ETHER_PROTO_PPP_DISCOVERY
je PPPoE_discovery_input
; cmp ax, ETHER_PROTO_PPP_DISCOVERY
; je PPPoE_discovery_input
 
cmp ax, ETHER_PROTO_PPP_SESSION
je PPPoE_session_input
; cmp ax, ETHER_PROTO_PPP_SESSION
; je PPPoE_session_input
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_input: Unknown packet type=%x\n", ax
 
171,17 → 166,16
;
; ETH_output
;
; IN: eax = pointer to source mac
; IN: ax = protocol
; ebx = device ptr
; ecx = packet size
; ecx = payload size
; edx = pointer to destination mac
; di = protocol
;
; OUT: edi = 0 on error, pointer to buffer otherwise
; eax = buffer start
; ebx = to device structure
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
; OUT: eax = start of ethernet frame / 0 on error
; ebx = device ptr
; ecx = payload size
; edx = ethernet frame size
; edi = start of ethernet payload
;
;-----------------------------------------------------------------
align 4
189,11 → 183,11
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: size=%u device=%x\n", ecx, ebx
 
cmp ecx, [ebx + NET_DEVICE.mtu]
cmp ecx, [ebx + ETH_DEVICE.mtu]
ja .exit
 
push ecx
push di eax edx
push ax edx
 
add ecx, sizeof.ETH_header
stdcall kernel_alloc, ecx
204,7 → 198,7
pop esi
movsd
movsw
pop esi
lea esi, [ebx + ETH_DEVICE.mac]
movsd
movsw
pop ax
227,13 → 221,13
 
.out_of_ram:
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Out of ram!\n"
add esp, 4+4+2+4
sub edi, edi
add esp, 4+2+4
xor eax, eax
ret
 
.exit:
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Packet too large!\n"
sub edi, edi
xor eax, eax
ret
 
 
/kernel/branches/Kolibri-acpi/network/icmp.inc
294,12 → 294,12
call mutex_unlock
popa
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input: no socket found\n"
DEBUGF DEBUG_NETWORK_ERROR, "ICMP_input: no socket found\n"
jmp .dump
 
 
.checksum_mismatch:
DEBUGF DEBUG_NETWORK_VERBOSE, "checksum mismatch\n"
DEBUGF DEBUG_NETWORK_ERROR, "ICMP_input: checksum mismatch\n"
 
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
/kernel/branches/Kolibri-acpi/network/queue.inc
28,7 → 28,6
size dd ? ; number of queued packets in this queue
w_ptr dd ? ; current writing pointer in queue
r_ptr dd ? ; current reading pointer
mutex MUTEX
 
ends
 
47,18 → 46,12
 
local .ok, .no_wrap
 
pusha
lea ecx, [ptr + queue.mutex]
call mutex_lock
popa
spin_lock_irqsave
 
cmp [ptr + queue.size], size ; Check if queue isnt full
jb .ok
 
pusha
lea ecx, [ptr + queue.mutex]
call mutex_unlock
popa
spin_unlock_irqrestore
jmp failaddr
 
.ok:
76,10 → 69,7
.no_wrap:
mov [ptr + queue.w_ptr], edi
 
pusha
lea ecx, [ptr + queue.mutex]
call mutex_unlock
popa
spin_unlock_irqrestore
 
}
 
89,18 → 79,12
 
local .ok, .no_wrap
 
pusha
lea ecx, [ptr + queue.mutex]
call mutex_lock
popa
spin_lock_irqsave
 
cmp [ptr + queue.size], 0 ; any packets queued?
ja .ok
 
pusha
lea ecx, [ptr + queue.mutex]
call mutex_unlock
popa
spin_unlock_irqrestore
jmp failaddr
 
.ok:
122,10 → 106,7
 
pop esi
 
pusha
lea ecx, [ptr + queue.mutex]
call mutex_unlock
popa
spin_unlock_irqrestore
 
}
 
136,6 → 117,4
mov [ptr + queue.w_ptr], edi
mov [ptr + queue.r_ptr], edi
 
lea ecx, [ptr + queue.mutex]
call mutex_init
}
/kernel/branches/Kolibri-acpi/network/socket.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
293,6 → 293,7
push ecx edx esi
call SOCKET_alloc
pop esi edx ecx
test eax, eax
jz .nobuffs
 
mov [esp+32], edi ; return socketnumber
697,7 → 698,7
 
test [eax + SOCKET.state], SS_BLOCKED ; Is the socket still in blocked state?
jz @f
call SOCKET_notify.unblock ; Unblock it.
call SOCKET_notify ; Unblock it.
@@:
 
cmp [eax + SOCKET.Domain], AF_INET4
1192,6 → 1193,7
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
 
call SOCKET_alloc
test eax, eax
jz .nomem1
mov [esp+32], edi ; application's eax
 
1204,6 → 1206,7
mov ebx, eax
 
call SOCKET_alloc
test eax, eax
jz .nomem2
mov [esp+20], edi ; application's ebx
 
1220,10 → 1223,13
 
lea eax, [eax + STREAM_SOCKET.rcv]
call SOCKET_ring_create
test eax, eax
jz .nomem1
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
pop eax
test eax, eax
jz .nomem2
 
ret
 
1465,7 → 1471,8
 
;--------------------------
;
; eax = ptr to ring struct (just a buffer of the right size)
; IN: eax = ptr to ring struct (just a buffer of the right size)
; OUT: eax = unchanged / 0 on error
;
align 4
SOCKET_ring_create:
1476,6 → 1483,8
push edx
stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
pop edx
test eax, eax
jz .fail
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
 
1493,6 → 1502,7
mov eax, esi
pop esi
 
.fail:
ret
 
;-----------------------------------------------------------------
1536,6 → 1546,7
jb @f
sub edi, SOCKET_MAXDATA ; WRAP
@@:
 
mov [eax + RING_BUFFER.write_ptr], edi
pop edi
 
1707,8 → 1718,9
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
 
push eax
 
pushf
push eax
cli
 
; Set the 'socket is blocked' flag
1724,12 → 1736,12
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
mov [eax + SOCKET.TID], edx
pop edx
popf
 
call change_task
pop eax
popf
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: continuing\n"
 
ret
 
1752,70 → 1764,54
call SOCKET_check
jz .error
 
test [eax + SOCKET.state], SS_BLOCKED
jnz .unblock
 
; test [eax + SOCKET.options], SO_NONBLOCK
; jz .error
 
push eax ecx esi
 
; socket exists and is of non blocking type.
; We'll try to flag an event to the thread
 
mov eax, [eax + SOCKET.TID]
test eax, eax
jz .done
mov ecx, 1
mov esi, TASK_DATA + TASKDATA.pid
 
.next_pid:
cmp [esi], eax
je .found_pid
; Find the associated thread's TASK_DATA
push ebx ecx esi
mov ebx, [eax + SOCKET.TID]
test ebx, ebx
jz .error2
xor ecx, ecx
inc ecx
mov esi, TASK_DATA
.next:
cmp [esi + TASKDATA.pid], ebx
je .found
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next_pid
jbe .next
 
.error2:
; PID not found, TODO: close socket!
jmp .done
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_notify: error finding thread 0x%x !\n", ebx
pop esi ecx ebx
ret
 
.found_pid:
.error:
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_notify: invalid socket ptr: 0x%x !\n", eax
ret
 
.found:
test [eax + SOCKET.state], SS_BLOCKED
jnz .un_block
 
; socket and thread exists and socket is of non blocking type.
; We'll try to flag an event to the thread.
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: poking thread %u!\n", eax
jmp .done
pop esi ecx ebx
ret
 
.unblock:
push eax ecx esi
; Clear the 'socket is blocked' flag
and [eax + SOCKET.state], not SS_BLOCKED
 
; Find the thread's TASK_DATA
mov eax, [eax + SOCKET.TID]
test eax, eax
jz .error
xor ecx, ecx
inc ecx
mov esi, TASK_DATA
.next:
cmp [esi + TASKDATA.pid], eax
je .found
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next
jmp .error
.found:
.un_block:
; socket and thread exists and socket is of blocking type
; We'll try to unblock it.
and [eax + SOCKET.state], not SS_BLOCKED ; Clear the 'socket is blocked' flag
mov [esi + TASKDATA.state], 0 ; Run the thread
 
; Run the thread
mov [esi + TASKDATA.state], 0 ; Running
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
 
.done:
pop esi ecx eax
 
.error:
pop esi ecx ebx
ret
 
 
1830,7 → 1826,6
; IN: /
; OUT: eax = 0 on error, socket ptr otherwise
; edi = socket number
; ZF = cleared on error
;
;--------------------------------------------------------------------
align 4
1917,7 → 1912,6
@@:
 
mov [net_sockets + SOCKET.NextPtr], eax
or eax, eax ; used to clear zero flag
 
pusha
mov ecx, socket_mutex
1968,8 → 1962,14
jnz .no_tcp
 
mov ebx, eax
cmp [ebx + STREAM_SOCKET.rcv.start_ptr], 0
je @f
stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
@@:
cmp [ebx + STREAM_SOCKET.snd.start_ptr], 0
je @f
stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
@@:
mov eax, ebx
.no_tcp:
 
2022,6 → 2022,7
push ebx
call SOCKET_alloc
pop ebx
test eax, eax
jz .fail
 
push eax
2101,7 → 2102,8
call mutex_unlock
popa
 
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: not found\n", eax
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: socket %u not found!\n", eax
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: caller = 0x%x\n", [esp]
ret
 
 
2210,6 → 2212,8
align 4
SOCKET_process_end:
 
ret ; FIXME
 
cmp [net_sockets + SOCKET.NextPtr], 0 ; Are there any active sockets at all?
je .quickret ; nope, exit immediately
 
/kernel/branches/Kolibri-acpi/network/stack.inc
110,7 → 110,7
SS_BLOCKED = 0x8000
 
 
SOCKET_MAXDATA = 4096*8 ; must be 4096*(power of 2) where 'power of 2' is at least 8
SOCKET_MAXDATA = 4096*64 ; must be 4096*(power of 2) where 'power of 2' is at least 8
MAX_backlog = 20 ; maximum backlog for stream sockets
 
; Error Codes
313,10 → 313,15
test [net_10ms], 0x3f ; 640ms
jnz .exit
 
TCP_timer_640ms
ARP_decrease_entry_ttls
IPv4_decrease_fragment_ttls
 
xor edx, edx
mov eax, [TCP_timer1_event]
mov ebx, [eax + EVENT.id]
xor esi, esi
call raise_event
 
.exit:
ret
 
/kernel/branches/Kolibri-acpi/network/tcp.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
96,6 → 96,7
TCP_BIT_NEEDOUTPUT = 1 shl 0
TCP_BIT_TIMESTAMP = 1 shl 1
TCP_BIT_DROPSOCKET = 1 shl 2
TCP_BIT_FIN_IS_ACKED = 1 shl 3
 
TCP_BIT_SENDALOT = 1 shl 0
 
141,6 → 142,7
TCP_sequence_num dd ?
TCP_queue rd (TCP_QUEUE_SIZE*sizeof.TCP_queue_entry + sizeof.queue)/4
TCP_input_event dd ?
TCP_timer1_event dd ?
endg
 
uglobal
224,9 → 226,17
call new_sys_threads
test eax, eax
jns @f
DEBUGF DEBUG_NETWORK_ERROR,'K : cannot create kernel thread for TCP, error %d\n', eax
DEBUGF DEBUG_NETWORK_ERROR,'K : cannot create kernel thread for TCP input, error %d\n', eax
@@:
 
movi ebx, 1
mov ecx, TCP_timer_640ms
call new_sys_threads
test eax, eax
jns @f
DEBUGF DEBUG_NETWORK_ERROR,'K : cannot create kernel thread for TCP timer, error %d\n', eax
@@:
 
}
 
 
264,6 → 274,8
jz .packets_missed ; 2
dec bl
jz .packets_dumped ; 3
dec bl
jz .packets_queued ; 4
 
.error:
mov eax, -1
284,3 → 296,7
.packets_dumped:
mov eax, [TCP_segments_dumped + eax]
ret
 
.packets_queued:
mov eax, [TCP_queue + queue.size]
ret
/kernel/branches/Kolibri-acpi/network/tcp_input.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
7,7 → 7,7
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; Based on the algorithms used in 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
14,7 → 14,7
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 3407 $
$Revision: 5155 $
 
;-----------------------------------------------------------------
;
43,11 → 43,7
push ebx ecx esi edi ; mind the order
mov esi, esp
 
pushf
cli
add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
popf
 
add esp, sizeof.TCP_queue_entry
 
call NET_ptr_to_num4
62,7 → 58,6
ret
 
.fail:
popf
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
 
call NET_ptr_to_num4
536,12 → 531,10
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
jne .not_uni_xfer
 
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
; - The reassembly list of out-of-order segments for the connection is empty.
cmp [ebx + TCP_SOCKET.seg_next], 0
jne .not_uni_xfer
 
;;; TODO
 
; jnz .not_uni_xfer
 
; Complete processing of received data
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx
845,7 → 838,7
pop word [ebx + TCP_SOCKET.SND_SCALE]
@@:
 
;;; TODO: call TCP_reassemble
call TCP_reassemble
 
mov eax, [edx + TCP_header.SequenceNumber]
dec eax
1099,8 → 1092,7
pop ebx edx ecx
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
stc
 
or [temp_bits], TCP_BIT_FIN_IS_ACKED
jmp .wakeup
 
.finiacked:
1114,19 → 1106,15
pop edx ecx
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n"
clc
 
;----------------------------------------
; Wake up process waiting on send buffer
 
.wakeup:
 
pushf ; Keep the flags (Carry flag)
mov eax, ebx
call SOCKET_notify
 
; Update TCPS
 
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
1134,8 → 1122,6
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
popf
 
; General ACK handling complete
; Now do the state-specific ones
; Carry flag is set when our FIN is acked
1158,7 → 1144,8
 
 
.ack_fw1:
jnc .ack_processed
test [temp_bits], TCP_BIT_FIN_IS_ACKED
jz .ack_processed
 
test [ebx + SOCKET.state], SS_CANTRCVMORE
jnz @f
1171,7 → 1158,8
jmp .ack_processed
 
.ack_c:
jnc .ack_processed
test [temp_bits], TCP_BIT_FIN_IS_ACKED
jz .ack_processed
 
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
mov eax, ebx
1183,7 → 1171,8
jmp .ack_processed
 
.ack_la:
jnc .ack_processed
test [temp_bits], TCP_BIT_FIN_IS_ACKED
jz .ack_processed
 
push ebx
lea ecx, [ebx + SOCKET.mutex]
1246,9 → 1235,13
 
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
test eax, eax
jz .drop
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
test eax, eax
jz .drop
 
and [temp_bits], not TCP_BIT_DROPSOCKET
 
1257,7 → 1250,7
call SOCKET_notify
popa
 
jmp .trim_then_step6
jmp .trim
 
;------------
; Active Open
1350,9 → 1343,9
 
mov eax, [ebx + TCP_SOCKET.t_rtt]
test eax, eax
je .trim_then_step6
je .trim
call TCP_xmit_timer
jmp .trim_then_step6
jmp .trim
 
.simultaneous_open:
 
1363,8 → 1356,7
;-------------------------------------
; Common processing for receipt of SYN
 
.trim_then_step6:
 
.trim:
inc [edx + TCP_header.SequenceNumber]
 
; Drop any received data that doesnt fit in the receive window.
1377,17 → 1369,12
;;; TODO: update stats
 
.dont_trim:
 
mov eax, [edx + TCP_header.SequenceNumber]
mov [ebx + TCP_SOCKET.RCV_UP], eax
dec eax
mov [ebx + TCP_SOCKET.SND_WL1], eax
 
;-------
; step 6
 
.ack_processed:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
 
;----------------------------------------------
1592,7 → 1579,7
jnz .need_output
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jz .dumpit
jz .done
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
 
.need_output:
1599,7 → 1586,7
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
call TCP_output
 
.dumpit:
.done:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
 
call NET_packet_free
1619,7 → 1606,7
pop eax edx
 
test [edx + TCP_header.Flags], TH_RST
jnz .dumpit
jnz .done
 
or [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jmp .need_output
1633,7 → 1620,7
pop edx ebx
 
test [edx + TCP_header.Flags], TH_RST
jnz .dumpit
jnz .done
 
;;; if its a multicast/broadcast, also drop
 
1642,7 → 1629,7
 
test [edx + TCP_header.Flags], TH_SYN
jnz .respond_syn
jmp .dumpit
jmp .done
 
;---------
; Respond
1661,8 → 1648,10
pop ebx
jmp .destroy_new_socket
 
;-----------------------------------------
; The connection has no associated socket
 
.no_socket:
 
pusha
mov ecx, socket_mutex
call mutex_unlock
1692,8 → 1681,8
call TCP_respond_segment
jmp .drop_no_socket
 
;-----
; Drop
;------------------------------------------------
; Unlock socket mutex and prepare to drop segment
 
.drop:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n"
1703,6 → 1692,9
call mutex_unlock
popa
 
;--------------------------------------------
; Destroy the newly created socket if needed
 
.destroy_new_socket:
test [temp_bits], TCP_BIT_DROPSOCKET
jz .drop_no_socket
1710,6 → 1702,9
mov eax, ebx
call SOCKET_free
 
;------------------
; Drop the segment
 
.drop_no_socket:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
 
/kernel/branches/Kolibri-acpi/network/tcp_subr.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
14,7 → 14,7
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 3514 $
$Revision: 5015 $
 
align 4
iglobal
143,7 → 143,7
;
;-------------------------
align 4
TCP_drop:
TCP_drop: ; FIXME CHECKME TODO
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_drop: %x\n", eax
 
290,7 → 290,6
mov ecx, sizeof.TCP_header
mov di, IP_PROTO_TCP shl 8 + 128
call IPv4_output
test edi, edi
jz .error
pop esi cx
push edx eax
/kernel/branches/Kolibri-acpi/network/tcp_timer.inc
14,7 → 14,7
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 3143 $
$Revision: 5013 $
 
timer_flag_retransmission = 1 shl 0
timer_flag_keepalive = 1 shl 1
61,14 → 61,19
}
 
 
;----------------------
; 640 ms timer
;----------------------
macro TCP_timer_640ms { ; TODO: implement timed wait timer!
align 4
proc TCP_timer_640ms ; TODO: implement timed wait timer!
 
local .loop
local .exit
xor esi, esi
mov ecx, MANUAL_DESTROY
call create_event
mov [TCP_timer1_event], eax
 
.wait:
mov eax, [TCP_timer1_event]
mov ebx, [eax + EVENT.id]
call wait_event
 
; Update TCP sequence number
 
add [TCP_sequence_num], 64000
81,7 → 86,7
mov eax, [eax + SOCKET.NextPtr]
.check_only:
or eax, eax
jz .exit
jz .wait
 
cmp [eax + SOCKET.Domain], AF_INET4
jne .loop
157,9 → 162,8
mov [eax + TCP_SOCKET.t_force], 0
 
jmp .loop
.exit:
 
}
endp
 
 
 
/kernel/branches/Kolibri-acpi/network/tcp_usreq.inc
14,7 → 14,9
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 4850 $
 
 
;-------------------------
;
; TCP_usrclose
186,7 → 188,7
mov eax, [esp+4]
mov [eax + SOCKET.errorcode], ETIMEDOUT
and [eax + SOCKET.state], not SS_ISCONNECTING
call SOCKET_notify.unblock
call SOCKET_notify
ret 4
 
.fail:
/kernel/branches/Kolibri-acpi/network/udp.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; UDP.INC ;;
245,6 → 245,8
; ecx = number of bytes to send
; esi = pointer to data
;
; OUT: eax = -1 on error
;
;-----------------------------------------------------------------
 
align 4
/kernel/branches/Kolibri-acpi/video/blitter.inc
1,10 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 5164 $
 
 
struct BLITTER_BLOCK
xmin dd ?
ymin dd ?
/kernel/branches/Kolibri-acpi/video/cursors.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
295,9 → 295,7
; jne .fail
mov ebx, [current_slot]
xchg eax, [ebx+APPDATA.cursor]
mov [redrawmouse_unconditional], 1
call __sys_draw_pointer
ret
jmp .end
;--------------------------------------
align 4
.fail:
304,6 → 302,10
mov eax, [def_cursor]
mov ebx, [current_slot]
xchg eax, [ebx+APPDATA.cursor]
align 4
.end:
mov [redrawmouse_unconditional], 1
call __sys_draw_pointer
ret
endp
;------------------------------------------------------------------------------
578,6 → 580,40
endp
;------------------------------------------------------------------------------
align 4
proc restore_16 stdcall, x:dword, y:dword
 
push ebx
 
mov ebx, [cur_saved_base]
mov edx, [cur.h]
test edx, edx
jz .ret
 
push esi
push edi
 
mov esi, cur_saved_data
;--------------------------------------
align 4
@@:
mov edi, ebx
add ebx, [_display.pitch]
 
mov ecx, [cur.w]
rep movsw
dec edx
jnz @B
 
pop edi
;--------------------------------------
align 4
.ret:
pop esi
pop ebx
ret
endp
;------------------------------------------------------------------------------
align 4
proc move_cursor_24 stdcall, hcursor:dword, x:dword, y:dword
locals
h dd ?
817,6 → 853,129
endp
;------------------------------------------------------------------------------
align 4
proc move_cursor_16 stdcall, hcursor:dword, x:dword, y:dword
locals
h dd ?
_dx dd ?
_dy dd ?
endl
 
mov esi, [hcursor]
mov ecx, [x]
mov eax, [y]
 
xor edx, edx
sub ecx, [esi+CURSOR.hot_x]
lea ebx, [ecx+32-1]
mov [x], ecx
sets dl
dec edx
and ecx, edx ;clip x to 0<=x
mov [cur.left], ecx
mov edi, ecx
sub edi, [x]
mov [_dx], edi
 
xor edx, edx
sub eax, [esi+CURSOR.hot_y]
lea edi, [eax+32-1]
mov [y], eax
sets dl
dec edx
and eax, edx ;clip y to 0<=y
mov [cur.top], eax
mov edx, eax
sub edx, [y]
mov [_dy], edx
 
; mul dword [BytesPerScanLine]
mov eax, [BPSLine_calc_area+eax*4]
lea edx, [LFB_BASE+eax+ecx*2]
mov [cur_saved_base], edx
 
cmp ebx, [Screen_Max_X]
jbe @F
mov ebx, [Screen_Max_X]
;--------------------------------------
align 4
@@:
cmp edi, [Screen_Max_Y]
jbe @F
mov edi, [Screen_Max_Y]
;--------------------------------------
align 4
@@:
mov [cur.right], ebx
mov [cur.bottom], edi
 
sub ebx, [x]
sub edi, [y]
inc ebx
inc edi
sub ebx, [_dx]
sub edi, [_dy]
 
mov [cur.w], ebx
mov [cur.h], edi
mov [h], edi
 
mov eax, edi
mov edi, cur_saved_data
;--------------------------------------
align 4
@@:
mov esi, edx
add edx, [_display.pitch]
mov ecx, [cur.w]
 
rep movsw
dec eax
jnz @B
 
;draw cursor
mov ebx, [cur_saved_base]
mov eax, [_dy]
shl eax, 5
add eax, [_dx]
 
mov esi, [hcursor]
mov esi, [esi+CURSOR.base]
lea edx, [esi+eax*4]
;--------------------------------------
align 4
.row:
mov ecx, [cur.w]
mov esi, edx
mov edi, ebx
add edx, 32*4
add ebx, [_display.pitch]
;--------------------------------------
align 4
.pix:
lodsd
test eax, 0xFF000000
jz @F
; convert to 16 bpp and store to real LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [edi], ax
;--------------------------------------
align 4
@@:
add edi, 2
dec ecx
jnz .pix
 
dec [h]
jnz .row
ret
endp
;------------------------------------------------------------------------------
align 4
check_mouse_area_for_getpixel_new:
; in:
; eax = x
852,9 → 1011,12
add eax, ebx
mov ebx, eax
shl eax, 2
cmp byte [_display.bpp], 32
cmp byte [_display.bits_per_pixel], 32
je @f
sub eax, ebx
cmp byte [_display.bits_per_pixel], 24
je @f
sub eax, ebx
;--------------------------------------
align 4
@@:
927,7 → 1089,9
add ecx, ebx
mov ebx, ecx
shl ecx, 2
cmp byte [_display.bpp], 24
cmp byte [_display.bits_per_pixel], 16
je .16
cmp byte [_display.bits_per_pixel], 24
je .24
and eax, 0xFFFFFF
mov [ecx + cur_saved_data], eax ;store new color to
934,6 → 1098,20
jmp @f
;--------------------------------------
align 4
.16:
sub ecx, ebx
sub ecx, ebx
; convert to 16 bpp and store to real LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [ecx + cur_saved_data], ax ;store new color to
jmp @f
;--------------------------------------
align 4
.24:
sub ecx, ebx
mov [ecx + cur_saved_data], ax ;store new color to
1001,9 → 1179,9
mov ebx, restore_32
mov ecx, move_cursor_32
mov edx, Vesa20_putpixel32_new
mov eax, [_display.bpp]
mov eax, [_display.bits_per_pixel]
cmp al, 32
jne .24
jne .not_32bpp
 
.set:
mov [_display.select_cursor], select_cursor
1022,13 → 1200,31
mov [def_cursor], eax
ret
 
.24:
.not_32bpp:
cmp al, 24
jne .not_24bpp
 
mov ebx, restore_24
mov ecx, move_cursor_24
mov edx, Vesa20_putpixel24_new
cmp al, 24
je .set
jmp .set
 
.not_24bpp:
cmp al, 16
jne .not_16bpp
mov ebx, restore_16
mov ecx, move_cursor_16
mov edx, Vesa20_putpixel16_new
jmp .set
 
.not_16bpp:
; cmp al, 15
; jne .fail
; mov ebx, restore_15
; mov ecx, move_cursor_15
; mov edx, Vesa20_putpixel15_new
; jmp .set
 
.fail:
xor eax, eax
mov [_display.select_cursor], eax
/kernel/branches/Kolibri-acpi/video/vesa20.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; VESA20.INC ;;
19,41 → 19,70
 
$Revision$
 
uglobal
align 4
bgr_cur_line rd 1920 ; maximum width of screen
bgr_next_line rd 1920
endg
 
; If you're planning to write your own video driver I suggest
; you replace the VESA12.INC file and see those instructions.
iglobal
align 4
overlapping_of_points_ptr dd overlapping_of_points
endg
 
 
;-----------------------------------------------------------------------------
; getpixel
;
; in:
; eax = x coordinate
; ebx = y coordinate
;
; ret:
; ecx = 00 RR GG BB
;-----------------------------------------------------------------------------
; eax = x
; ebx = y
 
align 4
getpixel:
push eax ebx edx edi
call dword [GETPIXEL]
pop edi edx ebx eax
Vesa20_getpixel16:
 
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
@@:
 
; check mouse area for putpixel
test ecx, 0x04000000 ; don't load to mouseunder area
jnz .no_mouseunder
call [_display.check_m_pixel]
test ecx, ecx ; 0xff000000
jnz @f
 
.no_mouseunder:
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [eax*2] ; edi = x*2
add edi, ebx ; edi = x*2+(y*y multiplier)
 
movzx ecx, word[LFB_BASE+edi]
shl ecx, 3
ror ecx, 8
shl cx, 2
ror ecx, 8
shl cl, 3
rol ecx, 16
@@:
and ecx, 0x00ffffff
ret
 
;-----------------------------------------------------------------------------
; eax = x
; ebx = y
 
align 4
Vesa20_getpixel24:
; eax = x
; ebx = y
;--------------------------------------
 
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
 
; check mouse area for putpixel
test ecx, 0x04000000 ; don't load to mouseunder area
jnz .no_mouseunder
60,32 → 89,32
call [_display.check_m_pixel]
test ecx, ecx ;0xff000000
jnz @f
;--------------------------------------
align 4
 
.no_mouseunder:
;--------------------------------------
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [eax+eax*2]; edi = x*3
add edi, ebx ; edi = x*3+(y*y multiplier)
 
mov ecx, [LFB_BASE+edi]
;--------------------------------------
align 4
@@:
and ecx, 0xffffff
and ecx, 0x00ffffff
ret
 
;-----------------------------------------------------------------------------
; eax = x
; ebx = y
 
align 4
Vesa20_getpixel32:
;--------------------------------------
 
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
 
; check mouse area for putpixel
test ecx, 0x04000000 ; don't load to mouseunder area
jnz .no_mouseunder
92,20 → 121,28
call [_display.check_m_pixel]
test ecx, ecx ;0xff000000
jnz @f
;--------------------------------------
align 4
 
.no_mouseunder:
;--------------------------------------
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier)
 
mov ecx, [LFB_BASE+edi]
;--------------------------------------
align 4
@@:
and ecx, 0xffffff
and ecx, 0x00ffffff
ret
 
;-----------------------------------------------------------------------------
; ebx = pointer
; ecx = size [x|y]
; edx = coordinates [x|y]
; ebp = pointer to 'get' function
; esi = pointer to 'init' function
; edi = parameter for 'get' function
 
align 16
vesa20_putimage:
 
virtual at esp
putimg:
.real_sx dd ?
134,15 → 171,7
.ret_addr dd ?
.arg_0 dd ?
end virtual
;-----------------------------------------------------------------------------
align 16
; ebx = pointer
; ecx = size [x|y]
; edx = coordinates [x|y]
; ebp = pointer to 'get' function
; esi = pointer to 'init' function
; edi = parameter for 'get' function
vesa20_putimage:
 
pushad
sub esp, putimg.stack_data
; save pointer to image
169,43 → 198,32
mov [putimg.abs_cy], ebx
; real_sx = MIN(wnd_sx-image_cx, image_sx);
mov ebx, [eax-twdw + WDATA.box.width]; ebx = wnd_sx
; \begin{diamond}[20.08.2006]
; note that WDATA.box.width is one pixel less than real window x-size
inc ebx
; \end{diamond}[20.08.2006]
inc ebx ; WDATA.box.width is one pixel less than real window x-size
sub ebx, [putimg.image_cx]
ja @f
add esp, putimg.stack_data
popad
ret
;--------------------------------------
align 4
 
@@:
cmp ebx, [putimg.image_sx]
jbe .end_x
mov ebx, [putimg.image_sx]
;--------------------------------------
align 4
.end_x:
mov [putimg.real_sx], ebx
; init real_sy
mov ebx, [eax-twdw + WDATA.box.height]; ebx = wnd_sy
; \begin{diamond}[20.08.2006]
inc ebx
; \end{diamond}[20.08.2006]
sub ebx, [putimg.image_cy]
ja @f
add esp, putimg.stack_data
popad
ret
;--------------------------------------
align 4
 
@@:
cmp ebx, [putimg.image_sy]
jbe .end_y
mov ebx, [putimg.image_sy]
;--------------------------------------
align 4
.end_y:
mov [putimg.real_sy], ebx
; line increment
218,13 → 236,13
add eax, [putimg.arg_0]
mov [putimg.line_increment], eax
; winmap new line increment
mov eax, [_display.width]
mov eax, [Screen_Max_X]
inc eax
sub eax, [putimg.real_sx]
mov [putimg.winmap_newline], eax
; screen new line increment
mov eax, [_display.pitch]
mov ebx, [_display.bpp]
shr ebx, 3
mov ebx, [_display.bytes_per_pixel]
imul ecx, ebx
sub eax, ecx
mov [putimg.screen_newline], eax
235,18 → 253,18
; imul edx, [BytesPerScanLine]
mov edx, [BPSLine_calc_area+edx*4]
mov eax, [putimg.abs_cx]
; movzx ebx, byte [ScreenBPP]
; shr ebx, 3
imul eax, ebx
add edx, eax
; pointer to pixel map
mov eax, [putimg.abs_cy]
; imul eax, [Screen_Max_X]
; add eax, [putimg.abs_cy]
mov eax, [d_width_calc_area + eax*4]
 
add eax, [putimg.abs_cx]
add eax, [_WinMapAddress]
xchg eax, ebp
;--------------------------------------
 
mov ecx, [putimg.real_sx]
add ecx, [putimg.abs_cx]
mov [putimg.real_sx_and_abs_cx], ecx
253,15 → 271,221
mov ecx, [putimg.real_sy]
add ecx, [putimg.abs_cy]
mov [putimg.real_sy_and_abs_cy], ecx
;--------------------------------------
 
; get process number
mov ebx, [CURRENT_TASK]
cmp byte [_display.bpp], 32
 
cmp byte [_display.bits_per_pixel], 16
je put_image_end_16
cmp byte [_display.bits_per_pixel], 24
je put_image_end_24
cmp byte [_display.bits_per_pixel], 32
je put_image_end_32
;--------------------------------------
 
;------------------------------------------------------------------------------
 
put_image_end_16:
 
mov edi, [putimg.real_sy]
 
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
je put_image_end_16_new
cmp ecx, 0
je put_image_end_16_old
.new_line:
mov ecx, [putimg.real_sx]
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
call eax
cmp [ebp], bl
jne .skip
; convert to 16 bpp and store to LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [LFB_BASE+edx], ax
.skip:
add edx, 2
inc ebp
dec ecx
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline]
add ebp, [putimg.winmap_newline]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
cmp [putimg.ebp], putimage_get2bpp
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
@@:
dec edi
jnz .new_line
.finish:
add esp, putimg.stack_data
popad
ret
 
;------------------------------------------------------------------------------
 
align 4
put_image_end_16_old:
 
.new_line:
mov ecx, [putimg.real_sx]
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
call eax
cmp [ebp], bl
jne .skip
 
push ecx
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
shl ecx, 16
add ecx, [putimg.real_sy_and_abs_cy + 4]
sub ecx, edi
 
; check mouse area for putpixel
call check_mouse_area_for_putpixel
pop ecx
 
; convert to 16 bpp and store to LFB
;; and eax, 00000000111110001111110011111000b
;; shr ah, 2
;; shr ax, 3
;; ror eax, 8
;; add al, ah
;; rol eax, 8
mov [LFB_BASE+edx], ax
.skip:
inc edx
inc edx
inc ebp
dec ecx
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline]
add ebp, [putimg.winmap_newline]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
cmp [putimg.ebp], putimage_get2bpp
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
@@:
dec edi
jnz .new_line
jmp put_image_end_16.finish
 
;------------------------------------------------------------------------------
 
align 4
put_image_end_16_new:
 
.new_line:
mov ecx, [putimg.real_sx]
 
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
call eax
 
cmp [ebp], bl
jne .skip
 
push ecx
.sh:
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
 
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
 
shl ecx, 16
add ecx, [putimg.real_sy_and_abs_cy + 4]
sub ecx, edi
 
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
 
; check mouse area for putpixel
call check_mouse_area_for_putpixel_new.1
cmp ecx, -1 ; SHIT HAPPENS?
jne .no_mouse_area
 
mov ecx, [esp]
jmp .sh
 
.no_mouse_area:
pop ecx
; convert to 16 bpp and store to LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [LFB_BASE+edx], ax
 
.skip:
add edx, 2
inc ebp
dec ecx
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline]
add ebp, [putimg.winmap_newline]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
cmp [putimg.ebp], putimage_get2bpp
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
 
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
 
@@:
dec edi
jnz .new_line
jmp put_image_end_16.finish
 
;------------------------------------------------------------------------------
 
align 4
put_image_end_24:
 
mov edi, [putimg.real_sy]
;--------------------------------------
 
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
268,12 → 492,8
je put_image_end_24_new
cmp ecx, 0
je put_image_end_24_old
;--------------------------------------
align 4
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
280,13 → 500,12
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
; store to real LFB
 
; store to LFB
mov [LFB_BASE+edx], ax
shr eax, 16
mov [LFB_BASE+edx+2], al
;--------------------------------------
align 4
 
.skip:
add edx, 3
inc ebp
294,8 → 513,8
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
add edx, [putimg.screen_newline]
add ebp, [putimg.winmap_newline]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
303,27 → 522,22
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
@@:
dec edi
jnz .new_line
;--------------------------------------
align 4
.finish:
add esp, putimg.stack_data
popad
ret
 
;------------------------------------------------------------------------------
 
align 4
put_image_end_24_old:
;--------------------------------------
align 4
 
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
334,9 → 548,8
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
 
push ecx
 
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
shl ecx, 16
346,12 → 559,11
; check mouse area for putpixel
call check_mouse_area_for_putpixel
pop ecx
; store to real LFB
; store to LFB
mov [LFB_BASE+edx], ax
shr eax, 16
mov [LFB_BASE+edx+2], al
;--------------------------------------
align 4
 
.skip:
add edx, 3
inc ebp
359,8 → 571,8
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
add edx, [putimg.screen_newline]
add ebp, [putimg.winmap_newline]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
368,26 → 580,24
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
 
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
 
@@:
dec edi
jnz .new_line
jmp put_image_end_24.finish
 
;------------------------------------------------------------------------------
 
align 4
put_image_end_24_new:
;--------------------------------------
align 4
 
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
 
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
394,14 → 604,12
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
 
push ecx
;--------------------------------------
align 4
.sh:
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
;--------------------------------------
 
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
413,7 → 621,7
 
add ecx, [putimg.real_sy_and_abs_cy + 4]
sub ecx, edi
;--------------------------------------
 
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
420,7 → 628,7
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
;--------------------------------------
 
; check mouse area for putpixel
call check_mouse_area_for_putpixel_new.1
cmp ecx, -1 ;SHIT HAPPENS?
428,16 → 636,15
 
mov ecx, [esp]
jmp .sh
;--------------------------------------
align 4
 
.no_mouse_area:
pop ecx
; store to real LFB
 
; store to LFB
mov [LFB_BASE+edx], ax
shr eax, 16
mov [LFB_BASE+edx+2], al
;--------------------------------------
align 4
 
.skip:
add edx, 3
inc ebp
445,8 → 652,8
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
add edx, [putimg.screen_newline]
add ebp, [putimg.winmap_newline]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
454,22 → 661,23
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
 
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
 
@@:
dec edi
jnz .new_line
jmp put_image_end_24.finish
 
;------------------------------------------------------------------------------
 
align 4
put_image_end_32:
 
mov edi, [putimg.real_sy]
;--------------------------------------
 
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
476,12 → 684,10
je put_image_end_32_new
cmp ecx, 0
je put_image_end_32_old
;--------------------------------------
align 4
 
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
 
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
488,11 → 694,10
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
; store to real LFB
 
; store to LFB
mov [LFB_BASE+edx], eax
;--------------------------------------
align 4
 
.skip:
add edx, 4
inc ebp
500,8 → 705,8
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
add edx, [putimg.screen_newline]
add ebp, [putimg.winmap_newline]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
509,18 → 714,15
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
 
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
 
@@:
dec edi
jnz .new_line
;--------------------------------------
align 4
 
.finish:
add esp, putimg.stack_data
popad
527,20 → 729,17
cmp [SCR_MODE], 0x12
jne @f
call VGA__putimage
;--------------------------------------
align 4
@@:
mov [EGA_counter], 1
ret
 
;------------------------------------------------------------------------------
 
align 4
put_image_end_32_old:
;--------------------------------------
align 4
 
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
547,9 → 746,8
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
 
push ecx
 
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
shl ecx, 16
559,10 → 757,9
; check mouse area for putpixel
call check_mouse_area_for_putpixel
pop ecx
; store to real LFB
; store to LFB
mov [LFB_BASE+edx], eax
;--------------------------------------
align 4
 
.skip:
add edx, 4
inc ebp
570,8 → 767,8
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
add edx, [putimg.screen_newline]
add ebp, [putimg.winmap_newline]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
579,26 → 776,24
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
 
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
 
@@:
dec edi
jnz .new_line
jmp put_image_end_32.finish
 
;------------------------------------------------------------------------------
 
align 4
put_image_end_32_new:
;--------------------------------------
align 4
 
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
 
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
605,33 → 800,29
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
 
push ecx
;--------------------------------------
align 4
 
.sh:
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
;--------------------------------------
 
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
 
shl ecx, 16
 
add ecx, [putimg.real_sy_and_abs_cy + 4]
sub ecx, edi
;--------------------------------------
 
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
;--------------------------------------
 
; check mouse area for putpixel
call check_mouse_area_for_putpixel_new.1
cmp ecx, -1 ;SHIT HAPPENS?
639,14 → 830,13
 
mov ecx, [esp]
jmp .sh
;--------------------------------------
align 4
 
.no_mouse_area:
pop ecx
; store to real LFB
 
; store to LFB
mov [LFB_BASE+edx], eax
;--------------------------------------
align 4
 
.skip:
add edx, 4
inc ebp
654,8 → 844,8
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
add edx, [putimg.screen_newline]
add ebp, [putimg.winmap_newline]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
663,71 → 853,105
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
 
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
 
@@:
dec edi
jnz .new_line
jmp put_image_end_32.finish
 
;------------------------------------------------------------------------------
align 4
__sys_putpixel:
 
; eax = x coordinate
; ebx = y coordinate
; ecx = ?? RR GG BB ; 0x01000000 negation
; 0x02000000 used for draw_rectangle without top line
; for example drawwindow_III and drawwindow_IV
; ecx = xx RR GG BB
; xx flags:
; 0x01000000 color inversion
; 0x02000000 used for draw_rectangle without top line (for drawwindow_III and drawwindow_IV)
; edi = 0x00000001 force
 
align 4
__sys_putpixel:
 
pushad
cmp eax, [_display.width]
jae .exit
cmp ebx, [_display.height]
jae .exit
cmp [Screen_Max_X], eax
jb .exit
cmp [Screen_Max_Y], ebx
jb .exit
test edi, 1 ; force ?
jnz .forced
 
; not forced:
; not forced
mov edx, [d_width_calc_area + ebx*4]
add edx, [_WinMapAddress]
movzx edx, byte [eax+edx]
cmp edx, [CURRENT_TASK]
jne .exit
;--------------------------------------
align 4
 
.forced:
; check if negation
; check for color inversion
test ecx, 0x01000000
jz .noneg
jz .no_inv
 
call getpixel
push eax ebx edx edi
call [GETPIXEL]
pop edi edx ebx eax
 
not ecx
 
rol ecx, 8
mov cl, [esp+32-8+3]
ror ecx, 8
mov [esp+32-8], ecx
;--------------------------------------
align 4
.noneg:
; OK to set pixel
call dword [PUTPIXEL]; call the real put_pixel function
;--------------------------------------
align 4
.no_inv:
call [PUTPIXEL] ; call the real put_pixel function
.exit:
popad
ret
 
;-----------------------------------------------------------------------------
; eax = x
; ebx = y
 
align 4
Vesa20_putpixel24:
Vesa20_putpixel16:
 
mov ecx, eax
shl ecx, 16
mov cx, bx
 
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [eax*2]; edi = x*2
mov eax, [esp+32-8+4]
 
; check for hardware cursor
cmp [_display.select_cursor], 0
jne @f
; check mouse area for putpixel
test eax, 0x04000000
jnz @f
call check_mouse_area_for_putpixel
@@:
; store to LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
 
mov [LFB_BASE+ebx+edi], ax
ret
 
;-----------------------------------------------------------------------------
; eax = x
; ebx = y
 
align 4
Vesa20_putpixel16_new:
 
mov ecx, eax
shl ecx, 16
mov cx, bx
734,9 → 958,59
 
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [eax*2]; edi = x*2
mov eax, [esp+32-8+4]
 
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
jne @f
; check mouse area for putpixel
test eax, 0x04000000
jnz @f
 
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae @f
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb @f
rol ecx, 16
 
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae @f
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb @f
ror ecx, 16
 
call check_mouse_area_for_putpixel_new.1
@@:
; store to LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
 
mov [LFB_BASE+ebx+edi], ax
ret
 
;-----------------------------------------------------------------------------
; eax = x
; ebx = y
 
align 4
Vesa20_putpixel24:
 
mov ecx, eax
shl ecx, 16
mov cx, bx
 
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [eax+eax*2]; edi = x*3
mov eax, [esp+32-8+4]
;--------------------------------------
 
; check for hardware cursor
cmp [_display.select_cursor], 0
jne @f
744,19 → 1018,21
test eax, 0x04000000
jnz @f
call check_mouse_area_for_putpixel
;--------------------------------------
align 4
@@:
; store to real LFB
 
; store to LFB
mov [LFB_BASE+ebx+edi], ax
shr eax, 16
mov [LFB_BASE+ebx+edi+2], al
ret
 
;-----------------------------------------------------------------------------
; eax = x
; ebx = y
 
align 4
Vesa20_putpixel24_new:
; eax = x
; ebx = y
 
mov ecx, eax
shl ecx, 16
mov cx, bx
765,7 → 1041,7
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [eax+eax*2]; edi = x*3
mov eax, [esp+32-8+4]
;--------------------------------------
 
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
jne @f
772,39 → 1048,36
; check mouse area for putpixel
test eax, 0x04000000
jnz @f
;--------------------------------------
 
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae @f
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb @f
rol ecx, 16
 
rol ecx, 16
;--------------------------------------
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae @f
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb @f
 
ror ecx, 16
 
call check_mouse_area_for_putpixel_new.1
;--------------------------------------
align 4
@@:
; store to real LFB
; store to LFB
mov [LFB_BASE+ebx+edi], ax
shr eax, 16
mov [LFB_BASE+ebx+edi+2], al
ret
 
;-----------------------------------------------------------------------------
; eax = x
; ebx = y
 
align 4
Vesa20_putpixel32:
; eax = x
; ebx = y
 
mov ecx, eax
shl ecx, 16
mov cx, bx
813,7 → 1086,7
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier)
mov eax, [esp+32-8+4]; eax = color
;--------------------------------------
 
; check for hardware cursor
cmp [_display.select_cursor], 0
jne @f
821,18 → 1094,19
test eax, 0x04000000
jnz @f
call check_mouse_area_for_putpixel
;--------------------------------------
align 4
@@:
and eax, 0xffffff
; store to real LFB
; store to LFB
mov [LFB_BASE+edi], eax
ret
 
;-----------------------------------------------------------------------------
; eax = x
; ebx = y
 
align 4
Vesa20_putpixel32_new:
; eax = x
; ebx = y
 
mov ecx, eax
shl ecx, 16
mov cx, bx
841,7 → 1115,7
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier)
mov eax, [esp+32-8+4]; eax = color
;--------------------------------------
 
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
jne @f
848,53 → 1122,51
; check mouse area for putpixel
test eax, 0x04000000
jnz @f
;--------------------------------------
 
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae @f
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb @f
rol ecx, 16
 
rol ecx, 16
;--------------------------------------
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae @f
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb @f
 
ror ecx, 16
 
call check_mouse_area_for_putpixel_new.1
;--------------------------------------
align 4
@@:
and eax, 0xffffff
; store to real LFB
and eax, 0x00ffffff
; store to LFB
mov [LFB_BASE+edi], eax
ret
 
;-----------------------------------------------------------------------------
 
align 4
calculate_edi:
; mov edi, ebx
; imul edi, [Screen_Max_X]
; add edi, ebx
mov edi, [d_width_calc_area + ebx*4]
add edi, eax
ret
 
 
;-----------------------------------------------------------------------------
; DRAWLINE
;-----------------------------------------------------------------------------
align 4
__sys_draw_line:
; draw a line
; eax = HIWORD = x1
; LOWORD = x2
; ebx = HIWORD = y1
; LOWORD = y2
; eax = x1 shl 16 + x2
; ebx = y1 shl 16 + y2
; ecx = color
; edi = force ?
pusha
 
align 4
__sys_draw_line:
 
dl_x1 equ esp+20
dl_y1 equ esp+16
dl_x2 equ esp+12
902,6 → 1174,8
dl_dx equ esp+4
dl_dy equ esp+0
 
pusha
 
xor edx, edx ; clear edx
xor esi, esi ; unpack arguments
xor ebp, ebp
922,12 → 1196,10
call vline
push edx ; necessary to rightly restore stack frame at .exit
jmp .exit
;--------------------------------------
align 4
 
.x2lx1:
neg esi ; get esi absolute value
;--------------------------------------
align 4
 
.no_vline:
; checking y-axis...
sub ebp, ebx ; ebp = y2-y1
937,12 → 1209,10
mov edx, [dl_x2]; else (if y1=y2)
call hline
jmp .exit
;--------------------------------------
align 4
 
.y2ly1:
neg ebp ; get ebp absolute value
;--------------------------------------
align 4
 
.no_hline:
cmp ebp, esi
jle .x_rules ; |y2-y1| < |x2-x1| ?
955,29 → 1225,23
mov edx, [dl_y2]
mov [dl_y2], ebx
mov [dl_y1], edx
;--------------------------------------
align 4
 
.no_reverse1:
mov eax, [dl_dx]
cdq ; extend eax sing to edx
shl eax, 16 ; using 16bit fix-point maths
idiv ebp ; eax = ((x2-x1)*65536)/(y2-y1)
;--------------------------------------
 
; correction for the remainder of the division
shl edx, 1
cmp ebp, edx
jb @f
inc eax
;--------------------------------------
align 4
@@:
;--------------------------------------
mov edx, ebp ; edx = counter (number of pixels to draw)
mov ebp, 1 *65536; <<16 ; ebp = dy = 1.0
mov ebp, 1 shl 16 ; ebp = dy = 1.0
mov esi, eax ; esi = dx
jmp .y_rules
;--------------------------------------
align 4
.x_rules:
cmp [dl_x2], eax ; make sure x1 is at the begining
jge .no_reverse2
988,8 → 1252,6
mov edx, [dl_y2]
mov [dl_y2], ebx
mov [dl_y1], edx
;--------------------------------------
align 4
.no_reverse2:
xor edx, edx
mov eax, [dl_dy]
996,21 → 1258,16
cdq ; extend eax sing to edx
shl eax, 16 ; using 16bit fix-point maths
idiv esi ; eax = ((y2-y1)*65536)/(x2-x1)
;--------------------------------------
; correction for the remainder of the division
shl edx, 1
cmp esi, edx
jb @f
inc eax
;--------------------------------------
align 4
@@:
;--------------------------------------
mov edx, esi ; edx = counter (number of pixels to draw)
mov esi, 1 *65536;<< 16 ; esi = dx = 1.0
mov esi, 1 shl 16 ; esi = dx = 1.0
mov ebp, eax ; ebp = dy
;--------------------------------------
align 4
 
.y_rules:
mov eax, [dl_x1]
mov ebx, [dl_y1]
1018,29 → 1275,20
shl ebx, 16
 
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
;-----------------------------------------------------------------------------
align 4
.draw:
push eax ebx
;--------------------------------------
 
; correction for the remainder of the division
test ah, 0x80
jz @f
add eax, 1 shl 16
;--------------------------------------
align 4
@@:
;--------------------------------------
shr eax, 16
;--------------------------------------
; correction for the remainder of the division
test bh, 0x80
jz @f
add ebx, 1 shl 16
;--------------------------------------
align 4
@@:
;--------------------------------------
shr ebx, 16
; and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
; call [putpixel]
1056,16 → 1304,14
; and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
; call [putpixel]
call __sys_putpixel
;--------------------------------------
align 4
 
.exit:
add esp, 6*4
popa
; call [draw_pointer]
ret
 
;------------------------------------------------------------------------------
align 4
hline:
; draw an horizontal line
; eax = x1
; edx = x2
1072,16 → 1318,16
; ebx = y
; ecx = color
; edi = force ?
 
align 4
hline:
 
push eax edx
cmp edx, eax ; make sure x2 is above x1
jge @f
xchg eax, edx
;--------------------------------------
align 4
@@:
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
;--------------------------------------
align 4
@@:
; call [putpixel]
call __sys_putpixel
1090,9 → 1336,8
jle @b
pop edx eax
ret
 
;------------------------------------------------------------------------------
align 4
vline:
; draw a vertical line
; eax = x
; ebx = y1
1099,16 → 1344,16
; edx = y2
; ecx = color
; edi = force ?
 
align 4
vline:
 
push ebx edx
cmp edx, ebx ; make sure y2 is above y1
jge @f
xchg ebx, edx
;--------------------------------------
align 4
@@:
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
;--------------------------------------
align 4
@@:
; call [putpixel]
call __sys_putpixel
1117,8 → 1362,17
jle @b
pop edx ebx
ret
 
;------------------------------------------------------------------------------
; eax cx
; ebx cy
; ecx xe
; edx ye
; edi color
 
align 4
vesa20_drawbar:
 
virtual at esp
drbar:
.bar_sx dd ?
1136,21 → 1390,14
.real_sy_and_abs_cy dd ?
.stack_data = 4*13
end virtual
;--------------------------------------
align 4
; eax cx
; ebx cy
; ecx xe
; edx ye
; edi color
vesa20_drawbar:
 
pushad
sub esp, drbar.stack_data
mov [drbar.color], edi
sub edx, ebx
jle .exit ;// mike.dld, 2005-01-29
jle .exit
sub ecx, eax
jle .exit ;// mike.dld, 2005-01-29
jle .exit
mov [drbar.bar_sy], edx
mov [drbar.bar_sx], ecx
mov [drbar.bar_cx], eax
1162,35 → 1409,24
mov [drbar.abs_cy], ebx
; real_sx = MIN(wnd_sx-bar_cx, bar_sx);
mov ebx, [edi-twdw + WDATA.box.width]; ebx = wnd_sx
; \begin{diamond}[20.08.2006]
; note that WDATA.box.width is one pixel less than real window x-size
inc ebx
; \end{diamond}[20.08.2006]
inc ebx ; WDATA.box.width is one pixel less than real window x-size
sub ebx, [drbar.bar_cx]
ja @f
;--------------------------------------
align 4
.exit: ;// mike.dld, 2005-01-29
.exit:
add esp, drbar.stack_data
popad
xor eax, eax
inc eax
ret
;--------------------------------------
align 4
@@:
cmp ebx, [drbar.bar_sx]
jbe .end_x
mov ebx, [drbar.bar_sx]
;--------------------------------------
align 4
.end_x:
mov [drbar.real_sx], ebx
; real_sy = MIN(wnd_sy-bar_cy, bar_sy);
mov ebx, [edi-twdw + WDATA.box.height]; ebx = wnd_sy
; \begin{diamond}[20.08.2006]
inc ebx
; \end{diamond}
sub ebx, [drbar.bar_cy]
ja @f
add esp, drbar.stack_data
1198,24 → 1434,20
xor eax, eax
inc eax
ret
;--------------------------------------
align 4
@@:
cmp ebx, [drbar.bar_sy]
jbe .end_y
mov ebx, [drbar.bar_sy]
;--------------------------------------
align 4
.end_y:
mov [drbar.real_sy], ebx
; line_inc_map
mov eax, [_display.width]
mov eax, [Screen_Max_X]
sub eax, [drbar.real_sx]
inc eax
mov [drbar.line_inc_map], eax
; line_inc_scr
mov eax, [drbar.real_sx]
mov ebx, [_display.bpp]
shr ebx, 3
mov ebx, [_display.bytes_per_pixel]
imul eax, ebx
neg eax
add eax, [_display.pitch]
1229,12 → 1461,14
add edx, eax
; pointer to pixel map
mov eax, [drbar.abs_cy]
; imul eax, [Screen_Max_X]
; add eax, [drbar.abs_cy]
mov eax, [d_width_calc_area + eax*4]
 
add eax, [drbar.abs_cx]
add eax, [_WinMapAddress]
xchg eax, ebp
;--------------------------------------
 
mov ebx, [drbar.real_sx]
add ebx, [drbar.abs_cx]
mov [drbar.real_sx_and_abs_cx], ebx
1243,7 → 1477,7
mov [drbar.real_sy_and_abs_cy], ebx
 
add edx, LFB_BASE
;--------------------------------------
 
; get process number
mov ebx, [CURRENT_TASK] ; bl - process num
mov esi, [drbar.real_sy]
1251,11 → 1485,15
rol eax, 8
mov bh, al ; 0x80 drawing gradient bars
ror eax, 8
cmp byte [_display.bpp], 24
jne draw_bar_end_32
 
cmp byte [_display.bits_per_pixel], 16
je draw_bar_end_16
cmp byte [_display.bits_per_pixel], 24
je draw_bar_end_24
cmp byte [_display.bits_per_pixel], 32
je draw_bar_end_32
 
;--------------------------------------
align 4
draw_bar_end_24:
; eax - color high RRGGBB
; bl - process num
; ecx - temp
1262,7 → 1500,10
; edx - pointer to screen
; esi - counter
; edi - counter
;--------------------------------------
 
align 4
draw_bar_end_24:
 
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
1269,22 → 1510,16
je draw_bar_end_24_new
cmp ecx, 0
je draw_bar_end_24_old
;--------------------------------------
align 4
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
; store to real LFB
 
; store to LFB
mov [edx], ax
shr eax, 16
mov [edx + 2], al
;--------------------------------------
align 4
.skip:
; add pixel
add edx, 3
1300,31 → 1535,26
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
;--------------------------------------
align 4
.end:
add esp, drbar.stack_data
popad
xor eax, eax
ret
 
;------------------------------------------------------------------------------
 
align 4
draw_bar_end_24_old:
;--------------------------------------
align 4
 
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
 
mov ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
shl ecx, 16
1332,13 → 1562,11
sub ecx, esi
; check mouse area for putpixel
call check_mouse_area_for_putpixel
; store to real LFB
; store to LFB
mov [edx], ax
shr eax, 16
mov [edx + 2], al
mov eax, [drbar.color]
;--------------------------------------
align 4
.skip:
; add pixel
add edx, 3
1354,48 → 1582,41
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
jmp draw_bar_end_24.end
 
;------------------------------------------------------------------------------
 
align 4
draw_bar_end_24_new:
;--------------------------------------
align 4
 
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
 
mov ecx, [drbar.real_sy_and_abs_cy]
sub ecx, esi
;--------------------------------------
 
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
 
rol ecx, 16
add ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
;--------------------------------------
 
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
ror ecx, 16
 
ror ecx, 16
;--------------------------------------
; check mouse area for putpixel
push eax
call check_mouse_area_for_putpixel_new.1
1404,25 → 1625,25
mov [edx + 2], al
pop eax
jmp .skip
; store to real LFB
;--------------------------------------
align 4
 
.no_mouse_area:
; store to LFB
mov [edx], ax
ror eax, 16
mov [edx + 2], al
rol eax, 16
;--------------------------------------
align 4
.skip:
 
; add pixel
add edx, 3
inc ebp
dec edi
jnz .new_x
 
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
 
; drawing gradient bars
test bh, 0x80
jz @f
1429,15 → 1650,12
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
jmp draw_bar_end_24.end
 
;------------------------------------------------------------------------------
align 4
draw_bar_end_32:
; eax - color high RRGGBB
; bl - process num
; ecx - temp
1444,7 → 1662,9
; edx - pointer to screen
; esi - counter
; edi - counter
;--------------------------------------
 
draw_bar_end_32:
 
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
1451,30 → 1671,28
je draw_bar_end_32_new
cmp ecx, 0
je draw_bar_end_32_old
;--------------------------------------
align 4
 
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
; store to real LFB
 
; store to LFB
mov [edx], eax
mov eax, [drbar.color]
;--------------------------------------
align 4
.skip:
 
; add pixel
add edx, 4
inc ebp
dec edi
jnz .new_x
 
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
 
; drawing gradient bars
test bh, 0x80
jz @f
1481,13 → 1699,9
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
;--------------------------------------
align 4
.end:
add esp, drbar.stack_data
popad
1494,25 → 1708,19
cmp [SCR_MODE], 0x12
jne @f
call VGA_draw_bar
;--------------------------------------
align 4
@@:
xor eax, eax
mov [EGA_counter], 1
ret
;------------------------------------------------------------------------------
align 4
 
draw_bar_end_32_old:
;--------------------------------------
align 4
 
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
 
mov ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
shl ecx, 16
1521,11 → 1729,9
 
; check mouse area for putpixel
call check_mouse_area_for_putpixel
; store to real LFB
; store to LFB
mov [edx], eax
mov eax, [drbar.color]
;--------------------------------------
align 4
.skip:
; add pixel
add edx, 4
1541,48 → 1747,41
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
jmp draw_bar_end_32.end
 
;------------------------------------------------------------------------------
 
align 4
draw_bar_end_32_new:
;--------------------------------------
align 4
 
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
 
mov ecx, [drbar.real_sy_and_abs_cy]
sub ecx, esi
;--------------------------------------
 
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
 
rol ecx, 16
add ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
;--------------------------------------
 
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
ror ecx, 16
 
ror ecx, 16
;--------------------------------------
; check mouse area for putpixel
push eax
call check_mouse_area_for_putpixel_new.1
1589,22 → 1788,22
mov [edx], eax
pop eax
jmp .skip
; store to real LFB
;--------------------------------------
align 4
.no_mouse_area:
 
; store to LFB
mov [edx], eax
;--------------------------------------
align 4
.skip:
 
; add pixel
add edx, 4
inc ebp
dec edi
jnz .new_x
 
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
 
; drawing gradient bars
test bh, 0x80
jz @f
1611,20 → 1810,210
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
jmp draw_bar_end_32.end
 
;------------------------------------------------------------------------------
; eax - color high RRGGBB
; bl - process num
; ecx - temp
; edx - pointer to screen
; esi - counter
; edi - counter
 
align 4
draw_bar_end_16:
 
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
je draw_bar_end_16_new
cmp ecx, 0
je draw_bar_end_16_old
.new_y:
mov edi, [drbar.real_sx]
.new_x:
cmp byte [ebp], bl
jne .skip
; convert to 16 bpp and store to LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [edx], ax
mov eax, [drbar.color]
.skip:
 
; add pixel
add edx, 2
inc ebp
dec edi
jnz .new_x
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
; drawing gradient bars
test bh, 0x80
jz @f
test al, al
jz @f
dec al
@@:
dec esi
jnz .new_y
.end:
add esp, drbar.stack_data
popad
cmp [SCR_MODE], 0x12
jne @f
call VGA_draw_bar
@@:
xor eax, eax
mov [EGA_counter], 1
ret
 
;------------------------------------------------------------------------------
 
align 4
draw_bar_end_16_old:
 
.new_y:
mov edi, [drbar.real_sx]
.new_x:
cmp byte [ebp], bl
jne .skip
 
mov ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
shl ecx, 16
add ecx, [drbar.real_sy_and_abs_cy]
sub ecx, esi
 
; check mouse area for putpixel
call check_mouse_area_for_putpixel
; convert to 16 bpp and store to LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [edx], ax
mov eax, [drbar.color]
.skip:
 
; add pixel
add edx, 2
inc ebp
dec edi
jnz .new_x
 
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
 
; drawing gradient bars
test bh, 0x80
jz @f
test al, al
jz @f
dec al
@@:
dec esi
jnz .new_y
jmp draw_bar_end_16.end
 
;------------------------------------------------------------------------------
 
align 4
draw_bar_end_16_new:
 
.new_y:
mov edi, [drbar.real_sx]
.new_x:
cmp byte [ebp], bl
jne .skip
 
mov ecx, [drbar.real_sy_and_abs_cy]
sub ecx, esi
 
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
rol ecx, 16
add ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
 
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
ror ecx, 16
 
; check mouse area for putpixel
push eax
call check_mouse_area_for_putpixel_new.1
push eax
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [edx], ax
pop eax
pop eax
jmp .skip
 
.no_mouse_area:
; convert to 16 bpp and store to LFB
push eax
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [edx], ax
pop eax
.skip:
 
; add pixel
add edx, 2
inc ebp
dec edi
jnz .new_x
 
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
 
; drawing gradient bars
test bh, 0x80
jz @f
test al, al
jz @f
dec al
@@:
dec esi
jnz .new_y
jmp draw_bar_end_16.end
 
;------------------------------------------------------------------------------
 
align 4
vesa20_drawbackground_tiled:
 
pushad
; External loop for all y from start to end
mov ebx, [draw_data+32+RECT.top] ; y start
;--------------------------------------
align 4
dp2:
mov ebp, [draw_data+32+RECT.left] ; x start
; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp]
1635,12 → 2024,13
xchg ebp, eax
add ebp, eax
add ebp, eax
cmp byte [_display.bytes_per_pixel], 2
je @f
add ebp, eax
cmp byte [_display.bpp], 24 ; 24 or 32 bpp ? - x size
jz @f
cmp byte [_display.bytes_per_pixel], 3
je @f
add ebp, eax
;--------------------------------------
align 4
 
@@:
add ebp, LFB_BASE
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB
1674,14 → 2064,11
; edx = 1
; esi -> bgr memory, edi -> output
; ebp = offset in WinMapAddress
;--------------------------------------
align 4
dp3:
cmp [ebp], dl
jnz nbgp
;--------------------------------------
jnz .next_pix
 
push eax ecx
 
mov ecx, eax
shl ecx, 16
add ecx, ebx
1693,32 → 2080,37
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
and eax, 0xffffff
; check mouse area for putpixel
call [_display.check_mouse]
;--------------------------------------
align 4
.no_mouseunder:
; store to real LFB
 
cmp byte [_display.bits_per_pixel], 16
je .16bpp
; store to LFB
mov [edi], ax
shr eax, 16
mov [edi+2], al
pop ecx eax
jmp .next_pix
 
.16bpp:
; convert to 16 bpp and store to LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [edi], ax
pop ecx eax
;--------------------------------------
align 4
nbgp:
 
; Advance to next pixel
.next_pix:
add esi, 3
add edi, 3
;--------------------------------------
align 4
@@:
cmp byte [_display.bpp], 25 ; 24 or 32 bpp?
sbb edi, -1 ; +1 for 32 bpp
; I do not use 'inc eax' because this is slightly slower then 'add eax,1'
add edi, [_display.bytes_per_pixel]
 
add ebp, edx
add eax, edx
cmp eax, [draw_data+32+RECT.right]
1725,6 → 2117,7
ja dp4
sub ecx, edx
jnz dp3
 
; next tile block on x-axis
mov ecx, [BgrDataWidth]
sub esi, ecx
1731,8 → 2124,7
sub esi, ecx
sub esi, ecx
jmp dp3
;--------------------------------------
align 4
 
dp4:
; next scan line
inc ebx
1743,31 → 2135,36
cmp [SCR_MODE], 0x12
jne @f
call VGA_drawbackground
;--------------------------------------
align 4
@@:
ret
 
;------------------------------------------------------------------------------
 
align 4
vesa20_drawbackground_stretch:
 
pushad
; Helper variables
; calculate 2^32*(BgrDataWidth) mod (ScreenWidth)
; calculate 2^32*(BgrDataWidth-1) mod (ScreenWidth-1)
mov eax, [BgrDataWidth]
dec eax
xor edx, edx
div dword [_display.width]
div dword [Screen_Max_X]
push eax ; high
xor eax, eax
div dword [_display.width]
div dword [Screen_Max_X]
push eax ; low
 
; the same for height
mov eax, [BgrDataHeight]
dec eax
xor edx, edx
div dword [_display.height]
div dword [Screen_Max_Y]
push eax ; high
xor eax, eax
div dword [_display.height]
div dword [Screen_Max_Y]
push eax ; low
 
; External loop for all y from start to end
mov ebx, [draw_data+32+RECT.top] ; y start
mov ebp, [draw_data+32+RECT.left] ; x start
1779,16 → 2176,18
xchg ebp, eax
add ebp, eax
add ebp, eax
cmp byte [_display.bytes_per_pixel], 2
jz @f
add ebp, eax
cmp byte [_display.bpp], 24 ; 24 or 32 bpp ? - x size
cmp byte [_display.bytes_per_pixel], 3
jz @f
add ebp, eax
;--------------------------------------
align 4
@@:
 
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB
call calculate_edi
xchg edi, ebp
 
; Now eax=x, ebx=y, edi->output, ebp=offset in WinMapAddress
push ebx
push eax
1814,9 → 2213,8
push eax
push edx
push esi
 
; 3) Smooth horizontal
;--------------------------------------
align 4
bgr_resmooth0:
mov ecx, [esp+8]
mov edx, [esp+4]
1824,8 → 2222,7
push edi
mov edi, bgr_cur_line
call smooth_line
;--------------------------------------
align 4
 
bgr_resmooth1:
mov eax, [esp+16+4]
inc eax
1839,15 → 2236,14
add esi, [BgrDataWidth]
mov edi, bgr_next_line
call smooth_line
;--------------------------------------
align 4
 
bgr.no2nd:
pop edi
;--------------------------------------
align 4
 
sdp3:
xor esi, esi
mov ecx, [esp+12]
 
; 4) Loop through redraw rectangle and copy background data
; Registers meaning:
; esi = offset in current line, edi -> output
1860,8 → 2256,7
; precalculated constants:
; qword [esp+28] = 2^32*(BgrDataHeight-1)/(ScreenHeight-1)
; qword [esp+36] = 2^32*(BgrDataWidth-1)/(ScreenWidth-1)
;--------------------------------------
align 4
 
sdp3a:
mov eax, [_WinMapAddress]
cmp [ebp+eax], byte 1
1871,8 → 2266,7
jz .novert
mov ebx, [bgr_next_line+esi]
call [overlapping_of_points_ptr]
;--------------------------------------
align 4
 
.novert:
push ecx
; check for hardware cursor
1880,8 → 2274,6
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
mov ecx, [esp+20+4] ;x
shl ecx, 16
1888,19 → 2280,30
add ecx, [esp+24+4] ;y
; check mouse area for putpixel
call [_display.check_mouse]
;--------------------------------------
align 4
.no_mouseunder:
; store to real LFB
 
cmp [_display.bits_per_pixel], 16
jne .not_16bpp
; convert to 16 bpp and store to LFB
and eax, 00000000111110001111110011111000b
shr ah, 2
shr ax, 3
ror eax, 8
add al, ah
rol eax, 8
mov [LFB_BASE+edi], ax
pop ecx
jmp snbgp
.not_16bpp:
 
; store to LFB
mov [LFB_BASE+edi], ax
shr eax, 16
mov [LFB_BASE+edi+2], al
pop ecx
;--------------------------------------
align 4
 
snbgp:
cmp byte [_display.bpp], 25
sbb edi, -4
add edi, [_display.bytes_per_pixel]
add ebp, 1
mov eax, [esp+20]
add eax, 1
1908,8 → 2311,7
add esi, 4
cmp eax, [draw_data+32+RECT.right]
jbe sdp3a
;--------------------------------------
align 4
 
sdp4:
; next y
mov ebx, [esp+24]
1917,18 → 2319,21
mov [esp+24], ebx
cmp ebx, [draw_data+32+RECT.bottom]
ja sdpdone
 
; advance edi, ebp to next scan line
sub eax, [draw_data+32+RECT.left]
sub ebp, eax
add ebp, [_display.width]
add ebp, [Screen_Max_X]
add ebp, 1
sub edi, eax
sub edi, eax
cmp byte [_display.bytes_per_pixel], 2
jz @f
sub edi, eax
cmp byte [_display.bpp], 24
cmp byte [_display.bytes_per_pixel], 3
jz @f
sub edi, eax
;--------------------------------------
align 4
 
@@:
add edi, [_display.pitch]
; restore ecx,edx; advance esi to next background line
1951,11 → 2356,11
push edi
mov esi, bgr_next_line
mov edi, bgr_cur_line
mov ecx, [_display.width]
mov ecx, [Screen_Max_X]
inc ecx
rep movsd
jmp bgr_resmooth1
;--------------------------------------
align 4
 
sdpdone:
add esp, 44
popad
1963,20 → 2368,12
cmp [SCR_MODE], 0x12
jne @f
call VGA_drawbackground
;--------------------------------------
align 4
@@:
ret
 
uglobal
;--------------------------------------
 
align 4
bgr_cur_line rd 1920 ; maximum width of screen
bgr_next_line rd 1920
;--------------------------------------
endg
;--------------------------------------
align 4
smooth_line:
mov al, [esi+2]
shl eax, 16
1986,8 → 2383,6
mov ebx, [esi+2]
shr ebx, 8
call [overlapping_of_points_ptr]
;--------------------------------------
align 4
@@:
stosd
mov eax, [esp+20+8]
2002,13 → 2397,13
lea eax, [eax*3]
sub esi, eax
jmp smooth_line
;--------------------------------------
align 4
@@:
mov eax, [draw_data+32+RECT.left]
mov [esp+20+8], eax
ret
 
;------------------------------------------------------------------------------
 
align 16
overlapping_of_points:
if 0
2072,26 → 2467,21
ret
end if
 
iglobal
;--------------------------------------
align 4
overlapping_of_points_ptr dd overlapping_of_points
;--------------------------------------
endg
 
;------------------------------------------------------------------------------
 
align 4
init_background:
 
mov edi, BgrAuxTable
xor edx, edx
;--------------------------------------
align 4
 
.loop2:
mov eax, edx
shl eax, 8
neg eax
mov ecx, 0x200
;--------------------------------------
align 4
 
.loop1:
mov byte [edi], ah
inc edi
2102,13 → 2492,14
test byte [cpu_caps+(CAPS_MMX/8)], 1 shl (CAPS_MMX mod 8)
jz @f
mov [overlapping_of_points_ptr], overlapping_of_points_mmx
;--------------------------------------
align 4
@@:
ret
 
;------------------------------------------------------------------------------
 
align 16
overlapping_of_points_mmx:
 
movd mm0, eax
movd mm4, eax
movd mm1, ebx
2125,5 → 2516,7
packuswb mm1, mm2
paddb mm4, mm1
movd eax, mm4
 
ret
 
;------------------------------------------------------------------------------