/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 |
;------------------------------------------------------------------------------ |