/kernel/trunk/blkdev/cd_drv.inc |
---|
1,929 → 1,931 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;********************************************************** |
; Íåïîñðåäñòâåííàÿ ðàáîòà ñ óñòðîéñòâîì ÑD (ATAPI) |
;********************************************************** |
; Àâòîð ÷àñòè èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷ |
; Àäàïòàöèÿ, äîðàáîòêà è ðàçðàáîòêà Mario79,<Lrz> |
; Ìàêñèìàëüíîå êîëè÷åñòâî ïîâòîðåíèé îïåðàöèè ÷òåíèÿ |
MaxRetr equ 10 |
; Ïðåäåëüíîå âðåìÿ îæèäàíèÿ ãîòîâíîñòè ê ïðèåìó êîìàíäû |
; (â òèêàõ) |
BSYWaitTime equ 1000 ;2 |
NoTickWaitTime equ 0xfffff |
CDBlockSize equ 2048 |
;******************************************** |
;* ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ Ñ ÏÎÂÒÎÐÀÌÈ * |
;* Ìíîãîêðàòíîå ïîâòîðåíèå ÷òåíèÿ ïðè ñáîÿõ * |
;******************************************** |
ReadCDWRetr: |
;----------------------------------------------------------- |
; input : eax = block to read |
; ebx = destination |
;----------------------------------------------------------- |
pushad |
mov eax,[CDSectorAddress] |
mov ebx,[CDDataBuf_pointer] |
call cd_calculate_cache |
xor edi,edi |
add esi,8 |
inc edi |
.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 |
push eax |
call cd_calculate_cache_2 |
shl edi,11 |
add edi,eax |
mov [CDDataBuf_pointer],edi |
pop eax |
pop edi |
call ReadCDWRetr_1 |
cmp [DevErrorCode],0 |
jne .exit |
mov [CDDataBuf_pointer],ebx |
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 |
push eax |
call cd_calculate_cache_2 |
add esi,eax |
pop eax |
mov edi,ebx ;[CDDataBuf_pointer] |
mov ecx,512 ;/4 |
cld |
rep movsd ; move data |
.exit: |
popad |
ret |
ReadCDWRetr_1: |
pushad |
; Öèêë, ïîêà êîìàíäà íå âûïîëíåíà óñïåøíî èëè íå |
; èñ÷åðïàíî êîëè÷åñòâî ïîïûòîê |
mov ECX,MaxRetr |
@@NextRetr: |
; Ïîäàòü êîìàíäó |
;************************************************* |
;* ÏÎËÍÎÅ ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ ÊÎÌÏÀÊÒ-ÄÈÑÊÀ * |
;* Ñ÷èòûâàþòñÿ äàííûå ïîëüçîâàòåëÿ, èíôîðìàöèÿ * |
;* ñóáêàíàëà è êîíòðîëüíàÿ èíôîðìàöèÿ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå; * |
;* CDSectorAddress - àäðåñ ñ÷èòûâàåìîãî ñåêòîðà. * |
;* Äàííûå ñ÷èòûâàåòñÿ â ìàññèâ CDDataBuf. * |
;************************************************* |
;ReadCD: |
push ecx |
; pusha |
; Çàäàòü ðàçìåð ñåêòîðà |
; mov [CDBlockSize],2048 ;2352 |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü ïàêåòíóþ êîìàíäó äëÿ ñ÷èòûâàíèÿ |
; ñåêòîðà äàííûõ |
; Çàäàòü êîä êîìàíäû Read CD |
mov [PacketCommand],byte 0x28 ;0xBE |
; Çàäàòü àäðåñ ñåêòîðà |
mov AX,word [CDSectorAddress+2] |
xchg AL,AH |
mov word [PacketCommand+2],AX |
mov AX,word [CDSectorAddress] |
xchg AL,AH |
mov word [PacketCommand+4],AX |
; mov eax,[CDSectorAddress] |
; mov [PacketCommand+2],eax |
; Çàäàòü êîëè÷åñòâî ñ÷èòûâàåìûõ ñåêòîðîâ |
mov [PacketCommand+8],byte 1 |
; Çàäàòü ñ÷èòûâàíèå äàííûõ â ïîëíîì îáúåìå |
; mov [PacketCommand+9],byte 0xF8 |
; Ïîäàòü êîìàíäó |
call SendPacketDatCommand |
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 |
.wait: |
dec eax |
; test eax,eax |
jz @@NextRetr |
jmp .wait |
@@: |
; Çàäåðæêà íà 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 ? |
; Âðåìÿ íà÷àëà î÷åðåäíîé îïåðàöèè ñ äèñêîì |
TickCounter_1 DD 0 |
; Âðåìÿ íà÷àëà îæèäàíèÿ ãîòîâíîñòè óñòðîéñòâà |
WURStartTime DD 0 |
; óêàçàòåëü áóôåðà äëÿ ñ÷èòûâàíèÿ |
CDDataBuf_pointer dd 0 |
endg |
;**************************************************** |
;* ÏÎÑËÀÒÜ ÓÑÒÐÎÉÑÒÂÓ ATAPI ÏÀÊÅÒÍÓÞ ÊÎÌÀÍÄÓ, * |
;* ÏÐÅÄÓÑÌÀÒÐÈÂÀÞÙÓÞ ÏÅÐÅÄÀ×Ó ÎÄÍÎÃÎ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ * |
;* ÐÀÇÌÅÐÎÌ 2048 ÁÀÉÒ ÎÒ ÓÑÒÐÎÉÑÒÂÀ Ê ÕÎÑÒÓ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå; * |
;* PacketCommand - 12-áàéòíûé êîìàíäíûé ïàêåò; * |
;* CDBlockSize - ðàçìåð ïðèíèìàåìîãî áëîêà äàííûõ. * |
; return eax DevErrorCode |
;**************************************************** |
SendPacketDatCommand: |
xor eax,eax |
; mov byte [DevErrorCode],al |
; Çàäàòü ðåæèì CHS |
mov byte [ATAAddressMode],al |
; Ïîñëàòü ATA-êîìàíäó ïåðåäà÷è ïàêåòíîé êîìàíäû |
mov byte [ATAFeatures],al |
mov byte [ATASectorCount],al |
mov byte [ATASectorNumber],al |
; Çàãðóçèòü ðàçìåð ïåðåäàâàåìîãî áëîêà |
mov [ATAHead],al |
; mov AX,[CDBlockSize] |
mov [ATACylinder],CDBlockSize |
mov [ATACommand],0A0h |
call SendCommandToHDD_1 |
test eax,eax |
; cmp [DevErrorCode],0 ;ïðîâåðèòü êîä îøèáêè |
jnz @@End_8 ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè |
; Îæèäàíèå ãîòîâíîñòè äèñêîâîäà ê ïðèåìó |
; ïàêåòíîé êîìàíäû |
mov DX,[ATABasePortAddr] |
add DX,7 ;ïîðò 1õ7h |
mov ecx,NoTickWaitTime |
@@WaitDevice0: |
cmp [timer_ticks_enable],0 |
jne @f |
dec ecx |
; test ecx,ecx |
jz @@Err1_1 |
jmp .test |
@@: |
call change_task |
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû |
mov EAX,[timer_ticks] |
sub EAX,[TickCounter_1] |
cmp EAX,BSYWaitTime |
ja @@Err1_1 ;îøèáêà òàéì-àóòà |
; Ïðîâåðèòü ãîòîâíîñòü |
.test: |
in AL,DX |
test AL,80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitDevice0 |
test AL,1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Err6 |
test AL,08h ;ñîñòîÿíèå ñèãíàëà DRQ |
jz @@WaitDevice0 |
; Ïîñëàòü ïàêåòíóþ êîìàíäó |
cli |
mov DX,[ATABasePortAddr] |
mov AX,[PacketCommand] |
out DX,AX |
mov AX,[PacketCommand+2] |
out DX,AX |
mov AX,[PacketCommand+4] |
out DX,AX |
mov AX,[PacketCommand+6] |
out DX,AX |
mov AX,[PacketCommand+8] |
out DX,AX |
mov AX,[PacketCommand+10] |
out DX,AX |
sti |
; Îæèäàíèå ãîòîâíîñòè äàííûõ |
mov DX,[ATABasePortAddr] |
add DX,7 ;ïîðò 1õ7h |
mov ecx,NoTickWaitTime |
@@WaitDevice1: |
cmp [timer_ticks_enable],0 |
jne @f |
dec ecx |
; test ecx,ecx |
jz @@Err1_1 |
jmp .test_1 |
@@: |
call change_task |
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû |
mov EAX,[timer_ticks] |
sub EAX,[TickCounter_1] |
cmp EAX,MaxCDWaitTime |
ja @@Err1_1 ;îøèáêà òàéì-àóòà |
; Ïðîâåðèòü ãîòîâíîñòü |
.test_1: |
in AL,DX |
test AL,80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitDevice1 |
test AL,1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Err6_temp |
test AL,08h ;ñîñòîÿíèå ñèãíàëà DRQ |
jz @@WaitDevice1 |
; Ïðèíÿòü áëîê äàííûõ îò êîíòðîëëåðà |
mov EDI,[CDDataBuf_pointer] ;0x7000 ;CDDataBuf |
; Çàãðóçèòü àäðåñ ðåãèñòðà äàííûõ êîíòðîëëåðà |
mov DX,[ATABasePortAddr] ;ïîðò 1x0h |
; Çàãðóçèòü â ñ÷åò÷èê ðàçìåð áëîêà â áàéòàõ |
xor ecx,ecx |
mov CX,CDBlockSize |
; Âû÷èñëèòü ðàçìåð áëîêà â 16-ðàçðÿäíûõ ñëîâàõ |
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 ÏÀÊÅÒÍÓÞ ÊÎÌÀÍÄÓ, * |
;* ÍÅ ÏÐÅÄÓÑÌÀÒÐÈÂÀÞÙÓÞ ÏÅÐÅÄÀ×È ÄÀÍÍÛÕ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç * |
;* ãëîáàëüíûå ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå; * |
;* PacketCommand - 12-áàéòíûé êîìàíäíûé ïàêåò. * |
;*********************************************** |
SendPacketNoDatCommand: |
pushad |
xor eax,eax |
; mov byte [DevErrorCode],al |
; Çàäàòü ðåæèì CHS |
mov byte [ATAAddressMode],al |
; Ïîñëàòü ATA-êîìàíäó ïåðåäà÷è ïàêåòíîé êîìàíäû |
mov byte [ATAFeatures],al |
mov byte [ATASectorCount],al |
mov byte [ATASectorNumber],al |
mov word [ATACylinder],ax |
mov byte [ATAHead],al |
mov [ATACommand],0A0h |
call SendCommandToHDD_1 |
; cmp [DevErrorCode],0 ;ïðîâåðèòü êîä îøèáêè |
test eax,eax |
jnz @@End_9 ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè |
; Îæèäàíèå ãîòîâíîñòè äèñêîâîäà ê ïðèåìó |
; ïàêåòíîé êîìàíäû |
mov DX,[ATABasePortAddr] |
add DX,7 ;ïîðò 1õ7h |
@@WaitDevice0_1: |
call change_task |
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ |
mov EAX,[timer_ticks] |
sub EAX,[TickCounter_1] |
cmp EAX,BSYWaitTime |
ja @@Err1_3 ;îøèáêà òàéì-àóòà |
; Ïðîâåðèòü ãîòîâíîñòü |
in AL,DX |
test AL,80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitDevice0_1 |
test AL,1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Err6_1 |
test AL,08h ;ñîñòîÿíèå ñèãíàëà DRQ |
jz @@WaitDevice0_1 |
; Ïîñëàòü ïàêåòíóþ êîìàíäó |
; cli |
mov DX,[ATABasePortAddr] |
mov AX,word [PacketCommand] |
out DX,AX |
mov AX,word [PacketCommand+2] |
out DX,AX |
mov AX,word [PacketCommand+4] |
out DX,AX |
mov AX,word [PacketCommand+6] |
out DX,AX |
mov AX,word [PacketCommand+8] |
out DX,AX |
mov AX,word [PacketCommand+10] |
out DX,AX |
; sti |
cmp [ignore_CD_eject_wait],1 |
je @@clear_DEC |
; Îæèäàíèå ïîäòâåðæäåíèÿ ïðèåìà êîìàíäû |
mov DX,[ATABasePortAddr] |
add DX,7 ;ïîðò 1õ7h |
@@WaitDevice1_1: |
call change_task |
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû |
mov EAX,[timer_ticks] |
sub EAX,[TickCounter_1] |
cmp EAX,MaxCDWaitTime |
ja @@Err1_3 ;îøèáêà òàéì-àóòà |
; Îæèäàòü îñâîáîæäåíèÿ óñòðîéñòâà |
in AL,DX |
test AL,80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitDevice1_1 |
test AL,1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Err6_1 |
test AL,40h ;ñîñòîÿíèå ñèãíàëà DRDY |
jz @@WaitDevice1_1 |
@@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 |
;**************************************************** |
;* ÏÎÑËÀÒÜ ÊÎÌÀÍÄÓ ÇÀÄÀÍÍÎÌÓ ÄÈÑÊÓ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); * |
;* DiskNumber - íîìåð äèñêà (0 èëè 1); * |
;* ATAFeatures - "îñîáåííîñòè"; * |
;* ATASectorCount - êîëè÷åñòâî ñåêòîðîâ; * |
;* ATASectorNumber - íîìåð íà÷àëüíîãî ñåêòîðà; * |
;* ATACylinder - íîìåð íà÷àëüíîãî öèëèíäðà; * |
;* ATAHead - íîìåð íà÷àëüíîé ãîëîâêè; * |
;* ATAAddressMode - ðåæèì àäðåñàöèè (0-CHS, 1-LBA); * |
;* ATACommand - êîä êîìàíäû. * |
;* Ïîñëå óñïåøíîãî âûïîëíåíèÿ ôóíêöèè: * |
;* â ATABasePortAddr - áàçîâûé àäðåñ HDD; * |
;* â DevErrorCode - íîëü. * |
;* Ïðè âîçíèêíîâåíèè îøèáêè â DevErrorCode áóäåò * |
;* âîçâðàùåí êîä îøèáêè â eax * |
;**************************************************** |
SendCommandToHDD_1: |
; pushad |
; mov [DevErrorCode],0 not need |
; Ïðîâåðèòü çíà÷åíèå êîäà ðåæèìà |
cmp [ATAAddressMode],1 |
ja @@Err2_4 |
; Ïðîâåðèòü êîððåêòíîñòü íîìåðà êàíàëà |
mov BX,[ChannelNumber] |
cmp BX,1 |
jb @@Err3_4 |
cmp BX,2 |
ja @@Err3_4 |
; Óñòàíîâèòü áàçîâûé àäðåñ |
dec BX |
shl BX,1 |
movzx ebx,bx |
mov AX,[ebx+StandardATABases] |
mov [ATABasePortAddr],AX |
; Îæèäàíèå ãîòîâíîñòè HDD ê ïðèåìó êîìàíäû |
; Âûáðàòü íóæíûé äèñê |
mov DX,[ATABasePortAddr] |
add DX,6 ;àäðåñ ðåãèñòðà ãîëîâîê |
mov AL,[DiskNumber] |
cmp AL,1 ;ïðîâåðèòü íîìåðà äèñêà |
ja @@Err4_4 |
shl AL,4 |
or AL,10100000b |
out DX,AL |
; Îæèäàòü, ïîêà äèñê íå áóäåò ãîòîâ |
inc DX |
mov eax,[timer_ticks] |
mov [TickCounter_1],eax |
mov ecx,NoTickWaitTime |
@@WaitHDReady_2: |
cmp [timer_ticks_enable],0 |
jne @f |
dec ecx |
; test ecx,ecx |
jz @@Err1_4 |
jmp .test |
@@: |
call change_task |
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ |
mov eax,[timer_ticks] |
sub eax,[TickCounter_1] |
cmp eax,BSYWaitTime ;300 ;îæèäàòü 3 ñåê. |
ja @@Err1_4 ;îøèáêà òàéì-àóòà |
; Ïðî÷èòàòü ðåãèñòð ñîñòîÿíèÿ |
.test: |
in AL,DX |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY |
test AL,80h |
jnz @@WaitHDReady_2 |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà DRQ |
test AL,08h |
jnz @@WaitHDReady_2 |
; Çàãðóçèòü êîìàíäó â ðåãèñòðû êîíòðîëëåðà |
cli |
mov DX,[ATABasePortAddr] |
inc DX ;ðåãèñòð "îñîáåííîñòåé" |
mov AL,[ATAFeatures] |
out DX,AL |
inc DX ;ñ÷åò÷èê ñåêòîðîâ |
mov AL,[ATASectorCount] |
out DX,AL |
inc DX ;ðåãèñòð íîìåðà ñåêòîðà |
mov AL,[ATASectorNumber] |
out DX,AL |
inc DX ;íîìåð öèëèíäðà (ìëàäøèé áàéò) |
mov AX,[ATACylinder] |
out DX,AL |
inc DX ;íîìåð öèëèíäðà (ñòàðøèé áàéò) |
mov AL,AH |
out DX,AL |
inc DX ;íîìåð ãîëîâêè/íîìåð äèñêà |
mov AL,[DiskNumber] |
shl AL,4 |
cmp [ATAHead],0Fh ;ïðîâåðèòü íîìåð ãîëîâêè |
ja @@Err5_4 |
or AL,[ATAHead] |
or AL,10100000b |
mov AH,[ATAAddressMode] |
shl AH,6 |
or AL,AH |
out DX,AL |
; Ïîñëàòü êîìàíäó |
mov AL,[ATACommand] |
inc DX ;ðåãèñòð êîìàíä |
out DX,AL |
sti |
; Ñáðîñèòü ïðèçíàê îøèáêè |
; mov [DevErrorCode],0 |
@@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 |
;************************************************* |
;* ÎÆÈÄÀÍÈÅ ÃÎÒÎÂÍÎÑÒÈ ÓÑÒÐÎÉÑÒÂÀ Ê ÐÀÁÎÒÅ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
WaitUnitReady: |
pusha |
; Çàïîìíèòü âðåìÿ íà÷àëà îïåðàöèè |
mov EAX,[timer_ticks] |
mov [WURStartTime],EAX |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü êîìàíäó TEST UNIT READY |
mov [PacketCommand],word 00h |
; ÖÈÊË ÎÆÈÄÀÍÈß ÃÎÒÎÂÍÎÑÒÈ ÓÑÒÐÎÉÑÒÂÀ |
mov ecx,NoTickWaitTime |
@@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 |
@@: |
call change_task |
; Ïðîâåðèòü êîä îøèáêè |
cmp [DevErrorCode],0 |
je @@End_11 |
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ ãîòîâíîñòè |
mov EAX,[timer_ticks] |
sub EAX,[WURStartTime] |
cmp EAX,MaxCDWaitTime |
jb @@SendCommand |
.Error: |
; Îøèáêà òàéì-àóòà |
mov [DevErrorCode],1 |
@@End_11: |
popa |
ret |
;************************************************* |
;* ÇÀÏÐÅÒÈÒÜ ÑÌÅÍÓ ÄÈÑÊÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
prevent_medium_removal: |
pusha |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand],byte 0x1E |
; Çàäàòü êîä çàïðåòà |
mov [PacketCommand+4],byte 11b |
; Ïîäàòü êîìàíäó |
call SendPacketNoDatCommand |
mov eax,ATAPI_IDE0_lock |
add eax,[cdpos] |
dec eax |
mov [eax],byte 1 |
popa |
ret |
;************************************************* |
;* ÐÀÇÐÅØÈÒÜ ÑÌÅÍÓ ÄÈÑÊÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
allow_medium_removal: |
pusha |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand],byte 0x1E |
; Çàäàòü êîä çàïðåòà |
mov [PacketCommand+4],byte 00b |
; Ïîäàòü êîìàíäó |
call SendPacketNoDatCommand |
mov eax,ATAPI_IDE0_lock |
add eax,[cdpos] |
dec eax |
mov [eax],byte 0 |
popa |
ret |
;************************************************* |
;* ÇÀÃÐÓÇÈÒÜ ÍÎÑÈÒÅËÜ Â ÄÈÑÊÎÂÎÄ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
LoadMedium: |
pusha |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü êîìàíäó START/STOP UNIT |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand],word 1Bh |
; Çàäàòü îïåðàöèþ çàãðóçêè íîñèòåëÿ |
mov [PacketCommand+4],word 00000011b |
; Ïîäàòü êîìàíäó |
call SendPacketNoDatCommand |
popa |
ret |
;************************************************* |
;* ÈÇÂËÅ×Ü ÍÎÑÈÒÅËÜ ÈÇ ÄÈÑÊÎÂÎÄÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
EjectMedium: |
pusha |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü êîìàíäó START/STOP UNIT |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand],word 1Bh |
; Çàäàòü îïåðàöèþ èçâëå÷åíèÿ íîñèòåëÿ |
mov [PacketCommand+4],word 00000010b |
; Ïîäàòü êîìàíäó |
call SendPacketNoDatCommand |
popa |
ret |
;************************************************* |
;* Ïðîâåðèòü ñîáûòèå íàæàòèÿ êíîïêè èçâëå÷åíèÿ * |
;* äèñêà * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
align 4 |
check_ATAPI_device_event: |
pusha |
mov eax,[timer_ticks] |
sub eax,[timer_ATAPI_check] |
cmp eax,100 |
jb .end_1 |
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 |
.end: |
sti |
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 |
call reserve_ok2 |
mov [ChannelNumber],2 |
mov [DiskNumber],1 |
mov [cdpos],4 |
call GetEvent_StatusNotification |
cmp [CDDataBuf+4],byte 1 |
je .eject_ide3 |
call syscall_cdaudio.free |
jmp .ide2_1 |
.eject_ide3: |
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 |
call reserve_ok2 |
mov [ChannelNumber],2 |
mov [DiskNumber],0 |
mov [cdpos],3 |
call GetEvent_StatusNotification |
cmp [CDDataBuf+4],byte 1 |
je .eject_ide2 |
call syscall_cdaudio.free |
jmp .ide1_1 |
.eject_ide2: |
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 |
call reserve_ok2 |
mov [ChannelNumber],1 |
mov [DiskNumber],1 |
mov [cdpos],2 |
call GetEvent_StatusNotification |
cmp [CDDataBuf+4],byte 1 |
je .eject_ide1 |
call syscall_cdaudio.free |
jmp .ide0_1 |
.eject_ide1: |
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 |
cmp [cd_status],0 |
jne .end |
mov [IDE_Channel_1],1 |
call reserve_ok2 |
mov [ChannelNumber],1 |
mov [DiskNumber],0 |
mov [cdpos],1 |
call GetEvent_StatusNotification |
cmp [CDDataBuf+4],byte 1 |
je .eject_ide0 |
call syscall_cdaudio.free |
jmp .end |
.eject_ide0: |
call .eject |
call syscall_cdaudio.free |
jmp .end |
.eject: |
call clear_CD_cache |
call allow_medium_removal |
mov [ignore_CD_eject_wait],1 |
call EjectMedium |
mov [ignore_CD_eject_wait],0 |
ret |
iglobal |
timer_ATAPI_check dd 0 |
ATAPI_IDE0_lock db 0 |
ATAPI_IDE1_lock db 0 |
ATAPI_IDE2_lock db 0 |
ATAPI_IDE3_lock db 0 |
ignore_CD_eject_wait db 0 |
endg |
;************************************************* |
;* Ïîëó÷èòü ñîîáùåíèå î ñîáûòèè èëè ñîñòîÿíèè * |
;* óñòðîéñòâà * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
GetEvent_StatusNotification: |
pusha |
mov [CDDataBuf_pointer],CDDataBuf |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand],byte 4Ah |
mov [PacketCommand+1],byte 00000001b |
; Çàäàòü çàïðîñ êëàññà ñîîáùåíèé |
mov [PacketCommand+4],byte 00010000b |
; Ðàçìåð âûäåëåííîé îáëàñòè |
mov [PacketCommand+7],byte 8h |
mov [PacketCommand+8],byte 0h |
; Ïîäàòü êîìàíäó |
call SendPacketDatCommand |
popa |
ret |
;************************************************* |
; ïðî÷èòàòü èíôîðìàöèþ èç TOC |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
Read_TOC: |
pusha |
mov [CDDataBuf_pointer],CDDataBuf |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü ïàêåòíóþ êîìàíäó äëÿ ñ÷èòûâàíèÿ |
; ñåêòîðà äàííûõ |
mov [PacketCommand],byte 0x43 |
; Çàäàòü ôîðìàò |
mov [PacketCommand+2],byte 1 |
; Ðàçìåð âûäåëåííîé îáëàñòè |
mov [PacketCommand+7],byte 0xFF |
mov [PacketCommand+8],byte 0h |
; Ïîäàòü êîìàíäó |
call SendPacketDatCommand |
popa |
ret |
;************************************************* |
;* ÎÏÐÅÄÅËÈÒÜ ÎÁÙÅÅ ÊÎËÈ×ÅÑÒÂÎ ÑÅÊÒÎÐΠÍÀ ÄÈÑÊÅ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
;ReadCapacity: |
; pusha |
;; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
; call clear_packet_buffer |
;; Çàäàòü ðàçìåð áóôåðà â áàéòàõ |
; mov [CDBlockSize],8 |
;; Ñôîðìèðîâàòü êîìàíäó READ CAPACITY |
; mov [PacketCommand],word 25h |
;; Ïîäàòü êîìàíäó |
; call SendPacketDatCommand |
; popa |
; ret |
clear_packet_buffer: |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
and [PacketCommand],dword 0 |
and [PacketCommand+4],dword 0 |
and [PacketCommand+8],dword 0 |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;********************************************************** |
; Íåïîñðåäñòâåííàÿ ðàáîòà ñ óñòðîéñòâîì ÑD (ATAPI) |
;********************************************************** |
; Àâòîð ÷àñòè èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷ |
; Àäàïòàöèÿ, äîðàáîòêà è ðàçðàáîòêà Mario79,<Lrz> |
; Ìàêñèìàëüíîå êîëè÷åñòâî ïîâòîðåíèé îïåðàöèè ÷òåíèÿ |
MaxRetr equ 10 |
; Ïðåäåëüíîå âðåìÿ îæèäàíèÿ ãîòîâíîñòè ê ïðèåìó êîìàíäû |
; (â òèêàõ) |
BSYWaitTime equ 1000 ;2 |
NoTickWaitTime equ 0xfffff |
CDBlockSize equ 2048 |
;******************************************** |
;* ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ Ñ ÏÎÂÒÎÐÀÌÈ * |
;* Ìíîãîêðàòíîå ïîâòîðåíèå ÷òåíèÿ ïðè ñáîÿõ * |
;******************************************** |
ReadCDWRetr: |
;----------------------------------------------------------- |
; input : eax = block to read |
; ebx = destination |
;----------------------------------------------------------- |
pushad |
mov eax, [CDSectorAddress] |
mov ebx, [CDDataBuf_pointer] |
call cd_calculate_cache |
xor edi, edi |
add esi, 8 |
inc edi |
.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 |
push eax |
call cd_calculate_cache_2 |
shl edi, 11 |
add edi, eax |
mov [CDDataBuf_pointer], edi |
pop eax |
pop edi |
call ReadCDWRetr_1 |
cmp [DevErrorCode], 0 |
jne .exit |
mov [CDDataBuf_pointer], ebx |
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 |
push eax |
call cd_calculate_cache_2 |
add esi, eax |
pop eax |
mov edi, ebx;[CDDataBuf_pointer] |
mov ecx, 512;/4 |
cld |
rep movsd ; move data |
.exit: |
popad |
ret |
ReadCDWRetr_1: |
pushad |
; Öèêë, ïîêà êîìàíäà íå âûïîëíåíà óñïåøíî èëè íå |
; èñ÷åðïàíî êîëè÷åñòâî ïîïûòîê |
mov ECX, MaxRetr |
@@NextRetr: |
; Ïîäàòü êîìàíäó |
;************************************************* |
;* ÏÎËÍÎÅ ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ ÊÎÌÏÀÊÒ-ÄÈÑÊÀ * |
;* Ñ÷èòûâàþòñÿ äàííûå ïîëüçîâàòåëÿ, èíôîðìàöèÿ * |
;* ñóáêàíàëà è êîíòðîëüíàÿ èíôîðìàöèÿ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå; * |
;* CDSectorAddress - àäðåñ ñ÷èòûâàåìîãî ñåêòîðà. * |
;* Äàííûå ñ÷èòûâàåòñÿ â ìàññèâ CDDataBuf. * |
;************************************************* |
;ReadCD: |
push ecx |
; pusha |
; Çàäàòü ðàçìåð ñåêòîðà |
; mov [CDBlockSize],2048 ;2352 |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü ïàêåòíóþ êîìàíäó äëÿ ñ÷èòûâàíèÿ |
; ñåêòîðà äàííûõ |
; Çàäàòü êîä êîìàíäû Read CD |
mov [PacketCommand], byte 0x28;0xBE |
; Çàäàòü àäðåñ ñåêòîðà |
mov AX, word [CDSectorAddress+2] |
xchg AL, AH |
mov word [PacketCommand+2], AX |
mov AX, word [CDSectorAddress] |
xchg AL, AH |
mov word [PacketCommand+4], AX |
; mov eax,[CDSectorAddress] |
; mov [PacketCommand+2],eax |
; Çàäàòü êîëè÷åñòâî ñ÷èòûâàåìûõ ñåêòîðîâ |
mov [PacketCommand+8], byte 1 |
; Çàäàòü ñ÷èòûâàíèå äàííûõ â ïîëíîì îáúåìå |
; mov [PacketCommand+9],byte 0xF8 |
; Ïîäàòü êîìàíäó |
call SendPacketDatCommand |
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 |
.wait: |
dec eax |
; test eax,eax |
jz @@NextRetr |
jmp .wait |
@@: |
; Çàäåðæêà íà 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 ? |
; Âðåìÿ íà÷àëà î÷åðåäíîé îïåðàöèè ñ äèñêîì |
TickCounter_1 DD 0 |
; Âðåìÿ íà÷àëà îæèäàíèÿ ãîòîâíîñòè óñòðîéñòâà |
WURStartTime DD 0 |
; óêàçàòåëü áóôåðà äëÿ ñ÷èòûâàíèÿ |
CDDataBuf_pointer dd 0 |
endg |
;**************************************************** |
;* ÏÎÑËÀÒÜ ÓÑÒÐÎÉÑÒÂÓ ATAPI ÏÀÊÅÒÍÓÞ ÊÎÌÀÍÄÓ, * |
;* ÏÐÅÄÓÑÌÀÒÐÈÂÀÞÙÓÞ ÏÅÐÅÄÀ×Ó ÎÄÍÎÃÎ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ * |
;* ÐÀÇÌÅÐÎÌ 2048 ÁÀÉÒ ÎÒ ÓÑÒÐÎÉÑÒÂÀ Ê ÕÎÑÒÓ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå; * |
;* PacketCommand - 12-áàéòíûé êîìàíäíûé ïàêåò; * |
;* CDBlockSize - ðàçìåð ïðèíèìàåìîãî áëîêà äàííûõ. * |
; return eax DevErrorCode |
;**************************************************** |
SendPacketDatCommand: |
xor eax, eax |
; mov byte [DevErrorCode],al |
; Çàäàòü ðåæèì CHS |
mov byte [ATAAddressMode], al |
; Ïîñëàòü ATA-êîìàíäó ïåðåäà÷è ïàêåòíîé êîìàíäû |
mov byte [ATAFeatures], al |
mov byte [ATASectorCount], al |
mov byte [ATASectorNumber], al |
; Çàãðóçèòü ðàçìåð ïåðåäàâàåìîãî áëîêà |
mov [ATAHead], al |
; mov AX,[CDBlockSize] |
mov [ATACylinder], CDBlockSize |
mov [ATACommand], 0A0h |
call SendCommandToHDD_1 |
test eax, eax |
; cmp [DevErrorCode],0 ;ïðîâåðèòü êîä îøèáêè |
jnz @@End_8 ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè |
; Îæèäàíèå ãîòîâíîñòè äèñêîâîäà ê ïðèåìó |
; ïàêåòíîé êîìàíäû |
mov DX, [ATABasePortAddr] |
add DX, 7 ;ïîðò 1õ7h |
mov ecx, NoTickWaitTime |
@@WaitDevice0: |
cmp [timer_ticks_enable], 0 |
jne @f |
dec ecx |
; test ecx,ecx |
jz @@Err1_1 |
jmp .test |
@@: |
call change_task |
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû |
mov EAX, [timer_ticks] |
sub EAX, [TickCounter_1] |
cmp EAX, BSYWaitTime |
ja @@Err1_1 ;îøèáêà òàéì-àóòà |
; Ïðîâåðèòü ãîòîâíîñòü |
.test: |
in AL, DX |
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitDevice0 |
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Err6 |
test AL, 08h ;ñîñòîÿíèå ñèãíàëà DRQ |
jz @@WaitDevice0 |
; Ïîñëàòü ïàêåòíóþ êîìàíäó |
cli |
mov DX, [ATABasePortAddr] |
mov AX, [PacketCommand] |
out DX, AX |
mov AX, [PacketCommand+2] |
out DX, AX |
mov AX, [PacketCommand+4] |
out DX, AX |
mov AX, [PacketCommand+6] |
out DX, AX |
mov AX, [PacketCommand+8] |
out DX, AX |
mov AX, [PacketCommand+10] |
out DX, AX |
sti |
; Îæèäàíèå ãîòîâíîñòè äàííûõ |
mov DX, [ATABasePortAddr] |
add DX, 7 ;ïîðò 1õ7h |
mov ecx, NoTickWaitTime |
@@WaitDevice1: |
cmp [timer_ticks_enable], 0 |
jne @f |
dec ecx |
; test ecx,ecx |
jz @@Err1_1 |
jmp .test_1 |
@@: |
call change_task |
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû |
mov EAX, [timer_ticks] |
sub EAX, [TickCounter_1] |
cmp EAX, MaxCDWaitTime |
ja @@Err1_1 ;îøèáêà òàéì-àóòà |
; Ïðîâåðèòü ãîòîâíîñòü |
.test_1: |
in AL, DX |
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitDevice1 |
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Err6_temp |
test AL, 08h ;ñîñòîÿíèå ñèãíàëà DRQ |
jz @@WaitDevice1 |
; Ïðèíÿòü áëîê äàííûõ îò êîíòðîëëåðà |
mov EDI, [CDDataBuf_pointer];0x7000 ;CDDataBuf |
; Çàãðóçèòü àäðåñ ðåãèñòðà äàííûõ êîíòðîëëåðà |
mov DX, [ATABasePortAddr];ïîðò 1x0h |
; Çàãðóçèòü â ñ÷åò÷èê ðàçìåð áëîêà â áàéòàõ |
xor ecx, ecx |
mov CX, CDBlockSize |
; Âû÷èñëèòü ðàçìåð áëîêà â 16-ðàçðÿäíûõ ñëîâàõ |
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 ÏÀÊÅÒÍÓÞ ÊÎÌÀÍÄÓ, * |
;* ÍÅ ÏÐÅÄÓÑÌÀÒÐÈÂÀÞÙÓÞ ÏÅÐÅÄÀ×È ÄÀÍÍÛÕ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç * |
;* ãëîáàëüíûå ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå; * |
;* PacketCommand - 12-áàéòíûé êîìàíäíûé ïàêåò. * |
;*********************************************** |
SendPacketNoDatCommand: |
pushad |
xor eax, eax |
; mov byte [DevErrorCode],al |
; Çàäàòü ðåæèì CHS |
mov byte [ATAAddressMode], al |
; Ïîñëàòü ATA-êîìàíäó ïåðåäà÷è ïàêåòíîé êîìàíäû |
mov byte [ATAFeatures], al |
mov byte [ATASectorCount], al |
mov byte [ATASectorNumber], al |
mov word [ATACylinder], ax |
mov byte [ATAHead], al |
mov [ATACommand], 0A0h |
call SendCommandToHDD_1 |
; cmp [DevErrorCode],0 ;ïðîâåðèòü êîä îøèáêè |
test eax, eax |
jnz @@End_9 ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè |
; Îæèäàíèå ãîòîâíîñòè äèñêîâîäà ê ïðèåìó |
; ïàêåòíîé êîìàíäû |
mov DX, [ATABasePortAddr] |
add DX, 7 ;ïîðò 1õ7h |
@@WaitDevice0_1: |
call change_task |
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ |
mov EAX, [timer_ticks] |
sub EAX, [TickCounter_1] |
cmp EAX, BSYWaitTime |
ja @@Err1_3 ;îøèáêà òàéì-àóòà |
; Ïðîâåðèòü ãîòîâíîñòü |
in AL, DX |
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitDevice0_1 |
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Err6_1 |
test AL, 08h ;ñîñòîÿíèå ñèãíàëà DRQ |
jz @@WaitDevice0_1 |
; Ïîñëàòü ïàêåòíóþ êîìàíäó |
; cli |
mov DX, [ATABasePortAddr] |
mov AX, word [PacketCommand] |
out DX, AX |
mov AX, word [PacketCommand+2] |
out DX, AX |
mov AX, word [PacketCommand+4] |
out DX, AX |
mov AX, word [PacketCommand+6] |
out DX, AX |
mov AX, word [PacketCommand+8] |
out DX, AX |
mov AX, word [PacketCommand+10] |
out DX, AX |
; sti |
cmp [ignore_CD_eject_wait], 1 |
je @@clear_DEC |
; Îæèäàíèå ïîäòâåðæäåíèÿ ïðèåìà êîìàíäû |
mov DX, [ATABasePortAddr] |
add DX, 7 ;ïîðò 1õ7h |
@@WaitDevice1_1: |
call change_task |
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû |
mov EAX, [timer_ticks] |
sub EAX, [TickCounter_1] |
cmp EAX, MaxCDWaitTime |
ja @@Err1_3 ;îøèáêà òàéì-àóòà |
; Îæèäàòü îñâîáîæäåíèÿ óñòðîéñòâà |
in AL, DX |
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitDevice1_1 |
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Err6_1 |
test AL, 40h ;ñîñòîÿíèå ñèãíàëà DRDY |
jz @@WaitDevice1_1 |
@@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 |
;**************************************************** |
;* ÏÎÑËÀÒÜ ÊÎÌÀÍÄÓ ÇÀÄÀÍÍÎÌÓ ÄÈÑÊÓ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); * |
;* DiskNumber - íîìåð äèñêà (0 èëè 1); * |
;* ATAFeatures - "îñîáåííîñòè"; * |
;* ATASectorCount - êîëè÷åñòâî ñåêòîðîâ; * |
;* ATASectorNumber - íîìåð íà÷àëüíîãî ñåêòîðà; * |
;* ATACylinder - íîìåð íà÷àëüíîãî öèëèíäðà; * |
;* ATAHead - íîìåð íà÷àëüíîé ãîëîâêè; * |
;* ATAAddressMode - ðåæèì àäðåñàöèè (0-CHS, 1-LBA); * |
;* ATACommand - êîä êîìàíäû. * |
;* Ïîñëå óñïåøíîãî âûïîëíåíèÿ ôóíêöèè: * |
;* â ATABasePortAddr - áàçîâûé àäðåñ HDD; * |
;* â DevErrorCode - íîëü. * |
;* Ïðè âîçíèêíîâåíèè îøèáêè â DevErrorCode áóäåò * |
;* âîçâðàùåí êîä îøèáêè â eax * |
;**************************************************** |
SendCommandToHDD_1: |
; pushad |
; mov [DevErrorCode],0 not need |
; Ïðîâåðèòü çíà÷åíèå êîäà ðåæèìà |
cmp [ATAAddressMode], 1 |
ja @@Err2_4 |
; Ïðîâåðèòü êîððåêòíîñòü íîìåðà êàíàëà |
mov BX, [ChannelNumber] |
cmp BX, 1 |
jb @@Err3_4 |
cmp BX, 2 |
ja @@Err3_4 |
; Óñòàíîâèòü áàçîâûé àäðåñ |
dec BX |
shl BX, 1 |
movzx ebx, bx |
mov AX, [ebx+StandardATABases] |
mov [ATABasePortAddr], AX |
; Îæèäàíèå ãîòîâíîñòè HDD ê ïðèåìó êîìàíäû |
; Âûáðàòü íóæíûé äèñê |
mov DX, [ATABasePortAddr] |
add DX, 6 ;àäðåñ ðåãèñòðà ãîëîâîê |
mov AL, [DiskNumber] |
cmp AL, 1 ;ïðîâåðèòü íîìåðà äèñêà |
ja @@Err4_4 |
shl AL, 4 |
or AL, 10100000b |
out DX, AL |
; Îæèäàòü, ïîêà äèñê íå áóäåò ãîòîâ |
inc DX |
mov eax, [timer_ticks] |
mov [TickCounter_1], eax |
mov ecx, NoTickWaitTime |
@@WaitHDReady_2: |
cmp [timer_ticks_enable], 0 |
jne @f |
dec ecx |
; test ecx,ecx |
jz @@Err1_4 |
jmp .test |
@@: |
call change_task |
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ |
mov eax, [timer_ticks] |
sub eax, [TickCounter_1] |
cmp eax, BSYWaitTime;300 ;îæèäàòü 3 ñåê. |
ja @@Err1_4 ;îøèáêà òàéì-àóòà |
; Ïðî÷èòàòü ðåãèñòð ñîñòîÿíèÿ |
.test: |
in AL, DX |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY |
test AL, 80h |
jnz @@WaitHDReady_2 |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà DRQ |
test AL, 08h |
jnz @@WaitHDReady_2 |
; Çàãðóçèòü êîìàíäó â ðåãèñòðû êîíòðîëëåðà |
cli |
mov DX, [ATABasePortAddr] |
inc DX ;ðåãèñòð "îñîáåííîñòåé" |
mov AL, [ATAFeatures] |
out DX, AL |
inc DX ;ñ÷åò÷èê ñåêòîðîâ |
mov AL, [ATASectorCount] |
out DX, AL |
inc DX ;ðåãèñòð íîìåðà ñåêòîðà |
mov AL, [ATASectorNumber] |
out DX, AL |
inc DX ;íîìåð öèëèíäðà (ìëàäøèé áàéò) |
mov AX, [ATACylinder] |
out DX, AL |
inc DX ;íîìåð öèëèíäðà (ñòàðøèé áàéò) |
mov AL, AH |
out DX, AL |
inc DX ;íîìåð ãîëîâêè/íîìåð äèñêà |
mov AL, [DiskNumber] |
shl AL, 4 |
cmp [ATAHead], 0Fh;ïðîâåðèòü íîìåð ãîëîâêè |
ja @@Err5_4 |
or AL, [ATAHead] |
or AL, 10100000b |
mov AH, [ATAAddressMode] |
shl AH, 6 |
or AL, AH |
out DX, AL |
; Ïîñëàòü êîìàíäó |
mov AL, [ATACommand] |
inc DX ;ðåãèñòð êîìàíä |
out DX, AL |
sti |
; Ñáðîñèòü ïðèçíàê îøèáêè |
; mov [DevErrorCode],0 |
@@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 |
;************************************************* |
;* ÎÆÈÄÀÍÈÅ ÃÎÒÎÂÍÎÑÒÈ ÓÑÒÐÎÉÑÒÂÀ Ê ÐÀÁÎÒÅ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
WaitUnitReady: |
pusha |
; Çàïîìíèòü âðåìÿ íà÷àëà îïåðàöèè |
mov EAX, [timer_ticks] |
mov [WURStartTime], EAX |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü êîìàíäó TEST UNIT READY |
mov [PacketCommand], word 00h |
; ÖÈÊË ÎÆÈÄÀÍÈß ÃÎÒÎÂÍÎÑÒÈ ÓÑÒÐÎÉÑÒÂÀ |
mov ecx, NoTickWaitTime |
@@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 |
@@: |
call change_task |
; Ïðîâåðèòü êîä îøèáêè |
cmp [DevErrorCode], 0 |
je @@End_11 |
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ ãîòîâíîñòè |
mov EAX, [timer_ticks] |
sub EAX, [WURStartTime] |
cmp EAX, MaxCDWaitTime |
jb @@SendCommand |
.Error: |
; Îøèáêà òàéì-àóòà |
mov [DevErrorCode], 1 |
@@End_11: |
popa |
ret |
;************************************************* |
;* ÇÀÏÐÅÒÈÒÜ ÑÌÅÍÓ ÄÈÑÊÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
prevent_medium_removal: |
pusha |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand], byte 0x1E |
; Çàäàòü êîä çàïðåòà |
mov [PacketCommand+4], byte 11b |
; Ïîäàòü êîìàíäó |
call SendPacketNoDatCommand |
mov eax, ATAPI_IDE0_lock |
add eax, [cdpos] |
dec eax |
mov [eax], byte 1 |
popa |
ret |
;************************************************* |
;* ÐÀÇÐÅØÈÒÜ ÑÌÅÍÓ ÄÈÑÊÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
allow_medium_removal: |
pusha |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand], byte 0x1E |
; Çàäàòü êîä çàïðåòà |
mov [PacketCommand+4], byte 00b |
; Ïîäàòü êîìàíäó |
call SendPacketNoDatCommand |
mov eax, ATAPI_IDE0_lock |
add eax, [cdpos] |
dec eax |
mov [eax], byte 0 |
popa |
ret |
;************************************************* |
;* ÇÀÃÐÓÇÈÒÜ ÍÎÑÈÒÅËÜ Â ÄÈÑÊÎÂÎÄ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
LoadMedium: |
pusha |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü êîìàíäó START/STOP UNIT |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand], word 1Bh |
; Çàäàòü îïåðàöèþ çàãðóçêè íîñèòåëÿ |
mov [PacketCommand+4], word 00000011b |
; Ïîäàòü êîìàíäó |
call SendPacketNoDatCommand |
popa |
ret |
;************************************************* |
;* ÈÇÂËÅ×Ü ÍÎÑÈÒÅËÜ ÈÇ ÄÈÑÊÎÂÎÄÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
EjectMedium: |
pusha |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü êîìàíäó START/STOP UNIT |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand], word 1Bh |
; Çàäàòü îïåðàöèþ èçâëå÷åíèÿ íîñèòåëÿ |
mov [PacketCommand+4], word 00000010b |
; Ïîäàòü êîìàíäó |
call SendPacketNoDatCommand |
popa |
ret |
;************************************************* |
;* Ïðîâåðèòü ñîáûòèå íàæàòèÿ êíîïêè èçâëå÷åíèÿ * |
;* äèñêà * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
align 4 |
check_ATAPI_device_event: |
pusha |
mov eax, [timer_ticks] |
sub eax, [timer_ATAPI_check] |
cmp eax, 100 |
jb .end_1 |
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 |
.end: |
sti |
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 |
call reserve_ok2 |
mov [ChannelNumber], 2 |
mov [DiskNumber], 1 |
mov [cdpos], 4 |
call GetEvent_StatusNotification |
cmp [CDDataBuf+4], byte 1 |
je .eject_ide3 |
call syscall_cdaudio.free |
jmp .ide2_1 |
.eject_ide3: |
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 |
call reserve_ok2 |
mov [ChannelNumber], 2 |
mov [DiskNumber], 0 |
mov [cdpos], 3 |
call GetEvent_StatusNotification |
cmp [CDDataBuf+4], byte 1 |
je .eject_ide2 |
call syscall_cdaudio.free |
jmp .ide1_1 |
.eject_ide2: |
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 |
call reserve_ok2 |
mov [ChannelNumber], 1 |
mov [DiskNumber], 1 |
mov [cdpos], 2 |
call GetEvent_StatusNotification |
cmp [CDDataBuf+4], byte 1 |
je .eject_ide1 |
call syscall_cdaudio.free |
jmp .ide0_1 |
.eject_ide1: |
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 |
cmp [cd_status], 0 |
jne .end |
mov [IDE_Channel_1], 1 |
call reserve_ok2 |
mov [ChannelNumber], 1 |
mov [DiskNumber], 0 |
mov [cdpos], 1 |
call GetEvent_StatusNotification |
cmp [CDDataBuf+4], byte 1 |
je .eject_ide0 |
call syscall_cdaudio.free |
jmp .end |
.eject_ide0: |
call .eject |
call syscall_cdaudio.free |
jmp .end |
.eject: |
call clear_CD_cache |
call allow_medium_removal |
mov [ignore_CD_eject_wait], 1 |
call EjectMedium |
mov [ignore_CD_eject_wait], 0 |
ret |
iglobal |
timer_ATAPI_check dd 0 |
ATAPI_IDE0_lock db 0 |
ATAPI_IDE1_lock db 0 |
ATAPI_IDE2_lock db 0 |
ATAPI_IDE3_lock db 0 |
ignore_CD_eject_wait db 0 |
endg |
;************************************************* |
;* Ïîëó÷èòü ñîîáùåíèå î ñîáûòèè èëè ñîñòîÿíèè * |
;* óñòðîéñòâà * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
GetEvent_StatusNotification: |
pusha |
mov [CDDataBuf_pointer], CDDataBuf |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Çàäàòü êîä êîìàíäû |
mov [PacketCommand], byte 4Ah |
mov [PacketCommand+1], byte 00000001b |
; Çàäàòü çàïðîñ êëàññà ñîîáùåíèé |
mov [PacketCommand+4], byte 00010000b |
; Ðàçìåð âûäåëåííîé îáëàñòè |
mov [PacketCommand+7], byte 8h |
mov [PacketCommand+8], byte 0h |
; Ïîäàòü êîìàíäó |
call SendPacketDatCommand |
popa |
ret |
;************************************************* |
; ïðî÷èòàòü èíôîðìàöèþ èç TOC |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
Read_TOC: |
pusha |
mov [CDDataBuf_pointer], CDDataBuf |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
call clear_packet_buffer |
; Ñôîðìèðîâàòü ïàêåòíóþ êîìàíäó äëÿ ñ÷èòûâàíèÿ |
; ñåêòîðà äàííûõ |
mov [PacketCommand], byte 0x43 |
; Çàäàòü ôîðìàò |
mov [PacketCommand+2], byte 1 |
; Ðàçìåð âûäåëåííîé îáëàñòè |
mov [PacketCommand+7], byte 0xFF |
mov [PacketCommand+8], byte 0h |
; Ïîäàòü êîìàíäó |
call SendPacketDatCommand |
popa |
ret |
;************************************************* |
;* ÎÏÐÅÄÅËÈÒÜ ÎÁÙÅÅ ÊÎËÈ×ÅÑÒÂÎ ÑÅÊÒÎÐΠÍÀ ÄÈÑÊÅ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;************************************************* |
;ReadCapacity: |
; pusha |
;; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
; call clear_packet_buffer |
;; Çàäàòü ðàçìåð áóôåðà â áàéòàõ |
; mov [CDBlockSize],8 |
;; Ñôîðìèðîâàòü êîìàíäó READ CAPACITY |
; mov [PacketCommand],word 25h |
;; Ïîäàòü êîìàíäó |
; call SendPacketDatCommand |
; popa |
; ret |
clear_packet_buffer: |
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû |
and [PacketCommand], dword 0 |
and [PacketCommand+4], dword 0 |
and [PacketCommand+8], dword 0 |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/blkdev/cdrom.inc |
---|
1,271 → 1,271 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
sys_cd_audio: |
cmp word [cdbase],word 0 |
jnz @f |
mov eax,1 |
ret |
@@: |
; eax=1 cdplay at ebx 0x00FFSSMM |
; eax=2 get tracklist size of ecx to [ebx] |
; eax=3 stop/pause playing |
cmp eax,1 |
jnz nocdp |
call sys_cdplay |
ret |
nocdp: |
cmp eax,2 |
jnz nocdtl |
mov edi,[TASK_BASE] |
add edi,TASKDATA.mem_start |
add ebx,[edi] |
call sys_cdtracklist |
ret |
nocdtl: |
cmp eax,3 |
jnz nocdpause |
call sys_cdpause |
ret |
nocdpause: |
mov eax,0xffffff01 |
ret |
sys_cd_atapi_command: |
pushad |
mov dx,word [cdbase] |
add dx,6 |
mov ax,word [cdid] |
out dx,al |
mov esi,10 |
call delay_ms |
mov dx,word [cdbase] |
add dx,7 |
in al,dx |
and al,0x80 |
cmp al,0 |
jnz res |
jmp cdl6 |
res: |
mov dx,word [cdbase] |
add dx,7 |
mov al,0x8 |
out dx,al |
mov dx,word [cdbase] |
add dx,0x206 |
mov al,0xe |
out dx,al |
mov esi,1 |
call delay_ms |
mov dx,word [cdbase] |
add dx,0x206 |
mov al,0x8 |
out dx,al |
mov esi,30 |
call delay_ms |
xor cx,cx |
cdl5: |
inc cx |
cmp cx,10 |
jz cdl6 |
mov dx,word [cdbase] |
add dx,7 |
in al,dx |
and al,0x88 |
cmp al,0x00 |
jz cdl5 |
mov esi,100 |
call delay_ms |
jmp cdl5 |
cdl6: |
mov dx,word [cdbase] |
add dx,4 |
mov al,0 |
out dx,al |
mov dx,word [cdbase] |
add dx,5 |
mov al,0 |
out dx,al |
mov dx,word [cdbase] |
add dx,7 |
mov al,0xec |
out dx,al |
mov esi,5 |
call delay_ms |
mov dx,word [cdbase] |
add dx,1 |
mov al,0 |
out dx,al |
add dx,1 |
mov al,0 |
out dx,al |
add dx,1 |
mov al,0 |
out dx,al |
add dx,1 |
mov al,0 |
out dx,al |
add dx,1 |
mov al,128 |
out dx,al |
add dx,2 |
mov al,0xa0 |
out dx,al |
xor cx,cx |
mov dx,word [cdbase] |
add dx,7 |
cdl1: |
inc cx |
cmp cx,100 |
jz cdl2 |
in al,dx |
and ax,0x88 |
cmp al,0x8 |
jz cdl2 |
mov esi,2 |
call delay_ms |
jmp cdl1 |
cdl2: |
popad |
ret |
sys_cdplay: |
mov ax,5 |
push ax |
push ebx |
cdplay: |
call sys_cd_atapi_command |
cli |
mov dx,word [cdbase] |
mov ax,0x0047 |
out dx,ax |
mov al,1 |
mov ah,[esp+0] ; min xx |
out dx,ax |
mov ax,[esp+1] ; fr sec |
out dx,ax |
mov ax,256+99 |
out dx,ax |
mov ax,0x0001 |
out dx,ax |
mov ax,0x0000 |
out dx,ax |
mov esi,10 |
call delay_ms |
sti |
add dx,7 |
in al,dx |
test al,1 |
jz cdplayok |
mov ax,[esp+4] |
dec ax |
mov [esp+4],ax |
cmp ax,0 |
jz cdplayfail |
jmp cdplay |
cdplayfail: |
cdplayok: |
pop ebx |
pop ax |
xor eax, eax |
ret |
sys_cdtracklist: |
push ebx |
tcdplay: |
call sys_cd_atapi_command |
mov dx,word [cdbase] |
mov ax,0x43+2*256 |
out dx,ax |
mov ax,0x0 |
out dx,ax |
mov ax,0x0 |
out dx,ax |
mov ax,0x0 |
out dx,ax |
mov ax,200 |
out dx,ax |
mov ax,0x0 |
out dx,ax |
in al,dx |
mov cx,1000 |
mov dx,word [cdbase] |
add dx,7 |
cld |
cdtrnwewait: |
mov esi,10 |
call delay_ms |
in al,dx |
and al,128 |
cmp al,0 |
jz cdtrl1 |
loop cdtrnwewait |
cdtrl1: |
; read the result |
mov ecx,[esp+0] |
mov dx,word [cdbase] |
cdtrread: |
add dx,7 |
in al,dx |
and al,8 |
cmp al,8 |
jnz cdtrdone |
sub dx,7 |
in ax,dx |
mov [ecx],ax |
add ecx,2 |
jmp cdtrread |
cdtrdone: |
pop ecx |
xor eax, eax |
ret |
sys_cdpause: |
call sys_cd_atapi_command |
mov dx,word [cdbase] |
mov ax,0x004B |
out dx,ax |
mov ax,0 |
out dx,ax |
mov ax,0 |
out dx,ax |
mov ax,0 |
out dx,ax |
mov ax,0 |
out dx,ax |
mov ax,0 |
out dx,ax |
mov esi,10 |
call delay_ms |
add dx,7 |
in al,dx |
xor eax, eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
sys_cd_audio: |
cmp word [cdbase], word 0 |
jnz @f |
mov eax, 1 |
ret |
@@: |
; eax=1 cdplay at ebx 0x00FFSSMM |
; eax=2 get tracklist size of ecx to [ebx] |
; eax=3 stop/pause playing |
cmp eax, 1 |
jnz nocdp |
call sys_cdplay |
ret |
nocdp: |
cmp eax, 2 |
jnz nocdtl |
mov edi, [TASK_BASE] |
add edi, TASKDATA.mem_start |
add ebx, [edi] |
call sys_cdtracklist |
ret |
nocdtl: |
cmp eax, 3 |
jnz nocdpause |
call sys_cdpause |
ret |
nocdpause: |
mov eax, 0xffffff01 |
ret |
sys_cd_atapi_command: |
pushad |
mov dx, word [cdbase] |
add dx, 6 |
mov ax, word [cdid] |
out dx, al |
mov esi, 10 |
call delay_ms |
mov dx, word [cdbase] |
add dx, 7 |
in al, dx |
and al, 0x80 |
cmp al, 0 |
jnz res |
jmp cdl6 |
res: |
mov dx, word [cdbase] |
add dx, 7 |
mov al, 0x8 |
out dx, al |
mov dx, word [cdbase] |
add dx, 0x206 |
mov al, 0xe |
out dx, al |
mov esi, 1 |
call delay_ms |
mov dx, word [cdbase] |
add dx, 0x206 |
mov al, 0x8 |
out dx, al |
mov esi, 30 |
call delay_ms |
xor cx, cx |
cdl5: |
inc cx |
cmp cx, 10 |
jz cdl6 |
mov dx, word [cdbase] |
add dx, 7 |
in al, dx |
and al, 0x88 |
cmp al, 0x00 |
jz cdl5 |
mov esi, 100 |
call delay_ms |
jmp cdl5 |
cdl6: |
mov dx, word [cdbase] |
add dx, 4 |
mov al, 0 |
out dx, al |
mov dx, word [cdbase] |
add dx, 5 |
mov al, 0 |
out dx, al |
mov dx, word [cdbase] |
add dx, 7 |
mov al, 0xec |
out dx, al |
mov esi, 5 |
call delay_ms |
mov dx, word [cdbase] |
add dx, 1 |
mov al, 0 |
out dx, al |
add dx, 1 |
mov al, 0 |
out dx, al |
add dx, 1 |
mov al, 0 |
out dx, al |
add dx, 1 |
mov al, 0 |
out dx, al |
add dx, 1 |
mov al, 128 |
out dx, al |
add dx, 2 |
mov al, 0xa0 |
out dx, al |
xor cx, cx |
mov dx, word [cdbase] |
add dx, 7 |
cdl1: |
inc cx |
cmp cx, 100 |
jz cdl2 |
in al, dx |
and ax, 0x88 |
cmp al, 0x8 |
jz cdl2 |
mov esi, 2 |
call delay_ms |
jmp cdl1 |
cdl2: |
popad |
ret |
sys_cdplay: |
mov ax, 5 |
push ax |
push ebx |
cdplay: |
call sys_cd_atapi_command |
cli |
mov dx, word [cdbase] |
mov ax, 0x0047 |
out dx, ax |
mov al, 1 |
mov ah, [esp+0]; min xx |
out dx, ax |
mov ax, [esp+1]; fr sec |
out dx, ax |
mov ax, 256+99 |
out dx, ax |
mov ax, 0x0001 |
out dx, ax |
mov ax, 0x0000 |
out dx, ax |
mov esi, 10 |
call delay_ms |
sti |
add dx, 7 |
in al, dx |
test al, 1 |
jz cdplayok |
mov ax, [esp+4] |
dec ax |
mov [esp+4], ax |
cmp ax, 0 |
jz cdplayfail |
jmp cdplay |
cdplayfail: |
cdplayok: |
pop ebx |
pop ax |
xor eax, eax |
ret |
sys_cdtracklist: |
push ebx |
tcdplay: |
call sys_cd_atapi_command |
mov dx, word [cdbase] |
mov ax, 0x43+2*256 |
out dx, ax |
mov ax, 0x0 |
out dx, ax |
mov ax, 0x0 |
out dx, ax |
mov ax, 0x0 |
out dx, ax |
mov ax, 200 |
out dx, ax |
mov ax, 0x0 |
out dx, ax |
in al, dx |
mov cx, 1000 |
mov dx, word [cdbase] |
add dx, 7 |
cld |
cdtrnwewait: |
mov esi, 10 |
call delay_ms |
in al, dx |
and al, 128 |
cmp al, 0 |
jz cdtrl1 |
loop cdtrnwewait |
cdtrl1: |
; read the result |
mov ecx, [esp+0] |
mov dx, word [cdbase] |
cdtrread: |
add dx, 7 |
in al, dx |
and al, 8 |
cmp al, 8 |
jnz cdtrdone |
sub dx, 7 |
in ax, dx |
mov [ecx], ax |
add ecx, 2 |
jmp cdtrread |
cdtrdone: |
pop ecx |
xor eax, eax |
ret |
sys_cdpause: |
call sys_cd_atapi_command |
mov dx, word [cdbase] |
mov ax, 0x004B |
out dx, ax |
mov ax, 0 |
out dx, ax |
mov ax, 0 |
out dx, ax |
mov ax, 0 |
out dx, ax |
mov ax, 0 |
out dx, ax |
mov ax, 0 |
out dx, ax |
mov esi, 10 |
call delay_ms |
add dx, 7 |
in al, dx |
xor eax, eax |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/blkdev/disk.inc |
---|
1,1258 → 1,1258 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; ============================================================================= |
; ================================= Constants ================================= |
; ============================================================================= |
; Error codes for callback functions. |
DISK_STATUS_OK = 0 ; success |
DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable |
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 |
; Driver flags. Represent bits in DISK.DriverFlags. |
DISK_NO_INSERT_NOTIFICATION = 1 |
; Media flags. Represent bits in DISKMEDIAINFO.Flags. |
DISK_MEDIA_READONLY = 1 |
; If too many partitions are detected,there is probably an error on the disk. |
; 256 partitions should be enough for any reasonable use. |
; Also, the same number is limiting the number of MBRs to process; if |
; too many MBRs are visible,there probably is a loop in the MBR structure. |
MAX_NUM_PARTITIONS = 256 |
; ============================================================================= |
; ================================ Structures ================================= |
; ============================================================================= |
; This structure defines all callback functions for working with the physical |
; device. They are implemented by a driver. Objects with this structure reside |
; in a driver. |
struct DISKFUNC |
.strucsize dd ? |
; Size of the structure. This field is intended for possible extensions of |
; this structure. If a new function is added to this structure and a driver |
; implements an old version, the caller can detect this by checking .strucsize, |
; so the driver remains compatible. |
.close dd ? |
; The pointer to the function which frees all driver-specific resources for |
; the disk. |
; Optional, may be NULL. |
; void close(void* userdata); |
.closemedia dd ? |
; The pointer to the function which informs the driver that the kernel has |
; finished all processing with the current media. If media is removed, the |
; driver should decline all requests to that media with DISK_STATUS_NO_MEDIA, |
; even if new media is inserted, until this function is called. If media is |
; removed, a new call to 'disk_media_changed' is not allowed until this |
; function is called. |
; Optional, may be NULL (if media is not removable). |
; void closemedia(void* userdata); |
.querymedia dd ? |
; The pointer to the function which determines capabilities of the media. |
; int querymedia(void* userdata, DISKMEDIAINFO* info); |
; Return value: one of DISK_STATUS_* |
.read dd ? |
; The pointer to the function which reads data from the device. |
; int read(void* userdata, void* buffer, __int64 startsector, int* numsectors); |
; input: *numsectors = number of sectors to read |
; output: *numsectors = number of sectors which were successfully read |
; Return value: one of DISK_STATUS_* |
.write dd ? |
; The pointer to the function which writes data to the device. |
; Optional, may be NULL. |
; int write(void* userdata, void* buffer, __int64 startsector, int* numsectors); |
; input: *numsectors = number of sectors to write |
; output: *numsectors = number of sectors which were successfully written |
; Return value: one of DISK_STATUS_* |
.flush dd ? |
; The pointer to the function which flushes the internal device cache. |
; Optional, may be NULL. |
; int flush(void* userdata); |
; Return value: one of DISK_STATUS_* |
; Note that read/write are called by the cache manager, so a driver should not |
; create a software cache. This function is implemented for flushing a hardware |
; cache, if it exists. |
.adjust_cache_size dd ? |
; The pointer to the function which returns the cache size for this device. |
; Optional, may be NULL. |
; unsigned int adjust_cache_size(unsigned int suggested_size); |
; Return value: 0 = disable cache, otherwise = used cache size in bytes. |
ends |
; This structure holds information on a medium. |
; Objects with this structure are allocated by the kernel as a part of the DISK |
; structure and are filled by a driver in the 'querymedia' callback. |
struct DISKMEDIAINFO |
.Flags dd ? |
; Combination of DISK_MEDIA_* bits. |
.SectorSize dd ? |
; Size of the sector. |
.Capacity dq ? |
; Size of the media in sectors. |
ends |
; This structure represents the disk cache. To follow the old implementation, |
; there are two distinct caches for a disk, one for "system" data,and the other |
; for "application" data. |
struct DISKCACHE |
.Lock MUTEX |
; Lock to protect the cache. |
; The following fields are inherited from data32.inc:cache_ideX. |
.pointer rd 1 |
.data_size rd 1 ; not use |
.data rd 1 |
.sad_size rd 1 |
.search_start rd 1 |
ends |
; This structure represents a disk device and its media for the kernel. |
; This structure is allocated by the kernel in the 'disk_add' function, |
; freed in the 'disk_dereference' function. |
struct DISK |
; Fields of disk object |
.Next dd ? |
.Prev dd ? |
; All disk devices are linked in one list with these two fields. |
; Head of the list is the 'disk_list' variable. |
.Functions dd ? |
; Pointer to the 'DISKFUNC' structure with driver functions. |
.Name dd ? |
; Pointer to the string used for accesses through the global filesystem. |
.UserData dd ? |
; This field is passed to all callback functions so a driver can decide which |
; physical device is addressed. |
.DriverFlags dd ? |
; Bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit is defined. |
; If it is set, the driver will never issue 'disk_media_changed' notification |
; with argument set to true, so the kernel must try to detect media during |
; requests from the file system. |
.RefCount dd ? |
; Count of active references to this structure. One reference is kept during |
; the lifetime of the structure between 'disk_add' and 'disk_del'. |
; Another reference is taken during any filesystem operation for this disk. |
; One reference is added if media is inserted. |
; The structure is destroyed when the reference count decrements to zero: |
; this usually occurs in 'disk_del', but can be delayed to the end of last |
; filesystem operation, if one is active. |
.MediaLock MUTEX |
; Lock to protect the MEDIA structure. See the description after |
; 'disk_list_mutex' for the locking strategy. |
; Fields of media object |
.MediaInserted db ? |
; 0 if media is not inserted, nonzero otherwise. |
.MediaUsed db ? |
; 0 if media fields are not used, nonzero otherwise. If .MediaRefCount is |
; nonzero, this field is nonzero too; however, when .MediaRefCount goes |
; to zero, there is some time interval during which media object is still used. |
align 4 |
; The following fields are not valid unless either .MediaInserted is nonzero |
; or they are accessed from a code which has obtained the reference when |
; .MediaInserted was nonzero. |
.MediaRefCount dd ? |
; Count of active references to the media object. One reference is kept during |
; the lifetime of the media between two calls to 'disk_media_changed'. |
; Another reference is taken during any filesystem operation for this media. |
; The callback 'closemedia' is called when the reference count decrements to |
; zero: this usually occurs in 'disk_media_changed', but can be delayed to the |
; end of the last filesystem operation, if one is active. |
.MediaInfo DISKMEDIAINFO |
; This field keeps information on the current media. |
.NumPartitions dd ? |
; Number of partitions on this media. |
.Partitions dd ? |
; Pointer to array of .NumPartitions pointers to PARTITION structures. |
.cache_size dd ? |
; inherited from cache_ideX_size |
.SysCache DISKCACHE |
.AppCache DISKCACHE |
; Two caches for the disk. |
ends |
; This structure represents one partition for the kernel. This is a base |
; template, the actual contents after common fields is determined by the |
; file system code for this partition. |
struct PARTITION |
.FirstSector dq ? |
; First sector of the partition. |
.Length dq ? |
; Length of the partition in sectors. |
.Disk dd ? |
; Pointer to parent DISK structure. |
.FSUserFunctions dd ? |
; Handlers for the sysfunction 70h. This field is a pointer to the following |
; array. The first dword is a number of supported subfunctions, other dwords |
; point to handlers of corresponding subfunctions. |
; This field is 0 if file system is not recognized. |
; ...fs-specific data may follow... |
ends |
; This is an external structure, it represents an entry in the partition table. |
struct PARTITION_TABLE_ENTRY |
.Bootable db ? |
; 80h = bootable partition, 0 = non-bootable partition, other values = invalid |
.FirstHead db ? |
.FirstSector db ? |
.FirstTrack db ? |
; Coordinates of first sector in CHS. |
.Type db ? |
; Partition type, one of predefined constants. 0 = empty, several types denote |
; extended partition (see process_partition_table_entry), we are not interested |
; in other values. |
.LastHead db ? |
.LastSector db ? |
.LastTrack db ? |
; Coordinates of last sector in CHS. |
.FirstAbsSector dd ? |
; Coordinate of first sector in LBA. |
.Length dd ? |
; Length of the partition in sectors. |
ends |
; ============================================================================= |
; ================================ Global data ================================ |
; ============================================================================= |
iglobal |
; The pseudo-item for the list of all DISK structures. |
; Initialized to the empty list. |
disk_list: |
dd disk_list |
dd disk_list |
endg |
uglobal |
; This mutex guards all operations with the global list of DISK structures. |
disk_list_mutex MUTEX |
; * There are two dependent objects, a disk and a media. In the simplest case, |
; disk and media are both non-removable. However, in the general case both |
; can be removed at any time, simultaneously or only media,and this makes things |
; complicated. |
; * For efficiency, both disk and media objects are located in the one |
; structure named DISK. However, logically they are different. |
; * The following operations use data of disk object: adding (disk_add); |
; deleting (disk_del); filesystem (fs_lfn which eventually calls |
; dyndisk_handler or dyndisk_enum_root). |
; * The following operations use data of media object: adding/removing |
; (disk_media_changed); filesystem (fs_lfn which eventually calls |
; dyndisk_handler; dyndisk_enum_root doesn't work with media). |
; * Notifications disk_add, disk_media_changed, disk_del are synchronized |
; between themselves, this is a requirement for the driver. However, file |
; system operations are asynchronous, can be issued at any time by any |
; thread. |
; * We must prevent a situation when a filesystem operation thinks that the |
; object is still valid but in fact the notification has destroyed the |
; object. So we keep a reference counter for both disk and media and destroy |
; the object when this counter goes to zero. |
; * The driver must know when it is safe to free driver-allocated resources. |
; The object can be alive even after death notification has completed. |
; We use special callbacks to satisfy both assertions: 'close' for the disk |
; and 'closemedia' for the media. The destruction of the object includes |
; calling the corresponding callback. |
; * Each filesystem operation keeps one reference for the disk and one |
; reference for the media. Notification disk_del forces notification on the |
; media death, so the reference counter for the disk is always not less than |
; the reference counter for the media. |
; * Two operations "get the object" and "increment the reference counter" can |
; not be done simultaneously. We use a mutex to guard the consistency here. |
; It must be a part of the container for the object, so that this mutex can |
; be acquired as a part of getting the object from the container. The |
; container for disk object is the global list, and this list is guarded by |
; 'disk_list_mutex'. The container for media object is the disk object, and |
; the corresponding mutex is DISK.MediaLock. |
; * Notifications do not change the data of objects, they can only remove |
; objects. Thus we don't need another synchronization at this level. If two |
; filesystem operations are referencing the same filesystem data, this is |
; better resolved at the level of the filesystem. |
endg |
iglobal |
; The function 'disk_scan_partitions' needs three 512-byte 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. |
; 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 |
; this value. If the resulting value is zero, it uses the buffers and |
; decrements the value when the job is done. Otherwise, it immediately |
; decrements the value and uses buffers from the heap, allocated in the |
; beginning and freed in the end. |
partition_buffer_users dd -1 |
endg |
uglobal |
; The static buffers for MBR, bootsector and fs-temporary sector data. |
align 16 |
mbr_buffer rb 512 |
bootsect_buffer rb 512 |
fs_tmp_buffer rb 512 |
endg |
iglobal |
; This is the array of default implementations of driver callbacks. |
; Same as DRIVERFUNC structure except for the first field; all functions must |
; have the default implementations. |
align 4 |
disk_default_callbacks: |
dd disk_default_close |
dd disk_default_closemedia |
dd disk_default_querymedia |
dd disk_default_read |
dd disk_default_write |
dd disk_default_flush |
dd disk_default_adjust_cache_size |
endg |
; ============================================================================= |
; ================================= Functions ================================= |
; ============================================================================= |
; This function registers a disk device. |
; This includes: |
; - allocating an internal structure describing this device; |
; - registering this structure in the global filesystem. |
; The function initializes the disk as if there is no media. If a media is |
; present, the function 'disk_media_changed' should be called after this |
; function succeeds. |
; Parameters: |
; [esp+4] = pointer to DISKFUNC structure with the callbacks |
; [esp+8] = pointer to name (ASCIIZ string) |
; [esp+12] = userdata to be passed to the callbacks as is. |
; [esp+16] = flags, bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit |
; is defined. |
; Return value: |
; NULL = operation has failed |
; non-NULL = handle of the disk. This handle can be used |
; in the operations with other Disk* functions. |
; The handle is the pointer to the internal structure DISK. |
disk_add: |
push ebx esi ; save used registers to be stdcall |
; 1. Allocate the DISK structure. |
; 1a. Call the heap manager. |
push sizeof.DISK |
pop eax |
call malloc |
; 1b. Check the result. If allocation failed, return (go to 9) with eax = 0. |
test eax, eax |
jz .nothing |
; 2. Copy the disk name to the DISK structure. |
; 2a. Get length of the name, including the terminating zero. |
mov ebx, [esp+8+8] ; ebx = pointer to name |
push eax ; save allocated pointer to DISK |
xor eax, eax ; the argument of malloc() is in eax |
@@: |
inc eax |
cmp byte [ebx+eax-1], 0 |
jnz @b |
; 2b. Call the heap manager. |
call malloc |
; 2c. Check the result. If allocation failed, go to 7. |
pop esi ; restore allocated pointer to DISK |
test eax, eax |
jz .free |
; 2d. Store the allocated pointer to the DISK structure. |
mov [esi+DISK.Name], eax |
; 2e. Copy the name. |
@@: |
mov dl, [ebx] |
mov [eax], dl |
inc ebx |
inc eax |
test dl, dl |
jnz @b |
; 3. Copy other arguments of the function to the DISK structure. |
mov eax, [esp+4+8] |
mov [esi+DISK.Functions], eax |
mov eax, [esp+12+8] |
mov [esi+DISK.UserData], eax |
mov eax, [esp+16+8] |
mov [esi+DISK.DriverFlags], eax |
; 4. Initialize other fields of the DISK structure. |
; Media is not inserted, reference counter is 1. |
lea ecx, [esi+DISK.MediaLock] |
call mutex_init |
xor eax, eax |
mov dword [esi+DISK.MediaInserted], eax |
inc eax |
mov [esi+DISK.RefCount], eax |
; The DISK structure is initialized. |
; 5. Insert the new structure to the global list. |
; 5a. Acquire the mutex. |
mov ecx, disk_list_mutex |
call mutex_lock |
; 5b. Insert item to the tail of double-linked list. |
mov edx, disk_list |
list_add_tail esi, edx ;esi= new edx= list head |
; 5c. Release the mutex. |
call mutex_unlock |
; 6. Return with eax = pointer to DISK. |
xchg eax, esi |
jmp .nothing |
.free: |
; Memory allocation for DISK structure succeeded, but for disk name failed. |
; 7. Free the DISK structure. |
xchg eax, esi |
call free |
; 8. Return with eax = 0. |
xor eax, eax |
.nothing: |
; 9. Return. |
pop esi ebx ; restore used registers to be stdcall |
ret 16 ; purge 4 dword arguments to be stdcall |
; This function deletes a disk device from the global filesystem. |
; This includes: |
; - removing a media including all partitions; |
; - deleting this structure from the global filesystem; |
; - dereferencing the DISK structure and possibly destroying it. |
; Parameters: |
; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. |
; Return value: none. |
disk_del: |
push esi ; save used registers to be stdcall |
; 1. Force media to be removed. If the media is already removed, the |
; call does nothing. |
mov esi, [esp+4+8] ; esi = handle of the disk |
stdcall disk_media_changed, esi, 0 |
; 2. Delete the structure from the global list. |
; 2a. Acquire the mutex. |
mov ecx, disk_list_mutex |
call mutex_lock |
; 2b. Delete item from double-linked list. |
mov eax, [esi+DISK.Next] |
mov edx, [esi+DISK.Prev] |
mov [eax+DISK.Prev], edx |
mov [edx+DISK.Next], eax |
; 2c. Release the mutex. |
call mutex_unlock |
; 3. The structure still has one reference created in disk_add. Remove this |
; reference. If there are no other references, disk_dereference will free the |
; structure. |
call disk_dereference |
; 4. Return. |
pop esi ; restore used registers to be stdcall |
ret 4 ; purge 1 dword argument to be stdcall |
; This is an internal function which removes a previously obtained reference |
; to the disk. If this is the last reference, this function lets the driver |
; finalize all associated data, and afterwards frees the DISK structure. |
; esi = pointer to DISK structure |
disk_dereference: |
; 1. Decrement reference counter. Use atomic operation to correctly handle |
; possible simultaneous calls. |
lock dec [esi+DISK.RefCount] |
; 2. If the result is nonzero, there are other references, so nothing to do. |
; In this case, return (go to 4). |
jnz .nothing |
; 3. If we are here, we just removed the last reference and must destroy the |
; disk object. |
; 3a. Call the driver. |
mov al, DISKFUNC.close |
stdcall disk_call_driver |
; 3b. Free the structure. |
xchg eax, esi |
call free |
; 4. Return. |
.nothing: |
ret |
; This is an internal function which removes a previously obtained reference |
; to the media. If this is the last reference, this function calls 'closemedia' |
; callback to signal the driver that the processing has finished and it is safe |
; to inform about a new media. |
; esi = pointer to DISK structure |
disk_media_dereference: |
; 1. Decrement reference counter. Use atomic operation to correctly handle |
; possible simultaneous calls. |
lock dec [esi+DISK.MediaRefCount] |
; 2. If the result is nonzero, there are other references, so nothing to do. |
; In this case, return (go to 4). |
jnz .nothing |
; 3. If we are here, we just removed the last reference and must destroy the |
; media object. |
; Note that the same place inside the DISK structure is reused for all media |
; objects, so we must guarantee that reusing does not happen while freeing. |
; Reusing is only possible when someone processes a new media. There are two |
; mutually exclusive variants: |
; * driver issues media insert notifications (DISK_NO_INSERT_NOTIFICATION bit |
; in DISK.DriverFlags is not set). In this case, we require from the driver |
; that such notification (except for the first one) can occur only after a |
; call to 'closemedia' callback. |
; * driver does not issue media insert notifications. In this case, the kernel |
; itself must sometimes check whether media is inserted. We have the flag |
; DISK.MediaUsed, visible to the kernel. This flag signals to the other parts |
; of kernel that the way is free. |
; In the first case other parts of the kernel do not use DISK.MediaUsed, so it |
; does not matter when this flag is cleared. In the second case this flag must |
; be cleared after all other actions, including call to 'closemedia'. |
; 3a. Free all partitions. |
push esi edi |
mov edi, [esi+DISK.NumPartitions] |
mov esi, [esi+DISK.Partitions] |
test edi, edi |
jz .nofree |
.freeloop: |
lodsd |
call free |
dec edi |
jnz .freeloop |
.nofree: |
pop edi esi |
; 3b. Free the cache. |
call disk_free_cache |
; 3c. Call the driver. |
mov al, DISKFUNC.closemedia |
stdcall disk_call_driver |
; 3d. Clear the flag. |
mov [esi+DISK.MediaUsed], 0 |
.nothing: |
ret |
; This function is called by the driver and informs the kernel that the media |
; has changed. If the media is non-removable, it is called exactly once |
; immediately after 'disk_add' and once from 'disk_del'. |
; Parameters: |
; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. |
; [esp+8] = new status of the media: zero = no media, nonzero = media inserted. |
disk_media_changed: |
push ebx esi edi ; save used registers to be stdcall |
; 1. Remove the existing media, if it is present. |
mov esi, [esp+4+12] ; esi = pointer to DISK |
; 1a. Check whether it is present. Since DISK.MediaInserted is changed only |
; in this function and calls to this function are synchronized, no lock is |
; required for checking. |
cmp [esi+DISK.MediaInserted], 0 |
jz .noremove |
; We really need to remove the media. |
; 1b. Acquire mutex. |
lea ecx, [esi+DISK.MediaLock] |
call mutex_lock |
; 1c. Clear the flag. |
mov [esi+DISK.MediaInserted], 0 |
; 1d. Release mutex. |
call mutex_unlock |
; 1e. Remove the "lifetime" reference and possibly destroy the structure. |
call disk_media_dereference |
.noremove: |
; 2. Test whether there is new media. |
cmp dword [esp+8+12], 0 |
jz .noinsert |
; Yep, there is. |
; 3. Process the new media. We assume that all media fields are available to |
; use, see comments in 'disk_media_dereference' (this covers using by previous |
; media referencers) and note that calls to this function are synchronized |
; (this covers using by new media referencers). |
; 3a. Call the 'querymedia' callback. |
; .Flags are set to zero for possible future extensions. |
lea edx, [esi+DISK.MediaInfo] |
and [edx+DISKMEDIAINFO.Flags], 0 |
mov al, DISKFUNC.querymedia |
stdcall disk_call_driver, edx |
; 3b. Check the result of the callback. Abort if it failed. |
test eax, eax |
jnz .noinsert |
; 3c. Allocate the cache unless disabled by the driver. Abort if failed. |
call disk_init_cache |
test al, al |
jz .noinsert |
; 3d. Acquire the lifetime reference for the media object. |
inc [esi+DISK.MediaRefCount] |
; 3e. Scan for partitions. Ignore result; the list of partitions is valid even |
; on errors. |
call disk_scan_partitions |
; 3f. Media is inserted and available for use. |
inc [esi+DISK.MediaInserted] |
.noinsert: |
; 4. Return. |
pop edi esi ebx ; restore used registers to be stdcall |
ret 8 ; purge 2 dword arguments to be stdcall |
; This function is a thunk for all functions of a disk driver. |
; It checks whether the referenced function is implemented in the driver. |
; If so, this function jumps to the function in the driver. |
; Otherwise, it jumps to the default implementation. |
; al = offset of function in the DISKFUNC structure; |
; esi = pointer to the DISK structure; |
; stack is the same as for the corresponding function except that the |
; first parameter (void* userdata) is prepended automatically. |
disk_call_driver: |
movzx eax, al ; eax = offset of function in the DISKFUNC structure |
; 1. Prepend the first argument to the stack. |
pop ecx ; ecx = return address |
push [esi+DISK.UserData] ; add argument |
push ecx ; save return address |
; 2. Check that the required function is inside the table. If not, go to 5. |
mov ecx, [esi+DISK.Functions] |
cmp eax, [ecx+DISKFUNC.strucsize] |
jae .default |
; 3. Check that the required function is implemented. If not, go to 5. |
mov ecx, [ecx+eax] |
test ecx, ecx |
jz .default |
; 4. Jump to the required function. |
jmp ecx |
.default: |
; 5. Driver does not implement the required function; use default implementation. |
jmp dword [disk_default_callbacks+eax-4] |
; The default implementation of DISKFUNC.querymedia. |
disk_default_querymedia: |
push DISK_STATUS_INVALID_CALL |
pop eax |
ret 8 |
; The default implementation of DISKFUNC.read and DISKFUNC.write. |
disk_default_read: |
disk_default_write: |
push DISK_STATUS_INVALID_CALL |
pop eax |
ret 20 |
; The default implementation of DISKFUNC.close, DISKFUNC.closemedia and |
; DISKFUNC.flush. |
disk_default_close: |
disk_default_closemedia: |
disk_default_flush: |
xor eax, eax |
ret 4 |
; The default implementation of DISKFUNC.adjust_cache_size. |
disk_default_adjust_cache_size: |
mov eax, [esp+4] |
ret 4 |
; This is an internal function called from 'disk_media_changed' when a new media |
; is detected. It creates the list of partitions for the media. |
; If media is not partitioned, then the list consists of one partition which |
; covers all the media. |
; esi = pointer to the DISK structure. |
disk_scan_partitions: |
; 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 |
; the 'partition_buffer_users' variable. |
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 |
test eax, eax |
jz .nothing |
xchg eax, ebx |
.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. |
; ebp will hold the sector number for current MBR/EBR. |
; [esp] will hold the sector number for current extended partition, if there |
; is one. |
; [esp+4] will hold the counter that prevents long loops. |
push ebp ; save ebp |
push MAX_NUM_PARTITIONS ; the counter of max MBRs to process |
xor ebp, ebp ; start from sector zero |
push ebp ; no extended partition yet |
.new_mbr: |
; 5. Read the current sector. |
; Note that 'read' callback operates with 64-bit sector numbers, so we must |
; push additional zero as a high dword of sector number. |
mov al, DISKFUNC.read |
push 1 |
stdcall disk_call_driver, ebx, ebp, 0, esp |
pop ecx |
; 6. If the read has failed, abort the loop. |
dec ecx |
jnz .mbr_failed |
; 7. Check the MBR/EBR signature. If it is wrong, abort the loop. |
; Soon we will access the partition table which starts at ebx+0x1BE, |
; so we can fill its address right now. If we do it now, then the addressing |
; [ecx+0x40] is shorter than [ebx+0x1fe]: one-byte offset vs 4-bytes offset. |
lea ecx, [ebx+0x1be] ; ecx -> partition table |
cmp word [ecx+0x40], 0xaa55 |
jnz .mbr_failed |
; 8. The MBR is treated differently from EBRs. For MBR we additionally need to |
; execute step 9 and possibly step 10. |
test ebp, ebp |
jnz .mbr |
; The partition table can be present or not present. In the first case, we just |
; read the MBR. In the second case, we just read the bootsector for a |
; filesystem. |
; The following algorithm is used to distinguish between these cases. |
; A. If at least one entry of the partition table is invalid, this is |
; a bootsector. See the description of 'is_partition_table_entry' for |
; definition of validity. |
; B. If all entries are empty (filesystem type field is zero) and the first |
; byte is jmp opcode (0EBh or 0E9h), this is a bootsector which happens to |
; have zeros in the place of partition table. |
; C. Otherwise, this is an MBR. |
; 9. Test for MBR vs bootsector. |
; 9a. Check entries. If any is invalid, go to 10 (rule A). |
call is_partition_table_entry |
jc .notmbr |
add ecx, 10h |
call is_partition_table_entry |
jc .notmbr |
add ecx, 10h |
call is_partition_table_entry |
jc .notmbr |
add ecx, 10h |
call is_partition_table_entry |
jc .notmbr |
; 9b. Check types of the entries. If at least one is nonzero, go to 11 (rule C). |
mov al, [ecx-30h+PARTITION_TABLE_ENTRY.Type] |
or al, [ecx-20h+PARTITION_TABLE_ENTRY.Type] |
or al, [ecx-10h+PARTITION_TABLE_ENTRY.Type] |
or al, [ecx+PARTITION_TABLE_ENTRY.Type] |
jnz .mbr |
; 9c. Empty partition table or bootsector with many zeroes? (rule B) |
cmp byte [ebx], 0EBh |
jz .notmbr |
cmp byte [ebx], 0E9h |
jnz .mbr |
.notmbr: |
; 10. This is not an MBR. The media is not partitioned. Create one partition |
; which covers all the media and abort the loop. |
stdcall disk_add_partition, 0, 0, \ |
dword [esi+DISK.MediaInfo.Capacity], dword [esi+DISK.MediaInfo.Capacity+4] |
jmp .done |
.mbr: |
; 11. Process all entries of the new MBR/EBR |
lea ecx, [ebx+0x1be] ; ecx -> partition table |
push 0 ; assume no extended partition |
call process_partition_table_entry |
add ecx, 10h |
call process_partition_table_entry |
add ecx, 10h |
call process_partition_table_entry |
add ecx, 10h |
call process_partition_table_entry |
pop ebp |
; 12. Test whether we found a new EBR and should continue the loop. |
; 12a. If there was no next EBR, return. |
test ebp, ebp |
jz .done |
; Ok, we have EBR. |
; 12b. EBRs addresses are relative to the start of extended partition. |
; For simplicity, just abort if an 32-bit overflow occurs; large disks |
; are most likely partitioned with GPT, not MBR scheme, since the precise |
; calculation here would increase limit just twice at the price of big |
; compatibility problems. |
pop eax ; load extended partition |
add ebp, eax |
jc .mbr_failed |
; 12c. If extended partition has not yet started, start it. |
test eax, eax |
jnz @f |
mov eax, ebp |
@@: |
; 12c. If the limit is not exceeded, continue the loop. |
dec dword [esp] |
push eax ; store extended partition |
jnz .new_mbr |
.mbr_failed: |
.done: |
; 13. Cleanup after the loop. |
pop eax ; not important anymore |
pop eax ; not important anymore |
pop ebp ; restore ebp |
; 14. Release the buffer. |
; 14a. Test whether it is the global buffer or we have allocated it. |
cmp ebx, mbr_buffer |
jz .release_partition_buffer |
; 14b. If we have allocated it, free it. |
xchg eax, ebx |
call free |
jmp .nothing |
; 14c. Otherwise, release reference. |
.release_partition_buffer: |
lock dec [partition_buffer_users] |
.nothing: |
; 15. Return. |
ret |
; This is an internal function called from disk_scan_partitions. It checks |
; whether the entry pointed to by ecx is a valid entry of partition table. |
; The entry is valid if the first byte is 0 or 80h, the first sector plus the |
; length is less than twice the size of media. Multiplication by two is |
; required since the size mentioned in the partition table can be slightly |
; greater than the real size. |
is_partition_table_entry: |
; 1. Check .Bootable field. |
mov al, [ecx+PARTITION_TABLE_ENTRY.Bootable] |
and al, 7Fh |
jnz .invalid |
; 3. Calculate first sector + length. Note that .FirstAbsSector is relative |
; to the MBR/EBR, so the real sum is ebp + .FirstAbsSector + .Length. |
mov eax, ebp |
xor edx, edx |
add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] |
adc edx, 0 |
add eax, [ecx+PARTITION_TABLE_ENTRY.Length] |
adc edx, 0 |
; 4. Divide by two. |
shr edx, 1 |
rcr eax, 1 |
; 5. Compare with capacity. If the subtraction (edx:eax) - .Capacity does not |
; overflow, this is bad. |
sub eax, dword [esi+DISK.MediaInfo.Capacity] |
sbb edx, dword [esi+DISK.MediaInfo.Capacity+4] |
jnc .invalid |
.valid: |
; 5. Return success: CF is cleared. |
clc |
ret |
.invalid: |
; 6. Return fail: CF is set. |
stc |
ret |
; This is an internal function called from disk_scan_partitions. It processes |
; the entry pointed to by ecx. |
; * If the entry is invalid, just ignore this entry. |
; * If the type is zero, just ignore this entry. |
; * If the type is one of types for extended partition, store the address |
; of this partition as the new MBR in [esp+4]. |
; * Otherwise, add the partition to the list of partitions for this disk. |
; We don't use the type from the entry to identify the file system; |
; fs-specific checks do this more reliably. |
process_partition_table_entry: |
; 1. Check for valid entry. If invalid, return (go to 5). |
call is_partition_table_entry |
jc .nothing |
; 2. Check for empty entry. If invalid, return (go to 5). |
mov al, [ecx+PARTITION_TABLE_ENTRY.Type] |
test al, al |
jz .nothing |
; 3. Check for extended partition. If extended, go to 6. |
irp type,\ |
0x05,\ ; DOS: extended partition |
0x0f,\ ; WIN95: extended partition, LBA-mapped |
0xc5,\ ; DRDOS/secured: extended partition |
0xd5 ; Old Multiuser DOS secured: extended partition |
{ |
cmp al, type |
jz .extended |
} |
; 4. If we are here, that is a normal partition. Add it to the list. |
; Note that the first sector is relative to MBR/EBR. |
mov eax, ebp |
xor edx, edx |
add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] |
adc edx, 0 |
push ecx |
stdcall disk_add_partition, eax, edx, \ |
[ecx+PARTITION_TABLE_ENTRY.Length], 0 |
pop ecx |
.nothing: |
; 5. Return. |
ret |
.extended: |
; 6. If we are here, that is an extended partition. Store the address. |
mov eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] |
mov [esp+4], eax |
ret |
; This is an internal function called from disk_scan_partitions and |
; process_partition_table_entry. It adds one partition to the list of |
; partitions for the media. |
proc disk_add_partition stdcall uses ebx edi, start:qword, length:qword |
; 1. Check that this partition will not exceed the limit on total number. |
cmp [esi+DISK.NumPartitions], MAX_NUM_PARTITIONS |
jae .nothing |
; 2. Check that this partition does not overlap with any already registered |
; partition. Since any file system assumes that the disk data will not change |
; outside of its control, such overlap could be destructive. |
; Since the number of partitions is usually very small and is guaranteed not |
; to be large, the simple linear search is sufficient. |
; 2a. Prepare the loop: edi will point to the current item of .Partitions |
; array, ecx will be the current item, ebx will hold number of items left. |
mov edi, [esi+DISK.Partitions] |
mov ebx, [esi+DISK.NumPartitions] |
test ebx, ebx |
jz .partitionok |
.scan_existing: |
; 2b. Get the next partition. |
mov ecx, [edi] |
add edi, 4 |
; The range [.FirstSector, .FirstSector+.Length) must be either entirely to |
; the left of [start, start+length) or entirely to the right. |
; 2c. Subtract .FirstSector - start. The possible overflow distinguish between |
; cases "to the left" (2e) and "to the right" (2d). |
mov eax, dword [ecx+PARTITION.FirstSector] |
mov edx, dword [ecx+PARTITION.FirstSector+4] |
sub eax, dword [start] |
sbb edx, dword [start+4] |
jb .less |
; 2d. .FirstSector is greater than or equal to start. Check that .FirstSector |
; is greater than or equal to start+length; the subtraction |
; (.FirstSector-start) - length must not cause overflow. Go to 2g if life is |
; good or to 2f in the other case. |
sub eax, dword [length] |
sbb edx, dword [length+4] |
jb .overlap |
jmp .next_existing |
.less: |
; 2e. .FirstSector is less than start. Check that .FirstSector+.Length is less |
; than or equal to start. If the addition (.FirstSector-start) + .Length does |
; not cause overflow, then .FirstSector + .Length is strictly less than start; |
; since the equality is also valid, use decrement preliminarily. Go to 2g or |
; 2f depending on the overflow. |
sub eax, 1 |
sbb edx, 0 |
add eax, dword [ecx+PARTITION.Length] |
adc edx, dword [ecx+PARTITION.Length+4] |
jnc .next_existing |
.overlap: |
; 2f. The partition overlaps with previously registered partition. Say warning |
; and return with nothing done. |
dbgstr 'two partitions overlap, ignoring the last one' |
jmp .nothing |
.next_existing: |
; 2g. The partition does not overlap with the current partition. Continue the |
; loop. |
dec ebx |
jnz .scan_existing |
.partitionok: |
; 3. The partition has passed tests. Reallocate the partitions array for a new |
; entry. |
; 3a. Call the allocator. |
mov eax, [esi+DISK.NumPartitions] |
inc eax ; one more entry |
shl eax, 2 ; each entry is dword |
call malloc |
; 3b. Test the result. If failed, return with nothing done. |
test eax, eax |
jz .nothing |
; 3c. Copy the old array to the new array. |
mov edi, eax |
push esi |
mov ecx, [esi+DISK.NumPartitions] |
mov esi, [esi+DISK.Partitions] |
rep movsd |
pop esi |
; 3d. Set the field in the DISK structure to the new array. |
xchg [esi+DISK.Partitions], eax |
; 3e. Free the old array. |
call free |
; 4. Recognize the file system. |
; 4a. Call the filesystem recognizer. It will allocate the PARTITION structure |
; with possible filesystem-specific fields. |
call disk_detect_partition |
; 4b. Check return value. If zero, return with list not changed; so far only |
; the array was reallocated, this is ok for other code. |
test eax, eax |
jz .nothing |
; 5. Insert the new partition to the list. |
stosd |
inc [esi+DISK.NumPartitions] |
; 6. Return. |
.nothing: |
ret |
endp |
; This is an internal function called from disk_add_partition. |
; It tries to recognize the file system on the partition and allocates the |
; corresponding PARTITION structure with filesystem-specific fields. |
disk_detect_partition: |
; This function inherits the stack frame from disk_add_partition. In stdcall |
; with ebp-based frame arguments start from ebp+8, since [ebp]=saved ebp |
; and [ebp+4]=return address. |
virtual at ebp+8 |
.start dq ? |
.length dq ? |
end virtual |
; Currently no file systems are supported, so just allocate the PARTITION |
; structure without extra fields. |
; 1. Allocate and check result. |
push sizeof.PARTITION |
pop eax |
call malloc |
test eax, eax |
jz .nothing |
; 2. Fill the common fields: copy .start and .length. |
mov edx, dword [.start] |
mov dword [eax+PARTITION.FirstSector], edx |
mov edx, dword [.start+4] |
mov dword [eax+PARTITION.FirstSector+4], edx |
mov edx, dword [.length] |
mov dword [eax+PARTITION.Length], edx |
mov edx, dword [.length+4] |
mov dword [eax+PARTITION.Length+4], edx |
.nothing: |
; 3. Return with eax = pointer to PARTITION or NULL. |
ret |
; This function is called from file_system_lfn. |
; This handler gets the control each time when fn 70 is called |
; with unknown item of root subdirectory. |
; in: esi -> name |
; ebp = 0 or rest of name relative to esi |
; out: if the handler processes path, it must not return in file_system_lfn, |
; but instead pop return address and return directly to the caller |
; otherwise simply return |
dyndisk_handler: |
push ebx edi ; save registers used in file_system_lfn |
; 1. Acquire the mutex. |
mov ecx, disk_list_mutex |
call mutex_lock |
; 2. Loop over the list of DISK structures. |
; 2a. Initialize. |
mov ebx, disk_list |
.scan: |
; 2b. Get the next item. |
mov ebx, [ebx+DISK.Next] |
; 2c. Check whether the list is done. If so, go to 3. |
cmp ebx, disk_list |
jz .notfound |
; 2d. Compare names. If names match, go to 5. |
mov edi, [ebx+DISK.Name] |
push esi |
@@: |
; esi points to the name from fs operation; it is terminated by zero or slash. |
lodsb |
test al, al |
jz .eoin_dec |
cmp al, '/' |
jz .eoin |
; edi points to the disk name. |
inc edi |
; edi points to lowercase name, this is a requirement for the driver. |
; Characters at esi can have any register. Lowercase the current character. |
; This lowercasing works for latin letters and digits; since the disk name |
; should not contain other symbols, this is ok. |
or al, 20h |
cmp al, [edi-1] |
jz @b |
.wrongname: |
; 2f. Names don't match. Continue the loop. |
pop esi |
jmp .scan |
.notfound: |
; The loop is done and no name matches. |
; 3. Release the mutex. |
call mutex_unlock |
; 4. Return normally. |
pop edi ebx ; restore registers used in file_system_lfn |
ret |
; part of 2d: the name matches partially, but we must check that this is full |
; equality. |
.eoin_dec: |
dec esi |
.eoin: |
cmp byte [edi], 0 |
jnz .wrongname |
; We found the addressed DISK structure. |
; 5. Reference the disk. |
lock inc [ebx+DISK.RefCount] |
; 6. Now we are sure that the DISK structure is not going to die at least |
; while we are working with it, so release the global mutex. |
call mutex_unlock |
; 7. Acquire the mutex for media object. |
pop edi ; restore edi |
lea ecx, [ebx+DISK.MediaLock] |
call mutex_lock |
; 8. Get the media object. If it is not NULL, reference it. |
xor edx, edx |
cmp [ebx+DISK.MediaInserted], dl |
jz @f |
mov edx, ebx |
inc [ebx+DISK.MediaRefCount] |
@@: |
; 9. Now we are sure that the media object, if it exists, is not going to die |
; at least while we are working with it, so release the mutex for media object. |
call mutex_unlock |
mov ecx, ebx |
pop ebx eax ; restore ebx, pop return address |
; 10. Check whether the fs operation wants to enumerate partitions (go to 11) |
; or work with some concrete partition (go to 12). |
cmp byte [esi], 0 |
jnz .haspartition |
; 11. The fs operation wants to enumerate partitions. |
; 11a. Only "list directory" operation is applicable to /<diskname> path. Check |
; the operation code. If wrong, go to 13. |
cmp dword [ebx], 1 |
jnz .access_denied |
; 11b. If the media is inserted, use 'fs_dyndisk_next' as an enumeration |
; procedure. Otherwise, use 'fs_dyndisk_next_nomedia'. |
mov esi, fs_dyndisk_next_nomedia |
test edx, edx |
jz @f |
mov esi, fs_dyndisk_next |
@@: |
; 11c. Let the procedure from fs_lfn.inc do the job. |
jmp file_system_lfn.maindir_noesi |
.haspartition: |
; 12. The fs operation has specified some partition. |
; 12a. Store parameters for callback functions. |
push edx |
push ecx |
; 12b. Store callback functions. |
push dyndisk_cleanup |
push fs_dyndisk |
mov edi, esp |
; 12c. Let the procedure from fs_lfn.inc do the job. |
jmp file_system_lfn.found2 |
.access_denied: |
; 13. Fail the operation with the appropriate code. |
mov dword [esp+32], ERROR_ACCESS_DENIED |
.cleanup: |
; 14. Cleanup. |
mov esi, ecx ; disk*dereference assume that esi points to DISK |
.cleanup_esi: |
test edx, edx ; if there are no media, we didn't reference it |
jz @f |
call disk_media_dereference |
@@: |
call disk_dereference |
; 15. Return. |
ret |
; This is a callback for cleaning up things called from file_system_lfn.found2. |
dyndisk_cleanup: |
mov esi, [edi+8] |
mov edx, [edi+12] |
jmp dyndisk_handler.cleanup_esi |
; This is a callback for enumerating partitions called from |
; file_system_lfn.maindir in the case of inserted media. |
; It just increments eax until DISK.NumPartitions reached and then |
; cleans up. |
fs_dyndisk_next: |
cmp eax, [ecx+DISK.NumPartitions] |
jae .nomore |
inc eax |
clc |
ret |
.nomore: |
pusha |
mov esi, ecx |
call disk_media_dereference |
call disk_dereference |
popa |
stc |
ret |
; This is a callback for enumerating partitions called from |
; file_system_lfn.maindir in the case of missing media. |
; In this case we create one pseudo-partition. |
fs_dyndisk_next_nomedia: |
cmp eax, 1 |
jae .nomore |
inc eax |
clc |
ret |
.nomore: |
pusha |
mov esi, ecx |
call disk_dereference |
popa |
stc |
ret |
; This is a callback for doing real work with selected partition. |
; Currently this is just placeholder, since no file systems are supported. |
; edi = esp -> {dd fs_dyndisk, dd dyndisk_cleanup, dd pointer to DISK, dd media object} |
; ecx = partition number, esi+ebp = ASCIIZ name |
fs_dyndisk: |
dec ecx ; convert to zero-based partition index |
pop edx edx edx eax ; edx = pointer to DISK, eax = NULL or edx |
test eax, eax |
jz .nomedia |
.main: |
cmp ecx, [edx+DISK.NumPartitions] |
jae .notfound |
mov dword [esp+32], ERROR_UNKNOWN_FS |
.cleanup: |
mov esi, edx |
call disk_media_dereference |
call disk_dereference |
ret |
.notfound: |
mov dword [esp+32], ERROR_FILE_NOT_FOUND |
jmp .cleanup |
.nomedia: |
test ecx, ecx |
jnz .notfound |
test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION |
jz .deverror |
; if the driver does not support insert notifications and we are the only fs |
; operation with this disk, issue the fake insert notification; if media is |
; still not inserted, 'disk_media_changed' will detect this and do nothing |
;;; push ebx |
lea ecx, [edx+DISK.MediaLock] |
call mutex_lock |
cmp [edx+DISK.MediaRefCount], 1 |
jnz .noluck |
call mutex_unlock |
push edx |
stdcall disk_media_changed, edx, 1 |
pop edx |
lea ecx, [edx+DISK.MediaLock] |
call mutex_lock |
cmp [edx+DISK.MediaInserted], 0 |
jz .noluck |
lock inc [edx+DISK.MediaRefCount] |
call mutex_unlock |
xor ecx, ecx |
jmp .main |
.noluck: |
call mutex_unlock |
.deverror: |
mov dword [esp+32], ERROR_DEVICE |
mov esi, edx |
call disk_dereference |
ret |
; This function is called from file_system_lfn. |
; This handler is called when virtual root is enumerated |
; and must return all items which can be handled by this. |
; It is called several times, first time with eax=0 |
; in: eax = 0 for first call, previously returned value for subsequent calls |
; out: eax = 0 => no more items |
; eax != 0 => buffer pointed to by edi contains name of item |
dyndisk_enum_root: |
push edx ; save register used in file_system_lfn |
mov ecx, disk_list_mutex ; it will be useful |
; 1. If this is the first call, acquire the mutex and initialize. |
test eax, eax |
jnz .notfirst |
call mutex_lock |
mov eax, disk_list |
.notfirst: |
; 2. Get next item. |
mov eax, [eax+DISK.Next] |
; 3. If there are no more items, go to 6. |
cmp eax, disk_list |
jz .last |
; 4. Copy name from the DISK structure to edi. |
push eax esi |
mov esi, [eax+DISK.Name] |
@@: |
lodsb |
stosb |
test al, al |
jnz @b |
pop esi eax |
; 5. Return with eax = item. |
pop edx ; restore register used in file_system_lfn |
ret |
.last: |
; 6. Release the mutex and return with eax = 0. |
call mutex_unlock |
xor eax, eax |
pop edx ; restore register used in file_system_lfn |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; ============================================================================= |
; ================================= Constants ================================= |
; ============================================================================= |
; Error codes for callback functions. |
DISK_STATUS_OK = 0 ; success |
DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable |
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 |
; Driver flags. Represent bits in DISK.DriverFlags. |
DISK_NO_INSERT_NOTIFICATION = 1 |
; Media flags. Represent bits in DISKMEDIAINFO.Flags. |
DISK_MEDIA_READONLY = 1 |
; If too many partitions are detected,there is probably an error on the disk. |
; 256 partitions should be enough for any reasonable use. |
; Also, the same number is limiting the number of MBRs to process; if |
; too many MBRs are visible,there probably is a loop in the MBR structure. |
MAX_NUM_PARTITIONS = 256 |
; ============================================================================= |
; ================================ Structures ================================= |
; ============================================================================= |
; This structure defines all callback functions for working with the physical |
; device. They are implemented by a driver. Objects with this structure reside |
; in a driver. |
struct DISKFUNC |
.strucsize dd ? |
; Size of the structure. This field is intended for possible extensions of |
; this structure. If a new function is added to this structure and a driver |
; implements an old version, the caller can detect this by checking .strucsize, |
; so the driver remains compatible. |
.close dd ? |
; The pointer to the function which frees all driver-specific resources for |
; the disk. |
; Optional, may be NULL. |
; void close(void* userdata); |
.closemedia dd ? |
; The pointer to the function which informs the driver that the kernel has |
; finished all processing with the current media. If media is removed, the |
; driver should decline all requests to that media with DISK_STATUS_NO_MEDIA, |
; even if new media is inserted, until this function is called. If media is |
; removed, a new call to 'disk_media_changed' is not allowed until this |
; function is called. |
; Optional, may be NULL (if media is not removable). |
; void closemedia(void* userdata); |
.querymedia dd ? |
; The pointer to the function which determines capabilities of the media. |
; int querymedia(void* userdata, DISKMEDIAINFO* info); |
; Return value: one of DISK_STATUS_* |
.read dd ? |
; The pointer to the function which reads data from the device. |
; int read(void* userdata, void* buffer, __int64 startsector, int* numsectors); |
; input: *numsectors = number of sectors to read |
; output: *numsectors = number of sectors which were successfully read |
; Return value: one of DISK_STATUS_* |
.write dd ? |
; The pointer to the function which writes data to the device. |
; Optional, may be NULL. |
; int write(void* userdata, void* buffer, __int64 startsector, int* numsectors); |
; input: *numsectors = number of sectors to write |
; output: *numsectors = number of sectors which were successfully written |
; Return value: one of DISK_STATUS_* |
.flush dd ? |
; The pointer to the function which flushes the internal device cache. |
; Optional, may be NULL. |
; int flush(void* userdata); |
; Return value: one of DISK_STATUS_* |
; Note that read/write are called by the cache manager, so a driver should not |
; create a software cache. This function is implemented for flushing a hardware |
; cache, if it exists. |
.adjust_cache_size dd ? |
; The pointer to the function which returns the cache size for this device. |
; Optional, may be NULL. |
; unsigned int adjust_cache_size(unsigned int suggested_size); |
; Return value: 0 = disable cache, otherwise = used cache size in bytes. |
ends |
; This structure holds information on a medium. |
; Objects with this structure are allocated by the kernel as a part of the DISK |
; structure and are filled by a driver in the 'querymedia' callback. |
struct DISKMEDIAINFO |
.Flags dd ? |
; Combination of DISK_MEDIA_* bits. |
.SectorSize dd ? |
; Size of the sector. |
.Capacity dq ? |
; Size of the media in sectors. |
ends |
; This structure represents the disk cache. To follow the old implementation, |
; there are two distinct caches for a disk, one for "system" data,and the other |
; for "application" data. |
struct DISKCACHE |
.Lock MUTEX |
; Lock to protect the cache. |
; The following fields are inherited from data32.inc:cache_ideX. |
.pointer rd 1 |
.data_size rd 1 ; not use |
.data rd 1 |
.sad_size rd 1 |
.search_start rd 1 |
ends |
; This structure represents a disk device and its media for the kernel. |
; This structure is allocated by the kernel in the 'disk_add' function, |
; freed in the 'disk_dereference' function. |
struct DISK |
; Fields of disk object |
.Next dd ? |
.Prev dd ? |
; All disk devices are linked in one list with these two fields. |
; Head of the list is the 'disk_list' variable. |
.Functions dd ? |
; Pointer to the 'DISKFUNC' structure with driver functions. |
.Name dd ? |
; Pointer to the string used for accesses through the global filesystem. |
.UserData dd ? |
; This field is passed to all callback functions so a driver can decide which |
; physical device is addressed. |
.DriverFlags dd ? |
; Bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit is defined. |
; If it is set, the driver will never issue 'disk_media_changed' notification |
; with argument set to true, so the kernel must try to detect media during |
; requests from the file system. |
.RefCount dd ? |
; Count of active references to this structure. One reference is kept during |
; the lifetime of the structure between 'disk_add' and 'disk_del'. |
; Another reference is taken during any filesystem operation for this disk. |
; One reference is added if media is inserted. |
; The structure is destroyed when the reference count decrements to zero: |
; this usually occurs in 'disk_del', but can be delayed to the end of last |
; filesystem operation, if one is active. |
.MediaLock MUTEX |
; Lock to protect the MEDIA structure. See the description after |
; 'disk_list_mutex' for the locking strategy. |
; Fields of media object |
.MediaInserted db ? |
; 0 if media is not inserted, nonzero otherwise. |
.MediaUsed db ? |
; 0 if media fields are not used, nonzero otherwise. If .MediaRefCount is |
; nonzero, this field is nonzero too; however, when .MediaRefCount goes |
; to zero, there is some time interval during which media object is still used. |
align 4 |
; The following fields are not valid unless either .MediaInserted is nonzero |
; or they are accessed from a code which has obtained the reference when |
; .MediaInserted was nonzero. |
.MediaRefCount dd ? |
; Count of active references to the media object. One reference is kept during |
; the lifetime of the media between two calls to 'disk_media_changed'. |
; Another reference is taken during any filesystem operation for this media. |
; The callback 'closemedia' is called when the reference count decrements to |
; zero: this usually occurs in 'disk_media_changed', but can be delayed to the |
; end of the last filesystem operation, if one is active. |
.MediaInfo DISKMEDIAINFO |
; This field keeps information on the current media. |
.NumPartitions dd ? |
; Number of partitions on this media. |
.Partitions dd ? |
; Pointer to array of .NumPartitions pointers to PARTITION structures. |
.cache_size dd ? |
; inherited from cache_ideX_size |
.SysCache DISKCACHE |
.AppCache DISKCACHE |
; Two caches for the disk. |
ends |
; This structure represents one partition for the kernel. This is a base |
; template, the actual contents after common fields is determined by the |
; file system code for this partition. |
struct PARTITION |
.FirstSector dq ? |
; First sector of the partition. |
.Length dq ? |
; Length of the partition in sectors. |
.Disk dd ? |
; Pointer to parent DISK structure. |
.FSUserFunctions dd ? |
; Handlers for the sysfunction 70h. This field is a pointer to the following |
; array. The first dword is a number of supported subfunctions, other dwords |
; point to handlers of corresponding subfunctions. |
; This field is 0 if file system is not recognized. |
; ...fs-specific data may follow... |
ends |
; This is an external structure, it represents an entry in the partition table. |
struct PARTITION_TABLE_ENTRY |
.Bootable db ? |
; 80h = bootable partition, 0 = non-bootable partition, other values = invalid |
.FirstHead db ? |
.FirstSector db ? |
.FirstTrack db ? |
; Coordinates of first sector in CHS. |
.Type db ? |
; Partition type, one of predefined constants. 0 = empty, several types denote |
; extended partition (see process_partition_table_entry), we are not interested |
; in other values. |
.LastHead db ? |
.LastSector db ? |
.LastTrack db ? |
; Coordinates of last sector in CHS. |
.FirstAbsSector dd ? |
; Coordinate of first sector in LBA. |
.Length dd ? |
; Length of the partition in sectors. |
ends |
; ============================================================================= |
; ================================ Global data ================================ |
; ============================================================================= |
iglobal |
; The pseudo-item for the list of all DISK structures. |
; Initialized to the empty list. |
disk_list: |
dd disk_list |
dd disk_list |
endg |
uglobal |
; This mutex guards all operations with the global list of DISK structures. |
disk_list_mutex MUTEX |
; * There are two dependent objects, a disk and a media. In the simplest case, |
; disk and media are both non-removable. However, in the general case both |
; can be removed at any time, simultaneously or only media,and this makes things |
; complicated. |
; * For efficiency, both disk and media objects are located in the one |
; structure named DISK. However, logically they are different. |
; * The following operations use data of disk object: adding (disk_add); |
; deleting (disk_del); filesystem (fs_lfn which eventually calls |
; dyndisk_handler or dyndisk_enum_root). |
; * The following operations use data of media object: adding/removing |
; (disk_media_changed); filesystem (fs_lfn which eventually calls |
; dyndisk_handler; dyndisk_enum_root doesn't work with media). |
; * Notifications disk_add, disk_media_changed, disk_del are synchronized |
; between themselves, this is a requirement for the driver. However, file |
; system operations are asynchronous, can be issued at any time by any |
; thread. |
; * We must prevent a situation when a filesystem operation thinks that the |
; object is still valid but in fact the notification has destroyed the |
; object. So we keep a reference counter for both disk and media and destroy |
; the object when this counter goes to zero. |
; * The driver must know when it is safe to free driver-allocated resources. |
; The object can be alive even after death notification has completed. |
; We use special callbacks to satisfy both assertions: 'close' for the disk |
; and 'closemedia' for the media. The destruction of the object includes |
; calling the corresponding callback. |
; * Each filesystem operation keeps one reference for the disk and one |
; reference for the media. Notification disk_del forces notification on the |
; media death, so the reference counter for the disk is always not less than |
; the reference counter for the media. |
; * Two operations "get the object" and "increment the reference counter" can |
; not be done simultaneously. We use a mutex to guard the consistency here. |
; It must be a part of the container for the object, so that this mutex can |
; be acquired as a part of getting the object from the container. The |
; container for disk object is the global list, and this list is guarded by |
; 'disk_list_mutex'. The container for media object is the disk object, and |
; the corresponding mutex is DISK.MediaLock. |
; * Notifications do not change the data of objects, they can only remove |
; objects. Thus we don't need another synchronization at this level. If two |
; filesystem operations are referencing the same filesystem data, this is |
; better resolved at the level of the filesystem. |
endg |
iglobal |
; The function 'disk_scan_partitions' needs three 512-byte 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. |
; 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 |
; this value. If the resulting value is zero, it uses the buffers and |
; decrements the value when the job is done. Otherwise, it immediately |
; decrements the value and uses buffers from the heap, allocated in the |
; beginning and freed in the end. |
partition_buffer_users dd -1 |
endg |
uglobal |
; The static buffers for MBR, bootsector and fs-temporary sector data. |
align 16 |
mbr_buffer rb 512 |
bootsect_buffer rb 512 |
fs_tmp_buffer rb 512 |
endg |
iglobal |
; This is the array of default implementations of driver callbacks. |
; Same as DRIVERFUNC structure except for the first field; all functions must |
; have the default implementations. |
align 4 |
disk_default_callbacks: |
dd disk_default_close |
dd disk_default_closemedia |
dd disk_default_querymedia |
dd disk_default_read |
dd disk_default_write |
dd disk_default_flush |
dd disk_default_adjust_cache_size |
endg |
; ============================================================================= |
; ================================= Functions ================================= |
; ============================================================================= |
; This function registers a disk device. |
; This includes: |
; - allocating an internal structure describing this device; |
; - registering this structure in the global filesystem. |
; The function initializes the disk as if there is no media. If a media is |
; present, the function 'disk_media_changed' should be called after this |
; function succeeds. |
; Parameters: |
; [esp+4] = pointer to DISKFUNC structure with the callbacks |
; [esp+8] = pointer to name (ASCIIZ string) |
; [esp+12] = userdata to be passed to the callbacks as is. |
; [esp+16] = flags, bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit |
; is defined. |
; Return value: |
; NULL = operation has failed |
; non-NULL = handle of the disk. This handle can be used |
; in the operations with other Disk* functions. |
; The handle is the pointer to the internal structure DISK. |
disk_add: |
push ebx esi ; save used registers to be stdcall |
; 1. Allocate the DISK structure. |
; 1a. Call the heap manager. |
push sizeof.DISK |
pop eax |
call malloc |
; 1b. Check the result. If allocation failed, return (go to 9) with eax = 0. |
test eax, eax |
jz .nothing |
; 2. Copy the disk name to the DISK structure. |
; 2a. Get length of the name, including the terminating zero. |
mov ebx, [esp+8+8] ; ebx = pointer to name |
push eax ; save allocated pointer to DISK |
xor eax, eax ; the argument of malloc() is in eax |
@@: |
inc eax |
cmp byte [ebx+eax-1], 0 |
jnz @b |
; 2b. Call the heap manager. |
call malloc |
; 2c. Check the result. If allocation failed, go to 7. |
pop esi ; restore allocated pointer to DISK |
test eax, eax |
jz .free |
; 2d. Store the allocated pointer to the DISK structure. |
mov [esi+DISK.Name], eax |
; 2e. Copy the name. |
@@: |
mov dl, [ebx] |
mov [eax], dl |
inc ebx |
inc eax |
test dl, dl |
jnz @b |
; 3. Copy other arguments of the function to the DISK structure. |
mov eax, [esp+4+8] |
mov [esi+DISK.Functions], eax |
mov eax, [esp+12+8] |
mov [esi+DISK.UserData], eax |
mov eax, [esp+16+8] |
mov [esi+DISK.DriverFlags], eax |
; 4. Initialize other fields of the DISK structure. |
; Media is not inserted, reference counter is 1. |
lea ecx, [esi+DISK.MediaLock] |
call mutex_init |
xor eax, eax |
mov dword [esi+DISK.MediaInserted], eax |
inc eax |
mov [esi+DISK.RefCount], eax |
; The DISK structure is initialized. |
; 5. Insert the new structure to the global list. |
; 5a. Acquire the mutex. |
mov ecx, disk_list_mutex |
call mutex_lock |
; 5b. Insert item to the tail of double-linked list. |
mov edx, disk_list |
list_add_tail esi, edx ;esi= new edx= list head |
; 5c. Release the mutex. |
call mutex_unlock |
; 6. Return with eax = pointer to DISK. |
xchg eax, esi |
jmp .nothing |
.free: |
; Memory allocation for DISK structure succeeded, but for disk name failed. |
; 7. Free the DISK structure. |
xchg eax, esi |
call free |
; 8. Return with eax = 0. |
xor eax, eax |
.nothing: |
; 9. Return. |
pop esi ebx ; restore used registers to be stdcall |
ret 16 ; purge 4 dword arguments to be stdcall |
; This function deletes a disk device from the global filesystem. |
; This includes: |
; - removing a media including all partitions; |
; - deleting this structure from the global filesystem; |
; - dereferencing the DISK structure and possibly destroying it. |
; Parameters: |
; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. |
; Return value: none. |
disk_del: |
push esi ; save used registers to be stdcall |
; 1. Force media to be removed. If the media is already removed, the |
; call does nothing. |
mov esi, [esp+4+8] ; esi = handle of the disk |
stdcall disk_media_changed, esi, 0 |
; 2. Delete the structure from the global list. |
; 2a. Acquire the mutex. |
mov ecx, disk_list_mutex |
call mutex_lock |
; 2b. Delete item from double-linked list. |
mov eax, [esi+DISK.Next] |
mov edx, [esi+DISK.Prev] |
mov [eax+DISK.Prev], edx |
mov [edx+DISK.Next], eax |
; 2c. Release the mutex. |
call mutex_unlock |
; 3. The structure still has one reference created in disk_add. Remove this |
; reference. If there are no other references, disk_dereference will free the |
; structure. |
call disk_dereference |
; 4. Return. |
pop esi ; restore used registers to be stdcall |
ret 4 ; purge 1 dword argument to be stdcall |
; This is an internal function which removes a previously obtained reference |
; to the disk. If this is the last reference, this function lets the driver |
; finalize all associated data, and afterwards frees the DISK structure. |
; esi = pointer to DISK structure |
disk_dereference: |
; 1. Decrement reference counter. Use atomic operation to correctly handle |
; possible simultaneous calls. |
lock dec [esi+DISK.RefCount] |
; 2. If the result is nonzero, there are other references, so nothing to do. |
; In this case, return (go to 4). |
jnz .nothing |
; 3. If we are here, we just removed the last reference and must destroy the |
; disk object. |
; 3a. Call the driver. |
mov al, DISKFUNC.close |
stdcall disk_call_driver |
; 3b. Free the structure. |
xchg eax, esi |
call free |
; 4. Return. |
.nothing: |
ret |
; This is an internal function which removes a previously obtained reference |
; to the media. If this is the last reference, this function calls 'closemedia' |
; callback to signal the driver that the processing has finished and it is safe |
; to inform about a new media. |
; esi = pointer to DISK structure |
disk_media_dereference: |
; 1. Decrement reference counter. Use atomic operation to correctly handle |
; possible simultaneous calls. |
lock dec [esi+DISK.MediaRefCount] |
; 2. If the result is nonzero, there are other references, so nothing to do. |
; In this case, return (go to 4). |
jnz .nothing |
; 3. If we are here, we just removed the last reference and must destroy the |
; media object. |
; Note that the same place inside the DISK structure is reused for all media |
; objects, so we must guarantee that reusing does not happen while freeing. |
; Reusing is only possible when someone processes a new media. There are two |
; mutually exclusive variants: |
; * driver issues media insert notifications (DISK_NO_INSERT_NOTIFICATION bit |
; in DISK.DriverFlags is not set). In this case, we require from the driver |
; that such notification (except for the first one) can occur only after a |
; call to 'closemedia' callback. |
; * driver does not issue media insert notifications. In this case, the kernel |
; itself must sometimes check whether media is inserted. We have the flag |
; DISK.MediaUsed, visible to the kernel. This flag signals to the other parts |
; of kernel that the way is free. |
; In the first case other parts of the kernel do not use DISK.MediaUsed, so it |
; does not matter when this flag is cleared. In the second case this flag must |
; be cleared after all other actions, including call to 'closemedia'. |
; 3a. Free all partitions. |
push esi edi |
mov edi, [esi+DISK.NumPartitions] |
mov esi, [esi+DISK.Partitions] |
test edi, edi |
jz .nofree |
.freeloop: |
lodsd |
call free |
dec edi |
jnz .freeloop |
.nofree: |
pop edi esi |
; 3b. Free the cache. |
call disk_free_cache |
; 3c. Call the driver. |
mov al, DISKFUNC.closemedia |
stdcall disk_call_driver |
; 3d. Clear the flag. |
mov [esi+DISK.MediaUsed], 0 |
.nothing: |
ret |
; This function is called by the driver and informs the kernel that the media |
; has changed. If the media is non-removable, it is called exactly once |
; immediately after 'disk_add' and once from 'disk_del'. |
; Parameters: |
; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. |
; [esp+8] = new status of the media: zero = no media, nonzero = media inserted. |
disk_media_changed: |
push ebx esi edi ; save used registers to be stdcall |
; 1. Remove the existing media, if it is present. |
mov esi, [esp+4+12] ; esi = pointer to DISK |
; 1a. Check whether it is present. Since DISK.MediaInserted is changed only |
; in this function and calls to this function are synchronized, no lock is |
; required for checking. |
cmp [esi+DISK.MediaInserted], 0 |
jz .noremove |
; We really need to remove the media. |
; 1b. Acquire mutex. |
lea ecx, [esi+DISK.MediaLock] |
call mutex_lock |
; 1c. Clear the flag. |
mov [esi+DISK.MediaInserted], 0 |
; 1d. Release mutex. |
call mutex_unlock |
; 1e. Remove the "lifetime" reference and possibly destroy the structure. |
call disk_media_dereference |
.noremove: |
; 2. Test whether there is new media. |
cmp dword [esp+8+12], 0 |
jz .noinsert |
; Yep, there is. |
; 3. Process the new media. We assume that all media fields are available to |
; use, see comments in 'disk_media_dereference' (this covers using by previous |
; media referencers) and note that calls to this function are synchronized |
; (this covers using by new media referencers). |
; 3a. Call the 'querymedia' callback. |
; .Flags are set to zero for possible future extensions. |
lea edx, [esi+DISK.MediaInfo] |
and [edx+DISKMEDIAINFO.Flags], 0 |
mov al, DISKFUNC.querymedia |
stdcall disk_call_driver, edx |
; 3b. Check the result of the callback. Abort if it failed. |
test eax, eax |
jnz .noinsert |
; 3c. Allocate the cache unless disabled by the driver. Abort if failed. |
call disk_init_cache |
test al, al |
jz .noinsert |
; 3d. Acquire the lifetime reference for the media object. |
inc [esi+DISK.MediaRefCount] |
; 3e. Scan for partitions. Ignore result; the list of partitions is valid even |
; on errors. |
call disk_scan_partitions |
; 3f. Media is inserted and available for use. |
inc [esi+DISK.MediaInserted] |
.noinsert: |
; 4. Return. |
pop edi esi ebx ; restore used registers to be stdcall |
ret 8 ; purge 2 dword arguments to be stdcall |
; This function is a thunk for all functions of a disk driver. |
; It checks whether the referenced function is implemented in the driver. |
; If so, this function jumps to the function in the driver. |
; Otherwise, it jumps to the default implementation. |
; al = offset of function in the DISKFUNC structure; |
; esi = pointer to the DISK structure; |
; stack is the same as for the corresponding function except that the |
; first parameter (void* userdata) is prepended automatically. |
disk_call_driver: |
movzx eax, al ; eax = offset of function in the DISKFUNC structure |
; 1. Prepend the first argument to the stack. |
pop ecx ; ecx = return address |
push [esi+DISK.UserData] ; add argument |
push ecx ; save return address |
; 2. Check that the required function is inside the table. If not, go to 5. |
mov ecx, [esi+DISK.Functions] |
cmp eax, [ecx+DISKFUNC.strucsize] |
jae .default |
; 3. Check that the required function is implemented. If not, go to 5. |
mov ecx, [ecx+eax] |
test ecx, ecx |
jz .default |
; 4. Jump to the required function. |
jmp ecx |
.default: |
; 5. Driver does not implement the required function; use default implementation. |
jmp dword [disk_default_callbacks+eax-4] |
; The default implementation of DISKFUNC.querymedia. |
disk_default_querymedia: |
push DISK_STATUS_INVALID_CALL |
pop eax |
ret 8 |
; The default implementation of DISKFUNC.read and DISKFUNC.write. |
disk_default_read: |
disk_default_write: |
push DISK_STATUS_INVALID_CALL |
pop eax |
ret 20 |
; The default implementation of DISKFUNC.close, DISKFUNC.closemedia and |
; DISKFUNC.flush. |
disk_default_close: |
disk_default_closemedia: |
disk_default_flush: |
xor eax, eax |
ret 4 |
; The default implementation of DISKFUNC.adjust_cache_size. |
disk_default_adjust_cache_size: |
mov eax, [esp+4] |
ret 4 |
; This is an internal function called from 'disk_media_changed' when a new media |
; is detected. It creates the list of partitions for the media. |
; If media is not partitioned, then the list consists of one partition which |
; covers all the media. |
; esi = pointer to the DISK structure. |
disk_scan_partitions: |
; 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 |
; the 'partition_buffer_users' variable. |
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 |
test eax, eax |
jz .nothing |
xchg eax, ebx |
.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. |
; ebp will hold the sector number for current MBR/EBR. |
; [esp] will hold the sector number for current extended partition, if there |
; is one. |
; [esp+4] will hold the counter that prevents long loops. |
push ebp ; save ebp |
push MAX_NUM_PARTITIONS ; the counter of max MBRs to process |
xor ebp, ebp ; start from sector zero |
push ebp ; no extended partition yet |
.new_mbr: |
; 5. Read the current sector. |
; Note that 'read' callback operates with 64-bit sector numbers, so we must |
; push additional zero as a high dword of sector number. |
mov al, DISKFUNC.read |
push 1 |
stdcall disk_call_driver, ebx, ebp, 0, esp |
pop ecx |
; 6. If the read has failed, abort the loop. |
dec ecx |
jnz .mbr_failed |
; 7. Check the MBR/EBR signature. If it is wrong, abort the loop. |
; Soon we will access the partition table which starts at ebx+0x1BE, |
; so we can fill its address right now. If we do it now, then the addressing |
; [ecx+0x40] is shorter than [ebx+0x1fe]: one-byte offset vs 4-bytes offset. |
lea ecx, [ebx+0x1be] ; ecx -> partition table |
cmp word [ecx+0x40], 0xaa55 |
jnz .mbr_failed |
; 8. The MBR is treated differently from EBRs. For MBR we additionally need to |
; execute step 9 and possibly step 10. |
test ebp, ebp |
jnz .mbr |
; The partition table can be present or not present. In the first case, we just |
; read the MBR. In the second case, we just read the bootsector for a |
; filesystem. |
; The following algorithm is used to distinguish between these cases. |
; A. If at least one entry of the partition table is invalid, this is |
; a bootsector. See the description of 'is_partition_table_entry' for |
; definition of validity. |
; B. If all entries are empty (filesystem type field is zero) and the first |
; byte is jmp opcode (0EBh or 0E9h), this is a bootsector which happens to |
; have zeros in the place of partition table. |
; C. Otherwise, this is an MBR. |
; 9. Test for MBR vs bootsector. |
; 9a. Check entries. If any is invalid, go to 10 (rule A). |
call is_partition_table_entry |
jc .notmbr |
add ecx, 10h |
call is_partition_table_entry |
jc .notmbr |
add ecx, 10h |
call is_partition_table_entry |
jc .notmbr |
add ecx, 10h |
call is_partition_table_entry |
jc .notmbr |
; 9b. Check types of the entries. If at least one is nonzero, go to 11 (rule C). |
mov al, [ecx-30h+PARTITION_TABLE_ENTRY.Type] |
or al, [ecx-20h+PARTITION_TABLE_ENTRY.Type] |
or al, [ecx-10h+PARTITION_TABLE_ENTRY.Type] |
or al, [ecx+PARTITION_TABLE_ENTRY.Type] |
jnz .mbr |
; 9c. Empty partition table or bootsector with many zeroes? (rule B) |
cmp byte [ebx], 0EBh |
jz .notmbr |
cmp byte [ebx], 0E9h |
jnz .mbr |
.notmbr: |
; 10. This is not an MBR. The media is not partitioned. Create one partition |
; which covers all the media and abort the loop. |
stdcall disk_add_partition, 0, 0, \ |
dword [esi+DISK.MediaInfo.Capacity], dword [esi+DISK.MediaInfo.Capacity+4] |
jmp .done |
.mbr: |
; 11. Process all entries of the new MBR/EBR |
lea ecx, [ebx+0x1be] ; ecx -> partition table |
push 0 ; assume no extended partition |
call process_partition_table_entry |
add ecx, 10h |
call process_partition_table_entry |
add ecx, 10h |
call process_partition_table_entry |
add ecx, 10h |
call process_partition_table_entry |
pop ebp |
; 12. Test whether we found a new EBR and should continue the loop. |
; 12a. If there was no next EBR, return. |
test ebp, ebp |
jz .done |
; Ok, we have EBR. |
; 12b. EBRs addresses are relative to the start of extended partition. |
; For simplicity, just abort if an 32-bit overflow occurs; large disks |
; are most likely partitioned with GPT, not MBR scheme, since the precise |
; calculation here would increase limit just twice at the price of big |
; compatibility problems. |
pop eax ; load extended partition |
add ebp, eax |
jc .mbr_failed |
; 12c. If extended partition has not yet started, start it. |
test eax, eax |
jnz @f |
mov eax, ebp |
@@: |
; 12c. If the limit is not exceeded, continue the loop. |
dec dword [esp] |
push eax ; store extended partition |
jnz .new_mbr |
.mbr_failed: |
.done: |
; 13. Cleanup after the loop. |
pop eax ; not important anymore |
pop eax ; not important anymore |
pop ebp ; restore ebp |
; 14. Release the buffer. |
; 14a. Test whether it is the global buffer or we have allocated it. |
cmp ebx, mbr_buffer |
jz .release_partition_buffer |
; 14b. If we have allocated it, free it. |
xchg eax, ebx |
call free |
jmp .nothing |
; 14c. Otherwise, release reference. |
.release_partition_buffer: |
lock dec [partition_buffer_users] |
.nothing: |
; 15. Return. |
ret |
; This is an internal function called from disk_scan_partitions. It checks |
; whether the entry pointed to by ecx is a valid entry of partition table. |
; The entry is valid if the first byte is 0 or 80h, the first sector plus the |
; length is less than twice the size of media. Multiplication by two is |
; required since the size mentioned in the partition table can be slightly |
; greater than the real size. |
is_partition_table_entry: |
; 1. Check .Bootable field. |
mov al, [ecx+PARTITION_TABLE_ENTRY.Bootable] |
and al, 7Fh |
jnz .invalid |
; 3. Calculate first sector + length. Note that .FirstAbsSector is relative |
; to the MBR/EBR, so the real sum is ebp + .FirstAbsSector + .Length. |
mov eax, ebp |
xor edx, edx |
add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] |
adc edx, 0 |
add eax, [ecx+PARTITION_TABLE_ENTRY.Length] |
adc edx, 0 |
; 4. Divide by two. |
shr edx, 1 |
rcr eax, 1 |
; 5. Compare with capacity. If the subtraction (edx:eax) - .Capacity does not |
; overflow, this is bad. |
sub eax, dword [esi+DISK.MediaInfo.Capacity] |
sbb edx, dword [esi+DISK.MediaInfo.Capacity+4] |
jnc .invalid |
.valid: |
; 5. Return success: CF is cleared. |
clc |
ret |
.invalid: |
; 6. Return fail: CF is set. |
stc |
ret |
; This is an internal function called from disk_scan_partitions. It processes |
; the entry pointed to by ecx. |
; * If the entry is invalid, just ignore this entry. |
; * If the type is zero, just ignore this entry. |
; * If the type is one of types for extended partition, store the address |
; of this partition as the new MBR in [esp+4]. |
; * Otherwise, add the partition to the list of partitions for this disk. |
; We don't use the type from the entry to identify the file system; |
; fs-specific checks do this more reliably. |
process_partition_table_entry: |
; 1. Check for valid entry. If invalid, return (go to 5). |
call is_partition_table_entry |
jc .nothing |
; 2. Check for empty entry. If invalid, return (go to 5). |
mov al, [ecx+PARTITION_TABLE_ENTRY.Type] |
test al, al |
jz .nothing |
; 3. Check for extended partition. If extended, go to 6. |
irp type,\ |
0x05,\ ; DOS: extended partition |
0x0f,\ ; WIN95: extended partition, LBA-mapped |
0xc5,\ ; DRDOS/secured: extended partition |
0xd5 ; Old Multiuser DOS secured: extended partition |
{ |
cmp al, type |
jz .extended |
} |
; 4. If we are here, that is a normal partition. Add it to the list. |
; Note that the first sector is relative to MBR/EBR. |
mov eax, ebp |
xor edx, edx |
add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] |
adc edx, 0 |
push ecx |
stdcall disk_add_partition, eax, edx, \ |
[ecx+PARTITION_TABLE_ENTRY.Length], 0 |
pop ecx |
.nothing: |
; 5. Return. |
ret |
.extended: |
; 6. If we are here, that is an extended partition. Store the address. |
mov eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] |
mov [esp+4], eax |
ret |
; This is an internal function called from disk_scan_partitions and |
; process_partition_table_entry. It adds one partition to the list of |
; partitions for the media. |
proc disk_add_partition stdcall uses ebx edi, start:qword, length:qword |
; 1. Check that this partition will not exceed the limit on total number. |
cmp [esi+DISK.NumPartitions], MAX_NUM_PARTITIONS |
jae .nothing |
; 2. Check that this partition does not overlap with any already registered |
; partition. Since any file system assumes that the disk data will not change |
; outside of its control, such overlap could be destructive. |
; Since the number of partitions is usually very small and is guaranteed not |
; to be large, the simple linear search is sufficient. |
; 2a. Prepare the loop: edi will point to the current item of .Partitions |
; array, ecx will be the current item, ebx will hold number of items left. |
mov edi, [esi+DISK.Partitions] |
mov ebx, [esi+DISK.NumPartitions] |
test ebx, ebx |
jz .partitionok |
.scan_existing: |
; 2b. Get the next partition. |
mov ecx, [edi] |
add edi, 4 |
; The range [.FirstSector, .FirstSector+.Length) must be either entirely to |
; the left of [start, start+length) or entirely to the right. |
; 2c. Subtract .FirstSector - start. The possible overflow distinguish between |
; cases "to the left" (2e) and "to the right" (2d). |
mov eax, dword [ecx+PARTITION.FirstSector] |
mov edx, dword [ecx+PARTITION.FirstSector+4] |
sub eax, dword [start] |
sbb edx, dword [start+4] |
jb .less |
; 2d. .FirstSector is greater than or equal to start. Check that .FirstSector |
; is greater than or equal to start+length; the subtraction |
; (.FirstSector-start) - length must not cause overflow. Go to 2g if life is |
; good or to 2f in the other case. |
sub eax, dword [length] |
sbb edx, dword [length+4] |
jb .overlap |
jmp .next_existing |
.less: |
; 2e. .FirstSector is less than start. Check that .FirstSector+.Length is less |
; than or equal to start. If the addition (.FirstSector-start) + .Length does |
; not cause overflow, then .FirstSector + .Length is strictly less than start; |
; since the equality is also valid, use decrement preliminarily. Go to 2g or |
; 2f depending on the overflow. |
sub eax, 1 |
sbb edx, 0 |
add eax, dword [ecx+PARTITION.Length] |
adc edx, dword [ecx+PARTITION.Length+4] |
jnc .next_existing |
.overlap: |
; 2f. The partition overlaps with previously registered partition. Say warning |
; and return with nothing done. |
dbgstr 'two partitions overlap, ignoring the last one' |
jmp .nothing |
.next_existing: |
; 2g. The partition does not overlap with the current partition. Continue the |
; loop. |
dec ebx |
jnz .scan_existing |
.partitionok: |
; 3. The partition has passed tests. Reallocate the partitions array for a new |
; entry. |
; 3a. Call the allocator. |
mov eax, [esi+DISK.NumPartitions] |
inc eax ; one more entry |
shl eax, 2 ; each entry is dword |
call malloc |
; 3b. Test the result. If failed, return with nothing done. |
test eax, eax |
jz .nothing |
; 3c. Copy the old array to the new array. |
mov edi, eax |
push esi |
mov ecx, [esi+DISK.NumPartitions] |
mov esi, [esi+DISK.Partitions] |
rep movsd |
pop esi |
; 3d. Set the field in the DISK structure to the new array. |
xchg [esi+DISK.Partitions], eax |
; 3e. Free the old array. |
call free |
; 4. Recognize the file system. |
; 4a. Call the filesystem recognizer. It will allocate the PARTITION structure |
; with possible filesystem-specific fields. |
call disk_detect_partition |
; 4b. Check return value. If zero, return with list not changed; so far only |
; the array was reallocated, this is ok for other code. |
test eax, eax |
jz .nothing |
; 5. Insert the new partition to the list. |
stosd |
inc [esi+DISK.NumPartitions] |
; 6. Return. |
.nothing: |
ret |
endp |
; This is an internal function called from disk_add_partition. |
; It tries to recognize the file system on the partition and allocates the |
; corresponding PARTITION structure with filesystem-specific fields. |
disk_detect_partition: |
; This function inherits the stack frame from disk_add_partition. In stdcall |
; with ebp-based frame arguments start from ebp+8, since [ebp]=saved ebp |
; and [ebp+4]=return address. |
virtual at ebp+8 |
.start dq ? |
.length dq ? |
end virtual |
; Currently no file systems are supported, so just allocate the PARTITION |
; structure without extra fields. |
; 1. Allocate and check result. |
push sizeof.PARTITION |
pop eax |
call malloc |
test eax, eax |
jz .nothing |
; 2. Fill the common fields: copy .start and .length. |
mov edx, dword [.start] |
mov dword [eax+PARTITION.FirstSector], edx |
mov edx, dword [.start+4] |
mov dword [eax+PARTITION.FirstSector+4], edx |
mov edx, dword [.length] |
mov dword [eax+PARTITION.Length], edx |
mov edx, dword [.length+4] |
mov dword [eax+PARTITION.Length+4], edx |
.nothing: |
; 3. Return with eax = pointer to PARTITION or NULL. |
ret |
; This function is called from file_system_lfn. |
; This handler gets the control each time when fn 70 is called |
; with unknown item of root subdirectory. |
; in: esi -> name |
; ebp = 0 or rest of name relative to esi |
; out: if the handler processes path, it must not return in file_system_lfn, |
; but instead pop return address and return directly to the caller |
; otherwise simply return |
dyndisk_handler: |
push ebx edi ; save registers used in file_system_lfn |
; 1. Acquire the mutex. |
mov ecx, disk_list_mutex |
call mutex_lock |
; 2. Loop over the list of DISK structures. |
; 2a. Initialize. |
mov ebx, disk_list |
.scan: |
; 2b. Get the next item. |
mov ebx, [ebx+DISK.Next] |
; 2c. Check whether the list is done. If so, go to 3. |
cmp ebx, disk_list |
jz .notfound |
; 2d. Compare names. If names match, go to 5. |
mov edi, [ebx+DISK.Name] |
push esi |
@@: |
; esi points to the name from fs operation; it is terminated by zero or slash. |
lodsb |
test al, al |
jz .eoin_dec |
cmp al, '/' |
jz .eoin |
; edi points to the disk name. |
inc edi |
; edi points to lowercase name, this is a requirement for the driver. |
; Characters at esi can have any register. Lowercase the current character. |
; This lowercasing works for latin letters and digits; since the disk name |
; should not contain other symbols, this is ok. |
or al, 20h |
cmp al, [edi-1] |
jz @b |
.wrongname: |
; 2f. Names don't match. Continue the loop. |
pop esi |
jmp .scan |
.notfound: |
; The loop is done and no name matches. |
; 3. Release the mutex. |
call mutex_unlock |
; 4. Return normally. |
pop edi ebx ; restore registers used in file_system_lfn |
ret |
; part of 2d: the name matches partially, but we must check that this is full |
; equality. |
.eoin_dec: |
dec esi |
.eoin: |
cmp byte [edi], 0 |
jnz .wrongname |
; We found the addressed DISK structure. |
; 5. Reference the disk. |
lock inc [ebx+DISK.RefCount] |
; 6. Now we are sure that the DISK structure is not going to die at least |
; while we are working with it, so release the global mutex. |
call mutex_unlock |
; 7. Acquire the mutex for media object. |
pop edi ; restore edi |
lea ecx, [ebx+DISK.MediaLock] |
call mutex_lock |
; 8. Get the media object. If it is not NULL, reference it. |
xor edx, edx |
cmp [ebx+DISK.MediaInserted], dl |
jz @f |
mov edx, ebx |
inc [ebx+DISK.MediaRefCount] |
@@: |
; 9. Now we are sure that the media object, if it exists, is not going to die |
; at least while we are working with it, so release the mutex for media object. |
call mutex_unlock |
mov ecx, ebx |
pop ebx eax ; restore ebx, pop return address |
; 10. Check whether the fs operation wants to enumerate partitions (go to 11) |
; or work with some concrete partition (go to 12). |
cmp byte [esi], 0 |
jnz .haspartition |
; 11. The fs operation wants to enumerate partitions. |
; 11a. Only "list directory" operation is applicable to /<diskname> path. Check |
; the operation code. If wrong, go to 13. |
cmp dword [ebx], 1 |
jnz .access_denied |
; 11b. If the media is inserted, use 'fs_dyndisk_next' as an enumeration |
; procedure. Otherwise, use 'fs_dyndisk_next_nomedia'. |
mov esi, fs_dyndisk_next_nomedia |
test edx, edx |
jz @f |
mov esi, fs_dyndisk_next |
@@: |
; 11c. Let the procedure from fs_lfn.inc do the job. |
jmp file_system_lfn.maindir_noesi |
.haspartition: |
; 12. The fs operation has specified some partition. |
; 12a. Store parameters for callback functions. |
push edx |
push ecx |
; 12b. Store callback functions. |
push dyndisk_cleanup |
push fs_dyndisk |
mov edi, esp |
; 12c. Let the procedure from fs_lfn.inc do the job. |
jmp file_system_lfn.found2 |
.access_denied: |
; 13. Fail the operation with the appropriate code. |
mov dword [esp+32], ERROR_ACCESS_DENIED |
.cleanup: |
; 14. Cleanup. |
mov esi, ecx ; disk*dereference assume that esi points to DISK |
.cleanup_esi: |
test edx, edx ; if there are no media, we didn't reference it |
jz @f |
call disk_media_dereference |
@@: |
call disk_dereference |
; 15. Return. |
ret |
; This is a callback for cleaning up things called from file_system_lfn.found2. |
dyndisk_cleanup: |
mov esi, [edi+8] |
mov edx, [edi+12] |
jmp dyndisk_handler.cleanup_esi |
; This is a callback for enumerating partitions called from |
; file_system_lfn.maindir in the case of inserted media. |
; It just increments eax until DISK.NumPartitions reached and then |
; cleans up. |
fs_dyndisk_next: |
cmp eax, [ecx+DISK.NumPartitions] |
jae .nomore |
inc eax |
clc |
ret |
.nomore: |
pusha |
mov esi, ecx |
call disk_media_dereference |
call disk_dereference |
popa |
stc |
ret |
; This is a callback for enumerating partitions called from |
; file_system_lfn.maindir in the case of missing media. |
; In this case we create one pseudo-partition. |
fs_dyndisk_next_nomedia: |
cmp eax, 1 |
jae .nomore |
inc eax |
clc |
ret |
.nomore: |
pusha |
mov esi, ecx |
call disk_dereference |
popa |
stc |
ret |
; This is a callback for doing real work with selected partition. |
; Currently this is just placeholder, since no file systems are supported. |
; edi = esp -> {dd fs_dyndisk, dd dyndisk_cleanup, dd pointer to DISK, dd media object} |
; ecx = partition number, esi+ebp = ASCIIZ name |
fs_dyndisk: |
dec ecx ; convert to zero-based partition index |
pop edx edx edx eax ; edx = pointer to DISK, eax = NULL or edx |
test eax, eax |
jz .nomedia |
.main: |
cmp ecx, [edx+DISK.NumPartitions] |
jae .notfound |
mov dword [esp+32], ERROR_UNKNOWN_FS |
.cleanup: |
mov esi, edx |
call disk_media_dereference |
call disk_dereference |
ret |
.notfound: |
mov dword [esp+32], ERROR_FILE_NOT_FOUND |
jmp .cleanup |
.nomedia: |
test ecx, ecx |
jnz .notfound |
test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION |
jz .deverror |
; if the driver does not support insert notifications and we are the only fs |
; operation with this disk, issue the fake insert notification; if media is |
; still not inserted, 'disk_media_changed' will detect this and do nothing |
;;; push ebx |
lea ecx, [edx+DISK.MediaLock] |
call mutex_lock |
cmp [edx+DISK.MediaRefCount], 1 |
jnz .noluck |
call mutex_unlock |
push edx |
stdcall disk_media_changed, edx, 1 |
pop edx |
lea ecx, [edx+DISK.MediaLock] |
call mutex_lock |
cmp [edx+DISK.MediaInserted], 0 |
jz .noluck |
lock inc [edx+DISK.MediaRefCount] |
call mutex_unlock |
xor ecx, ecx |
jmp .main |
.noluck: |
call mutex_unlock |
.deverror: |
mov dword [esp+32], ERROR_DEVICE |
mov esi, edx |
call disk_dereference |
ret |
; This function is called from file_system_lfn. |
; This handler is called when virtual root is enumerated |
; and must return all items which can be handled by this. |
; It is called several times, first time with eax=0 |
; in: eax = 0 for first call, previously returned value for subsequent calls |
; out: eax = 0 => no more items |
; eax != 0 => buffer pointed to by edi contains name of item |
dyndisk_enum_root: |
push edx ; save register used in file_system_lfn |
mov ecx, disk_list_mutex ; it will be useful |
; 1. If this is the first call, acquire the mutex and initialize. |
test eax, eax |
jnz .notfirst |
call mutex_lock |
mov eax, disk_list |
.notfirst: |
; 2. Get next item. |
mov eax, [eax+DISK.Next] |
; 3. If there are no more items, go to 6. |
cmp eax, disk_list |
jz .last |
; 4. Copy name from the DISK structure to edi. |
push eax esi |
mov esi, [eax+DISK.Name] |
@@: |
lodsb |
stosb |
test al, al |
jnz @b |
pop esi eax |
; 5. Return with eax = item. |
pop edx ; restore register used in file_system_lfn |
ret |
.last: |
; 6. Release the mutex and return with eax = 0. |
call mutex_unlock |
xor eax, eax |
pop edx ; restore register used in file_system_lfn |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/blkdev/disk_cache.inc |
---|
1,592 → 1,592 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; 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'. |
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
; eax is relative to partition start |
; out: eax = error code; 0 = ok |
fs_read32_sys: |
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, |
; this request should be processed by hd_read. |
cmp [ebp+PARTITION.Disk], 'old' |
jnz @f |
mov [hdd_appl_data], 0 |
call hd_read |
mov [hdd_appl_data], 1 ; restore to default state |
ret |
@@: |
; In the normal case, 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_read32_common |
; 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'. |
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
; eax is relative to partition start |
; out: eax = error code; 0 = ok |
fs_read32_app: |
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, |
; this request should be processed by hd_read. |
cmp [ebp+PARTITION.Disk], 'old' |
jnz @f |
mov [hdd_appl_data], 1 |
jmp hd_read |
@@: |
; In the normal case, 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_read32_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 |
@@: |
; 2. Get the absolute sector on the disk. |
push 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 the 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 al, DISKFUNC.read |
call disk_call_driver |
pop ecx |
pop edx |
pop ecx |
ret |
.scancache: |
; 4. Scan the cache. |
push esi 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_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. |
call mutex_lock |
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 |
test eax, eax |
jnz .read_done |
push 1 |
push esp |
push edx |
push [.sector_lo+12] |
mov ecx, [.cache] |
mov eax, edi |
shl eax, 9 |
add eax, [ecx+DISKCACHE.data] |
push eax |
mov esi, [ebp+PARTITION.Disk] |
mov al, DISKFUNC.read |
call disk_call_driver |
pop ecx |
dec ecx |
jnz .read_done |
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] |
push eax |
call mutex_unlock |
pop eax |
add esp, 12 |
pop edi esi edx ecx |
ret |
; 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 |
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. |
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
; eax is relative to partition start |
; out: eax = error code; 0 = ok |
fs_write32_sys: |
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, |
; this request should be processed by hd_write. |
cmp [ebp+PARTITION.Disk], 'old' |
jnz @f |
mov [hdd_appl_data], 0 |
call hd_write |
mov [hdd_appl_data], 1 ; restore to default state |
ret |
@@: |
; In the normal case, 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 |
; 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 |
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. |
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
; eax is relative to partition start |
; out: eax = error code; 0 = ok |
fs_write32_app: |
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, |
; this request should be processed by hd_write. |
cmp [ebp+PARTITION.Disk], 'old' |
jnz @f |
mov [hdd_appl_data], 1 |
jmp hd_write |
@@: |
; In the normal case, 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 |
; 2. Get the absolute sector on the disk. |
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 al, DISKFUNC.write |
call disk_call_driver |
pop ecx |
pop edx |
pop ecx |
ret |
.scancache: |
; 4. Scan the cache. |
push esi 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 |
mov edi, 1 |
.hdwritecache: |
cmp dword [esi+8], 0 ; if cache slot is empty |
je .not_in_cache_write |
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 |
.not_in_cache_write: |
add esi, 12 |
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+4], 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 |
ret |
; 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: |
;----------------------------------------------------------- |
; find empty or read slot, flush cache if next 12.5% is used by write |
; output : edi = cache slot |
;----------------------------------------------------------- |
.search_again: |
mov ecx, [esi+DISKCACHE.sad_size] |
mov edi, [esi+DISKCACHE.search_start] |
shr ecx, 3 |
.search_for_empty: |
inc edi |
cmp edi, [esi+DISKCACHE.sad_size] |
jbe .inside_cache |
mov edi, 1 |
.inside_cache: |
lea eax, [edi*3] |
shl eax, 2 |
add eax, [esi+DISKCACHE.pointer] |
cmp dword [eax+8], 2 |
jb .found_slot ; it's empty or read |
dec ecx |
jnz .search_for_empty |
call write_cache64 ; no empty slots found, write all |
test eax, eax |
jne .found_slot_access_denied |
jmp .search_again ; and start again |
.found_slot: |
mov [esi+DISKCACHE.search_start], edi |
xor eax, eax ; success |
.found_slot_access_denied: |
ret |
; This function is intended to replace the old 'write_cache' function. |
proc write_cache64 uses ecx edx esi edi |
locals |
cache_chain_started dd ? |
cache_chain_size dd ? |
cache_chain_pos dd ? |
cache_chain_ptr dd ? |
endl |
; 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 |
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 |
add eax, 1 |
adc edx, 0 |
cmp eax, [esi+12] |
jnz @f |
cmp edx, [esi+12+4] |
@@: |
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 |
@@: |
inc [cache_chain_size] |
cmp [cache_chain_size], 16 |
jnz .continue |
jmp .write_chain |
.nonext: |
call .flush_cache_chain |
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, [ebp] |
mov esi, [esi+PARTITION.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 |
@@: |
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-12] |
shl edi, 9 |
add edi, [ecx+DISKCACHE.data] |
mov ecx, [cache_chain_size] |
push ecx |
push esp ; numsectors |
mov eax, [cache_chain_ptr] |
pushd [eax+4] |
pushd [eax] ; startsector |
push edi ; buffer |
mov esi, [ebp] |
mov esi, [esi+PARTITION.Disk] |
mov al, DISKFUNC.write |
call disk_call_driver |
pop ecx |
mov [esp+28], eax |
popa |
retn |
endp |
; This internal function is called from disk_add to initialize the caching for |
; a new DISK. |
; The algorithm is inherited from getcache.inc: take 1/32 part of the available |
; physical memory, round down to 8 pages, limit by 128K from below and by 1M |
; from above. Reserve 1/8 part of the cache for system data and 7/8 for app |
; data. |
; After the size is calculated, but before the cache is allocated, the device |
; driver can adjust the size. In particular, setting size to zero disables |
; caching: there is no sense in a cache for a ramdisk. In fact, such action |
; 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. |
mov eax, [pg_data.pages_free] |
; 1b. 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. |
cmp eax, 1024*1024 |
jb @f |
mov eax, 1024*1024 |
@@: |
cmp eax, 128*1024 |
ja @f |
mov eax, 128*1024 |
@@: |
; 1d. Give a chance to the driver to adjust the size. |
push eax |
mov al, DISKFUNC.adjust_cache_size |
call disk_call_driver |
; Cache size calculated. |
mov [esi+DISK.cache_size], eax |
test eax, eax |
jz .nocache |
; 2. Allocate memory for the cache. |
; 2a. Call the allocator. |
stdcall kernel_alloc, eax |
test eax, eax |
jnz @f |
; 2b. If it failed, say a message and return with eax = 0. |
dbgstr 'no memory for disk cache' |
jmp .nothing |
@@: |
; 3. Fill two DISKCACHE structures. |
mov [esi+DISK.SysCache.pointer], eax |
lea ecx, [esi+DISK.SysCache.Lock] |
call mutex_init |
lea ecx, [esi+DISK.AppCache.Lock] |
call mutex_init |
; The following code is inherited from getcache.inc. |
mov edx, [esi+DISK.SysCache.pointer] |
and [esi+DISK.SysCache.search_start], 0 |
and [esi+DISK.AppCache.search_start], 0 |
mov eax, [esi+DISK.cache_size] |
shr eax, 3 |
mov [esi+DISK.SysCache.data_size], eax |
add edx, eax |
imul eax, 7 |
mov [esi+DISK.AppCache.data_size], eax |
mov [esi+DISK.AppCache.pointer], edx |
mov eax, [esi+DISK.SysCache.data_size] |
push ebx |
call calculate_for_hd |
pop ebx |
add eax, [esi+DISK.SysCache.pointer] |
mov [esi+DISK.SysCache.data], eax |
mov [esi+DISK.SysCache.sad_size], ecx |
push edi |
mov edi, [esi+DISK.SysCache.pointer] |
lea ecx, [ecx*3] |
xor eax, eax |
rep stosd |
pop edi |
mov eax, [esi+DISK.AppCache.data_size] |
push ebx |
call calculate_for_hd |
pop ebx |
add eax, [esi+DISK.AppCache.pointer] |
mov [esi+DISK.AppCache.data], eax |
mov [esi+DISK.AppCache.sad_size], ecx |
push edi |
mov edi, [esi+DISK.AppCache.pointer] |
lea ecx, [ecx*3] |
xor eax, eax |
rep stosd |
pop edi |
; 4. Return with nonzero al. |
mov al, 1 |
; 5. Return. |
.nothing: |
ret |
; No caching is required for this driver. Zero cache pointers and return with |
; nonzero al. |
.nocache: |
mov [esi+DISK.SysCache.pointer], eax |
mov [esi+DISK.AppCache.pointer], eax |
mov al, 1 |
ret |
; This internal function is called from disk_media_dereference to free the |
; allocated cache, if there is one. |
; esi = pointer to DISK structure |
disk_free_cache: |
; The algorithm is straightforward. |
mov eax, [esi+DISK.SysCache.pointer] |
test eax, eax |
jz .nothing |
stdcall kernel_free, eax |
.nothing: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; 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'. |
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
; eax is relative to partition start |
; out: eax = error code; 0 = ok |
fs_read32_sys: |
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, |
; this request should be processed by hd_read. |
cmp [ebp+PARTITION.Disk], 'old' |
jnz @f |
mov [hdd_appl_data], 0 |
call hd_read |
mov [hdd_appl_data], 1 ; restore to default state |
ret |
@@: |
; In the normal case, 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_read32_common |
; 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'. |
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
; eax is relative to partition start |
; out: eax = error code; 0 = ok |
fs_read32_app: |
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, |
; this request should be processed by hd_read. |
cmp [ebp+PARTITION.Disk], 'old' |
jnz @f |
mov [hdd_appl_data], 1 |
jmp hd_read |
@@: |
; In the normal case, 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_read32_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 |
@@: |
; 2. Get the absolute sector on the disk. |
push 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 the 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 al, DISKFUNC.read |
call disk_call_driver |
pop ecx |
pop edx |
pop ecx |
ret |
.scancache: |
; 4. Scan the cache. |
push esi 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_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. |
call mutex_lock |
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 |
test eax, eax |
jnz .read_done |
push 1 |
push esp |
push edx |
push [.sector_lo+12] |
mov ecx, [.cache] |
mov eax, edi |
shl eax, 9 |
add eax, [ecx+DISKCACHE.data] |
push eax |
mov esi, [ebp+PARTITION.Disk] |
mov al, DISKFUNC.read |
call disk_call_driver |
pop ecx |
dec ecx |
jnz .read_done |
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] |
push eax |
call mutex_unlock |
pop eax |
add esp, 12 |
pop edi esi edx ecx |
ret |
; 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 |
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. |
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
; eax is relative to partition start |
; out: eax = error code; 0 = ok |
fs_write32_sys: |
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, |
; this request should be processed by hd_write. |
cmp [ebp+PARTITION.Disk], 'old' |
jnz @f |
mov [hdd_appl_data], 0 |
call hd_write |
mov [hdd_appl_data], 1 ; restore to default state |
ret |
@@: |
; In the normal case, 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 |
; 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 |
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. |
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
; eax is relative to partition start |
; out: eax = error code; 0 = ok |
fs_write32_app: |
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, |
; this request should be processed by hd_write. |
cmp [ebp+PARTITION.Disk], 'old' |
jnz @f |
mov [hdd_appl_data], 1 |
jmp hd_write |
@@: |
; In the normal case, 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 |
; 2. Get the absolute sector on the disk. |
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 al, DISKFUNC.write |
call disk_call_driver |
pop ecx |
pop edx |
pop ecx |
ret |
.scancache: |
; 4. Scan the cache. |
push esi 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 |
mov edi, 1 |
.hdwritecache: |
cmp dword [esi+8], 0 ; if cache slot is empty |
je .not_in_cache_write |
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 |
.not_in_cache_write: |
add esi, 12 |
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+4], 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 |
ret |
; 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: |
;----------------------------------------------------------- |
; find empty or read slot, flush cache if next 12.5% is used by write |
; output : edi = cache slot |
;----------------------------------------------------------- |
.search_again: |
mov ecx, [esi+DISKCACHE.sad_size] |
mov edi, [esi+DISKCACHE.search_start] |
shr ecx, 3 |
.search_for_empty: |
inc edi |
cmp edi, [esi+DISKCACHE.sad_size] |
jbe .inside_cache |
mov edi, 1 |
.inside_cache: |
lea eax, [edi*3] |
shl eax, 2 |
add eax, [esi+DISKCACHE.pointer] |
cmp dword [eax+8], 2 |
jb .found_slot ; it's empty or read |
dec ecx |
jnz .search_for_empty |
call write_cache64 ; no empty slots found, write all |
test eax, eax |
jne .found_slot_access_denied |
jmp .search_again ; and start again |
.found_slot: |
mov [esi+DISKCACHE.search_start], edi |
xor eax, eax ; success |
.found_slot_access_denied: |
ret |
; This function is intended to replace the old 'write_cache' function. |
proc write_cache64 uses ecx edx esi edi |
locals |
cache_chain_started dd ? |
cache_chain_size dd ? |
cache_chain_pos dd ? |
cache_chain_ptr dd ? |
endl |
; 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 |
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 |
add eax, 1 |
adc edx, 0 |
cmp eax, [esi+12] |
jnz @f |
cmp edx, [esi+12+4] |
@@: |
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 |
@@: |
inc [cache_chain_size] |
cmp [cache_chain_size], 16 |
jnz .continue |
jmp .write_chain |
.nonext: |
call .flush_cache_chain |
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, [ebp] |
mov esi, [esi+PARTITION.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 |
@@: |
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-12] |
shl edi, 9 |
add edi, [ecx+DISKCACHE.data] |
mov ecx, [cache_chain_size] |
push ecx |
push esp ; numsectors |
mov eax, [cache_chain_ptr] |
pushd [eax+4] |
pushd [eax] ; startsector |
push edi ; buffer |
mov esi, [ebp] |
mov esi, [esi+PARTITION.Disk] |
mov al, DISKFUNC.write |
call disk_call_driver |
pop ecx |
mov [esp+28], eax |
popa |
retn |
endp |
; This internal function is called from disk_add to initialize the caching for |
; a new DISK. |
; The algorithm is inherited from getcache.inc: take 1/32 part of the available |
; physical memory, round down to 8 pages, limit by 128K from below and by 1M |
; from above. Reserve 1/8 part of the cache for system data and 7/8 for app |
; data. |
; After the size is calculated, but before the cache is allocated, the device |
; driver can adjust the size. In particular, setting size to zero disables |
; caching: there is no sense in a cache for a ramdisk. In fact, such action |
; 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. |
mov eax, [pg_data.pages_free] |
; 1b. 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. |
cmp eax, 1024*1024 |
jb @f |
mov eax, 1024*1024 |
@@: |
cmp eax, 128*1024 |
ja @f |
mov eax, 128*1024 |
@@: |
; 1d. Give a chance to the driver to adjust the size. |
push eax |
mov al, DISKFUNC.adjust_cache_size |
call disk_call_driver |
; Cache size calculated. |
mov [esi+DISK.cache_size], eax |
test eax, eax |
jz .nocache |
; 2. Allocate memory for the cache. |
; 2a. Call the allocator. |
stdcall kernel_alloc, eax |
test eax, eax |
jnz @f |
; 2b. If it failed, say a message and return with eax = 0. |
dbgstr 'no memory for disk cache' |
jmp .nothing |
@@: |
; 3. Fill two DISKCACHE structures. |
mov [esi+DISK.SysCache.pointer], eax |
lea ecx, [esi+DISK.SysCache.Lock] |
call mutex_init |
lea ecx, [esi+DISK.AppCache.Lock] |
call mutex_init |
; The following code is inherited from getcache.inc. |
mov edx, [esi+DISK.SysCache.pointer] |
and [esi+DISK.SysCache.search_start], 0 |
and [esi+DISK.AppCache.search_start], 0 |
mov eax, [esi+DISK.cache_size] |
shr eax, 3 |
mov [esi+DISK.SysCache.data_size], eax |
add edx, eax |
imul eax, 7 |
mov [esi+DISK.AppCache.data_size], eax |
mov [esi+DISK.AppCache.pointer], edx |
mov eax, [esi+DISK.SysCache.data_size] |
push ebx |
call calculate_for_hd |
pop ebx |
add eax, [esi+DISK.SysCache.pointer] |
mov [esi+DISK.SysCache.data], eax |
mov [esi+DISK.SysCache.sad_size], ecx |
push edi |
mov edi, [esi+DISK.SysCache.pointer] |
lea ecx, [ecx*3] |
xor eax, eax |
rep stosd |
pop edi |
mov eax, [esi+DISK.AppCache.data_size] |
push ebx |
call calculate_for_hd |
pop ebx |
add eax, [esi+DISK.AppCache.pointer] |
mov [esi+DISK.AppCache.data], eax |
mov [esi+DISK.AppCache.sad_size], ecx |
push edi |
mov edi, [esi+DISK.AppCache.pointer] |
lea ecx, [ecx*3] |
xor eax, eax |
rep stosd |
pop edi |
; 4. Return with nonzero al. |
mov al, 1 |
; 5. Return. |
.nothing: |
ret |
; No caching is required for this driver. Zero cache pointers and return with |
; nonzero al. |
.nocache: |
mov [esi+DISK.SysCache.pointer], eax |
mov [esi+DISK.AppCache.pointer], eax |
mov al, 1 |
ret |
; This internal function is called from disk_media_dereference to free the |
; allocated cache, if there is one. |
; esi = pointer to DISK structure |
disk_free_cache: |
; The algorithm is straightforward. |
mov eax, [esi+DISK.SysCache.pointer] |
test eax, eax |
jz .nothing |
stdcall kernel_free, eax |
.nothing: |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/blkdev/fdc.inc |
---|
1,71 → 1,71 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
;function pointers. |
fdc_irq_func dd fdc_null |
endg |
uglobal |
dmasize db 0x0 |
dmamode db 0x0 |
endg |
fdc_init: ;start with clean tracks. |
mov edi,OS_BASE+0xD201 |
mov al,0 |
mov ecx,160 |
rep stosb |
ret |
fdc_irq: |
call [fdc_irq_func] |
fdc_null: |
ret |
save_image: |
call reserve_flp |
call restorefatchain |
pusha |
call check_label |
cmp [FDC_Status],0 |
jne unnecessary_save_image |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],0 ; Ñòîðîíà |
mov [FDD_Sector],1 ; Ñåêòîð |
mov esi,RAMDISK |
call SeekTrack |
save_image_1: |
push esi |
call take_data_from_application_1 |
pop esi |
add esi,512 |
call WriteSectWithRetr |
; call WriteSector |
cmp [FDC_Status],0 |
jne unnecessary_save_image |
inc [FDD_Sector] |
cmp [FDD_Sector],19 |
jne save_image_1 |
mov [FDD_Sector],1 |
inc [FDD_Head] |
cmp [FDD_Head],2 |
jne save_image_1 |
mov [FDD_Head],0 |
inc [FDD_Track] |
call SeekTrack |
cmp [FDD_Track],80 |
jne save_image_1 |
unnecessary_save_image: |
mov [fdc_irq_func],fdc_null |
popa |
mov [flp_status],0 |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
;function pointers. |
fdc_irq_func dd fdc_null |
endg |
uglobal |
dmasize db 0x0 |
dmamode db 0x0 |
endg |
fdc_init: ;start with clean tracks. |
mov edi, OS_BASE+0xD201 |
mov al, 0 |
mov ecx, 160 |
rep stosb |
ret |
fdc_irq: |
call [fdc_irq_func] |
fdc_null: |
ret |
save_image: |
call reserve_flp |
call restorefatchain |
pusha |
call check_label |
cmp [FDC_Status], 0 |
jne unnecessary_save_image |
mov [FDD_Track], 0; Öèëèíäð |
mov [FDD_Head], 0; Ñòîðîíà |
mov [FDD_Sector], 1; Ñåêòîð |
mov esi, RAMDISK |
call SeekTrack |
save_image_1: |
push esi |
call take_data_from_application_1 |
pop esi |
add esi, 512 |
call WriteSectWithRetr |
; call WriteSector |
cmp [FDC_Status], 0 |
jne unnecessary_save_image |
inc [FDD_Sector] |
cmp [FDD_Sector], 19 |
jne save_image_1 |
mov [FDD_Sector], 1 |
inc [FDD_Head] |
cmp [FDD_Head], 2 |
jne save_image_1 |
mov [FDD_Head], 0 |
inc [FDD_Track] |
call SeekTrack |
cmp [FDD_Track], 80 |
jne save_image_1 |
unnecessary_save_image: |
mov [fdc_irq_func], fdc_null |
popa |
mov [flp_status], 0 |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/blkdev/flp_drv.inc |
---|
1,626 → 1,630 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;********************************************************** |
; Íåïîñðåäñòâåííàÿ ðàáîòà ñ êîíòðîëëåðîì ãèáêîãî äèñêà |
;********************************************************** |
; Àâòîð èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷. |
; Àäàïòàöèÿ è äîðàáîòêà Mario79 |
;give_back_application_data: ; ïåðåñëàòü ïðèëîæåíèþ |
; mov edi,[TASK_BASE] |
; mov edi,[edi+TASKDATA.mem_start] |
; add edi,ecx |
give_back_application_data_1: |
mov esi,FDD_BUFF ;FDD_DataBuffer ;0x40000 |
xor ecx,ecx |
mov cx,128 |
cld |
rep movsd |
ret |
;take_data_from_application: ; âçÿòü èç ïðèëîæåíè |
; mov esi,[TASK_BASE] |
; mov esi,[esi+TASKDATA.mem_start] |
; add esi,ecx |
take_data_from_application_1: |
mov edi,FDD_BUFF ;FDD_DataBuffer ;0x40000 |
xor ecx,ecx |
mov cx,128 |
cld |
rep movsd |
ret |
; Êîäû çàâåðøåíèÿ îïåðàöèè ñ êîíòðîëëåðîì (FDC_Status) |
FDC_Normal equ 0 ;íîðìàëüíîå çàâåðøåíèå |
FDC_TimeOut equ 1 ;îøèáêà òàéì-àóòà |
FDC_DiskNotFound equ 2 ;â äèñêîâîäå íåò äèñêà |
FDC_TrackNotFound equ 3 ;äîðîæêà íå íàéäåíà |
FDC_SectorNotFound equ 4 ;ñåêòîð íå íàéäåí |
; Ìàêñèìàëüíûå çíà÷åíèÿ êîîðäèíàò ñåêòîðà (çàäàííûå |
; çíà÷åíèÿ ñîîòâåòñòâóþò ïàðàìåòðàì ñòàíäàðòíîãî |
; òðåõäþéìîâîãî ãèáêîãî äèñêà îáúåìîì 1,44 Ìá) |
MAX_Track equ 79 |
MAX_Head equ 1 |
MAX_Sector equ 18 |
uglobal |
; Ñ÷åò÷èê òèêîâ òàéìåðà |
TickCounter dd ? |
; Êîä çàâåðøåíèÿ îïåðàöèè ñ êîíòðîëëåðîì ÍÃÌÄ |
FDC_Status DB ? |
; Ôëàã ïðåðûâàíèÿ îò ÍÃÌÄ |
FDD_IntFlag DB ? |
; Ìîìåíò íà÷àëà ïîñëåäíåé îïåðàöèè ñ ÍÃÌÄ |
FDD_Time DD ? |
; Íîìåð äèñêîâîäà |
FDD_Type db 0 |
; Êîîðäèíàòû ñåêòîðà |
FDD_Track DB ? |
FDD_Head DB ? |
FDD_Sector DB ? |
; Áëîê ðåçóëüòàòà îïåðàöèè |
FDC_ST0 DB ? |
FDC_ST1 DB ? |
FDC_ST2 DB ? |
FDC_C DB ? |
FDC_H DB ? |
FDC_R DB ? |
FDC_N DB ? |
; Ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè |
ReadRepCounter DB ? |
; Ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè |
RecalRepCounter DB ? |
endg |
; Îáëàñòü ïàìÿòè äëÿ õðàíåíèÿ ïðî÷èòàííîãî ñåêòîðà |
;FDD_DataBuffer: times 512 db 0 ;DB 512 DUP (?) |
fdd_motor_status db 0 |
timer_fdd_motor dd 0 |
;************************************* |
;* ÈÍÈÖÈÀËÈÇÀÖÈß ÐÅÆÈÌÀ ÏÄÏ ÄËß ÍÃÌÄ * |
;************************************* |
Init_FDC_DMA: |
pushad |
mov al,0 |
out 0x0c,al ; reset the flip-flop to a known state. |
mov al,6 ; mask channel 2 so we can reprogram it. |
out 0x0a,al |
mov al,[dmamode] ; 0x46 -> Read from floppy - 0x4A Write to floppy |
out 0x0b,al |
mov al,0 |
out 0x0c,al ; reset the flip-flop to a known state. |
mov eax,0xD000 |
out 0x04,al ; set the channel 2 starting address to 0 |
shr eax,8 |
out 0x04,al |
shr eax,8 |
out 0x81,al |
mov al,0 |
out 0x0c, al ; reset flip-flop |
mov al, 0xff ;set count (actual size -1) |
out 0x5, al |
mov al,0x1 ;[dmasize] ;(0x1ff = 511 / 0x23ff =9215) |
out 0x5,al |
mov al,2 |
out 0xa,al |
popad |
ret |
;*********************************** |
;* ÇÀÏÈÑÀÒÜ ÁÀÉÒ Â ÏÎÐÒ ÄÀÍÍÛÕ FDC * |
;* Ïàðàìåòðû: * |
;* AL - âûâîäèìûé áàéò. * |
;*********************************** |
FDCDataOutput: |
; pusha |
push eax ecx edx |
mov AH,AL ;çàïîìíèòü áàéò â AH |
; Ñáðîñèòü ïåðåìåííóþ ñîñòîÿíèÿ êîíòðîëëåðà |
mov [FDC_Status],FDC_Normal |
; Ïðîâåðèòü ãîòîâíîñòü êîíòðîëëåðà ê ïðèåìó äàííûõ |
mov DX,3F4h ;(ïîðò ñîñòîÿíèÿ FDC) |
mov ecx, 0x10000 ;óñòàíîâèòü ñ÷åò÷èê òàéì-àóòà |
@@TestRS: |
in AL,DX ;ïðî÷èòàòü ðåãèñòð RS |
and AL,0C0h ;âûäåëèòü ðàçðÿäû 6 è 7 |
cmp AL,80h ;ïðîâåðèòü ðàçðÿäû 6 è 7 |
je @@OutByteToFDC |
loop @@TestRS |
; Îøèáêà òàéì-àóòà |
mov [FDC_Status],FDC_TimeOut |
jmp @@End_5 |
; Âûâåñòè áàéò â ïîðò äàííûõ |
@@OutByteToFDC: |
inc DX |
mov AL,AH |
out DX,AL |
@@End_5: |
; popa |
pop edx ecx eax |
ret |
;****************************************** |
;* ÏÐÎ×ÈÒÀÒÜ ÁÀÉÒ ÈÇ ÏÎÐÒÀ ÄÀÍÍÛÕ FDC * |
;* Ïðîöåäóðà íå èìååò âõîäíûõ ïàðàìåòðîâ. * |
;* Âûõîäíûå äàííûå: * |
;* AL - ñ÷èòàííûé áàéò. * |
;****************************************** |
FDCDataInput: |
push ECX |
push DX |
; Ñáðîñèòü ïåðåìåííóþ ñîñòîÿíèÿ êîíòðîëëåðà |
mov [FDC_Status],FDC_Normal |
; Ïðîâåðèòü ãîòîâíîñòü êîíòðîëëåðà ê ïåðåäà÷å äàííûõ |
mov DX,3F4h ;(ïîðò ñîñòîÿíèÿ FDC) |
xor CX,CX ;óñòàíîâèòü ñ÷åò÷èê òàéì-àóòà |
@@TestRS_1: |
in AL,DX ;ïðî÷èòàòü ðåãèñòð RS |
and AL,0C0h ;âûäëèòü ðàçðÿäû 6 è 7 |
cmp AL,0C0h ;ïðîâåðèòü ðàçðÿäû 6 è 7 |
je @@GetByteFromFDC |
loop @@TestRS_1 |
; Îøèáêà òàéì-àóòà |
mov [FDC_Status],FDC_TimeOut |
jmp @@End_6 |
; Ââåñòè áàéò èç ïîðòà äàííûõ |
@@GetByteFromFDC: |
inc DX |
in AL,DX |
@@End_6: pop DX |
pop ECX |
ret |
;********************************************* |
;* ÎÁÐÀÁÎÒ×ÈÊ ÏÐÅÐÛÂÀÍÈß ÎÒ ÊÎÍÒÐÎËËÅÐÀ ÍÃÌÄ * |
;********************************************* |
FDCInterrupt: |
; Óñòàíîâèòü ôëàã ïðåðûâàíè |
mov [FDD_IntFlag],1 |
ret |
;****************************************** |
;* ÓÑÒÀÍÎÂÈÒÜ ÍÎÂÛÉ ÎÁÐÀÁÎÒ×ÈÊ ÏÐÅÐÛÂÀÍÈÉ * |
;* ÍÃÌÄ * |
;****************************************** |
SetUserInterrupts: |
mov [fdc_irq_func],FDCInterrupt |
ret |
;******************************************* |
;* ÎÆÈÄÀÍÈÅ ÏÐÅÐÛÂÀÍÈß ÎÒ ÊÎÍÒÐÎËËÅÐÀ ÍÃÌÄ * |
;******************************************* |
WaitFDCInterrupt: |
pusha |
; Ñáðîñèòü áàéò ñîñòîÿíèÿ îïåðàöèè |
mov [FDC_Status],FDC_Normal |
; Ñáðîñèòü ôëàã ïðåðûâàíè |
mov [FDD_IntFlag],0 |
; Îáíóëèòü ñ÷åò÷èê òèêîâ |
mov eax,[timer_ticks] |
mov [TickCounter],eax |
; Îæèäàòü óñòàíîâêè ôëàãà ïðåðûâàíèÿ ÍÃÌÄ |
@@TestRS_2: |
cmp [FDD_IntFlag],0 |
jnz @@End_7 ;ïðåðûâàíèå ïðîèçîøëî |
call change_task |
mov eax,[timer_ticks] |
sub eax,[TickCounter] |
cmp eax,50 ;25 ;5 ;îæèäàòü 5 òèêîâ |
jb @@TestRS_2 |
; jl @@TestRS_2 |
; Îøèáêà òàéì-àóòà |
mov [FDC_Status],FDC_TimeOut |
; mov [flp_status],0 |
@@End_7: popa |
ret |
;********************************* |
;* ÂÊËÞ×ÈÒÜ ÌÎÒÎÐ ÄÈÑÊÎÂÎÄÀ "A:" * |
;********************************* |
FDDMotorON: |
pusha |
; cmp [fdd_motor_status],1 |
; je fdd_motor_on |
mov al,[flp_number] |
cmp [fdd_motor_status],al |
je fdd_motor_on |
; Ïðîèçâåñòè ñáðîñ êîíòðîëëåðà ÍÃÌÄ |
mov DX,3F2h ;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè |
mov AL,0 |
out DX,AL |
; Âûáðàòü è âêëþ÷èòü ìîòîð äèñêîâîäà |
cmp [flp_number],1 |
jne FDDMotorON_B |
; call FDDMotorOFF_B |
mov AL,1Ch ; Floppy A |
jmp FDDMotorON_1 |
FDDMotorON_B: |
; call FDDMotorOFF_A |
mov AL,2Dh ; Floppy B |
FDDMotorON_1: |
out DX,AL |
; Îáíóëèòü ñ÷åò÷èê òèêîâ |
mov eax,[timer_ticks] |
mov [TickCounter],eax |
; Îæèäàòü 0,5 ñ |
@@dT: |
call change_task |
mov eax,[timer_ticks] |
sub eax,[TickCounter] |
cmp eax,50 ;10 |
jb @@dT |
cmp [flp_number],1 |
jne fdd_motor_on_B |
mov [fdd_motor_status],1 |
jmp fdd_motor_on |
fdd_motor_on_B: |
mov [fdd_motor_status],2 |
fdd_motor_on: |
call save_timer_fdd_motor |
popa |
ret |
;***************************************** |
;* ÑÎÕÐÀÍÅÍÈÅ ÓÊÀÇÀÒÅËß ÂÐÅÌÅÍÈ * |
;***************************************** |
save_timer_fdd_motor: |
mov eax,[timer_ticks] |
mov [timer_fdd_motor],eax |
ret |
;***************************************** |
;* ÏÐÎÂÅÐÊÀ ÇÀÄÅÐÆÊÈ ÂÛÊËÞ×ÅÍÈß ÌÎÒÎÐÀ * |
;***************************************** |
align 4 |
check_fdd_motor_status: |
cmp [fdd_motor_status],0 |
je end_check_fdd_motor_status_1 |
mov eax,[timer_ticks] |
sub eax,[timer_fdd_motor] |
cmp eax,500 |
jb end_check_fdd_motor_status |
call FDDMotorOFF |
mov [fdd_motor_status],0 |
end_check_fdd_motor_status_1: |
mov [flp_status],0 |
end_check_fdd_motor_status: |
ret |
;********************************** |
;* ÂÛÊËÞ×ÈÒÜ ÌÎÒÎÐ ÄÈÑÊÎÂÎÄÀ * |
;********************************** |
FDDMotorOFF: |
push AX |
push DX |
cmp [flp_number],1 |
jne FDDMotorOFF_1 |
call FDDMotorOFF_A |
jmp FDDMotorOFF_2 |
FDDMotorOFF_1: |
call FDDMotorOFF_B |
FDDMotorOFF_2: |
pop DX |
pop AX |
; ñáðîñ ôëàãîâ êåøèðîâàíèÿ â ñâÿçè ñ óñòàðåâàíèåì èíôîðìàöèè |
mov [root_read],0 |
mov [flp_fat],0 |
ret |
FDDMotorOFF_A: |
mov DX,3F2h ;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè |
mov AL,0Ch ; Floppy A |
out DX,AL |
ret |
FDDMotorOFF_B: |
mov DX,3F2h ;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè |
mov AL,5h ; Floppy B |
out DX,AL |
ret |
;******************************* |
;* ÐÅÊÀËÈÁÐÎÂÊÀ ÄÈÑÊÎÂÎÄÀ "A:" * |
;******************************* |
RecalibrateFDD: |
pusha |
call save_timer_fdd_motor |
; Ïîäàòü êîìàíäó "Ðåêàëèáðîâêà" |
mov AL,07h |
call FDCDataOutput |
mov AL,00h |
call FDCDataOutput |
; Îæèäàòü çàâåðøåíèÿ îïåðàöèè |
call WaitFDCInterrupt |
; cmp [FDC_Status],0 |
; je no_fdc_status_error |
; mov [flp_status],0 |
;no_fdc_status_error: |
call save_timer_fdd_motor |
popa |
ret |
;***************************************************** |
;* ÏÎÈÑÊ ÄÎÐÎÆÊÈ * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;***************************************************** |
SeekTrack: |
pusha |
call save_timer_fdd_motor |
; Ïîäàòü êîìàíäó "Ïîèñê" |
mov AL,0Fh |
call FDCDataOutput |
; Ïåðåäàòü áàéò íîìåðà ãîëîâêè/íàêîïèòåë |
mov AL,[FDD_Head] |
shl AL,2 |
call FDCDataOutput |
; Ïåðåäàòü áàéò íîìåðà äîðîæêè |
mov AL,[FDD_Track] |
call FDCDataOutput |
; Îæèäàòü çàâåðøåíèÿ îïåðàöèè |
call WaitFDCInterrupt |
cmp [FDC_Status],FDC_Normal |
jne @@Exit |
; Ñîõðàíèòü ðåçóëüòàò ïîèñêà |
mov AL,08h |
call FDCDataOutput |
call FDCDataInput |
mov [FDC_ST0],AL |
call FDCDataInput |
mov [FDC_C],AL |
; Ïðîâåðèòü ðåçóëüòàò ïîèñêà |
; Ïîèñê çàâåðøåí? |
test [FDC_ST0],100000b |
je @@Err |
; Çàäàííûé òðåê íàéäåí? |
mov AL,[FDC_C] |
cmp AL,[FDD_Track] |
jne @@Err |
; Íîìåð ãîëîâêè ñîâïàäàåò ñ çàäàííûì? |
mov AL,[FDC_ST0] |
and AL,100b |
shr AL,2 |
cmp AL,[FDD_Head] |
jne @@Err |
; Îïåðàöèÿ çàâåðøåíà óñïåøíî |
mov [FDC_Status],FDC_Normal |
jmp @@Exit |
@@Err: ; Òðåê íå íàéäåí |
mov [FDC_Status],FDC_TrackNotFound |
; mov [flp_status],0 |
@@Exit: |
call save_timer_fdd_motor |
popa |
ret |
;******************************************************* |
;* ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1); * |
;* FDD_Sector - íîìåð ñåêòîðà (1-18). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè ÷òåíèÿ * |
;* ñîäåðæèìîå ñåêòîðà áóäåò çàíåñåíî â FDD_DataBuffer. * |
;******************************************************* |
ReadSector: |
pushad |
call save_timer_fdd_motor |
; Óñòàíîâèòü ñêîðîñòü ïåðåäà÷è 500 Êáàéò/ñ |
mov AX,0 |
mov DX,03F7h |
out DX,AL |
; Èíèöèàëèçèðîâàòü êàíàë ïðÿìîãî äîñòóïà ê ïàìÿòè |
mov [dmamode],0x46 |
call Init_FDC_DMA |
; Ïîäàòü êîìàíäó "×òåíèå äàííûõ" |
mov AL,0E6h ;÷òåíèå â ìóëüòèòðåêîâîì ðåæèìå |
call FDCDataOutput |
mov AL,[FDD_Head] |
shl AL,2 |
call FDCDataOutput |
mov AL,[FDD_Track] |
call FDCDataOutput |
mov AL,[FDD_Head] |
call FDCDataOutput |
mov AL,[FDD_Sector] |
call FDCDataOutput |
mov AL,2 ;êîä ðàçìåðà ñåêòîðà (512 áàéò) |
call FDCDataOutput |
mov AL,18 ;+1; 3Fh ;÷èñëî ñåêòîðîâ íà äîðîæêå |
call FDCDataOutput |
mov AL,1Bh ;çíà÷åíèå GPL |
call FDCDataOutput |
mov AL,0FFh ;çíà÷åíèå DTL |
call FDCDataOutput |
; Îæèäàåì ïðåðûâàíèå ïî çàâåðøåíèè îïåðàöèè |
call WaitFDCInterrupt |
cmp [FDC_Status],FDC_Normal |
jne @@Exit_1 |
; Ñ÷èòûâàåì ñòàòóñ çàâåðøåíèÿ îïåðàöèè |
call GetStatusInfo |
test [FDC_ST0],11011000b |
jnz @@Err_1 |
mov [FDC_Status],FDC_Normal |
jmp @@Exit_1 |
@@Err_1: mov [FDC_Status],FDC_SectorNotFound |
; mov [flp_status],0 |
@@Exit_1: |
call save_timer_fdd_motor |
popad |
ret |
;******************************************************* |
;* ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ (Ñ ÏÎÂÒÎÐÅÍÈÅÌ ÎÏÅÐÀÖÈÈ ÏÐÈ ÑÁÎÅ) * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1); * |
;* FDD_Sector - íîìåð ñåêòîðà (1-18). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè ÷òåíèÿ * |
;* ñîäåðæèìîå ñåêòîðà áóäåò çàíåñåíî â FDD_DataBuffer. * |
;******************************************************* |
ReadSectWithRetr: |
pusha |
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè |
mov [RecalRepCounter],0 |
@@TryAgain: |
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè |
mov [ReadRepCounter],0 |
@@ReadSector_1: |
call ReadSector |
cmp [FDC_Status],0 |
je @@Exit_2 |
cmp [FDC_Status],1 |
je @@Err_3 |
; Òðîåêðàòíîå ïîâòîðåíèå ÷òåíè |
inc [ReadRepCounter] |
cmp [ReadRepCounter],3 |
jb @@ReadSector_1 |
; Òðîåêðàòíîå ïîâòîðåíèå ðåêàëèáðîâêè |
call RecalibrateFDD |
call SeekTrack |
inc [RecalRepCounter] |
cmp [RecalRepCounter],3 |
jb @@TryAgain |
; mov [flp_status],0 |
@@Exit_2: |
popa |
ret |
@@Err_3: |
mov [flp_status],0 |
popa |
ret |
;******************************************************* |
;* ÇÀÏÈÑÜ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1); * |
;* FDD_Sector - íîìåð ñåêòîðà (1-18). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè çàïèñè * |
;* ñîäåðæèìîå FDD_DataBuffer áóäåò çàíåñåíî â ñåêòîð. * |
;******************************************************* |
WriteSector: |
pushad |
call save_timer_fdd_motor |
; Óñòàíîâèòü ñêîðîñòü ïåðåäà÷è 500 Êáàéò/ñ |
mov AX,0 |
mov DX,03F7h |
out DX,AL |
; Èíèöèàëèçèðîâàòü êàíàë ïðÿìîãî äîñòóïà ê ïàìÿòè |
mov [dmamode],0x4A |
call Init_FDC_DMA |
; Ïîäàòü êîìàíäó "Çàïèñü äàííûõ" |
mov AL,0xC5 ;0x45 ;çàïèñü â ìóëüòèòðåêîâîì ðåæèìå |
call FDCDataOutput |
mov AL,[FDD_Head] |
shl AL,2 |
call FDCDataOutput |
mov AL,[FDD_Track] |
call FDCDataOutput |
mov AL,[FDD_Head] |
call FDCDataOutput |
mov AL,[FDD_Sector] |
call FDCDataOutput |
mov AL,2 ;êîä ðàçìåðà ñåêòîðà (512 áàéò) |
call FDCDataOutput |
mov AL,18; 3Fh ;÷èñëî ñåêòîðîâ íà äîðîæêå |
call FDCDataOutput |
mov AL,1Bh ;çíà÷åíèå GPL |
call FDCDataOutput |
mov AL,0FFh ;çíà÷åíèå DTL |
call FDCDataOutput |
; Îæèäàåì ïðåðûâàíèå ïî çàâåðøåíèè îïåðàöèè |
call WaitFDCInterrupt |
cmp [FDC_Status],FDC_Normal |
jne @@Exit_3 |
; Ñ÷èòûâàåì ñòàòóñ çàâåðøåíèÿ îïåðàöèè |
call GetStatusInfo |
test [FDC_ST0],11000000b ;11011000b |
jnz @@Err_2 |
mov [FDC_Status],FDC_Normal |
jmp @@Exit_3 |
@@Err_2: mov [FDC_Status],FDC_SectorNotFound |
@@Exit_3: |
call save_timer_fdd_motor |
popad |
ret |
;******************************************************* |
;* ÇÀÏÈÑÜ ÑÅÊÒÎÐÀ (Ñ ÏÎÂÒÎÐÅÍÈÅÌ ÎÏÅÐÀÖÈÈ ÏÐÈ ÑÁÎÅ) * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1); * |
;* FDD_Sector - íîìåð ñåêòîðà (1-18). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè çàïèñè * |
;* ñîäåðæèìîå FDD_DataBuffer áóäåò çàíåñåíî â ñåêòîð. * |
;******************************************************* |
WriteSectWithRetr: |
pusha |
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè |
mov [RecalRepCounter],0 |
@@TryAgain_1: |
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè |
mov [ReadRepCounter],0 |
@@WriteSector_1: |
call WriteSector |
cmp [FDC_Status],0 |
je @@Exit_4 |
cmp [FDC_Status],1 |
je @@Err_4 |
; Òðîåêðàòíîå ïîâòîðåíèå ÷òåíè |
inc [ReadRepCounter] |
cmp [ReadRepCounter],3 |
jb @@WriteSector_1 |
; Òðîåêðàòíîå ïîâòîðåíèå ðåêàëèáðîâêè |
call RecalibrateFDD |
call SeekTrack |
inc [RecalRepCounter] |
cmp [RecalRepCounter],3 |
jb @@TryAgain_1 |
@@Exit_4: |
popa |
ret |
@@Err_4: |
mov [flp_status],0 |
popa |
ret |
;********************************************* |
;* ÏÎËÓ×ÈÒÜ ÈÍÔÎÐÌÀÖÈÞ Î ÐÅÇÓËÜÒÀÒÅ ÎÏÅÐÀÖÈÈ * |
;********************************************* |
GetStatusInfo: |
push AX |
call FDCDataInput |
mov [FDC_ST0],AL |
call FDCDataInput |
mov [FDC_ST1],AL |
call FDCDataInput |
mov [FDC_ST2],AL |
call FDCDataInput |
mov [FDC_C],AL |
call FDCDataInput |
mov [FDC_H],AL |
call FDCDataInput |
mov [FDC_R],AL |
call FDCDataInput |
mov [FDC_N],AL |
pop AX |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;********************************************************** |
; Íåïîñðåäñòâåííàÿ ðàáîòà ñ êîíòðîëëåðîì ãèáêîãî äèñêà |
;********************************************************** |
; Àâòîð èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷. |
; Àäàïòàöèÿ è äîðàáîòêà Mario79 |
;give_back_application_data: ; ïåðåñëàòü ïðèëîæåíèþ |
; mov edi,[TASK_BASE] |
; mov edi,[edi+TASKDATA.mem_start] |
; add edi,ecx |
give_back_application_data_1: |
mov esi, FDD_BUFF;FDD_DataBuffer ;0x40000 |
xor ecx, ecx |
mov cx, 128 |
cld |
rep movsd |
ret |
;take_data_from_application: ; âçÿòü èç ïðèëîæåíè |
; mov esi,[TASK_BASE] |
; mov esi,[esi+TASKDATA.mem_start] |
; add esi,ecx |
take_data_from_application_1: |
mov edi, FDD_BUFF;FDD_DataBuffer ;0x40000 |
xor ecx, ecx |
mov cx, 128 |
cld |
rep movsd |
ret |
; Êîäû çàâåðøåíèÿ îïåðàöèè ñ êîíòðîëëåðîì (FDC_Status) |
FDC_Normal equ 0 ;íîðìàëüíîå çàâåðøåíèå |
FDC_TimeOut equ 1 ;îøèáêà òàéì-àóòà |
FDC_DiskNotFound equ 2 ;â äèñêîâîäå íåò äèñêà |
FDC_TrackNotFound equ 3 ;äîðîæêà íå íàéäåíà |
FDC_SectorNotFound equ 4 ;ñåêòîð íå íàéäåí |
; Ìàêñèìàëüíûå çíà÷åíèÿ êîîðäèíàò ñåêòîðà (çàäàííûå |
; çíà÷åíèÿ ñîîòâåòñòâóþò ïàðàìåòðàì ñòàíäàðòíîãî |
; òðåõäþéìîâîãî ãèáêîãî äèñêà îáúåìîì 1,44 Ìá) |
MAX_Track equ 79 |
MAX_Head equ 1 |
MAX_Sector equ 18 |
uglobal |
; Ñ÷åò÷èê òèêîâ òàéìåðà |
TickCounter dd ? |
; Êîä çàâåðøåíèÿ îïåðàöèè ñ êîíòðîëëåðîì ÍÃÌÄ |
FDC_Status DB ? |
; Ôëàã ïðåðûâàíèÿ îò ÍÃÌÄ |
FDD_IntFlag DB ? |
; Ìîìåíò íà÷àëà ïîñëåäíåé îïåðàöèè ñ ÍÃÌÄ |
FDD_Time DD ? |
; Íîìåð äèñêîâîäà |
FDD_Type db 0 |
; Êîîðäèíàòû ñåêòîðà |
FDD_Track DB ? |
FDD_Head DB ? |
FDD_Sector DB ? |
; Áëîê ðåçóëüòàòà îïåðàöèè |
FDC_ST0 DB ? |
FDC_ST1 DB ? |
FDC_ST2 DB ? |
FDC_C DB ? |
FDC_H DB ? |
FDC_R DB ? |
FDC_N DB ? |
; Ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè |
ReadRepCounter DB ? |
; Ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè |
RecalRepCounter DB ? |
endg |
; Îáëàñòü ïàìÿòè äëÿ õðàíåíèÿ ïðî÷èòàííîãî ñåêòîðà |
;FDD_DataBuffer: times 512 db 0 ;DB 512 DUP (?) |
fdd_motor_status db 0 |
timer_fdd_motor dd 0 |
;************************************* |
;* ÈÍÈÖÈÀËÈÇÀÖÈß ÐÅÆÈÌÀ ÏÄÏ ÄËß ÍÃÌÄ * |
;************************************* |
Init_FDC_DMA: |
pushad |
mov al, 0 |
out 0x0c, al; reset the flip-flop to a known state. |
mov al, 6 ; mask channel 2 so we can reprogram it. |
out 0x0a, al |
mov al, [dmamode]; 0x46 -> Read from floppy - 0x4A Write to floppy |
out 0x0b, al |
mov al, 0 |
out 0x0c, al; reset the flip-flop to a known state. |
mov eax, 0xD000 |
out 0x04, al; set the channel 2 starting address to 0 |
shr eax, 8 |
out 0x04, al |
shr eax, 8 |
out 0x81, al |
mov al, 0 |
out 0x0c, al; reset flip-flop |
mov al, 0xff;set count (actual size -1) |
out 0x5, al |
mov al, 0x1;[dmasize] ;(0x1ff = 511 / 0x23ff =9215) |
out 0x5, al |
mov al, 2 |
out 0xa, al |
popad |
ret |
;*********************************** |
;* ÇÀÏÈÑÀÒÜ ÁÀÉÒ Â ÏÎÐÒ ÄÀÍÍÛÕ FDC * |
;* Ïàðàìåòðû: * |
;* AL - âûâîäèìûé áàéò. * |
;*********************************** |
FDCDataOutput: |
; pusha |
push eax ecx edx |
mov AH, AL ;çàïîìíèòü áàéò â AH |
; Ñáðîñèòü ïåðåìåííóþ ñîñòîÿíèÿ êîíòðîëëåðà |
mov [FDC_Status], FDC_Normal |
; Ïðîâåðèòü ãîòîâíîñòü êîíòðîëëåðà ê ïðèåìó äàííûõ |
mov DX, 3F4h ;(ïîðò ñîñòîÿíèÿ FDC) |
mov ecx, 0x10000 ;óñòàíîâèòü ñ÷åò÷èê òàéì-àóòà |
@@TestRS: |
in AL, DX ;ïðî÷èòàòü ðåãèñòð RS |
and AL, 0C0h ;âûäåëèòü ðàçðÿäû 6 è 7 |
cmp AL, 80h ;ïðîâåðèòü ðàçðÿäû 6 è 7 |
je @@OutByteToFDC |
loop @@TestRS |
; Îøèáêà òàéì-àóòà |
mov [FDC_Status], FDC_TimeOut |
jmp @@End_5 |
; Âûâåñòè áàéò â ïîðò äàííûõ |
@@OutByteToFDC: |
inc DX |
mov AL, AH |
out DX, AL |
@@End_5: |
; popa |
pop edx ecx eax |
ret |
;****************************************** |
;* ÏÐÎ×ÈÒÀÒÜ ÁÀÉÒ ÈÇ ÏÎÐÒÀ ÄÀÍÍÛÕ FDC * |
;* Ïðîöåäóðà íå èìååò âõîäíûõ ïàðàìåòðîâ. * |
;* Âûõîäíûå äàííûå: * |
;* AL - ñ÷èòàííûé áàéò. * |
;****************************************** |
FDCDataInput: |
push ECX |
push DX |
; Ñáðîñèòü ïåðåìåííóþ ñîñòîÿíèÿ êîíòðîëëåðà |
mov [FDC_Status], FDC_Normal |
; Ïðîâåðèòü ãîòîâíîñòü êîíòðîëëåðà ê ïåðåäà÷å äàííûõ |
mov DX, 3F4h ;(ïîðò ñîñòîÿíèÿ FDC) |
xor CX, CX ;óñòàíîâèòü ñ÷åò÷èê òàéì-àóòà |
@@TestRS_1: |
in AL, DX ;ïðî÷èòàòü ðåãèñòð RS |
and AL, 0C0h ;âûäëèòü ðàçðÿäû 6 è 7 |
cmp AL, 0C0h ;ïðîâåðèòü ðàçðÿäû 6 è 7 |
je @@GetByteFromFDC |
loop @@TestRS_1 |
; Îøèáêà òàéì-àóòà |
mov [FDC_Status], FDC_TimeOut |
jmp @@End_6 |
; Ââåñòè áàéò èç ïîðòà äàííûõ |
@@GetByteFromFDC: |
inc DX |
in AL, DX |
@@End_6: |
pop DX |
pop ECX |
ret |
;********************************************* |
;* ÎÁÐÀÁÎÒ×ÈÊ ÏÐÅÐÛÂÀÍÈß ÎÒ ÊÎÍÒÐÎËËÅÐÀ ÍÃÌÄ * |
;********************************************* |
FDCInterrupt: |
; Óñòàíîâèòü ôëàã ïðåðûâàíè |
mov [FDD_IntFlag], 1 |
ret |
;****************************************** |
;* ÓÑÒÀÍÎÂÈÒÜ ÍÎÂÛÉ ÎÁÐÀÁÎÒ×ÈÊ ÏÐÅÐÛÂÀÍÈÉ * |
;* ÍÃÌÄ * |
;****************************************** |
SetUserInterrupts: |
mov [fdc_irq_func], FDCInterrupt |
ret |
;******************************************* |
;* ÎÆÈÄÀÍÈÅ ÏÐÅÐÛÂÀÍÈß ÎÒ ÊÎÍÒÐÎËËÅÐÀ ÍÃÌÄ * |
;******************************************* |
WaitFDCInterrupt: |
pusha |
; Ñáðîñèòü áàéò ñîñòîÿíèÿ îïåðàöèè |
mov [FDC_Status], FDC_Normal |
; Ñáðîñèòü ôëàã ïðåðûâàíè |
mov [FDD_IntFlag], 0 |
; Îáíóëèòü ñ÷åò÷èê òèêîâ |
mov eax, [timer_ticks] |
mov [TickCounter], eax |
; Îæèäàòü óñòàíîâêè ôëàãà ïðåðûâàíèÿ ÍÃÌÄ |
@@TestRS_2: |
cmp [FDD_IntFlag], 0 |
jnz @@End_7 ;ïðåðûâàíèå ïðîèçîøëî |
call change_task |
mov eax, [timer_ticks] |
sub eax, [TickCounter] |
cmp eax, 50 ;25 ;5 ;îæèäàòü 5 òèêîâ |
jb @@TestRS_2 |
; jl @@TestRS_2 |
; Îøèáêà òàéì-àóòà |
mov [FDC_Status], FDC_TimeOut |
; mov [flp_status],0 |
@@End_7: |
popa |
ret |
;********************************* |
;* ÂÊËÞ×ÈÒÜ ÌÎÒÎÐ ÄÈÑÊÎÂÎÄÀ "A:" * |
;********************************* |
FDDMotorON: |
pusha |
; cmp [fdd_motor_status],1 |
; je fdd_motor_on |
mov al, [flp_number] |
cmp [fdd_motor_status], al |
je fdd_motor_on |
; Ïðîèçâåñòè ñáðîñ êîíòðîëëåðà ÍÃÌÄ |
mov DX, 3F2h;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè |
mov AL, 0 |
out DX, AL |
; Âûáðàòü è âêëþ÷èòü ìîòîð äèñêîâîäà |
cmp [flp_number], 1 |
jne FDDMotorON_B |
; call FDDMotorOFF_B |
mov AL, 1Ch ; Floppy A |
jmp FDDMotorON_1 |
FDDMotorON_B: |
; call FDDMotorOFF_A |
mov AL, 2Dh ; Floppy B |
FDDMotorON_1: |
out DX, AL |
; Îáíóëèòü ñ÷åò÷èê òèêîâ |
mov eax, [timer_ticks] |
mov [TickCounter], eax |
; Îæèäàòü 0,5 ñ |
@@dT: |
call change_task |
mov eax, [timer_ticks] |
sub eax, [TickCounter] |
cmp eax, 50 ;10 |
jb @@dT |
cmp [flp_number], 1 |
jne fdd_motor_on_B |
mov [fdd_motor_status], 1 |
jmp fdd_motor_on |
fdd_motor_on_B: |
mov [fdd_motor_status], 2 |
fdd_motor_on: |
call save_timer_fdd_motor |
popa |
ret |
;***************************************** |
;* ÑÎÕÐÀÍÅÍÈÅ ÓÊÀÇÀÒÅËß ÂÐÅÌÅÍÈ * |
;***************************************** |
save_timer_fdd_motor: |
mov eax, [timer_ticks] |
mov [timer_fdd_motor], eax |
ret |
;***************************************** |
;* ÏÐÎÂÅÐÊÀ ÇÀÄÅÐÆÊÈ ÂÛÊËÞ×ÅÍÈß ÌÎÒÎÐÀ * |
;***************************************** |
align 4 |
check_fdd_motor_status: |
cmp [fdd_motor_status], 0 |
je end_check_fdd_motor_status_1 |
mov eax, [timer_ticks] |
sub eax, [timer_fdd_motor] |
cmp eax, 500 |
jb end_check_fdd_motor_status |
call FDDMotorOFF |
mov [fdd_motor_status], 0 |
end_check_fdd_motor_status_1: |
mov [flp_status], 0 |
end_check_fdd_motor_status: |
ret |
;********************************** |
;* ÂÛÊËÞ×ÈÒÜ ÌÎÒÎÐ ÄÈÑÊÎÂÎÄÀ * |
;********************************** |
FDDMotorOFF: |
push AX |
push DX |
cmp [flp_number], 1 |
jne FDDMotorOFF_1 |
call FDDMotorOFF_A |
jmp FDDMotorOFF_2 |
FDDMotorOFF_1: |
call FDDMotorOFF_B |
FDDMotorOFF_2: |
pop DX |
pop AX |
; ñáðîñ ôëàãîâ êåøèðîâàíèÿ â ñâÿçè ñ óñòàðåâàíèåì èíôîðìàöèè |
mov [root_read], 0 |
mov [flp_fat], 0 |
ret |
FDDMotorOFF_A: |
mov DX, 3F2h;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè |
mov AL, 0Ch ; Floppy A |
out DX, AL |
ret |
FDDMotorOFF_B: |
mov DX, 3F2h;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè |
mov AL, 5h ; Floppy B |
out DX, AL |
ret |
;******************************* |
;* ÐÅÊÀËÈÁÐÎÂÊÀ ÄÈÑÊÎÂÎÄÀ "A:" * |
;******************************* |
RecalibrateFDD: |
pusha |
call save_timer_fdd_motor |
; Ïîäàòü êîìàíäó "Ðåêàëèáðîâêà" |
mov AL, 07h |
call FDCDataOutput |
mov AL, 00h |
call FDCDataOutput |
; Îæèäàòü çàâåðøåíèÿ îïåðàöèè |
call WaitFDCInterrupt |
; cmp [FDC_Status],0 |
; je no_fdc_status_error |
; mov [flp_status],0 |
;no_fdc_status_error: |
call save_timer_fdd_motor |
popa |
ret |
;***************************************************** |
;* ÏÎÈÑÊ ÄÎÐÎÆÊÈ * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;***************************************************** |
SeekTrack: |
pusha |
call save_timer_fdd_motor |
; Ïîäàòü êîìàíäó "Ïîèñê" |
mov AL, 0Fh |
call FDCDataOutput |
; Ïåðåäàòü áàéò íîìåðà ãîëîâêè/íàêîïèòåë |
mov AL, [FDD_Head] |
shl AL, 2 |
call FDCDataOutput |
; Ïåðåäàòü áàéò íîìåðà äîðîæêè |
mov AL, [FDD_Track] |
call FDCDataOutput |
; Îæèäàòü çàâåðøåíèÿ îïåðàöèè |
call WaitFDCInterrupt |
cmp [FDC_Status], FDC_Normal |
jne @@Exit |
; Ñîõðàíèòü ðåçóëüòàò ïîèñêà |
mov AL, 08h |
call FDCDataOutput |
call FDCDataInput |
mov [FDC_ST0], AL |
call FDCDataInput |
mov [FDC_C], AL |
; Ïðîâåðèòü ðåçóëüòàò ïîèñêà |
; Ïîèñê çàâåðøåí? |
test [FDC_ST0], 100000b |
je @@Err |
; Çàäàííûé òðåê íàéäåí? |
mov AL, [FDC_C] |
cmp AL, [FDD_Track] |
jne @@Err |
; Íîìåð ãîëîâêè ñîâïàäàåò ñ çàäàííûì? |
mov AL, [FDC_ST0] |
and AL, 100b |
shr AL, 2 |
cmp AL, [FDD_Head] |
jne @@Err |
; Îïåðàöèÿ çàâåðøåíà óñïåøíî |
mov [FDC_Status], FDC_Normal |
jmp @@Exit |
@@Err: ; Òðåê íå íàéäåí |
mov [FDC_Status], FDC_TrackNotFound |
; mov [flp_status],0 |
@@Exit: |
call save_timer_fdd_motor |
popa |
ret |
;******************************************************* |
;* ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1); * |
;* FDD_Sector - íîìåð ñåêòîðà (1-18). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè ÷òåíèÿ * |
;* ñîäåðæèìîå ñåêòîðà áóäåò çàíåñåíî â FDD_DataBuffer. * |
;******************************************************* |
ReadSector: |
pushad |
call save_timer_fdd_motor |
; Óñòàíîâèòü ñêîðîñòü ïåðåäà÷è 500 Êáàéò/ñ |
mov AX, 0 |
mov DX, 03F7h |
out DX, AL |
; Èíèöèàëèçèðîâàòü êàíàë ïðÿìîãî äîñòóïà ê ïàìÿòè |
mov [dmamode], 0x46 |
call Init_FDC_DMA |
; Ïîäàòü êîìàíäó "×òåíèå äàííûõ" |
mov AL, 0E6h ;÷òåíèå â ìóëüòèòðåêîâîì ðåæèìå |
call FDCDataOutput |
mov AL, [FDD_Head] |
shl AL, 2 |
call FDCDataOutput |
mov AL, [FDD_Track] |
call FDCDataOutput |
mov AL, [FDD_Head] |
call FDCDataOutput |
mov AL, [FDD_Sector] |
call FDCDataOutput |
mov AL, 2 ;êîä ðàçìåðà ñåêòîðà (512 áàéò) |
call FDCDataOutput |
mov AL, 18 ;+1; 3Fh ;÷èñëî ñåêòîðîâ íà äîðîæêå |
call FDCDataOutput |
mov AL, 1Bh ;çíà÷åíèå GPL |
call FDCDataOutput |
mov AL, 0FFh;çíà÷åíèå DTL |
call FDCDataOutput |
; Îæèäàåì ïðåðûâàíèå ïî çàâåðøåíèè îïåðàöèè |
call WaitFDCInterrupt |
cmp [FDC_Status], FDC_Normal |
jne @@Exit_1 |
; Ñ÷èòûâàåì ñòàòóñ çàâåðøåíèÿ îïåðàöèè |
call GetStatusInfo |
test [FDC_ST0], 11011000b |
jnz @@Err_1 |
mov [FDC_Status], FDC_Normal |
jmp @@Exit_1 |
@@Err_1: |
mov [FDC_Status], FDC_SectorNotFound |
; mov [flp_status],0 |
@@Exit_1: |
call save_timer_fdd_motor |
popad |
ret |
;******************************************************* |
;* ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ (Ñ ÏÎÂÒÎÐÅÍÈÅÌ ÎÏÅÐÀÖÈÈ ÏÐÈ ÑÁÎÅ) * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1); * |
;* FDD_Sector - íîìåð ñåêòîðà (1-18). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè ÷òåíèÿ * |
;* ñîäåðæèìîå ñåêòîðà áóäåò çàíåñåíî â FDD_DataBuffer. * |
;******************************************************* |
ReadSectWithRetr: |
pusha |
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè |
mov [RecalRepCounter], 0 |
@@TryAgain: |
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè |
mov [ReadRepCounter], 0 |
@@ReadSector_1: |
call ReadSector |
cmp [FDC_Status], 0 |
je @@Exit_2 |
cmp [FDC_Status], 1 |
je @@Err_3 |
; Òðîåêðàòíîå ïîâòîðåíèå ÷òåíè |
inc [ReadRepCounter] |
cmp [ReadRepCounter], 3 |
jb @@ReadSector_1 |
; Òðîåêðàòíîå ïîâòîðåíèå ðåêàëèáðîâêè |
call RecalibrateFDD |
call SeekTrack |
inc [RecalRepCounter] |
cmp [RecalRepCounter], 3 |
jb @@TryAgain |
; mov [flp_status],0 |
@@Exit_2: |
popa |
ret |
@@Err_3: |
mov [flp_status], 0 |
popa |
ret |
;******************************************************* |
;* ÇÀÏÈÑÜ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1); * |
;* FDD_Sector - íîìåð ñåêòîðà (1-18). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè çàïèñè * |
;* ñîäåðæèìîå FDD_DataBuffer áóäåò çàíåñåíî â ñåêòîð. * |
;******************************************************* |
WriteSector: |
pushad |
call save_timer_fdd_motor |
; Óñòàíîâèòü ñêîðîñòü ïåðåäà÷è 500 Êáàéò/ñ |
mov AX, 0 |
mov DX, 03F7h |
out DX, AL |
; Èíèöèàëèçèðîâàòü êàíàë ïðÿìîãî äîñòóïà ê ïàìÿòè |
mov [dmamode], 0x4A |
call Init_FDC_DMA |
; Ïîäàòü êîìàíäó "Çàïèñü äàííûõ" |
mov AL, 0xC5 ;0x45 ;çàïèñü â ìóëüòèòðåêîâîì ðåæèìå |
call FDCDataOutput |
mov AL, [FDD_Head] |
shl AL, 2 |
call FDCDataOutput |
mov AL, [FDD_Track] |
call FDCDataOutput |
mov AL, [FDD_Head] |
call FDCDataOutput |
mov AL, [FDD_Sector] |
call FDCDataOutput |
mov AL, 2 ;êîä ðàçìåðà ñåêòîðà (512 áàéò) |
call FDCDataOutput |
mov AL, 18; 3Fh ;÷èñëî ñåêòîðîâ íà äîðîæêå |
call FDCDataOutput |
mov AL, 1Bh ;çíà÷åíèå GPL |
call FDCDataOutput |
mov AL, 0FFh;çíà÷åíèå DTL |
call FDCDataOutput |
; Îæèäàåì ïðåðûâàíèå ïî çàâåðøåíèè îïåðàöèè |
call WaitFDCInterrupt |
cmp [FDC_Status], FDC_Normal |
jne @@Exit_3 |
; Ñ÷èòûâàåì ñòàòóñ çàâåðøåíèÿ îïåðàöèè |
call GetStatusInfo |
test [FDC_ST0], 11000000b ;11011000b |
jnz @@Err_2 |
mov [FDC_Status], FDC_Normal |
jmp @@Exit_3 |
@@Err_2: |
mov [FDC_Status], FDC_SectorNotFound |
@@Exit_3: |
call save_timer_fdd_motor |
popad |
ret |
;******************************************************* |
;* ÇÀÏÈÑÜ ÑÅÊÒÎÐÀ (Ñ ÏÎÂÒÎÐÅÍÈÅÌ ÎÏÅÐÀÖÈÈ ÏÐÈ ÑÁÎÅ) * |
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: * |
;* FDD_Track - íîìåð äîðîæêè (0-79); * |
;* FDD_Head - íîìåð ãîëîâêè (0-1); * |
;* FDD_Sector - íîìåð ñåêòîðà (1-18). * |
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. * |
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè çàïèñè * |
;* ñîäåðæèìîå FDD_DataBuffer áóäåò çàíåñåíî â ñåêòîð. * |
;******************************************************* |
WriteSectWithRetr: |
pusha |
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè |
mov [RecalRepCounter], 0 |
@@TryAgain_1: |
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè |
mov [ReadRepCounter], 0 |
@@WriteSector_1: |
call WriteSector |
cmp [FDC_Status], 0 |
je @@Exit_4 |
cmp [FDC_Status], 1 |
je @@Err_4 |
; Òðîåêðàòíîå ïîâòîðåíèå ÷òåíè |
inc [ReadRepCounter] |
cmp [ReadRepCounter], 3 |
jb @@WriteSector_1 |
; Òðîåêðàòíîå ïîâòîðåíèå ðåêàëèáðîâêè |
call RecalibrateFDD |
call SeekTrack |
inc [RecalRepCounter] |
cmp [RecalRepCounter], 3 |
jb @@TryAgain_1 |
@@Exit_4: |
popa |
ret |
@@Err_4: |
mov [flp_status], 0 |
popa |
ret |
;********************************************* |
;* ÏÎËÓ×ÈÒÜ ÈÍÔÎÐÌÀÖÈÞ Î ÐÅÇÓËÜÒÀÒÅ ÎÏÅÐÀÖÈÈ * |
;********************************************* |
GetStatusInfo: |
push AX |
call FDCDataInput |
mov [FDC_ST0], AL |
call FDCDataInput |
mov [FDC_ST1], AL |
call FDCDataInput |
mov [FDC_ST2], AL |
call FDCDataInput |
mov [FDC_C], AL |
call FDCDataInput |
mov [FDC_H], AL |
call FDCDataInput |
mov [FDC_R], AL |
call FDCDataInput |
mov [FDC_N], AL |
pop AX |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/blkdev/hd_drv.inc |
---|
1,947 → 1,947 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Low-level driver for HDD access |
; DMA support by Mario79 |
; Access through BIOS by diamond |
align 4 |
hd_read: |
;----------------------------------------------------------- |
; input : eax = block to read |
; ebx = destination |
;----------------------------------------------------------- |
and [hd_error], 0 |
push ecx esi edi ; scan cache |
; mov ecx,cache_max ; entries in cache |
; mov esi,HD_CACHE+8 |
call calculate_cache |
add esi,8 |
mov edi,1 |
hdreadcache: |
cmp dword [esi+4],0 ; empty |
je nohdcache |
cmp [esi],eax ; correct sector |
je yeshdcache |
nohdcache: |
add esi,8 |
inc edi |
dec ecx |
jnz hdreadcache |
call find_empty_slot ; ret in edi |
cmp [hd_error],0 |
jne return_01 |
; Read through BIOS? |
cmp [hdpos], 0x80 |
jae .bios |
; hd_read_{dma,pio} use old ATA with 28 bit for sector number |
cmp eax, 0x10000000 |
jb @f |
inc [hd_error] |
jmp return_01 |
@@: |
; DMA read is permitted if [allow_dma_access]=1 or 2 |
cmp [allow_dma_access], 2 |
ja .nodma |
cmp [dma_hdd], 1 |
jnz .nodma |
call hd_read_dma |
jmp @f |
.nodma: |
call hd_read_pio |
jmp @f |
.bios: |
call bd_read |
@@: |
cmp [hd_error], 0 |
jne return_01 |
; lea esi,[edi*8+HD_CACHE] |
; push eax |
call calculate_cache_1 |
lea esi,[edi*8+esi] |
; pop eax |
mov [esi],eax ; sector number |
mov dword [esi+4],1 ; hd read - mark as same as in hd |
yeshdcache: |
mov esi,edi |
shl esi,9 |
; add esi,HD_CACHE+65536 |
push eax |
call calculate_cache_2 |
add esi,eax |
pop eax |
mov edi,ebx |
mov ecx,512/4 |
cld |
rep movsd ; move data |
return_01: |
pop edi esi ecx |
ret |
align 4 |
hd_read_pio: |
push eax edx |
call wait_for_hd_idle |
cmp [hd_error],0 |
jne hd_read_error |
cli |
xor eax,eax |
mov edx,[hdbase] |
inc edx |
out dx,al ; ATAFeatures ॣ¨áâà "®á®¡¥®á⥩" |
inc edx |
inc eax |
out dx,al ; ATASectorCount áçñâ稪 ᥪâ®à®¢ |
inc edx |
mov eax,[esp+4] |
out dx,al ; ATASectorNumber ॣ¨áâà ®¬¥à ᥪâ®à |
shr eax,8 |
inc edx |
out dx,al ; ATACylinder ®¬¥à 樫¨¤à (¬« ¤è¨© ¡ ©â) |
shr eax,8 |
inc edx |
out dx,al ; ®¬¥à 樫¨¤à (áâ à訩 ¡ ©â) |
shr eax,8 |
inc edx |
and al,1+2+4+8 |
add al,byte [hdid] |
add al,128+64+32 |
out dx,al ; ®¬¥à £®«®¢ª¨/®¬¥à ¤¨áª |
inc edx |
mov al,20h |
out dx,al ; ATACommand ॣ¨áâà ª®¬ ¤ |
sti |
call wait_for_sector_buffer |
cmp [hd_error],0 |
jne hd_read_error |
cli |
push edi |
shl edi,9 |
; add edi,HD_CACHE+65536 |
push eax |
call calculate_cache_2 |
add edi,eax |
pop eax |
mov ecx,256 |
mov edx,[hdbase] |
cld |
rep insw |
pop edi |
sti |
pop edx eax |
ret |
disable_ide_int: |
; mov edx,[hdbase] |
; add edx,0x206 |
; mov al,2 |
; out dx,al |
cli |
ret |
enable_ide_int: |
; mov edx,[hdbase] |
; add edx,0x206 |
; mov al,0 |
; out dx,al |
sti |
ret |
align 4 |
hd_write: |
;----------------------------------------------------------- |
; input : eax = block |
; ebx = pointer to memory |
;----------------------------------------------------------- |
push ecx esi edi |
; check if the cache already has the sector and overwrite it |
; mov ecx,cache_max |
; mov esi,HD_CACHE+8 |
call calculate_cache |
add esi,8 |
mov edi,1 |
hdwritecache: |
cmp dword [esi+4],0 ; if cache slot is empty |
je not_in_cache_write |
cmp [esi],eax ; if the slot has the sector |
je yes_in_cache_write |
not_in_cache_write: |
add esi,8 |
inc edi |
dec ecx |
jnz hdwritecache |
; sector not found in cache |
; write the block to a new location |
call find_empty_slot ; ret in edi |
cmp [hd_error],0 |
jne hd_write_access_denied |
; lea esi,[edi*8+HD_CACHE] |
; push eax |
call calculate_cache_1 |
lea esi,[edi*8+esi] |
; pop eax |
mov [esi],eax ; sector number |
yes_in_cache_write: |
mov dword [esi+4],2 ; write - differs from hd |
shl edi,9 |
; add edi,HD_CACHE+65536 |
push eax |
call calculate_cache_2 |
add edi,eax |
pop eax |
mov esi,ebx |
mov ecx,512/4 |
cld |
rep movsd ; move data |
hd_write_access_denied: |
pop edi esi ecx |
ret |
align 4 |
cache_write_pio: |
cmp dword[esi],0x10000000 |
jae .bad |
; call disable_ide_int |
call wait_for_hd_idle |
cmp [hd_error],0 |
jne hd_write_error |
cli |
xor eax,eax |
mov edx,[hdbase] |
inc edx |
out dx,al |
inc edx |
inc eax |
out dx,al |
inc edx |
mov eax,[esi] ; eax = sector to write |
out dx,al |
shr eax,8 |
inc edx |
out dx,al |
shr eax,8 |
inc edx |
out dx,al |
shr eax,8 |
inc edx |
and al,1+2+4+8 |
add al,byte [hdid] |
add al,128+64+32 |
out dx,al |
inc edx |
mov al,30h |
out dx,al |
sti |
call wait_for_sector_buffer |
cmp [hd_error],0 |
jne hd_write_error |
push ecx esi |
cli |
mov esi,edi |
shl esi,9 |
; add esi,HD_CACHE+65536 ; esi = from memory position |
push eax |
call calculate_cache_2 |
add esi,eax |
pop eax |
mov ecx,256 |
mov edx,[hdbase] |
cld |
rep outsw |
sti |
; call enable_ide_int |
pop esi ecx |
ret |
.bad: |
inc [hd_error] |
ret |
save_hd_wait_timeout: |
push eax |
mov eax,[timer_ticks] |
add eax,300 ; 3 sec timeout |
mov [hd_wait_timeout],eax |
pop eax |
ret |
align 4 |
check_hd_wait_timeout: |
push eax |
mov eax,[hd_wait_timeout] |
cmp [timer_ticks], eax |
jg hd_timeout_error |
pop eax |
mov [hd_error],0 |
ret |
;iglobal |
; hd_timeout_str db 'K : FS - HD timeout',0 |
; hd_read_str db 'K : FS - HD read error',0 |
; hd_write_str db 'K : FS - HD write error',0 |
; hd_lba_str db 'K : FS - HD LBA error',0 |
;endg |
hd_timeout_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_timeout_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD timeout\n" |
mov [hd_error],1 |
pop eax |
ret |
hd_read_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_read_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD read error\n" |
pop edx eax |
ret |
hd_write_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_write_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD write error\n" |
ret |
hd_write_error_dma: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi, hd_write_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD read error\n" |
pop esi |
ret |
hd_lba_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_lba_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD LBA error\n" |
jmp LBA_read_ret |
align 4 |
wait_for_hd_idle: |
push eax edx |
call save_hd_wait_timeout |
mov edx,[hdbase] |
add edx,0x7 |
wfhil1: |
call check_hd_wait_timeout |
cmp [hd_error],0 |
jne @f |
in al,dx |
test al,128 |
jnz wfhil1 |
@@: |
pop edx eax |
ret |
align 4 |
wait_for_sector_buffer: |
push eax edx |
mov edx,[hdbase] |
add edx,0x7 |
call save_hd_wait_timeout |
hdwait_sbuf: ; wait for sector buffer to be ready |
call check_hd_wait_timeout |
cmp [hd_error],0 |
jne @f |
in al,dx |
test al,8 |
jz hdwait_sbuf |
mov [hd_error],0 |
cmp [hd_setup],1 ; do not mark error for setup request |
je buf_wait_ok |
test al,1 ; previous command ended up with an error |
jz buf_wait_ok |
@@: |
mov [hd_error],1 |
buf_wait_ok: |
pop edx eax |
ret |
; \begin{Mario79} |
align 4 |
wait_for_sector_dma_ide0: |
push eax |
push edx |
call save_hd_wait_timeout |
.wait: |
call change_task |
cmp [irq14_func], hdd_irq14 |
jnz .done |
call check_hd_wait_timeout |
cmp [hd_error], 0 |
jz .wait |
mov [irq14_func], hdd_irq_null |
mov dx, [IDEContrRegsBaseAddr] |
mov al, 0 |
out dx, al |
.done: |
pop edx |
pop eax |
ret |
align 4 |
wait_for_sector_dma_ide1: |
push eax |
push edx |
call save_hd_wait_timeout |
.wait: |
call change_task |
cmp [irq15_func], hdd_irq15 |
jnz .done |
call check_hd_wait_timeout |
cmp [hd_error], 0 |
jz .wait |
mov [irq15_func], hdd_irq_null |
mov dx, [IDEContrRegsBaseAddr] |
add dx, 8 |
mov al, 0 |
out dx, al |
.done: |
pop edx |
pop eax |
ret |
iglobal |
align 4 |
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary |
IDE_descriptor_table: |
dd IDE_DMA |
dw 0x2000 |
dw 0x8000 |
dma_cur_sector dd not 40h |
dma_hdpos dd 0 |
irq14_func dd hdd_irq_null |
irq15_func dd hdd_irq_null |
endg |
uglobal |
; all uglobals are zeroed at boot |
dma_process dd 0 |
dma_slot_ptr dd 0 |
cache_chain_pos dd 0 |
cache_chain_ptr dd 0 |
cache_chain_size db 0 |
cache_chain_started db 0 |
dma_task_switched db 0 |
dma_hdd db 0 |
allow_dma_access db 0 |
endg |
align 4 |
hdd_irq14: |
pushfd |
cli |
pushad |
mov [irq14_func], hdd_irq_null |
mov dx, [IDEContrRegsBaseAddr] |
mov al, 0 |
out dx, al |
; call update_counters |
; mov ebx, [dma_process] |
; cmp [CURRENT_TASK], ebx |
; jz .noswitch |
; mov [dma_task_switched], 1 |
; mov edi, [dma_slot_ptr] |
; mov eax, [CURRENT_TASK] |
; mov [dma_process], eax |
; mov eax, [TASK_BASE] |
; mov [dma_slot_ptr], eax |
; mov [CURRENT_TASK], ebx |
; mov [TASK_BASE], edi |
; mov byte [DONT_SWITCH], 1 |
; call do_change_task |
.noswitch: |
popad |
popfd |
align 4 |
hdd_irq_null: |
ret |
align 4 |
hdd_irq15: |
pushfd |
cli |
pushad |
mov [irq15_func], hdd_irq_null |
mov dx, [IDEContrRegsBaseAddr] |
add dx, 8 |
mov al, 0 |
out dx, al |
; call update_counters |
; mov ebx, [dma_process] |
; cmp [CURRENT_TASK], ebx |
; jz .noswitch |
; mov [dma_task_switched], 1 |
; mov edi, [dma_slot_ptr] |
; mov eax, [CURRENT_TASK] |
; mov [dma_process], eax |
; mov eax, [TASK_BASE] |
; mov [dma_slot_ptr], eax |
; mov [CURRENT_TASK], ebx |
; mov [TASK_BASE], edi |
; mov byte [DONT_SWITCH], 1 |
; call do_change_task |
.noswitch: |
popad |
popfd |
ret |
align 4 |
hd_read_dma: |
push eax |
push edx |
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 edi |
mov esi, eax |
shl edi, 9 |
; add edi, HD_CACHE+0x10000 |
push eax |
call calculate_cache_2 |
add edi,eax |
pop eax |
mov ecx, 512/4 |
cld |
rep movsd |
pop edi esi ecx |
pop edx |
pop eax |
ret |
.notread: |
mov eax, IDE_descriptor_table |
mov dword [eax], IDE_DMA |
mov word [eax+4], 0x2000 |
sub eax, OS_BASE |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
jz @f |
add edx, 8 |
@@: |
push edx |
add edx, 4 |
out dx, eax |
pop edx |
mov al, 0 |
out dx, al |
add edx, 2 |
mov al, 6 |
out dx, al |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jnz hd_read_error |
call disable_ide_int |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al |
inc edx |
mov eax, 10h |
out dx, al |
inc edx |
mov eax, [esp+4] |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
and al, 0xF |
add al, byte [hdid] |
add al, 11100000b |
out dx, al |
inc edx |
mov al, 0xC8 |
out dx, al |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
jz @f |
add dx, 8 |
@@: |
mov al, 9 |
out dx, al |
mov eax, [CURRENT_TASK] |
mov [dma_process], eax |
mov eax, [TASK_BASE] |
mov [dma_slot_ptr], eax |
cmp [hdbase], 0x1F0 |
jnz .ide1 |
mov [irq14_func], hdd_irq14 |
jmp @f |
.ide1: |
mov [irq15_func], hdd_irq15 |
@@: |
call enable_ide_int |
cmp [hdbase], 0x1F0 |
jnz .wait_ide1 |
call wait_for_sector_dma_ide0 |
jmp @f |
.wait_ide1: |
call wait_for_sector_dma_ide1 |
@@: |
cmp [hd_error], 0 |
jnz hd_read_error |
mov eax,[hdpos] |
mov [dma_hdpos],eax |
pop edx |
pop eax |
mov [dma_cur_sector], eax |
jmp hd_read_dma |
align 4 |
write_cache_sector: |
mov [cache_chain_size],1 |
mov [cache_chain_pos],edi |
write_cache_chain: |
cmp [hdpos], 0x80 |
jae bd_write_cache_chain |
mov eax,[cache_chain_ptr] |
cmp dword[eax],0x10000000 |
jae .bad |
push esi |
mov eax, IDE_descriptor_table |
mov edx,eax |
pusha |
mov esi,[cache_chain_pos] |
shl esi, 9 |
call calculate_cache_2 |
add esi,eax |
mov edi, (OS_BASE+IDE_DMA) |
mov dword [edx], IDE_DMA |
movzx ecx, [cache_chain_size] |
shl ecx, 9 |
mov word [edx+4], cx |
shr ecx,2 |
cld |
rep movsd |
popa |
sub eax, OS_BASE |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
jz @f |
add edx, 8 |
@@: |
push edx |
add edx, 4 |
out dx, eax |
pop edx |
mov al, 0 |
out dx, al |
add edx, 2 |
mov al, 6 |
out dx, al |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jnz hd_write_error_dma |
call disable_ide_int |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al |
inc edx |
mov al, [cache_chain_size] |
out dx, al |
inc edx |
mov esi, [cache_chain_ptr] |
mov eax, [esi] |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
and al, 0xF |
add al, byte [hdid] |
add al, 11100000b |
out dx, al |
inc edx |
mov al, 0xCA |
out dx, al |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
jz @f |
add dx, 8 |
@@: |
mov al, 1 |
out dx, al |
mov eax, [CURRENT_TASK] |
mov [dma_process], eax |
mov eax, [TASK_BASE] |
mov [dma_slot_ptr], eax |
cmp [hdbase], 0x1F0 |
jnz .ide1 |
mov [irq14_func], hdd_irq14 |
jmp @f |
.ide1: |
mov [irq15_func], hdd_irq15 |
@@: |
call enable_ide_int |
mov [dma_cur_sector], not 0x40 |
cmp [hdbase], 0x1F0 |
jnz .wait_ide1 |
call wait_for_sector_dma_ide0 |
jmp @f |
.wait_ide1: |
call wait_for_sector_dma_ide1 |
@@: |
cmp [hd_error], 0 |
jnz hd_write_error_dma |
pop esi |
ret |
.bad: |
inc [hd_error] |
ret |
uglobal |
IDEContrRegsBaseAddr dw ? |
endg |
; \end{Mario79} |
; \begin{diamond} |
uglobal |
bios_hdpos dd 0 ; 0 is invalid value for [hdpos] |
bios_cur_sector dd ? |
bios_read_len dd ? |
endg |
bd_read: |
push eax |
push edx |
mov edx, [bios_hdpos] |
cmp edx, [hdpos] |
jne .notread |
mov edx, [bios_cur_sector] |
cmp eax, edx |
jb .notread |
add edx, [bios_read_len] |
dec edx |
cmp eax, edx |
ja .notread |
sub eax, [bios_cur_sector] |
shl eax, 9 |
add eax, (OS_BASE+0x9A000) |
push ecx esi edi |
mov esi, eax |
shl edi, 9 |
; add edi, HD_CACHE+0x10000 |
push eax |
call calculate_cache_2 |
add edi,eax |
pop eax |
mov ecx, 512/4 |
cld |
rep movsd |
pop edi esi ecx |
pop edx |
pop eax |
ret |
.notread: |
push ecx |
mov dl, 42h |
mov ecx, 16 |
call int13_call |
pop ecx |
test eax, eax |
jnz .v86err |
test edx, edx |
jz .readerr |
mov [bios_read_len], edx |
mov edx, [hdpos] |
mov [bios_hdpos], edx |
pop edx |
pop eax |
mov [bios_cur_sector], eax |
jmp bd_read |
.readerr: |
.v86err: |
mov [hd_error], 1 |
jmp hd_read_error |
bd_write_cache_chain: |
pusha |
mov esi, [cache_chain_pos] |
shl esi, 9 |
call calculate_cache_2 |
add esi, eax |
mov edi, OS_BASE + 0x9A000 |
movzx ecx, [cache_chain_size] |
push ecx |
shl ecx, 9-2 |
rep movsd |
pop ecx |
mov dl, 43h |
mov eax, [cache_chain_ptr] |
mov eax, [eax] |
call int13_call |
test eax, eax |
jnz .v86err |
cmp edx, ecx |
jnz .writeerr |
popa |
ret |
.v86err: |
.writeerr: |
popa |
mov [hd_error], 1 |
jmp hd_write_error |
uglobal |
int13_regs_in rb v86_regs.size |
int13_regs_out rb v86_regs.size |
endg |
int13_call: |
; Because this code uses fixed addresses, |
; it can not be run simultaniously by many threads. |
; In current implementation it is protected by common mutex 'hd1_status' |
mov word [OS_BASE + 510h], 10h ; packet length |
mov word [OS_BASE + 512h], cx ; number of sectors |
mov dword [OS_BASE + 514h], 9A000000h ; buffer 9A00:0000 |
mov dword [OS_BASE + 518h], eax |
and dword [OS_BASE + 51Ch], 0 |
push ebx ecx esi edi |
mov ebx, int13_regs_in |
mov edi, ebx |
mov ecx, v86_regs.size/4 |
xor eax, eax |
rep stosd |
mov byte [ebx+v86_regs.eax+1], dl |
mov eax, [hdpos] |
lea eax, [BiosDisksData+(eax-80h)*4] |
mov dl, [eax] |
mov byte [ebx+v86_regs.edx], dl |
movzx edx, byte [eax+1] |
; mov dl, 5 |
test edx, edx |
jnz .hasirq |
dec edx |
jmp @f |
.hasirq: |
pushad |
stdcall enable_irq, edx |
popad |
@@: |
mov word [ebx+v86_regs.esi], 510h |
mov word [ebx+v86_regs.ss], 9000h |
mov word [ebx+v86_regs.esp], 0A000h |
mov word [ebx+v86_regs.eip], 500h |
mov [ebx+v86_regs.eflags], 20200h |
mov esi, [sys_v86_machine] |
mov ecx, 0x502 |
push fs |
call v86_start |
pop fs |
and [bios_hdpos], 0 |
pop edi esi ecx ebx |
movzx edx, byte [OS_BASE + 512h] |
test byte [int13_regs_out+v86_regs.eflags], 1 |
jnz @f |
mov edx, ecx |
@@: |
ret |
; \end{diamond} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Low-level driver for HDD access |
; DMA support by Mario79 |
; Access through BIOS by diamond |
align 4 |
hd_read: |
;----------------------------------------------------------- |
; input : eax = block to read |
; ebx = destination |
;----------------------------------------------------------- |
and [hd_error], 0 |
push ecx esi edi ; scan cache |
; mov ecx,cache_max ; entries in cache |
; mov esi,HD_CACHE+8 |
call calculate_cache |
add esi, 8 |
mov edi, 1 |
hdreadcache: |
cmp dword [esi+4], 0; empty |
je nohdcache |
cmp [esi], eax ; correct sector |
je yeshdcache |
nohdcache: |
add esi, 8 |
inc edi |
dec ecx |
jnz hdreadcache |
call find_empty_slot ; ret in edi |
cmp [hd_error], 0 |
jne return_01 |
; Read through BIOS? |
cmp [hdpos], 0x80 |
jae .bios |
; hd_read_{dma,pio} use old ATA with 28 bit for sector number |
cmp eax, 0x10000000 |
jb @f |
inc [hd_error] |
jmp return_01 |
@@: |
; DMA read is permitted if [allow_dma_access]=1 or 2 |
cmp [allow_dma_access], 2 |
ja .nodma |
cmp [dma_hdd], 1 |
jnz .nodma |
call hd_read_dma |
jmp @f |
.nodma: |
call hd_read_pio |
jmp @f |
.bios: |
call bd_read |
@@: |
cmp [hd_error], 0 |
jne return_01 |
; lea esi,[edi*8+HD_CACHE] |
; push eax |
call calculate_cache_1 |
lea esi, [edi*8+esi] |
; pop eax |
mov [esi], eax ; sector number |
mov dword [esi+4], 1; hd read - mark as same as in hd |
yeshdcache: |
mov esi, edi |
shl esi, 9 |
; add esi,HD_CACHE+65536 |
push eax |
call calculate_cache_2 |
add esi, eax |
pop eax |
mov edi, ebx |
mov ecx, 512/4 |
cld |
rep movsd ; move data |
return_01: |
pop edi esi ecx |
ret |
align 4 |
hd_read_pio: |
push eax edx |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jne hd_read_error |
cli |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al; ATAFeatures ॣ¨áâà "®á®¡¥®á⥩" |
inc edx |
inc eax |
out dx, al; ATASectorCount áçñâ稪 ᥪâ®à®¢ |
inc edx |
mov eax, [esp+4] |
out dx, al; ATASectorNumber ॣ¨áâà ®¬¥à ᥪâ®à |
shr eax, 8 |
inc edx |
out dx, al; ATACylinder ®¬¥à 樫¨¤à (¬« ¤è¨© ¡ ©â) |
shr eax, 8 |
inc edx |
out dx, al; ®¬¥à 樫¨¤à (áâ à訩 ¡ ©â) |
shr eax, 8 |
inc edx |
and al, 1+2+4+8 |
add al, byte [hdid] |
add al, 128+64+32 |
out dx, al; ®¬¥à £®«®¢ª¨/®¬¥à ¤¨áª |
inc edx |
mov al, 20h |
out dx, al; ATACommand ॣ¨áâà ª®¬ ¤ |
sti |
call wait_for_sector_buffer |
cmp [hd_error], 0 |
jne hd_read_error |
cli |
push edi |
shl edi, 9 |
; add edi,HD_CACHE+65536 |
push eax |
call calculate_cache_2 |
add edi, eax |
pop eax |
mov ecx, 256 |
mov edx, [hdbase] |
cld |
rep insw |
pop edi |
sti |
pop edx eax |
ret |
disable_ide_int: |
; mov edx,[hdbase] |
; add edx,0x206 |
; mov al,2 |
; out dx,al |
cli |
ret |
enable_ide_int: |
; mov edx,[hdbase] |
; add edx,0x206 |
; mov al,0 |
; out dx,al |
sti |
ret |
align 4 |
hd_write: |
;----------------------------------------------------------- |
; input : eax = block |
; ebx = pointer to memory |
;----------------------------------------------------------- |
push ecx esi edi |
; check if the cache already has the sector and overwrite it |
; mov ecx,cache_max |
; mov esi,HD_CACHE+8 |
call calculate_cache |
add esi, 8 |
mov edi, 1 |
hdwritecache: |
cmp dword [esi+4], 0; if cache slot is empty |
je not_in_cache_write |
cmp [esi], eax ; if the slot has the sector |
je yes_in_cache_write |
not_in_cache_write: |
add esi, 8 |
inc edi |
dec ecx |
jnz hdwritecache |
; sector not found in cache |
; write the block to a new location |
call find_empty_slot ; ret in edi |
cmp [hd_error], 0 |
jne hd_write_access_denied |
; lea esi,[edi*8+HD_CACHE] |
; push eax |
call calculate_cache_1 |
lea esi, [edi*8+esi] |
; pop eax |
mov [esi], eax ; sector number |
yes_in_cache_write: |
mov dword [esi+4], 2; write - differs from hd |
shl edi, 9 |
; add edi,HD_CACHE+65536 |
push eax |
call calculate_cache_2 |
add edi, eax |
pop eax |
mov esi, ebx |
mov ecx, 512/4 |
cld |
rep movsd ; move data |
hd_write_access_denied: |
pop edi esi ecx |
ret |
align 4 |
cache_write_pio: |
cmp dword[esi], 0x10000000 |
jae .bad |
; call disable_ide_int |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jne hd_write_error |
cli |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al |
inc edx |
inc eax |
out dx, al |
inc edx |
mov eax, [esi] ; eax = sector to write |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
and al, 1+2+4+8 |
add al, byte [hdid] |
add al, 128+64+32 |
out dx, al |
inc edx |
mov al, 30h |
out dx, al |
sti |
call wait_for_sector_buffer |
cmp [hd_error], 0 |
jne hd_write_error |
push ecx esi |
cli |
mov esi, edi |
shl esi, 9 |
; add esi,HD_CACHE+65536 ; esi = from memory position |
push eax |
call calculate_cache_2 |
add esi, eax |
pop eax |
mov ecx, 256 |
mov edx, [hdbase] |
cld |
rep outsw |
sti |
; call enable_ide_int |
pop esi ecx |
ret |
.bad: |
inc [hd_error] |
ret |
save_hd_wait_timeout: |
push eax |
mov eax, [timer_ticks] |
add eax, 300 ; 3 sec timeout |
mov [hd_wait_timeout], eax |
pop eax |
ret |
align 4 |
check_hd_wait_timeout: |
push eax |
mov eax, [hd_wait_timeout] |
cmp [timer_ticks], eax |
jg hd_timeout_error |
pop eax |
mov [hd_error], 0 |
ret |
;iglobal |
; hd_timeout_str db 'K : FS - HD timeout',0 |
; hd_read_str db 'K : FS - HD read error',0 |
; hd_write_str db 'K : FS - HD write error',0 |
; hd_lba_str db 'K : FS - HD LBA error',0 |
;endg |
hd_timeout_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_timeout_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD timeout\n" |
mov [hd_error], 1 |
pop eax |
ret |
hd_read_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_read_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD read error\n" |
pop edx eax |
ret |
hd_write_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_write_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD write error\n" |
ret |
hd_write_error_dma: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi, hd_write_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD read error\n" |
pop esi |
ret |
hd_lba_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_lba_str |
; call sys_msg_board_str |
DEBUGF 1,"K : FS - HD LBA error\n" |
jmp LBA_read_ret |
align 4 |
wait_for_hd_idle: |
push eax edx |
call save_hd_wait_timeout |
mov edx, [hdbase] |
add edx, 0x7 |
wfhil1: |
call check_hd_wait_timeout |
cmp [hd_error], 0 |
jne @f |
in al, dx |
test al, 128 |
jnz wfhil1 |
@@: |
pop edx eax |
ret |
align 4 |
wait_for_sector_buffer: |
push eax edx |
mov edx, [hdbase] |
add edx, 0x7 |
call save_hd_wait_timeout |
hdwait_sbuf: ; wait for sector buffer to be ready |
call check_hd_wait_timeout |
cmp [hd_error], 0 |
jne @f |
in al, dx |
test al, 8 |
jz hdwait_sbuf |
mov [hd_error], 0 |
cmp [hd_setup], 1 ; do not mark error for setup request |
je buf_wait_ok |
test al, 1 ; previous command ended up with an error |
jz buf_wait_ok |
@@: |
mov [hd_error], 1 |
buf_wait_ok: |
pop edx eax |
ret |
; \begin{Mario79} |
align 4 |
wait_for_sector_dma_ide0: |
push eax |
push edx |
call save_hd_wait_timeout |
.wait: |
call change_task |
cmp [irq14_func], hdd_irq14 |
jnz .done |
call check_hd_wait_timeout |
cmp [hd_error], 0 |
jz .wait |
mov [irq14_func], hdd_irq_null |
mov dx, [IDEContrRegsBaseAddr] |
mov al, 0 |
out dx, al |
.done: |
pop edx |
pop eax |
ret |
align 4 |
wait_for_sector_dma_ide1: |
push eax |
push edx |
call save_hd_wait_timeout |
.wait: |
call change_task |
cmp [irq15_func], hdd_irq15 |
jnz .done |
call check_hd_wait_timeout |
cmp [hd_error], 0 |
jz .wait |
mov [irq15_func], hdd_irq_null |
mov dx, [IDEContrRegsBaseAddr] |
add dx, 8 |
mov al, 0 |
out dx, al |
.done: |
pop edx |
pop eax |
ret |
iglobal |
align 4 |
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary |
IDE_descriptor_table: |
dd IDE_DMA |
dw 0x2000 |
dw 0x8000 |
dma_cur_sector dd not 40h |
dma_hdpos dd 0 |
irq14_func dd hdd_irq_null |
irq15_func dd hdd_irq_null |
endg |
uglobal |
; all uglobals are zeroed at boot |
dma_process dd 0 |
dma_slot_ptr dd 0 |
cache_chain_pos dd 0 |
cache_chain_ptr dd 0 |
cache_chain_size db 0 |
cache_chain_started db 0 |
dma_task_switched db 0 |
dma_hdd db 0 |
allow_dma_access db 0 |
endg |
align 4 |
hdd_irq14: |
pushfd |
cli |
pushad |
mov [irq14_func], hdd_irq_null |
mov dx, [IDEContrRegsBaseAddr] |
mov al, 0 |
out dx, al |
; call update_counters |
; mov ebx, [dma_process] |
; cmp [CURRENT_TASK], ebx |
; jz .noswitch |
; mov [dma_task_switched], 1 |
; mov edi, [dma_slot_ptr] |
; mov eax, [CURRENT_TASK] |
; mov [dma_process], eax |
; mov eax, [TASK_BASE] |
; mov [dma_slot_ptr], eax |
; mov [CURRENT_TASK], ebx |
; mov [TASK_BASE], edi |
; mov byte [DONT_SWITCH], 1 |
; call do_change_task |
.noswitch: |
popad |
popfd |
align 4 |
hdd_irq_null: |
ret |
align 4 |
hdd_irq15: |
pushfd |
cli |
pushad |
mov [irq15_func], hdd_irq_null |
mov dx, [IDEContrRegsBaseAddr] |
add dx, 8 |
mov al, 0 |
out dx, al |
; call update_counters |
; mov ebx, [dma_process] |
; cmp [CURRENT_TASK], ebx |
; jz .noswitch |
; mov [dma_task_switched], 1 |
; mov edi, [dma_slot_ptr] |
; mov eax, [CURRENT_TASK] |
; mov [dma_process], eax |
; mov eax, [TASK_BASE] |
; mov [dma_slot_ptr], eax |
; mov [CURRENT_TASK], ebx |
; mov [TASK_BASE], edi |
; mov byte [DONT_SWITCH], 1 |
; call do_change_task |
.noswitch: |
popad |
popfd |
ret |
align 4 |
hd_read_dma: |
push eax |
push edx |
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 edi |
mov esi, eax |
shl edi, 9 |
; add edi, HD_CACHE+0x10000 |
push eax |
call calculate_cache_2 |
add edi, eax |
pop eax |
mov ecx, 512/4 |
cld |
rep movsd |
pop edi esi ecx |
pop edx |
pop eax |
ret |
.notread: |
mov eax, IDE_descriptor_table |
mov dword [eax], IDE_DMA |
mov word [eax+4], 0x2000 |
sub eax, OS_BASE |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
jz @f |
add edx, 8 |
@@: |
push edx |
add edx, 4 |
out dx, eax |
pop edx |
mov al, 0 |
out dx, al |
add edx, 2 |
mov al, 6 |
out dx, al |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jnz hd_read_error |
call disable_ide_int |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al |
inc edx |
mov eax, 10h |
out dx, al |
inc edx |
mov eax, [esp+4] |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
and al, 0xF |
add al, byte [hdid] |
add al, 11100000b |
out dx, al |
inc edx |
mov al, 0xC8 |
out dx, al |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
jz @f |
add dx, 8 |
@@: |
mov al, 9 |
out dx, al |
mov eax, [CURRENT_TASK] |
mov [dma_process], eax |
mov eax, [TASK_BASE] |
mov [dma_slot_ptr], eax |
cmp [hdbase], 0x1F0 |
jnz .ide1 |
mov [irq14_func], hdd_irq14 |
jmp @f |
.ide1: |
mov [irq15_func], hdd_irq15 |
@@: |
call enable_ide_int |
cmp [hdbase], 0x1F0 |
jnz .wait_ide1 |
call wait_for_sector_dma_ide0 |
jmp @f |
.wait_ide1: |
call wait_for_sector_dma_ide1 |
@@: |
cmp [hd_error], 0 |
jnz hd_read_error |
mov eax, [hdpos] |
mov [dma_hdpos], eax |
pop edx |
pop eax |
mov [dma_cur_sector], eax |
jmp hd_read_dma |
align 4 |
write_cache_sector: |
mov [cache_chain_size], 1 |
mov [cache_chain_pos], edi |
write_cache_chain: |
cmp [hdpos], 0x80 |
jae bd_write_cache_chain |
mov eax, [cache_chain_ptr] |
cmp dword[eax], 0x10000000 |
jae .bad |
push esi |
mov eax, IDE_descriptor_table |
mov edx, eax |
pusha |
mov esi, [cache_chain_pos] |
shl esi, 9 |
call calculate_cache_2 |
add esi, eax |
mov edi, (OS_BASE+IDE_DMA) |
mov dword [edx], IDE_DMA |
movzx ecx, [cache_chain_size] |
shl ecx, 9 |
mov word [edx+4], cx |
shr ecx, 2 |
cld |
rep movsd |
popa |
sub eax, OS_BASE |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
jz @f |
add edx, 8 |
@@: |
push edx |
add edx, 4 |
out dx, eax |
pop edx |
mov al, 0 |
out dx, al |
add edx, 2 |
mov al, 6 |
out dx, al |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jnz hd_write_error_dma |
call disable_ide_int |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al |
inc edx |
mov al, [cache_chain_size] |
out dx, al |
inc edx |
mov esi, [cache_chain_ptr] |
mov eax, [esi] |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
and al, 0xF |
add al, byte [hdid] |
add al, 11100000b |
out dx, al |
inc edx |
mov al, 0xCA |
out dx, al |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
jz @f |
add dx, 8 |
@@: |
mov al, 1 |
out dx, al |
mov eax, [CURRENT_TASK] |
mov [dma_process], eax |
mov eax, [TASK_BASE] |
mov [dma_slot_ptr], eax |
cmp [hdbase], 0x1F0 |
jnz .ide1 |
mov [irq14_func], hdd_irq14 |
jmp @f |
.ide1: |
mov [irq15_func], hdd_irq15 |
@@: |
call enable_ide_int |
mov [dma_cur_sector], not 0x40 |
cmp [hdbase], 0x1F0 |
jnz .wait_ide1 |
call wait_for_sector_dma_ide0 |
jmp @f |
.wait_ide1: |
call wait_for_sector_dma_ide1 |
@@: |
cmp [hd_error], 0 |
jnz hd_write_error_dma |
pop esi |
ret |
.bad: |
inc [hd_error] |
ret |
uglobal |
IDEContrRegsBaseAddr dw ? |
endg |
; \end{Mario79} |
; \begin{diamond} |
uglobal |
bios_hdpos dd 0 ; 0 is invalid value for [hdpos] |
bios_cur_sector dd ? |
bios_read_len dd ? |
endg |
bd_read: |
push eax |
push edx |
mov edx, [bios_hdpos] |
cmp edx, [hdpos] |
jne .notread |
mov edx, [bios_cur_sector] |
cmp eax, edx |
jb .notread |
add edx, [bios_read_len] |
dec edx |
cmp eax, edx |
ja .notread |
sub eax, [bios_cur_sector] |
shl eax, 9 |
add eax, (OS_BASE+0x9A000) |
push ecx esi edi |
mov esi, eax |
shl edi, 9 |
; add edi, HD_CACHE+0x10000 |
push eax |
call calculate_cache_2 |
add edi, eax |
pop eax |
mov ecx, 512/4 |
cld |
rep movsd |
pop edi esi ecx |
pop edx |
pop eax |
ret |
.notread: |
push ecx |
mov dl, 42h |
mov ecx, 16 |
call int13_call |
pop ecx |
test eax, eax |
jnz .v86err |
test edx, edx |
jz .readerr |
mov [bios_read_len], edx |
mov edx, [hdpos] |
mov [bios_hdpos], edx |
pop edx |
pop eax |
mov [bios_cur_sector], eax |
jmp bd_read |
.readerr: |
.v86err: |
mov [hd_error], 1 |
jmp hd_read_error |
bd_write_cache_chain: |
pusha |
mov esi, [cache_chain_pos] |
shl esi, 9 |
call calculate_cache_2 |
add esi, eax |
mov edi, OS_BASE + 0x9A000 |
movzx ecx, [cache_chain_size] |
push ecx |
shl ecx, 9-2 |
rep movsd |
pop ecx |
mov dl, 43h |
mov eax, [cache_chain_ptr] |
mov eax, [eax] |
call int13_call |
test eax, eax |
jnz .v86err |
cmp edx, ecx |
jnz .writeerr |
popa |
ret |
.v86err: |
.writeerr: |
popa |
mov [hd_error], 1 |
jmp hd_write_error |
uglobal |
int13_regs_in rb v86_regs.size |
int13_regs_out rb v86_regs.size |
endg |
int13_call: |
; Because this code uses fixed addresses, |
; it can not be run simultaniously by many threads. |
; In current implementation it is protected by common mutex 'hd1_status' |
mov word [OS_BASE + 510h], 10h ; packet length |
mov word [OS_BASE + 512h], cx ; number of sectors |
mov dword [OS_BASE + 514h], 9A000000h ; buffer 9A00:0000 |
mov dword [OS_BASE + 518h], eax |
and dword [OS_BASE + 51Ch], 0 |
push ebx ecx esi edi |
mov ebx, int13_regs_in |
mov edi, ebx |
mov ecx, v86_regs.size/4 |
xor eax, eax |
rep stosd |
mov byte [ebx+v86_regs.eax+1], dl |
mov eax, [hdpos] |
lea eax, [BiosDisksData+(eax-80h)*4] |
mov dl, [eax] |
mov byte [ebx+v86_regs.edx], dl |
movzx edx, byte [eax+1] |
; mov dl, 5 |
test edx, edx |
jnz .hasirq |
dec edx |
jmp @f |
.hasirq: |
pushad |
stdcall enable_irq, edx |
popad |
@@: |
mov word [ebx+v86_regs.esi], 510h |
mov word [ebx+v86_regs.ss], 9000h |
mov word [ebx+v86_regs.esp], 0A000h |
mov word [ebx+v86_regs.eip], 500h |
mov [ebx+v86_regs.eflags], 20200h |
mov esi, [sys_v86_machine] |
mov ecx, 0x502 |
push fs |
call v86_start |
pop fs |
and [bios_hdpos], 0 |
pop edi esi ecx ebx |
movzx edx, byte [OS_BASE + 512h] |
test byte [int13_regs_out+v86_regs.eflags], 1 |
jnz @f |
mov edx, ecx |
@@: |
ret |
; \end{diamond} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/blkdev/ide_cache.inc |
---|
1,922 → 1,922 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;************************************************************************** |
; |
; [cache_ide[X]_pointer] |
; or [cache_ide[X]_data_pointer] first entry in cache list |
; |
; +0 - lba sector |
; +4 - state of cache sector |
; 0 = empty |
; 1 = used for read ( same as in hd ) |
; 2 = used for write ( differs from hd ) |
; |
; [cache_ide[X]_system_data] |
; or [cache_ide[x]_appl_data] - cache entries |
; |
;************************************************************************** |
$Revision$ |
align 4 |
write_cache: |
;----------------------------------------------------------- |
; write all changed sectors to disk |
;----------------------------------------------------------- |
push eax ecx edx esi edi |
; write difference ( 2 ) from cache to hd |
call calculate_cache |
add esi,8 |
mov edi,1 |
write_cache_more: |
cmp dword [esi+4],2 ; if cache slot is not different |
jne .write_chain |
mov dword [esi+4],1 ; same as in hd |
mov eax,[esi] ; eax = sector to write |
cmp eax,[PARTITION_START] |
jb danger |
cmp eax,[PARTITION_END] |
ja danger |
cmp [hdpos], 0x80 |
jae @f |
; DMA write is permitted only if [allow_dma_access]=1 |
cmp [allow_dma_access], 2 |
jae .nodma |
cmp [dma_hdd], 1 |
jnz .nodma |
@@: |
; ¡ê¥¤¨ï¥¬ § ¯¨áì 楯®çª¨ ¯®á«¥¤®¢ ⥫ìëå ᥪâ®à®¢ ¢ ®¤® ®¡à 饨¥ ª ¤¨áªã |
cmp ecx, 1 |
jz .nonext |
cmp dword [esi+8+4], 2 |
jnz .nonext |
push eax |
inc eax |
cmp eax, [esi+8] |
pop eax |
jnz .nonext |
cmp [cache_chain_started], 1 |
jz @f |
mov [cache_chain_started], 1 |
mov [cache_chain_size], 0 |
mov [cache_chain_pos], edi |
mov [cache_chain_ptr], esi |
@@: |
inc [cache_chain_size] |
cmp [cache_chain_size], 16 |
jnz .continue |
jmp .write_chain |
.nonext: |
call flush_cache_chain |
mov [cache_chain_size], 1 |
mov [cache_chain_ptr], esi |
call write_cache_sector |
jmp .continue |
.nodma: |
call cache_write_pio |
.write_chain: |
call flush_cache_chain |
.continue: |
danger: |
add esi,8 |
inc edi |
dec ecx |
jnz write_cache_more |
call flush_cache_chain |
return_02: |
pop edi esi edx ecx eax |
ret |
flush_cache_chain: |
cmp [cache_chain_started], 0 |
jz @f |
call write_cache_chain |
mov [cache_chain_started], 0 |
@@: |
ret |
;-------------------------------------------------------------------- |
align 4 |
find_empty_slot: |
;----------------------------------------------------------- |
; find empty or read slot, flush cache if next 10% is used by write |
; output : edi = cache slot |
;----------------------------------------------------------- |
; push ecx esi |
search_again: |
call calculate_cache_3 |
shr ecx,3 |
search_for_empty: |
inc edi |
call calculate_cache_4 |
jbe inside_cache |
mov edi,1 |
inside_cache: |
push esi |
call calculate_cache_1 |
cmp dword [edi*8+esi+4],2 |
pop esi |
jb found_slot ; it's empty or read |
dec ecx |
jnz search_for_empty |
call write_cache ; no empty slots found, write all |
cmp [hd_error],0 |
jne found_slot_access_denied |
jmp search_again ; and start again |
found_slot: |
call calculate_cache_5 |
found_slot_access_denied: |
ret |
;-------------------------------------------------------------------- |
align 4 |
clear_hd_cache: |
mov [fat_in_cache],-1 |
mov [fat_change],0 |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache: |
; mov ecx,cache_max ; entries in cache |
; mov esi,HD_CACHE+8 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos],1 |
jne .ide1 |
cmp [hdd_appl_data],0 |
jne .ide0_appl_data |
mov ecx,[cache_ide0_system_sad_size] |
mov esi,[cache_ide0_pointer] |
ret |
.ide0_appl_data: |
mov ecx,[cache_ide0_appl_sad_size] |
mov esi,[cache_ide0_data_pointer] |
ret |
.ide1: |
cmp [hdpos],2 |
jne .ide2 |
cmp [hdd_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 [hdpos],3 |
jne .ide3 |
cmp [hdd_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 [hdpos],4 |
jne .noide |
cmp [hdd_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 |
.noide: |
push eax |
mov eax,[hdpos] |
sub eax,80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax,byte [BiosDisksData+eax*4+2] |
imul eax,cache_ide1-cache_ide0 |
add eax,cache_ide0 |
jmp .get |
@@: |
imul eax,cache_ide1-cache_ide0 |
add eax,BiosDiskCaches |
.get: |
cmp [hdd_appl_data],0 |
jne .bd_appl_data |
mov ecx,[cache_ide0_system_sad_size-cache_ide0+eax] |
mov esi,[cache_ide0_pointer-cache_ide0+eax] |
pop eax |
ret |
.bd_appl_data: |
mov ecx,[cache_ide0_appl_sad_size-cache_ide0+eax] |
mov esi,[cache_ide0_data_pointer-cache_ide0+eax] |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_1: |
; lea esi,[edi*8+HD_CACHE] |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos],1 |
jne .ide1 |
cmp [hdd_appl_data],0 |
jne .ide0_appl_data |
mov esi,[cache_ide0_pointer] |
ret |
.ide0_appl_data: |
mov esi,[cache_ide0_data_pointer] |
ret |
.ide1: |
cmp [hdpos],2 |
jne .ide2 |
cmp [hdd_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 [hdpos],3 |
jne .ide3 |
cmp [hdd_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 [hdpos],4 |
jne .noide |
cmp [hdd_appl_data],0 |
jne .ide3_appl_data |
mov esi,[cache_ide3_pointer] |
ret |
.ide3_appl_data: |
mov esi,[cache_ide3_data_pointer] |
ret |
.noide: |
push eax |
mov eax,[hdpos] |
sub eax,80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax,byte [BiosDisksData+eax*4+2] |
imul eax,cache_ide1-cache_ide0 |
add eax,cache_ide0 |
jmp .get |
@@: |
imul eax,cache_ide1-cache_ide0 |
add eax,BiosDiskCaches |
.get: |
cmp [hdd_appl_data],0 |
jne .bd_appl_data |
mov esi,[cache_ide0_pointer-cache_ide0+eax] |
pop eax |
ret |
.bd_appl_data: |
mov esi,[cache_ide0_data_pointer-cache_ide0+eax] |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_2: |
; add esi,HD_CACHE+65536 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos],1 |
jne .ide1 |
cmp [hdd_appl_data],0 |
jne .ide0_appl_data |
mov eax,[cache_ide0_system_data] |
ret |
.ide0_appl_data: |
mov eax,[cache_ide0_appl_data] |
ret |
.ide1: |
cmp [hdpos],2 |
jne .ide2 |
cmp [hdd_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 [hdpos],3 |
jne .ide3 |
cmp [hdd_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 [hdpos],4 |
jne .noide |
cmp [hdd_appl_data],0 |
jne .ide3_appl_data |
mov eax,[cache_ide3_system_data] |
ret |
.ide3_appl_data: |
mov eax,[cache_ide3_appl_data] |
ret |
.noide: |
mov eax,[hdpos] |
sub eax,80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax,byte [BiosDisksData+eax*4+2] |
imul eax,cache_ide1-cache_ide0 |
add eax,cache_ide0 |
jmp .get |
@@: |
imul eax,cache_ide1-cache_ide0 |
add eax,BiosDiskCaches |
.get: |
cmp [hdd_appl_data],0 |
jne .bd_appl_data |
mov eax,[cache_ide0_system_data-cache_ide0+eax] |
ret |
.bd_appl_data: |
mov eax,[cache_ide0_appl_data-cache_ide0+eax] |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_3: |
; mov ecx,cache_max*10/100 |
; mov edi,[cache_search_start] |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos],1 |
jne .ide1 |
cmp [hdd_appl_data],0 |
jne .ide0_appl_data |
mov ecx,[cache_ide0_system_sad_size] |
mov edi,[cache_ide0_search_start] |
ret |
.ide0_appl_data: |
mov ecx,[cache_ide0_appl_sad_size] |
mov edi,[cache_ide0_appl_search_start] |
ret |
.ide1: |
cmp [hdpos],2 |
jne .ide2 |
cmp [hdd_appl_data],0 |
jne .ide1_appl_data |
mov ecx,[cache_ide1_system_sad_size] |
mov edi,[cache_ide1_search_start] |
ret |
.ide1_appl_data: |
mov ecx,[cache_ide1_appl_sad_size] |
mov edi,[cache_ide1_appl_search_start] |
ret |
.ide2: |
cmp [hdpos],3 |
jne .ide3 |
cmp [hdd_appl_data],0 |
jne .ide2_appl_data |
mov ecx,[cache_ide2_system_sad_size] |
mov edi,[cache_ide2_search_start] |
ret |
.ide2_appl_data: |
mov ecx,[cache_ide2_appl_sad_size] |
mov edi,[cache_ide2_appl_search_start] |
ret |
.ide3: |
cmp [hdpos],4 |
jne .noide |
cmp [hdd_appl_data],0 |
jne .ide3_appl_data |
mov ecx,[cache_ide3_system_sad_size] |
mov edi,[cache_ide3_search_start] |
ret |
.ide3_appl_data: |
mov ecx,[cache_ide3_appl_sad_size] |
mov edi,[cache_ide3_appl_search_start] |
ret |
.noide: |
push eax |
mov eax,[hdpos] |
sub eax,80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax,byte [BiosDisksData+eax*4+2] |
imul eax,cache_ide1-cache_ide0 |
add eax,cache_ide0 |
jmp .get |
@@: |
imul eax,cache_ide1-cache_ide0 |
add eax,BiosDiskCaches |
.get: |
cmp [hdd_appl_data],0 |
jne .bd_appl_data |
mov ecx,[cache_ide0_system_sad_size-cache_ide0+eax] |
mov edi,[cache_ide0_search_start-cache_ide0+eax] |
pop eax |
ret |
.bd_appl_data: |
mov ecx,[cache_ide0_appl_sad_size-cache_ide0+eax] |
mov edi,[cache_ide0_appl_search_start-cache_ide0+eax] |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_4: |
; cmp edi,cache_max |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos],1 |
jne .ide1 |
cmp [hdd_appl_data],0 |
jne .ide0_appl_data |
cmp edi,[cache_ide0_system_sad_size] |
ret |
.ide0_appl_data: |
cmp edi,[cache_ide0_appl_sad_size] |
ret |
.ide1: |
cmp [hdpos],2 |
jne .ide2 |
cmp [hdd_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 [hdpos],3 |
jne .ide3 |
cmp [hdd_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 [hdpos],4 |
jne .noide |
cmp [hdd_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 |
.noide: |
push eax |
mov eax,[hdpos] |
sub eax,80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax,byte [BiosDisksData+eax*4+2] |
imul eax,cache_ide1-cache_ide0 |
add eax,cache_ide0 |
jmp .get |
@@: |
imul eax,cache_ide1-cache_ide0 |
add eax,BiosDiskCaches |
.get: |
cmp [hdd_appl_data],0 |
jne .bd_appl_data |
cmp edi,[cache_ide0_system_sad_size-cache_ide0+eax] |
pop eax |
ret |
.bd_appl_data: |
cmp edi,[cache_ide0_appl_sad_size-cache_ide0+eax] |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_5: |
; mov [cache_search_start],edi |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos],1 |
jne .ide1 |
cmp [hdd_appl_data],0 |
jne .ide0_appl_data |
mov [cache_ide0_search_start],edi |
ret |
.ide0_appl_data: |
mov [cache_ide0_appl_search_start],edi |
ret |
.ide1: |
cmp [hdpos],2 |
jne .ide2 |
cmp [hdd_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 [hdpos],3 |
jne .ide3 |
cmp [hdd_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 [hdpos],4 |
jne .noide |
cmp [hdd_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 |
.noide: |
push eax |
mov eax,[hdpos] |
sub eax,80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax,byte [BiosDisksData+eax*4+2] |
imul eax,cache_ide1-cache_ide0 |
add eax,cache_ide0 |
jmp .get |
@@: |
imul eax,cache_ide1-cache_ide0 |
add eax,BiosDiskCaches |
.get: |
cmp [hdd_appl_data],0 |
jne .bd_appl_data |
mov [cache_ide0_search_start-cache_ide0+eax],edi |
pop eax |
ret |
.bd_appl_data: |
mov [cache_ide0_appl_search_start-cache_ide0+eax],edi |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
find_empty_slot_CD_cache: |
;----------------------------------------------------------- |
; find empty or read slot, flush cache if next 10% is used by write |
; output : edi = cache slot |
;----------------------------------------------------------- |
.search_again: |
call cd_calculate_cache_3 |
.search_for_empty: |
inc edi |
call cd_calculate_cache_4 |
jbe .inside_cache |
mov edi,1 |
.inside_cache: |
call cd_calculate_cache_5 |
ret |
;-------------------------------------------------------------------- |
clear_CD_cache: |
pusha |
.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] |
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] |
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 |
rep stosd |
ret |
;-------------------------------------------------------------------- |
align 4 |
cd_calculate_cache: |
; mov ecx,cache_max ; entries in cache |
; mov esi,HD_CACHE+8 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [cdpos],1 |
jne .ide1 |
cmp [cd_appl_data],0 |
jne .ide0_appl_data |
mov ecx,[cache_ide0_system_sad_size] |
mov esi,[cache_ide0_pointer] |
ret |
.ide0_appl_data: |
mov ecx,[cache_ide0_appl_sad_size] |
mov esi,[cache_ide0_data_pointer] |
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: |
; lea esi,[edi*8+HD_CACHE] |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [cdpos],1 |
jne .ide1 |
cmp [cd_appl_data],0 |
jne .ide0_appl_data |
mov esi,[cache_ide0_pointer] |
ret |
.ide0_appl_data: |
mov esi,[cache_ide0_data_pointer] |
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: |
; add esi,HD_CACHE+65536 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [cdpos],1 |
jne .ide1 |
cmp [cd_appl_data],0 |
jne .ide0_appl_data |
mov eax,[cache_ide0_system_data] |
ret |
.ide0_appl_data: |
mov eax,[cache_ide0_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 ... 4 - IDE3 |
.ide0: |
cmp [cdpos],1 |
jne .ide1 |
cmp [cd_appl_data],0 |
jne .ide0_appl_data |
mov edi,[cache_ide0_search_start] |
ret |
.ide0_appl_data: |
mov edi,[cache_ide0_appl_search_start] |
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 |
cmp [cd_appl_data],0 |
jne .ide0_appl_data |
cmp edi,[cache_ide0_system_sad_size] |
ret |
.ide0_appl_data: |
cmp edi,[cache_ide0_appl_sad_size] |
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 |
cmp [cd_appl_data],0 |
jne .ide0_appl_data |
mov [cache_ide0_search_start],edi |
ret |
.ide0_appl_data: |
mov [cache_ide0_appl_search_start],edi |
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 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;************************************************************************** |
; |
; [cache_ide[X]_pointer] |
; or [cache_ide[X]_data_pointer] first entry in cache list |
; |
; +0 - lba sector |
; +4 - state of cache sector |
; 0 = empty |
; 1 = used for read ( same as in hd ) |
; 2 = used for write ( differs from hd ) |
; |
; [cache_ide[X]_system_data] |
; or [cache_ide[x]_appl_data] - cache entries |
; |
;************************************************************************** |
$Revision$ |
align 4 |
write_cache: |
;----------------------------------------------------------- |
; write all changed sectors to disk |
;----------------------------------------------------------- |
push eax ecx edx esi edi |
; write difference ( 2 ) from cache to hd |
call calculate_cache |
add esi, 8 |
mov edi, 1 |
write_cache_more: |
cmp dword [esi+4], 2; if cache slot is not different |
jne .write_chain |
mov dword [esi+4], 1; same as in hd |
mov eax, [esi] ; eax = sector to write |
cmp eax, [PARTITION_START] |
jb danger |
cmp eax, [PARTITION_END] |
ja danger |
cmp [hdpos], 0x80 |
jae @f |
; DMA write is permitted only if [allow_dma_access]=1 |
cmp [allow_dma_access], 2 |
jae .nodma |
cmp [dma_hdd], 1 |
jnz .nodma |
@@: |
; ¡ê¥¤¨ï¥¬ § ¯¨áì 楯®çª¨ ¯®á«¥¤®¢ ⥫ìëå ᥪâ®à®¢ ¢ ®¤® ®¡à 饨¥ ª ¤¨áªã |
cmp ecx, 1 |
jz .nonext |
cmp dword [esi+8+4], 2 |
jnz .nonext |
push eax |
inc eax |
cmp eax, [esi+8] |
pop eax |
jnz .nonext |
cmp [cache_chain_started], 1 |
jz @f |
mov [cache_chain_started], 1 |
mov [cache_chain_size], 0 |
mov [cache_chain_pos], edi |
mov [cache_chain_ptr], esi |
@@: |
inc [cache_chain_size] |
cmp [cache_chain_size], 16 |
jnz .continue |
jmp .write_chain |
.nonext: |
call flush_cache_chain |
mov [cache_chain_size], 1 |
mov [cache_chain_ptr], esi |
call write_cache_sector |
jmp .continue |
.nodma: |
call cache_write_pio |
.write_chain: |
call flush_cache_chain |
.continue: |
danger: |
add esi, 8 |
inc edi |
dec ecx |
jnz write_cache_more |
call flush_cache_chain |
return_02: |
pop edi esi edx ecx eax |
ret |
flush_cache_chain: |
cmp [cache_chain_started], 0 |
jz @f |
call write_cache_chain |
mov [cache_chain_started], 0 |
@@: |
ret |
;-------------------------------------------------------------------- |
align 4 |
find_empty_slot: |
;----------------------------------------------------------- |
; find empty or read slot, flush cache if next 10% is used by write |
; output : edi = cache slot |
;----------------------------------------------------------- |
; push ecx esi |
search_again: |
call calculate_cache_3 |
shr ecx, 3 |
search_for_empty: |
inc edi |
call calculate_cache_4 |
jbe inside_cache |
mov edi, 1 |
inside_cache: |
push esi |
call calculate_cache_1 |
cmp dword [edi*8+esi+4], 2 |
pop esi |
jb found_slot ; it's empty or read |
dec ecx |
jnz search_for_empty |
call write_cache ; no empty slots found, write all |
cmp [hd_error], 0 |
jne found_slot_access_denied |
jmp search_again ; and start again |
found_slot: |
call calculate_cache_5 |
found_slot_access_denied: |
ret |
;-------------------------------------------------------------------- |
align 4 |
clear_hd_cache: |
mov [fat_in_cache], -1 |
mov [fat_change], 0 |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache: |
; mov ecx,cache_max ; entries in cache |
; mov esi,HD_CACHE+8 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos], 1 |
jne .ide1 |
cmp [hdd_appl_data], 0 |
jne .ide0_appl_data |
mov ecx, [cache_ide0_system_sad_size] |
mov esi, [cache_ide0_pointer] |
ret |
.ide0_appl_data: |
mov ecx, [cache_ide0_appl_sad_size] |
mov esi, [cache_ide0_data_pointer] |
ret |
.ide1: |
cmp [hdpos], 2 |
jne .ide2 |
cmp [hdd_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 [hdpos], 3 |
jne .ide3 |
cmp [hdd_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 [hdpos], 4 |
jne .noide |
cmp [hdd_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 |
.noide: |
push eax |
mov eax, [hdpos] |
sub eax, 80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax, byte [BiosDisksData+eax*4+2] |
imul eax, cache_ide1-cache_ide0 |
add eax, cache_ide0 |
jmp .get |
@@: |
imul eax, cache_ide1-cache_ide0 |
add eax, BiosDiskCaches |
.get: |
cmp [hdd_appl_data], 0 |
jne .bd_appl_data |
mov ecx, [cache_ide0_system_sad_size-cache_ide0+eax] |
mov esi, [cache_ide0_pointer-cache_ide0+eax] |
pop eax |
ret |
.bd_appl_data: |
mov ecx, [cache_ide0_appl_sad_size-cache_ide0+eax] |
mov esi, [cache_ide0_data_pointer-cache_ide0+eax] |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_1: |
; lea esi,[edi*8+HD_CACHE] |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos], 1 |
jne .ide1 |
cmp [hdd_appl_data], 0 |
jne .ide0_appl_data |
mov esi, [cache_ide0_pointer] |
ret |
.ide0_appl_data: |
mov esi, [cache_ide0_data_pointer] |
ret |
.ide1: |
cmp [hdpos], 2 |
jne .ide2 |
cmp [hdd_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 [hdpos], 3 |
jne .ide3 |
cmp [hdd_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 [hdpos], 4 |
jne .noide |
cmp [hdd_appl_data], 0 |
jne .ide3_appl_data |
mov esi, [cache_ide3_pointer] |
ret |
.ide3_appl_data: |
mov esi, [cache_ide3_data_pointer] |
ret |
.noide: |
push eax |
mov eax, [hdpos] |
sub eax, 80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax, byte [BiosDisksData+eax*4+2] |
imul eax, cache_ide1-cache_ide0 |
add eax, cache_ide0 |
jmp .get |
@@: |
imul eax, cache_ide1-cache_ide0 |
add eax, BiosDiskCaches |
.get: |
cmp [hdd_appl_data], 0 |
jne .bd_appl_data |
mov esi, [cache_ide0_pointer-cache_ide0+eax] |
pop eax |
ret |
.bd_appl_data: |
mov esi, [cache_ide0_data_pointer-cache_ide0+eax] |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_2: |
; add esi,HD_CACHE+65536 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos], 1 |
jne .ide1 |
cmp [hdd_appl_data], 0 |
jne .ide0_appl_data |
mov eax, [cache_ide0_system_data] |
ret |
.ide0_appl_data: |
mov eax, [cache_ide0_appl_data] |
ret |
.ide1: |
cmp [hdpos], 2 |
jne .ide2 |
cmp [hdd_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 [hdpos], 3 |
jne .ide3 |
cmp [hdd_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 [hdpos], 4 |
jne .noide |
cmp [hdd_appl_data], 0 |
jne .ide3_appl_data |
mov eax, [cache_ide3_system_data] |
ret |
.ide3_appl_data: |
mov eax, [cache_ide3_appl_data] |
ret |
.noide: |
mov eax, [hdpos] |
sub eax, 80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax, byte [BiosDisksData+eax*4+2] |
imul eax, cache_ide1-cache_ide0 |
add eax, cache_ide0 |
jmp .get |
@@: |
imul eax, cache_ide1-cache_ide0 |
add eax, BiosDiskCaches |
.get: |
cmp [hdd_appl_data], 0 |
jne .bd_appl_data |
mov eax, [cache_ide0_system_data-cache_ide0+eax] |
ret |
.bd_appl_data: |
mov eax, [cache_ide0_appl_data-cache_ide0+eax] |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_3: |
; mov ecx,cache_max*10/100 |
; mov edi,[cache_search_start] |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos], 1 |
jne .ide1 |
cmp [hdd_appl_data], 0 |
jne .ide0_appl_data |
mov ecx, [cache_ide0_system_sad_size] |
mov edi, [cache_ide0_search_start] |
ret |
.ide0_appl_data: |
mov ecx, [cache_ide0_appl_sad_size] |
mov edi, [cache_ide0_appl_search_start] |
ret |
.ide1: |
cmp [hdpos], 2 |
jne .ide2 |
cmp [hdd_appl_data], 0 |
jne .ide1_appl_data |
mov ecx, [cache_ide1_system_sad_size] |
mov edi, [cache_ide1_search_start] |
ret |
.ide1_appl_data: |
mov ecx, [cache_ide1_appl_sad_size] |
mov edi, [cache_ide1_appl_search_start] |
ret |
.ide2: |
cmp [hdpos], 3 |
jne .ide3 |
cmp [hdd_appl_data], 0 |
jne .ide2_appl_data |
mov ecx, [cache_ide2_system_sad_size] |
mov edi, [cache_ide2_search_start] |
ret |
.ide2_appl_data: |
mov ecx, [cache_ide2_appl_sad_size] |
mov edi, [cache_ide2_appl_search_start] |
ret |
.ide3: |
cmp [hdpos], 4 |
jne .noide |
cmp [hdd_appl_data], 0 |
jne .ide3_appl_data |
mov ecx, [cache_ide3_system_sad_size] |
mov edi, [cache_ide3_search_start] |
ret |
.ide3_appl_data: |
mov ecx, [cache_ide3_appl_sad_size] |
mov edi, [cache_ide3_appl_search_start] |
ret |
.noide: |
push eax |
mov eax, [hdpos] |
sub eax, 80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax, byte [BiosDisksData+eax*4+2] |
imul eax, cache_ide1-cache_ide0 |
add eax, cache_ide0 |
jmp .get |
@@: |
imul eax, cache_ide1-cache_ide0 |
add eax, BiosDiskCaches |
.get: |
cmp [hdd_appl_data], 0 |
jne .bd_appl_data |
mov ecx, [cache_ide0_system_sad_size-cache_ide0+eax] |
mov edi, [cache_ide0_search_start-cache_ide0+eax] |
pop eax |
ret |
.bd_appl_data: |
mov ecx, [cache_ide0_appl_sad_size-cache_ide0+eax] |
mov edi, [cache_ide0_appl_search_start-cache_ide0+eax] |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_4: |
; cmp edi,cache_max |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos], 1 |
jne .ide1 |
cmp [hdd_appl_data], 0 |
jne .ide0_appl_data |
cmp edi, [cache_ide0_system_sad_size] |
ret |
.ide0_appl_data: |
cmp edi, [cache_ide0_appl_sad_size] |
ret |
.ide1: |
cmp [hdpos], 2 |
jne .ide2 |
cmp [hdd_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 [hdpos], 3 |
jne .ide3 |
cmp [hdd_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 [hdpos], 4 |
jne .noide |
cmp [hdd_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 |
.noide: |
push eax |
mov eax, [hdpos] |
sub eax, 80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax, byte [BiosDisksData+eax*4+2] |
imul eax, cache_ide1-cache_ide0 |
add eax, cache_ide0 |
jmp .get |
@@: |
imul eax, cache_ide1-cache_ide0 |
add eax, BiosDiskCaches |
.get: |
cmp [hdd_appl_data], 0 |
jne .bd_appl_data |
cmp edi, [cache_ide0_system_sad_size-cache_ide0+eax] |
pop eax |
ret |
.bd_appl_data: |
cmp edi, [cache_ide0_appl_sad_size-cache_ide0+eax] |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_5: |
; mov [cache_search_start],edi |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos], 1 |
jne .ide1 |
cmp [hdd_appl_data], 0 |
jne .ide0_appl_data |
mov [cache_ide0_search_start], edi |
ret |
.ide0_appl_data: |
mov [cache_ide0_appl_search_start], edi |
ret |
.ide1: |
cmp [hdpos], 2 |
jne .ide2 |
cmp [hdd_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 [hdpos], 3 |
jne .ide3 |
cmp [hdd_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 [hdpos], 4 |
jne .noide |
cmp [hdd_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 |
.noide: |
push eax |
mov eax, [hdpos] |
sub eax, 80h |
cmp byte [BiosDisksData+eax*4+2], -1 |
jz @f |
movzx eax, byte [BiosDisksData+eax*4+2] |
imul eax, cache_ide1-cache_ide0 |
add eax, cache_ide0 |
jmp .get |
@@: |
imul eax, cache_ide1-cache_ide0 |
add eax, BiosDiskCaches |
.get: |
cmp [hdd_appl_data], 0 |
jne .bd_appl_data |
mov [cache_ide0_search_start-cache_ide0+eax], edi |
pop eax |
ret |
.bd_appl_data: |
mov [cache_ide0_appl_search_start-cache_ide0+eax], edi |
pop eax |
ret |
;-------------------------------------------------------------------- |
align 4 |
find_empty_slot_CD_cache: |
;----------------------------------------------------------- |
; find empty or read slot, flush cache if next 10% is used by write |
; output : edi = cache slot |
;----------------------------------------------------------- |
.search_again: |
call cd_calculate_cache_3 |
.search_for_empty: |
inc edi |
call cd_calculate_cache_4 |
jbe .inside_cache |
mov edi, 1 |
.inside_cache: |
call cd_calculate_cache_5 |
ret |
;-------------------------------------------------------------------- |
clear_CD_cache: |
pusha |
.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] |
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] |
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 |
rep stosd |
ret |
;-------------------------------------------------------------------- |
align 4 |
cd_calculate_cache: |
; mov ecx,cache_max ; entries in cache |
; mov esi,HD_CACHE+8 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [cdpos], 1 |
jne .ide1 |
cmp [cd_appl_data], 0 |
jne .ide0_appl_data |
mov ecx, [cache_ide0_system_sad_size] |
mov esi, [cache_ide0_pointer] |
ret |
.ide0_appl_data: |
mov ecx, [cache_ide0_appl_sad_size] |
mov esi, [cache_ide0_data_pointer] |
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: |
; lea esi,[edi*8+HD_CACHE] |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [cdpos], 1 |
jne .ide1 |
cmp [cd_appl_data], 0 |
jne .ide0_appl_data |
mov esi, [cache_ide0_pointer] |
ret |
.ide0_appl_data: |
mov esi, [cache_ide0_data_pointer] |
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: |
; add esi,HD_CACHE+65536 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [cdpos], 1 |
jne .ide1 |
cmp [cd_appl_data], 0 |
jne .ide0_appl_data |
mov eax, [cache_ide0_system_data] |
ret |
.ide0_appl_data: |
mov eax, [cache_ide0_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 ... 4 - IDE3 |
.ide0: |
cmp [cdpos], 1 |
jne .ide1 |
cmp [cd_appl_data], 0 |
jne .ide0_appl_data |
mov edi, [cache_ide0_search_start] |
ret |
.ide0_appl_data: |
mov edi, [cache_ide0_appl_search_start] |
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 |
cmp [cd_appl_data], 0 |
jne .ide0_appl_data |
cmp edi, [cache_ide0_system_sad_size] |
ret |
.ide0_appl_data: |
cmp edi, [cache_ide0_appl_sad_size] |
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 |
cmp [cd_appl_data], 0 |
jne .ide0_appl_data |
mov [cache_ide0_search_start], edi |
ret |
.ide0_appl_data: |
mov [cache_ide0_appl_search_start], edi |
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 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/blkdev/rd.inc |
---|
1,2272 → 1,2273 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; RAMDISK functions ;; |
;; (C) 2004 Ville Turjanmaa, License: GPL ;; |
;; Addings by M.Lisovin ;; |
;; LFN support by diamond ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; calculate fat chain |
calculatefatchain: |
pushad |
mov esi,RAMDISK+512 |
mov edi,RAMDISK_FAT |
fcnew: |
mov eax,dword [esi] |
mov ebx,dword [esi+4] |
mov ecx,dword [esi+8] |
mov edx,ecx |
shr edx,4 ;8 ok |
shr dx,4 ;7 ok |
xor ch,ch |
shld ecx,ebx,20 ;6 ok |
shr cx,4 ;5 ok |
shld ebx,eax,12 |
and ebx,0x0fffffff ;4 ok |
shr bx,4 ;3 ok |
shl eax,4 |
and eax,0x0fffffff ;2 ok |
shr ax,4 ;1 ok |
mov dword [edi],eax |
mov dword [edi+4],ebx |
mov dword [edi+8],ecx |
mov dword [edi+12],edx |
add edi,16 |
add esi,12 |
cmp edi,RAMDISK_FAT+2856*2 ;2849 clusters |
jnz fcnew |
popad |
ret |
restorefatchain: ; restore fat chain |
pushad |
mov esi,RAMDISK_FAT |
mov edi,RAMDISK+512 |
fcnew2: |
mov eax,dword [esi] |
mov ebx,dword [esi+4] |
shl ax,4 |
shl eax,4 |
shl bx,4 |
shr ebx,4 |
shrd eax,ebx,8 |
shr ebx,8 |
mov dword [edi],eax |
mov word [edi+4],bx |
add edi,6 |
add esi,8 |
cmp edi,RAMDISK+512+4278 ;4274 bytes - all used FAT |
jb fcnew2 |
mov esi,RAMDISK+512 ; duplicate fat chain |
mov edi,RAMDISK+512+0x1200 |
mov ecx,1069 ;4274/4 |
cld |
rep movsd |
popad |
ret |
ramdisk_free_space: |
;--------------------------------------------- |
; |
; returns free space in edi |
; rewr.by Mihasik |
;--------------------------------------------- |
push eax ebx ecx |
mov edi,RAMDISK_FAT ;start of FAT |
xor ax,ax ;Free cluster=0x0000 in FAT |
xor ebx,ebx ;counter |
mov ecx,2849 ;2849 clusters |
cld |
rdfs1: |
repne scasw |
jnz rdfs2 ;if last cluster not 0 |
inc ebx |
test ecx, ecx |
jnz rdfs1 |
rdfs2: |
shl ebx,9 ;free clusters*512 |
mov edi,ebx |
pop ecx ebx eax |
ret |
expand_filename: |
;--------------------------------------------- |
; |
; exapand filename with '.' to 11 character |
; eax - pointer to filename |
;--------------------------------------------- |
push esi edi ebx |
mov edi,esp ; check for '.' in the name |
add edi,12+8 |
mov esi,eax |
mov eax,edi |
mov [eax+0],dword ' ' |
mov [eax+4],dword ' ' |
mov [eax+8],dword ' ' |
flr1: |
cmp [esi],byte '.' |
jne flr2 |
mov edi,eax |
add edi,7 |
jmp flr3 |
flr2: |
mov bl,[esi] |
mov [edi],bl |
flr3: |
inc esi |
inc edi |
mov ebx,eax |
add ebx,11 |
cmp edi,ebx |
jbe flr1 |
pop ebx edi esi |
ret |
fileread: |
;---------------------------------------------------------------- |
; |
; fileread - sys floppy |
; |
; eax points to filename 11 chars |
; ebx first wanted block ; 1+ ; if 0 then set to 1 |
; ecx number of blocks to read ; 1+ ; if 0 then set to 1 |
; edx mem location to return data |
; esi length of filename 12*X 0=root |
; |
; ret ebx = size or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
test ebx,ebx ;if ebx=0 - set to 1 |
jnz frfl5 |
inc ebx |
frfl5: |
test ecx,ecx ;if ecx=0 - set to 1 |
jnz frfl6 |
inc ecx |
frfl6: |
test esi,esi ; return ramdisk root |
jnz fr_noroot ;if not root |
cmp ebx,14 ;14 clusters=root dir |
ja oorr |
cmp ecx,14 |
ja oorr |
jmp fr_do |
oorr: |
mov eax,5 ;out of root range (fnf) |
xor ebx,ebx |
dec ebx ;0xffffffff |
ret |
fr_do: ;reading rootdir |
mov edi,edx |
dec ebx |
push edx |
mov edx,ecx |
add edx,ebx |
cmp edx,15 ;ebx+ecx=14+1 |
pushf |
jbe fr_do1 |
sub edx,14 |
sub ecx,edx |
fr_do1: |
shl ebx,9 |
mov esi,RAMDISK+512*19 |
add esi,ebx |
shl ecx,7 |
cld |
rep movsd |
popf |
pop edx |
jae fr_do2 |
xor eax,eax ; ok read |
xor ebx,ebx |
ret |
fr_do2: ;if last cluster |
mov eax,6 ;end of file |
xor ebx,ebx |
ret |
fr_noroot: |
sub esp,32 |
call expand_filename |
dec ebx |
push eax |
push eax ebx ecx edx esi edi |
call rd_findfile |
je fifound |
add esp,32+28 ;if file not found |
ret |
fifound: |
mov ebx,[edi-11+28] ;file size |
mov [esp+20],ebx |
mov [esp+24],ebx |
add edi,0xf |
movzx eax,word [edi] |
mov edi,eax ;edi=cluster |
frnew: |
add eax,31 ;bootsector+2*fat+filenames |
shl eax,9 ;*512 |
add eax,RAMDISK ;image base |
mov ebx,[esp+8] |
mov ecx,512 ;[esp+4] |
cmp [esp+16],dword 0 ; wanted cluster ? |
jne frfl7 |
call memmove |
add [esp+8],dword 512 |
dec dword [esp+12] ; last wanted cluster ? |
je frnoread |
jmp frfl8 |
frfl7: |
dec dword [esp+16] |
frfl8: |
movzx eax,word [edi*2+RAMDISK_FAT] ; find next cluster from FAT |
mov edi,eax |
cmp edi,4095 ;eof - cluster |
jz frnoread2 |
cmp [esp+24],dword 512 ;eof - size |
jb frnoread |
sub [esp+24],dword 512 |
jmp frnew |
frnoread2: |
cmp [esp+16],dword 0 ; eof without read ? |
je frnoread |
pop edi esi edx ecx |
add esp,4 |
pop ebx ; ebx <- eax : size of file |
add esp,36 |
mov eax,6 ; end of file |
ret |
frnoread: |
pop edi esi edx ecx |
add esp,4 |
pop ebx ; ebx <- eax : size of file |
add esp,36 |
xor eax,eax ;read ok |
ret |
rd_findfile: |
;by Mihasik |
;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx |
mov edi,RAMDISK+512*18+512 ;Point at directory |
cld |
rd_newsearch: |
mov esi,eax |
mov ecx,11 |
rep cmpsb |
je rd_ff |
add cl,21 |
add edi,ecx |
cmp edi,RAMDISK+512*33 |
jb rd_newsearch |
mov eax,5 ;if file not found - eax=5 |
xor ebx,ebx |
dec ebx ;ebx=0xffffffff and zf=0 |
rd_ff: |
ret |
; \begin{diamond} |
uni2ansi_str: |
; convert UNICODE zero-terminated string to ASCII-string (codepage 866) |
; in: esi->source, edi->buffer (may be esi=edi) |
; destroys: eax,esi,edi |
lodsw |
test ax, ax |
jz .done |
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, 'ð' |
jmp .doit |
.yo2: |
mov al, 'ñ' |
jmp .doit |
.rus1: |
; 0x410-0x43F -> 0x80-0xAF |
add al, 0x70 |
jmp .doit |
.rus2: |
; 0x440-0x44F -> 0xE0-0xEF |
add al, 0xA0 |
.ascii: |
.doit: |
stosb |
jmp uni2ansi_str |
.done: |
mov byte [edi], 0 |
ret |
ansi2uni_char: |
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding |
mov ah, 0 |
; 0x00-0x7F - trivial map |
cmp al, 0x80 |
jb .ret |
; 0x80-0xAF -> 0x410-0x43F |
cmp al, 0xB0 |
jae @f |
add ax, 0x410-0x80 |
.ret: |
ret |
@@: |
; 0xE0-0xEF -> 0x440-0x44F |
cmp al, 0xE0 |
jb .unk |
cmp al, 0xF0 |
jae @f |
add ax, 0x440-0xE0 |
ret |
; 0xF0 -> 0x401 |
; 0xF1 -> 0x451 |
@@: |
cmp al, 'ð' |
jz .yo1 |
cmp al, 'ñ' |
jz .yo2 |
.unk: |
mov al, '_' ; ah=0 |
ret |
.yo1: |
mov ax, 0x401 |
ret |
.yo2: |
mov ax, 0x451 |
ret |
char_toupper: |
; convert character to uppercase, using cp866 encoding |
; in: al=symbol |
; out: al=converted symbol |
cmp al, 'a' |
jb .ret |
cmp al, 'z' |
jbe .az |
cmp al, 'ñ' |
jz .yo1 |
cmp al, ' ' |
jb .ret |
cmp al, 'à' |
jb .rus1 |
cmp al, 'ï' |
ja .ret |
; 0xE0-0xEF -> 0x90-0x9F |
sub al, 'à'-'' |
.ret: |
ret |
.rus1: |
; 0xA0-0xAF -> 0x80-0x8F |
.az: |
and al, not 0x20 |
ret |
.yo1: |
; 0xF1 -> 0xF0 |
dec ax |
ret |
fat_get_name: |
; in: edi->FAT entry |
; out: CF=1 - no valid entry |
; else CF=0 and ebp->ASCIIZ-name |
; (maximum length of filename is 255 (wide) symbols without trailing 0, |
; but implementation requires buffer 261 words) |
; destroys eax |
cmp byte [edi], 0 |
jz .no |
cmp byte [edi], 0xE5 |
jnz @f |
.no: |
stc |
ret |
@@: |
cmp byte [edi+11], 0xF |
jz .longname |
test byte [edi+11], 8 |
jnz .no |
push ecx |
push edi ebp |
test byte [ebp-4], 1 |
jnz .unicode_short |
mov eax, [edi] |
mov ecx, [edi+4] |
mov [ebp], eax |
mov [ebp+4], ecx |
mov ecx, 8 |
@@: |
cmp byte [ebp+ecx-1], ' ' |
loope @b |
mov eax, [edi+8] |
cmp al, ' ' |
je .done |
shl eax, 8 |
mov al, '.' |
lea ebp, [ebp+ecx+1] |
mov [ebp], eax |
mov ecx, 3 |
@@: |
rol eax, 8 |
cmp al, ' ' |
jne .done |
loop @b |
dec ebp |
.done: |
and byte [ebp+ecx+1], 0 ; CF=0 |
pop ebp edi ecx |
ret |
.unicode_short: |
mov ecx, 8 |
push ecx |
@@: |
mov al, [edi] |
inc edi |
call ansi2uni_char |
mov [ebp], ax |
inc ebp |
inc ebp |
loop @b |
pop ecx |
@@: |
cmp word [ebp-2], ' ' |
jnz @f |
dec ebp |
dec ebp |
loop @b |
@@: |
mov word [ebp], '.' |
inc ebp |
inc ebp |
mov ecx, 3 |
push ecx |
@@: |
mov al, [edi] |
inc edi |
call ansi2uni_char |
mov [ebp], ax |
inc ebp |
inc ebp |
loop @b |
pop ecx |
@@: |
cmp word [ebp-2], ' ' |
jnz @f |
dec ebp |
dec ebp |
loop @b |
dec ebp |
dec ebp |
@@: |
and word [ebp], 0 ; CF=0 |
pop ebp edi ecx |
ret |
.longname: |
; LFN |
mov al, byte [edi] |
and eax, 0x3F |
dec eax |
cmp al, 20 |
jae .no ; ignore invalid entries |
mov word [ebp+260*2], 0 ; force null-terminating for orphans |
imul eax, 13*2 |
add ebp, eax |
test byte [edi], 0x40 |
jz @f |
mov word [ebp+13*2], 0 |
@@: |
push eax |
; now copy name from edi to ebp ... |
mov eax, [edi+1] |
mov [ebp], eax ; symbols 1,2 |
mov eax, [edi+5] |
mov [ebp+4], eax ; 3,4 |
mov eax, [edi+9] |
mov [ebp+8], ax ; 5 |
mov eax, [edi+14] |
mov [ebp+10], eax ; 6,7 |
mov eax, [edi+18] |
mov [ebp+14], eax ; 8,9 |
mov eax, [edi+22] |
mov [ebp+18], eax ; 10,11 |
mov eax, [edi+28] |
mov [ebp+22], eax ; 12,13 |
; ... done |
pop eax |
sub ebp, eax |
test eax, eax |
jz @f |
; if this is not first entry, more processing required |
stc |
ret |
@@: |
; if this is first entry: |
test byte [ebp-4], 1 |
jnz .ret |
; buffer at ebp contains UNICODE name, convert it to ANSI |
push esi edi |
mov esi, ebp |
mov edi, ebp |
call uni2ansi_str |
pop edi esi |
.ret: |
clc |
ret |
fat_compare_name: |
; compares ASCIIZ-names, case-insensitive (cp866 encoding) |
; in: esi->name, ebp->name |
; out: if names match: ZF=1 and esi->next component of name |
; else: ZF=0, esi is not changed |
; destroys eax |
push ebp esi |
.loop: |
mov al, [ebp] |
inc ebp |
call char_toupper |
push eax |
lodsb |
call char_toupper |
cmp al, [esp] |
jnz .done |
pop eax |
test al, al |
jnz .loop |
dec esi |
pop eax |
pop ebp |
xor eax, eax ; set ZF flag |
ret |
.done: |
cmp al, '/' |
jnz @f |
cmp byte [esp], 0 |
jnz @f |
mov [esp+4], esi |
@@: |
pop eax |
pop esi ebp |
ret |
fat_time_to_bdfe: |
; in: eax=FAT time |
; out: eax=BDFE time |
push ecx edx |
mov ecx, eax |
mov edx, eax |
shr eax, 11 |
shl eax, 16 ; hours |
and edx, 0x1F |
add edx, edx |
mov al, dl ; seconds |
shr ecx, 5 |
and ecx, 0x3F |
mov ah, cl ; minutes |
pop edx ecx |
ret |
fat_date_to_bdfe: |
push ecx edx |
mov ecx, eax |
mov edx, eax |
shr eax, 9 |
add ax, 1980 |
shl eax, 16 ; year |
and edx, 0x1F |
mov al, dl ; day |
shr ecx, 5 |
and ecx, 0xF |
mov ah, cl ; month |
pop edx ecx |
ret |
bdfe_to_fat_time: |
push edx |
mov edx, eax |
shr eax, 16 |
and dh, 0x3F |
shl eax, 6 |
or al, dh |
shr dl, 1 |
and dl, 0x1F |
shl eax, 5 |
or al, dl |
pop edx |
ret |
bdfe_to_fat_date: |
push edx |
mov edx, eax |
shr eax, 16 |
sub ax, 1980 |
and dh, 0xF |
shl eax, 4 |
or al, dh |
and dl, 0x1F |
shl eax, 5 |
or al, dl |
pop edx |
ret |
fat_entry_to_bdfe: |
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi |
; destroys eax |
mov eax, [ebp-4] |
mov [esi+4], eax ; ASCII/UNICODE name |
fat_entry_to_bdfe2: |
movzx eax, byte [edi+11] |
mov [esi], eax ; attributes |
movzx eax, word [edi+14] |
call fat_time_to_bdfe |
mov [esi+8], eax ; creation time |
movzx eax, word [edi+16] |
call fat_date_to_bdfe |
mov [esi+12], eax ; creation date |
and dword [esi+16], 0 ; last access time is not supported on FAT |
movzx eax, word [edi+18] |
call fat_date_to_bdfe |
mov [esi+20], eax ; last access date |
movzx eax, word [edi+22] |
call fat_time_to_bdfe |
mov [esi+24], eax ; last write time |
movzx eax, word [edi+24] |
call fat_date_to_bdfe |
mov [esi+28], eax ; last write date |
mov eax, [edi+28] |
mov [esi+32], eax ; file size (low dword) |
xor eax, eax |
mov [esi+36], eax ; file size (high dword) |
test ebp, ebp |
jz .ret |
push ecx edi |
lea edi, [esi+40] |
mov esi, ebp |
test byte [esi-4], 1 |
jz .ansi |
mov ecx, 260/2 |
rep movsd |
mov [edi-2], ax |
@@: |
mov esi, edi |
pop edi ecx |
.ret: |
ret |
.ansi: |
mov ecx, 264/4 |
rep movsd |
mov [edi-1], al |
jmp @b |
bdfe_to_fat_entry: |
; convert BDFE at edx to FAT entry at edi |
; destroys eax |
; attributes byte |
test byte [edi+11], 8 ; volume label? |
jnz @f |
mov al, [edx] |
and al, 0x27 |
and byte [edi+11], 0x10 |
or byte [edi+11], al |
@@: |
mov eax, [edx+8] |
call bdfe_to_fat_time |
mov [edi+14], ax ; creation time |
mov eax, [edx+12] |
call bdfe_to_fat_date |
mov [edi+16], ax ; creation date |
mov eax, [edx+20] |
call bdfe_to_fat_date |
mov [edi+18], ax ; last access date |
mov eax, [edx+24] |
call bdfe_to_fat_time |
mov [edi+22], ax ; last write time |
mov eax, [edx+28] |
call bdfe_to_fat_date |
mov [edi+24], ax ; last write date |
ret |
ramdisk_root_first: |
mov edi, RAMDISK+512*19 |
clc |
ret |
ramdisk_root_next: |
add edi, 0x20 |
cmp edi, RAMDISK+512*33 |
cmc |
ret |
ramdisk_root_extend_dir: |
stc |
ret |
uglobal |
; this is for delete support |
rd_prev_sector dd ? |
rd_prev_prev_sector dd ? |
endg |
ramdisk_notroot_next: |
add edi, 0x20 |
test edi, 0x1FF |
jz ramdisk_notroot_next_sector |
ret ; CF=0 |
ramdisk_notroot_next_sector: |
push ecx |
mov ecx, [eax] |
push [rd_prev_sector] |
pop [rd_prev_prev_sector] |
mov [rd_prev_sector], ecx |
mov ecx, [ecx*2+RAMDISK_FAT] |
and ecx, 0xFFF |
cmp ecx, 2849 |
jae ramdisk_notroot_first.err2 |
mov [eax], ecx |
pop ecx |
ramdisk_notroot_first: |
mov eax, [eax] |
cmp eax, 2 |
jb .err |
cmp eax, 2849 |
jae .err |
shl eax, 9 |
lea edi, [eax+(31 shl 9)+RAMDISK] |
clc |
ret |
.err2: |
pop ecx |
.err: |
stc |
ret |
ramdisk_notroot_next_write: |
test edi, 0x1FF |
jz ramdisk_notroot_next_sector |
ramdisk_root_next_write: |
ret |
ramdisk_notroot_extend_dir: |
pusha |
xor eax, eax |
mov edi, RAMDISK_FAT |
mov ecx, 2849 |
repnz scasw |
jnz .notfound |
mov word [edi-2], 0xFFF |
sub edi, RAMDISK_FAT |
shr edi, 1 |
dec edi |
mov eax, [esp+28] |
mov ecx, [eax] |
mov [RAMDISK_FAT+ecx*2], di |
mov [eax], edi |
shl edi, 9 |
add edi, (31 shl 9)+RAMDISK |
mov [esp], edi |
xor eax, eax |
mov ecx, 128 |
rep stosd |
popa |
clc |
ret |
.notfound: |
popa |
stc |
ret |
rd_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and edi->direntry |
push esi edi |
push 0 |
push ramdisk_root_first |
push ramdisk_root_next |
.loop: |
call fat_find_lfn |
jc .notfound |
cmp byte [esi], 0 |
jz .found |
.continue: |
test byte [edi+11], 10h |
jz .notfound |
movzx eax, word [edi+26] |
mov [esp+8], eax |
mov dword [esp+4], ramdisk_notroot_first |
mov dword [esp], ramdisk_notroot_next |
test eax, eax |
jnz .loop |
mov dword [esp+4], ramdisk_root_first |
mov dword [esp], ramdisk_notroot_next |
jmp .loop |
.notfound: |
add esp, 12 |
pop edi esi |
stc |
ret |
.found: |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .continue |
@@: |
mov eax, [esp+8] |
add esp, 16 ; CF=0 |
pop esi |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskRead - LFN variant for reading sys floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_RamdiskRead: |
cmp byte [esi], 0 |
jnz @f |
or ebx, -1 |
mov eax, 10 ; access denied |
ret |
@@: |
push edi |
call rd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, 5 ; file not found |
ret |
.found: |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
xor ebx, ebx |
.reteof: |
mov eax, 6 ; EOF |
pop edi |
ret |
@@: |
mov ebx, [ebx] |
.l1: |
push ecx edx |
push 0 |
mov eax, [edi+28] |
sub eax, ebx |
jb .eof |
cmp eax, ecx |
jae @f |
mov ecx, eax |
mov byte [esp], 6 ; EOF |
@@: |
movzx edi, word [edi+26] ; cluster |
.new: |
jecxz .done |
test edi, edi |
jz .eof |
cmp edi, 0xFF8 |
jae .eof |
lea eax, [edi+31] ; bootsector+2*fat+filenames |
shl eax, 9 ; *512 |
add eax, RAMDISK ; image base |
; now eax points to data of cluster |
sub ebx, 512 |
jae .skip |
lea eax, [eax+ebx+512] |
neg ebx |
push ecx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
mov ebx, edx |
call memmove |
add edx, ecx |
sub [esp], ecx |
pop ecx |
xor ebx, ebx |
.skip: |
movzx edi, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT |
jmp .new |
.eof: |
mov ebx, edx |
pop eax edx ecx |
sub ebx, edx |
jmp .reteof |
.done: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskReadFolder - LFN variant for reading sys floppy folder |
; |
; esi points to filename; only root is folder on ramdisk |
; ebx pointer to structure 32-bit number = first wanted block |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = size or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_RamdiskReadFolder: |
push edi |
cmp byte [esi], 0 |
jz .root |
call rd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 |
jnz .found_dir |
pop edi |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
movzx eax, word [edi+26] |
add eax, 31 |
push 0 |
jmp .doit |
.root: |
mov eax, 19 |
push 14 |
.doit: |
push esi ecx ebp |
sub esp, 262*2 ; reserve space for LFN |
mov ebp, esp |
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names |
mov ebx, [ebx] |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
mov byte [edx], 1 ; version |
pop ecx eax |
mov esi, edi ; esi points to block of data of folder entry (BDFE) |
.main_loop: |
mov edi, eax |
shl edi, 9 |
add edi, RAMDISK |
push eax |
.l1: |
call fat_get_name |
jc .l2 |
cmp byte [edi+11], 0xF |
jnz .do_bdfe |
add edi, 0x20 |
test edi, 0x1FF |
jnz .do_bdfe |
pop eax |
inc eax |
dec byte [esp+262*2+16] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+RAMDISK_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+16], 0 |
@@: |
mov edi, eax |
shl edi, 9 |
add edi, RAMDISK |
push eax |
.do_bdfe: |
inc dword [edx+8] ; new file found |
dec ebx |
jns .l2 |
dec ecx |
js .l2 |
inc dword [edx+4] ; new file block copied |
call fat_entry_to_bdfe |
.l2: |
add edi, 0x20 |
test edi, 0x1FF |
jnz .l1 |
pop eax |
inc eax |
dec byte [esp+262*2+16] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+RAMDISK_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+16], 0 |
@@: |
jmp .main_loop |
.done: |
add esp, 262*2+4 |
pop ebp |
mov ebx, [edx+4] |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
pop ecx esi edi edi |
ret |
iglobal |
label fat_legal_chars byte |
; 0 = not allowed |
; 1 = allowed only in long names |
; 3 = allowed |
times 32 db 0 |
; ! " # $ % & ' ( ) * + , - . / |
db 1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0 |
; 0 1 2 3 4 5 6 7 8 9 : ; < = > ? |
db 3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0 |
; @ A B C D E F G H I J K L M N O |
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 |
; P Q R S T U V W X Y Z [ \ ] ^ _ |
db 3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3 |
; ` a b c d e f g h i j k l m n o |
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 |
; p q r s t u v w x y z { | } ~ |
db 3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0 |
endg |
fat_name_is_legal: |
; in: esi->(long) name |
; out: CF set <=> legal |
; destroys eax |
push esi |
xor eax, eax |
@@: |
lodsb |
test al, al |
jz .done |
cmp al, 80h |
jae .big |
test [fat_legal_chars+eax], 1 |
jnz @b |
.err: |
pop esi |
clc |
ret |
.big: |
; 0x80-0xAF, 0xE0-0xEF |
cmp al, 0xB0 |
jb @b |
cmp al, 0xE0 |
jb .err |
cmp al, 0xF0 |
jb @b |
jmp .err |
.done: |
sub esi, [esp] |
cmp esi, 257 |
pop esi |
ret |
fat_next_short_name: |
; in: edi->8+3 name |
; out: name corrected |
; CF=1 <=> error |
pushad |
mov ecx, 8 |
mov al, '~' |
std |
push edi |
add edi, 7 |
repnz scasb |
pop edi |
cld |
jz .tilde |
; tilde is not found, insert "~1" at end |
add edi, 6 |
cmp word [edi], ' ' |
jnz .insert_tilde |
@@: dec edi |
cmp byte [edi], ' ' |
jz @b |
inc edi |
.insert_tilde: |
mov word [edi], '~1' |
popad |
clc |
ret |
.tilde: |
push edi |
add edi, 7 |
xor ecx, ecx |
@@: |
; after tilde may be only digits and trailing spaces |
cmp byte [edi], '~' |
jz .break |
cmp byte [edi], ' ' |
jz .space |
cmp byte [edi], '9' |
jnz .found |
dec edi |
jmp @b |
.space: |
dec edi |
inc ecx |
jmp @b |
.found: |
inc byte [edi] |
add dword [esp], 8 |
jmp .zerorest |
.break: |
jecxz .noplace |
inc edi |
mov al, '1' |
@@: |
xchg al, [edi] |
inc edi |
cmp al, ' ' |
mov al, '0' |
jnz @b |
.succ: |
pop edi |
popad |
clc |
ret |
.noplace: |
dec edi |
cmp edi, [esp] |
jz .err |
add dword [esp], 8 |
mov word [edi], '~1' |
inc edi |
inc edi |
@@: |
mov byte [edi], '0' |
.zerorest: |
inc edi |
cmp edi, [esp] |
jb @b |
pop edi |
popad |
;clc ; automatically |
ret |
.err: |
pop edi |
popad |
stc |
ret |
fat_gen_short_name: |
; in: esi->long name |
; edi->buffer (8+3=11 chars) |
; out: buffer filled |
pushad |
mov eax, ' ' |
push edi |
stosd |
stosd |
stosd |
pop edi |
xor eax, eax |
push 8 |
pop ebx |
lea ecx, [edi+8] |
.loop: |
lodsb |
test al, al |
jz .done |
call char_toupper |
cmp al, ' ' |
jz .space |
cmp al, 80h |
ja .big |
test [fat_legal_chars+eax], 2 |
jnz .symbol |
.inv_symbol: |
mov al, '_' |
or bh, 1 |
.symbol: |
cmp al, '.' |
jz .dot |
.normal_symbol: |
dec bl |
jns .store |
mov bl, 0 |
.space: |
or bh, 1 |
jmp .loop |
.store: |
stosb |
jmp .loop |
.big: |
cmp al, 0xB0 |
jb .normal_symbol |
cmp al, 0xE0 |
jb .inv_symbol |
cmp al, 0xF0 |
jb .normal_symbol |
jmp .inv_symbol |
.dot: |
test bh, 2 |
jz .firstdot |
pop ebx |
add ebx, edi |
sub ebx, ecx |
push ebx |
cmp ebx, ecx |
jb @f |
pop ebx |
push ecx |
@@: |
cmp edi, ecx |
jbe .skip |
@@: |
dec edi |
mov al, [edi] |
dec ebx |
mov [ebx], al |
mov byte [edi], ' ' |
cmp edi, ecx |
ja @b |
.skip: |
mov bh, 3 |
jmp @f |
.firstdot: |
cmp bl, 8 |
jz .space |
push edi |
or bh, 2 |
@@: |
mov edi, ecx |
mov bl, 3 |
jmp .loop |
.done: |
test bh, 2 |
jz @f |
pop edi |
@@: |
lea edi, [ecx-8] |
test bh, 1 |
jz @f |
call fat_next_short_name |
@@: |
popad |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskRewrite - LFN variant for writing ramdisk |
; fs_RamdiskCreateFolder - create folder on ramdisk |
; |
; esi points to file/folder name |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ (ignored for folders) |
; edx mem location to data (ignored for folders) |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
fs_RamdiskCreateFolder: |
mov al, 1 ; create folder |
jmp fs_RamdiskRewrite.common |
fs_RamdiskRewrite: |
xor eax, eax ; create file |
.common: |
cmp byte [esi], 0 |
jz @b |
pushad |
xor edi, edi |
push esi |
test ebp, ebp |
jz @f |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
lea edi, [esi-1] |
jmp @b |
@@: |
pop esi |
test edi, edi |
jnz .noroot |
test ebp, ebp |
jnz .hasebp |
push ramdisk_root_extend_dir |
push ramdisk_root_next_write |
push edi |
push ramdisk_root_first |
push ramdisk_root_next |
jmp .common1 |
.hasebp: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [ebp], 0 |
jz .ret1 |
push ebp |
xor ebp, ebp |
call rd_find_lfn |
pop esi |
jc .notfound0 |
jmp .common0 |
.noroot: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [edi+1], 0 |
jz .ret1 |
; check existence |
mov byte [edi], 0 |
push edi |
call rd_find_lfn |
pop esi |
mov byte [esi], '/' |
jnc @f |
.notfound0: |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
@@: |
inc esi |
.common0: |
test byte [edi+11], 0x10 ; must be directory |
mov eax, ERROR_ACCESS_DENIED |
jz .ret1 |
movzx ebp, word [edi+26] ; ebp=cluster |
mov eax, ERROR_FAT_TABLE |
cmp ebp, 2 |
jb .ret1 |
cmp ebp, 2849 |
jae .ret1 |
push ramdisk_notroot_extend_dir |
push ramdisk_notroot_next_write |
push ebp |
push ramdisk_notroot_first |
push ramdisk_notroot_next |
.common1: |
call fat_find_lfn |
jc .notfound |
; found |
test byte [edi+11], 10h |
jz .exists_file |
; found directory; if we are creating directory, return OK, |
; if we are creating file, say "access denied" |
add esp, 20 |
popad |
test al, al |
mov eax, ERROR_ACCESS_DENIED |
jz @f |
mov al, 0 |
@@: |
xor ebx, ebx |
ret |
.exists_file: |
; found file; if we are creating directory, return "access denied", |
; if we are creating file, delete existing file and continue |
cmp byte [esp+20+28], 0 |
jz @f |
add esp, 20 |
popad |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
@@: |
; delete FAT chain |
push edi |
xor eax, eax |
mov dword [edi+28], eax ; zero size |
xchg ax, word [edi+26] ; start cluster |
test eax, eax |
jz .done1 |
@@: |
cmp eax, 0xFF8 |
jae .done1 |
lea edi, [RAMDISK_FAT + eax*2] ; position in FAT |
xor eax, eax |
xchg ax, [edi] |
jmp @b |
.done1: |
pop edi |
call get_time_for_file |
mov [edi+22], ax |
call get_date_for_file |
mov [edi+24], ax |
mov [edi+18], ax |
or byte [edi+11], 20h ; set 'archive' attribute |
jmp .doit |
.notfound: |
; file is not found; generate short name |
call fat_name_is_legal |
jc @f |
add esp, 20 |
popad |
mov eax, ERROR_FILE_NOT_FOUND |
xor ebx, ebx |
ret |
@@: |
sub esp, 12 |
mov edi, esp |
call fat_gen_short_name |
.test_short_name_loop: |
push esi edi ecx |
mov esi, edi |
lea eax, [esp+12+12+8] |
mov [eax], ebp |
call dword [eax-4] |
jc .found |
.test_short_name_entry: |
cmp byte [edi+11], 0xF |
jz .test_short_name_cont |
mov ecx, 11 |
push esi edi |
repz cmpsb |
pop edi esi |
jz .short_name_found |
.test_short_name_cont: |
lea eax, [esp+12+12+8] |
call dword [eax-8] |
jnc .test_short_name_entry |
jmp .found |
.short_name_found: |
pop ecx edi esi |
call fat_next_short_name |
jnc .test_short_name_loop |
.disk_full: |
add esp, 12+20 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.found: |
pop ecx edi esi |
; now find space in directory |
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' |
mov al, '~' |
push ecx edi |
mov ecx, 8 |
repnz scasb |
push 1 |
pop eax ; 1 entry |
jnz .notilde |
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total |
xor eax, eax |
@@: |
cmp byte [esi], 0 |
jz @f |
inc esi |
inc eax |
jmp @b |
@@: |
sub esi, eax |
add eax, 12+13 |
mov ecx, 13 |
push edx |
cdq |
div ecx |
pop edx |
.notilde: |
push -1 |
push -1 |
; find <eax> successive entries in directory |
xor ecx, ecx |
push eax |
lea eax, [esp+12+8+12+8] |
mov [eax], ebp |
call dword [eax-4] |
pop eax |
.scan_dir: |
cmp byte [edi], 0 |
jz .free |
cmp byte [edi], 0xE5 |
jz .free |
xor ecx, ecx |
.scan_cont: |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax-8] |
pop eax |
jnc .scan_dir |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax+8] ; extend directory |
pop eax |
jnc .scan_dir |
add esp, 8+8+12+20 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.free: |
test ecx, ecx |
jnz @f |
mov [esp], edi |
mov ecx, [esp+8+8+12+8] |
mov [esp+4], ecx |
xor ecx, ecx |
@@: |
inc ecx |
cmp ecx, eax |
jb .scan_cont |
; found! |
; calculate name checksum |
push esi ecx |
mov esi, [esp+8+8] |
mov ecx, 11 |
xor eax, eax |
@@: |
ror al, 1 |
add al, [esi] |
inc esi |
loop @b |
pop ecx esi |
pop edi |
pop dword [esp+8+12+8] |
; edi points to last entry in free chunk |
dec ecx |
jz .nolfn |
push esi |
push eax |
mov al, 40h |
.writelfn: |
or al, cl |
mov esi, [esp+4] |
push ecx |
dec ecx |
imul ecx, 13 |
add esi, ecx |
stosb |
mov cl, 5 |
call .read_symbols |
mov ax, 0xF |
stosw |
mov al, [esp+4] |
stosb |
mov cl, 6 |
call .read_symbols |
xor eax, eax |
stosw |
mov cl, 2 |
call .read_symbols |
pop ecx |
lea eax, [esp+8+8+12+8] |
call dword [eax+4] ; next write |
xor eax, eax |
loop .writelfn |
pop eax |
pop esi |
.nolfn: |
xchg esi, [esp] |
mov ecx, 11 |
rep movsb |
mov word [edi], 20h ; attributes |
sub edi, 11 |
pop esi ecx |
add esp, 12 |
mov byte [edi+13], 0 ; tenths of a second at file creation time |
call get_time_for_file |
mov [edi+14], ax ; creation time |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+16], ax ; creation date |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
and word [edi+20], 0 ; high word of cluster |
and word [edi+26], 0 ; low word of cluster - to be filled |
and dword [edi+28], 0 ; file size - to be filled |
cmp byte [esp+20+28], 0 |
jz .doit |
; create directory |
mov byte [edi+11], 10h ; attributes: folder |
mov ecx, 32*2 |
mov edx, edi |
.doit: |
push edx |
push ecx |
push edi |
add edi, 26 ; edi points to low word of cluster |
push edi |
jecxz .done |
mov ecx, 2849 |
mov edi, RAMDISK_FAT |
.write_loop: |
; allocate new cluster |
xor eax, eax |
repnz scasw |
jnz .disk_full2 |
dec edi |
dec edi |
; lea eax, [edi-(RAMDISK_FAT)] |
mov eax, edi |
sub eax, RAMDISK_FAT |
shr eax, 1 ; eax = cluster |
mov word [edi], 0xFFF ; mark as last cluster |
xchg edi, [esp] |
stosw |
pop edi |
push edi |
inc ecx |
; write data |
cmp byte [esp+16+20+28], 0 |
jnz .writedir |
shl eax, 9 |
add eax, RAMDISK+31*512 |
.writefile: |
mov ebx, edx |
xchg eax, ebx |
push ecx |
mov ecx, 512 |
cmp dword [esp+12], ecx |
jae @f |
mov ecx, [esp+12] |
@@: |
call memmove |
add edx, ecx |
sub [esp+12], ecx |
pop ecx |
jnz .write_loop |
.done: |
mov ebx, edx |
pop edi edi ecx edx |
sub ebx, edx |
mov [edi+28], ebx |
add esp, 20 |
mov [esp+16], ebx |
popad |
xor eax, eax |
ret |
.disk_full2: |
mov ebx, edx |
pop edi edi ecx edx |
sub ebx, edx |
mov [edi+28], ebx |
add esp, 20 |
mov [esp+16], ebx |
popad |
push ERROR_DISK_FULL |
pop eax |
ret |
.writedir: |
mov edi, eax |
shl edi, 9 |
add edi, RAMDISK+31*512 |
mov esi, edx |
mov ecx, 32/4 |
push ecx |
rep movsd |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov word [edi-32+26], ax |
mov esi, edx |
pop ecx |
rep movsd |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov eax, [esp+16+8] |
mov word [edi-32+26], ax |
xor eax, eax |
mov ecx, (512-32*2)/4 |
rep stosd |
pop edi edi ecx edx |
add esp, 20 |
popad |
xor eax, eax |
xor ebx, ebx |
ret |
.read_symbol: |
or ax, -1 |
test esi, esi |
jz .retFFFF |
lodsb |
test al, al |
jnz ansi2uni_char |
xor eax, eax |
xor esi, esi |
.retFFFF: |
ret |
.read_symbols: |
call .read_symbol |
stosw |
loop .read_symbols |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskWrite - LFN variant for writing to sys floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
push ERROR_ACCESS_DENIED |
fs_RamdiskWrite.ret0: |
pop eax |
xor ebx, ebx |
ret |
fs_RamdiskWrite: |
cmp byte [esi], 0 |
jz @b |
pushad |
call rd_find_lfn |
jnc .found |
popad |
push ERROR_FILE_NOT_FOUND |
jmp .ret0 |
.found: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
popad |
push ERROR_ACCESS_DENIED |
jmp .ret0 |
@@: |
; FAT does not support files larger than 4GB |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
.eof: |
popad |
push ERROR_END_OF_FILE |
jmp .ret0 |
@@: |
mov ebx, [ebx] |
.l1: |
; now edi points to direntry, ebx=start byte to write, |
; ecx=number of bytes to write, edx=data pointer |
call fat_update_datetime |
; extend file if needed |
add ecx, ebx |
jc .eof ; FAT does not support files larger than 4GB |
push 0 ; return value=0 |
cmp ecx, [edi+28] |
jbe .length_ok |
cmp ecx, ebx |
jz .length_ok |
call ramdisk_extend_file |
jnc .length_ok |
; ramdisk_extend_file can return two error codes: FAT table error or disk full. |
; First case is fatal error, in second case we may write some data |
mov [esp], eax |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
.disk_full: |
; correct number of bytes to write |
mov ecx, [edi+28] |
cmp ecx, ebx |
ja .length_ok |
.ret: |
pop eax |
mov [esp+28], eax ; eax=return value |
sub edx, [esp+20] |
mov [esp+16], edx ; ebx=number of written bytes |
popad |
ret |
.length_ok: |
; now ebx=start pos, ecx=end pos, both lie inside file |
sub ecx, ebx |
jz .ret |
movzx edi, word [edi+26] ; starting cluster |
.write_loop: |
sub ebx, 0x200 |
jae .next_cluster |
push ecx |
neg ebx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
mov eax, edi |
shl eax, 9 |
add eax, RAMDISK+31*512+0x200 |
sub eax, ebx |
mov ebx, eax |
mov eax, edx |
call memmove |
xor ebx, ebx |
add edx, ecx |
sub [esp], ecx |
pop ecx |
jz .ret |
.next_cluster: |
movzx edi, word [edi*2+RAMDISK_FAT] |
jmp .write_loop |
ramdisk_extend_file.zero_size: |
xor eax, eax |
jmp ramdisk_extend_file.start_extend |
; extends file on ramdisk to given size, new data area is filled by 0 |
; in: edi->direntry, ecx=new size |
; out: CF=0 => OK, eax=0 |
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL) |
ramdisk_extend_file: |
push ecx |
; find the last cluster of file |
movzx eax, word [edi+26] ; first cluster |
mov ecx, [edi+28] |
jecxz .zero_size |
@@: |
sub ecx, 0x200 |
jbe @f |
mov eax, [eax*2+RAMDISK_FAT] |
and eax, 0xFFF |
jz .fat_err |
cmp eax, 0xFF8 |
jb @b |
.fat_err: |
pop ecx |
push ERROR_FAT_TABLE |
pop eax |
stc |
ret |
@@: |
push eax |
mov eax, [eax*2+RAMDISK_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
pop eax |
jb .fat_err |
; set length to full number of sectors and make sure that last sector is zero-padded |
sub [edi+28], ecx |
push eax edi |
mov edi, eax |
shl edi, 9 |
lea edi, [edi+RAMDISK+31*512+0x200+ecx] |
neg ecx |
xor eax, eax |
rep stosb |
pop edi eax |
.start_extend: |
pop ecx |
; now do extend |
push edx esi |
mov esi, RAMDISK_FAT+2*2 ; start scan from cluster 2 |
mov edx, 2847 ; number of clusters to scan |
.extend_loop: |
cmp [edi+28], ecx |
jae .extend_done |
; add new sector |
push ecx |
mov ecx, edx |
push edi |
mov edi, esi |
jecxz .disk_full |
push eax |
xor eax, eax |
repnz scasw |
pop eax |
jnz .disk_full |
mov word [edi-2], 0xFFF |
mov esi, edi |
mov edx, ecx |
sub edi, RAMDISK_FAT |
shr edi, 1 |
dec edi ; now edi=new cluster |
test eax, eax |
jz .first_cluster |
mov [RAMDISK_FAT+eax*2], di |
jmp @f |
.first_cluster: |
pop eax ; eax->direntry |
push eax |
mov [eax+26], di |
@@: |
push edi |
shl edi, 9 |
add edi, RAMDISK+31*512 |
xor eax, eax |
mov ecx, 512/4 |
rep stosd |
pop eax ; eax=new cluster |
pop edi ; edi->direntry |
pop ecx ; ecx=required size |
add dword [edi+28], 0x200 |
jmp .extend_loop |
.extend_done: |
mov [edi+28], ecx |
pop esi edx |
xor eax, eax ; CF=0 |
ret |
.disk_full: |
pop edi ecx |
pop esi edx |
stc |
push ERROR_DISK_FULL |
pop eax |
ret |
fat_update_datetime: |
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskSetFileEnd - set end of file on ramdisk |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_RamdiskSetFileEnd: |
cmp byte [esi], 0 |
jnz @f |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .ret |
@@: |
push edi |
call rd_find_lfn |
jnc @f |
pop edi |
push ERROR_FILE_NOT_FOUND |
.ret: |
pop eax |
ret |
@@: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
pop edi |
jmp .access_denied |
@@: |
; file size must not exceed 4Gb |
cmp dword [ebx+4], 0 |
jz @f |
pop edi |
push ERROR_END_OF_FILE |
jmp .ret |
@@: |
; set file modification date/time to current |
call fat_update_datetime |
mov eax, [ebx] |
cmp eax, [edi+28] |
jb .truncate |
ja .expand |
pop edi |
xor eax, eax |
ret |
.expand: |
push ecx |
mov ecx, eax |
call ramdisk_extend_file |
pop ecx |
pop edi |
ret |
.truncate: |
mov [edi+28], eax |
push ecx |
movzx ecx, word [edi+26] |
test eax, eax |
jz .zero_size |
; find new last sector |
@@: |
sub eax, 0x200 |
jbe @f |
movzx ecx, word [RAMDISK_FAT+ecx*2] |
jmp @b |
@@: |
; zero data at the end of last sector |
push ecx |
mov edi, ecx |
shl edi, 9 |
lea edi, [edi+RAMDISK+31*512+eax+0x200] |
mov ecx, eax |
neg ecx |
xor eax, eax |
rep stosb |
pop ecx |
; terminate FAT chain |
lea ecx, [RAMDISK_FAT+ecx+ecx] |
push dword [ecx] |
mov word [ecx], 0xFFF |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.zero_size: |
and word [edi+26], 0 |
.delete: |
; delete FAT chain starting with ecx |
; mark all clusters as free |
cmp ecx, 0xFF8 |
jae .deleted |
lea ecx, [RAMDISK_FAT+ecx+ecx] |
push dword [ecx] |
and word [ecx], 0 |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.deleted: |
pop ecx |
pop edi |
xor eax, eax |
ret |
fs_RamdiskGetFileInfo: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call rd_find_lfn |
fs_GetFileInfo_finish: |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
push esi ebp |
xor ebp, ebp |
mov esi, edx |
and dword [esi+4], 0 |
call fat_entry_to_bdfe2 |
pop ebp esi |
pop edi |
xor eax, eax |
ret |
fs_RamdiskSetFileInfo: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call rd_find_lfn |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
call bdfe_to_fat_entry |
pop edi |
xor eax, eax |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskDelete - delete file or empty folder from ramdisk |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_RamdiskDelete: |
cmp byte [esi], 0 |
jnz @f |
; cannot delete root! |
.access_denied: |
push ERROR_ACCESS_DENIED |
.pop_ret: |
pop eax |
ret |
@@: |
and [rd_prev_sector], 0 |
and [rd_prev_prev_sector], 0 |
push edi |
call rd_find_lfn |
jnc .found |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .pop_ret |
.found: |
cmp dword [edi], '. ' |
jz .access_denied2 |
cmp dword [edi], '.. ' |
jz .access_denied2 |
test byte [edi+11], 10h |
jz .dodel |
; we can delete only empty folders! |
movzx eax, word [edi+26] |
push ebx |
mov ebx, eax |
shl ebx, 9 |
add ebx, RAMDISK + 31*0x200 + 2*0x20 |
.checkempty: |
cmp byte [ebx], 0 |
jz .empty |
cmp byte [ebx], 0xE5 |
jnz .notempty |
add ebx, 0x20 |
test ebx, 0x1FF |
jnz .checkempty |
movzx eax, word [RAMDISK_FAT + eax*2] |
test eax, eax |
jz .empty |
mov ebx, eax |
shl ebx, 9 |
add ebx, RAMDISK + 31*0x200 |
jmp .checkempty |
.notempty: |
pop ebx |
.access_denied2: |
pop edi |
jmp .access_denied |
.empty: |
pop ebx |
.dodel: |
movzx eax, word [edi+26] |
; delete folder entry |
mov byte [edi], 0xE5 |
; delete LFN (if present) |
.lfndel: |
test edi, 0x1FF |
jnz @f |
cmp [rd_prev_sector], 0 |
jz @f |
cmp [rd_prev_sector], -1 |
jz .lfndone |
mov edi, [rd_prev_sector] |
push [rd_prev_prev_sector] |
pop [rd_prev_sector] |
or [rd_prev_prev_sector], -1 |
shl edi, 9 |
add edi, RAMDISK + 31*0x200 + 0x200 |
@@: |
sub edi, 0x20 |
cmp byte [edi], 0xE5 |
jz .lfndone |
cmp byte [edi+11], 0xF |
jnz .lfndone |
mov byte [edi], 0xE5 |
jmp .lfndel |
.lfndone: |
; delete FAT chain |
test eax, eax |
jz .done |
lea eax, [RAMDISK_FAT + eax*2] |
push dword [eax] |
and word [eax], 0 |
pop eax |
and eax, 0xFFF |
jmp .lfndone |
.done: |
pop edi |
xor eax, eax |
ret |
; \end{diamond} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; RAMDISK functions ;; |
;; (C) 2004 Ville Turjanmaa, License: GPL ;; |
;; Addings by M.Lisovin ;; |
;; LFN support by diamond ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; calculate fat chain |
calculatefatchain: |
pushad |
mov esi, RAMDISK+512 |
mov edi, RAMDISK_FAT |
fcnew: |
mov eax, dword [esi] |
mov ebx, dword [esi+4] |
mov ecx, dword [esi+8] |
mov edx, ecx |
shr edx, 4;8 ok |
shr dx, 4;7 ok |
xor ch, ch |
shld ecx, ebx, 20;6 ok |
shr cx, 4;5 ok |
shld ebx, eax, 12 |
and ebx, 0x0fffffff;4 ok |
shr bx, 4;3 ok |
shl eax, 4 |
and eax, 0x0fffffff;2 ok |
shr ax, 4;1 ok |
mov dword [edi], eax |
mov dword [edi+4], ebx |
mov dword [edi+8], ecx |
mov dword [edi+12], edx |
add edi, 16 |
add esi, 12 |
cmp edi, RAMDISK_FAT+2856*2;2849 clusters |
jnz fcnew |
popad |
ret |
restorefatchain: ; restore fat chain |
pushad |
mov esi, RAMDISK_FAT |
mov edi, RAMDISK+512 |
fcnew2: |
mov eax, dword [esi] |
mov ebx, dword [esi+4] |
shl ax, 4 |
shl eax, 4 |
shl bx, 4 |
shr ebx, 4 |
shrd eax, ebx, 8 |
shr ebx, 8 |
mov dword [edi], eax |
mov word [edi+4], bx |
add edi, 6 |
add esi, 8 |
cmp edi, RAMDISK+512+4278;4274 bytes - all used FAT |
jb fcnew2 |
mov esi, RAMDISK+512 ; duplicate fat chain |
mov edi, RAMDISK+512+0x1200 |
mov ecx, 1069;4274/4 |
cld |
rep movsd |
popad |
ret |
ramdisk_free_space: |
;--------------------------------------------- |
; |
; returns free space in edi |
; rewr.by Mihasik |
;--------------------------------------------- |
push eax ebx ecx |
mov edi, RAMDISK_FAT;start of FAT |
xor ax, ax;Free cluster=0x0000 in FAT |
xor ebx, ebx;counter |
mov ecx, 2849;2849 clusters |
cld |
rdfs1: |
repne scasw |
jnz rdfs2 ;if last cluster not 0 |
inc ebx |
test ecx, ecx |
jnz rdfs1 |
rdfs2: |
shl ebx, 9;free clusters*512 |
mov edi, ebx |
pop ecx ebx eax |
ret |
expand_filename: |
;--------------------------------------------- |
; |
; exapand filename with '.' to 11 character |
; eax - pointer to filename |
;--------------------------------------------- |
push esi edi ebx |
mov edi, esp ; check for '.' in the name |
add edi, 12+8 |
mov esi, eax |
mov eax, edi |
mov [eax+0], dword ' ' |
mov [eax+4], dword ' ' |
mov [eax+8], dword ' ' |
flr1: |
cmp [esi], byte '.' |
jne flr2 |
mov edi, eax |
add edi, 7 |
jmp flr3 |
flr2: |
mov bl, [esi] |
mov [edi], bl |
flr3: |
inc esi |
inc edi |
mov ebx, eax |
add ebx, 11 |
cmp edi, ebx |
jbe flr1 |
pop ebx edi esi |
ret |
fileread: |
;---------------------------------------------------------------- |
; |
; fileread - sys floppy |
; |
; eax points to filename 11 chars |
; ebx first wanted block ; 1+ ; if 0 then set to 1 |
; ecx number of blocks to read ; 1+ ; if 0 then set to 1 |
; edx mem location to return data |
; esi length of filename 12*X 0=root |
; |
; ret ebx = size or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
test ebx, ebx;if ebx=0 - set to 1 |
jnz frfl5 |
inc ebx |
frfl5: |
test ecx, ecx;if ecx=0 - set to 1 |
jnz frfl6 |
inc ecx |
frfl6: |
test esi, esi ; return ramdisk root |
jnz fr_noroot ;if not root |
cmp ebx, 14 ;14 clusters=root dir |
ja oorr |
cmp ecx, 14 |
ja oorr |
jmp fr_do |
oorr: |
mov eax, 5 ;out of root range (fnf) |
xor ebx, ebx |
dec ebx ;0xffffffff |
ret |
fr_do: ;reading rootdir |
mov edi, edx |
dec ebx |
push edx |
mov edx, ecx |
add edx, ebx |
cmp edx, 15 ;ebx+ecx=14+1 |
pushf |
jbe fr_do1 |
sub edx, 14 |
sub ecx, edx |
fr_do1: |
shl ebx, 9 |
mov esi, RAMDISK+512*19 |
add esi, ebx |
shl ecx, 7 |
cld |
rep movsd |
popf |
pop edx |
jae fr_do2 |
xor eax, eax; ok read |
xor ebx, ebx |
ret |
fr_do2: ;if last cluster |
mov eax, 6;end of file |
xor ebx, ebx |
ret |
fr_noroot: |
sub esp, 32 |
call expand_filename |
dec ebx |
push eax |
push eax ebx ecx edx esi edi |
call rd_findfile |
je fifound |
add esp, 32+28 ;if file not found |
ret |
fifound: |
mov ebx, [edi-11+28] ;file size |
mov [esp+20], ebx |
mov [esp+24], ebx |
add edi, 0xf |
movzx eax, word [edi] |
mov edi, eax ;edi=cluster |
frnew: |
add eax, 31 ;bootsector+2*fat+filenames |
shl eax, 9 ;*512 |
add eax, RAMDISK ;image base |
mov ebx, [esp+8] |
mov ecx, 512 ;[esp+4] |
cmp [esp+16], dword 0 ; wanted cluster ? |
jne frfl7 |
call memmove |
add [esp+8], dword 512 |
dec dword [esp+12] ; last wanted cluster ? |
je frnoread |
jmp frfl8 |
frfl7: |
dec dword [esp+16] |
frfl8: |
movzx eax, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT |
mov edi, eax |
cmp edi, 4095 ;eof - cluster |
jz frnoread2 |
cmp [esp+24], dword 512 ;eof - size |
jb frnoread |
sub [esp+24], dword 512 |
jmp frnew |
frnoread2: |
cmp [esp+16], dword 0 ; eof without read ? |
je frnoread |
pop edi esi edx ecx |
add esp, 4 |
pop ebx ; ebx <- eax : size of file |
add esp, 36 |
mov eax, 6 ; end of file |
ret |
frnoread: |
pop edi esi edx ecx |
add esp, 4 |
pop ebx ; ebx <- eax : size of file |
add esp, 36 |
xor eax, eax;read ok |
ret |
rd_findfile: |
;by Mihasik |
;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx |
mov edi, RAMDISK+512*18+512;Point at directory |
cld |
rd_newsearch: |
mov esi, eax |
mov ecx, 11 |
rep cmpsb |
je rd_ff |
add cl, 21 |
add edi, ecx |
cmp edi, RAMDISK+512*33 |
jb rd_newsearch |
mov eax, 5 ;if file not found - eax=5 |
xor ebx, ebx |
dec ebx ;ebx=0xffffffff and zf=0 |
rd_ff: |
ret |
; \begin{diamond} |
uni2ansi_str: |
; convert UNICODE zero-terminated string to ASCII-string (codepage 866) |
; in: esi->source, edi->buffer (may be esi=edi) |
; destroys: eax,esi,edi |
lodsw |
test ax, ax |
jz .done |
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, 'ð' |
jmp .doit |
.yo2: |
mov al, 'ñ' |
jmp .doit |
.rus1: |
; 0x410-0x43F -> 0x80-0xAF |
add al, 0x70 |
jmp .doit |
.rus2: |
; 0x440-0x44F -> 0xE0-0xEF |
add al, 0xA0 |
.ascii: |
.doit: |
stosb |
jmp uni2ansi_str |
.done: |
mov byte [edi], 0 |
ret |
ansi2uni_char: |
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding |
mov ah, 0 |
; 0x00-0x7F - trivial map |
cmp al, 0x80 |
jb .ret |
; 0x80-0xAF -> 0x410-0x43F |
cmp al, 0xB0 |
jae @f |
add ax, 0x410-0x80 |
.ret: |
ret |
@@: |
; 0xE0-0xEF -> 0x440-0x44F |
cmp al, 0xE0 |
jb .unk |
cmp al, 0xF0 |
jae @f |
add ax, 0x440-0xE0 |
ret |
; 0xF0 -> 0x401 |
; 0xF1 -> 0x451 |
@@: |
cmp al, 'ð' |
jz .yo1 |
cmp al, 'ñ' |
jz .yo2 |
.unk: |
mov al, '_' ; ah=0 |
ret |
.yo1: |
mov ax, 0x401 |
ret |
.yo2: |
mov ax, 0x451 |
ret |
char_toupper: |
; convert character to uppercase, using cp866 encoding |
; in: al=symbol |
; out: al=converted symbol |
cmp al, 'a' |
jb .ret |
cmp al, 'z' |
jbe .az |
cmp al, 'ñ' |
jz .yo1 |
cmp al, ' ' |
jb .ret |
cmp al, 'à' |
jb .rus1 |
cmp al, 'ï' |
ja .ret |
; 0xE0-0xEF -> 0x90-0x9F |
sub al, 'à'-'' |
.ret: |
ret |
.rus1: |
; 0xA0-0xAF -> 0x80-0x8F |
.az: |
and al, not 0x20 |
ret |
.yo1: |
; 0xF1 -> 0xF0 |
dec ax |
ret |
fat_get_name: |
; in: edi->FAT entry |
; out: CF=1 - no valid entry |
; else CF=0 and ebp->ASCIIZ-name |
; (maximum length of filename is 255 (wide) symbols without trailing 0, |
; but implementation requires buffer 261 words) |
; destroys eax |
cmp byte [edi], 0 |
jz .no |
cmp byte [edi], 0xE5 |
jnz @f |
.no: |
stc |
ret |
@@: |
cmp byte [edi+11], 0xF |
jz .longname |
test byte [edi+11], 8 |
jnz .no |
push ecx |
push edi ebp |
test byte [ebp-4], 1 |
jnz .unicode_short |
mov eax, [edi] |
mov ecx, [edi+4] |
mov [ebp], eax |
mov [ebp+4], ecx |
mov ecx, 8 |
@@: |
cmp byte [ebp+ecx-1], ' ' |
loope @b |
mov eax, [edi+8] |
cmp al, ' ' |
je .done |
shl eax, 8 |
mov al, '.' |
lea ebp, [ebp+ecx+1] |
mov [ebp], eax |
mov ecx, 3 |
@@: |
rol eax, 8 |
cmp al, ' ' |
jne .done |
loop @b |
dec ebp |
.done: |
and byte [ebp+ecx+1], 0 ; CF=0 |
pop ebp edi ecx |
ret |
.unicode_short: |
mov ecx, 8 |
push ecx |
@@: |
mov al, [edi] |
inc edi |
call ansi2uni_char |
mov [ebp], ax |
inc ebp |
inc ebp |
loop @b |
pop ecx |
@@: |
cmp word [ebp-2], ' ' |
jnz @f |
dec ebp |
dec ebp |
loop @b |
@@: |
mov word [ebp], '.' |
inc ebp |
inc ebp |
mov ecx, 3 |
push ecx |
@@: |
mov al, [edi] |
inc edi |
call ansi2uni_char |
mov [ebp], ax |
inc ebp |
inc ebp |
loop @b |
pop ecx |
@@: |
cmp word [ebp-2], ' ' |
jnz @f |
dec ebp |
dec ebp |
loop @b |
dec ebp |
dec ebp |
@@: |
and word [ebp], 0 ; CF=0 |
pop ebp edi ecx |
ret |
.longname: |
; LFN |
mov al, byte [edi] |
and eax, 0x3F |
dec eax |
cmp al, 20 |
jae .no ; ignore invalid entries |
mov word [ebp+260*2], 0 ; force null-terminating for orphans |
imul eax, 13*2 |
add ebp, eax |
test byte [edi], 0x40 |
jz @f |
mov word [ebp+13*2], 0 |
@@: |
push eax |
; now copy name from edi to ebp ... |
mov eax, [edi+1] |
mov [ebp], eax ; symbols 1,2 |
mov eax, [edi+5] |
mov [ebp+4], eax ; 3,4 |
mov eax, [edi+9] |
mov [ebp+8], ax ; 5 |
mov eax, [edi+14] |
mov [ebp+10], eax ; 6,7 |
mov eax, [edi+18] |
mov [ebp+14], eax ; 8,9 |
mov eax, [edi+22] |
mov [ebp+18], eax ; 10,11 |
mov eax, [edi+28] |
mov [ebp+22], eax ; 12,13 |
; ... done |
pop eax |
sub ebp, eax |
test eax, eax |
jz @f |
; if this is not first entry, more processing required |
stc |
ret |
@@: |
; if this is first entry: |
test byte [ebp-4], 1 |
jnz .ret |
; buffer at ebp contains UNICODE name, convert it to ANSI |
push esi edi |
mov esi, ebp |
mov edi, ebp |
call uni2ansi_str |
pop edi esi |
.ret: |
clc |
ret |
fat_compare_name: |
; compares ASCIIZ-names, case-insensitive (cp866 encoding) |
; in: esi->name, ebp->name |
; out: if names match: ZF=1 and esi->next component of name |
; else: ZF=0, esi is not changed |
; destroys eax |
push ebp esi |
.loop: |
mov al, [ebp] |
inc ebp |
call char_toupper |
push eax |
lodsb |
call char_toupper |
cmp al, [esp] |
jnz .done |
pop eax |
test al, al |
jnz .loop |
dec esi |
pop eax |
pop ebp |
xor eax, eax ; set ZF flag |
ret |
.done: |
cmp al, '/' |
jnz @f |
cmp byte [esp], 0 |
jnz @f |
mov [esp+4], esi |
@@: |
pop eax |
pop esi ebp |
ret |
fat_time_to_bdfe: |
; in: eax=FAT time |
; out: eax=BDFE time |
push ecx edx |
mov ecx, eax |
mov edx, eax |
shr eax, 11 |
shl eax, 16 ; hours |
and edx, 0x1F |
add edx, edx |
mov al, dl ; seconds |
shr ecx, 5 |
and ecx, 0x3F |
mov ah, cl ; minutes |
pop edx ecx |
ret |
fat_date_to_bdfe: |
push ecx edx |
mov ecx, eax |
mov edx, eax |
shr eax, 9 |
add ax, 1980 |
shl eax, 16 ; year |
and edx, 0x1F |
mov al, dl ; day |
shr ecx, 5 |
and ecx, 0xF |
mov ah, cl ; month |
pop edx ecx |
ret |
bdfe_to_fat_time: |
push edx |
mov edx, eax |
shr eax, 16 |
and dh, 0x3F |
shl eax, 6 |
or al, dh |
shr dl, 1 |
and dl, 0x1F |
shl eax, 5 |
or al, dl |
pop edx |
ret |
bdfe_to_fat_date: |
push edx |
mov edx, eax |
shr eax, 16 |
sub ax, 1980 |
and dh, 0xF |
shl eax, 4 |
or al, dh |
and dl, 0x1F |
shl eax, 5 |
or al, dl |
pop edx |
ret |
fat_entry_to_bdfe: |
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi |
; destroys eax |
mov eax, [ebp-4] |
mov [esi+4], eax ; ASCII/UNICODE name |
fat_entry_to_bdfe2: |
movzx eax, byte [edi+11] |
mov [esi], eax ; attributes |
movzx eax, word [edi+14] |
call fat_time_to_bdfe |
mov [esi+8], eax ; creation time |
movzx eax, word [edi+16] |
call fat_date_to_bdfe |
mov [esi+12], eax ; creation date |
and dword [esi+16], 0 ; last access time is not supported on FAT |
movzx eax, word [edi+18] |
call fat_date_to_bdfe |
mov [esi+20], eax ; last access date |
movzx eax, word [edi+22] |
call fat_time_to_bdfe |
mov [esi+24], eax ; last write time |
movzx eax, word [edi+24] |
call fat_date_to_bdfe |
mov [esi+28], eax ; last write date |
mov eax, [edi+28] |
mov [esi+32], eax ; file size (low dword) |
xor eax, eax |
mov [esi+36], eax ; file size (high dword) |
test ebp, ebp |
jz .ret |
push ecx edi |
lea edi, [esi+40] |
mov esi, ebp |
test byte [esi-4], 1 |
jz .ansi |
mov ecx, 260/2 |
rep movsd |
mov [edi-2], ax |
@@: |
mov esi, edi |
pop edi ecx |
.ret: |
ret |
.ansi: |
mov ecx, 264/4 |
rep movsd |
mov [edi-1], al |
jmp @b |
bdfe_to_fat_entry: |
; convert BDFE at edx to FAT entry at edi |
; destroys eax |
; attributes byte |
test byte [edi+11], 8 ; volume label? |
jnz @f |
mov al, [edx] |
and al, 0x27 |
and byte [edi+11], 0x10 |
or byte [edi+11], al |
@@: |
mov eax, [edx+8] |
call bdfe_to_fat_time |
mov [edi+14], ax ; creation time |
mov eax, [edx+12] |
call bdfe_to_fat_date |
mov [edi+16], ax ; creation date |
mov eax, [edx+20] |
call bdfe_to_fat_date |
mov [edi+18], ax ; last access date |
mov eax, [edx+24] |
call bdfe_to_fat_time |
mov [edi+22], ax ; last write time |
mov eax, [edx+28] |
call bdfe_to_fat_date |
mov [edi+24], ax ; last write date |
ret |
ramdisk_root_first: |
mov edi, RAMDISK+512*19 |
clc |
ret |
ramdisk_root_next: |
add edi, 0x20 |
cmp edi, RAMDISK+512*33 |
cmc |
ret |
ramdisk_root_extend_dir: |
stc |
ret |
uglobal |
; this is for delete support |
rd_prev_sector dd ? |
rd_prev_prev_sector dd ? |
endg |
ramdisk_notroot_next: |
add edi, 0x20 |
test edi, 0x1FF |
jz ramdisk_notroot_next_sector |
ret ; CF=0 |
ramdisk_notroot_next_sector: |
push ecx |
mov ecx, [eax] |
push [rd_prev_sector] |
pop [rd_prev_prev_sector] |
mov [rd_prev_sector], ecx |
mov ecx, [ecx*2+RAMDISK_FAT] |
and ecx, 0xFFF |
cmp ecx, 2849 |
jae ramdisk_notroot_first.err2 |
mov [eax], ecx |
pop ecx |
ramdisk_notroot_first: |
mov eax, [eax] |
cmp eax, 2 |
jb .err |
cmp eax, 2849 |
jae .err |
shl eax, 9 |
lea edi, [eax+(31 shl 9)+RAMDISK] |
clc |
ret |
.err2: |
pop ecx |
.err: |
stc |
ret |
ramdisk_notroot_next_write: |
test edi, 0x1FF |
jz ramdisk_notroot_next_sector |
ramdisk_root_next_write: |
ret |
ramdisk_notroot_extend_dir: |
pusha |
xor eax, eax |
mov edi, RAMDISK_FAT |
mov ecx, 2849 |
repnz scasw |
jnz .notfound |
mov word [edi-2], 0xFFF |
sub edi, RAMDISK_FAT |
shr edi, 1 |
dec edi |
mov eax, [esp+28] |
mov ecx, [eax] |
mov [RAMDISK_FAT+ecx*2], di |
mov [eax], edi |
shl edi, 9 |
add edi, (31 shl 9)+RAMDISK |
mov [esp], edi |
xor eax, eax |
mov ecx, 128 |
rep stosd |
popa |
clc |
ret |
.notfound: |
popa |
stc |
ret |
rd_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and edi->direntry |
push esi edi |
push 0 |
push ramdisk_root_first |
push ramdisk_root_next |
.loop: |
call fat_find_lfn |
jc .notfound |
cmp byte [esi], 0 |
jz .found |
.continue: |
test byte [edi+11], 10h |
jz .notfound |
movzx eax, word [edi+26] |
mov [esp+8], eax |
mov dword [esp+4], ramdisk_notroot_first |
mov dword [esp], ramdisk_notroot_next |
test eax, eax |
jnz .loop |
mov dword [esp+4], ramdisk_root_first |
mov dword [esp], ramdisk_notroot_next |
jmp .loop |
.notfound: |
add esp, 12 |
pop edi esi |
stc |
ret |
.found: |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .continue |
@@: |
mov eax, [esp+8] |
add esp, 16 ; CF=0 |
pop esi |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskRead - LFN variant for reading sys floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_RamdiskRead: |
cmp byte [esi], 0 |
jnz @f |
or ebx, -1 |
mov eax, 10 ; access denied |
ret |
@@: |
push edi |
call rd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, 5 ; file not found |
ret |
.found: |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
xor ebx, ebx |
.reteof: |
mov eax, 6 ; EOF |
pop edi |
ret |
@@: |
mov ebx, [ebx] |
.l1: |
push ecx edx |
push 0 |
mov eax, [edi+28] |
sub eax, ebx |
jb .eof |
cmp eax, ecx |
jae @f |
mov ecx, eax |
mov byte [esp], 6 ; EOF |
@@: |
movzx edi, word [edi+26] ; cluster |
.new: |
jecxz .done |
test edi, edi |
jz .eof |
cmp edi, 0xFF8 |
jae .eof |
lea eax, [edi+31] ; bootsector+2*fat+filenames |
shl eax, 9 ; *512 |
add eax, RAMDISK ; image base |
; now eax points to data of cluster |
sub ebx, 512 |
jae .skip |
lea eax, [eax+ebx+512] |
neg ebx |
push ecx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
mov ebx, edx |
call memmove |
add edx, ecx |
sub [esp], ecx |
pop ecx |
xor ebx, ebx |
.skip: |
movzx edi, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT |
jmp .new |
.eof: |
mov ebx, edx |
pop eax edx ecx |
sub ebx, edx |
jmp .reteof |
.done: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskReadFolder - LFN variant for reading sys floppy folder |
; |
; esi points to filename; only root is folder on ramdisk |
; ebx pointer to structure 32-bit number = first wanted block |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = size or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_RamdiskReadFolder: |
push edi |
cmp byte [esi], 0 |
jz .root |
call rd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 |
jnz .found_dir |
pop edi |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
movzx eax, word [edi+26] |
add eax, 31 |
push 0 |
jmp .doit |
.root: |
mov eax, 19 |
push 14 |
.doit: |
push esi ecx ebp |
sub esp, 262*2 ; reserve space for LFN |
mov ebp, esp |
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names |
mov ebx, [ebx] |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
mov byte [edx], 1 ; version |
pop ecx eax |
mov esi, edi ; esi points to block of data of folder entry (BDFE) |
.main_loop: |
mov edi, eax |
shl edi, 9 |
add edi, RAMDISK |
push eax |
.l1: |
call fat_get_name |
jc .l2 |
cmp byte [edi+11], 0xF |
jnz .do_bdfe |
add edi, 0x20 |
test edi, 0x1FF |
jnz .do_bdfe |
pop eax |
inc eax |
dec byte [esp+262*2+16] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+RAMDISK_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+16], 0 |
@@: |
mov edi, eax |
shl edi, 9 |
add edi, RAMDISK |
push eax |
.do_bdfe: |
inc dword [edx+8] ; new file found |
dec ebx |
jns .l2 |
dec ecx |
js .l2 |
inc dword [edx+4] ; new file block copied |
call fat_entry_to_bdfe |
.l2: |
add edi, 0x20 |
test edi, 0x1FF |
jnz .l1 |
pop eax |
inc eax |
dec byte [esp+262*2+16] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+RAMDISK_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+16], 0 |
@@: |
jmp .main_loop |
.done: |
add esp, 262*2+4 |
pop ebp |
mov ebx, [edx+4] |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
pop ecx esi edi edi |
ret |
iglobal |
label fat_legal_chars byte |
; 0 = not allowed |
; 1 = allowed only in long names |
; 3 = allowed |
times 32 db 0 |
; ! " # $ % & ' ( ) * + , - . / |
db 1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0 |
; 0 1 2 3 4 5 6 7 8 9 : ; < = > ? |
db 3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0 |
; @ A B C D E F G H I J K L M N O |
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 |
; P Q R S T U V W X Y Z [ \ ] ^ _ |
db 3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3 |
; ` a b c d e f g h i j k l m n o |
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 |
; p q r s t u v w x y z { | } ~ |
db 3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0 |
endg |
fat_name_is_legal: |
; in: esi->(long) name |
; out: CF set <=> legal |
; destroys eax |
push esi |
xor eax, eax |
@@: |
lodsb |
test al, al |
jz .done |
cmp al, 80h |
jae .big |
test [fat_legal_chars+eax], 1 |
jnz @b |
.err: |
pop esi |
clc |
ret |
.big: |
; 0x80-0xAF, 0xE0-0xEF |
cmp al, 0xB0 |
jb @b |
cmp al, 0xE0 |
jb .err |
cmp al, 0xF0 |
jb @b |
jmp .err |
.done: |
sub esi, [esp] |
cmp esi, 257 |
pop esi |
ret |
fat_next_short_name: |
; in: edi->8+3 name |
; out: name corrected |
; CF=1 <=> error |
pushad |
mov ecx, 8 |
mov al, '~' |
std |
push edi |
add edi, 7 |
repnz scasb |
pop edi |
cld |
jz .tilde |
; tilde is not found, insert "~1" at end |
add edi, 6 |
cmp word [edi], ' ' |
jnz .insert_tilde |
@@: |
dec edi |
cmp byte [edi], ' ' |
jz @b |
inc edi |
.insert_tilde: |
mov word [edi], '~1' |
popad |
clc |
ret |
.tilde: |
push edi |
add edi, 7 |
xor ecx, ecx |
@@: |
; after tilde may be only digits and trailing spaces |
cmp byte [edi], '~' |
jz .break |
cmp byte [edi], ' ' |
jz .space |
cmp byte [edi], '9' |
jnz .found |
dec edi |
jmp @b |
.space: |
dec edi |
inc ecx |
jmp @b |
.found: |
inc byte [edi] |
add dword [esp], 8 |
jmp .zerorest |
.break: |
jecxz .noplace |
inc edi |
mov al, '1' |
@@: |
xchg al, [edi] |
inc edi |
cmp al, ' ' |
mov al, '0' |
jnz @b |
.succ: |
pop edi |
popad |
clc |
ret |
.noplace: |
dec edi |
cmp edi, [esp] |
jz .err |
add dword [esp], 8 |
mov word [edi], '~1' |
inc edi |
inc edi |
@@: |
mov byte [edi], '0' |
.zerorest: |
inc edi |
cmp edi, [esp] |
jb @b |
pop edi |
popad |
;clc ; automatically |
ret |
.err: |
pop edi |
popad |
stc |
ret |
fat_gen_short_name: |
; in: esi->long name |
; edi->buffer (8+3=11 chars) |
; out: buffer filled |
pushad |
mov eax, ' ' |
push edi |
stosd |
stosd |
stosd |
pop edi |
xor eax, eax |
push 8 |
pop ebx |
lea ecx, [edi+8] |
.loop: |
lodsb |
test al, al |
jz .done |
call char_toupper |
cmp al, ' ' |
jz .space |
cmp al, 80h |
ja .big |
test [fat_legal_chars+eax], 2 |
jnz .symbol |
.inv_symbol: |
mov al, '_' |
or bh, 1 |
.symbol: |
cmp al, '.' |
jz .dot |
.normal_symbol: |
dec bl |
jns .store |
mov bl, 0 |
.space: |
or bh, 1 |
jmp .loop |
.store: |
stosb |
jmp .loop |
.big: |
cmp al, 0xB0 |
jb .normal_symbol |
cmp al, 0xE0 |
jb .inv_symbol |
cmp al, 0xF0 |
jb .normal_symbol |
jmp .inv_symbol |
.dot: |
test bh, 2 |
jz .firstdot |
pop ebx |
add ebx, edi |
sub ebx, ecx |
push ebx |
cmp ebx, ecx |
jb @f |
pop ebx |
push ecx |
@@: |
cmp edi, ecx |
jbe .skip |
@@: |
dec edi |
mov al, [edi] |
dec ebx |
mov [ebx], al |
mov byte [edi], ' ' |
cmp edi, ecx |
ja @b |
.skip: |
mov bh, 3 |
jmp @f |
.firstdot: |
cmp bl, 8 |
jz .space |
push edi |
or bh, 2 |
@@: |
mov edi, ecx |
mov bl, 3 |
jmp .loop |
.done: |
test bh, 2 |
jz @f |
pop edi |
@@: |
lea edi, [ecx-8] |
test bh, 1 |
jz @f |
call fat_next_short_name |
@@: |
popad |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskRewrite - LFN variant for writing ramdisk |
; fs_RamdiskCreateFolder - create folder on ramdisk |
; |
; esi points to file/folder name |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ (ignored for folders) |
; edx mem location to data (ignored for folders) |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
fs_RamdiskCreateFolder: |
mov al, 1 ; create folder |
jmp fs_RamdiskRewrite.common |
fs_RamdiskRewrite: |
xor eax, eax ; create file |
.common: |
cmp byte [esi], 0 |
jz @b |
pushad |
xor edi, edi |
push esi |
test ebp, ebp |
jz @f |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
lea edi, [esi-1] |
jmp @b |
@@: |
pop esi |
test edi, edi |
jnz .noroot |
test ebp, ebp |
jnz .hasebp |
push ramdisk_root_extend_dir |
push ramdisk_root_next_write |
push edi |
push ramdisk_root_first |
push ramdisk_root_next |
jmp .common1 |
.hasebp: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [ebp], 0 |
jz .ret1 |
push ebp |
xor ebp, ebp |
call rd_find_lfn |
pop esi |
jc .notfound0 |
jmp .common0 |
.noroot: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [edi+1], 0 |
jz .ret1 |
; check existence |
mov byte [edi], 0 |
push edi |
call rd_find_lfn |
pop esi |
mov byte [esi], '/' |
jnc @f |
.notfound0: |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
@@: |
inc esi |
.common0: |
test byte [edi+11], 0x10 ; must be directory |
mov eax, ERROR_ACCESS_DENIED |
jz .ret1 |
movzx ebp, word [edi+26] ; ebp=cluster |
mov eax, ERROR_FAT_TABLE |
cmp ebp, 2 |
jb .ret1 |
cmp ebp, 2849 |
jae .ret1 |
push ramdisk_notroot_extend_dir |
push ramdisk_notroot_next_write |
push ebp |
push ramdisk_notroot_first |
push ramdisk_notroot_next |
.common1: |
call fat_find_lfn |
jc .notfound |
; found |
test byte [edi+11], 10h |
jz .exists_file |
; found directory; if we are creating directory, return OK, |
; if we are creating file, say "access denied" |
add esp, 20 |
popad |
test al, al |
mov eax, ERROR_ACCESS_DENIED |
jz @f |
mov al, 0 |
@@: |
xor ebx, ebx |
ret |
.exists_file: |
; found file; if we are creating directory, return "access denied", |
; if we are creating file, delete existing file and continue |
cmp byte [esp+20+28], 0 |
jz @f |
add esp, 20 |
popad |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
@@: |
; delete FAT chain |
push edi |
xor eax, eax |
mov dword [edi+28], eax ; zero size |
xchg ax, word [edi+26] ; start cluster |
test eax, eax |
jz .done1 |
@@: |
cmp eax, 0xFF8 |
jae .done1 |
lea edi, [RAMDISK_FAT + eax*2] ; position in FAT |
xor eax, eax |
xchg ax, [edi] |
jmp @b |
.done1: |
pop edi |
call get_time_for_file |
mov [edi+22], ax |
call get_date_for_file |
mov [edi+24], ax |
mov [edi+18], ax |
or byte [edi+11], 20h ; set 'archive' attribute |
jmp .doit |
.notfound: |
; file is not found; generate short name |
call fat_name_is_legal |
jc @f |
add esp, 20 |
popad |
mov eax, ERROR_FILE_NOT_FOUND |
xor ebx, ebx |
ret |
@@: |
sub esp, 12 |
mov edi, esp |
call fat_gen_short_name |
.test_short_name_loop: |
push esi edi ecx |
mov esi, edi |
lea eax, [esp+12+12+8] |
mov [eax], ebp |
call dword [eax-4] |
jc .found |
.test_short_name_entry: |
cmp byte [edi+11], 0xF |
jz .test_short_name_cont |
mov ecx, 11 |
push esi edi |
repz cmpsb |
pop edi esi |
jz .short_name_found |
.test_short_name_cont: |
lea eax, [esp+12+12+8] |
call dword [eax-8] |
jnc .test_short_name_entry |
jmp .found |
.short_name_found: |
pop ecx edi esi |
call fat_next_short_name |
jnc .test_short_name_loop |
.disk_full: |
add esp, 12+20 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.found: |
pop ecx edi esi |
; now find space in directory |
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' |
mov al, '~' |
push ecx edi |
mov ecx, 8 |
repnz scasb |
push 1 |
pop eax ; 1 entry |
jnz .notilde |
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total |
xor eax, eax |
@@: |
cmp byte [esi], 0 |
jz @f |
inc esi |
inc eax |
jmp @b |
@@: |
sub esi, eax |
add eax, 12+13 |
mov ecx, 13 |
push edx |
cdq |
div ecx |
pop edx |
.notilde: |
push -1 |
push -1 |
; find <eax> successive entries in directory |
xor ecx, ecx |
push eax |
lea eax, [esp+12+8+12+8] |
mov [eax], ebp |
call dword [eax-4] |
pop eax |
.scan_dir: |
cmp byte [edi], 0 |
jz .free |
cmp byte [edi], 0xE5 |
jz .free |
xor ecx, ecx |
.scan_cont: |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax-8] |
pop eax |
jnc .scan_dir |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax+8] ; extend directory |
pop eax |
jnc .scan_dir |
add esp, 8+8+12+20 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.free: |
test ecx, ecx |
jnz @f |
mov [esp], edi |
mov ecx, [esp+8+8+12+8] |
mov [esp+4], ecx |
xor ecx, ecx |
@@: |
inc ecx |
cmp ecx, eax |
jb .scan_cont |
; found! |
; calculate name checksum |
push esi ecx |
mov esi, [esp+8+8] |
mov ecx, 11 |
xor eax, eax |
@@: |
ror al, 1 |
add al, [esi] |
inc esi |
loop @b |
pop ecx esi |
pop edi |
pop dword [esp+8+12+8] |
; edi points to last entry in free chunk |
dec ecx |
jz .nolfn |
push esi |
push eax |
mov al, 40h |
.writelfn: |
or al, cl |
mov esi, [esp+4] |
push ecx |
dec ecx |
imul ecx, 13 |
add esi, ecx |
stosb |
mov cl, 5 |
call .read_symbols |
mov ax, 0xF |
stosw |
mov al, [esp+4] |
stosb |
mov cl, 6 |
call .read_symbols |
xor eax, eax |
stosw |
mov cl, 2 |
call .read_symbols |
pop ecx |
lea eax, [esp+8+8+12+8] |
call dword [eax+4] ; next write |
xor eax, eax |
loop .writelfn |
pop eax |
pop esi |
.nolfn: |
xchg esi, [esp] |
mov ecx, 11 |
rep movsb |
mov word [edi], 20h ; attributes |
sub edi, 11 |
pop esi ecx |
add esp, 12 |
mov byte [edi+13], 0 ; tenths of a second at file creation time |
call get_time_for_file |
mov [edi+14], ax ; creation time |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+16], ax ; creation date |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
and word [edi+20], 0 ; high word of cluster |
and word [edi+26], 0 ; low word of cluster - to be filled |
and dword [edi+28], 0 ; file size - to be filled |
cmp byte [esp+20+28], 0 |
jz .doit |
; create directory |
mov byte [edi+11], 10h ; attributes: folder |
mov ecx, 32*2 |
mov edx, edi |
.doit: |
push edx |
push ecx |
push edi |
add edi, 26 ; edi points to low word of cluster |
push edi |
jecxz .done |
mov ecx, 2849 |
mov edi, RAMDISK_FAT |
.write_loop: |
; allocate new cluster |
xor eax, eax |
repnz scasw |
jnz .disk_full2 |
dec edi |
dec edi |
; lea eax, [edi-(RAMDISK_FAT)] |
mov eax, edi |
sub eax, RAMDISK_FAT |
shr eax, 1 ; eax = cluster |
mov word [edi], 0xFFF ; mark as last cluster |
xchg edi, [esp] |
stosw |
pop edi |
push edi |
inc ecx |
; write data |
cmp byte [esp+16+20+28], 0 |
jnz .writedir |
shl eax, 9 |
add eax, RAMDISK+31*512 |
.writefile: |
mov ebx, edx |
xchg eax, ebx |
push ecx |
mov ecx, 512 |
cmp dword [esp+12], ecx |
jae @f |
mov ecx, [esp+12] |
@@: |
call memmove |
add edx, ecx |
sub [esp+12], ecx |
pop ecx |
jnz .write_loop |
.done: |
mov ebx, edx |
pop edi edi ecx edx |
sub ebx, edx |
mov [edi+28], ebx |
add esp, 20 |
mov [esp+16], ebx |
popad |
xor eax, eax |
ret |
.disk_full2: |
mov ebx, edx |
pop edi edi ecx edx |
sub ebx, edx |
mov [edi+28], ebx |
add esp, 20 |
mov [esp+16], ebx |
popad |
push ERROR_DISK_FULL |
pop eax |
ret |
.writedir: |
mov edi, eax |
shl edi, 9 |
add edi, RAMDISK+31*512 |
mov esi, edx |
mov ecx, 32/4 |
push ecx |
rep movsd |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov word [edi-32+26], ax |
mov esi, edx |
pop ecx |
rep movsd |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov eax, [esp+16+8] |
mov word [edi-32+26], ax |
xor eax, eax |
mov ecx, (512-32*2)/4 |
rep stosd |
pop edi edi ecx edx |
add esp, 20 |
popad |
xor eax, eax |
xor ebx, ebx |
ret |
.read_symbol: |
or ax, -1 |
test esi, esi |
jz .retFFFF |
lodsb |
test al, al |
jnz ansi2uni_char |
xor eax, eax |
xor esi, esi |
.retFFFF: |
ret |
.read_symbols: |
call .read_symbol |
stosw |
loop .read_symbols |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskWrite - LFN variant for writing to sys floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
push ERROR_ACCESS_DENIED |
fs_RamdiskWrite.ret0: |
pop eax |
xor ebx, ebx |
ret |
fs_RamdiskWrite: |
cmp byte [esi], 0 |
jz @b |
pushad |
call rd_find_lfn |
jnc .found |
popad |
push ERROR_FILE_NOT_FOUND |
jmp .ret0 |
.found: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
popad |
push ERROR_ACCESS_DENIED |
jmp .ret0 |
@@: |
; FAT does not support files larger than 4GB |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
.eof: |
popad |
push ERROR_END_OF_FILE |
jmp .ret0 |
@@: |
mov ebx, [ebx] |
.l1: |
; now edi points to direntry, ebx=start byte to write, |
; ecx=number of bytes to write, edx=data pointer |
call fat_update_datetime |
; extend file if needed |
add ecx, ebx |
jc .eof ; FAT does not support files larger than 4GB |
push 0 ; return value=0 |
cmp ecx, [edi+28] |
jbe .length_ok |
cmp ecx, ebx |
jz .length_ok |
call ramdisk_extend_file |
jnc .length_ok |
; ramdisk_extend_file can return two error codes: FAT table error or disk full. |
; First case is fatal error, in second case we may write some data |
mov [esp], eax |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
.disk_full: |
; correct number of bytes to write |
mov ecx, [edi+28] |
cmp ecx, ebx |
ja .length_ok |
.ret: |
pop eax |
mov [esp+28], eax ; eax=return value |
sub edx, [esp+20] |
mov [esp+16], edx ; ebx=number of written bytes |
popad |
ret |
.length_ok: |
; now ebx=start pos, ecx=end pos, both lie inside file |
sub ecx, ebx |
jz .ret |
movzx edi, word [edi+26] ; starting cluster |
.write_loop: |
sub ebx, 0x200 |
jae .next_cluster |
push ecx |
neg ebx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
mov eax, edi |
shl eax, 9 |
add eax, RAMDISK+31*512+0x200 |
sub eax, ebx |
mov ebx, eax |
mov eax, edx |
call memmove |
xor ebx, ebx |
add edx, ecx |
sub [esp], ecx |
pop ecx |
jz .ret |
.next_cluster: |
movzx edi, word [edi*2+RAMDISK_FAT] |
jmp .write_loop |
ramdisk_extend_file.zero_size: |
xor eax, eax |
jmp ramdisk_extend_file.start_extend |
; extends file on ramdisk to given size, new data area is filled by 0 |
; in: edi->direntry, ecx=new size |
; out: CF=0 => OK, eax=0 |
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL) |
ramdisk_extend_file: |
push ecx |
; find the last cluster of file |
movzx eax, word [edi+26] ; first cluster |
mov ecx, [edi+28] |
jecxz .zero_size |
@@: |
sub ecx, 0x200 |
jbe @f |
mov eax, [eax*2+RAMDISK_FAT] |
and eax, 0xFFF |
jz .fat_err |
cmp eax, 0xFF8 |
jb @b |
.fat_err: |
pop ecx |
push ERROR_FAT_TABLE |
pop eax |
stc |
ret |
@@: |
push eax |
mov eax, [eax*2+RAMDISK_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
pop eax |
jb .fat_err |
; set length to full number of sectors and make sure that last sector is zero-padded |
sub [edi+28], ecx |
push eax edi |
mov edi, eax |
shl edi, 9 |
lea edi, [edi+RAMDISK+31*512+0x200+ecx] |
neg ecx |
xor eax, eax |
rep stosb |
pop edi eax |
.start_extend: |
pop ecx |
; now do extend |
push edx esi |
mov esi, RAMDISK_FAT+2*2 ; start scan from cluster 2 |
mov edx, 2847 ; number of clusters to scan |
.extend_loop: |
cmp [edi+28], ecx |
jae .extend_done |
; add new sector |
push ecx |
mov ecx, edx |
push edi |
mov edi, esi |
jecxz .disk_full |
push eax |
xor eax, eax |
repnz scasw |
pop eax |
jnz .disk_full |
mov word [edi-2], 0xFFF |
mov esi, edi |
mov edx, ecx |
sub edi, RAMDISK_FAT |
shr edi, 1 |
dec edi ; now edi=new cluster |
test eax, eax |
jz .first_cluster |
mov [RAMDISK_FAT+eax*2], di |
jmp @f |
.first_cluster: |
pop eax ; eax->direntry |
push eax |
mov [eax+26], di |
@@: |
push edi |
shl edi, 9 |
add edi, RAMDISK+31*512 |
xor eax, eax |
mov ecx, 512/4 |
rep stosd |
pop eax ; eax=new cluster |
pop edi ; edi->direntry |
pop ecx ; ecx=required size |
add dword [edi+28], 0x200 |
jmp .extend_loop |
.extend_done: |
mov [edi+28], ecx |
pop esi edx |
xor eax, eax ; CF=0 |
ret |
.disk_full: |
pop edi ecx |
pop esi edx |
stc |
push ERROR_DISK_FULL |
pop eax |
ret |
fat_update_datetime: |
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskSetFileEnd - set end of file on ramdisk |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_RamdiskSetFileEnd: |
cmp byte [esi], 0 |
jnz @f |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .ret |
@@: |
push edi |
call rd_find_lfn |
jnc @f |
pop edi |
push ERROR_FILE_NOT_FOUND |
.ret: |
pop eax |
ret |
@@: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
pop edi |
jmp .access_denied |
@@: |
; file size must not exceed 4Gb |
cmp dword [ebx+4], 0 |
jz @f |
pop edi |
push ERROR_END_OF_FILE |
jmp .ret |
@@: |
; set file modification date/time to current |
call fat_update_datetime |
mov eax, [ebx] |
cmp eax, [edi+28] |
jb .truncate |
ja .expand |
pop edi |
xor eax, eax |
ret |
.expand: |
push ecx |
mov ecx, eax |
call ramdisk_extend_file |
pop ecx |
pop edi |
ret |
.truncate: |
mov [edi+28], eax |
push ecx |
movzx ecx, word [edi+26] |
test eax, eax |
jz .zero_size |
; find new last sector |
@@: |
sub eax, 0x200 |
jbe @f |
movzx ecx, word [RAMDISK_FAT+ecx*2] |
jmp @b |
@@: |
; zero data at the end of last sector |
push ecx |
mov edi, ecx |
shl edi, 9 |
lea edi, [edi+RAMDISK+31*512+eax+0x200] |
mov ecx, eax |
neg ecx |
xor eax, eax |
rep stosb |
pop ecx |
; terminate FAT chain |
lea ecx, [RAMDISK_FAT+ecx+ecx] |
push dword [ecx] |
mov word [ecx], 0xFFF |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.zero_size: |
and word [edi+26], 0 |
.delete: |
; delete FAT chain starting with ecx |
; mark all clusters as free |
cmp ecx, 0xFF8 |
jae .deleted |
lea ecx, [RAMDISK_FAT+ecx+ecx] |
push dword [ecx] |
and word [ecx], 0 |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.deleted: |
pop ecx |
pop edi |
xor eax, eax |
ret |
fs_RamdiskGetFileInfo: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call rd_find_lfn |
fs_GetFileInfo_finish: |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
push esi ebp |
xor ebp, ebp |
mov esi, edx |
and dword [esi+4], 0 |
call fat_entry_to_bdfe2 |
pop ebp esi |
pop edi |
xor eax, eax |
ret |
fs_RamdiskSetFileInfo: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call rd_find_lfn |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
call bdfe_to_fat_entry |
pop edi |
xor eax, eax |
ret |
;---------------------------------------------------------------- |
; |
; fs_RamdiskDelete - delete file or empty folder from ramdisk |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_RamdiskDelete: |
cmp byte [esi], 0 |
jnz @f |
; cannot delete root! |
.access_denied: |
push ERROR_ACCESS_DENIED |
.pop_ret: |
pop eax |
ret |
@@: |
and [rd_prev_sector], 0 |
and [rd_prev_prev_sector], 0 |
push edi |
call rd_find_lfn |
jnc .found |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .pop_ret |
.found: |
cmp dword [edi], '. ' |
jz .access_denied2 |
cmp dword [edi], '.. ' |
jz .access_denied2 |
test byte [edi+11], 10h |
jz .dodel |
; we can delete only empty folders! |
movzx eax, word [edi+26] |
push ebx |
mov ebx, eax |
shl ebx, 9 |
add ebx, RAMDISK + 31*0x200 + 2*0x20 |
.checkempty: |
cmp byte [ebx], 0 |
jz .empty |
cmp byte [ebx], 0xE5 |
jnz .notempty |
add ebx, 0x20 |
test ebx, 0x1FF |
jnz .checkempty |
movzx eax, word [RAMDISK_FAT + eax*2] |
test eax, eax |
jz .empty |
mov ebx, eax |
shl ebx, 9 |
add ebx, RAMDISK + 31*0x200 |
jmp .checkempty |
.notempty: |
pop ebx |
.access_denied2: |
pop edi |
jmp .access_denied |
.empty: |
pop ebx |
.dodel: |
movzx eax, word [edi+26] |
; delete folder entry |
mov byte [edi], 0xE5 |
; delete LFN (if present) |
.lfndel: |
test edi, 0x1FF |
jnz @f |
cmp [rd_prev_sector], 0 |
jz @f |
cmp [rd_prev_sector], -1 |
jz .lfndone |
mov edi, [rd_prev_sector] |
push [rd_prev_prev_sector] |
pop [rd_prev_sector] |
or [rd_prev_prev_sector], -1 |
shl edi, 9 |
add edi, RAMDISK + 31*0x200 + 0x200 |
@@: |
sub edi, 0x20 |
cmp byte [edi], 0xE5 |
jz .lfndone |
cmp byte [edi+11], 0xF |
jnz .lfndone |
mov byte [edi], 0xE5 |
jmp .lfndel |
.lfndone: |
; delete FAT chain |
test eax, eax |
jz .done |
lea eax, [RAMDISK_FAT + eax*2] |
push dword [eax] |
and word [eax], 0 |
pop eax |
and eax, 0xFFF |
jmp .lfndone |
.done: |
pop edi |
xor eax, eax |
ret |
; \end{diamond} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/blkdev/rdsave.inc |
---|
1,30 → 1,30 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
saverd_fileinfo: |
dd 2 ; subfunction: write |
dd 0 ; (reserved) |
dd 0 ; (reserved) |
dd 1440*1024 ; size 1440 Kb |
dd RAMDISK |
db 0 |
.name: |
dd ? |
endg |
sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only) |
call restorefatchain |
mov ebx, saverd_fileinfo |
mov [saverd_fileinfo.name], ecx |
pushad |
call file_system_lfn ;in ebx |
popad |
mov [esp+32], eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
saverd_fileinfo: |
dd 2 ; subfunction: write |
dd 0 ; (reserved) |
dd 0 ; (reserved) |
dd 1440*1024 ; size 1440 Kb |
dd RAMDISK |
db 0 |
.name: |
dd ? |
endg |
sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only) |
call restorefatchain |
mov ebx, saverd_fileinfo |
mov [saverd_fileinfo.name], ecx |
pushad |
call file_system_lfn ;in ebx |
popad |
mov [esp+32], eax |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/bootcode.inc |
---|
1,1370 → 1,1377 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; BOOTCODE.INC ;; |
;; ;; |
;; KolibriOS 16-bit loader, ;; |
;; based on bootcode for MenuetOS ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;========================================================================== |
; |
; 16 BIT FUNCTIONS |
; |
;========================================================================== |
putchar: |
; in: al=character |
mov ah, 0Eh |
mov bh, 0 |
int 10h |
ret |
print: |
; in: si->string |
mov al, 186 |
call putchar |
mov al, ' ' |
call putchar |
printplain: |
; in: si->string |
pusha |
lodsb |
@@: |
call putchar |
lodsb |
test al,al |
jnz @b |
popa |
ret |
getkey: |
; get number in range [bl,bh] (bl,bh in ['0'..'9']) |
; in: bx=range |
; out: ax=digit (1..9, 10 for 0) |
mov ah, 0 |
int 16h |
cmp al, bl |
jb getkey |
cmp al, bh |
ja getkey |
push ax |
call putchar |
pop ax |
and ax, 0Fh |
jnz @f |
mov al, 10 |
@@: |
ret |
setcursor: |
; in: dl=column, dh=row |
mov ah, 2 |
mov bh, 0 |
int 10h |
ret |
macro _setcursor row,column |
{ |
mov dx, row*256 + column |
call setcursor |
} |
boot_read_floppy: |
push si |
xor si, si |
mov ah, 2 ; read |
@@: |
push ax |
int 0x13 |
pop ax |
jnc @f |
inc si |
cmp si, 10 |
jb @b |
sayerr_badsect: |
mov si, badsect |
sayerr_plain: |
call printplain |
jmp $ |
@@: |
pop si |
ret |
; convert abs. sector number (AX) to BIOS T:H:S |
; sector number = (abs.sector%BPB_SecPerTrk)+1 |
; pre.track number = (abs.sector/BPB_SecPerTrk) |
; head number = pre.track number%BPB_NumHeads |
; track number = pre.track number/BPB_NumHeads |
; Return: cl - sector number |
; ch - track number |
; dl - drive number (0 = a:) |
; dh - head number |
conv_abs_to_THS: |
push bx |
mov bx,word [BPB_SecPerTrk] |
xor dx,dx |
div bx |
inc dx |
mov cl, dl ; cl = sector number |
mov bx,word [BPB_NumHeads] |
xor dx,dx |
div bx |
; !!!!!!! ax = track number, dx = head number |
mov ch,al ; ch=track number |
xchg dh,dl ; dh=head number |
mov dl,0 ; dl=0 (drive 0 (a:)) |
pop bx |
retn |
; needed variables |
BPB_SecPerTrk dw 0 ; sectors per track |
BPB_NumHeads dw 0 ; number of heads |
BPB_FATSz16 dw 0 ; size of FAT |
BPB_RootEntCnt dw 0 ; count of root dir. entries |
BPB_BytsPerSec dw 0 ; bytes per sector |
BPB_RsvdSecCnt dw 0 ; number of reserved sectors |
BPB_TotSec16 dw 0 ; count of the sectors on the volume |
BPB_SecPerClus db 0 ; number of sectors per cluster |
BPB_NumFATs db 0 ; number of FAT tables |
abs_sector_adj dw 0 ; adjustment to make abs. sector number |
end_of_FAT dw 0 ; end of FAT table |
FirstDataSector dw 0 ; begin of data |
;========================================================================= |
; |
; 16 BIT CODE |
; |
;========================================================================= |
include 'bootvesa.inc' ;Include source for boot vesa |
if defined extended_primary_loader |
include 'parsers.inc' |
end if |
start_of_code: |
if defined extended_primary_loader |
; save data from primary loader |
mov word [cs:bootcallback], si |
mov word [cs:bootcallback+2], ds |
push cs |
pop ds |
mov [bootdevice], ax |
mov [bootfs], bx |
; set up stack |
mov ax, 3000h |
mov ss, ax |
mov sp, 0EC00h |
; try to load configuration file |
mov ax, 1 |
mov di, config_file_struct |
call [bootcallback] |
cld |
push cs |
pop es |
; bx=0 - ok, bx=1 - part of file loaded, assume this is ok |
cmp bx, 1 |
ja .config_bad |
; configuration file was loaded, parse |
; if length is too big, use first 0FFFFh bytes |
test dx, dx |
jz @f |
mov ax, 0FFFFh |
@@: |
; ds:si will be pointer to current data, dx = limit |
xchg ax, dx |
push 4000h |
pop ds |
xor si, si |
.parse_loop: |
; skip spaces |
cmp si, dx |
jae .parse_done |
lodsb |
cmp al, ' ' |
jbe .parse_loop |
dec si |
; loop over all possible configuration values |
mov bx, config_file_variables |
.find_variant: |
; get length |
mov cx, [es:bx] |
; zero length = end of list |
jecxz .find_newline |
; skip over length |
inc bx |
inc bx |
mov di, bx |
; skip over string |
add bx, cx |
; test whether we have at least cx symbols left |
mov ax, cx |
add ax, si |
jc .next_variant1 |
cmp ax, dx |
jae .next_variant1 |
; save current position |
push si |
; compare strings |
repz cmpsb |
jnz .next_variant2 |
; strings are equal; look for "=" with possible spaces before and after |
@@: |
cmp si, dx |
jae .next_variant2 |
lodsb |
cmp al, ' ' |
jbe @b |
cmp al, '=' |
jnz .next_variant2 |
; ok, we found the true variant |
; ignore saved position on the stack |
pop ax |
; call the parser |
call word [es:bx] |
; line parsed, find next |
.find_newline: |
cmp si, dx |
jae .parse_done |
lodsb |
cmp al, 13 |
jz .parse_loop |
cmp al, 10 |
jz .parse_loop |
jmp .find_newline |
.next_variant2: |
; continue to the next variant, restoring current position |
pop si |
.next_variant1: |
; continue to the next variant |
; skip over the parser |
inc bx |
inc bx |
jmp .find_variant |
.parse_done: |
.config_bad: |
; set up segment registers |
push cs |
pop ds |
else |
cld |
; \begin{diamond}[02.12.2005] |
; if bootloader sets ax = 'KL', then ds:si points to loader block |
cmp ax, 'KL' |
jnz @f |
mov word [cs:cfgmanager.loader_block], si |
mov word [cs:cfgmanager.loader_block+2], ds |
@@: |
; \end{diamond}[02.12.2005] |
; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk |
; (see comment to bx_from_load) |
cmp cx, 'HA' |
jnz no_hd_load |
cmp dx,'RD' |
jnz no_hd_load |
mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007] |
no_hd_load: |
; set up stack |
mov ax, 3000h |
mov ss, ax |
mov sp, 0EC00h |
; set up segment registers |
push cs |
pop ds |
push cs |
pop es |
end if |
; set videomode |
mov ax, 3 |
int 0x10 |
if lang eq ru |
; Load & set russian VGA font (RU.INC) |
mov bp, RU_FNT1 ; RU_FNT1 - First part |
mov bx, 1000h ; 768 bytes |
mov cx, 30h ; 48 symbols |
mov dx, 80h ; 128 - position of first symbol |
mov ax, 1100h |
int 10h |
mov bp, RU_FNT2 ; RU_FNT2 -Second part |
mov bx, 1000h ; 512 bytes |
mov cx, 20h ; 32 symbols |
mov dx, 0E0h ; 224 - position of first symbol |
mov ax, 1100h |
int 10h |
; End set VGA russian font |
else if lang eq et |
mov bp, ET_FNT ; ET_FNT1 |
mov bx, 1000h ; |
mov cx, 255 ; 256 symbols |
xor dx, dx ; 0 - position of first symbol |
mov ax, 1100h |
int 10h |
end if |
; draw frames |
push 0xb800 |
pop es |
xor di, di |
mov ah, 1*16+15 |
; draw top |
mov si, d80x25_top |
mov cx, d80x25_top_num * 80 |
@@: |
lodsb |
stosw |
loop @b |
; draw spaces |
mov si, space_msg |
mov dx, 25 - d80x25_top_num - d80x25_bottom_num |
dfl1: |
push si |
mov cx, 80 |
@@: |
lodsb |
stosw |
loop @b |
pop si |
dec dx |
jnz dfl1 |
; draw bottom |
mov si, d80x25_bottom |
mov cx, d80x25_bottom_num * 80 |
@@: |
lodsb |
stosw |
loop @b |
mov byte [space_msg+80], 0 ; now space_msg is null terminated |
_setcursor d80x25_top_num,0 |
; TEST FOR 386+ |
mov bx, 0x4000 |
pushf |
pop ax |
mov dx, ax |
xor ax, bx |
push ax |
popf |
pushf |
pop ax |
and ax, bx |
and dx, bx |
cmp ax, dx |
jnz cpugood |
mov si, not386 |
sayerr: |
call print |
jmp $ |
cpugood: |
push 0 |
popf |
sti |
; set up esp |
movzx esp, sp |
push 0 |
pop es |
and word [es:0x9031], 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 |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x80 |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
; b) class 1, subclass 1, programming interface 0x8A |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x8A |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
; c) class 1, subclass 1, programming interface 0x85 |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x85 |
xor si, si |
int 0x1A |
jc .nopci |
.found: |
; get memory base |
mov ax, 0xB10A |
mov di, 0x20 ; memory base is config register at 0x20 |
int 0x1A |
jc .nopci |
and cx, 0xFFF0 ; clear address decode type |
mov [es:0x9031], 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 |
;;;/diamond today 5.02.2008 |
; set keyboard typematic rate & delay |
mov al, 0xf3 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
mov al, 0 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; --------------- APM --------------------- |
and word [es:0x9044], 0 ; ver = 0.0 (APM not found) |
mov ax, 0x5300 |
xor bx, bx |
int 0x15 |
jc apm_end ; APM not found |
test cx, 2 |
jz apm_end ; APM 32-bit protected-mode interface not supported |
mov [es:0x9044], ax ; Save APM Version |
mov [es:0x9046], cx ; Save APM flags |
; Write APM ver ---- |
and ax, 0xf0f |
add ax, '00' |
mov si, msg_apm |
mov [si + 5], ah |
mov [si + 7], al |
_setcursor 0, 3 |
call printplain |
; ------------------ |
mov ax, 0x5304 ; Disconnect interface |
xor bx, bx |
int 0x15 |
mov ax, 0x5303 ; Connect 32 bit mode interface |
xor bx, bx |
int 0x15 |
mov [es:0x9040], ebx |
mov [es:0x9050], ax |
mov [es:0x9052], cx |
mov [es:0x9054], dx |
apm_end: |
_setcursor d80x25_top_num, 0 |
if ~ defined extended_primary_loader |
;CHECK current of code |
cmp [cfgmanager.loader_block], -1 |
jz noloaderblock |
les bx, [cfgmanager.loader_block] |
cmp byte [es:bx], 1 |
mov si, loader_block_error |
jnz sayerr |
push 0 |
pop es |
end if |
noloaderblock: |
; DISPLAY VESA INFORMATION |
call print_vesa_info |
call calc_vmodes_table |
call check_first_parm ;check and enable cursor_pos |
; \begin{diamond}[30.11.2005] |
cfgmanager: |
; settings: |
; a) preboot_graph = graphical mode |
; preboot_gprobe = probe this mode? |
; b) preboot_dma = use DMA access? |
; c) preboot_vrrm = use VRR? |
; d) preboot_device = from what boot? |
; determine default settings |
if ~ defined extended_primary_loader |
mov [.bSettingsChanged], 0 |
end if |
;.preboot_gr_end: |
mov di, preboot_device |
; if image in memory is present and [preboot_device] is uninitialized, |
; set it to use this preloaded image |
cmp byte [di], 0 |
jnz .preboot_device_inited |
if defined extended_primary_loader |
inc byte [di] |
cmp byte [bootdevice], 'f' ; floppy? |
jz .preboot_device_inited |
inc byte [di] |
else |
cmp [.loader_block], -1 |
jz @f |
les bx, [.loader_block] |
test byte [es:bx+1], 1 |
jz @f |
mov byte [di], 3 |
jmp .preboot_device_inited |
@@: |
; otherwise, set [preboot_device] to 1 (default value - boot from floppy) |
mov byte [di], 1 |
end if |
.preboot_device_inited: |
; following 4 lines set variables to 1 if its current value is 0 |
cmp byte [di+preboot_dma-preboot_device], 1 |
adc byte [di+preboot_dma-preboot_device], 0 |
cmp byte [di+preboot_biosdisk-preboot_device], 1 |
adc byte [di+preboot_biosdisk-preboot_device], 0 |
;; default value for VRR is OFF |
; cmp byte [di+preboot_vrrm-preboot_device], 0 |
; jnz @f |
; mov byte [di+preboot_vrrm-preboot_device], 2 |
;@@: |
; notify user |
_setcursor 5,2 |
mov si, linef |
call printplain |
mov si, start_msg |
call print |
mov si, time_msg |
call print |
; get start time |
call .gettime |
mov [.starttime], eax |
mov word [.timer], .newtimer |
mov word [.timer+2], cs |
.printcfg: |
_setcursor 9,0 |
mov si, current_cfg_msg |
call print |
mov si, curvideo_msg |
call print |
call draw_current_vmode |
mov si, usebd_msg |
cmp [preboot_biosdisk], 1 |
call .say_on_off |
; mov si, vrrm_msg |
; cmp [preboot_vrrm], 1 |
; call .say_on_off |
mov si, preboot_device_msg |
call print |
mov al, [preboot_device] |
if defined extended_primary_loader |
and eax, 3 |
else |
and eax, 7 |
end if |
mov si, [preboot_device_msgs+eax*2] |
call printplain |
.show_remarks: |
; show remarks in gray color |
mov di, ((21-num_remarks)*80 + 2)*2 |
push 0xB800 |
pop es |
mov cx, num_remarks |
mov si, remarks |
.write_remarks: |
lodsw |
push si |
xchg ax, si |
mov ah, 1*16+7 ; background: blue (1), foreground: gray (7) |
push di |
.write_remark: |
lodsb |
test al, al |
jz @f |
stosw |
jmp .write_remark |
@@: |
pop di |
pop si |
add di, 80*2 |
loop .write_remarks |
.wait: |
_setcursor 25,0 ; out of screen |
; set timer interrupt handler |
cli |
push 0 |
pop es |
push dword [es:8*4] |
pop dword [.oldtimer] |
push dword [.timer] |
pop dword [es:8*4] |
; mov eax, [es:8*4] |
; mov [.oldtimer], eax |
; mov eax, [.timer] |
; mov [es:8*4], eax |
sti |
; wait for keypressed |
xor ax,ax |
int 16h |
push ax |
; restore timer interrupt |
; push 0 |
; pop es |
mov eax, [.oldtimer] |
mov [es:8*4], eax |
mov [.timer], eax |
_setcursor 7,0 |
mov si, space_msg |
call printplain |
; clear remarks and restore normal attributes |
push es |
mov di, ((21-num_remarks)*80 + 2)*2 |
push 0xB800 |
pop es |
mov cx, num_remarks |
mov ax, ' ' + (1*16 + 15)*100h |
@@: |
push cx |
mov cx, 76 |
rep stosw |
pop cx |
add di, 4*2 |
loop @b |
pop es |
pop ax |
; switch on key |
cmp al, 13 |
jz .continue |
or al, 20h |
cmp al, 'a' |
jz .change_a |
cmp al, 'b' |
jz .change_b |
; cmp al, 'c' |
; jz .change_c |
cmp al, 'c' ; 'd' |
jnz .show_remarks |
_setcursor 15,0 |
mov si, bdev |
call print |
if defined extended_primary_loader |
mov bx, '12' |
else |
mov bx, '14' |
end if |
call getkey |
mov [preboot_device], al |
_setcursor 13,0 |
.d: |
if ~ defined extended_primary_loader |
mov [.bSettingsChanged], 1 |
end if |
call clear_vmodes_table ;clear vmodes_table |
jmp .printcfg |
.change_a: |
.loops: |
call draw_vmodes_table |
_setcursor 25,0 ; out of screen |
xor ax,ax |
int 0x16 |
; call clear_table_cursor ;clear current position of cursor |
mov si,word [cursor_pos] |
cmp ah,0x48;x,0x48E0 ; up |
jne .down |
cmp si,modes_table |
jbe .loops |
sub word [cursor_pos],size_of_step |
jmp .loops |
.down: cmp ah,0x50;x,0x50E0 ; down |
jne .pgup |
cmp word[es:si+10],-1 |
je .loops |
add word [cursor_pos],size_of_step |
jmp .loops |
.pgup: cmp ah,0x49 ; page up |
jne .pgdn |
sub si, size_of_step*long_v_table |
cmp si, modes_table |
jae @f |
mov si, modes_table |
@@: |
mov word [cursor_pos], si |
mov si, word [home_cursor] |
sub si, size_of_step*long_v_table |
cmp si, modes_table |
jae @f |
mov si, modes_table |
@@: |
mov word [home_cursor], si |
jmp .loops |
.pgdn: cmp ah,0x51 ; page down |
jne .enter |
mov ax, [end_cursor] |
add si, size_of_step*long_v_table |
cmp si, ax |
jb @f |
mov si, ax |
sub si, size_of_step |
@@: |
mov word [cursor_pos], si |
mov si, word [home_cursor] |
sub ax, size_of_step*long_v_table |
add si, size_of_step*long_v_table |
cmp si, ax |
jb @f |
mov si, ax |
@@: |
mov word [home_cursor], si |
jmp .loops |
.enter: cmp al,0x0D;x,0x1C0D ; enter |
jne .loops |
push word [cursor_pos] |
pop bp |
push word [es:bp] |
pop word [x_save] |
push word [es:bp+2] |
pop word [y_save] |
push word [es:bp+6] |
pop word [number_vm] |
mov word [preboot_graph],bp ;save choose |
jmp .d |
.change_b: |
_setcursor 15,0 |
; mov si, ask_dma |
; call print |
; mov bx, '13' |
; call getkey |
; mov [preboot_dma], al |
mov si, ask_bd |
call print |
mov bx, '12' |
call getkey |
mov [preboot_biosdisk], al |
_setcursor 11,0 |
jmp .d |
;.change_c: |
; _setcursor 15,0 |
; mov si, vrrmprint |
; call print |
; mov bx, '12' |
; call getkey |
; mov [preboot_vrrm], al |
; _setcursor 12,0 |
; jmp .d |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.say_on_off: |
pushf |
call print |
mov si, on_msg |
popf |
jz @f |
mov si, off_msg |
@@: jmp printplain |
; novesa and vervesa strings are not used at the moment of executing this code |
virtual at novesa |
.oldtimer dd ? |
.starttime dd ? |
if ~ defined extended_primary_loader |
.bSettingsChanged db ? |
end if |
.timer dd ? |
end virtual |
if ~ defined extended_primary_loader |
.loader_block dd -1 |
end if |
.gettime: |
mov ah, 0 |
int 1Ah |
xchg ax, cx |
shl eax, 10h |
xchg ax, dx |
ret |
.newtimer: |
push ds |
push cs |
pop ds |
pushf |
call [.oldtimer] |
pushad |
call .gettime |
sub eax, [.starttime] |
if defined extended_primary_loader |
sub ax, [preboot_timeout] |
else |
sub ax, 18*5 |
end if |
jae .timergo |
neg ax |
add ax, 18-1 |
mov bx, 18 |
xor dx, dx |
div bx |
if lang eq ru |
; ¯®¤®¦¤¨â¥ 5 ᥪã¤, 4/3/2 ᥪã¤ë, 1 ᥪã¤ã |
cmp al, 5 |
mov cl, ' ' |
jae @f |
cmp al, 1 |
mov cl, 'ã' |
jz @f |
mov cl, 'ë' |
@@: mov [time_str+9], cl |
else if lang eq et |
cmp al, 1 |
ja @f |
mov [time_str+9], ' ' |
mov [time_str+10],' ' |
@@: |
else |
; wait 5/4/3/2 seconds, 1 second |
cmp al, 1 |
mov cl, 's' |
ja @f |
mov cl, ' ' |
@@: mov [time_str+9], cl |
end if |
add al, '0' |
mov [time_str+1], al |
mov si, time_msg |
_setcursor 7,0 |
call print |
_setcursor 25,0 |
popad |
pop ds |
iret |
.timergo: |
push 0 |
pop es |
mov eax, [.oldtimer] |
mov [es:8*4], eax |
mov sp, 0EC00h |
.continue: |
sti |
_setcursor 6,0 |
mov si, space_msg |
call printplain |
call printplain |
_setcursor 6,0 |
mov si, loading_msg |
call print |
_setcursor 15,0 |
if ~ defined extended_primary_loader |
cmp [.bSettingsChanged], 0 |
jz .load |
cmp [.loader_block], -1 |
jz .load |
les bx, [.loader_block] |
mov eax, [es:bx+3] |
push ds |
pop es |
test eax, eax |
jz .load |
push eax |
mov si, save_quest |
call print |
.waityn: |
mov ah, 0 |
int 16h |
or al, 20h |
cmp al, 'n' |
jz .loadc |
cmp al, 'y' |
jnz .waityn |
call putchar |
mov byte [space_msg+80], 186 |
pop eax |
push cs |
push .cont |
push eax |
retf ;call back |
.loadc: |
pop eax |
.cont: |
push cs |
pop ds |
mov si, space_msg |
mov byte [si+80], 0 |
_setcursor 15,0 |
call printplain |
_setcursor 15,0 |
.load: |
end if |
; \end{diamond}[02.12.2005] |
; ASK GRAPHICS MODE |
call set_vmode |
; GRAPHICS ACCELERATION |
; force yes |
mov [es:0x901C], byte 1 |
; DMA ACCESS TO HD |
mov al, [preboot_dma] |
mov [es:0x901F], al |
;; VRR_M USE |
; |
; mov al,[preboot_vrrm] |
; mov [es:0x9030], al |
mov [es:0x901E], byte 1 |
; BOOT DEVICE |
mov al, [preboot_device] |
dec al |
mov [boot_dev], al |
; GET MEMORY MAP |
include '../detect/biosmem.inc' |
; READ DISKETTE TO MEMORY |
cmp [boot_dev],0 |
jne no_sys_on_floppy |
mov si,diskload |
call print |
xor ax, ax ; reset drive |
xor dx, dx |
int 0x13 |
; do we boot from CD-ROM? |
mov ah, 41h |
mov bx, 55AAh |
xor dx, dx |
int 0x13 |
jc .nocd |
cmp bx, 0AA55h |
jnz .nocd |
mov ah, 48h |
push ds |
push es |
pop ds |
mov si, 0xa000 |
mov word [si], 30 |
int 0x13 |
pop ds |
jc .nocd |
push ds |
lds si, [es:si+26] |
test byte [ds:si+10], 40h |
pop ds |
jz .nocd |
; yes - read all floppy by 18 sectors |
; TODO: !!!! read only first sector and set variables !!!!! |
; ... |
; TODO: !!! then read flippy image track by track |
mov cx, 0x0001 ; startcyl,startsector |
.a1: |
push cx dx |
mov al, 18 |
mov bx, 0xa000 |
call boot_read_floppy |
mov si, movedesc |
push es |
push ds |
pop es |
mov cx, 256*18 |
mov ah, 0x87 |
int 0x15 |
pop es |
pop dx cx |
test ah, ah |
jnz sayerr_floppy |
add dword [si+8*3+2], 512*18 |
inc dh |
cmp dh, 2 |
jnz .a1 |
mov dh, 0 |
inc ch |
cmp ch, 80 |
jae ok_sys_on_floppy |
pusha |
mov al, ch |
shr ch, 2 |
add al, ch |
aam |
xchg al, ah |
add ax, '00' |
mov si, pros |
mov [si], ax |
call printplain |
popa |
jmp .a1 |
.nocd: |
; no - read only used sectors from floppy |
; now load floppy image to memory |
; at first load boot sector and first FAT table |
; read only first sector and fill variables |
mov cx, 0x0001 ; first logical sector |
xor dx, dx ; head = 0, drive = 0 (a:) |
mov al, 1 ; read one sector |
mov bx, 0xB000 ; es:bx -> data area |
call boot_read_floppy |
; fill the necessary parameters to work with a floppy |
mov ax, word [es:bx+24] |
mov word [BPB_SecPerTrk], ax |
mov ax, word [es:bx+26] |
mov word [BPB_NumHeads], ax |
mov ax, word [es:bx+17] |
mov word [BPB_RootEntCnt], ax |
mov ax, word [es:bx+14] |
mov word [BPB_RsvdSecCnt], ax |
mov ax, word [es:bx+19] |
mov word [BPB_TotSec16], ax |
mov al, byte [es:bx+13] |
mov byte [BPB_SecPerClus], al |
mov al, byte [es:bx+16] |
mov byte [BPB_NumFATs], al |
;<Lrz> 18.11.2008 |
mov ax, word [es:bx+22] |
mov word [BPB_FATSz16], ax |
mov cx, word [es:bx+11] |
mov word [BPB_BytsPerSec], cx |
; count of clusters in FAT12 ((size_of_FAT*2)/3) |
; mov ax, word [BPB_FATSz16] |
; mov cx, word [BPB_BytsPerSec] |
;end <Lrz> 18.11.2008 |
xor dx, dx |
mul cx |
shl ax, 1 |
mov cx, 3 |
div cx ; now ax - number of clusters in FAT12 |
mov word [end_of_FAT], ax |
; load first FAT table |
mov cx, 0x0002 ; startcyl,startsector ; TODO!!!!! |
xor dx, dx ; starthead,drive |
mov al, byte [BPB_FATSz16] ; no of sectors to read |
add bx, word [BPB_BytsPerSec] ; es:bx -> data area |
call boot_read_floppy |
mov bx, 0xB000 |
; and copy them to extended memory |
mov si, movedesc |
mov [si+8*2+3], bh ; from |
mov ax, word [BPB_BytsPerSec] |
shr ax, 1 ; words per sector |
mov cx, word [BPB_RsvdSecCnt] |
add cx, word [BPB_FATSz16] |
mul cx |
push ax ; save to stack count of words in boot+FAT |
xchg ax, cx |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
test ah, ah |
jz @f |
sayerr_floppy: |
mov dx, 0x3f2 |
mov al, 0 |
out dx, al |
sayerr_memmove: |
mov si, memmovefailed |
jmp sayerr_plain |
@@: |
pop ax ; restore from stack count of words in boot+FAT |
shl ax, 1 ; make bytes count from count of words |
and eax, 0ffffh |
add dword [si+8*3+2], eax |
; copy first FAT to second copy |
; TODO: BPB_NumFATs !!!!! |
add bx, word [BPB_BytsPerSec] ; !!! TODO: may be need multiply by BPB_RsvdSecCnt !!! |
mov byte [si+8*2+3], bh ; bx - begin of FAT |
mov ax, word [BPB_BytsPerSec] |
shr ax, 1 ; words per sector |
mov cx, word [BPB_FATSz16] |
mul cx |
mov cx, ax ; cx - count of words in FAT |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
test ah, ah |
jnz sayerr_floppy |
mov ax, cx |
shl ax, 1 |
and eax, 0ffffh ; ax - count of bytes in FAT |
add dword [si+8*3+2], eax |
; reading RootDir |
; TODO: BPB_NumFATs |
add bx, ax |
add bx, 100h |
and bx, 0ff00h ; bx - place in buffer to write RootDir |
push bx |
mov bx, word [BPB_BytsPerSec] |
shr bx, 5 ; divide bx by 32 |
mov ax, word [BPB_RootEntCnt] |
xor dx, dx |
div bx |
push ax ; ax - count of RootDir sectors |
mov ax, word [BPB_FATSz16] |
xor cx, cx |
mov cl, byte [BPB_NumFATs] |
mul cx |
add ax, word [BPB_RsvdSecCnt] ; ax - first sector of RootDir |
mov word [FirstDataSector], ax |
pop bx |
push bx |
add word [FirstDataSector], bx ; Begin of data region of floppy |
; read RootDir |
call conv_abs_to_THS |
pop ax |
pop bx ; place in buffer to write |
push ax |
call boot_read_floppy ; read RootDir into buffer |
; copy RootDir |
mov byte [si+8*2+3], bh ; from buffer |
pop ax ; ax = count of RootDir sectors |
mov cx, word [BPB_BytsPerSec] |
mul cx |
shr ax, 1 |
mov cx, ax ; count of words to copy |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
mov ax, cx |
shl ax, 1 |
and eax, 0ffffh ; ax - count of bytes in RootDir |
add dword [si+8*3+2], eax ; add count of bytes copied |
; Reading data clusters from floppy |
mov byte [si+8*2+3], bh |
push bx |
mov di, 2 ; First data cluster |
.read_loop: |
mov bx, di |
shr bx, 1 ; bx+di = di*1.5 |
jnc .even |
test word [es:bx+di+0xB200], 0xFFF0 ; TODO: may not be 0xB200 !!! |
jmp @f |
.even: |
test word [es:bx+di+0xB200], 0xFFF ; TODO: may not be 0xB200 !!! |
@@: |
jz .skip |
; read cluster di |
;.read: |
;conv cluster di to abs. sector ax |
; ax = (N-2) * BPB_SecPerClus + FirstDataSector |
mov ax, di |
sub ax, 2 |
xor bx, bx |
mov bl, byte [BPB_SecPerClus] |
mul bx |
add ax, word [FirstDataSector] |
call conv_abs_to_THS |
pop bx |
push bx |
mov al, byte [BPB_SecPerClus] ; number of sectors in cluster |
call boot_read_floppy |
push es |
push ds |
pop es |
pusha |
; |
mov ax, word [BPB_BytsPerSec] |
xor cx, cx |
mov cl, byte [BPB_SecPerClus] |
mul cx |
shr ax, 1 ; ax = (BPB_BytsPerSec * BPB_SecPerClus)/2 |
mov cx, ax ; number of words to copy (count words in cluster) |
; |
mov ah, 0x87 |
int 0x15 ; copy data |
test ah, ah |
popa |
pop es |
jnz sayerr_floppy |
; skip cluster di |
.skip: |
mov ax, word [BPB_BytsPerSec] |
xor cx, cx |
mov cl, byte [BPB_SecPerClus] |
mul cx |
and eax, 0ffffh ; ax - count of bytes in cluster |
add dword [si+8*3+2], eax |
mov ax, word [end_of_FAT] ; max cluster number |
pusha |
; draw percentage |
; total clusters: ax |
; read clusters: di |
xchg ax, di |
mov cx, 100 |
mul cx |
div di |
aam |
xchg al, ah |
add ax, '00' |
mov si, pros |
cmp [si], ax |
jz @f |
mov [si], ax |
call printplain |
@@: |
popa |
inc di |
cmp di, word [end_of_FAT] ; max number of cluster |
jnz .read_loop |
pop bx ; clear stack |
ok_sys_on_floppy: |
mov si, backspace2 |
call printplain |
mov si, okt |
call printplain |
no_sys_on_floppy: |
xor ax, ax ; reset drive |
xor dx, dx |
int 0x13 |
mov dx, 0x3f2 ; floppy motor off |
mov al, 0 |
out dx, al |
if defined extended_primary_loader |
cmp [boot_dev], 1 |
jne no_sys_from_primary |
; load kolibri.img using callback from primary loader |
and word [movedesc + 24 + 2], 0 |
mov byte [movedesc + 24 + 4], 10h |
; read in blocks of 64K until file is fully loaded |
mov ax, 1 |
.repeat: |
mov di, image_file_struct |
call [bootcallback] |
push cs |
pop ds |
push cs |
pop es |
cmp bx, 1 |
ja sayerr_badsect |
push bx |
mov si, movedesc |
and word [si + 16 + 2], 0 |
mov byte [si + 16 + 4], 4 |
mov ah, 87h |
mov cx, 8000h |
int 15h |
pop bx |
test ah, ah |
jnz sayerr_memmove |
inc byte [si + 24 + 4] |
test bx, bx |
jz no_sys_from_primary |
mov ax, 2 |
jmp .repeat |
no_sys_from_primary: |
end if |
; SET GRAPHICS |
xor ax, ax |
mov es, ax |
mov ax, [es:0x9008] ; vga & 320x200 |
mov bx, ax |
cmp ax, 0x13 |
je setgr |
cmp ax, 0x12 |
je setgr |
mov ax, 0x4f02 ; Vesa |
setgr: |
int 0x10 |
test ah, ah |
mov si, fatalsel |
jnz v_mode_error |
; set mode 0x12 graphics registers: |
cmp bx, 0x12 |
jne gmok2 |
mov al, 0x05 |
mov dx, 0x03ce |
push dx |
out dx, al ; select GDC mode register |
mov al, 0x02 |
inc dx |
out dx, al ; set write mode 2 |
mov al, 0x02 |
mov dx, 0x03c4 |
out dx, al ; select VGA sequencer map mask register |
mov al, 0x0f |
inc dx |
out dx, al ; set mask for all planes 0-3 |
mov al, 0x08 |
pop dx |
out dx, al ; select GDC bit mask register |
; for writes to 0x03cf |
gmok2: |
push ds |
pop es |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; BOOTCODE.INC ;; |
;; ;; |
;; KolibriOS 16-bit loader, ;; |
;; based on bootcode for MenuetOS ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;========================================================================== |
; |
; 16 BIT FUNCTIONS |
; |
;========================================================================== |
putchar: |
; in: al=character |
mov ah, 0Eh |
mov bh, 0 |
int 10h |
ret |
print: |
; in: si->string |
mov al, 186 |
call putchar |
mov al, ' ' |
call putchar |
printplain: |
; in: si->string |
pusha |
lodsb |
@@: |
call putchar |
lodsb |
test al, al |
jnz @b |
popa |
ret |
getkey: |
; get number in range [bl,bh] (bl,bh in ['0'..'9']) |
; in: bx=range |
; out: ax=digit (1..9, 10 for 0) |
mov ah, 0 |
int 16h |
cmp al, bl |
jb getkey |
cmp al, bh |
ja getkey |
push ax |
call putchar |
pop ax |
and ax, 0Fh |
jnz @f |
mov al, 10 |
@@: |
ret |
setcursor: |
; in: dl=column, dh=row |
mov ah, 2 |
mov bh, 0 |
int 10h |
ret |
macro _setcursor row,column |
{ |
mov dx, row*256 + column |
call setcursor |
} |
boot_read_floppy: |
push si |
xor si, si |
mov ah, 2 ; read |
@@: |
push ax |
int 0x13 |
pop ax |
jnc @f |
inc si |
cmp si, 10 |
jb @b |
sayerr_badsect: |
mov si, badsect |
sayerr_plain: |
call printplain |
jmp $ |
@@: |
pop si |
ret |
; convert abs. sector number (AX) to BIOS T:H:S |
; sector number = (abs.sector%BPB_SecPerTrk)+1 |
; pre.track number = (abs.sector/BPB_SecPerTrk) |
; head number = pre.track number%BPB_NumHeads |
; track number = pre.track number/BPB_NumHeads |
; Return: cl - sector number |
; ch - track number |
; dl - drive number (0 = a:) |
; dh - head number |
conv_abs_to_THS: |
push bx |
mov bx, word [BPB_SecPerTrk] |
xor dx, dx |
div bx |
inc dx |
mov cl, dl ; cl = sector number |
mov bx, word [BPB_NumHeads] |
xor dx, dx |
div bx |
; !!!!!!! ax = track number, dx = head number |
mov ch, al ; ch=track number |
xchg dh, dl ; dh=head number |
mov dl, 0 ; dl=0 (drive 0 (a:)) |
pop bx |
retn |
; needed variables |
BPB_SecPerTrk dw 0 ; sectors per track |
BPB_NumHeads dw 0 ; number of heads |
BPB_FATSz16 dw 0 ; size of FAT |
BPB_RootEntCnt dw 0 ; count of root dir. entries |
BPB_BytsPerSec dw 0 ; bytes per sector |
BPB_RsvdSecCnt dw 0 ; number of reserved sectors |
BPB_TotSec16 dw 0 ; count of the sectors on the volume |
BPB_SecPerClus db 0 ; number of sectors per cluster |
BPB_NumFATs db 0 ; number of FAT tables |
abs_sector_adj dw 0 ; adjustment to make abs. sector number |
end_of_FAT dw 0 ; end of FAT table |
FirstDataSector dw 0 ; begin of data |
;========================================================================= |
; |
; 16 BIT CODE |
; |
;========================================================================= |
include 'bootvesa.inc' ;Include source for boot vesa |
if defined extended_primary_loader |
include 'parsers.inc' |
end if |
start_of_code: |
if defined extended_primary_loader |
; save data from primary loader |
mov word [cs:bootcallback], si |
mov word [cs:bootcallback+2], ds |
push cs |
pop ds |
mov [bootdevice], ax |
mov [bootfs], bx |
; set up stack |
mov ax, 3000h |
mov ss, ax |
mov sp, 0EC00h |
; try to load configuration file |
mov ax, 1 |
mov di, config_file_struct |
call [bootcallback] |
cld |
push cs |
pop es |
; bx=0 - ok, bx=1 - part of file loaded, assume this is ok |
cmp bx, 1 |
ja .config_bad |
; configuration file was loaded, parse |
; if length is too big, use first 0FFFFh bytes |
test dx, dx |
jz @f |
mov ax, 0FFFFh |
@@: |
; ds:si will be pointer to current data, dx = limit |
xchg ax, dx |
push 4000h |
pop ds |
xor si, si |
.parse_loop: |
; skip spaces |
cmp si, dx |
jae .parse_done |
lodsb |
cmp al, ' ' |
jbe .parse_loop |
dec si |
; loop over all possible configuration values |
mov bx, config_file_variables |
.find_variant: |
; get length |
mov cx, [es:bx] |
; zero length = end of list |
jecxz .find_newline |
; skip over length |
inc bx |
inc bx |
mov di, bx |
; skip over string |
add bx, cx |
; test whether we have at least cx symbols left |
mov ax, cx |
add ax, si |
jc .next_variant1 |
cmp ax, dx |
jae .next_variant1 |
; save current position |
push si |
; compare strings |
repz cmpsb |
jnz .next_variant2 |
; strings are equal; look for "=" with possible spaces before and after |
@@: |
cmp si, dx |
jae .next_variant2 |
lodsb |
cmp al, ' ' |
jbe @b |
cmp al, '=' |
jnz .next_variant2 |
; ok, we found the true variant |
; ignore saved position on the stack |
pop ax |
; call the parser |
call word [es:bx] |
; line parsed, find next |
.find_newline: |
cmp si, dx |
jae .parse_done |
lodsb |
cmp al, 13 |
jz .parse_loop |
cmp al, 10 |
jz .parse_loop |
jmp .find_newline |
.next_variant2: |
; continue to the next variant, restoring current position |
pop si |
.next_variant1: |
; continue to the next variant |
; skip over the parser |
inc bx |
inc bx |
jmp .find_variant |
.parse_done: |
.config_bad: |
; set up segment registers |
push cs |
pop ds |
else |
cld |
; \begin{diamond}[02.12.2005] |
; if bootloader sets ax = 'KL', then ds:si points to loader block |
cmp ax, 'KL' |
jnz @f |
mov word [cs:cfgmanager.loader_block], si |
mov word [cs:cfgmanager.loader_block+2], ds |
@@: |
; \end{diamond}[02.12.2005] |
; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk |
; (see comment to bx_from_load) |
cmp cx, 'HA' |
jnz no_hd_load |
cmp dx, 'RD' |
jnz no_hd_load |
mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007] |
no_hd_load: |
; set up stack |
mov ax, 3000h |
mov ss, ax |
mov sp, 0EC00h |
; set up segment registers |
push cs |
pop ds |
push cs |
pop es |
end if |
; set videomode |
mov ax, 3 |
int 0x10 |
if lang eq ru |
; Load & set russian VGA font (RU.INC) |
mov bp, RU_FNT1 ; RU_FNT1 - First part |
mov bx, 1000h ; 768 bytes |
mov cx, 30h ; 48 symbols |
mov dx, 80h ; 128 - position of first symbol |
mov ax, 1100h |
int 10h |
mov bp, RU_FNT2 ; RU_FNT2 -Second part |
mov bx, 1000h ; 512 bytes |
mov cx, 20h ; 32 symbols |
mov dx, 0E0h ; 224 - position of first symbol |
mov ax, 1100h |
int 10h |
; End set VGA russian font |
else if lang eq et |
mov bp, ET_FNT ; ET_FNT1 |
mov bx, 1000h ; |
mov cx, 255 ; 256 symbols |
xor dx, dx ; 0 - position of first symbol |
mov ax, 1100h |
int 10h |
end if |
; draw frames |
push 0xb800 |
pop es |
xor di, di |
mov ah, 1*16+15 |
; draw top |
mov si, d80x25_top |
mov cx, d80x25_top_num * 80 |
@@: |
lodsb |
stosw |
loop @b |
; draw spaces |
mov si, space_msg |
mov dx, 25 - d80x25_top_num - d80x25_bottom_num |
dfl1: |
push si |
mov cx, 80 |
@@: |
lodsb |
stosw |
loop @b |
pop si |
dec dx |
jnz dfl1 |
; draw bottom |
mov si, d80x25_bottom |
mov cx, d80x25_bottom_num * 80 |
@@: |
lodsb |
stosw |
loop @b |
mov byte [space_msg+80], 0 ; now space_msg is null terminated |
_setcursor d80x25_top_num,0 |
; TEST FOR 386+ |
mov bx, 0x4000 |
pushf |
pop ax |
mov dx, ax |
xor ax, bx |
push ax |
popf |
pushf |
pop ax |
and ax, bx |
and dx, bx |
cmp ax, dx |
jnz cpugood |
mov si, not386 |
sayerr: |
call print |
jmp $ |
cpugood: |
push 0 |
popf |
sti |
; set up esp |
movzx esp, sp |
push 0 |
pop es |
and word [es:0x9031], 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 |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x80 |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
; b) class 1, subclass 1, programming interface 0x8A |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x8A |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
; c) class 1, subclass 1, programming interface 0x85 |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x85 |
xor si, si |
int 0x1A |
jc .nopci |
.found: |
; get memory base |
mov ax, 0xB10A |
mov di, 0x20 ; memory base is config register at 0x20 |
int 0x1A |
jc .nopci |
and cx, 0xFFF0 ; clear address decode type |
mov [es:0x9031], 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 |
;;;/diamond today 5.02.2008 |
; set keyboard typematic rate & delay |
mov al, 0xf3 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
mov al, 0 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; --------------- APM --------------------- |
and word [es:0x9044], 0 ; ver = 0.0 (APM not found) |
mov ax, 0x5300 |
xor bx, bx |
int 0x15 |
jc apm_end ; APM not found |
test cx, 2 |
jz apm_end ; APM 32-bit protected-mode interface not supported |
mov [es:0x9044], ax ; Save APM Version |
mov [es:0x9046], cx ; Save APM flags |
; Write APM ver ---- |
and ax, 0xf0f |
add ax, '00' |
mov si, msg_apm |
mov [si + 5], ah |
mov [si + 7], al |
_setcursor 0, 3 |
call printplain |
; ------------------ |
mov ax, 0x5304 ; Disconnect interface |
xor bx, bx |
int 0x15 |
mov ax, 0x5303 ; Connect 32 bit mode interface |
xor bx, bx |
int 0x15 |
mov [es:0x9040], ebx |
mov [es:0x9050], ax |
mov [es:0x9052], cx |
mov [es:0x9054], dx |
apm_end: |
_setcursor d80x25_top_num, 0 |
if ~ defined extended_primary_loader |
;CHECK current of code |
cmp [cfgmanager.loader_block], -1 |
jz noloaderblock |
les bx, [cfgmanager.loader_block] |
cmp byte [es:bx], 1 |
mov si, loader_block_error |
jnz sayerr |
push 0 |
pop es |
end if |
noloaderblock: |
; DISPLAY VESA INFORMATION |
call print_vesa_info |
call calc_vmodes_table |
call check_first_parm ;check and enable cursor_pos |
; \begin{diamond}[30.11.2005] |
cfgmanager: |
; settings: |
; a) preboot_graph = graphical mode |
; preboot_gprobe = probe this mode? |
; b) preboot_dma = use DMA access? |
; c) preboot_vrrm = use VRR? |
; d) preboot_device = from what boot? |
; determine default settings |
if ~ defined extended_primary_loader |
mov [.bSettingsChanged], 0 |
end if |
;.preboot_gr_end: |
mov di, preboot_device |
; if image in memory is present and [preboot_device] is uninitialized, |
; set it to use this preloaded image |
cmp byte [di], 0 |
jnz .preboot_device_inited |
if defined extended_primary_loader |
inc byte [di] |
cmp byte [bootdevice], 'f' ; floppy? |
jz .preboot_device_inited |
inc byte [di] |
else |
cmp [.loader_block], -1 |
jz @f |
les bx, [.loader_block] |
test byte [es:bx+1], 1 |
jz @f |
mov byte [di], 3 |
jmp .preboot_device_inited |
@@: |
; otherwise, set [preboot_device] to 1 (default value - boot from floppy) |
mov byte [di], 1 |
end if |
.preboot_device_inited: |
; following 4 lines set variables to 1 if its current value is 0 |
cmp byte [di+preboot_dma-preboot_device], 1 |
adc byte [di+preboot_dma-preboot_device], 0 |
cmp byte [di+preboot_biosdisk-preboot_device], 1 |
adc byte [di+preboot_biosdisk-preboot_device], 0 |
;; default value for VRR is OFF |
; cmp byte [di+preboot_vrrm-preboot_device], 0 |
; jnz @f |
; mov byte [di+preboot_vrrm-preboot_device], 2 |
;@@: |
; notify user |
_setcursor 5,2 |
mov si, linef |
call printplain |
mov si, start_msg |
call print |
mov si, time_msg |
call print |
; get start time |
call .gettime |
mov [.starttime], eax |
mov word [.timer], .newtimer |
mov word [.timer+2], cs |
.printcfg: |
_setcursor 9,0 |
mov si, current_cfg_msg |
call print |
mov si, curvideo_msg |
call print |
call draw_current_vmode |
mov si, usebd_msg |
cmp [preboot_biosdisk], 1 |
call .say_on_off |
; mov si, vrrm_msg |
; cmp [preboot_vrrm], 1 |
; call .say_on_off |
mov si, preboot_device_msg |
call print |
mov al, [preboot_device] |
if defined extended_primary_loader |
and eax, 3 |
else |
and eax, 7 |
end if |
mov si, [preboot_device_msgs+eax*2] |
call printplain |
.show_remarks: |
; show remarks in gray color |
mov di, ((21-num_remarks)*80 + 2)*2 |
push 0xB800 |
pop es |
mov cx, num_remarks |
mov si, remarks |
.write_remarks: |
lodsw |
push si |
xchg ax, si |
mov ah, 1*16+7 ; background: blue (1), foreground: gray (7) |
push di |
.write_remark: |
lodsb |
test al, al |
jz @f |
stosw |
jmp .write_remark |
@@: |
pop di |
pop si |
add di, 80*2 |
loop .write_remarks |
.wait: |
_setcursor 25,0 ; out of screen |
; set timer interrupt handler |
cli |
push 0 |
pop es |
push dword [es:8*4] |
pop dword [.oldtimer] |
push dword [.timer] |
pop dword [es:8*4] |
; mov eax, [es:8*4] |
; mov [.oldtimer], eax |
; mov eax, [.timer] |
; mov [es:8*4], eax |
sti |
; wait for keypressed |
xor ax, ax |
int 16h |
push ax |
; restore timer interrupt |
; push 0 |
; pop es |
mov eax, [.oldtimer] |
mov [es:8*4], eax |
mov [.timer], eax |
_setcursor 7,0 |
mov si, space_msg |
call printplain |
; clear remarks and restore normal attributes |
push es |
mov di, ((21-num_remarks)*80 + 2)*2 |
push 0xB800 |
pop es |
mov cx, num_remarks |
mov ax, ' ' + (1*16 + 15)*100h |
@@: |
push cx |
mov cx, 76 |
rep stosw |
pop cx |
add di, 4*2 |
loop @b |
pop es |
pop ax |
; switch on key |
cmp al, 13 |
jz .continue |
or al, 20h |
cmp al, 'a' |
jz .change_a |
cmp al, 'b' |
jz .change_b |
; cmp al, 'c' |
; jz .change_c |
cmp al, 'c' ; 'd' |
jnz .show_remarks |
_setcursor 15,0 |
mov si, bdev |
call print |
if defined extended_primary_loader |
mov bx, '12' |
else |
mov bx, '14' |
end if |
call getkey |
mov [preboot_device], al |
_setcursor 13,0 |
.d: |
if ~ defined extended_primary_loader |
mov [.bSettingsChanged], 1 |
end if |
call clear_vmodes_table ;clear vmodes_table |
jmp .printcfg |
.change_a: |
.loops: |
call draw_vmodes_table |
_setcursor 25,0 ; out of screen |
xor ax, ax |
int 0x16 |
; call clear_table_cursor ;clear current position of cursor |
mov si, word [cursor_pos] |
cmp ah, 0x48;x,0x48E0 ; up |
jne .down |
cmp si, modes_table |
jbe .loops |
sub word [cursor_pos], size_of_step |
jmp .loops |
.down: |
cmp ah, 0x50;x,0x50E0 ; down |
jne .pgup |
cmp word[es:si+10], -1 |
je .loops |
add word [cursor_pos], size_of_step |
jmp .loops |
.pgup: |
cmp ah, 0x49 ; page up |
jne .pgdn |
sub si, size_of_step*long_v_table |
cmp si, modes_table |
jae @f |
mov si, modes_table |
@@: |
mov word [cursor_pos], si |
mov si, word [home_cursor] |
sub si, size_of_step*long_v_table |
cmp si, modes_table |
jae @f |
mov si, modes_table |
@@: |
mov word [home_cursor], si |
jmp .loops |
.pgdn: |
cmp ah, 0x51 ; page down |
jne .enter |
mov ax, [end_cursor] |
add si, size_of_step*long_v_table |
cmp si, ax |
jb @f |
mov si, ax |
sub si, size_of_step |
@@: |
mov word [cursor_pos], si |
mov si, word [home_cursor] |
sub ax, size_of_step*long_v_table |
add si, size_of_step*long_v_table |
cmp si, ax |
jb @f |
mov si, ax |
@@: |
mov word [home_cursor], si |
jmp .loops |
.enter: |
cmp al, 0x0D;x,0x1C0D ; enter |
jne .loops |
push word [cursor_pos] |
pop bp |
push word [es:bp] |
pop word [x_save] |
push word [es:bp+2] |
pop word [y_save] |
push word [es:bp+6] |
pop word [number_vm] |
mov word [preboot_graph], bp ;save choose |
jmp .d |
.change_b: |
_setcursor 15,0 |
; mov si, ask_dma |
; call print |
; mov bx, '13' |
; call getkey |
; mov [preboot_dma], al |
mov si, ask_bd |
call print |
mov bx, '12' |
call getkey |
mov [preboot_biosdisk], al |
_setcursor 11,0 |
jmp .d |
;.change_c: |
; _setcursor 15,0 |
; mov si, vrrmprint |
; call print |
; mov bx, '12' |
; call getkey |
; mov [preboot_vrrm], al |
; _setcursor 12,0 |
; jmp .d |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.say_on_off: |
pushf |
call print |
mov si, on_msg |
popf |
jz @f |
mov si, off_msg |
@@: |
jmp printplain |
; novesa and vervesa strings are not used at the moment of executing this code |
virtual at novesa |
.oldtimer dd ? |
.starttime dd ? |
if ~ defined extended_primary_loader |
.bSettingsChanged db ? |
end if |
.timer dd ? |
end virtual |
if ~ defined extended_primary_loader |
.loader_block dd -1 |
end if |
.gettime: |
mov ah, 0 |
int 1Ah |
xchg ax, cx |
shl eax, 10h |
xchg ax, dx |
ret |
.newtimer: |
push ds |
push cs |
pop ds |
pushf |
call [.oldtimer] |
pushad |
call .gettime |
sub eax, [.starttime] |
if defined extended_primary_loader |
sub ax, [preboot_timeout] |
else |
sub ax, 18*5 |
end if |
jae .timergo |
neg ax |
add ax, 18-1 |
mov bx, 18 |
xor dx, dx |
div bx |
if lang eq ru |
; ¯®¤®¦¤¨â¥ 5 ᥪã¤, 4/3/2 ᥪã¤ë, 1 ᥪã¤ã |
cmp al, 5 |
mov cl, ' ' |
jae @f |
cmp al, 1 |
mov cl, 'ã' |
jz @f |
mov cl, 'ë' |
@@: |
mov [time_str+9], cl |
else if lang eq et |
cmp al, 1 |
ja @f |
mov [time_str+9], ' ' |
mov [time_str+10], ' ' |
@@: |
else |
; wait 5/4/3/2 seconds, 1 second |
cmp al, 1 |
mov cl, 's' |
ja @f |
mov cl, ' ' |
@@: |
mov [time_str+9], cl |
end if |
add al, '0' |
mov [time_str+1], al |
mov si, time_msg |
_setcursor 7,0 |
call print |
_setcursor 25,0 |
popad |
pop ds |
iret |
.timergo: |
push 0 |
pop es |
mov eax, [.oldtimer] |
mov [es:8*4], eax |
mov sp, 0EC00h |
.continue: |
sti |
_setcursor 6,0 |
mov si, space_msg |
call printplain |
call printplain |
_setcursor 6,0 |
mov si, loading_msg |
call print |
_setcursor 15,0 |
if ~ defined extended_primary_loader |
cmp [.bSettingsChanged], 0 |
jz .load |
cmp [.loader_block], -1 |
jz .load |
les bx, [.loader_block] |
mov eax, [es:bx+3] |
push ds |
pop es |
test eax, eax |
jz .load |
push eax |
mov si, save_quest |
call print |
.waityn: |
mov ah, 0 |
int 16h |
or al, 20h |
cmp al, 'n' |
jz .loadc |
cmp al, 'y' |
jnz .waityn |
call putchar |
mov byte [space_msg+80], 186 |
pop eax |
push cs |
push .cont |
push eax |
retf ;call back |
.loadc: |
pop eax |
.cont: |
push cs |
pop ds |
mov si, space_msg |
mov byte [si+80], 0 |
_setcursor 15,0 |
call printplain |
_setcursor 15,0 |
.load: |
end if |
; \end{diamond}[02.12.2005] |
; ASK GRAPHICS MODE |
call set_vmode |
; GRAPHICS ACCELERATION |
; force yes |
mov [es:0x901C], byte 1 |
; DMA ACCESS TO HD |
mov al, [preboot_dma] |
mov [es:0x901F], al |
;; VRR_M USE |
; |
; mov al,[preboot_vrrm] |
; mov [es:0x9030], al |
mov [es:0x901E], byte 1 |
; BOOT DEVICE |
mov al, [preboot_device] |
dec al |
mov [boot_dev], al |
; GET MEMORY MAP |
include '../detect/biosmem.inc' |
; READ DISKETTE TO MEMORY |
cmp [boot_dev], 0 |
jne no_sys_on_floppy |
mov si, diskload |
call print |
xor ax, ax ; reset drive |
xor dx, dx |
int 0x13 |
; do we boot from CD-ROM? |
mov ah, 41h |
mov bx, 55AAh |
xor dx, dx |
int 0x13 |
jc .nocd |
cmp bx, 0AA55h |
jnz .nocd |
mov ah, 48h |
push ds |
push es |
pop ds |
mov si, 0xa000 |
mov word [si], 30 |
int 0x13 |
pop ds |
jc .nocd |
push ds |
lds si, [es:si+26] |
test byte [ds:si+10], 40h |
pop ds |
jz .nocd |
; yes - read all floppy by 18 sectors |
; TODO: !!!! read only first sector and set variables !!!!! |
; ... |
; TODO: !!! then read flippy image track by track |
mov cx, 0x0001 ; startcyl,startsector |
.a1: |
push cx dx |
mov al, 18 |
mov bx, 0xa000 |
call boot_read_floppy |
mov si, movedesc |
push es |
push ds |
pop es |
mov cx, 256*18 |
mov ah, 0x87 |
int 0x15 |
pop es |
pop dx cx |
test ah, ah |
jnz sayerr_floppy |
add dword [si+8*3+2], 512*18 |
inc dh |
cmp dh, 2 |
jnz .a1 |
mov dh, 0 |
inc ch |
cmp ch, 80 |
jae ok_sys_on_floppy |
pusha |
mov al, ch |
shr ch, 2 |
add al, ch |
aam |
xchg al, ah |
add ax, '00' |
mov si, pros |
mov [si], ax |
call printplain |
popa |
jmp .a1 |
.nocd: |
; no - read only used sectors from floppy |
; now load floppy image to memory |
; at first load boot sector and first FAT table |
; read only first sector and fill variables |
mov cx, 0x0001 ; first logical sector |
xor dx, dx ; head = 0, drive = 0 (a:) |
mov al, 1 ; read one sector |
mov bx, 0xB000 ; es:bx -> data area |
call boot_read_floppy |
; fill the necessary parameters to work with a floppy |
mov ax, word [es:bx+24] |
mov word [BPB_SecPerTrk], ax |
mov ax, word [es:bx+26] |
mov word [BPB_NumHeads], ax |
mov ax, word [es:bx+17] |
mov word [BPB_RootEntCnt], ax |
mov ax, word [es:bx+14] |
mov word [BPB_RsvdSecCnt], ax |
mov ax, word [es:bx+19] |
mov word [BPB_TotSec16], ax |
mov al, byte [es:bx+13] |
mov byte [BPB_SecPerClus], al |
mov al, byte [es:bx+16] |
mov byte [BPB_NumFATs], al |
;<Lrz> 18.11.2008 |
mov ax, word [es:bx+22] |
mov word [BPB_FATSz16], ax |
mov cx, word [es:bx+11] |
mov word [BPB_BytsPerSec], cx |
; count of clusters in FAT12 ((size_of_FAT*2)/3) |
; mov ax, word [BPB_FATSz16] |
; mov cx, word [BPB_BytsPerSec] |
;end <Lrz> 18.11.2008 |
xor dx, dx |
mul cx |
shl ax, 1 |
mov cx, 3 |
div cx ; now ax - number of clusters in FAT12 |
mov word [end_of_FAT], ax |
; load first FAT table |
mov cx, 0x0002 ; startcyl,startsector ; TODO!!!!! |
xor dx, dx ; starthead,drive |
mov al, byte [BPB_FATSz16] ; no of sectors to read |
add bx, word [BPB_BytsPerSec] ; es:bx -> data area |
call boot_read_floppy |
mov bx, 0xB000 |
; and copy them to extended memory |
mov si, movedesc |
mov [si+8*2+3], bh ; from |
mov ax, word [BPB_BytsPerSec] |
shr ax, 1 ; words per sector |
mov cx, word [BPB_RsvdSecCnt] |
add cx, word [BPB_FATSz16] |
mul cx |
push ax ; save to stack count of words in boot+FAT |
xchg ax, cx |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
test ah, ah |
jz @f |
sayerr_floppy: |
mov dx, 0x3f2 |
mov al, 0 |
out dx, al |
sayerr_memmove: |
mov si, memmovefailed |
jmp sayerr_plain |
@@: |
pop ax ; restore from stack count of words in boot+FAT |
shl ax, 1 ; make bytes count from count of words |
and eax, 0ffffh |
add dword [si+8*3+2], eax |
; copy first FAT to second copy |
; TODO: BPB_NumFATs !!!!! |
add bx, word [BPB_BytsPerSec] ; !!! TODO: may be need multiply by BPB_RsvdSecCnt !!! |
mov byte [si+8*2+3], bh ; bx - begin of FAT |
mov ax, word [BPB_BytsPerSec] |
shr ax, 1 ; words per sector |
mov cx, word [BPB_FATSz16] |
mul cx |
mov cx, ax ; cx - count of words in FAT |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
test ah, ah |
jnz sayerr_floppy |
mov ax, cx |
shl ax, 1 |
and eax, 0ffffh ; ax - count of bytes in FAT |
add dword [si+8*3+2], eax |
; reading RootDir |
; TODO: BPB_NumFATs |
add bx, ax |
add bx, 100h |
and bx, 0ff00h ; bx - place in buffer to write RootDir |
push bx |
mov bx, word [BPB_BytsPerSec] |
shr bx, 5 ; divide bx by 32 |
mov ax, word [BPB_RootEntCnt] |
xor dx, dx |
div bx |
push ax ; ax - count of RootDir sectors |
mov ax, word [BPB_FATSz16] |
xor cx, cx |
mov cl, byte [BPB_NumFATs] |
mul cx |
add ax, word [BPB_RsvdSecCnt] ; ax - first sector of RootDir |
mov word [FirstDataSector], ax |
pop bx |
push bx |
add word [FirstDataSector], bx ; Begin of data region of floppy |
; read RootDir |
call conv_abs_to_THS |
pop ax |
pop bx ; place in buffer to write |
push ax |
call boot_read_floppy ; read RootDir into buffer |
; copy RootDir |
mov byte [si+8*2+3], bh ; from buffer |
pop ax ; ax = count of RootDir sectors |
mov cx, word [BPB_BytsPerSec] |
mul cx |
shr ax, 1 |
mov cx, ax ; count of words to copy |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
mov ax, cx |
shl ax, 1 |
and eax, 0ffffh ; ax - count of bytes in RootDir |
add dword [si+8*3+2], eax ; add count of bytes copied |
; Reading data clusters from floppy |
mov byte [si+8*2+3], bh |
push bx |
mov di, 2 ; First data cluster |
.read_loop: |
mov bx, di |
shr bx, 1 ; bx+di = di*1.5 |
jnc .even |
test word [es:bx+di+0xB200], 0xFFF0 ; TODO: may not be 0xB200 !!! |
jmp @f |
.even: |
test word [es:bx+di+0xB200], 0xFFF ; TODO: may not be 0xB200 !!! |
@@: |
jz .skip |
; read cluster di |
;.read: |
;conv cluster di to abs. sector ax |
; ax = (N-2) * BPB_SecPerClus + FirstDataSector |
mov ax, di |
sub ax, 2 |
xor bx, bx |
mov bl, byte [BPB_SecPerClus] |
mul bx |
add ax, word [FirstDataSector] |
call conv_abs_to_THS |
pop bx |
push bx |
mov al, byte [BPB_SecPerClus] ; number of sectors in cluster |
call boot_read_floppy |
push es |
push ds |
pop es |
pusha |
; |
mov ax, word [BPB_BytsPerSec] |
xor cx, cx |
mov cl, byte [BPB_SecPerClus] |
mul cx |
shr ax, 1 ; ax = (BPB_BytsPerSec * BPB_SecPerClus)/2 |
mov cx, ax ; number of words to copy (count words in cluster) |
; |
mov ah, 0x87 |
int 0x15 ; copy data |
test ah, ah |
popa |
pop es |
jnz sayerr_floppy |
; skip cluster di |
.skip: |
mov ax, word [BPB_BytsPerSec] |
xor cx, cx |
mov cl, byte [BPB_SecPerClus] |
mul cx |
and eax, 0ffffh ; ax - count of bytes in cluster |
add dword [si+8*3+2], eax |
mov ax, word [end_of_FAT] ; max cluster number |
pusha |
; draw percentage |
; total clusters: ax |
; read clusters: di |
xchg ax, di |
mov cx, 100 |
mul cx |
div di |
aam |
xchg al, ah |
add ax, '00' |
mov si, pros |
cmp [si], ax |
jz @f |
mov [si], ax |
call printplain |
@@: |
popa |
inc di |
cmp di, word [end_of_FAT] ; max number of cluster |
jnz .read_loop |
pop bx ; clear stack |
ok_sys_on_floppy: |
mov si, backspace2 |
call printplain |
mov si, okt |
call printplain |
no_sys_on_floppy: |
xor ax, ax ; reset drive |
xor dx, dx |
int 0x13 |
mov dx, 0x3f2 ; floppy motor off |
mov al, 0 |
out dx, al |
if defined extended_primary_loader |
cmp [boot_dev], 1 |
jne no_sys_from_primary |
; load kolibri.img using callback from primary loader |
and word [movedesc + 24 + 2], 0 |
mov byte [movedesc + 24 + 4], 10h |
; read in blocks of 64K until file is fully loaded |
mov ax, 1 |
.repeat: |
mov di, image_file_struct |
call [bootcallback] |
push cs |
pop ds |
push cs |
pop es |
cmp bx, 1 |
ja sayerr_badsect |
push bx |
mov si, movedesc |
and word [si + 16 + 2], 0 |
mov byte [si + 16 + 4], 4 |
mov ah, 87h |
mov cx, 8000h |
int 15h |
pop bx |
test ah, ah |
jnz sayerr_memmove |
inc byte [si + 24 + 4] |
test bx, bx |
jz no_sys_from_primary |
mov ax, 2 |
jmp .repeat |
no_sys_from_primary: |
end if |
; SET GRAPHICS |
xor ax, ax |
mov es, ax |
mov ax, [es:0x9008] ; vga & 320x200 |
mov bx, ax |
cmp ax, 0x13 |
je setgr |
cmp ax, 0x12 |
je setgr |
mov ax, 0x4f02 ; Vesa |
setgr: |
int 0x10 |
test ah, ah |
mov si, fatalsel |
jnz v_mode_error |
; set mode 0x12 graphics registers: |
cmp bx, 0x12 |
jne gmok2 |
mov al, 0x05 |
mov dx, 0x03ce |
push dx |
out dx, al ; select GDC mode register |
mov al, 0x02 |
inc dx |
out dx, al ; set write mode 2 |
mov al, 0x02 |
mov dx, 0x03c4 |
out dx, al ; select VGA sequencer map mask register |
mov al, 0x0f |
inc dx |
out dx, al ; set mask for all planes 0-3 |
mov al, 0x08 |
pop dx |
out dx, al ; select GDC bit mask register |
; for writes to 0x03cf |
gmok2: |
push ds |
pop es |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/booteng.inc |
---|
1,101 → 1,101 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
$Revision$ |
d80x25_bottom: |
db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY ' |
db 'NO WARRANTY ',186 |
db 186,' See file COPYING for details ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
novesa db "Display: EGA/CGA",13,10,0 |
s_vesa db "Version of VESA: " |
.ver db "?.?",13,10,0 |
gr_mode db "Select a videomode: ",13,10,0 |
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 |
if defined extended_primary_loader |
bdev db "Load ramdisk from [1-floppy; 2-kolibri.img]: ",0 |
else |
bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-use preloaded ram-image from kernel restart;" |
db 13,10,186," " |
db "4-create blank image]: ",0 |
end if |
prnotfnd db "Fatal - Videomode not found.",0 |
not386 db "Fatal - CPU 386+ required.",0 |
fatalsel db "Fatal - Graphics mode not supported by hardware.",0 |
pres_key db "Press any key to choose a new videomode.",0 |
badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0 |
memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Loading diskette: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Press [abcd] 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 |
current_cfg_msg db "Current settings:",13,10,0 |
curvideo_msg db " [a] Videomode: ",0 |
mode0 db "320x200, EGA/CGA 256 colors",13,10,0 |
mode9 db "640x480, VGA 16 colors",13,10,0 |
usebd_msg db " [b] Add disks visible by BIOS:",0 |
on_msg db " on",13,10,0 |
off_msg db " off",13,10,0 |
preboot_device_msg db " [c] Floppy image: ",0 |
if defined extended_primary_loader |
preboot_device_msgs dw 0,pdm1,pdm2,0 |
pdm1 db "real floppy",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
else |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "real floppy",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "use already loaded image",13,10,0 |
pdm4 db "create blank image",13,10,0 |
end if |
loading_msg db "Loading KolibriOS...",0 |
if ~ defined extended_primary_loader |
save_quest db "Remember current settings? [y/n]: ",0 |
loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0 |
end if |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0 |
remark1 db "Default values were selected to match most of configurations, but not all.",0 |
remark2 db "If the system does not boot, try to disable the item [b].",0 |
remarks dw remark1, remark2 |
num_remarks = 2 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
$Revision$ |
d80x25_bottom: |
db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY ' |
db 'NO WARRANTY ',186 |
db 186,' See file COPYING for details ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
novesa db "Display: EGA/CGA",13,10,0 |
s_vesa db "Version of VESA: " |
.ver db "?.?",13,10,0 |
gr_mode db "Select a videomode: ",13,10,0 |
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 |
if defined extended_primary_loader |
bdev db "Load ramdisk from [1-floppy; 2-kolibri.img]: ",0 |
else |
bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-use preloaded ram-image from kernel restart;" |
db 13,10,186," " |
db "4-create blank image]: ",0 |
end if |
prnotfnd db "Fatal - Videomode not found.",0 |
not386 db "Fatal - CPU 386+ required.",0 |
fatalsel db "Fatal - Graphics mode not supported by hardware.",0 |
pres_key db "Press any key to choose a new videomode.",0 |
badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0 |
memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Loading diskette: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Press [abcd] 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 |
current_cfg_msg db "Current settings:",13,10,0 |
curvideo_msg db " [a] Videomode: ",0 |
mode0 db "320x200, EGA/CGA 256 colors",13,10,0 |
mode9 db "640x480, VGA 16 colors",13,10,0 |
usebd_msg db " [b] Add disks visible by BIOS:",0 |
on_msg db " on",13,10,0 |
off_msg db " off",13,10,0 |
preboot_device_msg db " [c] Floppy image: ",0 |
if defined extended_primary_loader |
preboot_device_msgs dw 0,pdm1,pdm2,0 |
pdm1 db "real floppy",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
else |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "real floppy",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "use already loaded image",13,10,0 |
pdm4 db "create blank image",13,10,0 |
end if |
loading_msg db "Loading KolibriOS...",0 |
if ~ defined extended_primary_loader |
save_quest db "Remember current settings? [y/n]: ",0 |
loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0 |
end if |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0 |
remark1 db "Default values were selected to match most of configurations, but not all.",0 |
remark2 db "If the system does not boot, try to disable the item [b].",0 |
remarks dw remark1, remark2 |
num_remarks = 2 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/bootet.inc |
---|
1,101 → 1,101 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
$Revision$ |
d80x25_bottom: |
db 186,' KolibriOS pohineb MenuetOS ja kaasas IGASUGUSE GARANTI' |
db 'ITA ',186 |
db 186,' Naha faili COPYING detailid ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
novesa db "Ekraan: EGA/CGA",13,10,0 |
s_vesa db "Vesa versioon: " |
.ver db "?.?",13,10,0 |
gr_mode db "Vali videomode: ",13,10,0 |
ask_bd db "Lisa kettad nahtavaks BIOS reziim V86? [1-jah, 2-no]: ",0 |
if defined extended_primary_loader |
bdev db "Paigalda mäluketas [1-diskett; 2-kolibri.img]: ",0 |
else |
bdev db "Paigalda mäluketas [1-diskett; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-kasuta eellaaditud mäluketast kerneli restardist;" |
db 13,10,186," " |
db "4-loo tühi pilt]: ",0 |
end if |
prnotfnd db "Fataalne - Videoreziimi ei leitud.",0 |
not386 db "Fataalne - CPU 386+ on vajalik.",0 |
fatalsel db "Fataalne - Graafilist reziimi riistvara ei toeta.",0 |
pres_key db "Vajutage suvalist klahvi, et valida uus videomode.",0 |
badsect db 13,10,186," Fataalne - Vigane sektor. Asenda diskett.",0 |
memmovefailed db 13,10,186," Fataalne - Int 0x15 liigutamine ebaõnnestus.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Loen disketti: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Vajuta [abcd] seadete muutmiseks, vajuta [Enter] laadimise jätkamiseks",13,10,0 |
time_msg db " või oota " |
time_str db " 5 sekundit" |
db " automaatseks jätkamiseks",13,10,0 |
current_cfg_msg db "Praegused seaded:",13,10,0 |
curvideo_msg db " [a] Videoreziim: ",0 |
mode0 db "320x200, EGA/CGA 256 värvi",0 |
mode9 db "640x480, VGA 16 värvi",0 |
usebd_msg db " [b] Lisa kettad nahtavaks BIOS:",0 |
on_msg db " sees",13,10,0 |
off_msg db " väljas",13,10,0 |
preboot_device_msg db " [c] Disketi kujutis: ",0 |
if defined extended_primary_loader |
preboot_device_msgs dw 0,pdm1,pdm2,0 |
pdm1 db "reaalne diskett",13,10,0 |
pdm2 db "kolibri.img",13,10,0 |
else |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "reaalne diskett",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "kasuta juba laaditud kujutist",13,10,0 |
pdm4 db "loo tühi pilt",13,10,0 |
end if |
loading_msg db "Laadin KolibriOS...",0 |
if ~ defined extended_primary_loader |
save_quest db "Jäta meelde praegused seaded? [y/n]: ",0 |
loader_block_error db "Alglaaduri andmed vigased, ei saa jätkata. Peatatud.",0 |
end if |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0 |
remark1 db "Vaikimisi maaratud vaartused on valitud mugavuse enamikes, kuid mitte koik.",0 |
remark2 db "Kui susteem ei kaivitu, proovige lulitada kirje [b].",0 |
remarks dw remark1, remark2 |
num_remarks = 2 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
$Revision$ |
d80x25_bottom: |
db 186,' KolibriOS pohineb MenuetOS ja kaasas IGASUGUSE GARANTI' |
db 'ITA ',186 |
db 186,' Naha faili COPYING detailid ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
novesa db "Ekraan: EGA/CGA",13,10,0 |
s_vesa db "Vesa versioon: " |
.ver db "?.?",13,10,0 |
gr_mode db "Vali videomode: ",13,10,0 |
ask_bd db "Lisa kettad nahtavaks BIOS reziim V86? [1-jah, 2-no]: ",0 |
if defined extended_primary_loader |
bdev db "Paigalda mäluketas [1-diskett; 2-kolibri.img]: ",0 |
else |
bdev db "Paigalda mäluketas [1-diskett; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-kasuta eellaaditud mäluketast kerneli restardist;" |
db 13,10,186," " |
db "4-loo tühi pilt]: ",0 |
end if |
prnotfnd db "Fataalne - Videoreziimi ei leitud.",0 |
not386 db "Fataalne - CPU 386+ on vajalik.",0 |
fatalsel db "Fataalne - Graafilist reziimi riistvara ei toeta.",0 |
pres_key db "Vajutage suvalist klahvi, et valida uus videomode.",0 |
badsect db 13,10,186," Fataalne - Vigane sektor. Asenda diskett.",0 |
memmovefailed db 13,10,186," Fataalne - Int 0x15 liigutamine ebaõnnestus.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Loen disketti: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Vajuta [abcd] seadete muutmiseks, vajuta [Enter] laadimise jätkamiseks",13,10,0 |
time_msg db " või oota " |
time_str db " 5 sekundit" |
db " automaatseks jätkamiseks",13,10,0 |
current_cfg_msg db "Praegused seaded:",13,10,0 |
curvideo_msg db " [a] Videoreziim: ",0 |
mode0 db "320x200, EGA/CGA 256 värvi",0 |
mode9 db "640x480, VGA 16 värvi",0 |
usebd_msg db " [b] Lisa kettad nahtavaks BIOS:",0 |
on_msg db " sees",13,10,0 |
off_msg db " väljas",13,10,0 |
preboot_device_msg db " [c] Disketi kujutis: ",0 |
if defined extended_primary_loader |
preboot_device_msgs dw 0,pdm1,pdm2,0 |
pdm1 db "reaalne diskett",13,10,0 |
pdm2 db "kolibri.img",13,10,0 |
else |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "reaalne diskett",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "kasuta juba laaditud kujutist",13,10,0 |
pdm4 db "loo tühi pilt",13,10,0 |
end if |
loading_msg db "Laadin KolibriOS...",0 |
if ~ defined extended_primary_loader |
save_quest db "Jäta meelde praegused seaded? [y/n]: ",0 |
loader_block_error db "Alglaaduri andmed vigased, ei saa jätkata. Peatatud.",0 |
end if |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0 |
remark1 db "Vaikimisi maaratud vaartused on valitud mugavuse enamikes, kuid mitte koik.",0 |
remark2 db "Kui susteem ei kaivitu, proovige lulitada kirje [b].",0 |
remarks dw remark1, remark2 |
num_remarks = 2 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/bootge.inc |
---|
1,101 → 1,101 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
$Revision$ |
d80x25_bottom: |
db 186,' KolibriOS basiert auf MenuetOS und wird ohne jegliche ' |
db ' Garantie vertrieben ',186 |
db 186,' Details stehen in der Datei COPYING ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
novesa db "Anzeige: EGA/CGA ",13,10,0 |
s_vesa db "Vesa-Version: " |
.ver db "?.?",13,10,0 |
gr_mode db "Wahlen Sie einen videomode: ",13,10,0 |
ask_bd db "Add-Festplatten sichtbar BIOS in V86-Modus emuliert? [1-ja, 2 nein]: ",0 |
if defined extended_primary_loader |
bdev db "Lade die Ramdisk von [1-Diskette; 2-kolibri.img]: ",0 |
else |
bdev db "Lade die Ramdisk von [1-Diskette; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-benutze ein bereits geladenes Kernel image;" |
db 13,10,186," " |
db "4-create blank image]: ",0 |
end if |
prnotfnd db "Fatal - Videomodus nicht gefunden.",0 |
not386 db "Fatal - CPU 386+ benoetigt.",0 |
fatalsel db "Fatal - Grafikmodus nicht unterstuetzt.",0 |
pres_key db "Drucken Sie eine beliebige Taste, um eine neue videomode wahlen.",0 |
badsect db 13,10,186," Fatal - Sektorfehler, Andere Diskette neutzen.",0 |
memmovefailed db 13,10,186," Fatal - Int 0x15 Fehler.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Lade Diskette: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Druecke [abcd], um die Einstellungen zu aendern, druecke [Enter] zum starten",13,10,0 |
time_msg db " oder warte " |
time_str db " 5 Sekunden" |
db " bis zum automatischen Start",13,10,0 |
current_cfg_msg db "Aktuelle Einstellungen:",13,10,0 |
curvideo_msg db " [a] Videomodus: ",0 |
mode0 db "320x200, EGA/CGA 256 colors",13,10,0 |
mode9 db "640x480, VGA 16 colors",13,10,0 |
usebd_msg db " [b] Add-Festplatten sichtbar durch das BIOS:",0 |
on_msg db " an",13,10,0 |
off_msg db " aus",13,10,0 |
preboot_device_msg db " [c] Diskettenimage: ",0 |
if defined extended_primary_loader |
preboot_device_msgs dw 0,pdm1,pdm2,0 |
pdm1 db "Echte Diskette",13,10,0 |
pdm2 db "kolibri.img",13,10,0 |
else |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "Echte Diskette",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "Nutze bereits geladenes Image",13,10,0 |
pdm4 db "create blank image",13,10,0 |
end if |
loading_msg db "Lade KolibriOS...",0 |
if ~ defined extended_primary_loader |
save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0 |
loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0 |
end if |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0 |
remark1 db "Die Standardwerte sind fur die meisten gewahlt, aber nicht fur jedermann.",0 |
remark2 db "Wenn das System nicht bootet, versuchen, das Element [b] deaktivieren.",0 |
remarks dw remark1, remark2 |
num_remarks = 2 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
$Revision$ |
d80x25_bottom: |
db 186,' KolibriOS basiert auf MenuetOS und wird ohne jegliche ' |
db ' Garantie vertrieben ',186 |
db 186,' Details stehen in der Datei COPYING ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
novesa db "Anzeige: EGA/CGA ",13,10,0 |
s_vesa db "Vesa-Version: " |
.ver db "?.?",13,10,0 |
gr_mode db "Wahlen Sie einen videomode: ",13,10,0 |
ask_bd db "Add-Festplatten sichtbar BIOS in V86-Modus emuliert? [1-ja, 2 nein]: ",0 |
if defined extended_primary_loader |
bdev db "Lade die Ramdisk von [1-Diskette; 2-kolibri.img]: ",0 |
else |
bdev db "Lade die Ramdisk von [1-Diskette; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-benutze ein bereits geladenes Kernel image;" |
db 13,10,186," " |
db "4-create blank image]: ",0 |
end if |
prnotfnd db "Fatal - Videomodus nicht gefunden.",0 |
not386 db "Fatal - CPU 386+ benoetigt.",0 |
fatalsel db "Fatal - Grafikmodus nicht unterstuetzt.",0 |
pres_key db "Drucken Sie eine beliebige Taste, um eine neue videomode wahlen.",0 |
badsect db 13,10,186," Fatal - Sektorfehler, Andere Diskette neutzen.",0 |
memmovefailed db 13,10,186," Fatal - Int 0x15 Fehler.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Lade Diskette: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Druecke [abcd], um die Einstellungen zu aendern, druecke [Enter] zum starten",13,10,0 |
time_msg db " oder warte " |
time_str db " 5 Sekunden" |
db " bis zum automatischen Start",13,10,0 |
current_cfg_msg db "Aktuelle Einstellungen:",13,10,0 |
curvideo_msg db " [a] Videomodus: ",0 |
mode0 db "320x200, EGA/CGA 256 colors",13,10,0 |
mode9 db "640x480, VGA 16 colors",13,10,0 |
usebd_msg db " [b] Add-Festplatten sichtbar durch das BIOS:",0 |
on_msg db " an",13,10,0 |
off_msg db " aus",13,10,0 |
preboot_device_msg db " [c] Diskettenimage: ",0 |
if defined extended_primary_loader |
preboot_device_msgs dw 0,pdm1,pdm2,0 |
pdm1 db "Echte Diskette",13,10,0 |
pdm2 db "kolibri.img",13,10,0 |
else |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "Echte Diskette",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "Nutze bereits geladenes Image",13,10,0 |
pdm4 db "create blank image",13,10,0 |
end if |
loading_msg db "Lade KolibriOS...",0 |
if ~ defined extended_primary_loader |
save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0 |
loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0 |
end if |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0 |
remark1 db "Die Standardwerte sind fur die meisten gewahlt, aber nicht fur jedermann.",0 |
remark2 db "Wenn das System nicht bootet, versuchen, das Element [b] deaktivieren.",0 |
remarks dw remark1, remark2 |
num_remarks = 2 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/bootru.inc |
---|
1,101 → 1,101 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;================================================================= |
; |
; BOOT DATA |
; |
;================================================================= |
$Revision$ |
d80x25_bottom: |
db 186,' KolibriOS ®á®¢ MenuetOS ¨ ' |
db ' A. ',186 |
db 186,' ®¤à®¡¥¥ ᬮâà¨â¥ ¢ ä ©«¥ COPYING.TXT ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
novesa db "¨¤¥®ª àâ : EGA/CGA",13,10,0 |
s_vesa db "¥àá¨ï VESA: " |
.ver db "?.?",13,10,0 |
gr_mode db "ë¡¥à¨â¥ ¢¨¤¥®à¥¦¨¬: ",13,10,0 |
ask_bd db "®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS ¢ ०¨¬¥ V86? [1-¤ , 2-¥â]: ",0 |
if defined extended_primary_loader |
bdev db " £à㧨âì ®¡à § ¨§ [1-¤¨áª¥â ; 2-kolibri.img ¨§ ¯ ¯ª¨ § £à㧪¨]: ",0 |
else |
bdev db " £à㧨âì ®¡à § ¨§ [1-¤¨áª¥â ; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-¨á¯®«ì§®¢ âì 㦥 § £àã¦¥ë© ®¡à §;" |
db 13,10,186," " |
db "4-ᮧ¤ âì ç¨áâë© ®¡à §]: ",0 |
end if |
prnotfnd db "訡ª - ¨¤¥®à¥¦¨¬ ¥ ©¤¥.",0 |
not386 db "訡ª - ॡã¥âáï ¯à®æ¥áá®à 386+.",0 |
fatalsel db "訡ª - ë¡à ë© ¢¨¤¥®à¥¦¨¬ ¥ ¯®¤¤¥à¦¨¢ ¥âáï.",0 |
pres_key db " ¦¨¬¨â¥ «î¡ãî ª« ¢¨èã, ¤«ï ¯¥à¥å®¤ ¢ ¢ë¡®à ०¨¬®¢.",0 |
badsect db 13,10,186," 訡ª - ¨áª¥â ¯®¢à¥¦¤¥ . ®¯à®¡ã©â¥ ¤àã£ãî.",0 |
memmovefailed db 13,10,186," 訡ª - Int 0x15 move failed.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db " £à㧪 ¤¨áª¥âë: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 |
start_msg db " ¦¬¨â¥ [abcd] ¤«ï ¨§¬¥¥¨ï áâ஥ª, [Enter] ¤«ï ¯à®¤®«¦¥¨ï § £à㧪¨",13,10,0 |
time_msg db " ¨«¨ ¯®¤®¦¤¨â¥ " |
time_str db " 5 ᥪ㭤 " |
db " ¤® ¢â®¬ â¨ç¥áª®£® ¯à®¤®«¦¥¨ï",13,10,0 |
current_cfg_msg db "¥ªã騥 áâனª¨:",13,10,0 |
curvideo_msg db " [a] ¨¤¥®à¥¦¨¬: ",0 |
mode0 db "320x200, EGA/CGA 256 梥⮢",13,10,0 |
mode9 db "640x480, VGA 16 梥⮢",13,10,0 |
usebd_msg db " [b] ®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS:",0 |
on_msg db " ¢ª«",13,10,0 |
off_msg db " ¢ëª«",13,10,0 |
preboot_device_msg db " [c] ¡à § ¤¨áª¥âë: ",0 |
if defined extended_primary_loader |
preboot_device_msgs dw 0,pdm1,pdm2,0 |
pdm1 db " áâ®ïé ï ¤¨áª¥â ",13,10,0 |
pdm2 db "kolibri.img ¨§ ¯ ¯ª¨ § £à㧪¨",13,10,0 |
else |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4 |
pdm1 db " áâ®ïé ï ¤¨áª¥â ",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "¨á¯®«ì§®¢ âì 㦥 § £àã¦¥ë© ®¡à §",13,10,0 |
pdm4 db "ᮧ¤ âì ç¨áâë© ®¡à §",13,10,0 |
end if |
loading_msg db "¤ñâ § £à㧪 KolibriOS...",0 |
if ~ defined extended_primary_loader ; saving not supported in this case |
save_quest db " ¯®¬¨âì ⥪ã騥 áâனª¨? [y/n]: ",0 |
loader_block_error db "訡ª ¢ ¤ ëå ç «ì®£® § £àã§ç¨ª , ¯à®¤®«¦¥¨¥ ¥¢®§¬®¦®.",0 |
end if |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 梥⮢ ³ ³ ',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 梥⮢ ³ ³ ',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³ ',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ',13,10,0 |
remark1 db " ç¥¨ï ¯® 㬮«ç ¨î ¢ë¡à ë ¤«ï 㤮¡á⢠¡®«ìè¨á⢠, ® ¥ ¢á¥å.",0 |
remark2 db " ᫨ ã á ¥ £à㧨âáï á¨á⥬ , ¯®¯à®¡ã©â¥ ®âª«îç¨âì ¯ãªâ [b].",0 |
remarks dw remark1, remark2 |
num_remarks = 2 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;================================================================= |
; |
; BOOT DATA |
; |
;================================================================= |
$Revision$ |
d80x25_bottom: |
db 186,' KolibriOS ®á®¢ MenuetOS ¨ ' |
db ' A. ',186 |
db 186,' ®¤à®¡¥¥ ᬮâà¨â¥ ¢ ä ©«¥ COPYING.TXT ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
novesa db "¨¤¥®ª àâ : EGA/CGA",13,10,0 |
s_vesa db "¥àá¨ï VESA: " |
.ver db "?.?",13,10,0 |
gr_mode db "ë¡¥à¨â¥ ¢¨¤¥®à¥¦¨¬: ",13,10,0 |
ask_bd db "®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS ¢ ०¨¬¥ V86? [1-¤ , 2-¥â]: ",0 |
if defined extended_primary_loader |
bdev db " £à㧨âì ®¡à § ¨§ [1-¤¨áª¥â ; 2-kolibri.img ¨§ ¯ ¯ª¨ § £à㧪¨]: ",0 |
else |
bdev db " £à㧨âì ®¡à § ¨§ [1-¤¨áª¥â ; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-¨á¯®«ì§®¢ âì 㦥 § £àã¦¥ë© ®¡à §;" |
db 13,10,186," " |
db "4-ᮧ¤ âì ç¨áâë© ®¡à §]: ",0 |
end if |
prnotfnd db "訡ª - ¨¤¥®à¥¦¨¬ ¥ ©¤¥.",0 |
not386 db "訡ª - ॡã¥âáï ¯à®æ¥áá®à 386+.",0 |
fatalsel db "訡ª - ë¡à ë© ¢¨¤¥®à¥¦¨¬ ¥ ¯®¤¤¥à¦¨¢ ¥âáï.",0 |
pres_key db " ¦¨¬¨â¥ «î¡ãî ª« ¢¨èã, ¤«ï ¯¥à¥å®¤ ¢ ¢ë¡®à ०¨¬®¢.",0 |
badsect db 13,10,186," 訡ª - ¨áª¥â ¯®¢à¥¦¤¥ . ®¯à®¡ã©â¥ ¤àã£ãî.",0 |
memmovefailed db 13,10,186," 訡ª - Int 0x15 move failed.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db " £à㧪 ¤¨áª¥âë: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 |
start_msg db " ¦¬¨â¥ [abcd] ¤«ï ¨§¬¥¥¨ï áâ஥ª, [Enter] ¤«ï ¯à®¤®«¦¥¨ï § £à㧪¨",13,10,0 |
time_msg db " ¨«¨ ¯®¤®¦¤¨â¥ " |
time_str db " 5 ᥪ㭤 " |
db " ¤® ¢â®¬ â¨ç¥áª®£® ¯à®¤®«¦¥¨ï",13,10,0 |
current_cfg_msg db "¥ªã騥 áâனª¨:",13,10,0 |
curvideo_msg db " [a] ¨¤¥®à¥¦¨¬: ",0 |
mode0 db "320x200, EGA/CGA 256 梥⮢",13,10,0 |
mode9 db "640x480, VGA 16 梥⮢",13,10,0 |
usebd_msg db " [b] ®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS:",0 |
on_msg db " ¢ª«",13,10,0 |
off_msg db " ¢ëª«",13,10,0 |
preboot_device_msg db " [c] ¡à § ¤¨áª¥âë: ",0 |
if defined extended_primary_loader |
preboot_device_msgs dw 0,pdm1,pdm2,0 |
pdm1 db " áâ®ïé ï ¤¨áª¥â ",13,10,0 |
pdm2 db "kolibri.img ¨§ ¯ ¯ª¨ § £à㧪¨",13,10,0 |
else |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4 |
pdm1 db " áâ®ïé ï ¤¨áª¥â ",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "¨á¯®«ì§®¢ âì 㦥 § £àã¦¥ë© ®¡à §",13,10,0 |
pdm4 db "ᮧ¤ âì ç¨áâë© ®¡à §",13,10,0 |
end if |
loading_msg db "¤ñâ § £à㧪 KolibriOS...",0 |
if ~ defined extended_primary_loader ; saving not supported in this case |
save_quest db " ¯®¬¨âì ⥪ã騥 áâனª¨? [y/n]: ",0 |
loader_block_error db "訡ª ¢ ¤ ëå ç «ì®£® § £àã§ç¨ª , ¯à®¤®«¦¥¨¥ ¥¢®§¬®¦®.",0 |
end if |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 梥⮢ ³ ³ ',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 梥⮢ ³ ³ ',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³ ',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ',13,10,0 |
remark1 db " ç¥¨ï ¯® 㬮«ç ¨î ¢ë¡à ë ¤«ï 㤮¡á⢠¡®«ìè¨á⢠, ® ¥ ¢á¥å.",0 |
remark2 db " ᫨ ã á ¥ £à㧨âáï á¨á⥬ , ¯®¯à®¡ã©â¥ ®âª«îç¨âì ¯ãªâ [b].",0 |
remarks dw remark1, remark2 |
num_remarks = 2 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/bootstr.inc |
---|
1,62 → 1,63 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; boot data: common strings (for all languages) |
macro line_full_top { |
db 201 |
times 78 db 205 |
db 187 |
} |
macro line_full_bottom { |
db 200 |
times 78 db 205 |
db 188 |
} |
macro line_half { |
db 186,' ' |
times 76 db 0xc4 |
db ' ',186 |
} |
macro line_space { |
db 186 |
times 78 db 32 |
db 186 |
} |
d80x25_top: |
line_full_top |
cur_line_pos = 75 |
store byte ' ' at d80x25_top+cur_line_pos+1 |
rev_var = __REV__ |
while rev_var > 0 |
store byte rev_var mod 10 + '0' at d80x25_top+cur_line_pos |
cur_line_pos = cur_line_pos - 1 |
rev_var = rev_var / 10 |
end while |
store byte ' ' at d80x25_top+cur_line_pos |
store dword ' SVN' at d80x25_top+cur_line_pos-4 |
space_msg: line_space |
verstr: |
; line_space |
; version string |
db 186,32 |
repeat 78 |
load a byte from version+%-1 |
if a = 13 |
break |
end if |
db a |
end repeat |
repeat 78 - ($-verstr) |
db ' ' |
end repeat |
db 32,186 |
line_half |
d80x25_top_num = 4 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; boot data: common strings (for all languages) |
macro line_full_top { |
db 201 |
times 78 db 205 |
db 187 |
} |
macro line_full_bottom { |
db 200 |
times 78 db 205 |
db 188 |
} |
macro line_half { |
db 186,' ' |
times 76 db 0xc4 |
db ' ',186 |
} |
macro line_space { |
db 186 |
times 78 db 32 |
db 186 |
} |
d80x25_top: |
line_full_top |
cur_line_pos = 75 |
store byte ' ' at d80x25_top+cur_line_pos+1 |
rev_var = __REV__ |
while rev_var > 0 |
store byte rev_var mod 10 + '0' at d80x25_top+cur_line_pos |
cur_line_pos = cur_line_pos - 1 |
rev_var = rev_var / 10 |
end while |
store byte ' ' at d80x25_top+cur_line_pos |
store dword ' SVN' at d80x25_top+cur_line_pos-4 |
space_msg: |
line_space |
verstr: |
; line_space |
; version string |
db 186,32 |
repeat 78 |
load a byte from version+%-1 |
if a = 13 |
break |
end if |
db a |
end repeat |
repeat 78 - ($-verstr) |
db ' ' |
end repeat |
db 32,186 |
line_half |
d80x25_top_num = 4 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/bootvesa.inc |
---|
1,790 → 1,799 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
struc VBE_VGAInfo { |
.VESASignature dd ? ; char |
.VESAVersion dw ? ; short |
.OemStringPtr dd ? ; char * |
.Capabilities dd ? ; ulong |
.VideoModePtr dd ? ; ulong |
.TotalMemory dw ? ; short |
; VBE 2.0+ |
.OemSoftwareRev db ? ; short |
.OemVendorNamePtr dw ? ; char * |
.OemProductNamePtr dw ? ; char * |
.OemProductRevPtr dw ? ; char * |
.reserved rb 222 ; char |
.OemData rb 256 ; char |
} |
struc VBE_ModeInfo { |
.ModeAttributes dw ? ; short |
.WinAAttributes db ? ; char |
.WinBAttributes db ? ; char |
.WinGranularity dw ? ; short |
.WinSize dw ? ; short |
.WinASegment dw ? ; ushort |
.WinBSegment dw ? ; ushort |
.WinFuncPtr dd ? ; void * |
.BytesPerScanLine dw ? ; short |
.XRes dw ? ; short |
.YRes dw ? ; short |
.XCharSize db ? ; char |
.YCharSize db ? ; char |
.NumberOfPlanes db ? ; char |
.BitsPerPixel db ? ; char |
.NumberOfBanks db ? ; char |
.MemoryModel db ? ; char |
.BankSize db ? ; char |
.NumberOfImagePages db ? ; char |
.res1 db ? ; char |
.RedMaskSize db ? ; char |
.RedFieldPosition db ? ; char |
.GreenMaskSize db ? ; char |
.GreenFieldPosition db ? ; char |
.BlueMaskSize db ? ; char |
.BlueFieldPosition db ? ; char |
.RsvedMaskSize db ? ; char |
.RsvedFieldPosition db ? ; char |
.DirectColorModeInfo db ? ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE |
; VBE 2.0+ |
.PhysBasePtr dd ? ; ulong |
.OffScreenMemOffset dd ? ; ulong |
.OffScreenMemSize dw ? ; short |
; VBE 3.0+ |
.LinbytesPerScanLine dw ? ; short |
.BankNumberOfImagePages db ? ; char |
.LinNumberOfImagePages db ? ; char |
.LinRedMaskSize db ? ; char |
.LinRedFieldPosition db ? ; char |
.LingreenMaskSize db ? ; char |
.LinGreenFieldPosition db ? ; char |
.LinBlueMaskSize db ? ; char |
.LinBlueFieldPosition db ? ; char |
.LinRsvdMaskSize db ? ; char |
.LinRsvdFieldPosition db ? ; char |
.MaxPixelClock dd ? ; ulong |
.res2 rb 190 ; char |
} |
virtual at $A000 |
vi VBE_VGAInfo |
mi VBE_ModeInfo |
modes_table: |
end virtual |
cursor_pos dw 0 ;âðåìåííîå õðàíåíèå êóðñîðà. |
home_cursor dw 0 ;current shows rows a table |
end_cursor dw 0 ;end of position current shows rows a table |
scroll_start dw 0 ;start position of scroll bar |
scroll_end dw 0 ;end position of scroll bar |
long_v_table equ 9 ;long of visible video table |
size_of_step equ 10 |
scroll_area_size equ (long_v_table-2) |
int2str: |
dec bl |
jz @f |
xor edx,edx |
div ecx |
push edx |
call int2str |
pop eax |
@@: or al,0x30 |
mov [ds:di],al |
inc di |
ret |
int2strnz: |
cmp eax,ecx |
jb @f |
xor edx,edx |
div ecx |
push edx |
call int2strnz |
pop eax |
@@: or al,0x30 |
mov [es:di],al |
inc di |
ret |
;------------------------------------------------------- |
;Write message about incorrect v_mode and write message about jmp on swith v_mode |
v_mode_error: |
_setcursor 19,2 |
mov si, fatalsel |
call printplain |
_setcursor 20,2 |
mov si,pres_key |
call printplain |
xor eax,eax |
int 16h |
jmp cfgmanager.d |
;------------------------------------------------------- |
; |
;------------------------------------------------------- |
print_vesa_info: |
_setcursor 5,2 |
mov [es:vi.VESASignature],'VBE2' |
mov ax,0x4F00 |
mov di,vi ;0xa000 |
int 0x10 |
or ah,ah |
jz @f |
mov [es:vi.VESASignature],'VESA' |
mov ax,$4F00 |
mov di,vi |
int 0x10 |
or ah,ah |
jnz .exit |
@@: |
cmp [es:vi.VESASignature],'VESA' |
jne .exit |
cmp [es:vi.VESAVersion],0x0100 |
jb .exit |
jmp .vesaok2 |
.exit: |
mov si,novesa |
call printplain |
ret |
.vesaok2: |
mov ax,[es:vi.VESAVersion] |
add ax,'00' |
mov [s_vesa.ver], ah |
mov [s_vesa.ver+2], al |
mov si,s_vesa |
call printplain |
_setcursor 4,2 |
mov si,word[es:vi.OemStringPtr] |
mov di,si |
push ds |
mov ds,word[es:vi.OemStringPtr+2] |
call printplain |
pop ds |
ret |
;----------------------------------------------------------------------------- |
calc_vmodes_table: |
pushad |
; push 0 |
; pop es |
lfs si, [es:vi.VideoModePtr] |
mov bx,modes_table |
;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢ |
mov word [es:bx],640 |
mov word [es:bx+2],480 |
mov word [es:bx+6],0x13 |
mov word [es:bx+10],640 |
mov word [es:bx+12],480 |
mov word [es:bx+16],0x12 |
add bx,20 |
.next_mode: |
mov cx,word [fs:si] ; mode number |
cmp cx,-1 |
je .modes_ok.2 |
mov ax,0x4F01 |
mov di,mi |
int 0x10 |
or ah,ah |
jnz .modes_ok.2;vesa_info.exit |
test [es:mi.ModeAttributes],00000001b ;videomode support ? |
jz @f |
test [es:mi.ModeAttributes],00010000b ;picture ? |
jz @f |
test [es:mi.ModeAttributes],10000000b ;LFB ? |
jz @f |
cmp [es:mi.BitsPerPixel], 24 ;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 |
; mov [es:mi.BitsPerPixel],15 |
.l0: |
cmp [es:mi.XRes],640 |
jb @f |
cmp [es:mi.YRes],480 |
jb @f |
; cmp [es:mi.BitsPerPixel],8 |
; jb @f |
mov ax,[es:mi.XRes] |
mov [es:bx+0],ax ; +0[2] : resolution X |
mov ax,[es:mi.YRes] |
mov [es:bx+2],ax ; +2[2] : resolution Y |
mov ax,[es:mi.ModeAttributes] |
mov [es:bx+4],ax ; +4[2] : attributes |
cmp [s_vesa.ver],'2' |
jb .lp1 |
or cx,0x4000 ; use LFB |
.lp1: mov [es:bx+6],cx ; +6 : mode number |
movzx ax,byte [es:mi.BitsPerPixel] |
mov word [es:bx+8],ax ; +8 : bits per pixel |
add bx,size_of_step ; size of record |
@@: |
add si,2 |
jmp .next_mode |
.modes_ok.2: |
mov word[es:bx],-1 ;end video table |
mov word[end_cursor],bx ;save end cursor position |
;;;;;;;;;;;;;;;;;; |
;Sort array |
; mov si,modes_table |
;.new_mode: |
; mov ax,word [es:si] |
; cmp ax,-1 |
; je .exxit |
; add ax,word [es:si+2] |
; add ax,word [es:si+8] |
; mov bp,si |
;.again: |
; add bp,12 |
; mov bx,word [es:bp] |
; cmp bx,-1 |
; je .exit |
; add bx,word [es:bp+2] |
; add bx,word [es:bp+8] |
; |
; cmp ax,bx |
; ja .loops |
; jmp .again |
;.loops: |
; push dword [es:si] |
; push dword [es:si+4] |
; push dword [es:si+8] |
; push dword [es:bp] |
; push dword [es:bp+4] |
; push dword [es:bp+8] |
; |
; pop dword [es:si+8] |
; pop dword [es:si+4] |
; pop dword [es:si] |
; pop dword [es:bp+8] |
; pop dword [es:bp+4] |
; pop dword [es:bp] |
; jmp .new_mode |
; |
;.exit: add si,12 |
; jmp .new_mode |
;.exxit: |
popad |
ret |
;----------------------------------------------------------------------------- |
draw_current_vmode: |
push 0 |
pop es |
mov si,word [cursor_pos] |
cmp word [es:si+6],0x12 |
je .no_vesa_0x12 |
cmp word [es:si+6],0x13 |
je .no_vesa_0x13 |
if defined extended_primary_loader |
mov di,config_file_variables |
else |
mov di,loader_block_error |
end if |
movzx eax,word[es:si+0] |
mov ecx,10 |
call int2strnz |
mov byte[es:di],'x' |
inc di |
movzx eax,word[es:si+2] |
call int2strnz |
mov byte[es:di],'x' |
inc di |
movzx eax,word[es:si+8] |
call int2strnz |
mov dword[es:di],0x00000d0a |
if defined extended_primary_loader |
mov si,config_file_variables |
else |
mov si,loader_block_error |
end if |
push ds |
push es |
pop ds |
call printplain |
pop ds |
ret |
.no_vesa_0x13: |
mov si,mode0 |
jmp .print |
.no_vesa_0x12: |
mov si,mode9 |
.print: |
call printplain |
ret |
;----------------------------------------------------------------------------- |
check_first_parm: |
if defined extended_primary_loader |
mov cx, [number_vm] |
jcxz .novbemode |
mov si, modes_table |
.findvbemode: |
cmp [es:si+6], cx |
jnz @f |
cmp word [es:si+8],32 |
je .ok_found_mode |
cmp word [es:si+8],24 |
je .ok_found_mode |
@@: add si,size_of_step |
cmp word [es:si],-1 |
jnz .findvbemode |
.novbemode: |
mov ax, [x_save] |
test ax, ax |
jz .zerro |
mov bx, [y_save] |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
else |
mov si,word [preboot_graph] |
test si,si |
jnz .no_zero ;if no zero |
end if |
.zerro: |
; mov ax,modes_table |
; mov word [cursor_pos],ax |
; 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 ax,1024 |
mov bx,768 |
mov si,modes_table |
call .loops |
test ax,ax |
jz .ok_found_mode |
mov ax,800 |
mov bx,600 |
mov si,modes_table |
call .loops |
test ax,ax |
jz .ok_found_mode |
mov ax,640 |
mov bx,480 |
mov si,modes_table |
call .loops |
test ax,ax |
jz .ok_found_mode |
mov si,modes_table |
if ~ defined extended_primary_loader |
jmp .ok_found_mode |
.no_zero: |
mov bp,word [number_vm] |
cmp bp,word [es:si+6] |
jz .ok_found_mode |
mov ax,word [x_save] |
mov bx,word [y_save] |
mov si,modes_table |
call .loops |
test ax,ax |
jz .ok_found_mode |
mov si,modes_table |
; cmp ax,modes_table |
; jb .zerro ;check on correct if bellow |
; cmp ax,word [end_cursor] |
; ja .zerro ;check on correct if anymore |
end if |
.ok_found_mode: |
mov word [home_cursor],si |
; mov word [cursor_pos],si |
mov word [preboot_graph],si |
mov ax,si |
mov ecx,long_v_table |
.loop: add ax,size_of_step |
cmp ax,word [end_cursor] |
jae .next_step |
loop .loop |
.next_step: |
sub ax,size_of_step*long_v_table |
cmp ax,modes_table |
jae @f |
mov ax,modes_table |
@@: |
mov word [home_cursor],ax |
mov si,[preboot_graph] |
mov word [cursor_pos],si |
push word [es:si] |
pop word [x_save] |
push word [es:si+2] |
pop word [y_save] |
push word [es:si+6] |
pop word [number_vm] |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.loops: |
cmp ax,word [es:si] |
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 |
.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 |
;----------------------------------------------------------------------------- |
;default_vmode: |
;----------------------------------------------------------------------------- |
draw_vmodes_table: |
_setcursor 9, 2 |
mov si,gr_mode |
call printplain |
mov si,_st |
call printplain |
push word [cursor_pos] |
pop ax |
push word [home_cursor] |
pop si |
mov cx,si |
cmp ax,si |
je .ok |
jb .low |
add cx,size_of_step*long_v_table |
cmp ax,cx |
jb .ok |
sub cx,size_of_step*long_v_table |
add cx,size_of_step |
cmp cx,word[end_cursor] |
jae .ok |
add si,size_of_step |
push si |
pop word [home_cursor] |
jmp .ok |
.low: sub cx,size_of_step |
cmp cx,modes_table |
jb .ok |
push cx |
push cx |
pop word [home_cursor] |
pop si |
.ok: |
; calculate scroll position |
push si |
mov ax, [end_cursor] |
sub ax, modes_table |
mov bx, size_of_step |
cwd |
div bx |
mov si, ax ; si = size of list |
mov ax, [home_cursor] |
sub ax, modes_table |
cwd |
div bx |
mov di, ax |
mov ax, scroll_area_size*long_v_table |
cwd |
div si |
test ax, ax |
jnz @f |
inc ax |
@@: |
cmp al, scroll_area_size |
jb @f |
mov al, scroll_area_size |
@@: |
mov cx, ax |
; cx = scroll height |
; calculate scroll pos |
xor bx, bx ; initialize scroll pos |
sub al, scroll_area_size+1 |
neg al |
sub si, long_v_table-1 |
jbe @f |
mul di |
div si |
mov bx, ax |
@@: |
inc bx |
imul ax, bx, size_of_step |
add ax, [home_cursor] |
mov [scroll_start], ax |
imul cx, size_of_step |
add ax, cx |
mov [scroll_end], ax |
pop si |
mov bp,long_v_table ;show rows |
.@@_next_bit: |
;clear cursor |
mov ax,' ' |
mov word[ds:_r1+21],ax |
mov word[ds:_r1+50],ax |
mov word[ds:_r2+21],ax |
mov word[ds:_r2+45],ax |
mov word[ds:_rs+21],ax |
mov word[ds:_rs+46],ax |
; draw string |
cmp word [es:si+6],0x12 |
je .show_0x12 |
cmp word [es:si+6],0x13 |
je .show_0x13 |
movzx eax,word[es:si] |
cmp ax,-1 |
je .@@_end |
mov di,_rs+23 |
mov ecx,10 |
mov bl,4 |
call int2str |
movzx eax,word[es:si+2] |
inc di |
mov bl,4 |
call int2str |
movzx eax,word[es:si+8] |
inc di |
mov bl,2 |
call int2str |
cmp si, word [cursor_pos] |
jne .next |
;draw cursor |
mov word[ds:_rs+21],'>>' |
mov word[ds:_rs+46],'<<' |
.next: |
push si |
mov si,_rs |
.@@_sh: |
; add to the string pseudographics for scrollbar |
pop bx |
push bx |
mov byte [si+53], ' ' |
cmp bx, [scroll_start] |
jb @f |
cmp bx, [scroll_end] |
jae @f |
mov byte [si+53], 0xDB ; filled bar |
@@: |
push bx |
add bx, size_of_step |
cmp bx, [end_cursor] |
jnz @f |
mov byte [si+53], 31 ; 'down arrow' symbol |
@@: |
sub bx, [home_cursor] |
cmp bx, size_of_step*long_v_table |
jnz @f |
mov byte [si+53], 31 ; 'down arrow' symbol |
@@: |
pop bx |
cmp bx, [home_cursor] |
jnz @f |
mov byte [si+53], 30 ; 'up arrow' symbol |
@@: |
call printplain |
pop si |
add si,size_of_step |
dec bp |
jnz .@@_next_bit |
.@@_end: |
mov si,_bt |
call printplain |
ret |
.show_0x13: |
push si |
cmp si, word [cursor_pos] |
jne @f |
mov word[ds:_r1+21],'>>' |
mov word[ds:_r1+50],'<<' |
@@: |
mov si,_r1 |
jmp .@@_sh |
.show_0x12: |
push si |
cmp si, word [cursor_pos] |
jne @f |
mov word[ds:_r2+21],'>>' |
mov word[ds:_r2+45],'<<' |
@@: |
mov si,_r2 |
jmp .@@_sh |
;----------------------------------------------------------------------------- |
;Clear arrea of current video page (0xb800) |
clear_vmodes_table: |
pusha |
; draw frames |
push es |
push 0xb800 |
pop es |
mov di,1444 |
xor ax,ax |
mov ah, 1*16+15 |
mov cx,70 |
mov bp,12 |
.loop_start: |
rep stosw |
mov cx,70 |
add di,20 |
dec bp |
jns .loop_start |
pop es |
popa |
ret |
;----------------------------------------------------------------------------- |
set_vmode: |
push 0 ;0;x1000 |
pop es |
mov si,word [preboot_graph] ;[preboot_graph] |
mov cx,word [es:si+6] ; number of mode |
mov ax,word [es:si+0] ; resolution X |
mov bx,word [es:si+2] ; resolution Y |
mov word [es:0x900A],ax ; resolution X |
mov word [es:0x900C],bx ; resolution Y |
mov word [es:0x9008],cx ; number of mode |
cmp cx,0x12 |
je .mode0x12_0x13 |
cmp cx,0x13 |
je .mode0x12_0x13 |
cmp byte [s_vesa.ver],'2' |
jb .vesa12 |
; VESA 2 and Vesa 3 |
mov ax,0x4f01 |
and cx,0xfff |
mov di,mi;0xa000 |
int 0x10 |
; LFB |
mov eax,[es:mi.PhysBasePtr];di+0x28] |
mov [es:0x9018],eax |
; ---- vbe voodoo |
BytesPerLine equ 0x10 |
mov ax, [es:di+BytesPerLine] |
mov [es:0x9001], ax |
; BPP |
cmp [es:mi.BitsPerPixel],16 |
jne .l0 |
cmp [es:mi.GreenMaskSize],5 |
jne .l0 |
mov [es:mi.BitsPerPixel],15 |
.l0: |
mov al, byte [es:di+0x19] |
mov [es:0x9000], al |
jmp .exit |
.mode0x12_0x13: |
mov byte [es:0x9000], 32 |
or dword [es:0x9018], 0xFFFFFFFF; 0x800000 |
; VESA 1.2 PM BANK SWITCH ADDRESS |
.vesa12: |
mov ax,0x4f0A |
xor bx,bx |
int 0x10 |
xor eax,eax |
xor ebx,ebx |
mov ax,es |
shl eax,4 |
mov bx,di |
add eax,ebx |
movzx ebx,word[es:di] |
add eax,ebx |
push 0x0000 |
pop es |
mov [es:0x9014],eax |
.exit: |
ret |
; mov dword[es:0x9018],0x000A0000 |
; ret |
;============================================================================= |
;============================================================================= |
;============================================================================= |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
struc VBE_VGAInfo { |
.VESASignature dd ? ; char |
.VESAVersion dw ? ; short |
.OemStringPtr dd ? ; char * |
.Capabilities dd ? ; ulong |
.VideoModePtr dd ? ; ulong |
.TotalMemory dw ? ; short |
; VBE 2.0+ |
.OemSoftwareRev db ? ; short |
.OemVendorNamePtr dw ? ; char * |
.OemProductNamePtr dw ? ; char * |
.OemProductRevPtr dw ? ; char * |
.reserved rb 222 ; char |
.OemData rb 256 ; char |
} |
struc VBE_ModeInfo { |
.ModeAttributes dw ? ; short |
.WinAAttributes db ? ; char |
.WinBAttributes db ? ; char |
.WinGranularity dw ? ; short |
.WinSize dw ? ; short |
.WinASegment dw ? ; ushort |
.WinBSegment dw ? ; ushort |
.WinFuncPtr dd ? ; void * |
.BytesPerScanLine dw ? ; short |
.XRes dw ? ; short |
.YRes dw ? ; short |
.XCharSize db ? ; char |
.YCharSize db ? ; char |
.NumberOfPlanes db ? ; char |
.BitsPerPixel db ? ; char |
.NumberOfBanks db ? ; char |
.MemoryModel db ? ; char |
.BankSize db ? ; char |
.NumberOfImagePages db ? ; char |
.res1 db ? ; char |
.RedMaskSize db ? ; char |
.RedFieldPosition db ? ; char |
.GreenMaskSize db ? ; char |
.GreenFieldPosition db ? ; char |
.BlueMaskSize db ? ; char |
.BlueFieldPosition db ? ; char |
.RsvedMaskSize db ? ; char |
.RsvedFieldPosition db ? ; char |
.DirectColorModeInfo db ? ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE |
; VBE 2.0+ |
.PhysBasePtr dd ? ; ulong |
.OffScreenMemOffset dd ? ; ulong |
.OffScreenMemSize dw ? ; short |
; VBE 3.0+ |
.LinbytesPerScanLine dw ? ; short |
.BankNumberOfImagePages db ? ; char |
.LinNumberOfImagePages db ? ; char |
.LinRedMaskSize db ? ; char |
.LinRedFieldPosition db ? ; char |
.LingreenMaskSize db ? ; char |
.LinGreenFieldPosition db ? ; char |
.LinBlueMaskSize db ? ; char |
.LinBlueFieldPosition db ? ; char |
.LinRsvdMaskSize db ? ; char |
.LinRsvdFieldPosition db ? ; char |
.MaxPixelClock dd ? ; ulong |
.res2 rb 190 ; char |
} |
virtual at $A000 |
vi VBE_VGAInfo |
mi VBE_ModeInfo |
modes_table: |
end virtual |
cursor_pos dw 0 ;âðåìåííîå õðàíåíèå êóðñîðà. |
home_cursor dw 0 ;current shows rows a table |
end_cursor dw 0 ;end of position current shows rows a table |
scroll_start dw 0 ;start position of scroll bar |
scroll_end dw 0 ;end position of scroll bar |
long_v_table equ 9 ;long of visible video table |
size_of_step equ 10 |
scroll_area_size equ (long_v_table-2) |
int2str: |
dec bl |
jz @f |
xor edx, edx |
div ecx |
push edx |
call int2str |
pop eax |
@@: |
or al, 0x30 |
mov [ds:di], al |
inc di |
ret |
int2strnz: |
cmp eax, ecx |
jb @f |
xor edx, edx |
div ecx |
push edx |
call int2strnz |
pop eax |
@@: |
or al, 0x30 |
mov [es:di], al |
inc di |
ret |
;------------------------------------------------------- |
;Write message about incorrect v_mode and write message about jmp on swith v_mode |
v_mode_error: |
_setcursor 19,2 |
mov si, fatalsel |
call printplain |
_setcursor 20,2 |
mov si, pres_key |
call printplain |
xor eax, eax |
int 16h |
jmp cfgmanager.d |
;------------------------------------------------------- |
; |
;------------------------------------------------------- |
print_vesa_info: |
_setcursor 5,2 |
mov [es:vi.VESASignature], 'VBE2' |
mov ax, 0x4F00 |
mov di, vi ;0xa000 |
int 0x10 |
or ah, ah |
jz @f |
mov [es:vi.VESASignature], 'VESA' |
mov ax, $4F00 |
mov di, vi |
int 0x10 |
or ah, ah |
jnz .exit |
@@: |
cmp [es:vi.VESASignature], 'VESA' |
jne .exit |
cmp [es:vi.VESAVersion], 0x0100 |
jb .exit |
jmp .vesaok2 |
.exit: |
mov si, novesa |
call printplain |
ret |
.vesaok2: |
mov ax, [es:vi.VESAVersion] |
add ax, '00' |
mov [s_vesa.ver], ah |
mov [s_vesa.ver+2], al |
mov si, s_vesa |
call printplain |
_setcursor 4,2 |
mov si, word[es:vi.OemStringPtr] |
mov di, si |
push ds |
mov ds, word[es:vi.OemStringPtr+2] |
call printplain |
pop ds |
ret |
;----------------------------------------------------------------------------- |
calc_vmodes_table: |
pushad |
; push 0 |
; pop es |
lfs si, [es:vi.VideoModePtr] |
mov bx, modes_table |
;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢ |
mov word [es:bx], 640 |
mov word [es:bx+2], 480 |
mov word [es:bx+6], 0x13 |
mov word [es:bx+10], 640 |
mov word [es:bx+12], 480 |
mov word [es:bx+16], 0x12 |
add bx, 20 |
.next_mode: |
mov cx, word [fs:si]; mode number |
cmp cx, -1 |
je .modes_ok.2 |
mov ax, 0x4F01 |
mov di, mi |
int 0x10 |
or ah, ah |
jnz .modes_ok.2;vesa_info.exit |
test [es:mi.ModeAttributes], 00000001b ;videomode support ? |
jz @f |
test [es:mi.ModeAttributes], 00010000b ;picture ? |
jz @f |
test [es:mi.ModeAttributes], 10000000b ;LFB ? |
jz @f |
cmp [es:mi.BitsPerPixel], 24 ;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 |
; mov [es:mi.BitsPerPixel],15 |
.l0: |
cmp [es:mi.XRes], 640 |
jb @f |
cmp [es:mi.YRes], 480 |
jb @f |
; cmp [es:mi.BitsPerPixel],8 |
; jb @f |
mov ax, [es:mi.XRes] |
mov [es:bx+0], ax ; +0[2] : resolution X |
mov ax, [es:mi.YRes] |
mov [es:bx+2], ax ; +2[2] : resolution Y |
mov ax, [es:mi.ModeAttributes] |
mov [es:bx+4], ax ; +4[2] : attributes |
cmp [s_vesa.ver], '2' |
jb .lp1 |
or cx, 0x4000 ; use LFB |
.lp1: |
mov [es:bx+6], cx ; +6 : mode number |
movzx ax, byte [es:mi.BitsPerPixel] |
mov word [es:bx+8], ax ; +8 : bits per pixel |
add bx, size_of_step ; size of record |
@@: |
add si, 2 |
jmp .next_mode |
.modes_ok.2: |
mov word[es:bx], -1 ;end video table |
mov word[end_cursor], bx ;save end cursor position |
;;;;;;;;;;;;;;;;;; |
;Sort array |
; mov si,modes_table |
;.new_mode: |
; mov ax,word [es:si] |
; cmp ax,-1 |
; je .exxit |
; add ax,word [es:si+2] |
; add ax,word [es:si+8] |
; mov bp,si |
;.again: |
; add bp,12 |
; mov bx,word [es:bp] |
; cmp bx,-1 |
; je .exit |
; add bx,word [es:bp+2] |
; add bx,word [es:bp+8] |
; |
; cmp ax,bx |
; ja .loops |
; jmp .again |
;.loops: |
; push dword [es:si] |
; push dword [es:si+4] |
; push dword [es:si+8] |
; push dword [es:bp] |
; push dword [es:bp+4] |
; push dword [es:bp+8] |
; |
; pop dword [es:si+8] |
; pop dword [es:si+4] |
; pop dword [es:si] |
; pop dword [es:bp+8] |
; pop dword [es:bp+4] |
; pop dword [es:bp] |
; jmp .new_mode |
; |
;.exit: add si,12 |
; jmp .new_mode |
;.exxit: |
popad |
ret |
;----------------------------------------------------------------------------- |
draw_current_vmode: |
push 0 |
pop es |
mov si, word [cursor_pos] |
cmp word [es:si+6], 0x12 |
je .no_vesa_0x12 |
cmp word [es:si+6], 0x13 |
je .no_vesa_0x13 |
if defined extended_primary_loader |
mov di, config_file_variables |
else |
mov di, loader_block_error |
end if |
movzx eax, word[es:si+0] |
mov ecx, 10 |
call int2strnz |
mov byte[es:di], 'x' |
inc di |
movzx eax, word[es:si+2] |
call int2strnz |
mov byte[es:di], 'x' |
inc di |
movzx eax, word[es:si+8] |
call int2strnz |
mov dword[es:di], 0x00000d0a |
if defined extended_primary_loader |
mov si, config_file_variables |
else |
mov si, loader_block_error |
end if |
push ds |
push es |
pop ds |
call printplain |
pop ds |
ret |
.no_vesa_0x13: |
mov si, mode0 |
jmp .print |
.no_vesa_0x12: |
mov si, mode9 |
.print: |
call printplain |
ret |
;----------------------------------------------------------------------------- |
check_first_parm: |
if defined extended_primary_loader |
mov cx, [number_vm] |
jcxz .novbemode |
mov si, modes_table |
.findvbemode: |
cmp [es:si+6], cx |
jnz @f |
cmp word [es:si+8], 32 |
je .ok_found_mode |
cmp word [es:si+8], 24 |
je .ok_found_mode |
@@: |
add si, size_of_step |
cmp word [es:si], -1 |
jnz .findvbemode |
.novbemode: |
mov ax, [x_save] |
test ax, ax |
jz .zerro |
mov bx, [y_save] |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
else |
mov si, word [preboot_graph] |
test si, si |
jnz .no_zero ;if no zero |
end if |
.zerro: |
; mov ax,modes_table |
; mov word [cursor_pos],ax |
; 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 ax, 1024 |
mov bx, 768 |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
mov ax, 800 |
mov bx, 600 |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
mov ax, 640 |
mov bx, 480 |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
mov si, modes_table |
if ~ defined extended_primary_loader |
jmp .ok_found_mode |
.no_zero: |
mov bp, word [number_vm] |
cmp bp, word [es:si+6] |
jz .ok_found_mode |
mov ax, word [x_save] |
mov bx, word [y_save] |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
mov si, modes_table |
; cmp ax,modes_table |
; jb .zerro ;check on correct if bellow |
; cmp ax,word [end_cursor] |
; ja .zerro ;check on correct if anymore |
end if |
.ok_found_mode: |
mov word [home_cursor], si |
; mov word [cursor_pos],si |
mov word [preboot_graph], si |
mov ax, si |
mov ecx, long_v_table |
.loop: |
add ax, size_of_step |
cmp ax, word [end_cursor] |
jae .next_step |
loop .loop |
.next_step: |
sub ax, size_of_step*long_v_table |
cmp ax, modes_table |
jae @f |
mov ax, modes_table |
@@: |
mov word [home_cursor], ax |
mov si, [preboot_graph] |
mov word [cursor_pos], si |
push word [es:si] |
pop word [x_save] |
push word [es:si+2] |
pop word [y_save] |
push word [es:si+6] |
pop word [number_vm] |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.loops: |
cmp ax, word [es:si] |
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 |
.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 |
;----------------------------------------------------------------------------- |
;default_vmode: |
;----------------------------------------------------------------------------- |
draw_vmodes_table: |
_setcursor 9, 2 |
mov si, gr_mode |
call printplain |
mov si, _st |
call printplain |
push word [cursor_pos] |
pop ax |
push word [home_cursor] |
pop si |
mov cx, si |
cmp ax, si |
je .ok |
jb .low |
add cx, size_of_step*long_v_table |
cmp ax, cx |
jb .ok |
sub cx, size_of_step*long_v_table |
add cx, size_of_step |
cmp cx, word[end_cursor] |
jae .ok |
add si, size_of_step |
push si |
pop word [home_cursor] |
jmp .ok |
.low: |
sub cx, size_of_step |
cmp cx, modes_table |
jb .ok |
push cx |
push cx |
pop word [home_cursor] |
pop si |
.ok: |
; calculate scroll position |
push si |
mov ax, [end_cursor] |
sub ax, modes_table |
mov bx, size_of_step |
cwd |
div bx |
mov si, ax ; si = size of list |
mov ax, [home_cursor] |
sub ax, modes_table |
cwd |
div bx |
mov di, ax |
mov ax, scroll_area_size*long_v_table |
cwd |
div si |
test ax, ax |
jnz @f |
inc ax |
@@: |
cmp al, scroll_area_size |
jb @f |
mov al, scroll_area_size |
@@: |
mov cx, ax |
; cx = scroll height |
; calculate scroll pos |
xor bx, bx ; initialize scroll pos |
sub al, scroll_area_size+1 |
neg al |
sub si, long_v_table-1 |
jbe @f |
mul di |
div si |
mov bx, ax |
@@: |
inc bx |
imul ax, bx, size_of_step |
add ax, [home_cursor] |
mov [scroll_start], ax |
imul cx, size_of_step |
add ax, cx |
mov [scroll_end], ax |
pop si |
mov bp, long_v_table ;show rows |
.@@_next_bit: |
;clear cursor |
mov ax, ' ' |
mov word[ds:_r1+21], ax |
mov word[ds:_r1+50], ax |
mov word[ds:_r2+21], ax |
mov word[ds:_r2+45], ax |
mov word[ds:_rs+21], ax |
mov word[ds:_rs+46], ax |
; draw string |
cmp word [es:si+6], 0x12 |
je .show_0x12 |
cmp word [es:si+6], 0x13 |
je .show_0x13 |
movzx eax, word[es:si] |
cmp ax, -1 |
je .@@_end |
mov di, _rs+23 |
mov ecx, 10 |
mov bl, 4 |
call int2str |
movzx eax, word[es:si+2] |
inc di |
mov bl, 4 |
call int2str |
movzx eax, word[es:si+8] |
inc di |
mov bl, 2 |
call int2str |
cmp si, word [cursor_pos] |
jne .next |
;draw cursor |
mov word[ds:_rs+21], '>>' |
mov word[ds:_rs+46], '<<' |
.next: |
push si |
mov si, _rs |
.@@_sh: |
; add to the string pseudographics for scrollbar |
pop bx |
push bx |
mov byte [si+53], ' ' |
cmp bx, [scroll_start] |
jb @f |
cmp bx, [scroll_end] |
jae @f |
mov byte [si+53], 0xDB ; filled bar |
@@: |
push bx |
add bx, size_of_step |
cmp bx, [end_cursor] |
jnz @f |
mov byte [si+53], 31 ; 'down arrow' symbol |
@@: |
sub bx, [home_cursor] |
cmp bx, size_of_step*long_v_table |
jnz @f |
mov byte [si+53], 31 ; 'down arrow' symbol |
@@: |
pop bx |
cmp bx, [home_cursor] |
jnz @f |
mov byte [si+53], 30 ; 'up arrow' symbol |
@@: |
call printplain |
pop si |
add si, size_of_step |
dec bp |
jnz .@@_next_bit |
.@@_end: |
mov si, _bt |
call printplain |
ret |
.show_0x13: |
push si |
cmp si, word [cursor_pos] |
jne @f |
mov word[ds:_r1+21], '>>' |
mov word[ds:_r1+50], '<<' |
@@: |
mov si, _r1 |
jmp .@@_sh |
.show_0x12: |
push si |
cmp si, word [cursor_pos] |
jne @f |
mov word[ds:_r2+21], '>>' |
mov word[ds:_r2+45], '<<' |
@@: |
mov si, _r2 |
jmp .@@_sh |
;----------------------------------------------------------------------------- |
;Clear arrea of current video page (0xb800) |
clear_vmodes_table: |
pusha |
; draw frames |
push es |
push 0xb800 |
pop es |
mov di, 1444 |
xor ax, ax |
mov ah, 1*16+15 |
mov cx, 70 |
mov bp, 12 |
.loop_start: |
rep stosw |
mov cx, 70 |
add di, 20 |
dec bp |
jns .loop_start |
pop es |
popa |
ret |
;----------------------------------------------------------------------------- |
set_vmode: |
push 0 ;0;x1000 |
pop es |
mov si, word [preboot_graph] ;[preboot_graph] |
mov cx, word [es:si+6] ; number of mode |
mov ax, word [es:si+0] ; resolution X |
mov bx, word [es:si+2] ; resolution Y |
mov word [es:0x900A], ax ; resolution X |
mov word [es:0x900C], bx ; resolution Y |
mov word [es:0x9008], cx ; number of mode |
cmp cx, 0x12 |
je .mode0x12_0x13 |
cmp cx, 0x13 |
je .mode0x12_0x13 |
cmp byte [s_vesa.ver], '2' |
jb .vesa12 |
; VESA 2 and Vesa 3 |
mov ax, 0x4f01 |
and cx, 0xfff |
mov di, mi;0xa000 |
int 0x10 |
; LFB |
mov eax, [es:mi.PhysBasePtr];di+0x28] |
mov [es:0x9018], eax |
; ---- vbe voodoo |
BytesPerLine equ 0x10 |
mov ax, [es:di+BytesPerLine] |
mov [es:0x9001], ax |
; BPP |
cmp [es:mi.BitsPerPixel], 16 |
jne .l0 |
cmp [es:mi.GreenMaskSize], 5 |
jne .l0 |
mov [es:mi.BitsPerPixel], 15 |
.l0: |
mov al, byte [es:di+0x19] |
mov [es:0x9000], al |
jmp .exit |
.mode0x12_0x13: |
mov byte [es:0x9000], 32 |
or dword [es:0x9018], 0xFFFFFFFF; 0x800000 |
; VESA 1.2 PM BANK SWITCH ADDRESS |
.vesa12: |
mov ax, 0x4f0A |
xor bx, bx |
int 0x10 |
xor eax, eax |
xor ebx, ebx |
mov ax, es |
shl eax, 4 |
mov bx, di |
add eax, ebx |
movzx ebx, word[es:di] |
add eax, ebx |
push 0x0000 |
pop es |
mov [es:0x9014], eax |
.exit: |
ret |
; mov dword[es:0x9018],0x000A0000 |
; ret |
;============================================================================= |
;============================================================================= |
;============================================================================= |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/et.inc |
---|
1,16 → 1,16 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Full ASCII code font |
; only õ and ä added |
; Kaitz |
ET_FNT: |
fontfile file "ETFONT.FNT" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Full ASCII code font |
; only õ and ä added |
; Kaitz |
ET_FNT: |
fontfile file "ETFONT.FNT" |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/parsers.inc |
---|
1,170 → 1,170 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; All parsers are called with ds:si -> value of the variable, |
; possibly with spaces before, and dx = limit of config file. |
; Three subroutines parse_char, parse_number and parse_bool set CF |
; if something has failed, otherwise return the value in al/ax. |
parse_timeout: |
; timeout is a number not greater than 9 |
call parse_number |
jc .nothing |
cmp ax, 9 |
jbe @f |
mov ax, 9 |
@@: |
imul ax, 18 |
mov [es:preboot_timeout], ax |
.nothing: |
ret |
parse_resolution: |
; resolution is <width>*<height>, 'x' can be used instead of '*' |
; parse width |
call parse_number |
jc .nothing |
; save width |
xchg ax, bx |
; test for 'x' or '*' |
call parse_char |
cmp al, 'x' |
jz @f |
cmp al, '*' |
jnz .nothing |
@@: |
; parse height |
call parse_number |
jc .nothing |
; write width and height |
mov [es:x_save], bx |
mov [es:y_save], ax |
.nothing: |
ret |
parse_vbemode: |
; vbemode is a number |
call parse_number |
jc .nothing |
mov [es:number_vm], ax |
.nothing: |
ret |
;parse_vrr: |
;; vrr is a boolean setting |
; call parse_bool |
; jc .nothing |
;; convert 0 to 2, 1 to 1 |
; inc ax |
; xor al, 3 |
; mov [es:preboot_vrrm], al |
;.nothing: |
; ret |
parse_biosdisks: |
; using biosdisks is a boolean setting |
call parse_bool |
jc .nothing |
; convert 0 to 2, 1 to 1 |
inc ax |
xor al, 3 |
mov [es:preboot_biosdisk], al |
.nothing: |
ret |
parse_imgfrom: |
; boot device (1-floppy 2-kolibri.img using primary loader) |
call parse_number |
jc .nothing |
cmp al, 1 |
jb .nothing |
cmp al, 2 |
ja .nothing |
mov [es:preboot_device], al |
.nothing: |
ret |
parse_char: |
; skip spaces and return the next character or CF if EOF. |
cmp si, dx |
jae .eof |
lodsb |
cmp al, ' ' |
jbe parse_char |
ret |
.eof: |
stc |
ret |
parse_number: |
; initialize high part of ax to zero |
xor ax, ax |
; skip spaces |
call parse_char |
jc .bad |
; al should be a digit |
sub al, '0' |
cmp al, 9 |
ja .bad |
; accumulate the value in cx |
xchg cx, ax |
@@: |
cmp si, dx |
jae .eof |
lodsb |
sub al, '0' |
cmp al, 9 |
ja .end |
imul cx, 10 |
add cx, ax |
jmp @b |
; if the end is caused by non-digit, unwind the last character |
.end: |
dec si |
.eof: |
xchg cx, ax |
clc |
ret |
.bad: |
stc |
ret |
parse_bool: |
; skip spaces |
call parse_char |
jc .bad |
; Boolean false can be represented as 0=no=off, |
; boolean true can be represented as 1=yes=on. |
cmp al, '0' |
jz .false |
cmp al, '1' |
jz .true |
mov ah, al |
cmp si, dx |
jae .bad |
lodsb |
cmp ax, 'n'*256 + 'o' |
jz .false |
cmp ax, 'o'*256 + 'f' |
jz .false |
cmp ax, 'y'*256 + 'e' |
jz .true |
cmp ax, 'o'*256 + 'n' |
jz .true |
.bad: |
stc |
ret |
.true: |
xor ax, ax |
inc ax |
ret |
.false: |
xor ax, ax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; All parsers are called with ds:si -> value of the variable, |
; possibly with spaces before, and dx = limit of config file. |
; Three subroutines parse_char, parse_number and parse_bool set CF |
; if something has failed, otherwise return the value in al/ax. |
parse_timeout: |
; timeout is a number not greater than 9 |
call parse_number |
jc .nothing |
cmp ax, 9 |
jbe @f |
mov ax, 9 |
@@: |
imul ax, 18 |
mov [es:preboot_timeout], ax |
.nothing: |
ret |
parse_resolution: |
; resolution is <width>*<height>, 'x' can be used instead of '*' |
; parse width |
call parse_number |
jc .nothing |
; save width |
xchg ax, bx |
; test for 'x' or '*' |
call parse_char |
cmp al, 'x' |
jz @f |
cmp al, '*' |
jnz .nothing |
@@: |
; parse height |
call parse_number |
jc .nothing |
; write width and height |
mov [es:x_save], bx |
mov [es:y_save], ax |
.nothing: |
ret |
parse_vbemode: |
; vbemode is a number |
call parse_number |
jc .nothing |
mov [es:number_vm], ax |
.nothing: |
ret |
;parse_vrr: |
;; vrr is a boolean setting |
; call parse_bool |
; jc .nothing |
;; convert 0 to 2, 1 to 1 |
; inc ax |
; xor al, 3 |
; mov [es:preboot_vrrm], al |
;.nothing: |
; ret |
parse_biosdisks: |
; using biosdisks is a boolean setting |
call parse_bool |
jc .nothing |
; convert 0 to 2, 1 to 1 |
inc ax |
xor al, 3 |
mov [es:preboot_biosdisk], al |
.nothing: |
ret |
parse_imgfrom: |
; boot device (1-floppy 2-kolibri.img using primary loader) |
call parse_number |
jc .nothing |
cmp al, 1 |
jb .nothing |
cmp al, 2 |
ja .nothing |
mov [es:preboot_device], al |
.nothing: |
ret |
parse_char: |
; skip spaces and return the next character or CF if EOF. |
cmp si, dx |
jae .eof |
lodsb |
cmp al, ' ' |
jbe parse_char |
ret |
.eof: |
stc |
ret |
parse_number: |
; initialize high part of ax to zero |
xor ax, ax |
; skip spaces |
call parse_char |
jc .bad |
; al should be a digit |
sub al, '0' |
cmp al, 9 |
ja .bad |
; accumulate the value in cx |
xchg cx, ax |
@@: |
cmp si, dx |
jae .eof |
lodsb |
sub al, '0' |
cmp al, 9 |
ja .end |
imul cx, 10 |
add cx, ax |
jmp @b |
; if the end is caused by non-digit, unwind the last character |
.end: |
dec si |
.eof: |
xchg cx, ax |
clc |
ret |
.bad: |
stc |
ret |
parse_bool: |
; skip spaces |
call parse_char |
jc .bad |
; Boolean false can be represented as 0=no=off, |
; boolean true can be represented as 1=yes=on. |
cmp al, '0' |
jz .false |
cmp al, '1' |
jz .true |
mov ah, al |
cmp si, dx |
jae .bad |
lodsb |
cmp ax, 'n'*256 + 'o' |
jz .false |
cmp ax, 'o'*256 + 'f' |
jz .false |
cmp ax, 'y'*256 + 'e' |
jz .true |
cmp ax, 'o'*256 + 'n' |
jz .true |
.bad: |
stc |
ret |
.true: |
xor ax, ax |
inc ax |
ret |
.false: |
xor ax, ax |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/preboot.inc |
---|
1,41 → 1,42 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
display_modechg db 0 ; display mode change for text, yes/no (0 or 2) |
; |
; !! Important note !! |
; |
; Must be set to 2, to avoid two screenmode |
; changes within a very short period of time. |
display_atboot db 0 ; show boot screen messages ( 2-no ) |
preboot_graph dw 0 ; graph mode |
x_save dw 0 ; x |
y_save dw 0 ; y |
number_vm dw 0 ; |
;pixel_save dw 0 ; per to pixel |
preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) |
;preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) |
preboot_dma db 0 ; use DMA for access to HDD (1-always, 2-only for read, 3-never) |
preboot_device db 0 ; boot device |
; (1-floppy 2-harddisk 3-kernel restart 4-format ram disk) |
;!!!! 0 - autodetect !!!! |
preboot_blogesc = 0 ; start immediately after bootlog |
preboot_biosdisk db 0 ; use V86 to access disks through BIOS (1-yes, 2-no) |
if defined extended_primary_loader |
preboot_timeout dw 5*18 ; timeout in 1/18th of second for config settings screen |
end if |
if $>0x200 |
ERROR: prebooting parameters must fit in first sector!!! |
end if |
hdsysimage db 'KOLIBRI IMG' ; load from |
image_save db 'KOLIBRI IMG' ; save to |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
display_modechg db 0 ; display mode change for text, yes/no (0 or 2) |
; |
; !! Important note !! |
; |
; Must be set to 2, to avoid two screenmode |
; changes within a very short period of time. |
display_atboot db 0 ; show boot screen messages ( 2-no ) |
preboot_graph dw 0 ; graph mode |
x_save dw 0 ; x |
y_save dw 0 ; y |
number_vm dw 0 ; |
;pixel_save dw 0 ; per to pixel |
preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) |
;preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) |
preboot_dma db 0 ; use DMA for access to HDD (1-always, 2-only for read, 3-never) |
preboot_device db 0 ; boot device |
; (1-floppy 2-harddisk 3-kernel restart 4-format ram disk) |
;!!!! 0 - autodetect !!!! |
preboot_blogesc = 0 ; start immediately after bootlog |
preboot_biosdisk db 0 ; use V86 to access disks through BIOS (1-yes, 2-no) |
if defined extended_primary_loader |
preboot_timeout dw 5*18 ; timeout in 1/18th of second for config settings screen |
end if |
if $>0x200 |
ERROR: |
prebooting parameters must fit in first sector!!! |
end if |
hdsysimage db 'KOLIBRI IMG' ; load from |
image_save db 'KOLIBRI IMG' ; save to |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/rdload.inc |
---|
1,125 → 1,125 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; READ RAMDISK IMAGE FROM HD |
cmp [boot_dev+OS_BASE+0x10000],1 |
jne no_sys_on_hd |
test [DRIVE_DATA+1],byte 0x40 |
jz position_2 |
mov [hdbase],0x1f0 |
mov [hdid],0x0 |
mov [hdpos],1 |
mov [fat32part],0 |
position_1_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved],1 |
je yes_sys_on_hd |
movzx eax,byte [DRIVE_DATA+2] |
cmp [fat32part],eax |
jle position_1_1 |
position_2: |
test [DRIVE_DATA+1],byte 0x10 |
jz position_3 |
mov [hdbase],0x1f0 |
mov [hdid],0x10 |
mov [hdpos],2 |
mov [fat32part],0 |
position_2_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved],1 |
je yes_sys_on_hd |
movzx eax,byte [DRIVE_DATA+3] |
cmp eax,[fat32part] |
jle position_2_1 |
position_3: |
test [DRIVE_DATA+1],byte 0x4 |
jz position_4 |
mov [hdbase],0x170 |
mov [hdid],0x0 |
mov [hdpos],3 |
mov [fat32part],0 |
position_3_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved],1 |
je yes_sys_on_hd |
movzx eax,byte [DRIVE_DATA+4] |
cmp eax,[fat32part] |
jle position_3_1 |
position_4: |
test [DRIVE_DATA+1],byte 0x1 |
jz no_sys_on_hd |
mov [hdbase],0x170 |
mov [hdid],0x10 |
mov [hdpos],4 |
mov [fat32part],0 |
position_4_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved],1 |
je yes_sys_on_hd |
movzx eax,byte [DRIVE_DATA+5] |
cmp eax,[fat32part] |
jle position_4_1 |
jmp yes_sys_on_hd |
search_and_read_image: |
call set_FAT32_variables |
mov edx, bootpath |
call read_image |
test eax, eax |
jz image_present |
mov edx, bootpath2 |
call read_image |
test eax, eax |
jz image_present |
ret |
image_present: |
mov [image_retrieved],1 |
ret |
read_image: |
mov eax, hdsysimage+OS_BASE+0x10000 |
mov ebx, 1474560/512 |
mov ecx, RAMDISK |
mov esi, 0 |
mov edi, 12 |
call file_read |
ret |
image_retrieved db 0 |
counter_of_partitions db 0 |
no_sys_on_hd: |
; test_to_format_ram_disk (need if not using ram disk) |
cmp [boot_dev+OS_BASE+0x10000],3 |
jne not_format_ram_disk |
; format_ram_disk |
mov edi, RAMDISK |
mov ecx, 0x1080 |
xor eax,eax |
@@: |
stosd |
loop @b |
mov ecx, 0x58F7F |
mov eax,0xF6F6F6F6 |
@@: |
stosd |
loop @b |
mov [RAMDISK+0x200],dword 0xFFFFF0 ; fat table |
mov [RAMDISK+0x4200],dword 0xFFFFF0 |
not_format_ram_disk: |
yes_sys_on_hd: |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; READ RAMDISK IMAGE FROM HD |
cmp [boot_dev+OS_BASE+0x10000], 1 |
jne no_sys_on_hd |
test [DRIVE_DATA+1], byte 0x40 |
jz position_2 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x0 |
mov [hdpos], 1 |
mov [fat32part], 0 |
position_1_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved], 1 |
je yes_sys_on_hd |
movzx eax, byte [DRIVE_DATA+2] |
cmp [fat32part], eax |
jle position_1_1 |
position_2: |
test [DRIVE_DATA+1], byte 0x10 |
jz position_3 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x10 |
mov [hdpos], 2 |
mov [fat32part], 0 |
position_2_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved], 1 |
je yes_sys_on_hd |
movzx eax, byte [DRIVE_DATA+3] |
cmp eax, [fat32part] |
jle position_2_1 |
position_3: |
test [DRIVE_DATA+1], byte 0x4 |
jz position_4 |
mov [hdbase], 0x170 |
mov [hdid], 0x0 |
mov [hdpos], 3 |
mov [fat32part], 0 |
position_3_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved], 1 |
je yes_sys_on_hd |
movzx eax, byte [DRIVE_DATA+4] |
cmp eax, [fat32part] |
jle position_3_1 |
position_4: |
test [DRIVE_DATA+1], byte 0x1 |
jz no_sys_on_hd |
mov [hdbase], 0x170 |
mov [hdid], 0x10 |
mov [hdpos], 4 |
mov [fat32part], 0 |
position_4_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved], 1 |
je yes_sys_on_hd |
movzx eax, byte [DRIVE_DATA+5] |
cmp eax, [fat32part] |
jle position_4_1 |
jmp yes_sys_on_hd |
search_and_read_image: |
call set_FAT32_variables |
mov edx, bootpath |
call read_image |
test eax, eax |
jz image_present |
mov edx, bootpath2 |
call read_image |
test eax, eax |
jz image_present |
ret |
image_present: |
mov [image_retrieved], 1 |
ret |
read_image: |
mov eax, hdsysimage+OS_BASE+0x10000 |
mov ebx, 1474560/512 |
mov ecx, RAMDISK |
mov esi, 0 |
mov edi, 12 |
call file_read |
ret |
image_retrieved db 0 |
counter_of_partitions db 0 |
no_sys_on_hd: |
; test_to_format_ram_disk (need if not using ram disk) |
cmp [boot_dev+OS_BASE+0x10000], 3 |
jne not_format_ram_disk |
; format_ram_disk |
mov edi, RAMDISK |
mov ecx, 0x1080 |
xor eax, eax |
@@: |
stosd |
loop @b |
mov ecx, 0x58F7F |
mov eax, 0xF6F6F6F6 |
@@: |
stosd |
loop @b |
mov [RAMDISK+0x200], dword 0xFFFFF0 ; fat table |
mov [RAMDISK+0x4200], dword 0xFFFFF0 |
not_format_ram_disk: |
yes_sys_on_hd: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/ru.inc |
---|
1,102 → 1,102 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Generated by RUFNT.EXE |
; By BadBugsKiller (C) |
; Modifyed by BadBugsKiller 12.01.2004 17:45 |
; Øðèôò óìåíüøåí â ðàçìåðå è òåïåðü ñîñòîèò èç 2-óõ ÷àñòåé, |
; ñîäåðæàùèõ òîëüêî ñèìâîëû ðóññêîãî àëôàâèòà. |
; ñèìâîëû â êîäèðîâêå ASCII (ÄÎÑ'îâñêàÿ), êîäîâàÿ ñòðàíèöà 866. |
RU_FNT1: |
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
RU_FNT2: |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 |
db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 |
db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Generated by RUFNT.EXE |
; By BadBugsKiller (C) |
; Modifyed by BadBugsKiller 12.01.2004 17:45 |
; Øðèôò óìåíüøåí â ðàçìåðå è òåïåðü ñîñòîèò èç 2-óõ ÷àñòåé, |
; ñîäåðæàùèõ òîëüêî ñèìâîëû ðóññêîãî àëôàâèòà. |
; ñèìâîëû â êîäèðîâêå ASCII (ÄÎÑ'îâñêàÿ), êîäîâàÿ ñòðàíèöà 866. |
RU_FNT1: |
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
RU_FNT2: |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 |
db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 |
db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/boot/shutdown.inc |
---|
1,212 → 1,212 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Shutdown for Menuet ;; |
;; ;; |
;; Distributed under General Public License ;; |
;; See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
align 4 |
pr_mode_exit: |
; setup stack |
mov ax, 0x3000 |
mov ss, ax |
mov esp, 0x0EC00 |
; setup ds |
push cs |
pop ds |
lidt [old_ints_h] |
;remap IRQs |
mov al,0x11 |
out 0x20,al |
call rdelay |
out 0xA0,al |
call rdelay |
mov al,0x08 |
out 0x21,al |
call rdelay |
mov al,0x70 |
out 0xA1,al |
call rdelay |
mov al,0x04 |
out 0x21,al |
call rdelay |
mov al,0x02 |
out 0xA1,al |
call rdelay |
mov al,0x01 |
out 0x21,al |
call rdelay |
out 0xA1,al |
call rdelay |
mov al,0xB8 |
out 0x21,al |
call rdelay |
mov al,0xBD |
out 0xA1,al |
sti |
temp_3456: |
xor ax,ax |
mov es,ax |
mov al,byte [es:0x9030] |
cmp al,1 |
jl nbw |
cmp al,4 |
jle nbw32 |
nbw: |
in al,0x60 |
cmp al,6 |
jae nbw |
mov bl,al |
nbw2: |
in al,0x60 |
cmp al,bl |
je nbw2 |
cmp al,240 ;ax,240 |
jne nbw31 |
mov al,bl |
dec ax |
jmp nbw32 |
nbw31: |
add bl,128 |
cmp al,bl |
jne nbw |
sub al,129 |
nbw32: |
dec ax |
dec ax ; 2 = power off |
jnz no_apm_off |
call APM_PowerOff |
jmp $ |
no_apm_off: |
if ~ defined extended_primary_loader ; kernel restarting is not supported |
dec ax ; 3 = reboot |
jnz restart_kernel ; 4 = restart kernel |
end if |
push 0x40 |
pop ds |
mov word[0x0072],0x1234 |
jmp 0xF000:0xFFF0 |
rdelay: |
ret |
APM_PowerOff: |
mov ax, 5304h |
xor bx, bx |
int 15h |
;!!!!!!!!!!!!!!!!!!!!!!!! |
mov ax,0x5300 |
xor bx,bx |
int 0x15 |
push ax |
mov ax,0x5301 |
xor bx,bx |
int 0x15 |
mov ax,0x5308 |
mov bx,1 |
mov cx,bx |
int 0x15 |
mov ax,0x530E |
xor bx,bx |
pop cx |
int 0x15 |
mov ax,0x530D |
mov bx,1 |
mov cx,bx |
int 0x15 |
mov ax,0x530F |
mov bx,1 |
mov cx,bx |
int 0x15 |
mov ax,0x5307 |
mov bx,1 |
mov cx,3 |
int 0x15 |
;!!!!!!!!!!!!!!!!!!!!!!!! |
ret |
if ~ defined extended_primary_loader |
restart_kernel: |
mov ax,0x0003 ; set text mode for screen |
int 0x10 |
jmp 0x4000:0000 |
restart_kernel_4000: |
cli |
push ds |
pop es |
mov cx, 0x8000 |
push cx |
push 0x7000 |
pop ds |
xor si, si |
xor di, di |
rep movsw |
pop cx |
mov ds, cx |
push 0x2000 |
pop es |
rep movsw |
push 0x9000 |
pop ds |
push 0x3000 |
pop es |
mov cx, 0xE000/2 |
rep movsw |
wbinvd ; write and invalidate cache |
mov al, 00110100b |
out 43h, al |
jcxz $+2 |
mov al, 0xFF |
out 40h, al |
jcxz $+2 |
out 40h, al |
jcxz $+2 |
sti |
; (hint by Black_mirror) |
; We must read data from keyboard port, |
; because there may be situation when previous keyboard interrupt is lost |
; (due to return to real mode and IRQ reprogramming) |
; and next interrupt will not be generated (as keyboard waits for handling) |
in al, 0x60 |
; bootloader interface |
push 0x1000 |
pop ds |
mov si, kernel_restart_bootblock |
mov ax, 'KL' |
jmp 0x1000:0000 |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Shutdown for Menuet ;; |
;; ;; |
;; Distributed under General Public License ;; |
;; See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
align 4 |
pr_mode_exit: |
; setup stack |
mov ax, 0x3000 |
mov ss, ax |
mov esp, 0x0EC00 |
; setup ds |
push cs |
pop ds |
lidt [old_ints_h] |
;remap IRQs |
mov al, 0x11 |
out 0x20, al |
call rdelay |
out 0xA0, al |
call rdelay |
mov al, 0x08 |
out 0x21, al |
call rdelay |
mov al, 0x70 |
out 0xA1, al |
call rdelay |
mov al, 0x04 |
out 0x21, al |
call rdelay |
mov al, 0x02 |
out 0xA1, al |
call rdelay |
mov al, 0x01 |
out 0x21, al |
call rdelay |
out 0xA1, al |
call rdelay |
mov al, 0xB8 |
out 0x21, al |
call rdelay |
mov al, 0xBD |
out 0xA1, al |
sti |
temp_3456: |
xor ax, ax |
mov es, ax |
mov al, byte [es:0x9030] |
cmp al, 1 |
jl nbw |
cmp al, 4 |
jle nbw32 |
nbw: |
in al, 0x60 |
cmp al, 6 |
jae nbw |
mov bl, al |
nbw2: |
in al, 0x60 |
cmp al, bl |
je nbw2 |
cmp al, 240;ax,240 |
jne nbw31 |
mov al, bl |
dec ax |
jmp nbw32 |
nbw31: |
add bl, 128 |
cmp al, bl |
jne nbw |
sub al, 129 |
nbw32: |
dec ax |
dec ax ; 2 = power off |
jnz no_apm_off |
call APM_PowerOff |
jmp $ |
no_apm_off: |
if ~ defined extended_primary_loader ; kernel restarting is not supported |
dec ax ; 3 = reboot |
jnz restart_kernel ; 4 = restart kernel |
end if |
push 0x40 |
pop ds |
mov word[0x0072], 0x1234 |
jmp 0xF000:0xFFF0 |
rdelay: |
ret |
APM_PowerOff: |
mov ax, 5304h |
xor bx, bx |
int 15h |
;!!!!!!!!!!!!!!!!!!!!!!!! |
mov ax, 0x5300 |
xor bx, bx |
int 0x15 |
push ax |
mov ax, 0x5301 |
xor bx, bx |
int 0x15 |
mov ax, 0x5308 |
mov bx, 1 |
mov cx, bx |
int 0x15 |
mov ax, 0x530E |
xor bx, bx |
pop cx |
int 0x15 |
mov ax, 0x530D |
mov bx, 1 |
mov cx, bx |
int 0x15 |
mov ax, 0x530F |
mov bx, 1 |
mov cx, bx |
int 0x15 |
mov ax, 0x5307 |
mov bx, 1 |
mov cx, 3 |
int 0x15 |
;!!!!!!!!!!!!!!!!!!!!!!!! |
ret |
if ~ defined extended_primary_loader |
restart_kernel: |
mov ax, 0x0003 ; set text mode for screen |
int 0x10 |
jmp 0x4000:0000 |
restart_kernel_4000: |
cli |
push ds |
pop es |
mov cx, 0x8000 |
push cx |
push 0x7000 |
pop ds |
xor si, si |
xor di, di |
rep movsw |
pop cx |
mov ds, cx |
push 0x2000 |
pop es |
rep movsw |
push 0x9000 |
pop ds |
push 0x3000 |
pop es |
mov cx, 0xE000/2 |
rep movsw |
wbinvd ; write and invalidate cache |
mov al, 00110100b |
out 43h, al |
jcxz $+2 |
mov al, 0xFF |
out 40h, al |
jcxz $+2 |
out 40h, al |
jcxz $+2 |
sti |
; (hint by Black_mirror) |
; We must read data from keyboard port, |
; because there may be situation when previous keyboard interrupt is lost |
; (due to return to real mode and IRQ reprogramming) |
; and next interrupt will not be generated (as keyboard waits for handling) |
in al, 0x60 |
; bootloader interface |
push 0x1000 |
pop ds |
mov si, kernel_restart_bootblock |
mov ax, 'KL' |
jmp 0x1000:0000 |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/boot_fat12.asm |
---|
8,15 → 8,15 |
; |
; Version 1.0 |
lf equ 0ah |
cr equ 0dh |
lf equ 0ah |
cr equ 0dh |
pos_read_tmp equ 0700h ;position for temporary read |
boot_program equ 07c00h ;position for boot code |
seg_read_kernel equ 01000h ;segment to kernel read |
pos_read_tmp equ 0700h ;position for temporary read |
boot_program equ 07c00h ;position for boot code |
seg_read_kernel equ 01000h ;segment to kernel read |
jmp start_program |
nop |
jmp start_program |
nop |
; Boot Sector and BPB Structure |
include 'floppy1440.inc' |
26,262 → 26,262 |
start_program: |
xor ax,ax |
mov ss,ax |
mov sp,boot_program |
push ss |
pop ds |
xor ax, ax |
mov ss, ax |
mov sp, boot_program |
push ss |
pop ds |
; print loading string |
mov si,loading+boot_program |
; print loading string |
mov si, loading+boot_program |
loop_loading: |
lodsb |
or al,al |
jz read_root_directory |
mov ah,0eh |
mov bx,7 |
int 10h |
jmp loop_loading |
lodsb |
or al, al |
jz read_root_directory |
mov ah, 0eh |
mov bx, 7 |
int 10h |
jmp loop_loading |
read_root_directory: |
push ss |
pop es |
push ss |
pop es |
; calculate some disk parameters |
; - beginning sector of RootDir |
mov ax,word [BPB_FATSz16+boot_program] |
xor cx,cx |
mov cl,byte [BPB_NumFATs+boot_program] |
mul cx |
add ax,word [BPB_RsvdSecCnt+boot_program] |
mov word [FirstRootDirSecNum+boot_program],ax ; 19 |
mov si,ax |
; calculate some disk parameters |
; - beginning sector of RootDir |
mov ax, word [BPB_FATSz16+boot_program] |
xor cx, cx |
mov cl, byte [BPB_NumFATs+boot_program] |
mul cx |
add ax, word [BPB_RsvdSecCnt+boot_program] |
mov word [FirstRootDirSecNum+boot_program], ax ; 19 |
mov si, ax |
; - count of sectors in RootDir |
mov bx,word [BPB_BytsPerSec+boot_program] |
mov cl,5 ; divide ax by 32 |
shr bx,cl ; bx = directory entries per sector |
mov ax,word [BPB_RootEntCnt+boot_program] |
xor dx,dx |
div bx |
mov word [RootDirSecs+boot_program],ax ; 14 |
; - count of sectors in RootDir |
mov bx, word [BPB_BytsPerSec+boot_program] |
mov cl, 5 ; divide ax by 32 |
shr bx, cl ; bx = directory entries per sector |
mov ax, word [BPB_RootEntCnt+boot_program] |
xor dx, dx |
div bx |
mov word [RootDirSecs+boot_program], ax ; 14 |
; - data start |
add si,ax ; add beginning sector of RootDir and count sectors in RootDir |
mov word [data_start+boot_program],si ; 33 |
; reading root directory |
; al=count root dir sectrors !!!! TODO: al, max 255 sectors !!!! |
mov ah,2 ; read |
push ax |
; - data start |
add si, ax ; add beginning sector of RootDir and count sectors in RootDir |
mov word [data_start+boot_program], si ; 33 |
; reading root directory |
; al=count root dir sectrors !!!! TODO: al, max 255 sectors !!!! |
mov ah, 2 ; read |
push ax |
mov ax,word [FirstRootDirSecNum+boot_program] |
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) |
pop ax |
mov bx,pos_read_tmp ; es:bx read buffer |
call read_sector |
mov ax, word [FirstRootDirSecNum+boot_program] |
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) |
pop ax |
mov bx, pos_read_tmp ; es:bx read buffer |
call read_sector |
mov si,bx ; read buffer address: es:si |
mov ax,[RootDirSecs+boot_program] |
mul word [BPB_BytsPerSec+boot_program] |
add ax,si ; AX = end of root dir. in buffer pos_read_tmp |
mov si, bx ; read buffer address: es:si |
mov ax, [RootDirSecs+boot_program] |
mul word [BPB_BytsPerSec+boot_program] |
add ax, si ; AX = end of root dir. in buffer pos_read_tmp |
; find kernel file in root directory |
; find kernel file in root directory |
loop_find_dir_entry: |
push si |
mov cx,11 |
mov di,kernel_name+boot_program |
rep cmpsb ; compare es:si and es:di, cx bytes long |
pop si |
je found_kernel_file |
add si,32 ; next dir. entry |
cmp si,ax ; end of directory |
jb loop_find_dir_entry |
push si |
mov cx, 11 |
mov di, kernel_name+boot_program |
rep cmpsb ; compare es:si and es:di, cx bytes long |
pop si |
je found_kernel_file |
add si, 32 ; next dir. entry |
cmp si, ax ; end of directory |
jb loop_find_dir_entry |
file_error_message: |
mov si,error_message+boot_program |
mov si, error_message+boot_program |
loop_error_message: |
lodsb |
or al,al |
jz freeze_pc |
mov ah,0eh |
mov bx,7 |
int 10h |
jmp loop_error_message |
lodsb |
or al, al |
jz freeze_pc |
mov ah, 0eh |
mov bx, 7 |
int 10h |
jmp loop_error_message |
freeze_pc: |
jmp $ ; endless loop |
jmp $ ; endless loop |
; === KERNEL FOUND. LOADING... === |
; === KERNEL FOUND. LOADING... === |
found_kernel_file: |
mov bp,[si+01ah] ; first cluster of kernel file |
; <diamond> |
mov [cluster1st+boot_program],bp ; starting cluster of kernel file |
; <\diamond> |
mov bp, [si+01ah] ; first cluster of kernel file |
; <diamond> |
mov [cluster1st+boot_program], bp ; starting cluster of kernel file |
; <\diamond> |
; reading first FAT table |
mov ax,word [BPB_RsvdSecCnt+boot_program] ; begin first FAT abs sector number |
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) |
mov bx,pos_read_tmp ; es:bx read position |
mov ah,2 ; ah=2 (read) |
mov al, byte [BPB_FATSz16+boot_program] ; FAT size in sectors (TODO: max 255 sectors) |
call read_sector |
jc file_error_message ; read error |
; reading first FAT table |
mov ax, word [BPB_RsvdSecCnt+boot_program] ; begin first FAT abs sector number |
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) |
mov bx, pos_read_tmp ; es:bx read position |
mov ah, 2 ; ah=2 (read) |
mov al, byte [BPB_FATSz16+boot_program] ; FAT size in sectors (TODO: max 255 sectors) |
call read_sector |
jc file_error_message ; read error |
mov ax,seg_read_kernel |
mov es,ax |
xor bx,bx ; es:bx = 1000h:0000h |
mov ax, seg_read_kernel |
mov es, ax |
xor bx, bx ; es:bx = 1000h:0000h |
; reading kernel file |
; reading kernel file |
loop_obtains_kernel_data: |
; read one cluster of file |
call obtain_cluster |
jc file_error_message ; read error |
; read one cluster of file |
call obtain_cluster |
jc file_error_message ; read error |
; add one cluster length to segment:offset |
push bx |
mov bx,es |
mov ax,word [BPB_BytsPerSec+boot_program] ;\ |
movsx cx,byte [BPB_SecPerClus+boot_program] ; | !!! TODO: !!! |
mul cx ; | out this from loop !!! |
shr ax,4 ;/ |
add bx,ax |
mov es,bx |
pop bx |
; add one cluster length to segment:offset |
push bx |
mov bx, es |
mov ax, word [BPB_BytsPerSec+boot_program] ;\ |
movsx cx, byte [BPB_SecPerClus+boot_program] ; | !!! TODO: !!! |
mul cx ; | out this from loop !!! |
shr ax, 4 ;/ |
add bx, ax |
mov es, bx |
pop bx |
mov di,bp |
shr di,1 |
pushf |
add di,bp ; di = bp * 1.5 |
add di,pos_read_tmp |
mov ax,[di] ; read next entry from FAT-chain |
popf |
jc move_4_right |
and ax,0fffh |
jmp verify_end_sector |
mov di, bp |
shr di, 1 |
pushf |
add di, bp ; di = bp * 1.5 |
add di, pos_read_tmp |
mov ax, [di] ; read next entry from FAT-chain |
popf |
jc move_4_right |
and ax, 0fffh |
jmp verify_end_sector |
move_4_right: |
mov cl,4 |
shr ax,cl |
mov cl, 4 |
shr ax, cl |
verify_end_sector: |
cmp ax,0ff8h ; last cluster |
jae execute_kernel |
mov bp,ax |
jmp loop_obtains_kernel_data |
cmp ax, 0ff8h ; last cluster |
jae execute_kernel |
mov bp, ax |
jmp loop_obtains_kernel_data |
execute_kernel: |
; <diamond> |
mov ax,'KL' |
push 0 |
pop ds |
mov si,loader_block+boot_program |
; </diamond> |
push word seg_read_kernel |
push word 0 |
retf ; jmp far 1000:0000 |
; <diamond> |
mov ax, 'KL' |
push 0 |
pop ds |
mov si, loader_block+boot_program |
; </diamond> |
push word seg_read_kernel |
push word 0 |
retf ; jmp far 1000:0000 |
;------------------------------------------ |
; loading cluster from file to es:bx |
; loading cluster from file to es:bx |
obtain_cluster: |
; bp - cluster number to read |
; carry = 0 -> read OK |
; carry = 1 -> read ERROR |
; bp - cluster number to read |
; carry = 0 -> read OK |
; carry = 1 -> read ERROR |
; print one dot |
push bx |
mov ax,0e2eh ; ah=0eh (teletype), al='.' |
xor bh,bh |
int 10h |
pop bx |
; print one dot |
push bx |
mov ax, 0e2eh ; ah=0eh (teletype), al='.' |
xor bh, bh |
int 10h |
pop bx |
writesec: |
; convert cluster number to sector number |
mov ax,bp ; data cluster to read |
sub ax,2 |
xor dx,dx |
mov dl,byte [BPB_SecPerClus+boot_program] |
mul dx |
add ax,word [data_start+boot_program] |
; convert cluster number to sector number |
mov ax, bp ; data cluster to read |
sub ax, 2 |
xor dx, dx |
mov dl, byte [BPB_SecPerClus+boot_program] |
mul dx |
add ax, word [data_start+boot_program] |
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) |
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) |
patchhere: |
mov ah,2 ; ah=2 (read) |
mov al,byte [BPB_SecPerClus+boot_program] ; al=(one cluster) |
call read_sector |
retn |
mov ah, 2 ; ah=2 (read) |
mov al, byte [BPB_SecPerClus+boot_program] ; al=(one cluster) |
call read_sector |
retn |
;------------------------------------------ |
;------------------------------------------ |
; read sector from disk |
; read sector from disk |
read_sector: |
push bp |
mov bp,20 ; try 20 times |
push bp |
mov bp, 20 ; try 20 times |
newread: |
dec bp |
jz file_error_message |
push ax bx cx dx |
int 13h |
pop dx cx bx ax |
jc newread |
pop bp |
retn |
dec bp |
jz file_error_message |
push ax bx cx dx |
int 13h |
pop dx cx bx ax |
jc newread |
pop bp |
retn |
;------------------------------------------ |
; convert abs. sector number (AX) to BIOS T:H:S |
; sector number = (abs.sector%BPB_SecPerTrk)+1 |
; pre.track number = (abs.sector/BPB_SecPerTrk) |
; head number = pre.track number%BPB_NumHeads |
; track number = pre.track number/BPB_NumHeads |
; Return: cl - sector number |
; ch - track number |
; dl - drive number (0 = a:) |
; dh - head number |
; convert abs. sector number (AX) to BIOS T:H:S |
; sector number = (abs.sector%BPB_SecPerTrk)+1 |
; pre.track number = (abs.sector/BPB_SecPerTrk) |
; head number = pre.track number%BPB_NumHeads |
; track number = pre.track number/BPB_NumHeads |
; Return: cl - sector number |
; ch - track number |
; dl - drive number (0 = a:) |
; dh - head number |
conv_abs_to_THS: |
push bx |
mov bx,word [BPB_SecPerTrk+boot_program] |
xor dx,dx |
div bx |
inc dx |
mov cl, dl ; cl = sector number |
mov bx,word [BPB_NumHeads+boot_program] |
xor dx,dx |
div bx |
; !!!!!!! ax = track number, dx = head number |
mov ch,al ; ch=track number |
xchg dh,dl ; dh=head number |
mov dl,0 ; dl=0 (drive 0 (a:)) |
pop bx |
retn |
push bx |
mov bx, word [BPB_SecPerTrk+boot_program] |
xor dx, dx |
div bx |
inc dx |
mov cl, dl ; cl = sector number |
mov bx, word [BPB_NumHeads+boot_program] |
xor dx, dx |
div bx |
; !!!!!!! ax = track number, dx = head number |
mov ch, al ; ch=track number |
xchg dh, dl ; dh=head number |
mov dl, 0 ; dl=0 (drive 0 (a:)) |
pop bx |
retn |
;------------------------------------------ |
loading db cr,lf,'Starting system ',00h |
error_message db 13,10 |
kernel_name db 'KERNEL MNT ?',cr,lf,00h |
FirstRootDirSecNum dw ? |
RootDirSecs dw ? |
data_start dw ? |
loading db cr,lf,'Starting system ',00h |
error_message db 13,10 |
kernel_name db 'KERNEL MNT ?',cr,lf,00h |
FirstRootDirSecNum dw ? |
RootDirSecs dw ? |
data_start dw ? |
; <diamond> |
write1st: |
push cs |
pop ds |
mov byte [patchhere+1+boot_program], 3 ; change ah=2 to ah=3 |
mov bp,[cluster1st+boot_program] |
push 1000h |
pop es |
xor bx,bx |
call writesec |
mov byte [patchhere+1+boot_program], 2 ; change back ah=3 to ah=2 |
retf |
cluster1st dw ? |
push cs |
pop ds |
mov byte [patchhere+1+boot_program], 3 ; change ah=2 to ah=3 |
mov bp, [cluster1st+boot_program] |
push 1000h |
pop es |
xor bx, bx |
call writesec |
mov byte [patchhere+1+boot_program], 2 ; change back ah=3 to ah=2 |
retf |
cluster1st dw ? |
loader_block: |
db 1 |
dw 0 |
dw write1st+boot_program |
dw 0 |
db 1 |
dw 0 |
dw write1st+boot_program |
dw 0 |
; <\diamond> |
times 0x1fe-$ db 00h |
times 0x1fe-$ db 00h |
db 55h,0aah ;boot signature |
db 55h,0aah ;boot signature |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/after_win/fat.inc |
---|
1,509 → 1,509 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
load_file_fat: |
mov eax, [bp + root_clus - dat] |
mov [bp + cur_obj - dat], root_string |
push es |
push bx |
push cx |
.parse_dir_loop: |
; convert name to FAT name |
push [bp + cur_obj - dat] |
push ax |
mov [bp + cur_obj - dat], si |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
mov di, fat_filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
.nameloop: |
lodsb |
test al, al |
jz .namedone |
cmp al, '/' |
jz .namedone |
cmp al, '.' |
jz .namedot |
dec cx |
js .badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp .nameloop |
.namedot: |
inc bx |
jp .badname |
add di, cx |
mov cl, 3 |
jmp .nameloop |
.badname: |
mov si, badname_msg |
jmp find_error_si |
.namedone: |
; scan directory |
pop ax ; eax = cluster of directory |
; high word of eax is preserved by operations above |
push ds |
push si |
; read a folder sector-by-sector and scan |
; first, try to use the cache |
push ss |
pop ds |
mov bx, -2 |
mov cx, [bp + rootcache_size - dat] |
cmp [bp + root_clus - dat], eax |
jz .lookcache_root |
mov di, foldcache_mark |
xor bx, bx |
mov cx, [bp + cachelimit - dat] |
@@: |
lea si, [di+bx] |
mov edx, dword [foldcache_clus+si-foldcache_mark+bx] |
cmp edx, eax |
jz .cacheok |
test edx, edx |
jz .cacheadd ; the cache has place for new entry |
inc bx |
inc bx |
dec cx |
js @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov bx, -2 |
mov dx, [bp + cachelimit - dat] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
.cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
lea si, [di+bx] |
mov dword [foldcache_clus+si-foldcache_mark+bx], eax |
.cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [bp + cachelimit - dat] |
add di, di |
.cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns .cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
.lookcache_root: |
; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder |
;mov dx, bx |
;shl dx, 8 |
;add dx, 0x9200 |
lea dx, [bx + 0x92] |
xchg dl, dh |
mov ds, dx |
mov si, fat_filename ; ss:si -> filename in FAT style |
call fat_scan_for_filename |
jz .lookup_done |
; cache miss, read folder data from disk |
; we are reading parent directory, it can result in disk read errors; restore [cur_obj] |
mov di, sp |
mov bx, [bp + cur_obj - dat] |
xchg bx, [ss:di+4] |
mov [bp + cur_obj - dat], bx |
mov bx, cx |
add bx, 0xF |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
.folder_next_cluster: |
; internal loop: scan sectors in cluster |
movzx ecx, byte [ss:0x320D] ; BPB_SecPerClus |
push eax |
; FAT12/16 root - special handling |
test eax, eax |
jnz .folder_notroot |
mov cx, [ss:0x3211] ; BPB_RootEntCnt |
mov dx, cx |
add cx, 0xF |
rcr cx, 1 |
shr cx, 3 |
mov eax, [bp + root_start - dat] |
jmp .folder_next_sector |
.folder_notroot: |
mul ecx |
add eax, [bp + data_start - dat] |
.folder_next_sector: |
sub dx, 0x10 |
; skip first bx sectors |
dec bx |
jns .folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
call read |
jc ..found_disk_error |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
pusha |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
cmp di, 0x90 |
jz .update_rootcache_size |
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache |
jmp .updated_cachesize |
.update_rootcache_size: |
mov cl, 0x10 |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
add [bp + rootcache_size - dat], cx |
.updated_cachesize: |
popa |
@@: |
push es |
mov cl, 0x10 ; ch=0 at this point |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
call fat_scan_for_filename |
pop es |
pop cx |
jz .lookup_done_pop |
.folder_skip_sector: |
inc eax |
loop .folder_next_sector |
pop eax ; eax = current cluster |
test eax, eax |
jz @f |
call [bp + get_next_cluster_ptr - dat] |
jc .folder_next_cluster |
@@: |
stc |
push eax |
.lookup_done_pop: |
pop eax |
.lookup_done: |
pop si |
; CF=1 <=> failed |
jnc .found |
pop ds |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.found: |
mov eax, [di+20-2] |
mov edx, [di+28] |
mov ax, [di+26] ; get cluster |
test byte [di+11], 10h ; directory? |
pop ds |
pop [bp + cur_obj - dat] ; forget old [cur_obj] |
jz .regular_file |
cmp byte [si-1], 0 |
jnz .parse_dir_loop |
..directory_error: |
mov si, directory_string |
jmp find_error_si |
.regular_file: |
cmp byte [si-1], 0 |
jz @f |
..notdir_error: |
mov si, notdir_string |
jmp find_error_si |
@@: |
; ok, we have found a regular file and the caller requested it |
; parse FAT chunk |
push ss |
pop es |
push ss |
pop ds |
mov di, 0x4005 |
mov byte [di-5], 1 ; non-resident attribute |
mov dword [di-4], 1 |
stosd |
pop cx |
push cx |
.parsefat: |
call [bp + get_next_cluster_ptr - dat] |
jnc .done |
mov esi, [di-8] |
add esi, [di-4] |
cmp eax, esi |
jz .contc |
mov dword [di], 1 |
scasd |
stosd |
jmp @f |
.contc: |
inc dword [di-8] |
@@: |
sub cl, [0x320D] |
sbb ch, 0 |
ja .parsefat |
.done: |
xor eax, eax |
stosd |
mov si, 0x4000 |
load_file_common_end: |
xor ecx, ecx |
pop cx |
pop bx |
pop es |
mov [bp + filesize - dat], edx |
mov [bp + sectors_read - dat], ecx |
add edx, 0x1FF |
shr edx, 9 |
mov [bp + filesize_sectors - dat], edx |
cmp edx, ecx |
seta al |
mov ah, 0 |
push ax |
call read_file_chunk |
continue_load_common_end: |
mov [bp + cur_chunk_ptr - dat], si |
pop bx |
mov ax, word [bp + filesize - dat] |
mov dx, word [bp + filesize+2 - dat] |
jnc @f |
mov bl, 3 ; read error |
@@: |
ret |
continue_load_file: |
; es:bx -> buffer for output, ecx = cx = number of sectors |
mov si, [bp + cur_chunk_ptr - dat] |
push ecx |
add ecx, [bp + sectors_read - dat] |
mov [bp + sectors_read - dat], ecx |
cmp [bp + filesize_sectors - dat], ecx |
pop ecx |
seta al |
mov ah, 0 |
push ax |
push continue_load_common_end |
push ss |
pop ds |
cmp [bp + cur_chunk_resident - dat], ah |
jnz .nonresident |
.resident: |
mov ax, word [bp + num_sectors - dat] |
jmp read_file_chunk.resident.continue |
.nonresident: |
mov eax, [bp + cur_cluster - dat] |
mov edx, [bp + num_sectors - dat] |
add eax, [bp + cur_delta - dat] |
jmp read_file_chunk.nonresident.continue |
fat_scan_for_filename: |
; in: ss:si -> 11-bytes FAT name |
; in: ds:0 -> part of directory data |
; in: cx = number of entries |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
push ds |
pop es |
xor di, di |
push cx |
jcxz .noent |
.loop: |
cmp byte [di], 0 |
jz .notfound |
test byte [di+11], 8 ; volume label? |
jnz .cont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmps byte [ss:si], byte [es:di] |
popa |
jz .done |
.cont: |
add di, 0x20 |
loop .loop |
.noent: |
inc cx ; clear ZF flag |
.notfound: |
stc |
.done: |
pop cx |
ret |
fat12_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
push si |
push ds |
push 0x6000 |
pop ds |
mov si, ax |
shr si, 1 |
add si, ax |
test al, 1 |
lodsw |
jz @f |
shr ax, 4 |
@@: |
and ax, 0xFFF |
cmp ax, 0xFF7 |
pop ds si |
ret |
fat16_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
; each sector contains 200h bytes = 100h FAT entries |
; so ah = # of sector, al = offset in sector |
push si |
mov si, ax |
shr si, 8 |
; calculate segment for this sector of FAT table |
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) |
; segment = 6000 + 20*si, offset = 0 |
push es |
push si |
shl si, 5 |
add si, 0x6000 |
mov es, si |
pop si |
cmp byte [ss:0x3400+si], 0 ; sector already loaded? |
jnz .noread |
; load corresponding sector, try all FATs if disk read error detected |
pusha |
movzx di, byte [ss:0x3210] ; BPB_NumFATs |
xor bx, bx |
mov ax, [ss:0x320E] ; BPB_RsvdSecCnt |
xor dx, dx |
add ax, si |
adc dx, bx |
@@: |
push es |
push dx ax |
pop eax |
mov cx, 1 ; read 1 sector |
call read |
pop es |
jnc @f |
add ax, [ss:0x3216] ; BPB_FATSz16 |
adc dx, bx |
dec di |
jnz @b |
..found_disk_error: |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
popa |
.noread: |
mov si, ax |
and si, 0xFF |
add si, si |
mov ax, [es:si] |
pop es |
cmp ax, 0xFFF7 |
pop si |
ret |
fat32_get_next_cluster: |
; in: eax = cluster |
; out: if there is next cluster: CF=1, eax = next cluster |
; out: if there is no next cluster: CF=0 |
push di |
push ax |
shr eax, 7 |
; eax = FAT sector number; look in cache |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
jnc .noread |
; read FAT, try all FATs if disk read error detected |
push es |
pushad |
movzx edx, word [ss:0x320E] ; BPB_RsvdSecCnt |
add eax, edx |
movzx si, byte [ss:0x3210] ; BPB_NumFATs |
@@: |
lea cx, [di - 0x3400 + (0x6000 shr (9-3))] |
shl cx, 9-3 |
mov es, cx |
xor bx, bx |
mov cx, 1 |
call read |
jnc @f |
add eax, [ss:0x3224] ; BPB_FATSz32 |
dec si |
jnz @b |
jmp ..found_disk_error |
@@: |
popad |
pop es |
.noread: |
; get requested item |
lea ax, [di - 0x3400 + (0x6000 shr (9-3))] |
pop di |
and di, 0x7F |
shl di, 2 |
shl ax, 9-3 |
push ds |
mov ds, ax |
and byte [di+3], 0x0F |
mov eax, [di] |
pop ds |
pop di |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
ret |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
load_file_fat: |
mov eax, [bp + root_clus - dat] |
mov [bp + cur_obj - dat], root_string |
push es |
push bx |
push cx |
.parse_dir_loop: |
; convert name to FAT name |
push [bp + cur_obj - dat] |
push ax |
mov [bp + cur_obj - dat], si |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
mov di, fat_filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
.nameloop: |
lodsb |
test al, al |
jz .namedone |
cmp al, '/' |
jz .namedone |
cmp al, '.' |
jz .namedot |
dec cx |
js .badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp .nameloop |
.namedot: |
inc bx |
jp .badname |
add di, cx |
mov cl, 3 |
jmp .nameloop |
.badname: |
mov si, badname_msg |
jmp find_error_si |
.namedone: |
; scan directory |
pop ax ; eax = cluster of directory |
; high word of eax is preserved by operations above |
push ds |
push si |
; read a folder sector-by-sector and scan |
; first, try to use the cache |
push ss |
pop ds |
mov bx, -2 |
mov cx, [bp + rootcache_size - dat] |
cmp [bp + root_clus - dat], eax |
jz .lookcache_root |
mov di, foldcache_mark |
xor bx, bx |
mov cx, [bp + cachelimit - dat] |
@@: |
lea si, [di+bx] |
mov edx, dword [foldcache_clus+si-foldcache_mark+bx] |
cmp edx, eax |
jz .cacheok |
test edx, edx |
jz .cacheadd ; the cache has place for new entry |
inc bx |
inc bx |
dec cx |
js @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov bx, -2 |
mov dx, [bp + cachelimit - dat] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
.cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
lea si, [di+bx] |
mov dword [foldcache_clus+si-foldcache_mark+bx], eax |
.cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [bp + cachelimit - dat] |
add di, di |
.cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns .cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
.lookcache_root: |
; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder |
;mov dx, bx |
;shl dx, 8 |
;add dx, 0x9200 |
lea dx, [bx + 0x92] |
xchg dl, dh |
mov ds, dx |
mov si, fat_filename ; ss:si -> filename in FAT style |
call fat_scan_for_filename |
jz .lookup_done |
; cache miss, read folder data from disk |
; we are reading parent directory, it can result in disk read errors; restore [cur_obj] |
mov di, sp |
mov bx, [bp + cur_obj - dat] |
xchg bx, [ss:di+4] |
mov [bp + cur_obj - dat], bx |
mov bx, cx |
add bx, 0xF |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
.folder_next_cluster: |
; internal loop: scan sectors in cluster |
movzx ecx, byte [ss:0x320D] ; BPB_SecPerClus |
push eax |
; FAT12/16 root - special handling |
test eax, eax |
jnz .folder_notroot |
mov cx, [ss:0x3211] ; BPB_RootEntCnt |
mov dx, cx |
add cx, 0xF |
rcr cx, 1 |
shr cx, 3 |
mov eax, [bp + root_start - dat] |
jmp .folder_next_sector |
.folder_notroot: |
mul ecx |
add eax, [bp + data_start - dat] |
.folder_next_sector: |
sub dx, 0x10 |
; skip first bx sectors |
dec bx |
jns .folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
call read |
jc ..found_disk_error |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
pusha |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
cmp di, 0x90 |
jz .update_rootcache_size |
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache |
jmp .updated_cachesize |
.update_rootcache_size: |
mov cl, 0x10 |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
add [bp + rootcache_size - dat], cx |
.updated_cachesize: |
popa |
@@: |
push es |
mov cl, 0x10 ; ch=0 at this point |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
call fat_scan_for_filename |
pop es |
pop cx |
jz .lookup_done_pop |
.folder_skip_sector: |
inc eax |
loop .folder_next_sector |
pop eax ; eax = current cluster |
test eax, eax |
jz @f |
call [bp + get_next_cluster_ptr - dat] |
jc .folder_next_cluster |
@@: |
stc |
push eax |
.lookup_done_pop: |
pop eax |
.lookup_done: |
pop si |
; CF=1 <=> failed |
jnc .found |
pop ds |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.found: |
mov eax, [di+20-2] |
mov edx, [di+28] |
mov ax, [di+26] ; get cluster |
test byte [di+11], 10h ; directory? |
pop ds |
pop [bp + cur_obj - dat] ; forget old [cur_obj] |
jz .regular_file |
cmp byte [si-1], 0 |
jnz .parse_dir_loop |
..directory_error: |
mov si, directory_string |
jmp find_error_si |
.regular_file: |
cmp byte [si-1], 0 |
jz @f |
..notdir_error: |
mov si, notdir_string |
jmp find_error_si |
@@: |
; ok, we have found a regular file and the caller requested it |
; parse FAT chunk |
push ss |
pop es |
push ss |
pop ds |
mov di, 0x4005 |
mov byte [di-5], 1 ; non-resident attribute |
mov dword [di-4], 1 |
stosd |
pop cx |
push cx |
.parsefat: |
call [bp + get_next_cluster_ptr - dat] |
jnc .done |
mov esi, [di-8] |
add esi, [di-4] |
cmp eax, esi |
jz .contc |
mov dword [di], 1 |
scasd |
stosd |
jmp @f |
.contc: |
inc dword [di-8] |
@@: |
sub cl, [0x320D] |
sbb ch, 0 |
ja .parsefat |
.done: |
xor eax, eax |
stosd |
mov si, 0x4000 |
load_file_common_end: |
xor ecx, ecx |
pop cx |
pop bx |
pop es |
mov [bp + filesize - dat], edx |
mov [bp + sectors_read - dat], ecx |
add edx, 0x1FF |
shr edx, 9 |
mov [bp + filesize_sectors - dat], edx |
cmp edx, ecx |
seta al |
mov ah, 0 |
push ax |
call read_file_chunk |
continue_load_common_end: |
mov [bp + cur_chunk_ptr - dat], si |
pop bx |
mov ax, word [bp + filesize - dat] |
mov dx, word [bp + filesize+2 - dat] |
jnc @f |
mov bl, 3 ; read error |
@@: |
ret |
continue_load_file: |
; es:bx -> buffer for output, ecx = cx = number of sectors |
mov si, [bp + cur_chunk_ptr - dat] |
push ecx |
add ecx, [bp + sectors_read - dat] |
mov [bp + sectors_read - dat], ecx |
cmp [bp + filesize_sectors - dat], ecx |
pop ecx |
seta al |
mov ah, 0 |
push ax |
push continue_load_common_end |
push ss |
pop ds |
cmp [bp + cur_chunk_resident - dat], ah |
jnz .nonresident |
.resident: |
mov ax, word [bp + num_sectors - dat] |
jmp read_file_chunk.resident.continue |
.nonresident: |
mov eax, [bp + cur_cluster - dat] |
mov edx, [bp + num_sectors - dat] |
add eax, [bp + cur_delta - dat] |
jmp read_file_chunk.nonresident.continue |
fat_scan_for_filename: |
; in: ss:si -> 11-bytes FAT name |
; in: ds:0 -> part of directory data |
; in: cx = number of entries |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
push ds |
pop es |
xor di, di |
push cx |
jcxz .noent |
.loop: |
cmp byte [di], 0 |
jz .notfound |
test byte [di+11], 8 ; volume label? |
jnz .cont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmps byte [ss:si], byte [es:di] |
popa |
jz .done |
.cont: |
add di, 0x20 |
loop .loop |
.noent: |
inc cx ; clear ZF flag |
.notfound: |
stc |
.done: |
pop cx |
ret |
fat12_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
push si |
push ds |
push 0x6000 |
pop ds |
mov si, ax |
shr si, 1 |
add si, ax |
test al, 1 |
lodsw |
jz @f |
shr ax, 4 |
@@: |
and ax, 0xFFF |
cmp ax, 0xFF7 |
pop ds si |
ret |
fat16_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
; each sector contains 200h bytes = 100h FAT entries |
; so ah = # of sector, al = offset in sector |
push si |
mov si, ax |
shr si, 8 |
; calculate segment for this sector of FAT table |
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) |
; segment = 6000 + 20*si, offset = 0 |
push es |
push si |
shl si, 5 |
add si, 0x6000 |
mov es, si |
pop si |
cmp byte [ss:0x3400+si], 0 ; sector already loaded? |
jnz .noread |
; load corresponding sector, try all FATs if disk read error detected |
pusha |
movzx di, byte [ss:0x3210] ; BPB_NumFATs |
xor bx, bx |
mov ax, [ss:0x320E] ; BPB_RsvdSecCnt |
xor dx, dx |
add ax, si |
adc dx, bx |
@@: |
push es |
push dx ax |
pop eax |
mov cx, 1 ; read 1 sector |
call read |
pop es |
jnc @f |
add ax, [ss:0x3216] ; BPB_FATSz16 |
adc dx, bx |
dec di |
jnz @b |
..found_disk_error: |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
popa |
.noread: |
mov si, ax |
and si, 0xFF |
add si, si |
mov ax, [es:si] |
pop es |
cmp ax, 0xFFF7 |
pop si |
ret |
fat32_get_next_cluster: |
; in: eax = cluster |
; out: if there is next cluster: CF=1, eax = next cluster |
; out: if there is no next cluster: CF=0 |
push di |
push ax |
shr eax, 7 |
; eax = FAT sector number; look in cache |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
jnc .noread |
; read FAT, try all FATs if disk read error detected |
push es |
pushad |
movzx edx, word [ss:0x320E] ; BPB_RsvdSecCnt |
add eax, edx |
movzx si, byte [ss:0x3210] ; BPB_NumFATs |
@@: |
lea cx, [di - 0x3400 + (0x6000 shr (9-3))] |
shl cx, 9-3 |
mov es, cx |
xor bx, bx |
mov cx, 1 |
call read |
jnc @f |
add eax, [ss:0x3224] ; BPB_FATSz32 |
dec si |
jnz @b |
jmp ..found_disk_error |
@@: |
popad |
pop es |
.noread: |
; get requested item |
lea ax, [di - 0x3400 + (0x6000 shr (9-3))] |
pop di |
and di, 0x7F |
shl di, 2 |
shl ax, 9-3 |
push ds |
mov ds, ax |
and byte [di+3], 0x0F |
mov eax, [di] |
pop ds |
pop di |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/after_win/kordldr.win.asm |
---|
1,921 → 1,924 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond |
; It is used when main bootloader is Windows loader. |
; this code is loaded: |
; NT/2k/XP: by ntldr to 0D00:0000 |
; 9x: by io.sys from config.sys to xxxx:0100 |
; Vista: by bootmgr to 0000:7C00 |
format binary |
use16 |
; in any case, we relocate this code to 0000:0600 |
org 0x600 |
; entry point for 9x and Vista booting |
call @f |
db 'NTFS' |
@@: |
pop si |
sub si, 3 |
cmp si, 100h |
jnz boot_vista |
mov si, load_question + 100h - 600h |
call out_string |
; mov si, answer + 100h - 0600h ; already is |
xxy: mov ah, 0 |
int 16h |
or al, 20h |
mov [si], al |
cmp al, 'y' |
jz xxz |
cmp al, 'n' |
jnz xxy |
; continue load Windows |
; call out_string |
; ret |
out_string: |
push bx |
@@: |
lodsb |
test al, al |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
pop bx |
ret |
xxz: |
; boot KordOS |
call out_string |
; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers, |
; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached |
xor di, di |
mov ds, di |
mov word [di+4], new01handler + 100h - 600h |
mov [di+6], cs |
pushf |
pop ax |
or ah, 1 |
push ax |
popf |
; we cannot issue INT 19h directly, because INT command clears TF |
; int 19h ; don't issue it directly, because INT command clears TF |
; so instead we use direct call |
; pushf ; there will be no IRET |
call far [di + 19h*4] |
xxt: |
xor di, di |
mov ds, di |
cmp word [di + 8*4+2], 0F000h |
jz @f |
les bx, [di + 8*4] |
mov eax, [es:bx+1] |
mov [di + 8*4], eax |
@@: |
mov si, 100h |
boot_vista: |
; relocate cs:si -> 0000:0600 |
push cs |
pop ds |
xor ax, ax |
mov es, ax |
mov di, 0x600 |
mov cx, 2000h/2 |
rep movsw |
jmp 0:real_entry |
load_question db 'Load KordOS? [y/n]: ',0 |
answer db ? |
db 13,10,0 |
new01handler: |
; [sp]=ip, [sp+2]=cs, [sp+4]=flags |
push bp |
mov bp, sp |
push ds |
lds bp, [bp+2] |
cmp word [ds:bp], 19cdh |
jz xxt |
pop ds |
pop bp |
iret |
; read from hard disk |
; in: eax = absolute sector |
; cx = number of sectors |
; es:bx -> buffer |
; out: CF=1 if error |
read: |
pushad |
add eax, [bp + partition_start - dat] |
cmp [bp + use_lba - dat], 0 |
jz .chs |
; LBA read |
push ds |
.lbado: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp + boot_drive - dat] |
mov ah, 42h |
int 13h |
jc .disk_error_lba |
add sp, 10h ; restore stack |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz .lbado |
pop ds |
popad |
ret |
.disk_error_lba: |
add sp, 14h |
pop ds |
popad |
stc |
ret |
.chs: |
pusha |
pop edi ; loword(edi) = di, hiword(edi) = si |
push bx |
; eax / (SectorsPerTrack) -> eax, remainder bx |
movzx esi, [bp + sectors - dat] |
xor edx, edx |
div esi |
mov bx, dx ; bx = sector-1 |
; eax -> dx:ax |
push eax |
pop ax |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp + heads - dat] |
; number of sectors: read no more than to end of track |
sub si, bx |
cmp cx, si |
jbe @f |
mov cx, si |
@@: |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector |
; convert to int13 format |
movzx edi, cx |
mov dh, dl |
mov dl, [bp + boot_drive - dat] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
add sp, 12 |
popad |
stc |
ret |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push edi |
popa |
add eax, edi |
sub cx, di |
jnz .chs |
popad |
ret |
disk_error2 db 'Fatal: cannot read partitions info: ' |
disk_error_msg db 'disk read error',0 |
disk_params_msg db 'Fatal: cannot get drive parameters',0 |
start_msg db 2,' KordOS bootloader',13,10,0 |
part_msg db 'looking at partition ' |
part_char db '0' ; will be incremented before writing message |
db ' ... ',0 |
errfs_msg db 'unknown filesystem',13,10,0 |
fatxx_msg db 'FATxx' |
newline db 13,10,0 |
ntfs_msg db 'NTFS',13,10,0 |
error_msg db 'Error' |
colon db ': ',0 |
root_string db '\',0 |
nomem_msg db 'No memory',0 |
filesys_string db '(filesystem)',0 |
directory_string db 'is a directory',0 |
notdir_string db 'not a directory',0 |
; entry point for NT/2k/XP booting |
; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256 |
repeat 600h + 256h - $ |
db 1 ; any data can be here; 1 in ASCII is a nice face :) |
end repeat |
; cs=es=0D00, ds=07C0, ss=0 |
; esi=edi=ebp=0, esp=7C00 |
xor si, si |
jmp boot_vista |
real_entry: |
; ax = 0 |
mov ds, ax |
mov es, ax |
; our stack is 4 Kb: memory range 2000-3000 |
mov ss, ax |
mov sp, 3000h |
mov bp, dat |
sti ; just for case |
; say hi to user |
mov si, start_msg |
call out_string |
; we are booting from hard disk identified by [boot_drive] |
mov dl, [bp + boot_drive - dat] |
; is LBA supported? |
mov [bp + use_lba - dat], 0 |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
jc .no_lba |
cmp bx, 0AA55h |
jnz .no_lba |
test cl, 1 |
jz .no_lba |
inc [bp + use_lba - dat] |
jmp disk_params_ok |
.no_lba: |
; get drive geometry |
mov ah, 8 |
mov dl, [bp + boot_drive - dat] |
int 13h |
jnc @f |
mov si, disk_params_msg |
call out_string |
jmp $ |
@@: |
movzx ax, dh |
inc ax |
mov [bp + heads - dat], ax |
and cx, 3Fh |
mov [bp + sectors - dat], cx |
disk_params_ok: |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 94000h / 1024 |
jc nomem |
shr ax, 3 |
mov [bp + cachelimit - dat], ax ; size of cache - 1 |
; scan all partitions |
new_partition_ex: |
xor eax, eax ; read first sector of current disk area |
mov [bp + extended_part_cur - dat], eax ; no extended partition yet |
mov [bp + cur_partition_ofs - dat], 31BEh ; start from first partition |
push es |
mov cx, 1 |
mov bx, 3000h |
call read |
pop es |
jnc new_partition |
mov si, disk_error2 |
call out_string |
jmp $ |
new_partition: |
mov bx, [bp + cur_partition_ofs - dat] |
mov al, [bx+4] ; partition type |
test al, al |
jz next_partition |
cmp al, 5 |
jz @f |
cmp al, 0xF |
jnz not_extended |
@@: |
; extended partition |
mov eax, [bx+8] ; partition start |
add eax, [bp + extended_part_start - dat] |
mov [bp + extended_part_cur - dat], eax |
next_partition: |
add [bp + cur_partition_ofs - dat], 10h |
cmp [bp + cur_partition_ofs - dat], 31FEh |
jb new_partition |
mov eax, [bp + extended_part_cur - dat] |
test eax, eax |
jz partitions_done |
cmp [bp + extended_part_start - dat], 0 |
jnz @f |
mov [bp + extended_part_start - dat], eax |
@@: |
mov [bp + extended_parent - dat], eax |
mov [bp + partition_start - dat], eax |
jmp new_partition_ex |
partitions_done: |
mov si, total_kaput |
call out_string |
jmp $ |
not_extended: |
mov eax, [bx+8] |
add eax, [bp + extended_parent - dat] |
mov [bp + partition_start - dat], eax |
; try to load from current partition |
; inform user |
mov si, part_msg |
inc [si + part_char - part_msg] |
call out_string |
; read bootsector |
xor eax, eax |
mov [bp + cur_obj - dat], filesys_string |
push es |
mov cx, 1 |
mov bx, 3200h |
call read |
pop es |
mov si, disk_error_msg |
jc find_error_si |
movzx si, byte [bx+13] |
mov word [bp + sect_per_clust - dat], si |
test si, si |
jz unknown_fs |
lea ax, [si-1] |
test si, ax |
jnz unknown_fs |
; determine file system |
; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h) |
cmp word [bx+11], 0x200 |
jnz unknown_fs |
; is it NTFS? |
cmp dword [bx+3], 'NTFS' |
jnz not_ntfs |
cmp byte [bx+16], bl |
jz ntfs |
not_ntfs: |
; is it FAT? FAT12/FAT16/FAT32? |
; get count of sectors to dword in cx:si |
mov si, [bx+19] |
xor cx, cx |
test si, si |
jnz @f |
mov si, [bx+32] |
mov cx, [bx+34] |
@@: |
xor eax, eax |
; subtract size of system area |
sub si, [bx+14] ; BPB_ResvdSecCnt |
sbb cx, ax |
mov ax, [bx+17] ; BPB_RootEntCnt |
add ax, 0xF |
rcr ax, 1 |
shr ax, 3 |
sub si, ax |
sbb cx, 0 |
push cx |
push si |
mov ax, word [bx+22] |
test ax, ax |
jnz @f |
mov eax, [bx+36] |
@@: |
movzx ecx, byte [bx+16] |
imul ecx, eax |
pop eax |
sub eax, ecx |
; now eax = count of sectors in the data region |
xor edx, edx |
div [bp + sect_per_clust - dat] |
; now eax = count of clusters in the data region |
mov si, fatxx_msg |
cmp eax, 0xFFF5 |
jae test_fat32 |
; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38 |
cmp byte [bx+38], 0x29 |
jnz not_fat |
cmp ax, 0xFF5 |
jae fat16 |
fat12: |
mov [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster |
mov di, cx ; BPB_NumFATs |
mov ax, '12' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
movzx ecx, word [bx+22] ; BPB_FATSz16 |
; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes) |
.fatloop: |
; if first copy is not readable, try to switch to other copies |
push 0x6000 |
pop es |
xor bx, bx |
movzx eax, word [0x320E] ; BPB_RsvdSecCnt |
push cx |
cmp cx, 12 |
jb @f |
mov cx, 12 |
@@: |
call read |
pop cx |
jnc fat1x_common |
add eax, ecx ; switch to next copy of FAT |
dec di |
jnz .fatloop |
mov si, disk_error_msg |
jmp find_error_si |
fat16: |
mov [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster |
mov ax, '16' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT16: init FAT cache - no sectors loaded |
mov di, 0x3400 |
xor ax, ax |
mov cx, 0x100/2 |
rep stosw |
fat1x_common: |
mov bx, 0x3200 |
movzx eax, word [bx+22] ; BPB_FATSz16 |
xor esi, esi ; no root cluster |
jmp fat_common |
test_fat32: |
; FAT32 bootsector has it at the offset +66 |
cmp byte [bx+66], 0x29 |
jnz not_fat |
mov [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster |
mov ax, '32' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT32 - init cache for FAT table: no sectors loaded |
lea si, [bp + cache1head - dat] |
mov [si], si ; no sectors in cache: |
mov [si+2], si ; 'prev' & 'next' links point to self |
mov [bp + cache1end - dat], 3400h ; first free item = 3400h |
mov [bp + cache1limit - dat], 3C00h |
mov eax, [bx+36] ; BPB_FATSz32 |
mov esi, [bx+44] ; BPB_RootClus |
jmp fat_common |
not_fat: |
unknown_fs: |
mov si, errfs_msg |
call out_string |
jmp next_partition |
fat_common: |
push ss |
pop es |
movzx edx, byte [bx+16] ; BPB_NumFATs |
mul edx |
mov [bp + root_start - dat], eax ; this is for FAT1x |
; eax = total size of all FAT tables, in sectors |
movzx ecx, word [bx+17] ; BPB_RootEntCnt |
add ecx, 0xF |
shr ecx, 4 |
add eax, ecx |
mov cx, word [bx+14] ; BPB_RsvdSecCnt |
add [bp + root_start - dat], ecx ; this is for FAT1x |
add eax, ecx |
; cluster 2 begins from sector eax |
movzx ebx, byte [bx+13] ; BPB_SecPerClus |
sub eax, ebx |
sub eax, ebx |
mov [bp + data_start - dat], eax |
; no clusters in folders cache |
mov di, foldcache_clus - 2 |
xor ax, ax |
mov cx, 7*8/2 + 1 |
rep stosw |
mov [bp + root_clus - dat], esi |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_fat |
load_secondary: |
push 0x1000 |
pop es |
xor bx, bx |
mov si, kernel_name |
mov cx, 0x30000 / 0x200 |
call [bp + load_file_ptr - dat] |
; say error if needed |
mov si, error_too_big |
dec bx |
js @f |
jz find_error_si |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
; fill loader information and jump to secondary loader |
mov al, 'h' ; boot device: hard drive |
mov ah, [bp + boot_drive - dat] |
sub ah, 80h ; boot device: identifier |
pop bx ; restore file system ID ('12'/'16'/'32'/'nt') |
mov si, callback |
jmp 1000h:0000h |
nomem: |
mov si, nomem_msg |
call out_string |
jmp $ |
ntfs: |
push 'nt' ; save for secondary loader |
mov si, ntfs_msg |
call out_string |
xor eax, eax |
mov [bp + data_start - dat], eax |
mov ecx, [bx+40h] ; frs_size |
cmp cl, al |
jg .1 |
neg cl |
inc ax |
shl eax, cl |
jmp .2 |
.1: |
mov eax, ecx |
shl eax, 9 |
.2: |
mov [bp + frs_size - dat], ax |
; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different |
; (at least with standard tools) |
; we allow extra size, but no more than 0x1000 bytes = 4 Kb |
mov si, invalid_volume_msg |
cmp eax, 0x1000 |
ja find_error_si |
; must be multiple of sector size |
test ax, 0x1FF |
jnz find_error_si |
shr ax, 9 |
xchg cx, ax |
; initialize cache - no data loaded |
lea si, [bp + cache1head - dat] |
mov [si], si |
mov [si+2], si |
mov word [si+4], 3400h ; first free item = 3400h |
mov word [si+6], 3400h + 8*8 ; 8 items in this cache |
; read first MFT record - description of MFT itself |
mov [bp + cur_obj - dat], mft_string |
mov eax, [bx+30h] ; mft_cluster |
mul [bp + sect_per_clust - dat] |
push 0x8000 |
pop es |
xor bx, bx |
push es |
call read |
pop ds |
call restore_usa |
; scan for unnamed $DATA attribute |
mov [bp + freeattr - dat], 4000h |
mov ax, 80h |
call load_attr |
push ss |
pop ds |
mov si, nodata_string |
jc find_error_si |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_ntfs |
jmp load_secondary |
find_error_si: |
push si |
find_error_sp: |
cmp [bp + in_callback - dat], 0 |
jnz error_in_callback |
push ss |
pop ds |
push ss |
pop es |
mov si, error_msg |
call out_string |
mov si, [bp + cur_obj - dat] |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
mov si, colon |
call out_string |
pop si |
call out_string |
mov si, newline |
call out_string |
mov sp, 0x3000 |
jmp next_partition |
error_in_callback: |
; return status: file not found, except for read errors |
mov bx, 2 |
cmp si, disk_error_msg |
jnz @f |
inc bx |
@@: |
mov ax, 0xFFFF |
mov dx, ax |
mov sp, 3000h - 6 |
ret |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 3000h |
mov bp, dat |
mov [bp + in_callback - dat], 1 |
push dx |
push cx |
; set ds:si -> ASCIIZ name |
lea si, [di+6] |
; set cx = limit in sectors; 4Kb = 8 sectors |
movzx ecx, word [di+4] |
shl cx, 3 |
; set es:bx = pointer to buffer |
les bx, [di] |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call [bp + load_file_ptr - dat] |
callback_ret_succ: |
clc |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
read_file_chunk.resident: |
; auxiliary label for read_file_chunk procedure |
mov di, bx |
lodsw |
read_file_chunk.resident.continue: |
mov dx, ax |
add dx, 0x1FF |
shr dx, 9 |
cmp dx, cx |
jbe @f |
mov ax, cx |
shl ax, 9 |
@@: |
xchg ax, cx |
rep movsb |
xchg ax, cx |
clc ; no disk error if no disk requests |
mov word [bp + num_sectors - dat], ax |
ret |
read_file_chunk: |
; in: ds:si -> file chunk |
; in: es:bx -> buffer for output |
; in: ecx = maximum number of sectors to read (high word must be 0) |
; out: CF=1 <=> disk read error |
lodsb |
mov [bp + cur_chunk_resident - dat], al |
test al, al |
jz .resident |
; normal case: load (non-resident) attribute from disk |
.read_block: |
lodsd |
xchg eax, edx |
test edx, edx |
jz .ret |
lodsd |
; eax = start cluster, edx = number of clusters, cx = limit in sectors |
imul eax, [bp + sect_per_clust - dat] |
add eax, [bp + data_start - dat] |
mov [bp + cur_cluster - dat], eax |
imul edx, [bp + sect_per_clust - dat] |
mov [bp + num_sectors - dat], edx |
and [bp + cur_delta - dat], 0 |
.nonresident.continue: |
cmp edx, ecx |
jb @f |
mov edx, ecx |
@@: |
test dx, dx |
jz .read_block |
add [bp + cur_delta - dat], edx |
sub [bp + num_sectors - dat], edx |
sub ecx, edx |
push cx |
mov cx, dx |
call read |
pop cx |
jc .ret |
test cx, cx |
jnz .read_block |
.ret: |
ret |
cache_lookup: |
; in: eax = value to look, si = pointer to cache structure |
; out: di->cache entry; CF=1 <=> the value was not found |
push ds bx |
push ss |
pop ds |
mov di, [si+2] |
.look: |
cmp di, si |
jz .not_in_cache |
cmp eax, [di+4] |
jz .in_cache |
mov di, [di+2] |
jmp .look |
.not_in_cache: |
; cache miss |
; cache is full? |
mov di, [si+4] |
cmp di, [si+6] |
jnz .cache_not_full |
; yes, delete the oldest entry |
mov di, [si] |
mov bx, [di] |
mov [si], bx |
push word [di+2] |
pop word [bx+2] |
jmp .cache_append |
.cache_not_full: |
; no, allocate new item |
add word [si+4], 8 |
.cache_append: |
mov [di+4], eax |
stc |
jmp @f |
.in_cache: |
; delete this sector from the list |
push si |
mov si, [di] |
mov bx, [di+2] |
mov [si+2], bx |
mov [bx], si |
pop si |
@@: |
; add new sector to the end of list |
mov bx, di |
xchg bx, [si+2] |
push word [bx] |
pop word [di] |
mov [bx], di |
mov [di+2], bx |
pop bx ds |
ret |
include 'fat.inc' |
include 'ntfs.inc' |
total_kaput db 13,10,'Fatal error: cannot load the secondary loader',0 |
error_too_big db 'file is too big',0 |
nodata_string db '$DATA ' |
error_not_found db 'not found',0 |
noindex_string db '$INDEX_ROOT not found',0 |
badname_msg db 'bad name for FAT',0 |
invalid_volume_msg db 'invalid volume',0 |
mft_string db '$MFT',0 |
fragmented_string db 'too fragmented file',0 |
invalid_read_request_string db 'cannot read attribute',0 |
kernel_name db 'kernel.mnt',0 |
align 4 |
dat: |
extended_part_start dd 0 ; start sector for main extended partition |
extended_part_cur dd ? ; start sector for current extended child |
extended_parent dd 0 ; start sector for current extended parent |
partition_start dd 0 ; start sector for current logical disk |
cur_partition_ofs dw ? ; offset in MBR data for current partition |
sect_per_clust dd 0 |
; change this variable if you want to boot from other physical drive |
boot_drive db 80h |
in_callback db 0 |
; uninitialized data |
use_lba db ? |
cur_chunk_resident db ? |
align 2 |
heads dw ? |
sectors dw ? |
cache1head rw 2 |
cache1end dw ? |
cache1limit dw ? |
data_start dd ? |
cachelimit dw ? |
load_file_ptr dw ? |
cur_obj dw ? |
missing_slash dw ? |
root_clus dd ? |
root_start dd ? |
get_next_cluster_ptr dw ? |
frs_size dw ? |
freeattr dw ? |
index_root dw ? |
index_alloc dw ? |
cur_index_seg dw ? |
cur_index_cache dw ? |
filesize dd ? |
filesize_sectors dd ? |
cur_cluster dd ? |
cur_delta dd ? |
num_sectors dd ? |
sectors_read dd ? |
cur_chunk_ptr dw ? |
rootcache_size dw ? ; must be immediately before foldcache_clus |
if $-dat >= 0x80 |
warning: unoptimal data displacement! |
end if |
foldcache_clus rd 7 |
foldcache_mark rw 7 |
foldcache_size rw 7 |
fat_filename rb 11 |
if $ > 2000h |
error: file is too big |
end if |
; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long |
repeat 0x2600 - $ |
db 2 ; any data can be here; 2 is another nice face in ASCII :) |
end repeat |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond |
; It is used when main bootloader is Windows loader. |
; this code is loaded: |
; NT/2k/XP: by ntldr to 0D00:0000 |
; 9x: by io.sys from config.sys to xxxx:0100 |
; Vista: by bootmgr to 0000:7C00 |
format binary |
use16 |
; in any case, we relocate this code to 0000:0600 |
org 0x600 |
; entry point for 9x and Vista booting |
call @f |
db 'NTFS' |
@@: |
pop si |
sub si, 3 |
cmp si, 100h |
jnz boot_vista |
mov si, load_question + 100h - 600h |
call out_string |
; mov si, answer + 100h - 0600h ; already is |
xxy: |
mov ah, 0 |
int 16h |
or al, 20h |
mov [si], al |
cmp al, 'y' |
jz xxz |
cmp al, 'n' |
jnz xxy |
; continue load Windows |
; call out_string |
; ret |
out_string: |
push bx |
@@: |
lodsb |
test al, al |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
pop bx |
ret |
xxz: |
; boot KordOS |
call out_string |
; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers, |
; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached |
xor di, di |
mov ds, di |
mov word [di+4], new01handler + 100h - 600h |
mov [di+6], cs |
pushf |
pop ax |
or ah, 1 |
push ax |
popf |
; we cannot issue INT 19h directly, because INT command clears TF |
; int 19h ; don't issue it directly, because INT command clears TF |
; so instead we use direct call |
; pushf ; there will be no IRET |
call far [di + 19h*4] |
xxt: |
xor di, di |
mov ds, di |
cmp word [di + 8*4+2], 0F000h |
jz @f |
les bx, [di + 8*4] |
mov eax, [es:bx+1] |
mov [di + 8*4], eax |
@@: |
mov si, 100h |
boot_vista: |
; relocate cs:si -> 0000:0600 |
push cs |
pop ds |
xor ax, ax |
mov es, ax |
mov di, 0x600 |
mov cx, 2000h/2 |
rep movsw |
jmp 0:real_entry |
load_question db 'Load KordOS? [y/n]: ',0 |
answer db ? |
db 13,10,0 |
new01handler: |
; [sp]=ip, [sp+2]=cs, [sp+4]=flags |
push bp |
mov bp, sp |
push ds |
lds bp, [bp+2] |
cmp word [ds:bp], 19cdh |
jz xxt |
pop ds |
pop bp |
iret |
; read from hard disk |
; in: eax = absolute sector |
; cx = number of sectors |
; es:bx -> buffer |
; out: CF=1 if error |
read: |
pushad |
add eax, [bp + partition_start - dat] |
cmp [bp + use_lba - dat], 0 |
jz .chs |
; LBA read |
push ds |
.lbado: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp + boot_drive - dat] |
mov ah, 42h |
int 13h |
jc .disk_error_lba |
add sp, 10h ; restore stack |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz .lbado |
pop ds |
popad |
ret |
.disk_error_lba: |
add sp, 14h |
pop ds |
popad |
stc |
ret |
.chs: |
pusha |
pop edi ; loword(edi) = di, hiword(edi) = si |
push bx |
; eax / (SectorsPerTrack) -> eax, remainder bx |
movzx esi, [bp + sectors - dat] |
xor edx, edx |
div esi |
mov bx, dx ; bx = sector-1 |
; eax -> dx:ax |
push eax |
pop ax |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp + heads - dat] |
; number of sectors: read no more than to end of track |
sub si, bx |
cmp cx, si |
jbe @f |
mov cx, si |
@@: |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector |
; convert to int13 format |
movzx edi, cx |
mov dh, dl |
mov dl, [bp + boot_drive - dat] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
add sp, 12 |
popad |
stc |
ret |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push edi |
popa |
add eax, edi |
sub cx, di |
jnz .chs |
popad |
ret |
disk_error2 db 'Fatal: cannot read partitions info: ' |
disk_error_msg db 'disk read error',0 |
disk_params_msg db 'Fatal: cannot get drive parameters',0 |
start_msg db 2,' KordOS bootloader',13,10,0 |
part_msg db 'looking at partition ' |
part_char db '0' ; will be incremented before writing message |
db ' ... ',0 |
errfs_msg db 'unknown filesystem',13,10,0 |
fatxx_msg db 'FATxx' |
newline db 13,10,0 |
ntfs_msg db 'NTFS',13,10,0 |
error_msg db 'Error' |
colon db ': ',0 |
root_string db '\',0 |
nomem_msg db 'No memory',0 |
filesys_string db '(filesystem)',0 |
directory_string db 'is a directory',0 |
notdir_string db 'not a directory',0 |
; entry point for NT/2k/XP booting |
; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256 |
repeat 600h + 256h - $ |
db 1 ; any data can be here; 1 in ASCII is a nice face :) |
end repeat |
; cs=es=0D00, ds=07C0, ss=0 |
; esi=edi=ebp=0, esp=7C00 |
xor si, si |
jmp boot_vista |
real_entry: |
; ax = 0 |
mov ds, ax |
mov es, ax |
; our stack is 4 Kb: memory range 2000-3000 |
mov ss, ax |
mov sp, 3000h |
mov bp, dat |
sti ; just for case |
; say hi to user |
mov si, start_msg |
call out_string |
; we are booting from hard disk identified by [boot_drive] |
mov dl, [bp + boot_drive - dat] |
; is LBA supported? |
mov [bp + use_lba - dat], 0 |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
jc .no_lba |
cmp bx, 0AA55h |
jnz .no_lba |
test cl, 1 |
jz .no_lba |
inc [bp + use_lba - dat] |
jmp disk_params_ok |
.no_lba: |
; get drive geometry |
mov ah, 8 |
mov dl, [bp + boot_drive - dat] |
int 13h |
jnc @f |
mov si, disk_params_msg |
call out_string |
jmp $ |
@@: |
movzx ax, dh |
inc ax |
mov [bp + heads - dat], ax |
and cx, 3Fh |
mov [bp + sectors - dat], cx |
disk_params_ok: |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 94000h / 1024 |
jc nomem |
shr ax, 3 |
mov [bp + cachelimit - dat], ax ; size of cache - 1 |
; scan all partitions |
new_partition_ex: |
xor eax, eax ; read first sector of current disk area |
mov [bp + extended_part_cur - dat], eax ; no extended partition yet |
mov [bp + cur_partition_ofs - dat], 31BEh ; start from first partition |
push es |
mov cx, 1 |
mov bx, 3000h |
call read |
pop es |
jnc new_partition |
mov si, disk_error2 |
call out_string |
jmp $ |
new_partition: |
mov bx, [bp + cur_partition_ofs - dat] |
mov al, [bx+4] ; partition type |
test al, al |
jz next_partition |
cmp al, 5 |
jz @f |
cmp al, 0xF |
jnz not_extended |
@@: |
; extended partition |
mov eax, [bx+8] ; partition start |
add eax, [bp + extended_part_start - dat] |
mov [bp + extended_part_cur - dat], eax |
next_partition: |
add [bp + cur_partition_ofs - dat], 10h |
cmp [bp + cur_partition_ofs - dat], 31FEh |
jb new_partition |
mov eax, [bp + extended_part_cur - dat] |
test eax, eax |
jz partitions_done |
cmp [bp + extended_part_start - dat], 0 |
jnz @f |
mov [bp + extended_part_start - dat], eax |
@@: |
mov [bp + extended_parent - dat], eax |
mov [bp + partition_start - dat], eax |
jmp new_partition_ex |
partitions_done: |
mov si, total_kaput |
call out_string |
jmp $ |
not_extended: |
mov eax, [bx+8] |
add eax, [bp + extended_parent - dat] |
mov [bp + partition_start - dat], eax |
; try to load from current partition |
; inform user |
mov si, part_msg |
inc [si + part_char - part_msg] |
call out_string |
; read bootsector |
xor eax, eax |
mov [bp + cur_obj - dat], filesys_string |
push es |
mov cx, 1 |
mov bx, 3200h |
call read |
pop es |
mov si, disk_error_msg |
jc find_error_si |
movzx si, byte [bx+13] |
mov word [bp + sect_per_clust - dat], si |
test si, si |
jz unknown_fs |
lea ax, [si-1] |
test si, ax |
jnz unknown_fs |
; determine file system |
; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h) |
cmp word [bx+11], 0x200 |
jnz unknown_fs |
; is it NTFS? |
cmp dword [bx+3], 'NTFS' |
jnz not_ntfs |
cmp byte [bx+16], bl |
jz ntfs |
not_ntfs: |
; is it FAT? FAT12/FAT16/FAT32? |
; get count of sectors to dword in cx:si |
mov si, [bx+19] |
xor cx, cx |
test si, si |
jnz @f |
mov si, [bx+32] |
mov cx, [bx+34] |
@@: |
xor eax, eax |
; subtract size of system area |
sub si, [bx+14] ; BPB_ResvdSecCnt |
sbb cx, ax |
mov ax, [bx+17] ; BPB_RootEntCnt |
add ax, 0xF |
rcr ax, 1 |
shr ax, 3 |
sub si, ax |
sbb cx, 0 |
push cx |
push si |
mov ax, word [bx+22] |
test ax, ax |
jnz @f |
mov eax, [bx+36] |
@@: |
movzx ecx, byte [bx+16] |
imul ecx, eax |
pop eax |
sub eax, ecx |
; now eax = count of sectors in the data region |
xor edx, edx |
div [bp + sect_per_clust - dat] |
; now eax = count of clusters in the data region |
mov si, fatxx_msg |
cmp eax, 0xFFF5 |
jae test_fat32 |
; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38 |
cmp byte [bx+38], 0x29 |
jnz not_fat |
cmp ax, 0xFF5 |
jae fat16 |
fat12: |
mov [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster |
mov di, cx ; BPB_NumFATs |
mov ax, '12' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
movzx ecx, word [bx+22] ; BPB_FATSz16 |
; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes) |
.fatloop: |
; if first copy is not readable, try to switch to other copies |
push 0x6000 |
pop es |
xor bx, bx |
movzx eax, word [0x320E] ; BPB_RsvdSecCnt |
push cx |
cmp cx, 12 |
jb @f |
mov cx, 12 |
@@: |
call read |
pop cx |
jnc fat1x_common |
add eax, ecx ; switch to next copy of FAT |
dec di |
jnz .fatloop |
mov si, disk_error_msg |
jmp find_error_si |
fat16: |
mov [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster |
mov ax, '16' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT16: init FAT cache - no sectors loaded |
mov di, 0x3400 |
xor ax, ax |
mov cx, 0x100/2 |
rep stosw |
fat1x_common: |
mov bx, 0x3200 |
movzx eax, word [bx+22] ; BPB_FATSz16 |
xor esi, esi ; no root cluster |
jmp fat_common |
test_fat32: |
; FAT32 bootsector has it at the offset +66 |
cmp byte [bx+66], 0x29 |
jnz not_fat |
mov [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster |
mov ax, '32' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT32 - init cache for FAT table: no sectors loaded |
lea si, [bp + cache1head - dat] |
mov [si], si ; no sectors in cache: |
mov [si+2], si ; 'prev' & 'next' links point to self |
mov [bp + cache1end - dat], 3400h ; first free item = 3400h |
mov [bp + cache1limit - dat], 3C00h |
mov eax, [bx+36] ; BPB_FATSz32 |
mov esi, [bx+44] ; BPB_RootClus |
jmp fat_common |
not_fat: |
unknown_fs: |
mov si, errfs_msg |
call out_string |
jmp next_partition |
fat_common: |
push ss |
pop es |
movzx edx, byte [bx+16] ; BPB_NumFATs |
mul edx |
mov [bp + root_start - dat], eax ; this is for FAT1x |
; eax = total size of all FAT tables, in sectors |
movzx ecx, word [bx+17] ; BPB_RootEntCnt |
add ecx, 0xF |
shr ecx, 4 |
add eax, ecx |
mov cx, word [bx+14] ; BPB_RsvdSecCnt |
add [bp + root_start - dat], ecx ; this is for FAT1x |
add eax, ecx |
; cluster 2 begins from sector eax |
movzx ebx, byte [bx+13] ; BPB_SecPerClus |
sub eax, ebx |
sub eax, ebx |
mov [bp + data_start - dat], eax |
; no clusters in folders cache |
mov di, foldcache_clus - 2 |
xor ax, ax |
mov cx, 7*8/2 + 1 |
rep stosw |
mov [bp + root_clus - dat], esi |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_fat |
load_secondary: |
push 0x1000 |
pop es |
xor bx, bx |
mov si, kernel_name |
mov cx, 0x30000 / 0x200 |
call [bp + load_file_ptr - dat] |
; say error if needed |
mov si, error_too_big |
dec bx |
js @f |
jz find_error_si |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
; fill loader information and jump to secondary loader |
mov al, 'h' ; boot device: hard drive |
mov ah, [bp + boot_drive - dat] |
sub ah, 80h ; boot device: identifier |
pop bx ; restore file system ID ('12'/'16'/'32'/'nt') |
mov si, callback |
jmp 1000h:0000h |
nomem: |
mov si, nomem_msg |
call out_string |
jmp $ |
ntfs: |
push 'nt' ; save for secondary loader |
mov si, ntfs_msg |
call out_string |
xor eax, eax |
mov [bp + data_start - dat], eax |
mov ecx, [bx+40h] ; frs_size |
cmp cl, al |
jg .1 |
neg cl |
inc ax |
shl eax, cl |
jmp .2 |
.1: |
mov eax, ecx |
shl eax, 9 |
.2: |
mov [bp + frs_size - dat], ax |
; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different |
; (at least with standard tools) |
; we allow extra size, but no more than 0x1000 bytes = 4 Kb |
mov si, invalid_volume_msg |
cmp eax, 0x1000 |
ja find_error_si |
; must be multiple of sector size |
test ax, 0x1FF |
jnz find_error_si |
shr ax, 9 |
xchg cx, ax |
; initialize cache - no data loaded |
lea si, [bp + cache1head - dat] |
mov [si], si |
mov [si+2], si |
mov word [si+4], 3400h ; first free item = 3400h |
mov word [si+6], 3400h + 8*8 ; 8 items in this cache |
; read first MFT record - description of MFT itself |
mov [bp + cur_obj - dat], mft_string |
mov eax, [bx+30h] ; mft_cluster |
mul [bp + sect_per_clust - dat] |
push 0x8000 |
pop es |
xor bx, bx |
push es |
call read |
pop ds |
call restore_usa |
; scan for unnamed $DATA attribute |
mov [bp + freeattr - dat], 4000h |
mov ax, 80h |
call load_attr |
push ss |
pop ds |
mov si, nodata_string |
jc find_error_si |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_ntfs |
jmp load_secondary |
find_error_si: |
push si |
find_error_sp: |
cmp [bp + in_callback - dat], 0 |
jnz error_in_callback |
push ss |
pop ds |
push ss |
pop es |
mov si, error_msg |
call out_string |
mov si, [bp + cur_obj - dat] |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
mov si, colon |
call out_string |
pop si |
call out_string |
mov si, newline |
call out_string |
mov sp, 0x3000 |
jmp next_partition |
error_in_callback: |
; return status: file not found, except for read errors |
mov bx, 2 |
cmp si, disk_error_msg |
jnz @f |
inc bx |
@@: |
mov ax, 0xFFFF |
mov dx, ax |
mov sp, 3000h - 6 |
ret |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 3000h |
mov bp, dat |
mov [bp + in_callback - dat], 1 |
push dx |
push cx |
; set ds:si -> ASCIIZ name |
lea si, [di+6] |
; set cx = limit in sectors; 4Kb = 8 sectors |
movzx ecx, word [di+4] |
shl cx, 3 |
; set es:bx = pointer to buffer |
les bx, [di] |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call [bp + load_file_ptr - dat] |
callback_ret_succ: |
clc |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
read_file_chunk.resident: |
; auxiliary label for read_file_chunk procedure |
mov di, bx |
lodsw |
read_file_chunk.resident.continue: |
mov dx, ax |
add dx, 0x1FF |
shr dx, 9 |
cmp dx, cx |
jbe @f |
mov ax, cx |
shl ax, 9 |
@@: |
xchg ax, cx |
rep movsb |
xchg ax, cx |
clc ; no disk error if no disk requests |
mov word [bp + num_sectors - dat], ax |
ret |
read_file_chunk: |
; in: ds:si -> file chunk |
; in: es:bx -> buffer for output |
; in: ecx = maximum number of sectors to read (high word must be 0) |
; out: CF=1 <=> disk read error |
lodsb |
mov [bp + cur_chunk_resident - dat], al |
test al, al |
jz .resident |
; normal case: load (non-resident) attribute from disk |
.read_block: |
lodsd |
xchg eax, edx |
test edx, edx |
jz .ret |
lodsd |
; eax = start cluster, edx = number of clusters, cx = limit in sectors |
imul eax, [bp + sect_per_clust - dat] |
add eax, [bp + data_start - dat] |
mov [bp + cur_cluster - dat], eax |
imul edx, [bp + sect_per_clust - dat] |
mov [bp + num_sectors - dat], edx |
and [bp + cur_delta - dat], 0 |
.nonresident.continue: |
cmp edx, ecx |
jb @f |
mov edx, ecx |
@@: |
test dx, dx |
jz .read_block |
add [bp + cur_delta - dat], edx |
sub [bp + num_sectors - dat], edx |
sub ecx, edx |
push cx |
mov cx, dx |
call read |
pop cx |
jc .ret |
test cx, cx |
jnz .read_block |
.ret: |
ret |
cache_lookup: |
; in: eax = value to look, si = pointer to cache structure |
; out: di->cache entry; CF=1 <=> the value was not found |
push ds bx |
push ss |
pop ds |
mov di, [si+2] |
.look: |
cmp di, si |
jz .not_in_cache |
cmp eax, [di+4] |
jz .in_cache |
mov di, [di+2] |
jmp .look |
.not_in_cache: |
; cache miss |
; cache is full? |
mov di, [si+4] |
cmp di, [si+6] |
jnz .cache_not_full |
; yes, delete the oldest entry |
mov di, [si] |
mov bx, [di] |
mov [si], bx |
push word [di+2] |
pop word [bx+2] |
jmp .cache_append |
.cache_not_full: |
; no, allocate new item |
add word [si+4], 8 |
.cache_append: |
mov [di+4], eax |
stc |
jmp @f |
.in_cache: |
; delete this sector from the list |
push si |
mov si, [di] |
mov bx, [di+2] |
mov [si+2], bx |
mov [bx], si |
pop si |
@@: |
; add new sector to the end of list |
mov bx, di |
xchg bx, [si+2] |
push word [bx] |
pop word [di] |
mov [bx], di |
mov [di+2], bx |
pop bx ds |
ret |
include 'fat.inc' |
include 'ntfs.inc' |
total_kaput db 13,10,'Fatal error: cannot load the secondary loader',0 |
error_too_big db 'file is too big',0 |
nodata_string db '$DATA ' |
error_not_found db 'not found',0 |
noindex_string db '$INDEX_ROOT not found',0 |
badname_msg db 'bad name for FAT',0 |
invalid_volume_msg db 'invalid volume',0 |
mft_string db '$MFT',0 |
fragmented_string db 'too fragmented file',0 |
invalid_read_request_string db 'cannot read attribute',0 |
kernel_name db 'kernel.mnt',0 |
align 4 |
dat: |
extended_part_start dd 0 ; start sector for main extended partition |
extended_part_cur dd ? ; start sector for current extended child |
extended_parent dd 0 ; start sector for current extended parent |
partition_start dd 0 ; start sector for current logical disk |
cur_partition_ofs dw ? ; offset in MBR data for current partition |
sect_per_clust dd 0 |
; change this variable if you want to boot from other physical drive |
boot_drive db 80h |
in_callback db 0 |
; uninitialized data |
use_lba db ? |
cur_chunk_resident db ? |
align 2 |
heads dw ? |
sectors dw ? |
cache1head rw 2 |
cache1end dw ? |
cache1limit dw ? |
data_start dd ? |
cachelimit dw ? |
load_file_ptr dw ? |
cur_obj dw ? |
missing_slash dw ? |
root_clus dd ? |
root_start dd ? |
get_next_cluster_ptr dw ? |
frs_size dw ? |
freeattr dw ? |
index_root dw ? |
index_alloc dw ? |
cur_index_seg dw ? |
cur_index_cache dw ? |
filesize dd ? |
filesize_sectors dd ? |
cur_cluster dd ? |
cur_delta dd ? |
num_sectors dd ? |
sectors_read dd ? |
cur_chunk_ptr dw ? |
rootcache_size dw ? ; must be immediately before foldcache_clus |
if $-dat >= 0x80 |
warning: |
unoptimal data displacement! |
end if |
foldcache_clus rd 7 |
foldcache_mark rw 7 |
foldcache_size rw 7 |
fat_filename rb 11 |
if $ > 2000h |
error: |
file is too big |
end if |
; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long |
repeat 0x2600 - $ |
db 2 ; any data can be here; 2 is another nice face in ASCII :) |
end repeat |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/after_win/ntfs.inc |
---|
1,587 → 1,587 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
restore_usa: |
; Update Sequence Array restore |
; in: ds:bx -> USA-protected structure |
push bx |
lea di, [bx+1feh] |
mov cx, [bx+6] |
add bx, [bx+4] |
dec cx |
@@: |
mov ax, [bx+2] |
mov [di], ax |
inc bx |
inc bx |
add di, 200h |
loop @b |
pop bx |
ret |
find_attr: |
; in: ds:di->file record, ax=attribute |
; out: ds:di->attribute or di=0 if not found |
add di, [di+14h] |
.1: |
; attributes' codes are formally dwords, but all of them fit in word |
cmp word [di], -1 |
jz .notfound |
cmp word [di], ax |
jnz .continue |
; for $DATA attribute, scan only unnamed |
cmp ax, 80h |
jnz .found |
cmp byte [di+9], 0 |
jz .found |
.continue: |
add di, [di+4] |
jmp .1 |
.notfound: |
xor di, di |
.found: |
ret |
process_mcb_nonres: |
; in: ds:si->attribute, es:di->buffer |
; out: es:di->buffer end |
pushad |
pop di |
add si, [si+20h] |
xor ebx, ebx |
.loop: |
lodsb |
test al, al |
jz .done |
push invalid_read_request_string |
movzx cx, al |
shr cx, 4 |
jz find_error_sp |
xchg ax, dx |
and dx, 0Fh |
jz find_error_sp |
add si, cx |
add si, dx |
pop ax |
push si |
dec si |
movsx eax, byte [si] |
dec cx |
jz .l1e |
.l1: |
dec si |
shl eax, 8 |
mov al, [si] |
loop .l1 |
.l1e: |
xchg ebp, eax |
dec si |
movsx eax, byte [si] |
mov cx, dx |
dec cx |
jz .l2e |
.l2: |
dec si |
shl eax, 8 |
mov al, byte [si] |
loop .l2 |
.l2e: |
pop si |
add ebx, ebp |
; eax=length, ebx=disk block |
stosd |
mov eax, ebx |
stosd |
cmp di, 0x8000 - 12 |
jbe .loop |
..attr_overflow: |
mov si, fragmented_string |
jmp find_error_si |
.done: |
xor ax, ax |
stosw |
stosw |
push di |
popad |
ret |
load_attr: |
; in: ax=attribute, ds:bx->base record |
; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, |
; edx=size of attribute in bytes |
; out: if not found: CF=1 |
mov di, [bp + freeattr - dat] |
push ss |
pop es |
mov byte [es:di], 1 |
inc di |
cmp di, 0x8000 - 12 |
ja ..attr_overflow |
or edx, -1 ; file size is not known yet |
; scan for attribute |
push di |
mov di, bx |
add di, [di+14h] |
@@: |
call find_attr.1 |
test di, di |
jz .notfound1 |
cmp byte [di+8], 0 |
jnz .nonresident |
mov si, di |
pop di |
push ds |
jmp .resident |
.aux_resident: |
mov ax, ds |
mov si, di |
pop di ds bx ds edx |
push ss |
pop es |
push ds |
mov ds, ax |
; resident attribute |
.resident: |
dec di |
mov al, 0 |
stosb |
mov ax, [si+10h] |
stosw |
push di |
add di, ax |
cmp di, 0x8000 - 12 |
pop di |
ja ..attr_overflow |
movzx edx, ax ; length of attribute |
xchg ax, cx |
add si, [si+14h] |
rep movsb |
mov [bp + freeattr - dat], di |
pop ds |
ret |
.nonresident: |
; nonresident attribute |
cmp dword [di+10h], 0 |
jnz @b |
; read start of data |
mov si, di |
mov edx, [di+30h] ; size of attribute |
pop di |
call process_mcb_nonres |
sub di, 4 |
push di |
.notfound1: |
pop di |
push edx |
; $ATTRIBUTE_LIST is always in base file record |
cmp ax, 20h |
jz .nofragmented |
; try to load $ATTRIBUTE_LIST = 20h |
push ax |
mov ax, 20h |
push [bp + freeattr - dat] |
mov [bp + freeattr - dat], di |
push di |
call load_attr |
pop di |
pop [bp + freeattr - dat] |
pop ax |
jc .nofragmented |
push ds bx |
pusha |
mov si, di |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
popa |
push ss |
pop es |
xor bx, bx |
.1: |
cmp [bx], ax |
jnz .continue1 |
; only unnamed $DATA attributes! |
cmp ax, 80h |
jnz @f |
cmp byte [bx+6], 0 |
jnz .continue1 |
@@: |
cmp dword [bx+10h], 0 |
jz .continue1 |
cmp dword [bx+8], 0 |
jnz @f |
dec di |
cmp di, [bp + freeattr - dat] |
lea di, [di+1] |
jnz .continue1 |
@@: |
push ds di |
push ax |
mov eax, [bx+10h] |
mov ecx, [bx+8] |
call read_file_record |
pop ax |
mov di, [14h] |
.2: |
call find_attr.1 |
cmp byte [di+8], 0 |
jz .aux_resident |
cmp dword [di+10h], ecx |
jnz .2 |
mov si, di |
mov di, sp |
cmp dword [ss:di+8], -1 |
jnz @f |
push dword [si+30h] ; size of attribute |
pop dword [ss:di+8] |
@@: |
pop di |
call process_mcb_nonres |
sub di, 4 |
pop ds |
.continue1: |
add bx, [bx+4] |
cmp bx, dx |
jb .1 |
pop bx ds |
.nofragmented: |
pop edx |
dec di |
cmp di, [bp + freeattr - dat] |
jnz @f |
stc |
ret |
@@: |
inc di |
xor ax, ax |
stosw |
stosw |
mov [bp + freeattr - dat], di |
ret |
read_file_record: |
; in: eax = index of record |
; out: ds:0 -> record |
; find place in cache |
push di |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
pushf |
sub di, 3400h |
shl di, 10-3 |
add di, 0x6000 |
mov ds, di |
popf |
pop di |
jnc .noread |
; read file record <eax> to ds:0 |
pushad |
push ds |
push es |
movzx ecx, [bp + frs_size - dat] |
shr cx, 9 |
mul ecx |
push ds |
pop es |
push ss |
pop ds |
mov si, 0x4000 |
xor bx, bx |
push [bp + cur_obj - dat] |
mov [bp + cur_obj - dat], mft_string |
push es |
call read_attr |
; initialize cache for $INDEX_ALLOCATION for this record |
pop si |
push si |
sub si, 0x6000 |
mov ax, si |
shr si, 10-3 |
shr ax, 2 |
add si, 3480h |
add ax, 3500h |
mov [si], si |
mov [si+2], si |
mov [si+4], ax |
pop ds |
call restore_usa |
pop [bp + cur_obj - dat] |
pop es |
pop ds |
popad |
.noread: |
ret |
read_attr: |
; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute |
push invalid_read_request_string |
cmp byte [si], 0 |
jnz .nonresident |
cmp eax, 10000h shr 9 |
jae find_error_sp |
shl ax, 9 |
shl cx, 9 |
cmp ax, [si+2] |
jae find_error_sp |
cmp cx, [si+2] |
ja find_error_sp |
add si, 3 |
add si, ax |
mov di, bx |
rep movsb |
pop ax |
ret |
.nonresident: |
inc si |
.loop: |
mov edx, dword [si] |
add si, 8 |
test edx, edx |
jz find_error_sp |
imul edx, [bp + sect_per_clust - dat] |
sub eax, edx |
jnc .loop |
add eax, edx |
sub edx, eax |
push cx |
cmp ecx, edx |
jb @f |
mov cx, dx |
@@: |
push bx |
mov ebx, [si-4] |
imul ebx, [bp + sect_per_clust - dat] |
add eax, ebx |
pop bx |
call read |
jc ..found_disk_error |
mov dx, cx |
pop cx |
xor eax, eax |
sub cx, dx |
jnz .loop |
pop ax |
ret |
load_file_ntfs: |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
push es bx cx |
mov eax, 5 ; root cluster |
mov [bp + cur_obj - dat], root_string |
.parse_dir_loop: |
push ds si |
call read_file_record |
; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP |
mov ax, [bp + freeattr - dat] |
mov [bp + index_root - dat], ax |
mov ax, 90h ; $INDEX_ROOT |
xor bx, bx |
call load_attr |
mov si, noindex_string |
jc find_error_si |
mov ax, [bp + freeattr - dat] |
mov [bp + index_alloc - dat], ax |
mov ax, 0A0h ; $INDEX_ALLOCATION |
call load_attr |
jnc @f |
mov [bp + index_alloc - dat], bx |
@@: |
push ds |
; search for entry |
mov si, [bp + index_root - dat] |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
mov si, invalid_read_request_string |
cmp word [bx+10], 0 |
jnz find_error_si |
; calculate number of items in cache |
mov di, [bx+8] ; subnode_size |
mov ax, 0x4000 |
sub ax, word [bp + frs_size - dat] |
cwd |
div di |
test ax, ax |
jz find_error_si |
mov si, invalid_volume_msg |
test di, 0x1FF |
jnz find_error_si |
pop cx |
mov [bp + cur_index_seg - dat], cx |
shl ax, 3 |
sub cx, 6000h |
mov si, cx |
shr cx, 2 |
shr si, 10-3 |
add cx, ax |
add si, 3480h |
mov [bp + cur_index_cache - dat], si |
add cx, 3500h |
mov [ss:si+6], cx |
mov dx, di |
add bx, 10h |
.scan_record: |
add bx, [bx] |
.scan: |
test byte [bx+0Ch], 2 |
jnz .look_child |
movzx cx, byte [bx+50h] ; namelen |
lea di, [bx+52h] ; name |
push ds |
pop es |
pop si ds |
push ds si |
xor ax, ax |
.1: |
lodsb |
cmp al, '/' |
jnz @f |
mov al, 0 |
@@: |
cmp al, 'A' |
jb .nocapital |
cmp al, 'Z' |
ja .nocapital |
or al, 20h |
.nocapital: |
cmp al, 'a' |
jb .notletter |
cmp al, 'z' |
ja .notletter |
or byte [es:di], 20h |
.notletter: |
scasw |
loopz .1 |
jb .look_child |
ja @f |
cmp byte [si], 0 |
jz .file_found |
cmp byte [si], '/' |
jz .file_found |
@@: |
push es |
pop ds |
add bx, [bx+8] |
jmp .scan |
.look_child: |
push es |
pop ds |
test byte [bx+0Ch], 1 |
jz .not_found |
mov si, [bp + index_alloc - dat] |
test si, si |
jz .not_found |
add bx, [bx+8] |
mov eax, [bx-8] |
mov es, [bp + cur_index_seg - dat] |
push si |
mov si, [bp + cur_index_cache - dat] |
call cache_lookup |
pop si |
pushf |
mov bx, di |
mov bh, 0 |
shr bx, 3 |
imul bx, dx |
add bx, [bp + frs_size - dat] |
popf |
jnc .noread |
push es |
push dx |
push ss |
pop ds |
movzx ecx, dx |
shr cx, 9 |
mul [bp + sect_per_clust - dat] |
call read_attr |
pop dx |
pop es |
push es |
pop ds |
call restore_usa |
.noread: |
push es |
pop ds |
add bx, 18h |
jmp .scan_record |
.not_found: |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.file_found: |
pop [bp + cur_obj - dat] |
pop cx |
mov ax, [bp + index_root - dat] |
mov [bp + freeattr - dat], ax |
mov eax, [es:bx] |
test byte [es:bx+48h+3], 10h |
jz .regular_file |
cmp byte [si], 0 |
jz ..directory_error |
inc si |
jmp .parse_dir_loop |
.regular_file: |
cmp byte [si], 0 |
jnz ..notdir_error |
; read entry |
call read_file_record |
xor bx, bx |
mov ax, 80h |
call load_attr |
mov si, nodata_string |
jc find_error_si |
mov si, [bp + index_root - dat] |
mov [bp + freeattr - dat], si |
push ss |
pop ds |
jmp load_file_common_end |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
restore_usa: |
; Update Sequence Array restore |
; in: ds:bx -> USA-protected structure |
push bx |
lea di, [bx+1feh] |
mov cx, [bx+6] |
add bx, [bx+4] |
dec cx |
@@: |
mov ax, [bx+2] |
mov [di], ax |
inc bx |
inc bx |
add di, 200h |
loop @b |
pop bx |
ret |
find_attr: |
; in: ds:di->file record, ax=attribute |
; out: ds:di->attribute or di=0 if not found |
add di, [di+14h] |
.1: |
; attributes' codes are formally dwords, but all of them fit in word |
cmp word [di], -1 |
jz .notfound |
cmp word [di], ax |
jnz .continue |
; for $DATA attribute, scan only unnamed |
cmp ax, 80h |
jnz .found |
cmp byte [di+9], 0 |
jz .found |
.continue: |
add di, [di+4] |
jmp .1 |
.notfound: |
xor di, di |
.found: |
ret |
process_mcb_nonres: |
; in: ds:si->attribute, es:di->buffer |
; out: es:di->buffer end |
pushad |
pop di |
add si, [si+20h] |
xor ebx, ebx |
.loop: |
lodsb |
test al, al |
jz .done |
push invalid_read_request_string |
movzx cx, al |
shr cx, 4 |
jz find_error_sp |
xchg ax, dx |
and dx, 0Fh |
jz find_error_sp |
add si, cx |
add si, dx |
pop ax |
push si |
dec si |
movsx eax, byte [si] |
dec cx |
jz .l1e |
.l1: |
dec si |
shl eax, 8 |
mov al, [si] |
loop .l1 |
.l1e: |
xchg ebp, eax |
dec si |
movsx eax, byte [si] |
mov cx, dx |
dec cx |
jz .l2e |
.l2: |
dec si |
shl eax, 8 |
mov al, byte [si] |
loop .l2 |
.l2e: |
pop si |
add ebx, ebp |
; eax=length, ebx=disk block |
stosd |
mov eax, ebx |
stosd |
cmp di, 0x8000 - 12 |
jbe .loop |
..attr_overflow: |
mov si, fragmented_string |
jmp find_error_si |
.done: |
xor ax, ax |
stosw |
stosw |
push di |
popad |
ret |
load_attr: |
; in: ax=attribute, ds:bx->base record |
; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, |
; edx=size of attribute in bytes |
; out: if not found: CF=1 |
mov di, [bp + freeattr - dat] |
push ss |
pop es |
mov byte [es:di], 1 |
inc di |
cmp di, 0x8000 - 12 |
ja ..attr_overflow |
or edx, -1 ; file size is not known yet |
; scan for attribute |
push di |
mov di, bx |
add di, [di+14h] |
@@: |
call find_attr.1 |
test di, di |
jz .notfound1 |
cmp byte [di+8], 0 |
jnz .nonresident |
mov si, di |
pop di |
push ds |
jmp .resident |
.aux_resident: |
mov ax, ds |
mov si, di |
pop di ds bx ds edx |
push ss |
pop es |
push ds |
mov ds, ax |
; resident attribute |
.resident: |
dec di |
mov al, 0 |
stosb |
mov ax, [si+10h] |
stosw |
push di |
add di, ax |
cmp di, 0x8000 - 12 |
pop di |
ja ..attr_overflow |
movzx edx, ax ; length of attribute |
xchg ax, cx |
add si, [si+14h] |
rep movsb |
mov [bp + freeattr - dat], di |
pop ds |
ret |
.nonresident: |
; nonresident attribute |
cmp dword [di+10h], 0 |
jnz @b |
; read start of data |
mov si, di |
mov edx, [di+30h] ; size of attribute |
pop di |
call process_mcb_nonres |
sub di, 4 |
push di |
.notfound1: |
pop di |
push edx |
; $ATTRIBUTE_LIST is always in base file record |
cmp ax, 20h |
jz .nofragmented |
; try to load $ATTRIBUTE_LIST = 20h |
push ax |
mov ax, 20h |
push [bp + freeattr - dat] |
mov [bp + freeattr - dat], di |
push di |
call load_attr |
pop di |
pop [bp + freeattr - dat] |
pop ax |
jc .nofragmented |
push ds bx |
pusha |
mov si, di |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
popa |
push ss |
pop es |
xor bx, bx |
.1: |
cmp [bx], ax |
jnz .continue1 |
; only unnamed $DATA attributes! |
cmp ax, 80h |
jnz @f |
cmp byte [bx+6], 0 |
jnz .continue1 |
@@: |
cmp dword [bx+10h], 0 |
jz .continue1 |
cmp dword [bx+8], 0 |
jnz @f |
dec di |
cmp di, [bp + freeattr - dat] |
lea di, [di+1] |
jnz .continue1 |
@@: |
push ds di |
push ax |
mov eax, [bx+10h] |
mov ecx, [bx+8] |
call read_file_record |
pop ax |
mov di, [14h] |
.2: |
call find_attr.1 |
cmp byte [di+8], 0 |
jz .aux_resident |
cmp dword [di+10h], ecx |
jnz .2 |
mov si, di |
mov di, sp |
cmp dword [ss:di+8], -1 |
jnz @f |
push dword [si+30h] ; size of attribute |
pop dword [ss:di+8] |
@@: |
pop di |
call process_mcb_nonres |
sub di, 4 |
pop ds |
.continue1: |
add bx, [bx+4] |
cmp bx, dx |
jb .1 |
pop bx ds |
.nofragmented: |
pop edx |
dec di |
cmp di, [bp + freeattr - dat] |
jnz @f |
stc |
ret |
@@: |
inc di |
xor ax, ax |
stosw |
stosw |
mov [bp + freeattr - dat], di |
ret |
read_file_record: |
; in: eax = index of record |
; out: ds:0 -> record |
; find place in cache |
push di |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
pushf |
sub di, 3400h |
shl di, 10-3 |
add di, 0x6000 |
mov ds, di |
popf |
pop di |
jnc .noread |
; read file record <eax> to ds:0 |
pushad |
push ds |
push es |
movzx ecx, [bp + frs_size - dat] |
shr cx, 9 |
mul ecx |
push ds |
pop es |
push ss |
pop ds |
mov si, 0x4000 |
xor bx, bx |
push [bp + cur_obj - dat] |
mov [bp + cur_obj - dat], mft_string |
push es |
call read_attr |
; initialize cache for $INDEX_ALLOCATION for this record |
pop si |
push si |
sub si, 0x6000 |
mov ax, si |
shr si, 10-3 |
shr ax, 2 |
add si, 3480h |
add ax, 3500h |
mov [si], si |
mov [si+2], si |
mov [si+4], ax |
pop ds |
call restore_usa |
pop [bp + cur_obj - dat] |
pop es |
pop ds |
popad |
.noread: |
ret |
read_attr: |
; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute |
push invalid_read_request_string |
cmp byte [si], 0 |
jnz .nonresident |
cmp eax, 10000h shr 9 |
jae find_error_sp |
shl ax, 9 |
shl cx, 9 |
cmp ax, [si+2] |
jae find_error_sp |
cmp cx, [si+2] |
ja find_error_sp |
add si, 3 |
add si, ax |
mov di, bx |
rep movsb |
pop ax |
ret |
.nonresident: |
inc si |
.loop: |
mov edx, dword [si] |
add si, 8 |
test edx, edx |
jz find_error_sp |
imul edx, [bp + sect_per_clust - dat] |
sub eax, edx |
jnc .loop |
add eax, edx |
sub edx, eax |
push cx |
cmp ecx, edx |
jb @f |
mov cx, dx |
@@: |
push bx |
mov ebx, [si-4] |
imul ebx, [bp + sect_per_clust - dat] |
add eax, ebx |
pop bx |
call read |
jc ..found_disk_error |
mov dx, cx |
pop cx |
xor eax, eax |
sub cx, dx |
jnz .loop |
pop ax |
ret |
load_file_ntfs: |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
push es bx cx |
mov eax, 5 ; root cluster |
mov [bp + cur_obj - dat], root_string |
.parse_dir_loop: |
push ds si |
call read_file_record |
; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP |
mov ax, [bp + freeattr - dat] |
mov [bp + index_root - dat], ax |
mov ax, 90h ; $INDEX_ROOT |
xor bx, bx |
call load_attr |
mov si, noindex_string |
jc find_error_si |
mov ax, [bp + freeattr - dat] |
mov [bp + index_alloc - dat], ax |
mov ax, 0A0h ; $INDEX_ALLOCATION |
call load_attr |
jnc @f |
mov [bp + index_alloc - dat], bx |
@@: |
push ds |
; search for entry |
mov si, [bp + index_root - dat] |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
mov si, invalid_read_request_string |
cmp word [bx+10], 0 |
jnz find_error_si |
; calculate number of items in cache |
mov di, [bx+8] ; subnode_size |
mov ax, 0x4000 |
sub ax, word [bp + frs_size - dat] |
cwd |
div di |
test ax, ax |
jz find_error_si |
mov si, invalid_volume_msg |
test di, 0x1FF |
jnz find_error_si |
pop cx |
mov [bp + cur_index_seg - dat], cx |
shl ax, 3 |
sub cx, 6000h |
mov si, cx |
shr cx, 2 |
shr si, 10-3 |
add cx, ax |
add si, 3480h |
mov [bp + cur_index_cache - dat], si |
add cx, 3500h |
mov [ss:si+6], cx |
mov dx, di |
add bx, 10h |
.scan_record: |
add bx, [bx] |
.scan: |
test byte [bx+0Ch], 2 |
jnz .look_child |
movzx cx, byte [bx+50h] ; namelen |
lea di, [bx+52h] ; name |
push ds |
pop es |
pop si ds |
push ds si |
xor ax, ax |
.1: |
lodsb |
cmp al, '/' |
jnz @f |
mov al, 0 |
@@: |
cmp al, 'A' |
jb .nocapital |
cmp al, 'Z' |
ja .nocapital |
or al, 20h |
.nocapital: |
cmp al, 'a' |
jb .notletter |
cmp al, 'z' |
ja .notletter |
or byte [es:di], 20h |
.notletter: |
scasw |
loopz .1 |
jb .look_child |
ja @f |
cmp byte [si], 0 |
jz .file_found |
cmp byte [si], '/' |
jz .file_found |
@@: |
push es |
pop ds |
add bx, [bx+8] |
jmp .scan |
.look_child: |
push es |
pop ds |
test byte [bx+0Ch], 1 |
jz .not_found |
mov si, [bp + index_alloc - dat] |
test si, si |
jz .not_found |
add bx, [bx+8] |
mov eax, [bx-8] |
mov es, [bp + cur_index_seg - dat] |
push si |
mov si, [bp + cur_index_cache - dat] |
call cache_lookup |
pop si |
pushf |
mov bx, di |
mov bh, 0 |
shr bx, 3 |
imul bx, dx |
add bx, [bp + frs_size - dat] |
popf |
jnc .noread |
push es |
push dx |
push ss |
pop ds |
movzx ecx, dx |
shr cx, 9 |
mul [bp + sect_per_clust - dat] |
call read_attr |
pop dx |
pop es |
push es |
pop ds |
call restore_usa |
.noread: |
push es |
pop ds |
add bx, 18h |
jmp .scan_record |
.not_found: |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.file_found: |
pop [bp + cur_obj - dat] |
pop cx |
mov ax, [bp + index_root - dat] |
mov [bp + freeattr - dat], ax |
mov eax, [es:bx] |
test byte [es:bx+48h+3], 10h |
jz .regular_file |
cmp byte [si], 0 |
jz ..directory_error |
inc si |
jmp .parse_dir_loop |
.regular_file: |
cmp byte [si], 0 |
jnz ..notdir_error |
; read entry |
call read_file_record |
xor bx, bx |
mov ax, 80h |
call load_attr |
mov si, nodata_string |
jc find_error_si |
mov si, [bp + index_root - dat] |
mov [bp + freeattr - dat], si |
push ss |
pop ds |
jmp load_file_common_end |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/cdfs/bootsect.asm |
---|
1,1024 → 1,1024 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
jmp far 0:real_start |
; special text |
org $+0x7C00 |
real_start: |
; initialize |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov es, ax |
cld |
sti |
mov [bootdrive], dl |
; check LBA support |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cl, 1 |
jz err_ |
; get file system information |
; scan for Primary Volume Descriptor |
db 66h |
push 10h-1 |
pop eax |
pvd_scan_loop: |
mov cx, 1 |
inc eax |
mov bx, 0x1000 |
call read_sectors |
jnc @f |
fatal_read_err: |
mov si, aReadError |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
@@: |
push ds |
pop es |
cmp word [bx+1], 'CD' |
jnz pvd_scan_loop |
cmp word [bx+3], '00' |
jnz pvd_scan_loop |
cmp byte [bx+5], '1' |
jnz pvd_scan_loop |
; we have found ISO9660 descriptor, look for type |
cmp byte [bx], 1 ; Primary Volume Descriptor? |
jz pvd_found |
cmp byte [bx], 0xFF ; Volume Descriptor Set Terminator? |
jnz pvd_scan_loop |
; Volume Descriptor Set Terminator reached, no PVD found - fatal error |
mov si, no_pvd |
jmp err_ |
pvd_found: |
add bx, 80h |
mov ax, [bx] |
mov [lb_size], ax |
; calculate number of logical blocks in one sector |
mov ax, 800h |
cwd |
div word [bx] |
mov [lb_per_sec], ax |
; get location of root directory |
mov di, root_location |
movzx eax, byte [bx+1Dh] |
add eax, [bx+1Eh] |
stosd |
; get memory size |
int 12h |
mov si, nomem_str |
cmp ax, 71000h / 400h |
jb err_ |
shr ax, 1 |
sub ax, 60000h / 800h |
mov [size_rest], ax |
mov [free_ptr], 60000h / 800h |
; load path table |
; if size > 62K => it's very strange, avoid using it |
; if size > (size of cache)/2 => avoid using it too |
mov ecx, [bx+4] |
cmp ecx, 0x10000 - 0x800 |
ja nopathtable |
shr ax, 1 |
cmp ax, 0x20 |
jae @f |
shl ax, 11 |
cmp cx, ax |
ja nopathtable |
@@: |
; size is ok, try to load it |
mov [pathtable_size], cx |
mov eax, [bx+12] |
xor edx, edx |
div dword [lb_per_sec] |
imul dx, [bx] |
mov [pathtable_start], dx |
add cx, dx |
call cx_to_sectors |
xor bx, bx |
push 6000h |
pop es |
call read_sectors |
jc nopathtable |
; path table has been loaded |
inc [use_path_table] |
sub [size_rest], cx |
add [free_ptr], cx |
nopathtable: |
; init cache |
mov ax, [size_rest] |
mov [cache_size], ax |
mov ax, [free_ptr] |
mov [cache_start], ax |
; load secondary loader |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
jnz noloader |
; set registers for secondary loader |
mov ah, [bootdrive] |
mov al, 'c' |
mov bx, 'is' |
mov si, callback |
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 |
noloader: |
mov si, aKernelNotFound |
jmp err_ |
read_sectors: |
; es:bx = pointer to data |
; eax = first sector |
; cx = number of sectors |
pushad |
push ds |
do_read_sectors: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
db 66h |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [cs:bootdrive] |
mov ah, 42h |
int 13h |
jc diskreaderr |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 7 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz do_read_sectors |
pop ds |
popad |
ret |
diskreaderr: |
add sp, 10h + 2*2 |
pop ds |
popad |
stc |
out_string.ret: |
ret |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz .ret |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aNoLBA db 'The drive does not support LBA!',0 |
aReadError db 'Read error',0 |
no_pvd db 'Primary Volume Descriptor not found!',0 |
nomem_str db 'No memory',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
load_file: |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
; parse path to the file |
lea si, [di+6] |
mov eax, [cs:root_location] |
cmp [cs:use_path_table], 0 |
jz parse_dir |
; scan for path in path table |
push di |
push 6000h |
pop es |
mov di, [cs:pathtable_start] ; es:di = pointer to current entry in path table |
mov dx, 1 ; dx = number of current entry in path table, start from 1 |
mov cx, [cs:pathtable_size] |
pathtable_newparent: |
mov bx, dx ; bx = number of current parent in path table: root = 1 |
scan_path_table_e: |
call is_last_component |
jnc path_table_scanned |
scan_path_table_i: |
cmp word [es:di+6], bx |
jb .next |
ja path_table_notfound |
call test_filename1 |
jc .next |
@@: |
lodsb |
cmp al, '/' |
jnz @b |
jmp pathtable_newparent |
.next: |
; go to next entry |
inc dx |
movzx ax, byte [es:di] |
add ax, 8+1 |
and al, not 1 |
add di, ax |
sub cx, ax |
ja scan_path_table_i |
path_table_notfound: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 2 ; file not found |
ret |
path_table_scanned: |
movzx eax, byte [es:di+1] |
add eax, [es:di+2] |
pop di |
parse_dir: |
; eax = logical block, ds:di -> information structure, ds:si -> file name |
; was the folder already read? |
push di ds |
push cs |
pop ds |
mov [cur_desc_end], 2000h |
mov bx, cachelist |
.scan1: |
mov bx, [bx+2] |
cmp bx, cachelist |
jz .notfound |
cmp [bx+4], eax |
jnz .scan1 |
.found: |
; yes; delete this item from the list (the following code will append this item to the tail) |
mov di, [bx] |
push word [bx+2] |
pop word [di+2] |
mov di, [bx+2] |
push word [bx] |
pop word [di] |
mov di, bx |
jmp .scan |
.notfound: |
; no; load first sector of the folder to get its size |
push eax |
push si |
mov si, 1 |
call load_phys_sector_for_lb_force |
mov bx, si |
pop si |
pop eax |
jnc @f |
; read error - return |
.readerr: |
pop ds |
.readerr2: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 3 |
ret |
@@: |
; first item of the folder describes the folder itself |
; do not cache too big folders: size < 64K and size <= (total cache size)/2 |
cmp word [bx+12], 0 |
jnz .nocache |
mov cx, [cache_size] ; cx = cache size in sectors |
shr cx, 1 ; cx = (cache size)/2 |
cmp cx, 0x20 |
jae @f |
shl cx, 11 |
cmp [bx+10], cx |
ja .nocache |
@@: |
; we want to cache this folder; get space for it |
mov cx, [bx+10] |
call cx_to_sectors |
jnz .yescache |
.nocache: |
push dword [bx+10] |
pop dword [cur_nocache_len] |
call lb_to_sector |
push ds |
pop es |
pop ds |
.nocache_loop: |
push eax |
mov dx, 1800h |
call scan_for_filename_in_sector |
mov cx, dx |
pop eax |
jnc .j_scandone |
sub cx, bx |
sub word [es:cur_nocache_len], cx |
sbb word [es:cur_nocache_len+2], 0 |
jb .j_scandone |
ja @f |
cmp word [es:cur_nocache_len], 0 |
jz .j_scandone |
@@: |
mov cx, 1 |
inc eax |
push es |
mov bx, 1000h |
call read_sectors |
pop es |
jc .readerr2 |
jmp .nocache_loop |
.j_scandone: |
jmp .scandone |
.yescache: |
push bx |
mov bx, [cachelist.head] |
.freeloop: |
cmp cx, [size_rest] |
jbe .sizeok |
@@: |
; if we are here: there is not enough free space, so we must delete old folders' data |
; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2). |
; one loop iteration: delete data of one folder |
pusha |
mov dx, [bx+10] |
mov es, dx ; es = segment of folder data to be deleted |
xor di, di |
mov ax, [bx+8] |
add ax, 0x7FF |
rcr ax, 1 |
shr ax, 10 |
push ax |
shl ax, 11-4 ; get number of paragraphs in folder data to be deleted |
mov cx, [cache_size] |
add cx, [cache_start] |
push ds |
push ax |
add ax, dx |
mov ds, ax |
pop ax |
shl cx, 11-4 |
sub cx, dx ; cx = number of paragraphs to be moved |
push si |
xor si, si |
; move cx paragraphs from ds:si to es:di to get free space in the end of cache |
@@: |
sub cx, 1000h |
jbe @f |
push cx |
mov cx, 8000h |
rep movsw |
mov cx, ds |
add cx, 1000h |
mov ds, cx |
mov cx, es |
add cx, 1000h |
mov es, cx |
pop cx |
jmp @b |
@@: |
add cx, 1000h |
shl cx, 3 |
rep movsw |
pop si |
pop ds |
; correct positions in cache for existing items |
mov cx, 80h |
mov di, 8400h |
.correct: |
cmp [di+10], dx |
jbe @f |
sub [di+10], ax |
@@: |
add di, 12 |
loop .correct |
; some additional space is free now |
pop ax |
add [size_rest], ax |
sub [free_ptr], ax |
; add cache item to the list of free items |
mov dx, [bx] |
mov ax, [free_cache_item] |
mov [bx], ax |
mov [free_cache_item], bx |
mov bx, dx |
; current iteration done |
popa |
jmp .freeloop |
.sizeok: |
mov [cachelist.head], bx |
mov word [bx+2], cachelist |
; allocate new item in cache |
mov di, [free_cache_item] |
test di, di |
jz .nofree |
push word [di] |
pop [free_cache_item] |
jmp @f |
.nofree: |
mov di, [last_cache_item] |
add [last_cache_item], 12 |
@@: |
pop bx |
push si di |
; mov [di+4], eax ; start of folder |
scasd |
stosd |
push ax |
mov ax, [free_ptr] |
shl ax, 11-4 |
mov [di+10-8], ax |
mov es, ax |
pop ax |
add [free_ptr], cx |
sub [size_rest], cx |
; read folder data |
; first sector is already in memory, 0000:bx |
pusha |
mov cx, [bx+10] |
mov [di+8-8], cx ; folder size in bytes |
mov si, bx |
xor di, di |
mov cx, 0x1800 |
sub cx, si |
rep movsb |
pop ax |
push di |
popa |
; read rest of folder |
mov esi, dword [lb_per_sec] |
add eax, esi |
dec si |
not si |
and ax, si |
mov si, word [bx+10] |
mov bx, di |
pop di |
sub si, bx |
jbe @f |
mov [cur_limit], esi |
call read_many_bytes |
pop si |
jnc .scan |
jmp .readerr |
@@: |
pop si |
.scan: |
; now we have required cache item; append it to the end of list |
mov bx, [cachelist.tail] |
mov [cachelist.tail], di |
mov [di+2], bx |
mov word [di], cachelist |
mov [bx], di |
; scan for given filename |
mov es, [di+10] |
mov dx, [di+8] |
pop ds |
xor bx, bx |
call scan_for_filename_in_sector |
.scandone: |
push cs |
pop es |
mov bx, 2000h |
cmp bx, [es:cur_desc_end] |
jnz filefound |
j_notfound: |
jmp path_table_notfound |
filefound: |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
@@: |
mov cl, [es:bx+8] |
test al, al |
jz @f |
; parse next component of file name |
test cl, 2 ; directory? |
jz j_notfound |
mov eax, [es:bx] |
pop di |
jmp parse_dir |
@@: |
test cl, 2 ; directory? |
jnz j_notfound ; do not allow read directories as regular files |
; ok, now load the file |
pop di |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; esi = limit in 4K blocks |
shl esi, 12 ; esi = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, 2000h |
loadloop: |
and [cur_start], 0 |
.loadnew: |
mov esi, [cur_limit] |
mov eax, [cur_start] |
add esi, eax |
mov [overflow], 1 |
sub esi, [di+4] |
jb @f |
xor esi, esi |
dec [overflow] |
@@: |
add esi, [di+4] ; esi = number of bytes to read |
mov [cur_start], esi |
sub esi, eax |
jz .loadcontinue |
xor edx, edx |
div dword [lb_size] ; eax = number of logical blocks to skip, |
mov [first_byte], dx; [first_byte] = number of bytes to skip in 1st block |
cmp byte [di+10], 0 |
jnz .interleaved |
add eax, [di] |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
jc .readerr3 |
.loadcontinue: |
mov [cur_chunk], di |
add di, 11 |
cmp di, [cur_desc_end] |
jae @f |
cmp [cur_limit], 0 |
jnz loadloop |
@@: |
mov bx, [overflow] |
.calclen: |
; calculate length of file |
xor ax, ax |
xor dx, dx |
mov di, 2000h |
@@: |
add ax, [di+4] |
adc dx, [di+6] |
add di, 11 |
cmp di, [cur_desc_end] |
jb @b |
ret |
.interleaved: |
mov [cur_unit_limit], esi |
push esi |
; skip first blocks |
movzx ecx, byte [di+9] ; Unit Size |
movzx esi, byte [di+10] ; Interleave Gap |
add si, cx |
mov edx, [di] |
@@: |
sub eax, ecx |
jb @f |
add edx, esi |
jmp @b |
@@: |
add ecx, eax ; ecx = number of logical blocks to skip |
lea eax, [ecx+edx] ; eax = first logical block |
pop esi |
.interleaved_loop: |
; get number of bytes in current file unit |
push eax |
movzx eax, byte [di+9] |
sub ax, cx |
imul eax, dword [lb_size] |
cmp eax, esi |
ja .i2 |
.i1: |
xchg esi, eax |
.i2: |
pop eax |
sub [cur_unit_limit], esi |
push eax |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
pop eax |
jnc @f |
.readerr3: |
mov bx, 3 |
jmp .calclen |
@@: |
mov esi, [cur_unit_limit] |
test esi, esi |
jz .loadcontinue |
movzx ecx, byte [di+9] ; add Unit Size |
add cl, byte [di+10] ; add Interleave Gap |
adc ch, 0 |
add eax, ecx |
xor cx, cx |
mov [first_byte], cx |
jmp .interleaved_loop |
cx_to_sectors: |
add cx, 7FFh |
rcr cx, 1 |
shr cx, 10 |
ret |
is_last_component: |
; in: ds:si -> name |
; out: CF set <=> current component is not last (=> folder) |
push si |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
stc |
@@: |
pop si |
ret |
test_filename1: |
; in: ds:si -> filename, es:di -> path table item |
; out: CF set <=> no match |
pusha |
mov cl, [es:di] |
add di, 8 |
jmp test_filename2.start |
test_filename2: |
; in: ds:si -> filename, es:bx -> directory item |
; out: CF set <=> no match |
pusha |
mov cl, [es:bx+32] |
lea di, [bx+33] |
.start: |
mov ch, 0 |
@@: |
lodsb |
test al, al |
jz .test1 |
cmp al, '/' |
jz .test1 |
call toupper |
mov ah, al |
mov al, [es:di] |
call toupper |
inc di |
cmp al, ah |
loopz @b |
jnz .next1 |
; if we have reached this point: current name is done |
lodsb |
test al, al |
jz .ret |
cmp al, '/' |
jz .ret |
; if we have reached this point: current name is done, but input name continues |
; so they do not match |
jmp .next1 |
.test1: |
; if we have reached this point: input name is done, but current name continues |
; "filename.ext;version" in ISO-9660 represents file "filename.ext" |
; "filename." and "filename.;version" are also possible for "filename" |
cmp byte [es:di], '.' |
jnz @f |
inc di |
dec cx |
jz .ret |
@@: |
cmp byte [es:di], ';' |
jnz .next1 |
jmp .ret |
.next1: |
stc |
.ret: |
popa |
ret |
toupper: |
; in: al=symbol |
; out: al=symbol in uppercase |
cmp al, 'a' |
jb .ret |
cmp al, 'z' |
ja .ret |
sub al, 'a'-'A' |
.ret: |
ret |
scan_for_filename_in_sector: |
; in: ds:si->filename, es:bx->folder data, dx=limit |
; out: CF=0 if found |
push bx |
.loope: |
push bx |
.loop: |
cmp bx, dx |
jae .notfound |
cmp byte [es:bx], 0 |
jz .loopd |
test byte [es:bx+25], 4 ; ignore files with Associated bit |
jnz .next |
call test_filename2 |
jc .next |
push ds es di |
push es |
pop ds |
push cs |
pop es |
mov di, [es:cur_desc_end] |
movzx eax, byte [bx+1] |
add eax, [bx+2] |
stosd ; first logical block |
mov eax, [bx+10] |
stosd ; length |
mov al, [bx+25] |
stosb ; flags |
mov ax, [bx+26] |
stosw ; File Unit size, Interleave Gap size |
mov [es:cur_desc_end], di |
cmp di, 3000h |
pop di es ds |
jae .done |
test byte [es:bx+25], 80h |
jz .done |
.next: |
add bl, [es:bx] |
adc bh, 0 |
jmp .loop |
.loopd: |
mov ax, bx |
pop bx |
@@: |
add bx, [cs:lb_size] |
jz .done2 |
cmp bx, ax |
jb @b |
jmp .loope |
.notfound: |
stc |
.done: |
pop bx |
.done2: |
pop bx |
ret |
lb_to_sector: |
xor edx, edx |
div dword [lb_per_sec] |
ret |
load_phys_sector_for_lb_force: |
; in: eax = logical block, ds=0 |
; in: si=0 - accept 0 logical blocks, otherwise force read at least 1 |
; out: 0000:1000 = physical sector data; si -> logical block |
; out: eax = next physical sector |
; out: CF=1 if read error |
; destroys cx |
; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector |
call lb_to_sector |
or si, dx |
jnz @f |
mov si, 1800h |
jmp .done |
@@: |
mov si, 1000h |
imul dx, [lb_size] |
add si, dx |
mov cx, 1 |
push es bx |
push ds |
pop es |
mov bx, 1000h |
call read_sectors |
pop bx es |
inc eax |
.done: |
ret |
normalize: |
; in: es:bx = far pointer |
; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10) |
push ax bx |
mov ax, es |
shr bx, 4 |
add ax, bx |
mov es, ax |
pop bx ax |
and bx, 0x0F |
ret |
read_many_bytes: |
and [first_byte], 0 |
read_many_bytes.with_first: |
; read esi bytes from logical block dx:ax to buffer es:bx |
; out: CF=1 <=> disk error |
push di |
; load first physical sector |
push bx si |
mov si, [first_byte] |
call load_phys_sector_for_lb_force |
jnc @f |
pop si bx |
.ret: |
pop di |
ret |
@@: |
add si, [first_byte] |
mov ecx, 1800h |
sub cx, si |
mov ebx, esi |
pop bx |
sub ebx, ecx |
jnc @f |
add cx, bx |
xor ebx, ebx |
@@: |
pop di |
sub [cur_limit], ecx |
rep movsb |
mov esi, ebx |
mov bx, di |
call normalize |
; load other physical sectors |
; read esi bytes from physical sector eax to buffer es:bx |
test esi, esi |
jz .ret |
push esi |
add esi, 0x7FF |
and si, not 0x7FF |
cmp esi, [cur_limit] |
jbe .okplace |
.noplace: |
sub esi, 800h |
.okplace: |
shr esi, 11 ; si = number of sectors |
mov cx, si |
jz @f |
call read_sectors |
@@: |
pop esi |
jc .ret |
movzx ecx, cx |
add eax, ecx |
shl ecx, 11 |
sub [cur_limit], ecx |
sub esi, ecx |
jc .big |
jz .nopost |
push bx es |
push ds |
pop es |
mov bx, 1000h |
mov cx, 1 |
call read_sectors |
pop es di |
jc .ret2 |
mov cx, si |
mov si, 1000h |
sub word [cur_limit], cx |
sbb word [cur_limit+2], 0 |
rep movsb |
mov bx, di |
call normalize |
.nopost: |
clc |
.ret2: |
pop di |
ret |
.big: |
mov ax, es |
sub ax, 80h |
mov es, ax |
add bx, 800h |
add bx, si |
call normalize |
sub [cur_limit], esi |
jmp .nopost |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only function 1 is defined for now |
dec ax |
jz callback_readfile |
dec ax |
jz callback_continueread |
stc ; unsupported function |
retf |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
clc ; function is supported |
retf |
callback_continueread: |
; function 2: continue to read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; si = limit in 4K blocks |
shl esi, 12 ; bp:si = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, [cur_chunk] |
call loadloop.loadnew |
clc ; function is supported |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kernel.mnt',0 |
aKernelNotFound db 'Fatal error: cannot load the kernel',0 |
align 2 |
cachelist: |
.head dw cachelist |
.tail dw cachelist |
free_cache_item dw 0 |
last_cache_item dw 0x8400 |
use_path_table db 0 |
bootdrive db ? |
align 2 |
lb_size dw ? ; Logical Block size in bytes |
dw 0 ; to allow access dword [lb_size] |
lb_per_sec dw ? ; Logical Blocks per physical sector |
dw 0 ; to allow access dword [lb_per_sec] |
free_ptr dw ? ; first free block in cache (cache block = sector = 0x800 bytes) |
size_rest dw ? ; free space in cache (in blocks) |
cache_size dw ? |
cache_start dw ? |
pathtable_size dw ? |
pathtable_start dw ? |
root_location dd ? |
cur_desc_end dw ? |
cur_nocache_len dd ? |
cur_limit dd ? |
cur_unit_limit dd ? |
overflow dw ? |
cur_chunk dw ? |
first_byte dw ? |
cur_start dd ? |
times 83FCh-$ db 0 |
db 43h |
; just to make file 2048 bytes long :) |
db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' |
dw 0xAA55 ; this is not required for CD, but to be consistent... |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
jmp far 0:real_start |
; special text |
org $+0x7C00 |
real_start: |
; initialize |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov es, ax |
cld |
sti |
mov [bootdrive], dl |
; check LBA support |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cl, 1 |
jz err_ |
; get file system information |
; scan for Primary Volume Descriptor |
db 66h |
push 10h-1 |
pop eax |
pvd_scan_loop: |
mov cx, 1 |
inc eax |
mov bx, 0x1000 |
call read_sectors |
jnc @f |
fatal_read_err: |
mov si, aReadError |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
@@: |
push ds |
pop es |
cmp word [bx+1], 'CD' |
jnz pvd_scan_loop |
cmp word [bx+3], '00' |
jnz pvd_scan_loop |
cmp byte [bx+5], '1' |
jnz pvd_scan_loop |
; we have found ISO9660 descriptor, look for type |
cmp byte [bx], 1 ; Primary Volume Descriptor? |
jz pvd_found |
cmp byte [bx], 0xFF ; Volume Descriptor Set Terminator? |
jnz pvd_scan_loop |
; Volume Descriptor Set Terminator reached, no PVD found - fatal error |
mov si, no_pvd |
jmp err_ |
pvd_found: |
add bx, 80h |
mov ax, [bx] |
mov [lb_size], ax |
; calculate number of logical blocks in one sector |
mov ax, 800h |
cwd |
div word [bx] |
mov [lb_per_sec], ax |
; get location of root directory |
mov di, root_location |
movzx eax, byte [bx+1Dh] |
add eax, [bx+1Eh] |
stosd |
; get memory size |
int 12h |
mov si, nomem_str |
cmp ax, 71000h / 400h |
jb err_ |
shr ax, 1 |
sub ax, 60000h / 800h |
mov [size_rest], ax |
mov [free_ptr], 60000h / 800h |
; load path table |
; if size > 62K => it's very strange, avoid using it |
; if size > (size of cache)/2 => avoid using it too |
mov ecx, [bx+4] |
cmp ecx, 0x10000 - 0x800 |
ja nopathtable |
shr ax, 1 |
cmp ax, 0x20 |
jae @f |
shl ax, 11 |
cmp cx, ax |
ja nopathtable |
@@: |
; size is ok, try to load it |
mov [pathtable_size], cx |
mov eax, [bx+12] |
xor edx, edx |
div dword [lb_per_sec] |
imul dx, [bx] |
mov [pathtable_start], dx |
add cx, dx |
call cx_to_sectors |
xor bx, bx |
push 6000h |
pop es |
call read_sectors |
jc nopathtable |
; path table has been loaded |
inc [use_path_table] |
sub [size_rest], cx |
add [free_ptr], cx |
nopathtable: |
; init cache |
mov ax, [size_rest] |
mov [cache_size], ax |
mov ax, [free_ptr] |
mov [cache_start], ax |
; load secondary loader |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
jnz noloader |
; set registers for secondary loader |
mov ah, [bootdrive] |
mov al, 'c' |
mov bx, 'is' |
mov si, callback |
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 |
noloader: |
mov si, aKernelNotFound |
jmp err_ |
read_sectors: |
; es:bx = pointer to data |
; eax = first sector |
; cx = number of sectors |
pushad |
push ds |
do_read_sectors: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
db 66h |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [cs:bootdrive] |
mov ah, 42h |
int 13h |
jc diskreaderr |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 7 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz do_read_sectors |
pop ds |
popad |
ret |
diskreaderr: |
add sp, 10h + 2*2 |
pop ds |
popad |
stc |
out_string.ret: |
ret |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz .ret |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aNoLBA db 'The drive does not support LBA!',0 |
aReadError db 'Read error',0 |
no_pvd db 'Primary Volume Descriptor not found!',0 |
nomem_str db 'No memory',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
load_file: |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
; parse path to the file |
lea si, [di+6] |
mov eax, [cs:root_location] |
cmp [cs:use_path_table], 0 |
jz parse_dir |
; scan for path in path table |
push di |
push 6000h |
pop es |
mov di, [cs:pathtable_start] ; es:di = pointer to current entry in path table |
mov dx, 1 ; dx = number of current entry in path table, start from 1 |
mov cx, [cs:pathtable_size] |
pathtable_newparent: |
mov bx, dx ; bx = number of current parent in path table: root = 1 |
scan_path_table_e: |
call is_last_component |
jnc path_table_scanned |
scan_path_table_i: |
cmp word [es:di+6], bx |
jb .next |
ja path_table_notfound |
call test_filename1 |
jc .next |
@@: |
lodsb |
cmp al, '/' |
jnz @b |
jmp pathtable_newparent |
.next: |
; go to next entry |
inc dx |
movzx ax, byte [es:di] |
add ax, 8+1 |
and al, not 1 |
add di, ax |
sub cx, ax |
ja scan_path_table_i |
path_table_notfound: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 2 ; file not found |
ret |
path_table_scanned: |
movzx eax, byte [es:di+1] |
add eax, [es:di+2] |
pop di |
parse_dir: |
; eax = logical block, ds:di -> information structure, ds:si -> file name |
; was the folder already read? |
push di ds |
push cs |
pop ds |
mov [cur_desc_end], 2000h |
mov bx, cachelist |
.scan1: |
mov bx, [bx+2] |
cmp bx, cachelist |
jz .notfound |
cmp [bx+4], eax |
jnz .scan1 |
.found: |
; yes; delete this item from the list (the following code will append this item to the tail) |
mov di, [bx] |
push word [bx+2] |
pop word [di+2] |
mov di, [bx+2] |
push word [bx] |
pop word [di] |
mov di, bx |
jmp .scan |
.notfound: |
; no; load first sector of the folder to get its size |
push eax |
push si |
mov si, 1 |
call load_phys_sector_for_lb_force |
mov bx, si |
pop si |
pop eax |
jnc @f |
; read error - return |
.readerr: |
pop ds |
.readerr2: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 3 |
ret |
@@: |
; first item of the folder describes the folder itself |
; do not cache too big folders: size < 64K and size <= (total cache size)/2 |
cmp word [bx+12], 0 |
jnz .nocache |
mov cx, [cache_size] ; cx = cache size in sectors |
shr cx, 1 ; cx = (cache size)/2 |
cmp cx, 0x20 |
jae @f |
shl cx, 11 |
cmp [bx+10], cx |
ja .nocache |
@@: |
; we want to cache this folder; get space for it |
mov cx, [bx+10] |
call cx_to_sectors |
jnz .yescache |
.nocache: |
push dword [bx+10] |
pop dword [cur_nocache_len] |
call lb_to_sector |
push ds |
pop es |
pop ds |
.nocache_loop: |
push eax |
mov dx, 1800h |
call scan_for_filename_in_sector |
mov cx, dx |
pop eax |
jnc .j_scandone |
sub cx, bx |
sub word [es:cur_nocache_len], cx |
sbb word [es:cur_nocache_len+2], 0 |
jb .j_scandone |
ja @f |
cmp word [es:cur_nocache_len], 0 |
jz .j_scandone |
@@: |
mov cx, 1 |
inc eax |
push es |
mov bx, 1000h |
call read_sectors |
pop es |
jc .readerr2 |
jmp .nocache_loop |
.j_scandone: |
jmp .scandone |
.yescache: |
push bx |
mov bx, [cachelist.head] |
.freeloop: |
cmp cx, [size_rest] |
jbe .sizeok |
@@: |
; if we are here: there is not enough free space, so we must delete old folders' data |
; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2). |
; one loop iteration: delete data of one folder |
pusha |
mov dx, [bx+10] |
mov es, dx ; es = segment of folder data to be deleted |
xor di, di |
mov ax, [bx+8] |
add ax, 0x7FF |
rcr ax, 1 |
shr ax, 10 |
push ax |
shl ax, 11-4 ; get number of paragraphs in folder data to be deleted |
mov cx, [cache_size] |
add cx, [cache_start] |
push ds |
push ax |
add ax, dx |
mov ds, ax |
pop ax |
shl cx, 11-4 |
sub cx, dx ; cx = number of paragraphs to be moved |
push si |
xor si, si |
; move cx paragraphs from ds:si to es:di to get free space in the end of cache |
@@: |
sub cx, 1000h |
jbe @f |
push cx |
mov cx, 8000h |
rep movsw |
mov cx, ds |
add cx, 1000h |
mov ds, cx |
mov cx, es |
add cx, 1000h |
mov es, cx |
pop cx |
jmp @b |
@@: |
add cx, 1000h |
shl cx, 3 |
rep movsw |
pop si |
pop ds |
; correct positions in cache for existing items |
mov cx, 80h |
mov di, 8400h |
.correct: |
cmp [di+10], dx |
jbe @f |
sub [di+10], ax |
@@: |
add di, 12 |
loop .correct |
; some additional space is free now |
pop ax |
add [size_rest], ax |
sub [free_ptr], ax |
; add cache item to the list of free items |
mov dx, [bx] |
mov ax, [free_cache_item] |
mov [bx], ax |
mov [free_cache_item], bx |
mov bx, dx |
; current iteration done |
popa |
jmp .freeloop |
.sizeok: |
mov [cachelist.head], bx |
mov word [bx+2], cachelist |
; allocate new item in cache |
mov di, [free_cache_item] |
test di, di |
jz .nofree |
push word [di] |
pop [free_cache_item] |
jmp @f |
.nofree: |
mov di, [last_cache_item] |
add [last_cache_item], 12 |
@@: |
pop bx |
push si di |
; mov [di+4], eax ; start of folder |
scasd |
stosd |
push ax |
mov ax, [free_ptr] |
shl ax, 11-4 |
mov [di+10-8], ax |
mov es, ax |
pop ax |
add [free_ptr], cx |
sub [size_rest], cx |
; read folder data |
; first sector is already in memory, 0000:bx |
pusha |
mov cx, [bx+10] |
mov [di+8-8], cx ; folder size in bytes |
mov si, bx |
xor di, di |
mov cx, 0x1800 |
sub cx, si |
rep movsb |
pop ax |
push di |
popa |
; read rest of folder |
mov esi, dword [lb_per_sec] |
add eax, esi |
dec si |
not si |
and ax, si |
mov si, word [bx+10] |
mov bx, di |
pop di |
sub si, bx |
jbe @f |
mov [cur_limit], esi |
call read_many_bytes |
pop si |
jnc .scan |
jmp .readerr |
@@: |
pop si |
.scan: |
; now we have required cache item; append it to the end of list |
mov bx, [cachelist.tail] |
mov [cachelist.tail], di |
mov [di+2], bx |
mov word [di], cachelist |
mov [bx], di |
; scan for given filename |
mov es, [di+10] |
mov dx, [di+8] |
pop ds |
xor bx, bx |
call scan_for_filename_in_sector |
.scandone: |
push cs |
pop es |
mov bx, 2000h |
cmp bx, [es:cur_desc_end] |
jnz filefound |
j_notfound: |
jmp path_table_notfound |
filefound: |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
@@: |
mov cl, [es:bx+8] |
test al, al |
jz @f |
; parse next component of file name |
test cl, 2 ; directory? |
jz j_notfound |
mov eax, [es:bx] |
pop di |
jmp parse_dir |
@@: |
test cl, 2 ; directory? |
jnz j_notfound ; do not allow read directories as regular files |
; ok, now load the file |
pop di |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; esi = limit in 4K blocks |
shl esi, 12 ; esi = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, 2000h |
loadloop: |
and [cur_start], 0 |
.loadnew: |
mov esi, [cur_limit] |
mov eax, [cur_start] |
add esi, eax |
mov [overflow], 1 |
sub esi, [di+4] |
jb @f |
xor esi, esi |
dec [overflow] |
@@: |
add esi, [di+4] ; esi = number of bytes to read |
mov [cur_start], esi |
sub esi, eax |
jz .loadcontinue |
xor edx, edx |
div dword [lb_size] ; eax = number of logical blocks to skip, |
mov [first_byte], dx; [first_byte] = number of bytes to skip in 1st block |
cmp byte [di+10], 0 |
jnz .interleaved |
add eax, [di] |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
jc .readerr3 |
.loadcontinue: |
mov [cur_chunk], di |
add di, 11 |
cmp di, [cur_desc_end] |
jae @f |
cmp [cur_limit], 0 |
jnz loadloop |
@@: |
mov bx, [overflow] |
.calclen: |
; calculate length of file |
xor ax, ax |
xor dx, dx |
mov di, 2000h |
@@: |
add ax, [di+4] |
adc dx, [di+6] |
add di, 11 |
cmp di, [cur_desc_end] |
jb @b |
ret |
.interleaved: |
mov [cur_unit_limit], esi |
push esi |
; skip first blocks |
movzx ecx, byte [di+9] ; Unit Size |
movzx esi, byte [di+10] ; Interleave Gap |
add si, cx |
mov edx, [di] |
@@: |
sub eax, ecx |
jb @f |
add edx, esi |
jmp @b |
@@: |
add ecx, eax ; ecx = number of logical blocks to skip |
lea eax, [ecx+edx] ; eax = first logical block |
pop esi |
.interleaved_loop: |
; get number of bytes in current file unit |
push eax |
movzx eax, byte [di+9] |
sub ax, cx |
imul eax, dword [lb_size] |
cmp eax, esi |
ja .i2 |
.i1: |
xchg esi, eax |
.i2: |
pop eax |
sub [cur_unit_limit], esi |
push eax |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
pop eax |
jnc @f |
.readerr3: |
mov bx, 3 |
jmp .calclen |
@@: |
mov esi, [cur_unit_limit] |
test esi, esi |
jz .loadcontinue |
movzx ecx, byte [di+9] ; add Unit Size |
add cl, byte [di+10] ; add Interleave Gap |
adc ch, 0 |
add eax, ecx |
xor cx, cx |
mov [first_byte], cx |
jmp .interleaved_loop |
cx_to_sectors: |
add cx, 7FFh |
rcr cx, 1 |
shr cx, 10 |
ret |
is_last_component: |
; in: ds:si -> name |
; out: CF set <=> current component is not last (=> folder) |
push si |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
stc |
@@: |
pop si |
ret |
test_filename1: |
; in: ds:si -> filename, es:di -> path table item |
; out: CF set <=> no match |
pusha |
mov cl, [es:di] |
add di, 8 |
jmp test_filename2.start |
test_filename2: |
; in: ds:si -> filename, es:bx -> directory item |
; out: CF set <=> no match |
pusha |
mov cl, [es:bx+32] |
lea di, [bx+33] |
.start: |
mov ch, 0 |
@@: |
lodsb |
test al, al |
jz .test1 |
cmp al, '/' |
jz .test1 |
call toupper |
mov ah, al |
mov al, [es:di] |
call toupper |
inc di |
cmp al, ah |
loopz @b |
jnz .next1 |
; if we have reached this point: current name is done |
lodsb |
test al, al |
jz .ret |
cmp al, '/' |
jz .ret |
; if we have reached this point: current name is done, but input name continues |
; so they do not match |
jmp .next1 |
.test1: |
; if we have reached this point: input name is done, but current name continues |
; "filename.ext;version" in ISO-9660 represents file "filename.ext" |
; "filename." and "filename.;version" are also possible for "filename" |
cmp byte [es:di], '.' |
jnz @f |
inc di |
dec cx |
jz .ret |
@@: |
cmp byte [es:di], ';' |
jnz .next1 |
jmp .ret |
.next1: |
stc |
.ret: |
popa |
ret |
toupper: |
; in: al=symbol |
; out: al=symbol in uppercase |
cmp al, 'a' |
jb .ret |
cmp al, 'z' |
ja .ret |
sub al, 'a'-'A' |
.ret: |
ret |
scan_for_filename_in_sector: |
; in: ds:si->filename, es:bx->folder data, dx=limit |
; out: CF=0 if found |
push bx |
.loope: |
push bx |
.loop: |
cmp bx, dx |
jae .notfound |
cmp byte [es:bx], 0 |
jz .loopd |
test byte [es:bx+25], 4 ; ignore files with Associated bit |
jnz .next |
call test_filename2 |
jc .next |
push ds es di |
push es |
pop ds |
push cs |
pop es |
mov di, [es:cur_desc_end] |
movzx eax, byte [bx+1] |
add eax, [bx+2] |
stosd ; first logical block |
mov eax, [bx+10] |
stosd ; length |
mov al, [bx+25] |
stosb ; flags |
mov ax, [bx+26] |
stosw ; File Unit size, Interleave Gap size |
mov [es:cur_desc_end], di |
cmp di, 3000h |
pop di es ds |
jae .done |
test byte [es:bx+25], 80h |
jz .done |
.next: |
add bl, [es:bx] |
adc bh, 0 |
jmp .loop |
.loopd: |
mov ax, bx |
pop bx |
@@: |
add bx, [cs:lb_size] |
jz .done2 |
cmp bx, ax |
jb @b |
jmp .loope |
.notfound: |
stc |
.done: |
pop bx |
.done2: |
pop bx |
ret |
lb_to_sector: |
xor edx, edx |
div dword [lb_per_sec] |
ret |
load_phys_sector_for_lb_force: |
; in: eax = logical block, ds=0 |
; in: si=0 - accept 0 logical blocks, otherwise force read at least 1 |
; out: 0000:1000 = physical sector data; si -> logical block |
; out: eax = next physical sector |
; out: CF=1 if read error |
; destroys cx |
; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector |
call lb_to_sector |
or si, dx |
jnz @f |
mov si, 1800h |
jmp .done |
@@: |
mov si, 1000h |
imul dx, [lb_size] |
add si, dx |
mov cx, 1 |
push es bx |
push ds |
pop es |
mov bx, 1000h |
call read_sectors |
pop bx es |
inc eax |
.done: |
ret |
normalize: |
; in: es:bx = far pointer |
; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10) |
push ax bx |
mov ax, es |
shr bx, 4 |
add ax, bx |
mov es, ax |
pop bx ax |
and bx, 0x0F |
ret |
read_many_bytes: |
and [first_byte], 0 |
read_many_bytes.with_first: |
; read esi bytes from logical block dx:ax to buffer es:bx |
; out: CF=1 <=> disk error |
push di |
; load first physical sector |
push bx si |
mov si, [first_byte] |
call load_phys_sector_for_lb_force |
jnc @f |
pop si bx |
.ret: |
pop di |
ret |
@@: |
add si, [first_byte] |
mov ecx, 1800h |
sub cx, si |
mov ebx, esi |
pop bx |
sub ebx, ecx |
jnc @f |
add cx, bx |
xor ebx, ebx |
@@: |
pop di |
sub [cur_limit], ecx |
rep movsb |
mov esi, ebx |
mov bx, di |
call normalize |
; load other physical sectors |
; read esi bytes from physical sector eax to buffer es:bx |
test esi, esi |
jz .ret |
push esi |
add esi, 0x7FF |
and si, not 0x7FF |
cmp esi, [cur_limit] |
jbe .okplace |
.noplace: |
sub esi, 800h |
.okplace: |
shr esi, 11 ; si = number of sectors |
mov cx, si |
jz @f |
call read_sectors |
@@: |
pop esi |
jc .ret |
movzx ecx, cx |
add eax, ecx |
shl ecx, 11 |
sub [cur_limit], ecx |
sub esi, ecx |
jc .big |
jz .nopost |
push bx es |
push ds |
pop es |
mov bx, 1000h |
mov cx, 1 |
call read_sectors |
pop es di |
jc .ret2 |
mov cx, si |
mov si, 1000h |
sub word [cur_limit], cx |
sbb word [cur_limit+2], 0 |
rep movsb |
mov bx, di |
call normalize |
.nopost: |
clc |
.ret2: |
pop di |
ret |
.big: |
mov ax, es |
sub ax, 80h |
mov es, ax |
add bx, 800h |
add bx, si |
call normalize |
sub [cur_limit], esi |
jmp .nopost |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only function 1 is defined for now |
dec ax |
jz callback_readfile |
dec ax |
jz callback_continueread |
stc ; unsupported function |
retf |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
clc ; function is supported |
retf |
callback_continueread: |
; function 2: continue to read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; si = limit in 4K blocks |
shl esi, 12 ; bp:si = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, [cur_chunk] |
call loadloop.loadnew |
clc ; function is supported |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kernel.mnt',0 |
aKernelNotFound db 'Fatal error: cannot load the kernel',0 |
align 2 |
cachelist: |
.head dw cachelist |
.tail dw cachelist |
free_cache_item dw 0 |
last_cache_item dw 0x8400 |
use_path_table db 0 |
bootdrive db ? |
align 2 |
lb_size dw ? ; Logical Block size in bytes |
dw 0 ; to allow access dword [lb_size] |
lb_per_sec dw ? ; Logical Blocks per physical sector |
dw 0 ; to allow access dword [lb_per_sec] |
free_ptr dw ? ; first free block in cache (cache block = sector = 0x800 bytes) |
size_rest dw ? ; free space in cache (in blocks) |
cache_size dw ? |
cache_start dw ? |
pathtable_size dw ? |
pathtable_start dw ? |
root_location dd ? |
cur_desc_end dw ? |
cur_nocache_len dd ? |
cur_limit dd ? |
cur_unit_limit dd ? |
overflow dw ? |
cur_chunk dw ? |
first_byte dw ? |
cur_start dd ? |
times 83FCh-$ db 0 |
db 43h |
; just to make file 2048 bytes long :) |
db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' |
dw 0xAA55 ; this is not required for CD, but to be consistent... |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/fat1x/bootsect.asm |
---|
1,392 → 1,392 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
use_lba = 0 |
org 0x7C00 |
jmp start |
nop |
; FAT parameters, BPB |
; note: they can be changed at install, replaced with real values |
; these settings are for most typical 1.44M floppies |
db 'KOLIBRI ' ; BS_OEMName, ignored |
dw 200h ; BPB_BytsPerSec |
BPB_SecsPerClus db 1 |
BPB_RsvdSecCnt dw 1 |
BPB_NumFATs db 2 |
BPB_RootEntCnt dw 0xE0 |
dw 2880 ; BPB_TotSec16 |
db 0xF0 ; BPB_Media |
BPB_FATSz16 dw 9 |
BPB_SecPerTrk dw 18 |
BPB_NumHeads dw 2 |
BPB_HiddSec dd 0 |
dd 0 ; BPB_TotSec32 |
BS_DrvNum db 0 |
db 0 ; BS_Reserved1 |
db ')' ; BS_BootSig |
dd 12344321h ; BS_VolID |
filename: |
db 'KORD.OS ' ; BS_VolLab |
db 'FAT12 ' ; BS_FilSysType |
; Used memory map: |
; 8000:0000 - current directory |
; 9000:0000 - root directory data [cached] |
start: |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov bp, sp |
cld |
sti |
mov [bp+BS_DrvNum-0x7C00], dl |
if use_lba |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cx, 1 |
jz err_ |
else |
mov ah, 8 |
int 13h |
jc @f ; on error, assume that BPB geometry is valid |
mov al, dh |
mov ah, 0 |
inc ax |
mov [bp+BPB_NumHeads-0x7C00], ax |
and cx, 3Fh |
mov [bp+BPB_SecPerTrk-0x7C00], cx |
@@: |
end if |
; get FAT parameters |
xor bx, bx |
mov al, [bp+BPB_NumFATs-0x7C00] |
mov ah, 0 |
mul [bp+BPB_FATSz16-0x7C00] |
add ax, [bp+BPB_RsvdSecCnt-0x7C00] |
adc dx, bx |
push dx |
push ax ; root directory start = dword [bp-4] |
mov cx, [bp+BPB_RootEntCnt-0x7C00] |
add cx, 0xF |
rcr cx, 1 |
shr cx, 3 ; cx = size of root directory in sectors |
add ax, cx |
adc dx, bx |
push dx |
push ax ; data start = dword [bp-8] |
; load start of root directory (no more than 0x2000 bytes = 0x10 sectors) |
cmp cx, 0x10 |
jb @f |
mov cx, 0x10 |
@@: |
mov ax, [bp-4] |
mov dx, [bp-2] |
push 0x9000 |
pop es |
call read_sectors |
add word [bp-4], cx ; dword [bp-4] = start of non-cached root data |
adc word [bp-2], bx |
; load kordldr.f12 |
mov si, main_loader |
call lookup_in_root_dir |
jc noloader |
test byte [es:di+11], 10h ; directory? |
jz kordldr_ok |
noloader: |
mov si, aLoaderNotFound |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
kordldr_ok: |
mov ax, [es:di+26] ; get file cluster |
mov bx, 0x7E00 |
xor cx, cx |
mov es, cx |
sub ax, 2 |
jc noloader |
push bx ; save return address: bx = 7E00 |
mov cl, [bp+BPB_SecsPerClus-0x7C00] |
mul cx |
; fall through - 'ret' in read_sectors will return to 7E00 |
read_sectors2: |
; same as read_sectors, but dx:ax is relative to start of data |
add ax, [bp-8] |
adc dx, [bp-6] |
read_sectors: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; dx:ax = first sector |
; cx = number of sectors |
pusha |
add ax, word [bp+BPB_HiddSec-0x7C00] |
adc dx, word [bp+BPB_HiddSec+2-0x7C00] |
if use_lba |
push ds |
do_read_sectors: |
push ax |
push cx |
push dx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push dx |
push ax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp+BS_DrvNum-0x7C00] |
mov ah, 42h |
int 13h |
mov si, aReadError |
jc err_ |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
mov si, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop dx |
pop cx |
pop ax |
add ax, si |
adc dx, 0 |
sub cx, si |
jnz do_read_sectors |
pop ds |
popa |
ret |
else |
do_read_sectors: |
pusha |
pop di |
push bx |
; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx |
mov si, ax |
xchg ax, dx |
xor dx, dx |
div [bp+BPB_SecPerTrk-0x7C00] |
push ax |
mov ax, si |
div [bp+BPB_SecPerTrk-0x7C00] |
mov bx, dx ; bx=sector-1 |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp+BPB_NumHeads-0x7C00] |
; number of sectors: read no more than to end of track |
push bx |
sub bx, [bp+BPB_SecPerTrk-0x7C00] |
neg bx |
cmp cx, bx |
jbe @f |
mov cx, bx |
@@: |
pop bx |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format |
mov di, cx |
mov dh, dl |
mov dl, [bp+BS_DrvNum-0x7C00] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
mov si, aReadError |
jmp err_ |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push di |
popa |
add ax, di |
adc dx, 0 |
sub cx, di |
jnz do_read_sectors |
popa |
ret |
end if |
scan_for_filename: |
; in: ds:si -> 11-bytes FAT name |
; in: es:0 -> part of directory data |
; in: cx = number of entries |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
xor di, di |
push cx |
sloop: |
cmp byte [es:di], 0 |
jz snotfound |
test byte [es:di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmpsb |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
inc cx ; clear ZF flag |
snotfound: |
stc |
sdone: |
pop cx |
lrdret: |
ret |
lookup_in_root_dir: |
; ss:bp = 0:7C00 |
; in: ds:si -> 11-bytes FAT name |
; out: if found: CF=0, es:di -> directory entry |
; out: if not found: CF=1 |
mov cx, [bp+BPB_RootEntCnt-0x7C00] |
push cx |
; first, look in root directory cache |
push 0x9000 |
pop es |
test ch, ch |
jz @f |
mov cx, 0x100 |
@@: |
mov ax, [bp-4] |
mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory |
lrdloop: |
call scan_for_filename |
pop bx |
jz lrdret |
sub bx, cx |
mov cx, bx |
stc |
jz lrdret |
; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries |
push cx |
cmp ch, 0x8 |
jb @f |
mov cx, 0x800 |
@@: |
push 0x8000 |
pop es |
push cx |
push es |
xor bx, bx |
add cx, 0xF |
shr cx, 4 |
call read_sectors |
pop es |
add ax, cx |
adc dx, bx |
pop cx |
jmp lrdloop |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz lrdret |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aReadError db 'Read error',0 |
if use_lba |
aNoLBA db 'The drive does not support LBA!',0 |
end if |
aLoaderNotFound db 'Loader not found',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
main_loader db 'KORDLDR F1X' |
if use_lba |
db 0 ; make bootsector 512 bytes in length |
end if |
; bootsector signature |
dw 0xAA55 |
; display offsets of all procedures used by kordldr.f12.asm |
macro show [procedure] |
{ |
bits = 16 |
display `procedure,' = ' |
repeat bits/4 |
d = '0' + procedure shr (bits - %*4) and 0Fh |
if d > '9' |
d = d + 'A'-'9'-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
use_lba = 0 |
org 0x7C00 |
jmp start |
nop |
; FAT parameters, BPB |
; note: they can be changed at install, replaced with real values |
; these settings are for most typical 1.44M floppies |
db 'KOLIBRI ' ; BS_OEMName, ignored |
dw 200h ; BPB_BytsPerSec |
BPB_SecsPerClus db 1 |
BPB_RsvdSecCnt dw 1 |
BPB_NumFATs db 2 |
BPB_RootEntCnt dw 0xE0 |
dw 2880 ; BPB_TotSec16 |
db 0xF0 ; BPB_Media |
BPB_FATSz16 dw 9 |
BPB_SecPerTrk dw 18 |
BPB_NumHeads dw 2 |
BPB_HiddSec dd 0 |
dd 0 ; BPB_TotSec32 |
BS_DrvNum db 0 |
db 0 ; BS_Reserved1 |
db ')' ; BS_BootSig |
dd 12344321h ; BS_VolID |
filename: |
db 'KORD.OS ' ; BS_VolLab |
db 'FAT12 ' ; BS_FilSysType |
; Used memory map: |
; 8000:0000 - current directory |
; 9000:0000 - root directory data [cached] |
start: |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov bp, sp |
cld |
sti |
mov [bp+BS_DrvNum-0x7C00], dl |
if use_lba |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cx, 1 |
jz err_ |
else |
mov ah, 8 |
int 13h |
jc @f ; on error, assume that BPB geometry is valid |
mov al, dh |
mov ah, 0 |
inc ax |
mov [bp+BPB_NumHeads-0x7C00], ax |
and cx, 3Fh |
mov [bp+BPB_SecPerTrk-0x7C00], cx |
@@: |
end if |
; get FAT parameters |
xor bx, bx |
mov al, [bp+BPB_NumFATs-0x7C00] |
mov ah, 0 |
mul [bp+BPB_FATSz16-0x7C00] |
add ax, [bp+BPB_RsvdSecCnt-0x7C00] |
adc dx, bx |
push dx |
push ax ; root directory start = dword [bp-4] |
mov cx, [bp+BPB_RootEntCnt-0x7C00] |
add cx, 0xF |
rcr cx, 1 |
shr cx, 3 ; cx = size of root directory in sectors |
add ax, cx |
adc dx, bx |
push dx |
push ax ; data start = dword [bp-8] |
; load start of root directory (no more than 0x2000 bytes = 0x10 sectors) |
cmp cx, 0x10 |
jb @f |
mov cx, 0x10 |
@@: |
mov ax, [bp-4] |
mov dx, [bp-2] |
push 0x9000 |
pop es |
call read_sectors |
add word [bp-4], cx ; dword [bp-4] = start of non-cached root data |
adc word [bp-2], bx |
; load kordldr.f12 |
mov si, main_loader |
call lookup_in_root_dir |
jc noloader |
test byte [es:di+11], 10h ; directory? |
jz kordldr_ok |
noloader: |
mov si, aLoaderNotFound |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
kordldr_ok: |
mov ax, [es:di+26] ; get file cluster |
mov bx, 0x7E00 |
xor cx, cx |
mov es, cx |
sub ax, 2 |
jc noloader |
push bx ; save return address: bx = 7E00 |
mov cl, [bp+BPB_SecsPerClus-0x7C00] |
mul cx |
; fall through - 'ret' in read_sectors will return to 7E00 |
read_sectors2: |
; same as read_sectors, but dx:ax is relative to start of data |
add ax, [bp-8] |
adc dx, [bp-6] |
read_sectors: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; dx:ax = first sector |
; cx = number of sectors |
pusha |
add ax, word [bp+BPB_HiddSec-0x7C00] |
adc dx, word [bp+BPB_HiddSec+2-0x7C00] |
if use_lba |
push ds |
do_read_sectors: |
push ax |
push cx |
push dx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push dx |
push ax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp+BS_DrvNum-0x7C00] |
mov ah, 42h |
int 13h |
mov si, aReadError |
jc err_ |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
mov si, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop dx |
pop cx |
pop ax |
add ax, si |
adc dx, 0 |
sub cx, si |
jnz do_read_sectors |
pop ds |
popa |
ret |
else |
do_read_sectors: |
pusha |
pop di |
push bx |
; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx |
mov si, ax |
xchg ax, dx |
xor dx, dx |
div [bp+BPB_SecPerTrk-0x7C00] |
push ax |
mov ax, si |
div [bp+BPB_SecPerTrk-0x7C00] |
mov bx, dx ; bx=sector-1 |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp+BPB_NumHeads-0x7C00] |
; number of sectors: read no more than to end of track |
push bx |
sub bx, [bp+BPB_SecPerTrk-0x7C00] |
neg bx |
cmp cx, bx |
jbe @f |
mov cx, bx |
@@: |
pop bx |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format |
mov di, cx |
mov dh, dl |
mov dl, [bp+BS_DrvNum-0x7C00] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
mov si, aReadError |
jmp err_ |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push di |
popa |
add ax, di |
adc dx, 0 |
sub cx, di |
jnz do_read_sectors |
popa |
ret |
end if |
scan_for_filename: |
; in: ds:si -> 11-bytes FAT name |
; in: es:0 -> part of directory data |
; in: cx = number of entries |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
xor di, di |
push cx |
sloop: |
cmp byte [es:di], 0 |
jz snotfound |
test byte [es:di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmpsb |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
inc cx ; clear ZF flag |
snotfound: |
stc |
sdone: |
pop cx |
lrdret: |
ret |
lookup_in_root_dir: |
; ss:bp = 0:7C00 |
; in: ds:si -> 11-bytes FAT name |
; out: if found: CF=0, es:di -> directory entry |
; out: if not found: CF=1 |
mov cx, [bp+BPB_RootEntCnt-0x7C00] |
push cx |
; first, look in root directory cache |
push 0x9000 |
pop es |
test ch, ch |
jz @f |
mov cx, 0x100 |
@@: |
mov ax, [bp-4] |
mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory |
lrdloop: |
call scan_for_filename |
pop bx |
jz lrdret |
sub bx, cx |
mov cx, bx |
stc |
jz lrdret |
; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries |
push cx |
cmp ch, 0x8 |
jb @f |
mov cx, 0x800 |
@@: |
push 0x8000 |
pop es |
push cx |
push es |
xor bx, bx |
add cx, 0xF |
shr cx, 4 |
call read_sectors |
pop es |
add ax, cx |
adc dx, bx |
pop cx |
jmp lrdloop |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz lrdret |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aReadError db 'Read error',0 |
if use_lba |
aNoLBA db 'The drive does not support LBA!',0 |
end if |
aLoaderNotFound db 'Loader not found',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
main_loader db 'KORDLDR F1X' |
if use_lba |
db 0 ; make bootsector 512 bytes in length |
end if |
; bootsector signature |
dw 0xAA55 |
; display offsets of all procedures used by kordldr.f12.asm |
macro show [procedure] |
{ |
bits = 16 |
display `procedure,' = ' |
repeat bits/4 |
d = '0' + procedure shr (bits - %*4) and 0Fh |
if d > '9' |
d = d + 'A'-'9'-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/fat1x/kordldr.f1x.asm |
---|
1,688 → 1,689 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
org 0x7E00 |
; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here |
; ss:bp = 0:7C00 |
virtual at bp |
rb 3 ; BS_jmpBoot |
rb 8 ; BS_OEMName, ignored |
dw ? ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
BPB_TotSec16 dw ? |
db ? ; BPB_Media |
BPB_FATSz16 dw ? |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
BPB_TotSec32 dd ? |
BS_DrvNum db ? |
fat_type db ? ; this is BS_Reserved1, |
; we use it to save FS type: 0=FAT12, 1=FAT16 |
db ? ; BS_BootSig |
num_sectors dd ? ; BS_VolID |
; rb 11 ; BS_VolLab |
; rb 3 ; BS_FilSysType, first 3 bytes |
read_sectors dw ? |
read_sectors2 dw ? |
lookup_in_root_dir dw ? |
scan_for_filename dw ? |
err_ dw ? |
noloader dw ? |
cachelimit dw ? |
filesize: ; will be used to save file size |
rb 5 ; BS_FilSysType, last 5 bytes |
; following variables are located in the place of starting code; |
; starting code is no more used at this point |
sect_per_clus dw ? |
cur_cluster dw ? |
next_cluster dw ? |
flags dw ? |
cur_delta dd ? |
end virtual |
; procedures from boot sector |
; LBA version |
lba_read_sectors = 7CE2h |
lba_read_sectors2 = 7CDCh |
lba_lookup_in_root_dir = 7D4Fh |
lba_scan_for_filename = 7D2Dh |
lba_err = 7CB5h |
lba_noloader = 7CB2h |
; CHS version |
chs_read_sectors = 7CDEh |
chs_read_sectors2 = 7CD8h |
chs_lookup_in_root_dir = 7D70h |
chs_scan_for_filename = 7D4Eh |
chs_err = 7CB1h |
chs_noloader = 7CAEh |
push ax cx ; save our position on disk |
push ss |
pop es |
; determine version of bootsector (LBA vs CHS) |
; mov [read_sectors], chs_read_sectors |
; mov [read_sectors2], chs_read_sectors2 |
; mov [lookup_in_root_dir], chs_lookup_in_root_dir |
; mov [scan_for_filename], chs_scan_for_filename |
; mov [err], chs_err |
; mov [noloader], chs_noloader |
lea di, [read_sectors] |
mov si, chs_proc_addresses |
mov cx, 6*2 |
cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di' |
jz @f |
add si, cx |
; mov [read_sectors], lba_read_sectors |
; mov [read_sectors2], lba_read_sectors2 |
; mov [lookup_in_root_dir], lba_lookup_in_root_dir |
; mov [scan_for_filename], lba_scan_for_filename |
; mov [err], lba_err |
; mov [noloader], lba_noloader |
@@: |
rep movsb |
mov cl, [BPB_SecsPerClus] |
mov [sect_per_clus], cx |
xor bx, bx |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 94000h / 1024 |
jae @f |
nomem: |
mov si, nomem_str |
jmp [err_] |
@@: |
shr ax, 3 |
mov [cachelimit], ax ; size of cache - 1 |
; get type of file system - FAT12 or FAT16? |
; calculate number of clusters |
mov ax, [BPB_TotSec16] |
xor dx, dx |
test ax, ax |
jnz @f |
mov ax, word [BPB_TotSec32] |
mov dx, word [BPB_TotSec32+2] |
@@: |
sub ax, [bp-8] ; dword [bp-8] = first data sector |
sbb dx, [bp-6] |
jb j_noloader |
div [sect_per_clus] |
; ax = number of clusters |
; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes |
mov [fat_type], ch |
cmp ax, 0xFF5 |
jb init_fat12 |
inc [fat_type] |
init_fat16: |
; no sectors loaded |
mov di, 0x8200 |
xor ax, ax |
mov cx, 0x100/2 |
rep stosw |
jmp init_fat_done |
init_fat12: |
; read FAT |
push 0x6000 |
pop es |
mov ax, [BPB_RsvdSecCnt] |
mov cx, [BPB_FATSz16] |
cmp cx, 12 |
jb @f |
mov cx, 12 |
@@: |
xor dx, dx |
call [read_sectors] |
init_fat_done: |
; if cluster = sector, we need to read second part of our file |
; (bootsector loads only first cluster of kordldr.f1x) |
pop cx ax ; restore our position on disk |
cmp cx, 1 |
ja kordldr_full |
sub ax, [bp-8] |
inc ax |
inc ax ; ax = first cluster of kordldr.f12 |
call get_next_cluster |
jc @f |
j_noloader: |
jmp [noloader] |
@@: |
dec ax |
dec ax |
push 0x800 |
pop es |
call [read_sectors2] |
kordldr_full: |
; ...continue loading... |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
mov bx, [err_] |
jz @f |
mov si, aKernelNotFound |
jmp bx |
@@: |
; for subsequent calls to callback function, hook error handler |
; mov byte [bx], 0xE9 ; 'jmp' opcode |
; mov ax, hooked_err - 3 |
; sub ax, bx |
; mov word [bx+1], ax |
; push hooked_err / ret |
mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8) |
mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8) |
; set registers for secondary loader |
mov ah, [BS_DrvNum] |
mov al, 'f' |
test ah, ah |
jns @f |
sub ah, 80h |
mov al, 'h' |
@@: |
mov bx, '12' |
cmp [fat_type], 0 |
jz @f |
mov bh, '6' |
@@: |
mov si, callback ; ds:si = far pointer to callback procedure |
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 |
nomem_str db 'No memory',0 |
chs_proc_addresses: |
dw chs_read_sectors |
dw chs_read_sectors2 |
dw chs_lookup_in_root_dir |
dw chs_scan_for_filename |
dw chs_err |
dw chs_noloader |
lba_proc_addresses: |
dw lba_read_sectors |
dw lba_read_sectors2 |
dw lba_lookup_in_root_dir |
dw lba_scan_for_filename |
dw lba_err |
dw lba_noloader |
get_next_cluster: |
; in: ax = cluster |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
push si |
cmp [fat_type], 0 |
jnz gnc16 |
; for FAT12 |
push ds |
push 0x6000 |
pop ds |
mov si, ax |
shr si, 1 |
add si, ax |
test al, 1 |
lodsw |
jz @f |
shr ax, 4 |
@@: |
and ax, 0xFFF |
cmp ax, 0xFF7 |
pop ds si |
ret |
; for FAT16 |
gnc16: |
; each sector contains 200h bytes = 100h FAT entries |
; so ah = # of sector, al = offset in sector |
mov si, ax |
mov ah, 0 |
shr si, 8 |
; calculate segment for this sector of FAT table |
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) |
; segment = 6000 + 20*si, offset = 0 |
push es |
push si |
shl si, 5 |
add si, 0x6000 |
mov es, si |
pop si |
cmp byte [ss:0x8200+si], ah ; sector already loaded? |
jnz @f |
; load corresponding sector |
pusha |
push es |
xor bx, bx |
mov ax, [BPB_RsvdSecCnt] |
xor dx, dx |
add ax, si |
adc dx, bx |
mov cx, 1 ; read 1 sector |
call [read_sectors] |
pop es |
popa |
@@: |
mov si, ax |
add si, si |
; mov ax, [es:si] |
lods word [es:si] |
pop es |
cmp ax, 0xFFF7 |
pop si |
ret |
if $ > 0x8000 |
error 'get_next_cluster must fit in first sector of kordldr.f1x!' |
end if |
load_file: |
; in: ss:bp = 0:7C00 |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
xor ax, ax ; start from root directory |
mov dx, -1 |
mov word [filesize], dx |
mov word [filesize+2], dx ; initialize file size with invalid value |
lea si, [di+6] |
parse_dir_loop: |
; convert name to FAT name |
push di |
push ax |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
mov di, filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
nameloop: |
lodsb |
test al, al |
jz namedone |
cmp al, '/' |
jz namedone |
cmp al, '.' |
jz namedot |
dec cx |
js badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp nameloop |
namedot: |
inc bx |
jp badname |
add di, cx |
mov cl, 3 |
jmp nameloop |
badname: ; do not make direct js/jp to notfound_pop: |
; this generates long forms of conditional jumps and results in longer code |
jmp notfound_pop |
namedone: |
; scan directory |
pop ax ; ax = cluster of directory or 0 for root |
push ds |
push si |
push es |
pop ds |
mov si, filename ; ds:si -> filename in FAT style |
test ax, ax |
jnz lookup_in_notroot_dir |
; for root directory, use the subroutine from bootsector |
call [lookup_in_root_dir] |
jmp lookup_done |
lookup_in_notroot_dir: |
; for other directories, read a folder sector-by-sector and scan |
; first, try to use the cache |
push ds |
push cs |
pop ds |
mov bx, [cachelimit] |
add bx, bx |
mov di, foldcache_mark |
@@: |
mov dx, [foldcache_clus+di-foldcache_mark+bx] |
cmp dx, ax |
jz cacheok |
test dx, dx |
jz cacheadd ; the cache has place for new entry |
dec bx |
dec bx |
jns @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov dx, [cachelimit] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
mov [foldcache_clus+di-foldcache_mark+bx], ax |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [cachelimit] |
add di, di |
cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
pop ds |
; mov dx, bx |
; shl dx, 8 ; dx = (position in cache)*0x2000/0x10 |
; add dx, 0x9200 |
lea dx, [bx+0x92] |
xchg dl, dh |
mov es, dx |
jcxz not_in_cache |
call [scan_for_filename] |
jz lookup_done |
not_in_cache: |
; cache miss, read folder data from disk |
mov bx, cx |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
folder_next_cluster: |
; internal loop: scan sectors in cluster |
mov cx, [sect_per_clus] |
push ax |
dec ax |
dec ax |
mul cx |
add ax, [bp-8] |
adc dx, [bp-6] ; dx:ax = absolute sector |
folder_next_sector: |
; skip first bx sectors |
dec bx |
jns folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
call [read_sectors] |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
push si di |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache |
pop di si |
@@: |
push es |
push 0x8000 |
pop es |
push cs |
pop ds |
mov cx, 0x10 |
call [scan_for_filename] |
pop es |
pop cx |
jz lookup_done_pop |
folder_skip_sector: |
inc ax |
jnz @f |
inc dx |
@@: |
loop folder_next_sector |
pop ax ; ax = current cluster |
call get_next_cluster |
jc folder_next_cluster |
stc |
push ax |
lookup_done_pop: |
pop ax |
lookup_done: |
pop si |
pop ds |
; CF=1 <=> failed |
jnc found |
notfound: |
pop di |
mov bx, 2 ; file not found |
mov ax, 0xFFFF |
mov dx, ax ; invalid file size |
ret |
notfound_pop: |
pop ax |
jmp notfound |
found: |
mov ax, [es:di+26] ; get cluster |
test byte [es:di+11], 10h ; directory? |
jz regular_file |
cmp byte [si-1], 0 |
jz notfound ; don't read directories as a regular files |
; ok, we have found a directory and the caller requested a file into it |
pop di |
jmp parse_dir_loop ; restart with new cluster in ax |
regular_file: |
cmp byte [si-1], 0 |
jnz notfound ; file does not contain another files |
; ok, we have found a regular file and the caller requested it |
; save file size |
mov dx, [es:di+28] |
mov [filesize], dx |
mov dx, [es:di+30] |
mov [filesize+2], dx |
pop di |
mov si, [di+4] |
shl si, 3 |
push si ; [ds:di+4] = limit in 4K blocks |
les bx, [di] ; es:bx -> buffer |
clusloop: |
; ax = first cluster, top of stack contains limit in sectors |
mov si, ax ; remember current cluster |
xor cx, cx ; cx will contain number of consecutive clusters |
mov word [cur_delta], cx |
mov word [cur_delta+2], cx |
mov di, ax |
clusfind: |
inc di |
inc cx |
call get_next_cluster |
jnc clusread |
cmp ax, di |
jz clusfind |
stc |
clusread: |
pop di ; limit in sectors |
push ax ; save next cluster |
pushf ; save flags |
; read cx clusters, starting from si |
; calculate number of sectors |
xchg ax, cx |
mul [sect_per_clus] |
; dx:ax = number of sectors; compare with limit |
mov word [num_sectors], ax |
mov word [num_sectors+2], dx |
jmp @f |
continue_load_file: |
les bx, [di] ; es:bx -> buffer |
mov di, [di+4] ; ds:di = limit in 4K blocks |
shl di, 3 ; now di = limit in sectors |
mov ax, word [num_sectors] |
mov dx, word [num_sectors+2] |
mov si, [cur_cluster] |
push [next_cluster] |
push [flags] |
or ax, dx |
jz nextclus |
@@: |
test dx, dx |
jnz clusdecrease |
push dx ; limit was not exceeded |
cmp ax, di |
jbe @f |
pop ax |
clusdecrease: |
push 1 ; limit was exceeded |
mov ax, di |
@@: |
sub di, ax ; calculate new limit |
sub word [num_sectors], ax |
sbb word [num_sectors+2], 0 |
readloop: |
push ax |
; buffer should not cross a 64K boundary |
push bx |
shr bx, 4 |
mov cx, es |
add bx, cx |
neg bx |
and bh, 0xF |
shr bx, 5 |
jnz @f |
mov bl, 0x80 |
@@: |
cmp ax, bx |
jbe @f |
xchg ax, bx |
@@: |
pop bx |
xchg ax, cx |
; calculate starting sector |
lea ax, [si-2] |
mul [sect_per_clus] |
add ax, word [cur_delta] |
adc dx, word [cur_delta+2] |
add word [cur_delta], cx |
adc word [cur_delta+2], 0 |
; read |
call [read_sectors2] |
pop ax |
sub ax, cx |
jnz readloop |
pop dx |
; next cluster? |
nextclus: |
popf |
pop ax |
mov [cur_cluster], si |
mov [next_cluster], ax |
pushf |
pop [flags] |
jnc @f ; no next cluster => return |
mov dl, 1 ; dh=0 in any case |
test di, di |
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded |
push di |
jmp clusloop ; all is ok, continue |
hooked_err: |
mov sp, 7C00h-12-2 ; restore stack |
mov dx, 3 ; return: read error |
@@: |
mov bx, dx |
mov ax, [filesize] |
mov dx, [filesize+2] |
ret |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 7C00h-8 |
mov bp, 7C00h |
push dx |
push cx |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
; function 2: continue loading file |
; can be called only after function 1 returned value bx=1 (only part of file was loaded) |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
callback_ret_succ: |
clc ; function is supported |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kernel.mnt',0 |
aKernelNotFound db 'Fatal error: cannot load the kernel',0 |
foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache |
foldcache_mark rw 7 |
foldcache_size rw 7 |
filename rb 11 |
if $ > 0x8200 |
error: table overwritten |
end if |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
org 0x7E00 |
; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here |
; ss:bp = 0:7C00 |
virtual at bp |
rb 3 ; BS_jmpBoot |
rb 8 ; BS_OEMName, ignored |
dw ? ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
BPB_TotSec16 dw ? |
db ? ; BPB_Media |
BPB_FATSz16 dw ? |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
BPB_TotSec32 dd ? |
BS_DrvNum db ? |
fat_type db ? ; this is BS_Reserved1, |
; we use it to save FS type: 0=FAT12, 1=FAT16 |
db ? ; BS_BootSig |
num_sectors dd ? ; BS_VolID |
; rb 11 ; BS_VolLab |
; rb 3 ; BS_FilSysType, first 3 bytes |
read_sectors dw ? |
read_sectors2 dw ? |
lookup_in_root_dir dw ? |
scan_for_filename dw ? |
err_ dw ? |
noloader dw ? |
cachelimit dw ? |
filesize: ; will be used to save file size |
rb 5 ; BS_FilSysType, last 5 bytes |
; following variables are located in the place of starting code; |
; starting code is no more used at this point |
sect_per_clus dw ? |
cur_cluster dw ? |
next_cluster dw ? |
flags dw ? |
cur_delta dd ? |
end virtual |
; procedures from boot sector |
; LBA version |
lba_read_sectors = 7CE2h |
lba_read_sectors2 = 7CDCh |
lba_lookup_in_root_dir = 7D4Fh |
lba_scan_for_filename = 7D2Dh |
lba_err = 7CB5h |
lba_noloader = 7CB2h |
; CHS version |
chs_read_sectors = 7CDEh |
chs_read_sectors2 = 7CD8h |
chs_lookup_in_root_dir = 7D70h |
chs_scan_for_filename = 7D4Eh |
chs_err = 7CB1h |
chs_noloader = 7CAEh |
push ax cx ; save our position on disk |
push ss |
pop es |
; determine version of bootsector (LBA vs CHS) |
; mov [read_sectors], chs_read_sectors |
; mov [read_sectors2], chs_read_sectors2 |
; mov [lookup_in_root_dir], chs_lookup_in_root_dir |
; mov [scan_for_filename], chs_scan_for_filename |
; mov [err], chs_err |
; mov [noloader], chs_noloader |
lea di, [read_sectors] |
mov si, chs_proc_addresses |
mov cx, 6*2 |
cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di' |
jz @f |
add si, cx |
; mov [read_sectors], lba_read_sectors |
; mov [read_sectors2], lba_read_sectors2 |
; mov [lookup_in_root_dir], lba_lookup_in_root_dir |
; mov [scan_for_filename], lba_scan_for_filename |
; mov [err], lba_err |
; mov [noloader], lba_noloader |
@@: |
rep movsb |
mov cl, [BPB_SecsPerClus] |
mov [sect_per_clus], cx |
xor bx, bx |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 94000h / 1024 |
jae @f |
nomem: |
mov si, nomem_str |
jmp [err_] |
@@: |
shr ax, 3 |
mov [cachelimit], ax ; size of cache - 1 |
; get type of file system - FAT12 or FAT16? |
; calculate number of clusters |
mov ax, [BPB_TotSec16] |
xor dx, dx |
test ax, ax |
jnz @f |
mov ax, word [BPB_TotSec32] |
mov dx, word [BPB_TotSec32+2] |
@@: |
sub ax, [bp-8] ; dword [bp-8] = first data sector |
sbb dx, [bp-6] |
jb j_noloader |
div [sect_per_clus] |
; ax = number of clusters |
; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes |
mov [fat_type], ch |
cmp ax, 0xFF5 |
jb init_fat12 |
inc [fat_type] |
init_fat16: |
; no sectors loaded |
mov di, 0x8200 |
xor ax, ax |
mov cx, 0x100/2 |
rep stosw |
jmp init_fat_done |
init_fat12: |
; read FAT |
push 0x6000 |
pop es |
mov ax, [BPB_RsvdSecCnt] |
mov cx, [BPB_FATSz16] |
cmp cx, 12 |
jb @f |
mov cx, 12 |
@@: |
xor dx, dx |
call [read_sectors] |
init_fat_done: |
; if cluster = sector, we need to read second part of our file |
; (bootsector loads only first cluster of kordldr.f1x) |
pop cx ax ; restore our position on disk |
cmp cx, 1 |
ja kordldr_full |
sub ax, [bp-8] |
inc ax |
inc ax ; ax = first cluster of kordldr.f12 |
call get_next_cluster |
jc @f |
j_noloader: |
jmp [noloader] |
@@: |
dec ax |
dec ax |
push 0x800 |
pop es |
call [read_sectors2] |
kordldr_full: |
; ...continue loading... |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
mov bx, [err_] |
jz @f |
mov si, aKernelNotFound |
jmp bx |
@@: |
; for subsequent calls to callback function, hook error handler |
; mov byte [bx], 0xE9 ; 'jmp' opcode |
; mov ax, hooked_err - 3 |
; sub ax, bx |
; mov word [bx+1], ax |
; push hooked_err / ret |
mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8) |
mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8) |
; set registers for secondary loader |
mov ah, [BS_DrvNum] |
mov al, 'f' |
test ah, ah |
jns @f |
sub ah, 80h |
mov al, 'h' |
@@: |
mov bx, '12' |
cmp [fat_type], 0 |
jz @f |
mov bh, '6' |
@@: |
mov si, callback ; ds:si = far pointer to callback procedure |
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 |
nomem_str db 'No memory',0 |
chs_proc_addresses: |
dw chs_read_sectors |
dw chs_read_sectors2 |
dw chs_lookup_in_root_dir |
dw chs_scan_for_filename |
dw chs_err |
dw chs_noloader |
lba_proc_addresses: |
dw lba_read_sectors |
dw lba_read_sectors2 |
dw lba_lookup_in_root_dir |
dw lba_scan_for_filename |
dw lba_err |
dw lba_noloader |
get_next_cluster: |
; in: ax = cluster |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
push si |
cmp [fat_type], 0 |
jnz gnc16 |
; for FAT12 |
push ds |
push 0x6000 |
pop ds |
mov si, ax |
shr si, 1 |
add si, ax |
test al, 1 |
lodsw |
jz @f |
shr ax, 4 |
@@: |
and ax, 0xFFF |
cmp ax, 0xFF7 |
pop ds si |
ret |
; for FAT16 |
gnc16: |
; each sector contains 200h bytes = 100h FAT entries |
; so ah = # of sector, al = offset in sector |
mov si, ax |
mov ah, 0 |
shr si, 8 |
; calculate segment for this sector of FAT table |
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) |
; segment = 6000 + 20*si, offset = 0 |
push es |
push si |
shl si, 5 |
add si, 0x6000 |
mov es, si |
pop si |
cmp byte [ss:0x8200+si], ah ; sector already loaded? |
jnz @f |
; load corresponding sector |
pusha |
push es |
xor bx, bx |
mov ax, [BPB_RsvdSecCnt] |
xor dx, dx |
add ax, si |
adc dx, bx |
mov cx, 1 ; read 1 sector |
call [read_sectors] |
pop es |
popa |
@@: |
mov si, ax |
add si, si |
; mov ax, [es:si] |
lods word [es:si] |
pop es |
cmp ax, 0xFFF7 |
pop si |
ret |
if $ > 0x8000 |
error 'get_next_cluster must fit in first sector of kordldr.f1x!' |
end if |
load_file: |
; in: ss:bp = 0:7C00 |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
xor ax, ax ; start from root directory |
mov dx, -1 |
mov word [filesize], dx |
mov word [filesize+2], dx ; initialize file size with invalid value |
lea si, [di+6] |
parse_dir_loop: |
; convert name to FAT name |
push di |
push ax |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
mov di, filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
nameloop: |
lodsb |
test al, al |
jz namedone |
cmp al, '/' |
jz namedone |
cmp al, '.' |
jz namedot |
dec cx |
js badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp nameloop |
namedot: |
inc bx |
jp badname |
add di, cx |
mov cl, 3 |
jmp nameloop |
badname: ; do not make direct js/jp to notfound_pop: |
; this generates long forms of conditional jumps and results in longer code |
jmp notfound_pop |
namedone: |
; scan directory |
pop ax ; ax = cluster of directory or 0 for root |
push ds |
push si |
push es |
pop ds |
mov si, filename ; ds:si -> filename in FAT style |
test ax, ax |
jnz lookup_in_notroot_dir |
; for root directory, use the subroutine from bootsector |
call [lookup_in_root_dir] |
jmp lookup_done |
lookup_in_notroot_dir: |
; for other directories, read a folder sector-by-sector and scan |
; first, try to use the cache |
push ds |
push cs |
pop ds |
mov bx, [cachelimit] |
add bx, bx |
mov di, foldcache_mark |
@@: |
mov dx, [foldcache_clus+di-foldcache_mark+bx] |
cmp dx, ax |
jz cacheok |
test dx, dx |
jz cacheadd ; the cache has place for new entry |
dec bx |
dec bx |
jns @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov dx, [cachelimit] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
mov [foldcache_clus+di-foldcache_mark+bx], ax |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [cachelimit] |
add di, di |
cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
pop ds |
; mov dx, bx |
; shl dx, 8 ; dx = (position in cache)*0x2000/0x10 |
; add dx, 0x9200 |
lea dx, [bx+0x92] |
xchg dl, dh |
mov es, dx |
jcxz not_in_cache |
call [scan_for_filename] |
jz lookup_done |
not_in_cache: |
; cache miss, read folder data from disk |
mov bx, cx |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
folder_next_cluster: |
; internal loop: scan sectors in cluster |
mov cx, [sect_per_clus] |
push ax |
dec ax |
dec ax |
mul cx |
add ax, [bp-8] |
adc dx, [bp-6] ; dx:ax = absolute sector |
folder_next_sector: |
; skip first bx sectors |
dec bx |
jns folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
call [read_sectors] |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
push si di |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache |
pop di si |
@@: |
push es |
push 0x8000 |
pop es |
push cs |
pop ds |
mov cx, 0x10 |
call [scan_for_filename] |
pop es |
pop cx |
jz lookup_done_pop |
folder_skip_sector: |
inc ax |
jnz @f |
inc dx |
@@: |
loop folder_next_sector |
pop ax ; ax = current cluster |
call get_next_cluster |
jc folder_next_cluster |
stc |
push ax |
lookup_done_pop: |
pop ax |
lookup_done: |
pop si |
pop ds |
; CF=1 <=> failed |
jnc found |
notfound: |
pop di |
mov bx, 2 ; file not found |
mov ax, 0xFFFF |
mov dx, ax ; invalid file size |
ret |
notfound_pop: |
pop ax |
jmp notfound |
found: |
mov ax, [es:di+26] ; get cluster |
test byte [es:di+11], 10h ; directory? |
jz regular_file |
cmp byte [si-1], 0 |
jz notfound ; don't read directories as a regular files |
; ok, we have found a directory and the caller requested a file into it |
pop di |
jmp parse_dir_loop ; restart with new cluster in ax |
regular_file: |
cmp byte [si-1], 0 |
jnz notfound ; file does not contain another files |
; ok, we have found a regular file and the caller requested it |
; save file size |
mov dx, [es:di+28] |
mov [filesize], dx |
mov dx, [es:di+30] |
mov [filesize+2], dx |
pop di |
mov si, [di+4] |
shl si, 3 |
push si ; [ds:di+4] = limit in 4K blocks |
les bx, [di] ; es:bx -> buffer |
clusloop: |
; ax = first cluster, top of stack contains limit in sectors |
mov si, ax ; remember current cluster |
xor cx, cx ; cx will contain number of consecutive clusters |
mov word [cur_delta], cx |
mov word [cur_delta+2], cx |
mov di, ax |
clusfind: |
inc di |
inc cx |
call get_next_cluster |
jnc clusread |
cmp ax, di |
jz clusfind |
stc |
clusread: |
pop di ; limit in sectors |
push ax ; save next cluster |
pushf ; save flags |
; read cx clusters, starting from si |
; calculate number of sectors |
xchg ax, cx |
mul [sect_per_clus] |
; dx:ax = number of sectors; compare with limit |
mov word [num_sectors], ax |
mov word [num_sectors+2], dx |
jmp @f |
continue_load_file: |
les bx, [di] ; es:bx -> buffer |
mov di, [di+4] ; ds:di = limit in 4K blocks |
shl di, 3 ; now di = limit in sectors |
mov ax, word [num_sectors] |
mov dx, word [num_sectors+2] |
mov si, [cur_cluster] |
push [next_cluster] |
push [flags] |
or ax, dx |
jz nextclus |
@@: |
test dx, dx |
jnz clusdecrease |
push dx ; limit was not exceeded |
cmp ax, di |
jbe @f |
pop ax |
clusdecrease: |
push 1 ; limit was exceeded |
mov ax, di |
@@: |
sub di, ax ; calculate new limit |
sub word [num_sectors], ax |
sbb word [num_sectors+2], 0 |
readloop: |
push ax |
; buffer should not cross a 64K boundary |
push bx |
shr bx, 4 |
mov cx, es |
add bx, cx |
neg bx |
and bh, 0xF |
shr bx, 5 |
jnz @f |
mov bl, 0x80 |
@@: |
cmp ax, bx |
jbe @f |
xchg ax, bx |
@@: |
pop bx |
xchg ax, cx |
; calculate starting sector |
lea ax, [si-2] |
mul [sect_per_clus] |
add ax, word [cur_delta] |
adc dx, word [cur_delta+2] |
add word [cur_delta], cx |
adc word [cur_delta+2], 0 |
; read |
call [read_sectors2] |
pop ax |
sub ax, cx |
jnz readloop |
pop dx |
; next cluster? |
nextclus: |
popf |
pop ax |
mov [cur_cluster], si |
mov [next_cluster], ax |
pushf |
pop [flags] |
jnc @f ; no next cluster => return |
mov dl, 1 ; dh=0 in any case |
test di, di |
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded |
push di |
jmp clusloop ; all is ok, continue |
hooked_err: |
mov sp, 7C00h-12-2 ; restore stack |
mov dx, 3 ; return: read error |
@@: |
mov bx, dx |
mov ax, [filesize] |
mov dx, [filesize+2] |
ret |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 7C00h-8 |
mov bp, 7C00h |
push dx |
push cx |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
; function 2: continue loading file |
; can be called only after function 1 returned value bx=1 (only part of file was loaded) |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
callback_ret_succ: |
clc ; function is supported |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kernel.mnt',0 |
aKernelNotFound db 'Fatal error: cannot load the kernel',0 |
foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache |
foldcache_mark rw 7 |
foldcache_size rw 7 |
filename rb 11 |
if $ > 0x8200 |
error: |
table overwritten |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/fat32/bootsect.asm |
---|
1,358 → 1,358 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
use_lba = 0 |
org 0x7C00 |
jmp start |
nop |
; FAT parameters, BPB |
; they must be changed at install, replaced with real values |
rb 8 ; BS_OEMName, ignored |
dw 200h ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
dw ? ; BPB_TotSec16 |
db ? ; BPB_Media |
dw ? ; BPB_FATSz16 = 0 for FAT32 |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
dd ? ; BPB_TotSec32 |
BPB_FATSz32 dd ? |
BPB_ExtFlags dw ? |
dw ? ; BPB_FSVer |
BPB_RootClus dd ? |
dw ? ; BPB_FSInfo |
BPB_BkBootSec dw ? |
rb 12 ; BPB_Reserved |
BS_DrvNum db ? |
db ? ; BS_Reserved1 |
db ? ; BS_BootSig |
dd ? ; BS_VolID |
rb 11 ; BS_VolLab |
rb 8 ; |
curseg dw 0x8000 |
start: |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov bp, sp |
cld |
sti |
push dx ; byte [bp-2] = boot drive |
if use_lba |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cl, 1 |
jz err_ |
else |
mov ah, 8 |
int 13h |
jc @f |
movzx ax, dh |
inc ax |
mov [bp+BPB_NumHeads-0x7C00], ax |
and cx, 3Fh |
mov [bp+BPB_SecPerTrk-0x7C00], cx |
@@: |
end if |
; get FAT parameters |
xor bx, bx |
movzx eax, [bp+BPB_NumFATs-0x7C00] |
mul [bp+BPB_FATSz32-0x7C00] |
movzx ecx, [bp+BPB_RsvdSecCnt-0x7C00] |
push ecx ; FAT start = dword [bp-6] |
add eax, ecx |
push eax ; data start = dword [bp-10] |
;push dword -1 ; dword [bp-14] = current sector for FAT cache |
db 66h |
push -1 ; dword [bp-14] = current sector for FAT cache |
mov eax, [bp+BPB_RootClus-0x7C00] |
mov si, main_loader |
call lookup_in_dir |
jnc kordldr_ok |
noloader: |
mov si, aLoaderNotFound |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
kordldr_ok: |
mov eax, [es:di+20-2] ; hiword(eax) = hiword(cluster) |
mov ax, [es:di+26] ; loword(eax) = loword(cluster) |
mov es, bx ; es = 0 |
mov bx, 0x7E00 |
push bx ; save return address: bx = 7E00 |
; fall through - 'ret' in read_cluster will return to 7E00 |
read_cluster: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; eax = cluster |
sub eax, 2 |
movzx ecx, [bp+BPB_SecsPerClus-0x7C00] |
mul ecx |
read_sectors2: |
; same as read_sectors32, but eax is relative to start of data |
add eax, [bp-10] |
read_sectors32: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; eax = first sector |
; cx = number of sectors |
; some high words of 32-bit registers are destroyed! |
pusha |
add eax, [bp+BPB_HiddSec-0x7C00] |
if use_lba |
push ds |
do_read_sectors: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp-2] |
mov ah, 42h |
int 13h |
mov si, aReadError |
jc err_ |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz do_read_sectors |
pop ds |
popa |
ret |
else |
do_read_sectors: |
pusha |
pop edi ; loword(edi) = di, hiword(edi) = si |
push bx |
; eax / (SectorsPerTrack) -> eax, remainder bx |
movzx esi, [bp+BPB_SecPerTrk-0x7C00] |
xor edx, edx |
div esi |
mov bx, dx ; bx=sector-1 |
; eax -> dx:ax |
push eax |
pop ax |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp+BPB_NumHeads-0x7C00] |
; number of sectors: read no more than to end of track |
sub si, bx |
cmp cx, si |
jbe @f |
mov cx, si |
@@: |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format |
movzx edi, cx |
mov dh, dl |
mov dl, [bp-2] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
mov si, aReadError |
jmp err_ |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push edi |
popa |
add eax, edi |
sub cx, di |
jnz do_read_sectors |
popa |
ret |
end if |
lookup_in_dir: |
; in: ds:si -> 11-bytes FAT name |
; in: eax = cluster |
; in: bx = 0 |
; out: if found: CF=0, es:di -> directory entry |
; out: if not found: CF=1 |
; push 0x8000 |
; pop es |
; read current cluster: first cluster goes to 8000:0000, others - to 8200:0000 |
mov es, [bp-7C00h + curseg] |
push es |
push eax |
call read_cluster |
mov ax, es |
cmp ah, 82h |
jb @f |
mov ax, 8200h |
@@: |
mov [bp-7C00h + curseg], ax |
pop eax |
pop es |
; scan for filename |
shl cx, 4 |
xor di, di |
sloop: |
cmp byte [es:di], bl |
jz snotfound |
test byte [es:di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmpsb |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
; next cluster |
push 0x6000 |
pop es |
push es ax |
shr eax, 7 |
cmp eax, [bp-14] |
mov [bp-14], eax |
jz @f |
add eax, [bp-6] |
mov cx, 1 |
call read_sectors32 |
@@: |
pop di es |
and di, 0x7F |
shl di, 2 |
and byte [es:di+3], 0x0F |
mov eax, [es:di] |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
jb lookup_in_dir |
snotfound: |
stc |
sdone: |
ret |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz sdone |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aReadError db 'Read error',0 |
if use_lba |
aNoLBA db 'The drive does not support LBA!',0 |
end if |
aLoaderNotFound db 'Loader not found',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
main_loader db 'KORDLDR F32' |
db 56h |
; just to make file 512 bytes long :) |
db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' |
; bootsector signature |
dw 0xAA55 |
; display offsets of all procedures used by kordldr.f12.asm |
macro show [procedure] |
{ |
bits = 16 |
display `procedure,' = ' |
repeat bits/4 |
d = '0' + procedure shr (bits - %*4) and 0Fh |
if d > '9' |
d = d + 'A'-'9'-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
show read_sectors32, read_sectors2, err_, noloader |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
use_lba = 0 |
org 0x7C00 |
jmp start |
nop |
; FAT parameters, BPB |
; they must be changed at install, replaced with real values |
rb 8 ; BS_OEMName, ignored |
dw 200h ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
dw ? ; BPB_TotSec16 |
db ? ; BPB_Media |
dw ? ; BPB_FATSz16 = 0 for FAT32 |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
dd ? ; BPB_TotSec32 |
BPB_FATSz32 dd ? |
BPB_ExtFlags dw ? |
dw ? ; BPB_FSVer |
BPB_RootClus dd ? |
dw ? ; BPB_FSInfo |
BPB_BkBootSec dw ? |
rb 12 ; BPB_Reserved |
BS_DrvNum db ? |
db ? ; BS_Reserved1 |
db ? ; BS_BootSig |
dd ? ; BS_VolID |
rb 11 ; BS_VolLab |
rb 8 ; |
curseg dw 0x8000 |
start: |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov bp, sp |
cld |
sti |
push dx ; byte [bp-2] = boot drive |
if use_lba |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cl, 1 |
jz err_ |
else |
mov ah, 8 |
int 13h |
jc @f |
movzx ax, dh |
inc ax |
mov [bp+BPB_NumHeads-0x7C00], ax |
and cx, 3Fh |
mov [bp+BPB_SecPerTrk-0x7C00], cx |
@@: |
end if |
; get FAT parameters |
xor bx, bx |
movzx eax, [bp+BPB_NumFATs-0x7C00] |
mul [bp+BPB_FATSz32-0x7C00] |
movzx ecx, [bp+BPB_RsvdSecCnt-0x7C00] |
push ecx ; FAT start = dword [bp-6] |
add eax, ecx |
push eax ; data start = dword [bp-10] |
;push dword -1 ; dword [bp-14] = current sector for FAT cache |
db 66h |
push -1 ; dword [bp-14] = current sector for FAT cache |
mov eax, [bp+BPB_RootClus-0x7C00] |
mov si, main_loader |
call lookup_in_dir |
jnc kordldr_ok |
noloader: |
mov si, aLoaderNotFound |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
kordldr_ok: |
mov eax, [es:di+20-2] ; hiword(eax) = hiword(cluster) |
mov ax, [es:di+26] ; loword(eax) = loword(cluster) |
mov es, bx ; es = 0 |
mov bx, 0x7E00 |
push bx ; save return address: bx = 7E00 |
; fall through - 'ret' in read_cluster will return to 7E00 |
read_cluster: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; eax = cluster |
sub eax, 2 |
movzx ecx, [bp+BPB_SecsPerClus-0x7C00] |
mul ecx |
read_sectors2: |
; same as read_sectors32, but eax is relative to start of data |
add eax, [bp-10] |
read_sectors32: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; eax = first sector |
; cx = number of sectors |
; some high words of 32-bit registers are destroyed! |
pusha |
add eax, [bp+BPB_HiddSec-0x7C00] |
if use_lba |
push ds |
do_read_sectors: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp-2] |
mov ah, 42h |
int 13h |
mov si, aReadError |
jc err_ |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz do_read_sectors |
pop ds |
popa |
ret |
else |
do_read_sectors: |
pusha |
pop edi ; loword(edi) = di, hiword(edi) = si |
push bx |
; eax / (SectorsPerTrack) -> eax, remainder bx |
movzx esi, [bp+BPB_SecPerTrk-0x7C00] |
xor edx, edx |
div esi |
mov bx, dx ; bx=sector-1 |
; eax -> dx:ax |
push eax |
pop ax |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp+BPB_NumHeads-0x7C00] |
; number of sectors: read no more than to end of track |
sub si, bx |
cmp cx, si |
jbe @f |
mov cx, si |
@@: |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format |
movzx edi, cx |
mov dh, dl |
mov dl, [bp-2] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
mov si, aReadError |
jmp err_ |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push edi |
popa |
add eax, edi |
sub cx, di |
jnz do_read_sectors |
popa |
ret |
end if |
lookup_in_dir: |
; in: ds:si -> 11-bytes FAT name |
; in: eax = cluster |
; in: bx = 0 |
; out: if found: CF=0, es:di -> directory entry |
; out: if not found: CF=1 |
; push 0x8000 |
; pop es |
; read current cluster: first cluster goes to 8000:0000, others - to 8200:0000 |
mov es, [bp-7C00h + curseg] |
push es |
push eax |
call read_cluster |
mov ax, es |
cmp ah, 82h |
jb @f |
mov ax, 8200h |
@@: |
mov [bp-7C00h + curseg], ax |
pop eax |
pop es |
; scan for filename |
shl cx, 4 |
xor di, di |
sloop: |
cmp byte [es:di], bl |
jz snotfound |
test byte [es:di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmpsb |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
; next cluster |
push 0x6000 |
pop es |
push es ax |
shr eax, 7 |
cmp eax, [bp-14] |
mov [bp-14], eax |
jz @f |
add eax, [bp-6] |
mov cx, 1 |
call read_sectors32 |
@@: |
pop di es |
and di, 0x7F |
shl di, 2 |
and byte [es:di+3], 0x0F |
mov eax, [es:di] |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
jb lookup_in_dir |
snotfound: |
stc |
sdone: |
ret |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz sdone |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aReadError db 'Read error',0 |
if use_lba |
aNoLBA db 'The drive does not support LBA!',0 |
end if |
aLoaderNotFound db 'Loader not found',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
main_loader db 'KORDLDR F32' |
db 56h |
; just to make file 512 bytes long :) |
db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' |
; bootsector signature |
dw 0xAA55 |
; display offsets of all procedures used by kordldr.f12.asm |
macro show [procedure] |
{ |
bits = 16 |
display `procedure,' = ' |
repeat bits/4 |
d = '0' + procedure shr (bits - %*4) and 0Fh |
if d > '9' |
d = d + 'A'-'9'-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
show read_sectors32, read_sectors2, err_, noloader |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/fat32/kordldr.f32.asm |
---|
1,673 → 1,673 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
org 0x7E00 |
; the KordOS FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here |
; ss:bp = 0:7C00 |
; ds = 0 |
virtual at bp |
rb 3 ; BS_jmpBoot |
rb 8 ; BS_OEMName, ignored |
dw ? ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
dw ? ; BPB_TotSec16 |
db ? ; BPB_Media |
dw ? ; BPB_FATSz16 = 0 for FAT32 |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
dd ? ; BPB_TotSec32 |
BPB_FATSz32 dd ? |
BPB_ExtFlags dw ? |
dw ? ; BPB_FSVer |
BPB_RootClus dd ? |
filesize: |
dw ? ; BPB_FSInfo |
dw ? ; BPB_BkBootSec |
rb 12 ; BPB_Reserved |
BS_DrvNum db ? |
db ? ; BS_Reserved1 |
db ? ; BS_BootSig |
dd ? ; BS_VolID |
; rb 11 ; BS_VolLab |
; rb 5 ; BS_FilSysType, first 5 bytes |
read_sectors32 dw ? |
read_sectors2 dw ? |
err_ dw ? |
noloader dw ? |
cachelimit dw ? |
fatcachehead rw 2 |
fatcacheend dw ? |
rb 3 ; BS_FilSysType, last 3 bytes |
curseg dw ? |
num_sectors dd ? |
cur_cluster dd ? |
next_cluster dd ? |
flags dw ? |
cur_delta dd ? |
end virtual |
; procedures from boot sector |
; LBA version |
lba_read_sectors2 = 7CD6h |
lba_err = 7CAAh |
lba_noloader = 7CA7h ; = lba_err - 3 |
; CHS version |
chs_read_sectors2 = 7CD2h |
chs_err = 7CA6h |
chs_noloader = 7CA3h ; = chs_err - 3 |
push eax cx ; save our position on disk |
; determine version of bootsector (LBA vs CHS) |
mov [read_sectors2], chs_read_sectors2 |
mov bx, chs_err |
mov [err_], bx |
; mov [noloader], chs_noloader |
cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version |
jz @f |
add [read_sectors2], lba_read_sectors2 - chs_read_sectors2 |
add [err_], lba_err - chs_err |
; mov [noloader], lba_noloader |
@@: |
xor bx, bx |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 92000h / 1024 |
jae @f |
nomem: |
mov si, nomem_str |
jmp [err_] |
@@: |
shr ax, 3 |
mov [cachelimit], ax ; size of cache - 1 |
mov es, bx |
; no folders in cache yet |
mov di, foldcache_clus |
mov cx, 8*4/2 + 1 |
xor ax, ax |
rep stosw |
; bootsector code caches one FAT sector, [bp-14], in 6000:0000 |
; initialize our (more advanced) FAT caching from this |
mov di, 8400h |
mov cx, di |
lea si, [fatcachehead] |
mov [si], si ; no sectors in cache: |
mov [si+2], si ; 'prev' & 'next' links point to self |
mov [fatcacheend], di ; first free item = 8400h |
stosw ; 'next cached sector' link |
stosw ; 'prev cached sector' link |
mov eax, [bp-14] |
stosd ; first sector number in cache |
test eax, eax |
js @f |
mov [si], cx ; 'first cached sector' link = 8400h |
mov [si+2], cx ; 'next cached sector' link = 8400h |
mov [fatcacheend], di ; first free item = 8406h |
@@: |
; if cluster = sector, we need to read second part of our file |
; (bootsector loads only first cluster of kordldr.f32) |
pop cx eax ; restore our position on disk |
cmp cx, 1 |
ja kordldr_full |
sub eax, [bp-10] |
inc eax |
inc eax ; eax = first cluster of kordldr.f32 |
call get_next_cluster |
jc @f |
; jmp [noloader] |
mov ax, [err_] |
sub ax, 3 |
jmp ax |
@@: |
dec eax |
dec eax |
push 0x800 |
pop es |
call [read_sectors2] |
kordldr_full: |
; bootsector code has read some data of root directory to 8000:0000 |
; initialize our folder caching from this |
mov eax, [BPB_RootClus] |
mov [foldcache_clus], eax |
mov cx, [curseg] |
mov ax, 8000h |
sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes) |
shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes) |
mov [foldcache_size], cx |
shl cx, 4 |
push ds |
mov ds, ax |
push 0x9000 |
pop es |
xor si, si |
xor di, di |
rep movsw |
pop ds |
; ...continue loading... |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
mov bx, [err_] |
jz @f |
mov si, aKernelNotFound |
jmp bx |
@@: |
; for subsequent calls to callback function, hook error handler |
; push hooked_err / ret |
mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24) |
; set registers for secondary loader |
mov ah, [bp-2] ; drive id |
mov al, 'f' |
btr ax, 15 |
jnc @f |
mov al, 'h' |
@@: |
mov bx, '32' |
mov si, callback |
jmp far [si+secondary_loader_info-callback] |
nomem_str db 'No memory',0 |
cluster2sector: |
sub eax, 2 |
clustersz2sectorsz: |
movzx ecx, [BPB_SecsPerClus] |
mul ecx |
ret |
get_next_cluster: |
; in: eax = cluster |
; out: if there is next cluster: CF=1, eax = next cluster |
; out: if there is no next cluster: CF=0 |
push di bx |
push ds es |
push ss |
pop ds |
push ss |
pop es |
push ax |
shr eax, 7 |
; eax = FAT sector number; look in cache |
mov di, 8400h |
.cache_lookup: |
cmp di, [fatcacheend] |
jae .not_in_cache |
scasd |
scasd |
jnz .cache_lookup |
.in_cache: |
sub di, 8 |
; delete this sector from the list |
push si |
mov si, [di] |
mov bx, [di+2] |
mov [si+2], bx |
mov [bx], si |
pop si |
jmp @f |
.not_in_cache: |
; cache miss |
; cache is full? |
mov di, [fatcacheend] |
cmp di, 8C00h |
jnz .cache_not_full |
; yes, delete the oldest entry |
mov di, [fatcachehead] |
mov bx, [di] |
mov [fatcachehead], bx |
push word [di+2] |
pop word [bx+2] |
jmp .cache_append |
.cache_not_full: |
; no, allocate new sector |
add [fatcacheend], 8 |
.cache_append: |
; read FAT |
mov [di+4], eax |
pushad |
lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] ; +0x10000 - for FASM |
shl cx, 9-4-3 |
mov es, cx |
xor bx, bx |
mov cx, 1 |
add eax, [bp-6] ; FAT start |
sub eax, [bp-10] |
call [read_sectors2] |
popad |
@@: |
; add new sector to the end of list |
mov bx, di |
xchg bx, [fatcachehead+2] |
push word [bx] |
pop word [di] |
mov [bx], di |
mov [di+2], bx |
; get requested item |
lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] |
pop di |
and di, 0x7F |
shl di, 2 |
shl ax, 9-4-3 |
mov ds, ax |
and byte [di+3], 0x0F |
mov eax, [di] |
pop es ds |
pop bx di |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
ret |
if $ > 0x8000 |
error 'get_next_cluster must fit in first sector of kordldr.f32!' |
end if |
load_file: |
; in: ss:bp = 0:7C00 |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
mov eax, [BPB_RootClus] ; start from root directory |
or dword [filesize], -1 ; initialize file size with invalid value |
lea si, [di+6] |
parse_dir_loop: |
; convert name to FAT name |
push di |
push ax |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
filename equ bp |
mov di, filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
nameloop: |
lodsb |
test al, al |
jz namedone |
cmp al, '/' |
jz namedone |
cmp al, '.' |
jz namedot |
dec cx |
js badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp nameloop |
namedot: |
inc bx |
jp badname |
add di, cx |
mov cl, 3 |
jmp nameloop |
badname: ; do not make direct js/jp to notfound_pop: |
; this generates long forms of conditional jumps and results in longer code |
jmp notfound_pop |
namedone: |
; scan directory |
pop ax ; eax = cluster of directory |
; high word of eax is preserved by operations above |
push ds |
push si |
; read a folder sector-by-sector and scan |
; first, try to use the cache |
push ss |
pop ds |
mov di, foldcache_mark |
xor bx, bx |
mov cx, [cachelimit] |
@@: |
lea si, [di+bx] |
mov edx, dword [foldcache_clus+si-foldcache_mark+bx] |
cmp edx, eax |
jz cacheok |
test edx, edx |
jz cacheadd ; the cache has place for new entry |
inc bx |
inc bx |
dec cx |
jns @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov bx, -2 |
mov dx, [cachelimit] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
lea si, [di+bx] |
cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
mov dword [foldcache_clus+si-foldcache_mark+bx], eax |
cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [cachelimit] |
add di, di |
cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
;mov dx, bx |
;shl dx, 8 ; dx = (position in cache)*0x2000/0x10 |
;add dx, 0x9000 |
lea dx, [bx + 0x90] |
xchg dl, dh |
mov ds, dx |
mov si, filename ; ss:si -> filename in FAT style |
call scan_for_filename |
jz lookup_done |
; cache miss, read folder data from disk |
mov bx, cx |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
folder_next_cluster: |
; internal loop: scan sectors in cluster |
push eax |
call cluster2sector |
folder_next_sector: |
; skip first bx sectors |
dec bx |
jns folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
push eax |
call [read_sectors2] |
pop eax |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
pusha |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache |
popa |
@@: |
push es |
mov cl, 0x10 ; ch=0 at this point |
call scan_for_filename |
pop es |
pop cx |
jz lookup_done_pop |
folder_skip_sector: |
inc eax |
loop folder_next_sector |
pop eax ; eax = current cluster |
call get_next_cluster |
jc folder_next_cluster |
stc |
push eax |
lookup_done_pop: |
pop eax |
lookup_done: |
pop si |
; CF=1 <=> failed |
jnc found |
pop ds |
notfound: |
pop di |
notfound2: |
mov bx, 2 ; file not found |
mov ax, 0xFFFF |
mov dx, ax ; invalid file size |
ret |
notfound_pop: |
pop ax |
jmp notfound |
found: |
mov eax, [di+20-2] |
mov edx, [di+28] |
mov ax, [di+26] ; get cluster |
test byte [di+11], 10h ; directory? |
pop ds |
pop di |
jz regular_file |
cmp byte [si-1], 0 |
jz notfound2 ; don't read directories as regular files |
; ok, we have found a directory and the caller requested a file into it |
jmp parse_dir_loop ; restart with new cluster in ax |
regular_file: |
cmp byte [si-1], 0 |
jnz notfound2 ; file does not contain another files |
; ok, we have found a regular file and the caller requested it |
; save file size |
mov [filesize], edx |
mov si, [di+4] ; [ds:di+4] = limit in 4K blocks |
shl si, 3 |
push si |
les bx, [di] ; es:bx -> buffer |
clusloop: |
; eax = first cluster, top of stack contains limit in sectors |
mov esi, eax ; remember current cluster |
xor ecx, ecx ; ecx will contain number of consecutive clusters |
mov [cur_delta], ecx |
mov edi, eax |
clusfind: |
inc edi |
inc ecx |
call get_next_cluster |
jnc clusread |
cmp eax, edi |
jz clusfind |
stc |
clusread: |
pop di ; limit in sectors |
movzx edi, di |
push eax ; save next cluster |
pushf ; save flags |
; read cx clusters, starting from si |
; calculate number of sectors |
xchg eax, ecx |
call clustersz2sectorsz |
mov [num_sectors], eax |
jmp @f |
continue_load_file: |
les bx, [di] ; es:bx -> buffer |
movzx edi, word [di+4] ; di = limit in 4K blocks |
shl di, 3 ; now di = limit in sectors |
mov eax, [num_sectors] |
mov esi, [cur_cluster] |
push [next_cluster] |
push [flags] |
test eax, eax |
jz nextclus |
@@: |
; eax = number of sectors; compare with limit |
cmp eax, edi |
seta dl |
push dx ; limit was exceeded? |
jbe @f |
mov eax, edi |
@@: |
sub di, ax ; calculate new limit |
sub [num_sectors], eax |
mov [cur_cluster], esi |
; calculate starting sector |
push ax |
xchg eax, esi |
call cluster2sector |
pop cx |
add eax, [cur_delta] |
add [cur_delta], ecx |
; read |
call [read_sectors2] |
pop dx |
; next cluster? |
nextclus: |
popf |
pop eax |
mov [next_cluster], eax |
pushf |
pop [flags] |
jnc @f ; no next cluster => return |
mov dl, 1 |
test di, di |
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded |
push di |
jmp clusloop ; all is ok, continue |
hooked_err: |
mov sp, 7C00h-14-2 ; restore stack |
mov dl, 3 ; return: read error |
@@: |
mov bl, dl |
mov bh, 0 |
mov ax, [filesize] |
mov dx, [filesize+2] |
ret |
scan_for_filename: |
; in: ss:si -> 11-bytes FAT name |
; in: ds:0 -> part of directory data |
; in: cx = number of entries |
; in: bh = 0 |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
push ds |
pop es |
xor di, di |
push cx |
jcxz snoent |
sloop: |
cmp byte [di], bh |
jz snotfound |
test byte [di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmps byte [ss:si], byte [es:di] |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
snoent: |
inc cx ; clear ZF flag |
snotfound: |
stc |
sdone: |
pop cx |
lrdret: |
ret |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 7C00h-10 |
mov bp, 7C00h |
push dx |
push cx |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
; function 2: continue loading file |
; can be called only after function 1 returned value bx=1 (only part of file was loaded) |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
callback_ret_succ: |
clc ; function is supported |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kernel.mnt',0 |
aKernelNotFound db 'Fatal error: cannot load the kernel',0 |
;if $ > 0x8200 |
;error 'total size of kordldr.f32 must not exceed 1024 bytes!' |
;end if |
;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache |
;foldcache_mark dw 0 |
; rw 7 |
;foldcache_size rw 8 |
foldcache_clus rd 8 |
foldcache_mark rw 8 |
foldcache_size rw 8 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
org 0x7E00 |
; the KordOS FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here |
; ss:bp = 0:7C00 |
; ds = 0 |
virtual at bp |
rb 3 ; BS_jmpBoot |
rb 8 ; BS_OEMName, ignored |
dw ? ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
dw ? ; BPB_TotSec16 |
db ? ; BPB_Media |
dw ? ; BPB_FATSz16 = 0 for FAT32 |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
dd ? ; BPB_TotSec32 |
BPB_FATSz32 dd ? |
BPB_ExtFlags dw ? |
dw ? ; BPB_FSVer |
BPB_RootClus dd ? |
filesize: |
dw ? ; BPB_FSInfo |
dw ? ; BPB_BkBootSec |
rb 12 ; BPB_Reserved |
BS_DrvNum db ? |
db ? ; BS_Reserved1 |
db ? ; BS_BootSig |
dd ? ; BS_VolID |
; rb 11 ; BS_VolLab |
; rb 5 ; BS_FilSysType, first 5 bytes |
read_sectors32 dw ? |
read_sectors2 dw ? |
err_ dw ? |
noloader dw ? |
cachelimit dw ? |
fatcachehead rw 2 |
fatcacheend dw ? |
rb 3 ; BS_FilSysType, last 3 bytes |
curseg dw ? |
num_sectors dd ? |
cur_cluster dd ? |
next_cluster dd ? |
flags dw ? |
cur_delta dd ? |
end virtual |
; procedures from boot sector |
; LBA version |
lba_read_sectors2 = 7CD6h |
lba_err = 7CAAh |
lba_noloader = 7CA7h ; = lba_err - 3 |
; CHS version |
chs_read_sectors2 = 7CD2h |
chs_err = 7CA6h |
chs_noloader = 7CA3h ; = chs_err - 3 |
push eax cx ; save our position on disk |
; determine version of bootsector (LBA vs CHS) |
mov [read_sectors2], chs_read_sectors2 |
mov bx, chs_err |
mov [err_], bx |
; mov [noloader], chs_noloader |
cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version |
jz @f |
add [read_sectors2], lba_read_sectors2 - chs_read_sectors2 |
add [err_], lba_err - chs_err |
; mov [noloader], lba_noloader |
@@: |
xor bx, bx |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 92000h / 1024 |
jae @f |
nomem: |
mov si, nomem_str |
jmp [err_] |
@@: |
shr ax, 3 |
mov [cachelimit], ax ; size of cache - 1 |
mov es, bx |
; no folders in cache yet |
mov di, foldcache_clus |
mov cx, 8*4/2 + 1 |
xor ax, ax |
rep stosw |
; bootsector code caches one FAT sector, [bp-14], in 6000:0000 |
; initialize our (more advanced) FAT caching from this |
mov di, 8400h |
mov cx, di |
lea si, [fatcachehead] |
mov [si], si ; no sectors in cache: |
mov [si+2], si ; 'prev' & 'next' links point to self |
mov [fatcacheend], di ; first free item = 8400h |
stosw ; 'next cached sector' link |
stosw ; 'prev cached sector' link |
mov eax, [bp-14] |
stosd ; first sector number in cache |
test eax, eax |
js @f |
mov [si], cx ; 'first cached sector' link = 8400h |
mov [si+2], cx ; 'next cached sector' link = 8400h |
mov [fatcacheend], di ; first free item = 8406h |
@@: |
; if cluster = sector, we need to read second part of our file |
; (bootsector loads only first cluster of kordldr.f32) |
pop cx eax ; restore our position on disk |
cmp cx, 1 |
ja kordldr_full |
sub eax, [bp-10] |
inc eax |
inc eax ; eax = first cluster of kordldr.f32 |
call get_next_cluster |
jc @f |
; jmp [noloader] |
mov ax, [err_] |
sub ax, 3 |
jmp ax |
@@: |
dec eax |
dec eax |
push 0x800 |
pop es |
call [read_sectors2] |
kordldr_full: |
; bootsector code has read some data of root directory to 8000:0000 |
; initialize our folder caching from this |
mov eax, [BPB_RootClus] |
mov [foldcache_clus], eax |
mov cx, [curseg] |
mov ax, 8000h |
sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes) |
shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes) |
mov [foldcache_size], cx |
shl cx, 4 |
push ds |
mov ds, ax |
push 0x9000 |
pop es |
xor si, si |
xor di, di |
rep movsw |
pop ds |
; ...continue loading... |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
mov bx, [err_] |
jz @f |
mov si, aKernelNotFound |
jmp bx |
@@: |
; for subsequent calls to callback function, hook error handler |
; push hooked_err / ret |
mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24) |
; set registers for secondary loader |
mov ah, [bp-2] ; drive id |
mov al, 'f' |
btr ax, 15 |
jnc @f |
mov al, 'h' |
@@: |
mov bx, '32' |
mov si, callback |
jmp far [si+secondary_loader_info-callback] |
nomem_str db 'No memory',0 |
cluster2sector: |
sub eax, 2 |
clustersz2sectorsz: |
movzx ecx, [BPB_SecsPerClus] |
mul ecx |
ret |
get_next_cluster: |
; in: eax = cluster |
; out: if there is next cluster: CF=1, eax = next cluster |
; out: if there is no next cluster: CF=0 |
push di bx |
push ds es |
push ss |
pop ds |
push ss |
pop es |
push ax |
shr eax, 7 |
; eax = FAT sector number; look in cache |
mov di, 8400h |
.cache_lookup: |
cmp di, [fatcacheend] |
jae .not_in_cache |
scasd |
scasd |
jnz .cache_lookup |
.in_cache: |
sub di, 8 |
; delete this sector from the list |
push si |
mov si, [di] |
mov bx, [di+2] |
mov [si+2], bx |
mov [bx], si |
pop si |
jmp @f |
.not_in_cache: |
; cache miss |
; cache is full? |
mov di, [fatcacheend] |
cmp di, 8C00h |
jnz .cache_not_full |
; yes, delete the oldest entry |
mov di, [fatcachehead] |
mov bx, [di] |
mov [fatcachehead], bx |
push word [di+2] |
pop word [bx+2] |
jmp .cache_append |
.cache_not_full: |
; no, allocate new sector |
add [fatcacheend], 8 |
.cache_append: |
; read FAT |
mov [di+4], eax |
pushad |
lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] ; +0x10000 - for FASM |
shl cx, 9-4-3 |
mov es, cx |
xor bx, bx |
mov cx, 1 |
add eax, [bp-6] ; FAT start |
sub eax, [bp-10] |
call [read_sectors2] |
popad |
@@: |
; add new sector to the end of list |
mov bx, di |
xchg bx, [fatcachehead+2] |
push word [bx] |
pop word [di] |
mov [bx], di |
mov [di+2], bx |
; get requested item |
lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] |
pop di |
and di, 0x7F |
shl di, 2 |
shl ax, 9-4-3 |
mov ds, ax |
and byte [di+3], 0x0F |
mov eax, [di] |
pop es ds |
pop bx di |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
ret |
if $ > 0x8000 |
error 'get_next_cluster must fit in first sector of kordldr.f32!' |
end if |
load_file: |
; in: ss:bp = 0:7C00 |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
mov eax, [BPB_RootClus] ; start from root directory |
or dword [filesize], -1 ; initialize file size with invalid value |
lea si, [di+6] |
parse_dir_loop: |
; convert name to FAT name |
push di |
push ax |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
filename equ bp |
mov di, filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
nameloop: |
lodsb |
test al, al |
jz namedone |
cmp al, '/' |
jz namedone |
cmp al, '.' |
jz namedot |
dec cx |
js badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp nameloop |
namedot: |
inc bx |
jp badname |
add di, cx |
mov cl, 3 |
jmp nameloop |
badname: ; do not make direct js/jp to notfound_pop: |
; this generates long forms of conditional jumps and results in longer code |
jmp notfound_pop |
namedone: |
; scan directory |
pop ax ; eax = cluster of directory |
; high word of eax is preserved by operations above |
push ds |
push si |
; read a folder sector-by-sector and scan |
; first, try to use the cache |
push ss |
pop ds |
mov di, foldcache_mark |
xor bx, bx |
mov cx, [cachelimit] |
@@: |
lea si, [di+bx] |
mov edx, dword [foldcache_clus+si-foldcache_mark+bx] |
cmp edx, eax |
jz cacheok |
test edx, edx |
jz cacheadd ; the cache has place for new entry |
inc bx |
inc bx |
dec cx |
jns @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov bx, -2 |
mov dx, [cachelimit] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
lea si, [di+bx] |
cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
mov dword [foldcache_clus+si-foldcache_mark+bx], eax |
cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [cachelimit] |
add di, di |
cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
;mov dx, bx |
;shl dx, 8 ; dx = (position in cache)*0x2000/0x10 |
;add dx, 0x9000 |
lea dx, [bx + 0x90] |
xchg dl, dh |
mov ds, dx |
mov si, filename ; ss:si -> filename in FAT style |
call scan_for_filename |
jz lookup_done |
; cache miss, read folder data from disk |
mov bx, cx |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
folder_next_cluster: |
; internal loop: scan sectors in cluster |
push eax |
call cluster2sector |
folder_next_sector: |
; skip first bx sectors |
dec bx |
jns folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
push eax |
call [read_sectors2] |
pop eax |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
pusha |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache |
popa |
@@: |
push es |
mov cl, 0x10 ; ch=0 at this point |
call scan_for_filename |
pop es |
pop cx |
jz lookup_done_pop |
folder_skip_sector: |
inc eax |
loop folder_next_sector |
pop eax ; eax = current cluster |
call get_next_cluster |
jc folder_next_cluster |
stc |
push eax |
lookup_done_pop: |
pop eax |
lookup_done: |
pop si |
; CF=1 <=> failed |
jnc found |
pop ds |
notfound: |
pop di |
notfound2: |
mov bx, 2 ; file not found |
mov ax, 0xFFFF |
mov dx, ax ; invalid file size |
ret |
notfound_pop: |
pop ax |
jmp notfound |
found: |
mov eax, [di+20-2] |
mov edx, [di+28] |
mov ax, [di+26] ; get cluster |
test byte [di+11], 10h ; directory? |
pop ds |
pop di |
jz regular_file |
cmp byte [si-1], 0 |
jz notfound2 ; don't read directories as regular files |
; ok, we have found a directory and the caller requested a file into it |
jmp parse_dir_loop ; restart with new cluster in ax |
regular_file: |
cmp byte [si-1], 0 |
jnz notfound2 ; file does not contain another files |
; ok, we have found a regular file and the caller requested it |
; save file size |
mov [filesize], edx |
mov si, [di+4] ; [ds:di+4] = limit in 4K blocks |
shl si, 3 |
push si |
les bx, [di] ; es:bx -> buffer |
clusloop: |
; eax = first cluster, top of stack contains limit in sectors |
mov esi, eax ; remember current cluster |
xor ecx, ecx ; ecx will contain number of consecutive clusters |
mov [cur_delta], ecx |
mov edi, eax |
clusfind: |
inc edi |
inc ecx |
call get_next_cluster |
jnc clusread |
cmp eax, edi |
jz clusfind |
stc |
clusread: |
pop di ; limit in sectors |
movzx edi, di |
push eax ; save next cluster |
pushf ; save flags |
; read cx clusters, starting from si |
; calculate number of sectors |
xchg eax, ecx |
call clustersz2sectorsz |
mov [num_sectors], eax |
jmp @f |
continue_load_file: |
les bx, [di] ; es:bx -> buffer |
movzx edi, word [di+4] ; di = limit in 4K blocks |
shl di, 3 ; now di = limit in sectors |
mov eax, [num_sectors] |
mov esi, [cur_cluster] |
push [next_cluster] |
push [flags] |
test eax, eax |
jz nextclus |
@@: |
; eax = number of sectors; compare with limit |
cmp eax, edi |
seta dl |
push dx ; limit was exceeded? |
jbe @f |
mov eax, edi |
@@: |
sub di, ax ; calculate new limit |
sub [num_sectors], eax |
mov [cur_cluster], esi |
; calculate starting sector |
push ax |
xchg eax, esi |
call cluster2sector |
pop cx |
add eax, [cur_delta] |
add [cur_delta], ecx |
; read |
call [read_sectors2] |
pop dx |
; next cluster? |
nextclus: |
popf |
pop eax |
mov [next_cluster], eax |
pushf |
pop [flags] |
jnc @f ; no next cluster => return |
mov dl, 1 |
test di, di |
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded |
push di |
jmp clusloop ; all is ok, continue |
hooked_err: |
mov sp, 7C00h-14-2 ; restore stack |
mov dl, 3 ; return: read error |
@@: |
mov bl, dl |
mov bh, 0 |
mov ax, [filesize] |
mov dx, [filesize+2] |
ret |
scan_for_filename: |
; in: ss:si -> 11-bytes FAT name |
; in: ds:0 -> part of directory data |
; in: cx = number of entries |
; in: bh = 0 |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
push ds |
pop es |
xor di, di |
push cx |
jcxz snoent |
sloop: |
cmp byte [di], bh |
jz snotfound |
test byte [di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmps byte [ss:si], byte [es:di] |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
snoent: |
inc cx ; clear ZF flag |
snotfound: |
stc |
sdone: |
pop cx |
lrdret: |
ret |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 7C00h-10 |
mov bp, 7C00h |
push dx |
push cx |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
; function 2: continue loading file |
; can be called only after function 1 returned value bx=1 (only part of file was loaded) |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
callback_ret_succ: |
clc ; function is supported |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kernel.mnt',0 |
aKernelNotFound db 'Fatal error: cannot load the kernel',0 |
;if $ > 0x8200 |
;error 'total size of kordldr.f32 must not exceed 1024 bytes!' |
;end if |
;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache |
;foldcache_mark dw 0 |
; rw 7 |
;foldcache_size rw 8 |
foldcache_clus rd 8 |
foldcache_mark rw 8 |
foldcache_size rw 8 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/floppy1440.inc |
---|
1,19 → 1,19 |
BS_OEMName db 'KOLIBRI ' ; db 8 |
BPB_BytsPerSec dw 512 ; bytes per sector |
BPB_SecPerClus db 1 ; sectors per cluster |
BPB_RsvdSecCnt dw 1 ; number of reserver sectors |
BPB_NumFATs db 2 ; count of FAT data structures |
BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors) |
BPB_TotSec16 dw 2880 ; count of sectors on the volume (2880 for 1.44 mbytes disk) |
BPB_Media db 0f0h ; f0 - used for removable media |
BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT |
BPB_SecPerTrk dw 18 ; sectors per track |
BPB_NumHeads dw 2 ; number of heads |
BPB_HiddSec dd 0 ; count of hidden sectors |
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) |
BS_DrvNum db 0 ; int 13h drive number |
BS_Reserved db 0 ; reserved |
BS_BootSig db 29h ; Extended boot signature |
BS_VolID dd 0 ; Volume serial number |
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) |
BS_FilSysType db 'FAT12 ' ; file system type (db 8) |
BS_OEMName db 'KOLIBRI ' ; db 8 |
BPB_BytsPerSec dw 512 ; bytes per sector |
BPB_SecPerClus db 1 ; sectors per cluster |
BPB_RsvdSecCnt dw 1 ; number of reserver sectors |
BPB_NumFATs db 2 ; count of FAT data structures |
BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors) |
BPB_TotSec16 dw 2880 ; count of sectors on the volume (2880 for 1.44 mbytes disk) |
BPB_Media db 0f0h ; f0 - used for removable media |
BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT |
BPB_SecPerTrk dw 18 ; sectors per track |
BPB_NumHeads dw 2 ; number of heads |
BPB_HiddSec dd 0 ; count of hidden sectors |
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) |
BS_DrvNum db 0 ; int 13h drive number |
BS_Reserved db 0 ; reserved |
BS_BootSig db 29h ; Extended boot signature |
BS_VolID dd 0 ; Volume serial number |
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) |
BS_FilSysType db 'FAT12 ' ; file system type (db 8) |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/floppy1680.inc |
---|
1,19 → 1,19 |
BS_OEMName db 'KOLIBRI ' ; db 8 |
BPB_BytsPerSec dw 512 ; bytes per sector |
BPB_SecPerClus db 1 ; sectors per cluster |
BPB_RsvdSecCnt dw 1 ; number of reserver sectors |
BPB_NumFATs db 2 ; count of FAT data structures |
BPB_RootEntCnt dw 112 ; count of 32-byte dir. entries (112*32 = 7 sectors) |
BPB_TotSec16 dw 3360 ; count of sectors on the volume (3360 for 1.68 mbytes disk) |
BPB_Media db 0f0h ; f0 - used for removable media |
BPB_FATSz16 dw 10 ; count of sectors by one copy of FAT |
BPB_SecPerTrk dw 21 ; sectors per track |
BPB_NumHeads dw 2 ; number of heads |
BPB_HiddSec dd 0 ; count of hidden sectors |
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) |
BS_DrvNum db 0 ; int 13h drive number |
BS_Reserved db 0 ; reserved |
BS_BootSig db 29h ; Extended boot signature |
BS_VolID dd 0 ; Volume serial number |
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) |
BS_FilSysType db 'FAT12 ' ; file system type (db 8) |
BS_OEMName db 'KOLIBRI ' ; db 8 |
BPB_BytsPerSec dw 512 ; bytes per sector |
BPB_SecPerClus db 1 ; sectors per cluster |
BPB_RsvdSecCnt dw 1 ; number of reserver sectors |
BPB_NumFATs db 2 ; count of FAT data structures |
BPB_RootEntCnt dw 112 ; count of 32-byte dir. entries (112*32 = 7 sectors) |
BPB_TotSec16 dw 3360 ; count of sectors on the volume (3360 for 1.68 mbytes disk) |
BPB_Media db 0f0h ; f0 - used for removable media |
BPB_FATSz16 dw 10 ; count of sectors by one copy of FAT |
BPB_SecPerTrk dw 21 ; sectors per track |
BPB_NumHeads dw 2 ; number of heads |
BPB_HiddSec dd 0 ; count of hidden sectors |
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) |
BS_DrvNum db 0 ; int 13h drive number |
BS_Reserved db 0 ; reserved |
BS_BootSig db 29h ; Extended boot signature |
BS_VolID dd 0 ; Volume serial number |
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) |
BS_FilSysType db 'FAT12 ' ; file system type (db 8) |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/floppy1743.inc |
---|
1,19 → 1,19 |
BS_OEMName db 'KOLIBRI ' ; db 8 |
BPB_BytsPerSec dw 512 ; bytes per sector |
BPB_SecPerClus db 1 ; sectors per cluster |
BPB_RsvdSecCnt dw 1 ; number of reserver sectors |
BPB_NumFATs db 2 ; count of FAT data structures |
BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors) |
BPB_TotSec16 dw 3486 ; count of sectors on the volume (3486 for 1.74 mbytes disk) |
BPB_Media db 0f0h ; f0 - used for removable media |
BPB_FATSz16 dw 11 ; count of sectors by one copy of FAT |
BPB_SecPerTrk dw 21 ; sectors per track |
BPB_NumHeads dw 2 ; number of heads |
BPB_HiddSec dd 0 ; count of hidden sectors |
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) |
BS_DrvNum db 0 ; int 13h drive number |
BS_Reserved db 0 ; reserved |
BS_BootSig db 29h ; Extended boot signature |
BS_VolID dd 0 ; Volume serial number |
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) |
BS_FilSysType db 'FAT12 ' ; file system type (db 8) |
BS_OEMName db 'KOLIBRI ' ; db 8 |
BPB_BytsPerSec dw 512 ; bytes per sector |
BPB_SecPerClus db 1 ; sectors per cluster |
BPB_RsvdSecCnt dw 1 ; number of reserver sectors |
BPB_NumFATs db 2 ; count of FAT data structures |
BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors) |
BPB_TotSec16 dw 3486 ; count of sectors on the volume (3486 for 1.74 mbytes disk) |
BPB_Media db 0f0h ; f0 - used for removable media |
BPB_FATSz16 dw 11 ; count of sectors by one copy of FAT |
BPB_SecPerTrk dw 21 ; sectors per track |
BPB_NumHeads dw 2 ; number of heads |
BPB_HiddSec dd 0 ; count of hidden sectors |
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) |
BS_DrvNum db 0 ; int 13h drive number |
BS_Reserved db 0 ; reserved |
BS_BootSig db 29h ; Extended boot signature |
BS_VolID dd 0 ; Volume serial number |
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) |
BS_FilSysType db 'FAT12 ' ; file system type (db 8) |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bootloader/floppy2880.inc |
---|
1,19 → 1,19 |
BS_OEMName db 'KOLIBRI ' ; db 8 |
BPB_BytsPerSec dw 512 ; bytes per sector |
BPB_SecPerClus db 2 ; sectors per cluster |
BPB_RsvdSecCnt dw 1 ; number of reserver sectors |
BPB_NumFATs db 2 ; count of FAT data structures |
BPB_RootEntCnt dw 240 ; count of 32-byte dir. entries (240*32 = 15 sectors) |
BPB_TotSec16 dw 5760 ; count of sectors on the volume (5760 for 2.88 mbytes disk) |
BPB_Media db 0f0h ; f0 - used for removable media |
BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT |
BPB_SecPerTrk dw 36 ; sectors per track |
BPB_NumHeads dw 2 ; number of heads |
BPB_HiddSec dd 0 ; count of hidden sectors |
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) |
BS_DrvNum db 0 ; int 13h drive number |
BS_Reserved db 0 ; reserved |
BS_BootSig db 29h ; Extended boot signature |
BS_VolID dd 0 ; Volume serial number |
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) |
BS_FilSysType db 'FAT12 ' ; file system type (db 8) |
BS_OEMName db 'KOLIBRI ' ; db 8 |
BPB_BytsPerSec dw 512 ; bytes per sector |
BPB_SecPerClus db 2 ; sectors per cluster |
BPB_RsvdSecCnt dw 1 ; number of reserver sectors |
BPB_NumFATs db 2 ; count of FAT data structures |
BPB_RootEntCnt dw 240 ; count of 32-byte dir. entries (240*32 = 15 sectors) |
BPB_TotSec16 dw 5760 ; count of sectors on the volume (5760 for 2.88 mbytes disk) |
BPB_Media db 0f0h ; f0 - used for removable media |
BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT |
BPB_SecPerTrk dw 36 ; sectors per track |
BPB_NumHeads dw 2 ; number of heads |
BPB_HiddSec dd 0 ; count of hidden sectors |
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) |
BS_DrvNum db 0 ; int 13h drive number |
BS_Reserved db 0 ; reserved |
BS_BootSig db 29h ; Extended boot signature |
BS_VolID dd 0 ; Volume serial number |
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) |
BS_FilSysType db 'FAT12 ' ; file system type (db 8) |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bus/pci/PCIe.inc |
---|
1,119 → 1,119 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) 2010 KolibriOS team. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; PCIe.INC ;; |
;; ;; |
;; Extended PCI express services ;; |
;; ;; |
;; art_zh <artem@jerdev.co.uk> ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision: 1463 $ |
;*************************************************************************** |
; Function |
; pci_ext_config: |
; |
; Description |
; PCIe extended (memory-mapped) config space detection |
; |
; WARNINGs: |
; 1) Very Experimental! |
; 2) direct HT-detection (no ACPI or BIOS service used) |
; 3) Only AMD/HT processors currently supported |
; |
;*************************************************************************** |
PCIe_CONFIG_SPACE equ 0xF0000000 ; to be moved to const.inc |
mmio_pcie_cfg_addr dd 0x0 ; intel pcie space may be defined here |
mmio_pcie_cfg_lim dd 0x0 ; upper pcie space address |
align 4 |
pci_ext_config: |
mov ebx, [mmio_pcie_cfg_addr] |
or ebx,ebx |
jz @f |
or ebx, 0x7FFFFFFF ; required by PCI-SIG standards |
jnz .pcie_failed |
add ebx, 0x0FFFFC |
cmp ebx, [mmio_pcie_cfg_lim]; is the space limit correct? |
ja .pcie_failed |
jmp .pcie_cfg_mapped |
@@: |
mov ebx, [cpu_vendor] |
cmp ebx, dword [AMD_str] |
jne .pcie_failed |
mov bx, 0xC184 ; dev = 24, fn = 01, reg = 84h |
.check_HT_mmio: |
mov cx, bx |
mov ax, 0x0002 ; bus = 0, 1dword to read |
call pci_read_reg |
mov bx, cx |
sub bl, 4 |
and al, 0x80 ; check the NP bit |
jz .no_pcie_cfg |
shl eax, 8 ; bus:[27..20], dev:[19:15] |
or eax, 0x00007FFC ; fun:[14..12], reg:[11:2] |
mov [mmio_pcie_cfg_lim], eax |
mov cl, bl |
mov ax, 0x0002 ; bus = 0, 1dword to read |
call pci_read_reg |
mov bx, cx |
test al, 0x03 ; MMIO Base RW enabled? |
jz .no_pcie_cfg |
test al, 0x0C ; MMIO Base locked? |
jnz .no_pcie_cfg |
xor al, al |
shl eax, 8 |
test eax, 0x000F0000 ; MMIO Base must be bus0-aligned |
jnz .no_pcie_cfg |
mov [mmio_pcie_cfg_addr], eax |
add eax, 0x000FFFFC |
sub eax,[mmio_pcie_cfg_lim] ; MMIO must cover at least one bus |
ja .no_pcie_cfg |
; -- it looks like a true PCIe config space; |
mov eax,[mmio_pcie_cfg_addr] ; physical address |
or eax, (PG_SHARED + PG_LARGE + PG_USER) |
mov ebx, PCIe_CONFIG_SPACE ; linear address |
mov ecx, ebx |
shr ebx, 20 |
add ebx, sys_pgdir ; PgDir entry @ |
@@: |
mov dword[ebx], eax ; map 4 buses |
invlpg [ecx] |
cmp bl, 4 |
jz .pcie_cfg_mapped ; fix it later |
add bl, 4 ; next PgDir entry |
add eax, 0x400000 ; eax += 4M |
add ecx, 0x400000 |
jmp @b |
.pcie_cfg_mapped: |
; -- glad to have the extended PCIe config field found |
; mov esi, boot_pcie_ok |
; call boot_log |
ret ; <<<<<<<<<<< OK >>>>>>>>>>> |
.no_pcie_cfg: |
xor eax, eax |
mov [mmio_pcie_cfg_addr], eax |
mov [mmio_pcie_cfg_lim], eax |
add bl, 12 |
cmp bl, 0xC0 ; MMIO regs lay below this offset |
jb .check_HT_mmio |
.pcie_failed: |
; mov esi, boot_pcie_fail |
; call boot_log |
ret ; <<<<<<<<< FAILURE >>>>>>>>> |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) 2010 KolibriOS team. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; PCIe.INC ;; |
;; ;; |
;; Extended PCI express services ;; |
;; ;; |
;; art_zh <artem@jerdev.co.uk> ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision: 1463 $ |
;*************************************************************************** |
; Function |
; pci_ext_config: |
; |
; Description |
; PCIe extended (memory-mapped) config space detection |
; |
; WARNINGs: |
; 1) Very Experimental! |
; 2) direct HT-detection (no ACPI or BIOS service used) |
; 3) Only AMD/HT processors currently supported |
; |
;*************************************************************************** |
PCIe_CONFIG_SPACE equ 0xF0000000 ; to be moved to const.inc |
mmio_pcie_cfg_addr dd 0x0 ; intel pcie space may be defined here |
mmio_pcie_cfg_lim dd 0x0 ; upper pcie space address |
align 4 |
pci_ext_config: |
mov ebx, [mmio_pcie_cfg_addr] |
or ebx, ebx |
jz @f |
or ebx, 0x7FFFFFFF ; required by PCI-SIG standards |
jnz .pcie_failed |
add ebx, 0x0FFFFC |
cmp ebx, [mmio_pcie_cfg_lim]; is the space limit correct? |
ja .pcie_failed |
jmp .pcie_cfg_mapped |
@@: |
mov ebx, [cpu_vendor] |
cmp ebx, dword [AMD_str] |
jne .pcie_failed |
mov bx, 0xC184 ; dev = 24, fn = 01, reg = 84h |
.check_HT_mmio: |
mov cx, bx |
mov ax, 0x0002 ; bus = 0, 1dword to read |
call pci_read_reg |
mov bx, cx |
sub bl, 4 |
and al, 0x80 ; check the NP bit |
jz .no_pcie_cfg |
shl eax, 8 ; bus:[27..20], dev:[19:15] |
or eax, 0x00007FFC ; fun:[14..12], reg:[11:2] |
mov [mmio_pcie_cfg_lim], eax |
mov cl, bl |
mov ax, 0x0002 ; bus = 0, 1dword to read |
call pci_read_reg |
mov bx, cx |
test al, 0x03 ; MMIO Base RW enabled? |
jz .no_pcie_cfg |
test al, 0x0C ; MMIO Base locked? |
jnz .no_pcie_cfg |
xor al, al |
shl eax, 8 |
test eax, 0x000F0000 ; MMIO Base must be bus0-aligned |
jnz .no_pcie_cfg |
mov [mmio_pcie_cfg_addr], eax |
add eax, 0x000FFFFC |
sub eax, [mmio_pcie_cfg_lim]; MMIO must cover at least one bus |
ja .no_pcie_cfg |
; -- it looks like a true PCIe config space; |
mov eax, [mmio_pcie_cfg_addr] ; physical address |
or eax, (PG_SHARED + PG_LARGE + PG_USER) |
mov ebx, PCIe_CONFIG_SPACE ; linear address |
mov ecx, ebx |
shr ebx, 20 |
add ebx, sys_pgdir ; PgDir entry @ |
@@: |
mov dword[ebx], eax ; map 4 buses |
invlpg [ecx] |
cmp bl, 4 |
jz .pcie_cfg_mapped ; fix it later |
add bl, 4 ; next PgDir entry |
add eax, 0x400000 ; eax += 4M |
add ecx, 0x400000 |
jmp @b |
.pcie_cfg_mapped: |
; -- glad to have the extended PCIe config field found |
; mov esi, boot_pcie_ok |
; call boot_log |
ret ; <<<<<<<<<<< OK >>>>>>>>>>> |
.no_pcie_cfg: |
xor eax, eax |
mov [mmio_pcie_cfg_addr], eax |
mov [mmio_pcie_cfg_lim], eax |
add bl, 12 |
cmp bl, 0xC0 ; MMIO regs lay below this offset |
jb .check_HT_mmio |
.pcie_failed: |
; mov esi, boot_pcie_fail |
; call boot_log |
ret ; <<<<<<<<< FAILURE >>>>>>>>> |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bus/pci/pci16.inc |
---|
1,51 → 1,51 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; PCI16.INC ;; |
;; ;; |
;; 16 bit PCI driver code ;; |
;; ;; |
;; Version 0.2 December 21st, 2002 ;; |
;; ;; |
;; Author: Victor Prodan, victorprodan@yahoo.com ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
init_pci_16: |
pushad |
xor ax,ax |
mov es,ax |
mov byte [es:0x9020],1 ;default mechanism:1 |
mov ax,0xb101 |
int 0x1a |
or ah,ah |
jnz pci16skip |
mov [es:0x9021],cl ;last PCI bus in system |
mov [es:0x9022],bx |
mov [es:0x9024],edi |
; we have a PCI BIOS, so check which configuration mechanism(s) |
; it supports |
; AL = PCI hardware characteristics (bit0 => mechanism1, bit1 => mechanism2) |
test al,1 |
jnz pci16skip |
test al,2 |
jz pci16skip |
mov byte [es:0x9020],2 ; if (al&3)==2 => mechanism 2 |
pci16skip: |
mov ax,0x1000 |
mov es,ax |
popad |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; PCI16.INC ;; |
;; ;; |
;; 16 bit PCI driver code ;; |
;; ;; |
;; Version 0.2 December 21st, 2002 ;; |
;; ;; |
;; Author: Victor Prodan, victorprodan@yahoo.com ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
init_pci_16: |
pushad |
xor ax, ax |
mov es, ax |
mov byte [es:0x9020], 1;default mechanism:1 |
mov ax, 0xb101 |
int 0x1a |
or ah, ah |
jnz pci16skip |
mov [es:0x9021], cl;last PCI bus in system |
mov [es:0x9022], bx |
mov [es:0x9024], edi |
; we have a PCI BIOS, so check which configuration mechanism(s) |
; it supports |
; AL = PCI hardware characteristics (bit0 => mechanism1, bit1 => mechanism2) |
test al, 1 |
jnz pci16skip |
test al, 2 |
jz pci16skip |
mov byte [es:0x9020], 2; if (al&3)==2 => mechanism 2 |
pci16skip: |
mov ax, 0x1000 |
mov es, ax |
popad |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/bus/pci/pci32.inc |
---|
1,654 → 1,660 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; PCI32.INC ;; |
;; ;; |
;; 32 bit PCI driver code ;; |
;; ;; |
;; Version 0.3 April 9, 2007 ;; |
;; Version 0.2 December 21st, 2002 ;; |
;; ;; |
;; Author: Victor Prodan, victorprodan@yahoo.com ;; |
;; Mihailov Ilia, ghost.nsk@gmail.com ;; |
;; Credits: ;; |
;; Ralf Brown ;; |
;; Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;*************************************************************************** |
; Function |
; pci_api: |
; |
; Description |
; entry point for system PCI calls |
;*************************************************************************** |
;mmio_pci_addr equ 0x400 ; set actual PCI address here to activate user-MMIO |
iglobal |
align 4 |
f62call: |
dd pci_fn_0 |
dd pci_fn_1 |
dd pci_fn_2 |
dd pci_service_not_supported ;3 |
dd pci_read_reg ;4 byte |
dd pci_read_reg ;5 word |
dd pci_read_reg ;6 dword |
dd pci_service_not_supported ;7 |
dd pci_write_reg ;8 byte |
dd pci_write_reg ;9 word |
dd pci_write_reg ;10 dword |
if defined mmio_pci_addr |
dd pci_mmio_init ;11 |
dd pci_mmio_map ;12 |
dd pci_mmio_unmap ;13 |
end if |
endg |
align 4 |
pci_api: |
;cross |
mov eax,ebx |
mov ebx,ecx |
mov ecx,edx |
cmp [pci_access_enabled],1 |
jne pci_service_not_supported |
movzx edx, al |
if defined mmio_pci_addr |
cmp al, 13 |
ja pci_service_not_supported |
else |
cmp al, 10 |
ja pci_service_not_supported |
end if |
call dword [f62call+edx*4] |
mov dword [esp+32],eax |
ret |
align 4 |
pci_api_drv: |
cmp [pci_access_enabled],1 |
jne .fail |
cmp eax, 2 |
ja .fail |
jmp dword [f62call+eax*4] |
.fail: |
or eax,-1 |
ret |
;; ============================================ |
pci_fn_0: |
; PCI function 0: get pci version (AH.AL) |
movzx eax,word [BOOT_VAR+0x9022] |
ret |
pci_fn_1: |
; PCI function 1: get last bus in AL |
mov al,[BOOT_VAR+0x9021] |
ret |
pci_fn_2: |
; PCI function 2: get pci access mechanism |
mov al,[BOOT_VAR+0x9020] |
ret |
pci_service_not_supported: |
or eax,-1 |
mov dword [esp+32],eax |
ret |
;*************************************************************************** |
; Function |
; pci_make_config_cmd |
; |
; Description |
; creates a command dword for use with the PCI bus |
; bus # in ah |
; device+func in bh (dddddfff) |
; register in bl |
; |
; command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 ) |
;*************************************************************************** |
align 4 |
pci_make_config_cmd: |
shl eax,8 ; move bus to bits 16-23 |
mov ax,bx ; combine all |
and eax,0xffffff |
or eax,0x80000000 |
ret |
;*************************************************************************** |
; Function |
; pci_read_reg: |
; |
; Description |
; read a register from the PCI config space into EAX/AX/AL |
; IN: ah=bus,device+func=bh,register address=bl |
; number of bytes to read (1,2,4) coded into AL, bits 0-1 |
; (0 - byte, 1 - word, 2 - dword) |
;*************************************************************************** |
align 4 |
pci_read_reg: |
cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? |
je pci_read_reg_2 |
; mechanism 1 |
push esi ; save register size into ESI |
mov esi,eax |
and esi,3 |
call pci_make_config_cmd |
mov ebx,eax |
; get current state |
mov dx,0xcf8 |
in eax, dx |
push eax |
; set up addressing to config data |
mov eax,ebx |
and al,0xfc ; make address dword-aligned |
out dx,eax |
; get requested DWORD of config data |
mov dl,0xfc |
and bl,3 |
or dl,bl ; add to port address first 2 bits of register address |
or esi,esi |
jz pci_read_byte1 |
cmp esi,1 |
jz pci_read_word1 |
cmp esi,2 |
jz pci_read_dword1 |
jmp pci_fin_read1 |
pci_read_byte1: |
in al,dx |
jmp pci_fin_read1 |
pci_read_word1: |
in ax,dx |
jmp pci_fin_read1 |
pci_read_dword1: |
in eax,dx |
jmp pci_fin_read1 |
pci_fin_read1: |
; restore configuration control |
xchg eax,[esp] |
mov dx,0xcf8 |
out dx,eax |
pop eax |
pop esi |
ret |
pci_read_reg_2: |
test bh,128 ;mech#2 only supports 16 devices per bus |
jnz pci_read_reg_err |
push esi ; save register size into ESI |
mov esi,eax |
and esi,3 |
push eax |
;store current state of config space |
mov dx,0xcf8 |
in al,dx |
mov ah,al |
mov dl,0xfa |
in al,dx |
xchg eax,[esp] |
; out 0xcfa,bus |
mov al,ah |
out dx,al |
; out 0xcf8,0x80 |
mov dl,0xf8 |
mov al,0x80 |
out dx,al |
; compute addr |
shr bh,3 ; func is ignored in mechanism 2 |
or bh,0xc0 |
mov dx,bx |
or esi,esi |
jz pci_read_byte2 |
cmp esi,1 |
jz pci_read_word2 |
cmp esi,2 |
jz pci_read_dword2 |
jmp pci_fin_read2 |
pci_read_byte2: |
in al,dx |
jmp pci_fin_read2 |
pci_read_word2: |
in ax,dx |
jmp pci_fin_read2 |
pci_read_dword2: |
in eax,dx |
; jmp pci_fin_read2 |
pci_fin_read2: |
; restore configuration space |
xchg eax,[esp] |
mov dx,0xcfa |
out dx,al |
mov dl,0xf8 |
mov al,ah |
out dx,al |
pop eax |
pop esi |
ret |
pci_read_reg_err: |
xor eax,eax |
dec eax |
ret |
;*************************************************************************** |
; Function |
; pci_write_reg: |
; |
; Description |
; write a register from ECX/CX/CL into the PCI config space |
; IN: ah=bus,device+func=bh,register address (dword aligned)=bl, |
; value to write in ecx |
; number of bytes to write (1,2,4) coded into AL, bits 0-1 |
; (0 - byte, 1 - word, 2 - dword) |
;*************************************************************************** |
align 4 |
pci_write_reg: |
cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? |
je pci_write_reg_2 |
; mechanism 1 |
push esi ; save register size into ESI |
mov esi,eax |
and esi,3 |
call pci_make_config_cmd |
mov ebx,eax |
; get current state into ecx |
mov dx,0xcf8 |
in eax, dx |
push eax |
; set up addressing to config data |
mov eax,ebx |
and al,0xfc ; make address dword-aligned |
out dx,eax |
; write DWORD of config data |
mov dl,0xfc |
and bl,3 |
or dl,bl |
mov eax,ecx |
or esi,esi |
jz pci_write_byte1 |
cmp esi,1 |
jz pci_write_word1 |
cmp esi,2 |
jz pci_write_dword1 |
jmp pci_fin_write1 |
pci_write_byte1: |
out dx,al |
jmp pci_fin_write1 |
pci_write_word1: |
out dx,ax |
jmp pci_fin_write1 |
pci_write_dword1: |
out dx,eax |
jmp pci_fin_write1 |
pci_fin_write1: |
; restore configuration control |
pop eax |
mov dl,0xf8 |
out dx,eax |
xor eax,eax |
pop esi |
ret |
pci_write_reg_2: |
test bh,128 ;mech#2 only supports 16 devices per bus |
jnz pci_write_reg_err |
push esi ; save register size into ESI |
mov esi,eax |
and esi,3 |
push eax |
;store current state of config space |
mov dx,0xcf8 |
in al,dx |
mov ah,al |
mov dl,0xfa |
in al,dx |
xchg eax,[esp] |
; out 0xcfa,bus |
mov al,ah |
out dx,al |
; out 0xcf8,0x80 |
mov dl,0xf8 |
mov al,0x80 |
out dx,al |
; compute addr |
shr bh,3 ; func is ignored in mechanism 2 |
or bh,0xc0 |
mov dx,bx |
; write register |
mov eax,ecx |
or esi,esi |
jz pci_write_byte2 |
cmp esi,1 |
jz pci_write_word2 |
cmp esi,2 |
jz pci_write_dword2 |
jmp pci_fin_write2 |
pci_write_byte2: |
out dx,al |
jmp pci_fin_write2 |
pci_write_word2: |
out dx,ax |
jmp pci_fin_write2 |
pci_write_dword2: |
out dx,eax |
jmp pci_fin_write2 |
pci_fin_write2: |
; restore configuration space |
pop eax |
mov dx,0xcfa |
out dx,al |
mov dl,0xf8 |
mov al,ah |
out dx,al |
xor eax,eax |
pop esi |
ret |
pci_write_reg_err: |
xor eax,eax |
dec eax |
ret |
if defined mmio_pci_addr ; must be set above |
;*************************************************************************** |
; Function |
; pci_mmio_init |
; |
; Description |
; IN: bx = device's PCI bus address (bbbbbbbbdddddfff) |
; Returns eax = user heap space available (bytes) |
; Error codes |
; eax = -1 : PCI user access blocked, |
; eax = -2 : device not registered for uMMIO service |
; eax = -3 : user heap initialization failure |
;*************************************************************************** |
pci_mmio_init: |
cmp bx, mmio_pci_addr |
jz @f |
mov eax,-2 |
ret |
@@: |
call init_heap ; (if not initialized yet) |
or eax,eax |
jz @f |
ret |
@@: |
mov eax,-3 |
ret |
;*************************************************************************** |
; Function |
; pci_mmio_map |
; |
; Description |
; maps a block of PCI memory to user-accessible linear address |
; |
; WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only! |
; The target device address should be set in kernel var mmio_pci_addr |
; |
; IN: ah = BAR#; |
; IN: ebx = block size (bytes); |
; IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages); |
; |
; Returns eax = MMIO block's linear address in the userspace (if no error) |
; |
; |
; Error codes |
; eax = -1 : user access to PCI blocked, |
; eax = -2 : an invalid BAR register referred |
; eax = -3 : no i/o space on that BAR |
; eax = -4 : a port i/o BAR register referred |
; eax = -5 : dynamic userspace allocation problem |
;*************************************************************************** |
pci_mmio_map: |
and edx,0x0ffff |
cmp ah,6 |
jc .bar_0_5 |
jz .bar_rom |
mov eax,-2 |
ret |
.bar_rom: |
mov ah, 8 ; bar6 = Expansion ROM base address |
.bar_0_5: |
push ecx |
add ebx, 4095 |
and ebx,-4096 |
push ebx |
mov bl, ah ; bl = BAR# (0..5), however bl=8 for BAR6 |
shl bl, 1 |
shl bl, 1 |
add bl, 0x10 ; now bl = BAR offset in PCI config. space |
mov ax, mmio_pci_addr |
mov bh, al ; bh = dddddfff |
mov al, 2 ; al : DW to read |
call pci_read_reg |
or eax, eax |
jnz @f |
mov eax,-3 ; empty I/O space |
jmp mmio_ret_fail |
@@: |
test eax, 1 |
jz @f |
mov eax,-4 ; damned ports (not MMIO space) |
jmp mmio_ret_fail |
@@: |
pop ecx ; ecx = block size, bytes (expanded to whole page) |
mov ebx, ecx ; user_alloc destroys eax, ecx, edx, but saves ebx |
and eax, 0xFFFFFFF0 |
push eax ; store MMIO physical address + keep 2DWords in the stack |
stdcall user_alloc, ecx |
or eax, eax |
jnz mmio_map_over |
mov eax,-5 ; problem with page allocation |
mmio_ret_fail: |
pop ecx |
pop edx |
ret |
mmio_map_over: |
mov ecx, ebx ; ecx = size (bytes, expanded to whole page) |
shr ecx, 12 ; ecx = number of pages |
mov ebx, eax ; ebx = linear address |
pop eax ; eax = MMIO start |
pop edx ; edx = MMIO shift (pages) |
shl edx, 12 ; edx = MMIO shift (bytes) |
add eax, edx ; eax = uMMIO physical address |
or eax, PG_SHARED |
or eax, PG_UW |
or eax, PG_NOCACHE |
mov edi, ebx |
call commit_pages |
mov eax, edi |
ret |
;*************************************************************************** |
; Function |
; pci_mmio_unmap_page |
; |
; Description |
; unmaps the linear space previously tied to a PCI memory block |
; |
; IN: ebx = linear address of space previously allocated by pci_mmio_map |
; returns eax = 1 if successfully unmapped |
; |
; Error codes |
; eax = -1 if no user PCI access allowed, |
; eax = 0 if unmapping failed |
;*************************************************************************** |
pci_mmio_unmap: |
stdcall user_free, ebx |
ret |
end if |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
uglobal |
align 4 |
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1) |
pci_emu_dat: times 30*10 db 0 |
endg |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
align 4 |
sys_pcibios: |
cmp [pci_access_enabled], 1 |
jne .unsupported_func |
cmp [pci_bios_entry], 0 |
jz .emulate_bios |
push ds |
mov ax, pci_data_sel |
mov ds, ax |
mov eax, ebp |
mov ah, 0B1h |
call pword [cs:pci_bios_entry] |
pop ds |
jmp .return |
;-=-=-=-=-=-=-=-= |
.emulate_bios: |
cmp ebp, 1 ; PCI_FUNCTION_ID |
jnz .not_PCI_BIOS_PRESENT |
mov edx, 'PCI ' |
mov al, [BOOT_VAR + 0x9020] |
mov bx, [BOOT_VAR + 0x9022] |
mov cl, [BOOT_VAR + 0x9021] |
xor ah, ah |
jmp .return_abcd |
.not_PCI_BIOS_PRESENT: |
cmp ebp, 2 ; FIND_PCI_DEVICE |
jne .not_FIND_PCI_DEVICE |
mov ebx, pci_emu_dat |
..nxt: cmp [ebx], dx |
jne ..no |
cmp [ebx + 2], cx |
jne ..no |
dec si |
jns ..no |
mov bx, [ebx + 4] |
xor ah, ah |
jmp .return_ab |
..no: cmp word[ebx], 0 |
je ..dev_not_found |
add ebx, 10 |
jmp ..nxt |
..dev_not_found: |
mov ah, 0x86 ; DEVICE_NOT_FOUND |
jmp .return_a |
.not_FIND_PCI_DEVICE: |
cmp ebp, 3 ; FIND_PCI_CLASS_CODE |
jne .not_FIND_PCI_CLASS_CODE |
mov esi, pci_emu_dat |
shl ecx, 8 |
..nxt2: cmp [esi], ecx |
jne ..no2 |
mov bx, [esi] |
xor ah, ah |
jmp .return_ab |
..no2: cmp dword[esi], 0 |
je ..dev_not_found |
add esi, 10 |
jmp ..nxt2 |
.not_FIND_PCI_CLASS_CODE: |
cmp ebp, 8 ; READ_CONFIG_* |
jb .not_READ_CONFIG |
cmp ebp, 0x0A |
ja .not_READ_CONFIG |
mov eax, ebp |
mov ah, bh |
mov edx, edi |
mov bh, bl |
mov bl, dl |
call pci_read_reg |
mov ecx, eax |
xor ah, ah ; SUCCESSFUL |
jmp .return_abc |
.not_READ_CONFIG: |
cmp ebp, 0x0B ; WRITE_CONFIG_* |
jb .not_WRITE_CONFIG |
cmp ebp, 0x0D |
ja .not_WRITE_CONFIG |
lea eax, [ebp+1] |
mov ah, bh |
mov edx, edi |
mov bh, bl |
mov bl, dl |
call pci_write_reg |
xor ah, ah ; SUCCESSFUL |
jmp .return_abc |
.not_WRITE_CONFIG: |
.unsupported_func: |
mov ah, 0x81 ; FUNC_NOT_SUPPORTED |
.return:mov dword[esp + 4 ], edi |
mov dword[esp + 8], esi |
.return_abcd: |
mov dword[esp + 24], edx |
.return_abc: |
mov dword[esp + 28], ecx |
.return_ab: |
mov dword[esp + 20], ebx |
.return_a: |
mov dword[esp + 32], eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; PCI32.INC ;; |
;; ;; |
;; 32 bit PCI driver code ;; |
;; ;; |
;; Version 0.3 April 9, 2007 ;; |
;; Version 0.2 December 21st, 2002 ;; |
;; ;; |
;; Author: Victor Prodan, victorprodan@yahoo.com ;; |
;; Mihailov Ilia, ghost.nsk@gmail.com ;; |
;; Credits: ;; |
;; Ralf Brown ;; |
;; Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;*************************************************************************** |
; Function |
; pci_api: |
; |
; Description |
; entry point for system PCI calls |
;*************************************************************************** |
;mmio_pci_addr equ 0x400 ; set actual PCI address here to activate user-MMIO |
iglobal |
align 4 |
f62call: |
dd pci_fn_0 |
dd pci_fn_1 |
dd pci_fn_2 |
dd pci_service_not_supported ;3 |
dd pci_read_reg ;4 byte |
dd pci_read_reg ;5 word |
dd pci_read_reg ;6 dword |
dd pci_service_not_supported ;7 |
dd pci_write_reg ;8 byte |
dd pci_write_reg ;9 word |
dd pci_write_reg ;10 dword |
if defined mmio_pci_addr |
dd pci_mmio_init ;11 |
dd pci_mmio_map ;12 |
dd pci_mmio_unmap ;13 |
end if |
endg |
align 4 |
pci_api: |
;cross |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
cmp [pci_access_enabled], 1 |
jne pci_service_not_supported |
movzx edx, al |
if defined mmio_pci_addr |
cmp al, 13 |
ja pci_service_not_supported |
else |
cmp al, 10 |
ja pci_service_not_supported |
end if |
call dword [f62call+edx*4] |
mov dword [esp+32], eax |
ret |
align 4 |
pci_api_drv: |
cmp [pci_access_enabled], 1 |
jne .fail |
cmp eax, 2 |
ja .fail |
jmp dword [f62call+eax*4] |
.fail: |
or eax, -1 |
ret |
;; ============================================ |
pci_fn_0: |
; PCI function 0: get pci version (AH.AL) |
movzx eax, word [BOOT_VAR+0x9022] |
ret |
pci_fn_1: |
; PCI function 1: get last bus in AL |
mov al, [BOOT_VAR+0x9021] |
ret |
pci_fn_2: |
; PCI function 2: get pci access mechanism |
mov al, [BOOT_VAR+0x9020] |
ret |
pci_service_not_supported: |
or eax, -1 |
mov dword [esp+32], eax |
ret |
;*************************************************************************** |
; Function |
; pci_make_config_cmd |
; |
; Description |
; creates a command dword for use with the PCI bus |
; bus # in ah |
; device+func in bh (dddddfff) |
; register in bl |
; |
; command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 ) |
;*************************************************************************** |
align 4 |
pci_make_config_cmd: |
shl eax, 8 ; move bus to bits 16-23 |
mov ax, bx ; combine all |
and eax, 0xffffff |
or eax, 0x80000000 |
ret |
;*************************************************************************** |
; Function |
; pci_read_reg: |
; |
; Description |
; read a register from the PCI config space into EAX/AX/AL |
; IN: ah=bus,device+func=bh,register address=bl |
; number of bytes to read (1,2,4) coded into AL, bits 0-1 |
; (0 - byte, 1 - word, 2 - dword) |
;*************************************************************************** |
align 4 |
pci_read_reg: |
cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use? |
je pci_read_reg_2 |
; mechanism 1 |
push esi ; save register size into ESI |
mov esi, eax |
and esi, 3 |
call pci_make_config_cmd |
mov ebx, eax |
; get current state |
mov dx, 0xcf8 |
in eax, dx |
push eax |
; set up addressing to config data |
mov eax, ebx |
and al, 0xfc; make address dword-aligned |
out dx, eax |
; get requested DWORD of config data |
mov dl, 0xfc |
and bl, 3 |
or dl, bl ; add to port address first 2 bits of register address |
or esi, esi |
jz pci_read_byte1 |
cmp esi, 1 |
jz pci_read_word1 |
cmp esi, 2 |
jz pci_read_dword1 |
jmp pci_fin_read1 |
pci_read_byte1: |
in al, dx |
jmp pci_fin_read1 |
pci_read_word1: |
in ax, dx |
jmp pci_fin_read1 |
pci_read_dword1: |
in eax, dx |
jmp pci_fin_read1 |
pci_fin_read1: |
; restore configuration control |
xchg eax, [esp] |
mov dx, 0xcf8 |
out dx, eax |
pop eax |
pop esi |
ret |
pci_read_reg_2: |
test bh, 128 ;mech#2 only supports 16 devices per bus |
jnz pci_read_reg_err |
push esi; save register size into ESI |
mov esi, eax |
and esi, 3 |
push eax |
;store current state of config space |
mov dx, 0xcf8 |
in al, dx |
mov ah, al |
mov dl, 0xfa |
in al, dx |
xchg eax, [esp] |
; out 0xcfa,bus |
mov al, ah |
out dx, al |
; out 0xcf8,0x80 |
mov dl, 0xf8 |
mov al, 0x80 |
out dx, al |
; compute addr |
shr bh, 3; func is ignored in mechanism 2 |
or bh, 0xc0 |
mov dx, bx |
or esi, esi |
jz pci_read_byte2 |
cmp esi, 1 |
jz pci_read_word2 |
cmp esi, 2 |
jz pci_read_dword2 |
jmp pci_fin_read2 |
pci_read_byte2: |
in al, dx |
jmp pci_fin_read2 |
pci_read_word2: |
in ax, dx |
jmp pci_fin_read2 |
pci_read_dword2: |
in eax, dx |
; jmp pci_fin_read2 |
pci_fin_read2: |
; restore configuration space |
xchg eax, [esp] |
mov dx, 0xcfa |
out dx, al |
mov dl, 0xf8 |
mov al, ah |
out dx, al |
pop eax |
pop esi |
ret |
pci_read_reg_err: |
xor eax, eax |
dec eax |
ret |
;*************************************************************************** |
; Function |
; pci_write_reg: |
; |
; Description |
; write a register from ECX/CX/CL into the PCI config space |
; IN: ah=bus,device+func=bh,register address (dword aligned)=bl, |
; value to write in ecx |
; number of bytes to write (1,2,4) coded into AL, bits 0-1 |
; (0 - byte, 1 - word, 2 - dword) |
;*************************************************************************** |
align 4 |
pci_write_reg: |
cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use? |
je pci_write_reg_2 |
; mechanism 1 |
push esi ; save register size into ESI |
mov esi, eax |
and esi, 3 |
call pci_make_config_cmd |
mov ebx, eax |
; get current state into ecx |
mov dx, 0xcf8 |
in eax, dx |
push eax |
; set up addressing to config data |
mov eax, ebx |
and al, 0xfc; make address dword-aligned |
out dx, eax |
; write DWORD of config data |
mov dl, 0xfc |
and bl, 3 |
or dl, bl |
mov eax, ecx |
or esi, esi |
jz pci_write_byte1 |
cmp esi, 1 |
jz pci_write_word1 |
cmp esi, 2 |
jz pci_write_dword1 |
jmp pci_fin_write1 |
pci_write_byte1: |
out dx, al |
jmp pci_fin_write1 |
pci_write_word1: |
out dx, ax |
jmp pci_fin_write1 |
pci_write_dword1: |
out dx, eax |
jmp pci_fin_write1 |
pci_fin_write1: |
; restore configuration control |
pop eax |
mov dl, 0xf8 |
out dx, eax |
xor eax, eax |
pop esi |
ret |
pci_write_reg_2: |
test bh, 128 ;mech#2 only supports 16 devices per bus |
jnz pci_write_reg_err |
push esi; save register size into ESI |
mov esi, eax |
and esi, 3 |
push eax |
;store current state of config space |
mov dx, 0xcf8 |
in al, dx |
mov ah, al |
mov dl, 0xfa |
in al, dx |
xchg eax, [esp] |
; out 0xcfa,bus |
mov al, ah |
out dx, al |
; out 0xcf8,0x80 |
mov dl, 0xf8 |
mov al, 0x80 |
out dx, al |
; compute addr |
shr bh, 3; func is ignored in mechanism 2 |
or bh, 0xc0 |
mov dx, bx |
; write register |
mov eax, ecx |
or esi, esi |
jz pci_write_byte2 |
cmp esi, 1 |
jz pci_write_word2 |
cmp esi, 2 |
jz pci_write_dword2 |
jmp pci_fin_write2 |
pci_write_byte2: |
out dx, al |
jmp pci_fin_write2 |
pci_write_word2: |
out dx, ax |
jmp pci_fin_write2 |
pci_write_dword2: |
out dx, eax |
jmp pci_fin_write2 |
pci_fin_write2: |
; restore configuration space |
pop eax |
mov dx, 0xcfa |
out dx, al |
mov dl, 0xf8 |
mov al, ah |
out dx, al |
xor eax, eax |
pop esi |
ret |
pci_write_reg_err: |
xor eax, eax |
dec eax |
ret |
if defined mmio_pci_addr ; must be set above |
;*************************************************************************** |
; Function |
; pci_mmio_init |
; |
; Description |
; IN: bx = device's PCI bus address (bbbbbbbbdddddfff) |
; Returns eax = user heap space available (bytes) |
; Error codes |
; eax = -1 : PCI user access blocked, |
; eax = -2 : device not registered for uMMIO service |
; eax = -3 : user heap initialization failure |
;*************************************************************************** |
pci_mmio_init: |
cmp bx, mmio_pci_addr |
jz @f |
mov eax, -2 |
ret |
@@: |
call init_heap ; (if not initialized yet) |
or eax, eax |
jz @f |
ret |
@@: |
mov eax, -3 |
ret |
;*************************************************************************** |
; Function |
; pci_mmio_map |
; |
; Description |
; maps a block of PCI memory to user-accessible linear address |
; |
; WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only! |
; The target device address should be set in kernel var mmio_pci_addr |
; |
; IN: ah = BAR#; |
; IN: ebx = block size (bytes); |
; IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages); |
; |
; Returns eax = MMIO block's linear address in the userspace (if no error) |
; |
; |
; Error codes |
; eax = -1 : user access to PCI blocked, |
; eax = -2 : an invalid BAR register referred |
; eax = -3 : no i/o space on that BAR |
; eax = -4 : a port i/o BAR register referred |
; eax = -5 : dynamic userspace allocation problem |
;*************************************************************************** |
pci_mmio_map: |
and edx, 0x0ffff |
cmp ah, 6 |
jc .bar_0_5 |
jz .bar_rom |
mov eax, -2 |
ret |
.bar_rom: |
mov ah, 8 ; bar6 = Expansion ROM base address |
.bar_0_5: |
push ecx |
add ebx, 4095 |
and ebx, -4096 |
push ebx |
mov bl, ah ; bl = BAR# (0..5), however bl=8 for BAR6 |
shl bl, 1 |
shl bl, 1 |
add bl, 0x10; now bl = BAR offset in PCI config. space |
mov ax, mmio_pci_addr |
mov bh, al ; bh = dddddfff |
mov al, 2 ; al : DW to read |
call pci_read_reg |
or eax, eax |
jnz @f |
mov eax, -3 ; empty I/O space |
jmp mmio_ret_fail |
@@: |
test eax, 1 |
jz @f |
mov eax, -4 ; damned ports (not MMIO space) |
jmp mmio_ret_fail |
@@: |
pop ecx ; ecx = block size, bytes (expanded to whole page) |
mov ebx, ecx; user_alloc destroys eax, ecx, edx, but saves ebx |
and eax, 0xFFFFFFF0 |
push eax ; store MMIO physical address + keep 2DWords in the stack |
stdcall user_alloc, ecx |
or eax, eax |
jnz mmio_map_over |
mov eax, -5 ; problem with page allocation |
mmio_ret_fail: |
pop ecx |
pop edx |
ret |
mmio_map_over: |
mov ecx, ebx; ecx = size (bytes, expanded to whole page) |
shr ecx, 12 ; ecx = number of pages |
mov ebx, eax; ebx = linear address |
pop eax ; eax = MMIO start |
pop edx ; edx = MMIO shift (pages) |
shl edx, 12 ; edx = MMIO shift (bytes) |
add eax, edx; eax = uMMIO physical address |
or eax, PG_SHARED |
or eax, PG_UW |
or eax, PG_NOCACHE |
mov edi, ebx |
call commit_pages |
mov eax, edi |
ret |
;*************************************************************************** |
; Function |
; pci_mmio_unmap_page |
; |
; Description |
; unmaps the linear space previously tied to a PCI memory block |
; |
; IN: ebx = linear address of space previously allocated by pci_mmio_map |
; returns eax = 1 if successfully unmapped |
; |
; Error codes |
; eax = -1 if no user PCI access allowed, |
; eax = 0 if unmapping failed |
;*************************************************************************** |
pci_mmio_unmap: |
stdcall user_free, ebx |
ret |
end if |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
uglobal |
align 4 |
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1) |
pci_emu_dat: |
times 30*10 db 0 |
endg |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
align 4 |
sys_pcibios: |
cmp [pci_access_enabled], 1 |
jne .unsupported_func |
cmp [pci_bios_entry], 0 |
jz .emulate_bios |
push ds |
mov ax, pci_data_sel |
mov ds, ax |
mov eax, ebp |
mov ah, 0B1h |
call pword [cs:pci_bios_entry] |
pop ds |
jmp .return |
;-=-=-=-=-=-=-=-= |
.emulate_bios: |
cmp ebp, 1 ; PCI_FUNCTION_ID |
jnz .not_PCI_BIOS_PRESENT |
mov edx, 'PCI ' |
mov al, [BOOT_VAR + 0x9020] |
mov bx, [BOOT_VAR + 0x9022] |
mov cl, [BOOT_VAR + 0x9021] |
xor ah, ah |
jmp .return_abcd |
.not_PCI_BIOS_PRESENT: |
cmp ebp, 2 ; FIND_PCI_DEVICE |
jne .not_FIND_PCI_DEVICE |
mov ebx, pci_emu_dat |
..nxt: |
cmp [ebx], dx |
jne ..no |
cmp [ebx + 2], cx |
jne ..no |
dec si |
jns ..no |
mov bx, [ebx + 4] |
xor ah, ah |
jmp .return_ab |
..no: |
cmp word[ebx], 0 |
je ..dev_not_found |
add ebx, 10 |
jmp ..nxt |
..dev_not_found: |
mov ah, 0x86 ; DEVICE_NOT_FOUND |
jmp .return_a |
.not_FIND_PCI_DEVICE: |
cmp ebp, 3 ; FIND_PCI_CLASS_CODE |
jne .not_FIND_PCI_CLASS_CODE |
mov esi, pci_emu_dat |
shl ecx, 8 |
..nxt2: |
cmp [esi], ecx |
jne ..no2 |
mov bx, [esi] |
xor ah, ah |
jmp .return_ab |
..no2: |
cmp dword[esi], 0 |
je ..dev_not_found |
add esi, 10 |
jmp ..nxt2 |
.not_FIND_PCI_CLASS_CODE: |
cmp ebp, 8 ; READ_CONFIG_* |
jb .not_READ_CONFIG |
cmp ebp, 0x0A |
ja .not_READ_CONFIG |
mov eax, ebp |
mov ah, bh |
mov edx, edi |
mov bh, bl |
mov bl, dl |
call pci_read_reg |
mov ecx, eax |
xor ah, ah ; SUCCESSFUL |
jmp .return_abc |
.not_READ_CONFIG: |
cmp ebp, 0x0B ; WRITE_CONFIG_* |
jb .not_WRITE_CONFIG |
cmp ebp, 0x0D |
ja .not_WRITE_CONFIG |
lea eax, [ebp+1] |
mov ah, bh |
mov edx, edi |
mov bh, bl |
mov bl, dl |
call pci_write_reg |
xor ah, ah ; SUCCESSFUL |
jmp .return_abc |
.not_WRITE_CONFIG: |
.unsupported_func: |
mov ah, 0x81 ; FUNC_NOT_SUPPORTED |
.return: |
mov dword[esp + 4 ], edi |
mov dword[esp + 8], esi |
.return_abcd: |
mov dword[esp + 24], edx |
.return_abc: |
mov dword[esp + 28], ecx |
.return_ab: |
mov dword[esp + 20], ebx |
.return_a: |
mov dword[esp + 32], eax |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/const.inc |
---|
1,782 → 1,782 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
dpl0 equ 10010000b ; data read dpl0 |
drw0 equ 10010010b ; data read/write dpl0 |
drw3 equ 11110010b ; data read/write dpl3 |
cpl0 equ 10011010b ; code read dpl0 |
cpl3 equ 11111010b ; code read dpl3 |
D32 equ 01000000b ; 32bit segment |
G32 equ 10000000b ; page gran |
;;;;;;;;;;;;cpu_caps flags;;;;;;;;;;;;;;;; |
CPU_386 equ 3 |
CPU_486 equ 4 |
CPU_PENTIUM equ 5 |
CPU_P6 equ 6 |
CPU_PENTIUM4 equ 0x0F |
CAPS_FPU equ 00 ;on-chip x87 floating point unit |
CAPS_VME equ 01 ;virtual-mode enhancements |
CAPS_DE equ 02 ;debugging extensions |
CAPS_PSE equ 03 ;page-size extensions |
CAPS_TSC equ 04 ;time stamp counter |
CAPS_MSR equ 05 ;model-specific registers |
CAPS_PAE equ 06 ;physical-address extensions |
CAPS_MCE equ 07 ;machine check exception |
CAPS_CX8 equ 08 ;CMPXCHG8B instruction |
CAPS_APIC equ 09 ;on-chip advanced programmable |
; interrupt controller |
; 10 ;unused |
CAPS_SEP equ 11 ;SYSENTER and SYSEXIT instructions |
CAPS_MTRR equ 12 ;memory-type range registers |
CAPS_PGE equ 13 ;page global extension |
CAPS_MCA equ 14 ;machine check architecture |
CAPS_CMOV equ 15 ;conditional move instructions |
CAPS_PAT equ 16 ;page attribute table |
CAPS_PSE36 equ 17 ;page-size extensions |
CAPS_PSN equ 18 ;processor serial number |
CAPS_CLFLUSH equ 19 ;CLFUSH instruction |
CAPS_DS equ 21 ;debug store |
CAPS_ACPI equ 22 ;thermal monitor and software |
;controlled clock supported |
CAPS_MMX equ 23 ;MMX instructions |
CAPS_FXSR equ 24 ;FXSAVE and FXRSTOR instructions |
CAPS_SSE equ 25 ;SSE instructions |
CAPS_SSE2 equ 26 ;SSE2 instructions |
CAPS_SS equ 27 ;self-snoop |
CAPS_HTT equ 28 ;hyper-threading technology |
CAPS_TM equ 29 ;thermal monitor supported |
CAPS_IA64 equ 30 ;IA64 capabilities |
CAPS_PBE equ 31 ;pending break enable |
;ecx |
CAPS_SSE3 equ 32 ;SSE3 instructions |
; 33 |
; 34 |
CAPS_MONITOR equ 35 ;MONITOR/MWAIT instructions |
CAPS_DS_CPL equ 36 ; |
CAPS_VMX equ 37 ;virtual mode extensions |
; 38 ; |
CAPS_EST equ 39 ;enhansed speed step |
CAPS_TM2 equ 40 ;thermal monitor2 supported |
; 41 |
CAPS_CID equ 42 ; |
; 43 |
; 44 |
CAPS_CX16 equ 45 ;CMPXCHG16B instruction |
CAPS_xTPR equ 46 ; |
; |
;reserved |
; |
;ext edx /ecx |
CAPS_SYSCAL equ 64 ; |
CAPS_XD equ 65 ;execution disable |
CAPS_FFXSR equ 66 ; |
CAPS_RDTSCP equ 67 ; |
CAPS_X64 equ 68 ; |
CAPS_3DNOW equ 69 ; |
CAPS_3DNOWEXT equ 70 ; |
CAPS_LAHF equ 71 ; |
CAPS_CMP_LEG equ 72 ; |
CAPS_SVM equ 73 ;secure virual machine |
CAPS_ALTMOVCR8 equ 74 ; |
; CPU MSR names |
MSR_SYSENTER_CS equ 0x174 |
MSR_SYSENTER_ESP equ 0x175 |
MSR_SYSENTER_EIP equ 0x176 |
MSR_AMD_EFER equ 0xC0000080 ; Extended Feature Enable Register |
MSR_AMD_STAR equ 0xC0000081 ; SYSCALL/SYSRET Target Address Register |
CR0_PE equ 0x00000001 ;protected mode |
CR0_MP equ 0x00000002 ;monitor fpu |
CR0_EM equ 0x00000004 ;fpu emulation |
CR0_TS equ 0x00000008 ;task switch |
CR0_ET equ 0x00000010 ;extension type hardcoded to 1 |
CR0_NE equ 0x00000020 ;numeric error |
CR0_WP equ 0x00010000 ;write protect |
CR0_AM equ 0x00040000 ;alignment check |
CR0_NW equ 0x20000000 ;not write-through |
CR0_CD equ 0x40000000 ;cache disable |
CR0_PG equ 0x80000000 ;paging |
CR4_VME equ 0x0001 |
CR4_PVI equ 0x0002 |
CR4_TSD equ 0x0004 |
CR4_DE equ 0x0008 |
CR4_PSE equ 0x0010 |
CR4_PAE equ 0x0020 |
CR4_MCE equ 0x0040 |
CR4_PGE equ 0x0080 |
CR4_PCE equ 0x0100 |
CR4_OSFXSR equ 0x0200 |
CR4_OSXMMEXPT equ 0x0400 |
SSE_IE equ 0x0001 |
SSE_DE equ 0x0002 |
SSE_ZE equ 0x0004 |
SSE_OE equ 0x0008 |
SSE_UE equ 0x0010 |
SSE_PE equ 0x0020 |
SSE_DAZ equ 0x0040 |
SSE_IM equ 0x0080 |
SSE_DM equ 0x0100 |
SSE_ZM equ 0x0200 |
SSE_OM equ 0x0400 |
SSE_UM equ 0x0800 |
SSE_PM equ 0x1000 |
SSE_FZ equ 0x8000 |
SSE_INIT equ (SSE_IM+SSE_DM+SSE_ZM+SSE_OM+SSE_UM+SSE_PM) |
IRQ_PIC equ 0 |
IRQ_APIC equ 1 |
struc TSS |
{ |
._back rw 2 |
._esp0 rd 1 |
._ss0 rw 2 |
._esp1 rd 1 |
._ss1 rw 2 |
._esp2 rd 1 |
._ss2 rw 2 |
._cr3 rd 1 |
._eip rd 1 |
._eflags rd 1 |
._eax rd 1 |
._ecx rd 1 |
._edx rd 1 |
._ebx rd 1 |
._esp rd 1 |
._ebp rd 1 |
._esi rd 1 |
._edi rd 1 |
._es rw 2 |
._cs rw 2 |
._ss rw 2 |
._ds rw 2 |
._fs rw 2 |
._gs rw 2 |
._ldt rw 2 |
._trap rw 1 |
._io rw 1 |
rb 24 |
._io_map_0 rb 4096 |
._io_map_1 rb 4096 |
} |
virtual at 0 |
TSS TSS |
end virtual |
TSS_SIZE equ (128+8192) |
OS_BASE equ 0x80000000 |
window_data equ (OS_BASE+0x0001000) |
CURRENT_TASK equ (OS_BASE+0x0003000) |
TASK_COUNT equ (OS_BASE+0x0003004) |
TASK_BASE equ (OS_BASE+0x0003010) |
TASK_DATA equ (OS_BASE+0x0003020) |
TASK_EVENT equ (OS_BASE+0x0003020) |
mouseunder equ (OS_BASE+0x0006900) |
CDDataBuf equ (OS_BASE+0x0007000) |
FLOPPY_BUFF equ (OS_BASE+0x0008000) |
ACTIVE_PROC_STACK equ (OS_BASE+0x000A400) ;unused |
idts equ (OS_BASE+0x000B100) |
WIN_STACK equ (OS_BASE+0x000C000) |
WIN_POS equ (OS_BASE+0x000C400) |
FDD_BUFF equ (OS_BASE+0x000D000) |
;unused ? only one reference |
ENABLE_TASKSWITCH equ (OS_BASE+0x000E000) |
PUTPIXEL equ (OS_BASE+0x000E020) |
GETPIXEL equ (OS_BASE+0x000E024) |
;unused ? only one reference |
BANK_SWITCH equ (OS_BASE+0x000E030) |
;unused ? store mousepointer |
MOUSE_PICTURE equ (OS_BASE+0x000F200) |
MOUSE_VISIBLE equ (OS_BASE+0x000F204) |
WIN_TEMP_XY equ (OS_BASE+0x000F300) |
KEY_COUNT equ (OS_BASE+0x000F400) |
KEY_BUFF equ (OS_BASE+0x000F401) |
BTN_COUNT equ (OS_BASE+0x000F500) |
BTN_BUFF equ (OS_BASE+0x000F501) |
CPU_FREQ equ (OS_BASE+0x000F600) |
;unused ? no active references |
MOUSE_PORT equ (OS_BASE+0x000F604) |
;unused |
PS2_CHUNK equ (OS_BASE+0x000FB00) |
MOUSE_SCROLL_H equ (OS_BASE+0x000FB08) |
MOUSE_X equ (OS_BASE+0x000FB0A) |
MOUSE_Y equ (OS_BASE+0x000FB0C) |
MOUSE_SCROLL_V equ (OS_BASE+0x000FB0E) |
MOUSE_COLOR_MEM equ (OS_BASE+0x000FB10) |
COLOR_TEMP equ (OS_BASE+0x000FB30) |
BTN_DOWN equ (OS_BASE+0x000FB40) |
MOUSE_DOWN equ (OS_BASE+0x000FB44) |
X_UNDER equ (OS_BASE+0x000FB4A) |
Y_UNDER equ (OS_BASE+0x000FB4C) |
ScreenBPP equ (OS_BASE+0x000FBF1) |
;unused ? only one reference |
MOUSE_BUFF_COUNT equ (OS_BASE+0x000FCFF) |
Screen_Max_X equ (OS_BASE+0x000FE00) |
Screen_Max_Y equ (OS_BASE+0x000FE04) |
BytesPerScanLine equ (OS_BASE+0x000FE08) |
SCR_MODE equ (OS_BASE+0x000FE0C) |
LFBAddress equ (OS_BASE+0x000FE80) |
BTN_ADDR equ (OS_BASE+0x000FE88) |
MEM_AMOUNT equ (OS_BASE+0x000FE8C) |
SYS_SHUTDOWN equ (OS_BASE+0x000FF00) |
TASK_ACTIVATE equ (OS_BASE+0x000FF01) |
REDRAW_BACKGROUND equ (OS_BASE+0x000FFF0) |
BACKGROUND_CHANGED equ (OS_BASE+0x000FFF1) |
BANK_RW equ (OS_BASE+0x000FFF2) |
MOUSE_BACKGROUND equ (OS_BASE+0x000FFF4) |
DONT_DRAW_MOUSE equ (OS_BASE+0x000FFF5) |
DONT_SWITCH equ (OS_BASE+0x000FFFF) |
TMP_STACK_TOP equ 0x006CC00 |
FONT_II equ (OS_BASE+0x006DC00) |
FONT_I equ (OS_BASE+0x006E600) |
sys_pgdir equ (OS_BASE+0x006F000) |
DRIVE_DATA equ (OS_BASE+0x0070000) |
SLOT_BASE equ (OS_BASE+0x0080000) |
;unused |
TMP_BUFF equ (OS_BASE+0x0090000) |
VGABasePtr equ (OS_BASE+0x00A0000) |
RAMDISK equ (OS_BASE+0x0100000) |
RAMDISK_FAT equ (OS_BASE+0x0280000) |
FLOPPY_FAT equ (OS_BASE+0x0282000) |
CLEAN_ZONE equ 0x284000 |
IDE_DMA equ 0x284000 |
BgrAuxTable equ (OS_BASE+0x0298000) |
; unused? |
SB16Buffer equ (OS_BASE+0x02A0000) |
SB16_Status equ (OS_BASE+0x02B0000) |
BUTTON_INFO equ (OS_BASE+0x02C0000) |
RESERVED_PORTS equ (OS_BASE+0x02D0000) |
BOOT_VAR equ (OS_BASE+0x02E0000) |
stack_data_start equ (OS_BASE+0x02F0000) |
eth_data_start equ (OS_BASE+0x02F0000) |
stack_data equ (OS_BASE+0x02F4000) |
stack_data_end equ (OS_BASE+0x030ffff) |
resendQ equ (OS_BASE+0x0310000) |
skin_data equ (OS_BASE+0x0318000) |
draw_data equ (OS_BASE+0x0320000) |
BgrDrawMode equ (OS_BASE+0x0323FF4) |
BgrDataWidth equ (OS_BASE+0x0323FF8) |
BgrDataHeight equ (OS_BASE+0x0323FFC) |
sys_pgmap equ (OS_BASE+0x0324000) |
UPPER_KERNEL_PAGES equ (OS_BASE+0x0400000) |
virtual at (OS_BASE+0x05FFF80) |
tss TSS |
end virtual |
HEAP_BASE equ (OS_BASE+0x0800000) |
HEAP_MIN_SIZE equ 0x01000000 |
page_tabs equ 0xFDC00000 |
app_page_tabs equ 0xFDC00000 |
kernel_tabs equ (page_tabs+ (OS_BASE shr 10)) ;0xFDE00000 |
master_tab equ (page_tabs+ (page_tabs shr 10)) ;0xFDFF70000 |
LFB_BASE equ 0xFE000000 |
new_app_base equ 0; |
twdw equ 0x2000 ;(CURRENT_TASK-window_data) |
std_application_base_address equ new_app_base |
RING0_STACK_SIZE equ (0x2000 - 512) ;512 áàéò äëÿ êîíòåêñòà FPU |
REG_SS equ (RING0_STACK_SIZE-4) |
REG_APP_ESP equ (RING0_STACK_SIZE-8) |
REG_EFLAGS equ (RING0_STACK_SIZE-12) |
REG_CS equ (RING0_STACK_SIZE-16) |
REG_EIP equ (RING0_STACK_SIZE-20) |
REG_EAX equ (RING0_STACK_SIZE-24) |
REG_ECX equ (RING0_STACK_SIZE-28) |
REG_EDX equ (RING0_STACK_SIZE-32) |
REG_EBX equ (RING0_STACK_SIZE-36) |
REG_ESP equ (RING0_STACK_SIZE-40) ;RING0_STACK_SIZE-20 |
REG_EBP equ (RING0_STACK_SIZE-44) |
REG_ESI equ (RING0_STACK_SIZE-48) |
REG_EDI equ (RING0_STACK_SIZE-52) |
REG_RET equ (RING0_STACK_SIZE-56) ;irq0.return |
PG_UNMAP equ 0x000 |
PG_MAP equ 0x001 |
PG_WRITE equ 0x002 |
PG_SW equ 0x003 |
PG_USER equ 0x005 |
PG_UW equ 0x007 |
PG_NOCACHE equ 0x018 |
PG_LARGE equ 0x080 |
PG_GLOBAL equ 0x100 |
PG_SHARED equ 0x200 |
;;;;;;;;;;;boot time variables |
;BOOT_BPP equ 0x9000 ;byte bits per pixel |
BOOT_SCANLINE equ 0x9001 ;word scanline length |
BOOT_VESA_MODE equ 0x9008 ;word vesa video mode |
;;BOOT_X_RES equ 0x900A ;word X res |
;;BOOT_Y_RES equ 0x900C ;word Y res |
;;BOOT_MOUSE_PORT equ 0x9010 ;byte mouse port - not used |
BOOT_BANK_SW equ 0x9014 ;dword Vesa 1.2 pm bank switch |
BOOT_LFB equ 0x9018 ;dword Vesa 2.0 LFB address |
BOOT_MTRR equ 0x901C ;byte 0 or 1 : enable MTRR graphics acceleration |
BOOT_LOG equ 0x901D ;byte not used anymore (0 or 1 : enable system log display) |
BOOT_DIRECT_LFB equ 0x901E ;byte 0 or 1 : enable direct lfb write, paging disabled |
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_MEM_AMOUNT equ 0x9034 ;dword memory amount |
TMP_FILE_NAME equ 0 |
TMP_CMD_LINE equ 1024 |
TMP_ICON_OFFS equ 1280 |
EVENT_REDRAW equ 0x00000001 |
EVENT_KEY equ 0x00000002 |
EVENT_BUTTON equ 0x00000004 |
EVENT_BACKGROUND equ 0x00000010 |
EVENT_MOUSE equ 0x00000020 |
EVENT_IPC equ 0x00000040 |
EVENT_NETWORK equ 0x00000080 |
EVENT_DEBUG equ 0x00000100 |
EVENT_EXTENDED equ 0x00000200 |
EV_INTR equ 1 |
struc THR_DATA |
{ |
rb (8192-512) |
.pl0_stack: |
.fpu_state rb 512 |
.tls_page rb 4096 |
.pdbr rb 4096 |
} |
THR_DATA_SIZE equ 4096*4 |
virtual at (OS_BASE-THR_DATA_SIZE) |
thr_data THR_DATA |
end virtual |
struc SYS_VARS |
{ .bpp dd ? |
.scanline dd ? |
.vesa_mode dd ? |
.x_res dd ? |
.y_res dd ? |
} |
struc APPOBJ ;common object header |
{ |
.magic dd ? ; |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
}; |
virtual at 0 |
APPOBJ APPOBJ |
end virtual |
APP_OBJ_OFFSET equ 48 |
APP_EV_OFFSET equ 40 |
struc CURSOR |
{ |
;common object header |
.magic dd ? ;'CURS' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
;cursor data |
.base dd ? ;allocated memory |
.hot_x dd ? ;hotspot coords |
.hot_y dd ? |
.list_next dd ? ;next cursor in cursor list |
.list_prev dd ? ;prev cursor in cursor list |
.dev_obj dd ? ;device depended data |
.sizeof: |
} |
virtual at 0 |
CURSOR CURSOR |
end virtual |
struc EVENT |
{ |
.magic dd ? ;'EVNT' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.id dd ? ;event uid |
.state dd ? ;internal flags |
.code dd ? |
rd 5 |
.size = $ - .magic |
.codesize = $ - .code |
} |
virtual at 0 |
EVENT EVENT |
end virtual |
struc SMEM |
{ |
.bk dd ? |
.fd dd ? ;+4 |
.base dd ? ;+8 |
.size dd ? ;+12 |
.access dd ? ;+16 |
.refcount dd ? ;+20 |
.name rb 32 ;+24 |
.sizeof: |
} |
struc SMAP |
{ |
.magic dd ? ; SMAP |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.base dd ? ;mapped base |
.parent dd ? ;SMEM |
.sizeof: |
} |
virtual at 0 |
SMEM SMEM |
end virtual |
virtual at 0 |
SMAP SMAP |
end virtual |
struc DLLDESCR |
{ |
.bk dd ? |
.fd dd ? ;+4 |
.data dd ? ;+8 |
.size dd ? ;+12 |
.timestamp dq ? |
.refcount dd ? |
.defaultbase dd ? |
.coff_hdr dd ? |
.symbols_ptr dd ? |
.symbols_num dd ? |
.symbols_lim dd ? |
.exports dd ? ;export table |
.name: |
.sizeof: |
} |
struc HDLL |
{ |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.base dd ? ;mapped base |
.size dd ? ;mapped size |
.refcount dd ? ;reference counter for this process and this lib |
.parent dd ? ;DLLDESCR |
.sizeof: |
} |
virtual at 0 |
DLLDESCR DLLDESCR |
end virtual |
virtual at 0 |
HDLL HDLL |
end virtual |
struc display_t |
{ |
.x dd ? |
.y dd ? |
.width dd ? |
.height dd ? |
.bpp dd ? |
.vrefresh dd ? |
.pitch dd ? |
.lfb dd ? |
.modes dd ? |
.ddev dd ? |
.connector dd ? |
.crtc dd ? |
.cr_list.next dd ? |
.cr_list.prev dd ? |
.cursor dd ? |
.init_cursor dd ? |
.select_cursor dd ? |
.show_cursor dd ? |
.move_cursor dd ? |
.restore_cursor dd ? |
.disable_mouse dd ? |
} |
virtual at 0 |
display_t display_t |
end virtual |
struc BOOT_DATA |
{ .bpp dd ? |
.scanline dd ? |
.vesa_mode dd ? |
.x_res dd ? |
.y_res dd ? |
.mouse_port dd ? |
.bank_switch dd ? |
.lfb dd ? |
.vesa_mem dd ? |
.log dd ? |
.direct_lfb dd ? |
.pci_data dd ? |
; dd ? |
.vrr dd ? |
.ide_base dd ? |
.mem_amount dd ? |
.pages_count dd ? |
.pagemap_size dd ? |
.kernel_max dd ? |
.kernel_pages dd ? |
.kernel_tables dd ? |
.cpu_vendor dd ? |
dd ? |
dd ? |
.cpu_sign dd ? |
.cpu_info dd ? |
.cpu_caps dd ? |
dd ? |
dd ? |
} |
virtual at 0 |
BOOT_DATA BOOT_DATA |
end virtual |
struc MEM_STATE |
{ .mutex MUTEX |
.smallmap rd 1 |
.treemap rd 1 |
.topsize rd 1 |
.top rd 1 |
.smallbins rd 4*32 |
.treebins rd 32 |
} |
struc PG_DATA |
{ .mem_amount dd ? |
.vesa_mem dd ? |
.pages_count dd ? |
.pages_free dd ? |
.pages_faults dd ? |
.pagemap_size dd ? |
.kernel_pages dd ? |
.kernel_tables dd ? |
.sys_page_dir dd ? |
.mutex MUTEX |
} |
;struc LIB |
;{ .lib_name rb 16 |
; .lib_base dd ? |
; .lib_start dd ? |
; .export dd ? |
; .import dd ? |
;} |
struc SRV |
{ |
.srv_name rb 16 ;ASCIIZ string |
.magic dd ? ;+0x10 ;'SRV ' |
.size dd ? ;+0x14 ;size of structure SRV |
.fd dd ? ;+0x18 ;next SRV descriptor |
.bk dd ? ;+0x1C ;prev SRV descriptor |
.base dd ? ;+0x20 ;service base address |
.entry dd ? ;+0x24 ;service START function |
.srv_proc dd ? ;+0x28 ;user mode service handler |
.srv_proc_ex dd ? ;+0x2C ;kernel mode service handler |
.sizeof: |
} |
SRV_FD_OFFSET equ 0x18 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
struc COFF_HEADER |
{ .machine dw ? |
.nSections dw ? |
.DataTime dd ? |
.pSymTable dd ? |
.nSymbols dd ? |
.optHeader dw ? |
.flags dw ? |
}; |
struc COFF_SECTION |
{ .Name rb 8 |
.VirtualSize dd ? |
.VirtualAddress dd ? |
.SizeOfRawData dd ? |
.PtrRawData dd ? |
.PtrReloc dd ? |
.PtrLinenumbers dd ? |
.NumReloc dw ? |
.NumLinenum dw ? |
.Characteristics dd ? |
} |
COFF_SECTION_SIZE equ 40 |
struc COFF_RELOC |
{ .VirtualAddress dd ? |
.SymIndex dd ? |
.Type dw ? |
} |
struc COFF_SYM |
{ .Name rb 8 |
.Value dd ? |
.SectionNumber dw ? |
.Type dw ? |
.StorageClass db ? |
.NumAuxSymbols db ? |
} |
CSYM_SIZE equ 18 |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
;virtual at 0 |
; LIB LIB |
;end virtual |
virtual at 0 |
SRV SRV |
end virtual |
virtual at 0 |
CFH COFF_HEADER |
end virtual |
virtual at 0 |
CFS COFF_SECTION |
end virtual |
virtual at 0 |
CRELOC COFF_RELOC |
end virtual |
virtual at 0 |
CSYM COFF_SYM |
end virtual |
struc LHEAD |
{ |
.next dd ? ;next object in list |
.prev dd ? ;prev object in list |
.sizeof: |
} |
virtual at 0 |
LHEAD LHEAD |
end virtual |
struc IRQH |
{ |
.list LHEAD |
.handler dd ? ;handler roututine |
.data dd ? ;user-specific data |
.sizeof: |
} |
virtual at 0 |
IRQH IRQH |
end virtual |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
dpl0 equ 10010000b ; data read dpl0 |
drw0 equ 10010010b ; data read/write dpl0 |
drw3 equ 11110010b ; data read/write dpl3 |
cpl0 equ 10011010b ; code read dpl0 |
cpl3 equ 11111010b ; code read dpl3 |
D32 equ 01000000b ; 32bit segment |
G32 equ 10000000b ; page gran |
;;;;;;;;;;;;cpu_caps flags;;;;;;;;;;;;;;;; |
CPU_386 equ 3 |
CPU_486 equ 4 |
CPU_PENTIUM equ 5 |
CPU_P6 equ 6 |
CPU_PENTIUM4 equ 0x0F |
CAPS_FPU equ 00 ;on-chip x87 floating point unit |
CAPS_VME equ 01 ;virtual-mode enhancements |
CAPS_DE equ 02 ;debugging extensions |
CAPS_PSE equ 03 ;page-size extensions |
CAPS_TSC equ 04 ;time stamp counter |
CAPS_MSR equ 05 ;model-specific registers |
CAPS_PAE equ 06 ;physical-address extensions |
CAPS_MCE equ 07 ;machine check exception |
CAPS_CX8 equ 08 ;CMPXCHG8B instruction |
CAPS_APIC equ 09 ;on-chip advanced programmable |
; interrupt controller |
; 10 ;unused |
CAPS_SEP equ 11 ;SYSENTER and SYSEXIT instructions |
CAPS_MTRR equ 12 ;memory-type range registers |
CAPS_PGE equ 13 ;page global extension |
CAPS_MCA equ 14 ;machine check architecture |
CAPS_CMOV equ 15 ;conditional move instructions |
CAPS_PAT equ 16 ;page attribute table |
CAPS_PSE36 equ 17 ;page-size extensions |
CAPS_PSN equ 18 ;processor serial number |
CAPS_CLFLUSH equ 19 ;CLFUSH instruction |
CAPS_DS equ 21 ;debug store |
CAPS_ACPI equ 22 ;thermal monitor and software |
;controlled clock supported |
CAPS_MMX equ 23 ;MMX instructions |
CAPS_FXSR equ 24 ;FXSAVE and FXRSTOR instructions |
CAPS_SSE equ 25 ;SSE instructions |
CAPS_SSE2 equ 26 ;SSE2 instructions |
CAPS_SS equ 27 ;self-snoop |
CAPS_HTT equ 28 ;hyper-threading technology |
CAPS_TM equ 29 ;thermal monitor supported |
CAPS_IA64 equ 30 ;IA64 capabilities |
CAPS_PBE equ 31 ;pending break enable |
;ecx |
CAPS_SSE3 equ 32 ;SSE3 instructions |
; 33 |
; 34 |
CAPS_MONITOR equ 35 ;MONITOR/MWAIT instructions |
CAPS_DS_CPL equ 36 ; |
CAPS_VMX equ 37 ;virtual mode extensions |
; 38 ; |
CAPS_EST equ 39 ;enhansed speed step |
CAPS_TM2 equ 40 ;thermal monitor2 supported |
; 41 |
CAPS_CID equ 42 ; |
; 43 |
; 44 |
CAPS_CX16 equ 45 ;CMPXCHG16B instruction |
CAPS_xTPR equ 46 ; |
; |
;reserved |
; |
;ext edx /ecx |
CAPS_SYSCAL equ 64 ; |
CAPS_XD equ 65 ;execution disable |
CAPS_FFXSR equ 66 ; |
CAPS_RDTSCP equ 67 ; |
CAPS_X64 equ 68 ; |
CAPS_3DNOW equ 69 ; |
CAPS_3DNOWEXT equ 70 ; |
CAPS_LAHF equ 71 ; |
CAPS_CMP_LEG equ 72 ; |
CAPS_SVM equ 73 ;secure virual machine |
CAPS_ALTMOVCR8 equ 74 ; |
; CPU MSR names |
MSR_SYSENTER_CS equ 0x174 |
MSR_SYSENTER_ESP equ 0x175 |
MSR_SYSENTER_EIP equ 0x176 |
MSR_AMD_EFER equ 0xC0000080 ; Extended Feature Enable Register |
MSR_AMD_STAR equ 0xC0000081 ; SYSCALL/SYSRET Target Address Register |
CR0_PE equ 0x00000001 ;protected mode |
CR0_MP equ 0x00000002 ;monitor fpu |
CR0_EM equ 0x00000004 ;fpu emulation |
CR0_TS equ 0x00000008 ;task switch |
CR0_ET equ 0x00000010 ;extension type hardcoded to 1 |
CR0_NE equ 0x00000020 ;numeric error |
CR0_WP equ 0x00010000 ;write protect |
CR0_AM equ 0x00040000 ;alignment check |
CR0_NW equ 0x20000000 ;not write-through |
CR0_CD equ 0x40000000 ;cache disable |
CR0_PG equ 0x80000000 ;paging |
CR4_VME equ 0x0001 |
CR4_PVI equ 0x0002 |
CR4_TSD equ 0x0004 |
CR4_DE equ 0x0008 |
CR4_PSE equ 0x0010 |
CR4_PAE equ 0x0020 |
CR4_MCE equ 0x0040 |
CR4_PGE equ 0x0080 |
CR4_PCE equ 0x0100 |
CR4_OSFXSR equ 0x0200 |
CR4_OSXMMEXPT equ 0x0400 |
SSE_IE equ 0x0001 |
SSE_DE equ 0x0002 |
SSE_ZE equ 0x0004 |
SSE_OE equ 0x0008 |
SSE_UE equ 0x0010 |
SSE_PE equ 0x0020 |
SSE_DAZ equ 0x0040 |
SSE_IM equ 0x0080 |
SSE_DM equ 0x0100 |
SSE_ZM equ 0x0200 |
SSE_OM equ 0x0400 |
SSE_UM equ 0x0800 |
SSE_PM equ 0x1000 |
SSE_FZ equ 0x8000 |
SSE_INIT equ (SSE_IM+SSE_DM+SSE_ZM+SSE_OM+SSE_UM+SSE_PM) |
IRQ_PIC equ 0 |
IRQ_APIC equ 1 |
struc TSS |
{ |
._back rw 2 |
._esp0 rd 1 |
._ss0 rw 2 |
._esp1 rd 1 |
._ss1 rw 2 |
._esp2 rd 1 |
._ss2 rw 2 |
._cr3 rd 1 |
._eip rd 1 |
._eflags rd 1 |
._eax rd 1 |
._ecx rd 1 |
._edx rd 1 |
._ebx rd 1 |
._esp rd 1 |
._ebp rd 1 |
._esi rd 1 |
._edi rd 1 |
._es rw 2 |
._cs rw 2 |
._ss rw 2 |
._ds rw 2 |
._fs rw 2 |
._gs rw 2 |
._ldt rw 2 |
._trap rw 1 |
._io rw 1 |
rb 24 |
._io_map_0 rb 4096 |
._io_map_1 rb 4096 |
} |
virtual at 0 |
TSS TSS |
end virtual |
TSS_SIZE equ (128+8192) |
OS_BASE equ 0x80000000 |
window_data equ (OS_BASE+0x0001000) |
CURRENT_TASK equ (OS_BASE+0x0003000) |
TASK_COUNT equ (OS_BASE+0x0003004) |
TASK_BASE equ (OS_BASE+0x0003010) |
TASK_DATA equ (OS_BASE+0x0003020) |
TASK_EVENT equ (OS_BASE+0x0003020) |
mouseunder equ (OS_BASE+0x0006900) |
CDDataBuf equ (OS_BASE+0x0007000) |
FLOPPY_BUFF equ (OS_BASE+0x0008000) |
ACTIVE_PROC_STACK equ (OS_BASE+0x000A400) ;unused |
idts equ (OS_BASE+0x000B100) |
WIN_STACK equ (OS_BASE+0x000C000) |
WIN_POS equ (OS_BASE+0x000C400) |
FDD_BUFF equ (OS_BASE+0x000D000) |
;unused ? only one reference |
ENABLE_TASKSWITCH equ (OS_BASE+0x000E000) |
PUTPIXEL equ (OS_BASE+0x000E020) |
GETPIXEL equ (OS_BASE+0x000E024) |
;unused ? only one reference |
BANK_SWITCH equ (OS_BASE+0x000E030) |
;unused ? store mousepointer |
MOUSE_PICTURE equ (OS_BASE+0x000F200) |
MOUSE_VISIBLE equ (OS_BASE+0x000F204) |
WIN_TEMP_XY equ (OS_BASE+0x000F300) |
KEY_COUNT equ (OS_BASE+0x000F400) |
KEY_BUFF equ (OS_BASE+0x000F401) |
BTN_COUNT equ (OS_BASE+0x000F500) |
BTN_BUFF equ (OS_BASE+0x000F501) |
CPU_FREQ equ (OS_BASE+0x000F600) |
;unused ? no active references |
MOUSE_PORT equ (OS_BASE+0x000F604) |
;unused |
PS2_CHUNK equ (OS_BASE+0x000FB00) |
MOUSE_SCROLL_H equ (OS_BASE+0x000FB08) |
MOUSE_X equ (OS_BASE+0x000FB0A) |
MOUSE_Y equ (OS_BASE+0x000FB0C) |
MOUSE_SCROLL_V equ (OS_BASE+0x000FB0E) |
MOUSE_COLOR_MEM equ (OS_BASE+0x000FB10) |
COLOR_TEMP equ (OS_BASE+0x000FB30) |
BTN_DOWN equ (OS_BASE+0x000FB40) |
MOUSE_DOWN equ (OS_BASE+0x000FB44) |
X_UNDER equ (OS_BASE+0x000FB4A) |
Y_UNDER equ (OS_BASE+0x000FB4C) |
ScreenBPP equ (OS_BASE+0x000FBF1) |
;unused ? only one reference |
MOUSE_BUFF_COUNT equ (OS_BASE+0x000FCFF) |
Screen_Max_X equ (OS_BASE+0x000FE00) |
Screen_Max_Y equ (OS_BASE+0x000FE04) |
BytesPerScanLine equ (OS_BASE+0x000FE08) |
SCR_MODE equ (OS_BASE+0x000FE0C) |
LFBAddress equ (OS_BASE+0x000FE80) |
BTN_ADDR equ (OS_BASE+0x000FE88) |
MEM_AMOUNT equ (OS_BASE+0x000FE8C) |
SYS_SHUTDOWN equ (OS_BASE+0x000FF00) |
TASK_ACTIVATE equ (OS_BASE+0x000FF01) |
REDRAW_BACKGROUND equ (OS_BASE+0x000FFF0) |
BACKGROUND_CHANGED equ (OS_BASE+0x000FFF1) |
BANK_RW equ (OS_BASE+0x000FFF2) |
MOUSE_BACKGROUND equ (OS_BASE+0x000FFF4) |
DONT_DRAW_MOUSE equ (OS_BASE+0x000FFF5) |
DONT_SWITCH equ (OS_BASE+0x000FFFF) |
TMP_STACK_TOP equ 0x006CC00 |
FONT_II equ (OS_BASE+0x006DC00) |
FONT_I equ (OS_BASE+0x006E600) |
sys_pgdir equ (OS_BASE+0x006F000) |
DRIVE_DATA equ (OS_BASE+0x0070000) |
SLOT_BASE equ (OS_BASE+0x0080000) |
;unused |
TMP_BUFF equ (OS_BASE+0x0090000) |
VGABasePtr equ (OS_BASE+0x00A0000) |
RAMDISK equ (OS_BASE+0x0100000) |
RAMDISK_FAT equ (OS_BASE+0x0280000) |
FLOPPY_FAT equ (OS_BASE+0x0282000) |
CLEAN_ZONE equ 0x284000 |
IDE_DMA equ 0x284000 |
BgrAuxTable equ (OS_BASE+0x0298000) |
; unused? |
SB16Buffer equ (OS_BASE+0x02A0000) |
SB16_Status equ (OS_BASE+0x02B0000) |
BUTTON_INFO equ (OS_BASE+0x02C0000) |
RESERVED_PORTS equ (OS_BASE+0x02D0000) |
BOOT_VAR equ (OS_BASE+0x02E0000) |
stack_data_start equ (OS_BASE+0x02F0000) |
eth_data_start equ (OS_BASE+0x02F0000) |
stack_data equ (OS_BASE+0x02F4000) |
stack_data_end equ (OS_BASE+0x030ffff) |
resendQ equ (OS_BASE+0x0310000) |
skin_data equ (OS_BASE+0x0318000) |
draw_data equ (OS_BASE+0x0320000) |
BgrDrawMode equ (OS_BASE+0x0323FF4) |
BgrDataWidth equ (OS_BASE+0x0323FF8) |
BgrDataHeight equ (OS_BASE+0x0323FFC) |
sys_pgmap equ (OS_BASE+0x0324000) |
UPPER_KERNEL_PAGES equ (OS_BASE+0x0400000) |
virtual at (OS_BASE+0x05FFF80) |
tss TSS |
end virtual |
HEAP_BASE equ (OS_BASE+0x0800000) |
HEAP_MIN_SIZE equ 0x01000000 |
page_tabs equ 0xFDC00000 |
app_page_tabs equ 0xFDC00000 |
kernel_tabs equ (page_tabs+ (OS_BASE shr 10)) ;0xFDE00000 |
master_tab equ (page_tabs+ (page_tabs shr 10)) ;0xFDFF70000 |
LFB_BASE equ 0xFE000000 |
new_app_base equ 0; |
twdw equ 0x2000 ;(CURRENT_TASK-window_data) |
std_application_base_address equ new_app_base |
RING0_STACK_SIZE equ (0x2000 - 512) ;512 áàéò äëÿ êîíòåêñòà FPU |
REG_SS equ (RING0_STACK_SIZE-4) |
REG_APP_ESP equ (RING0_STACK_SIZE-8) |
REG_EFLAGS equ (RING0_STACK_SIZE-12) |
REG_CS equ (RING0_STACK_SIZE-16) |
REG_EIP equ (RING0_STACK_SIZE-20) |
REG_EAX equ (RING0_STACK_SIZE-24) |
REG_ECX equ (RING0_STACK_SIZE-28) |
REG_EDX equ (RING0_STACK_SIZE-32) |
REG_EBX equ (RING0_STACK_SIZE-36) |
REG_ESP equ (RING0_STACK_SIZE-40) ;RING0_STACK_SIZE-20 |
REG_EBP equ (RING0_STACK_SIZE-44) |
REG_ESI equ (RING0_STACK_SIZE-48) |
REG_EDI equ (RING0_STACK_SIZE-52) |
REG_RET equ (RING0_STACK_SIZE-56) ;irq0.return |
PG_UNMAP equ 0x000 |
PG_MAP equ 0x001 |
PG_WRITE equ 0x002 |
PG_SW equ 0x003 |
PG_USER equ 0x005 |
PG_UW equ 0x007 |
PG_NOCACHE equ 0x018 |
PG_LARGE equ 0x080 |
PG_GLOBAL equ 0x100 |
PG_SHARED equ 0x200 |
;;;;;;;;;;;boot time variables |
;BOOT_BPP equ 0x9000 ;byte bits per pixel |
BOOT_SCANLINE equ 0x9001 ;word scanline length |
BOOT_VESA_MODE equ 0x9008 ;word vesa video mode |
;;BOOT_X_RES equ 0x900A ;word X res |
;;BOOT_Y_RES equ 0x900C ;word Y res |
;;BOOT_MOUSE_PORT equ 0x9010 ;byte mouse port - not used |
BOOT_BANK_SW equ 0x9014 ;dword Vesa 1.2 pm bank switch |
BOOT_LFB equ 0x9018 ;dword Vesa 2.0 LFB address |
BOOT_MTRR equ 0x901C ;byte 0 or 1 : enable MTRR graphics acceleration |
BOOT_LOG equ 0x901D ;byte not used anymore (0 or 1 : enable system log display) |
BOOT_DIRECT_LFB equ 0x901E ;byte 0 or 1 : enable direct lfb write, paging disabled |
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_MEM_AMOUNT equ 0x9034 ;dword memory amount |
TMP_FILE_NAME equ 0 |
TMP_CMD_LINE equ 1024 |
TMP_ICON_OFFS equ 1280 |
EVENT_REDRAW equ 0x00000001 |
EVENT_KEY equ 0x00000002 |
EVENT_BUTTON equ 0x00000004 |
EVENT_BACKGROUND equ 0x00000010 |
EVENT_MOUSE equ 0x00000020 |
EVENT_IPC equ 0x00000040 |
EVENT_NETWORK equ 0x00000080 |
EVENT_DEBUG equ 0x00000100 |
EVENT_EXTENDED equ 0x00000200 |
EV_INTR equ 1 |
struc THR_DATA |
{ |
rb (8192-512) |
.pl0_stack: |
.fpu_state rb 512 |
.tls_page rb 4096 |
.pdbr rb 4096 |
} |
THR_DATA_SIZE equ 4096*4 |
virtual at (OS_BASE-THR_DATA_SIZE) |
thr_data THR_DATA |
end virtual |
struc SYS_VARS |
{ .bpp dd ? |
.scanline dd ? |
.vesa_mode dd ? |
.x_res dd ? |
.y_res dd ? |
} |
struc APPOBJ ;common object header |
{ |
.magic dd ? ; |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
}; |
virtual at 0 |
APPOBJ APPOBJ |
end virtual |
APP_OBJ_OFFSET equ 48 |
APP_EV_OFFSET equ 40 |
struc CURSOR |
{ |
;common object header |
.magic dd ? ;'CURS' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
;cursor data |
.base dd ? ;allocated memory |
.hot_x dd ? ;hotspot coords |
.hot_y dd ? |
.list_next dd ? ;next cursor in cursor list |
.list_prev dd ? ;prev cursor in cursor list |
.dev_obj dd ? ;device depended data |
.sizeof: |
} |
virtual at 0 |
CURSOR CURSOR |
end virtual |
struc EVENT |
{ |
.magic dd ? ;'EVNT' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.id dd ? ;event uid |
.state dd ? ;internal flags |
.code dd ? |
rd 5 |
.size = $ - .magic |
.codesize = $ - .code |
} |
virtual at 0 |
EVENT EVENT |
end virtual |
struc SMEM |
{ |
.bk dd ? |
.fd dd ? ;+4 |
.base dd ? ;+8 |
.size dd ? ;+12 |
.access dd ? ;+16 |
.refcount dd ? ;+20 |
.name rb 32 ;+24 |
.sizeof: |
} |
struc SMAP |
{ |
.magic dd ? ; SMAP |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.base dd ? ;mapped base |
.parent dd ? ;SMEM |
.sizeof: |
} |
virtual at 0 |
SMEM SMEM |
end virtual |
virtual at 0 |
SMAP SMAP |
end virtual |
struc DLLDESCR |
{ |
.bk dd ? |
.fd dd ? ;+4 |
.data dd ? ;+8 |
.size dd ? ;+12 |
.timestamp dq ? |
.refcount dd ? |
.defaultbase dd ? |
.coff_hdr dd ? |
.symbols_ptr dd ? |
.symbols_num dd ? |
.symbols_lim dd ? |
.exports dd ? ;export table |
.name: |
.sizeof: |
} |
struc HDLL |
{ |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.base dd ? ;mapped base |
.size dd ? ;mapped size |
.refcount dd ? ;reference counter for this process and this lib |
.parent dd ? ;DLLDESCR |
.sizeof: |
} |
virtual at 0 |
DLLDESCR DLLDESCR |
end virtual |
virtual at 0 |
HDLL HDLL |
end virtual |
struc display_t |
{ |
.x dd ? |
.y dd ? |
.width dd ? |
.height dd ? |
.bpp dd ? |
.vrefresh dd ? |
.pitch dd ? |
.lfb dd ? |
.modes dd ? |
.ddev dd ? |
.connector dd ? |
.crtc dd ? |
.cr_list.next dd ? |
.cr_list.prev dd ? |
.cursor dd ? |
.init_cursor dd ? |
.select_cursor dd ? |
.show_cursor dd ? |
.move_cursor dd ? |
.restore_cursor dd ? |
.disable_mouse dd ? |
} |
virtual at 0 |
display_t display_t |
end virtual |
struc BOOT_DATA |
{ .bpp dd ? |
.scanline dd ? |
.vesa_mode dd ? |
.x_res dd ? |
.y_res dd ? |
.mouse_port dd ? |
.bank_switch dd ? |
.lfb dd ? |
.vesa_mem dd ? |
.log dd ? |
.direct_lfb dd ? |
.pci_data dd ? |
; dd ? |
.vrr dd ? |
.ide_base dd ? |
.mem_amount dd ? |
.pages_count dd ? |
.pagemap_size dd ? |
.kernel_max dd ? |
.kernel_pages dd ? |
.kernel_tables dd ? |
.cpu_vendor dd ? |
dd ? |
dd ? |
.cpu_sign dd ? |
.cpu_info dd ? |
.cpu_caps dd ? |
dd ? |
dd ? |
} |
virtual at 0 |
BOOT_DATA BOOT_DATA |
end virtual |
struc MEM_STATE |
{ .mutex MUTEX |
.smallmap rd 1 |
.treemap rd 1 |
.topsize rd 1 |
.top rd 1 |
.smallbins rd 4*32 |
.treebins rd 32 |
} |
struc PG_DATA |
{ .mem_amount dd ? |
.vesa_mem dd ? |
.pages_count dd ? |
.pages_free dd ? |
.pages_faults dd ? |
.pagemap_size dd ? |
.kernel_pages dd ? |
.kernel_tables dd ? |
.sys_page_dir dd ? |
.mutex MUTEX |
} |
;struc LIB |
;{ .lib_name rb 16 |
; .lib_base dd ? |
; .lib_start dd ? |
; .export dd ? |
; .import dd ? |
;} |
struc SRV |
{ |
.srv_name rb 16 ;ASCIIZ string |
.magic dd ? ;+0x10 ;'SRV ' |
.size dd ? ;+0x14 ;size of structure SRV |
.fd dd ? ;+0x18 ;next SRV descriptor |
.bk dd ? ;+0x1C ;prev SRV descriptor |
.base dd ? ;+0x20 ;service base address |
.entry dd ? ;+0x24 ;service START function |
.srv_proc dd ? ;+0x28 ;user mode service handler |
.srv_proc_ex dd ? ;+0x2C ;kernel mode service handler |
.sizeof: |
} |
SRV_FD_OFFSET equ 0x18 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
struc COFF_HEADER |
{ .machine dw ? |
.nSections dw ? |
.DataTime dd ? |
.pSymTable dd ? |
.nSymbols dd ? |
.optHeader dw ? |
.flags dw ? |
}; |
struc COFF_SECTION |
{ .Name rb 8 |
.VirtualSize dd ? |
.VirtualAddress dd ? |
.SizeOfRawData dd ? |
.PtrRawData dd ? |
.PtrReloc dd ? |
.PtrLinenumbers dd ? |
.NumReloc dw ? |
.NumLinenum dw ? |
.Characteristics dd ? |
} |
COFF_SECTION_SIZE equ 40 |
struc COFF_RELOC |
{ .VirtualAddress dd ? |
.SymIndex dd ? |
.Type dw ? |
} |
struc COFF_SYM |
{ .Name rb 8 |
.Value dd ? |
.SectionNumber dw ? |
.Type dw ? |
.StorageClass db ? |
.NumAuxSymbols db ? |
} |
CSYM_SIZE equ 18 |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
;virtual at 0 |
; LIB LIB |
;end virtual |
virtual at 0 |
SRV SRV |
end virtual |
virtual at 0 |
CFH COFF_HEADER |
end virtual |
virtual at 0 |
CFS COFF_SECTION |
end virtual |
virtual at 0 |
CRELOC COFF_RELOC |
end virtual |
virtual at 0 |
CSYM COFF_SYM |
end virtual |
struc LHEAD |
{ |
.next dd ? ;next object in list |
.prev dd ? ;prev object in list |
.sizeof: |
} |
virtual at 0 |
LHEAD LHEAD |
end virtual |
struc IRQH |
{ |
.list LHEAD |
.handler dd ? ;handler roututine |
.data dd ? ;user-specific data |
.sizeof: |
} |
virtual at 0 |
IRQH IRQH |
end virtual |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/apic.inc |
---|
1,417 → 1,417 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
iglobal |
IRQ_COUNT dd 24 |
endg |
uglobal |
irq_mode rd 1 |
IOAPIC_base rd 1 |
LAPIC_BASE rd 1 |
endg |
APIC_ID equ 0x20 |
APIC_TPR equ 0x80 |
APIC_EOI equ 0xb0 |
APIC_LDR equ 0xd0 |
APIC_DFR equ 0xe0 |
APIC_SVR equ 0xf0 |
APIC_ISR equ 0x100 |
APIC_ESR equ 0x280 |
APIC_ICRL equ 0x300 |
APIC_ICRH equ 0x310 |
APIC_LVT_LINT0 equ 0x350 |
APIC_LVT_LINT1 equ 0x360 |
APIC_LVT_err equ 0x370 |
; APIC timer |
APIC_LVT_timer equ 0x320 |
APIC_timer_div equ 0x3e0 |
APIC_timer_init equ 0x380 |
APIC_timer_cur equ 0x390 |
; IOAPIC |
IOAPIC_ID equ 0x0 |
IOAPIC_VER equ 0x1 |
IOAPIC_ARB equ 0x2 |
IOAPIC_REDTBL equ 0x10 |
align 4 |
APIC_init: |
mov [irq_mode], IRQ_PIC |
cmp [acpi_ioapic_base], 0 |
jz .no_apic |
cmp [acpi_lapic_base], 0 |
jz .no_apic |
stdcall load_file, dev_data_path |
test eax, eax |
jz .no_apic |
mov [acpi_dev_data], eax |
mov [acpi_dev_size], ebx |
call IRQ_mask_all |
; IOAPIC init |
stdcall map_io_mem, [acpi_ioapic_base], 0x20, PG_SW |
mov [IOAPIC_base], eax |
mov eax, IOAPIC_VER |
call IOAPIC_read |
shr eax, 16 |
inc al |
movzx eax, al |
cmp al, IRQ_RESERVED |
jbe @f |
mov al, IRQ_RESERVED |
@@: |
mov [IRQ_COUNT], eax |
; Reroute IOAPIC & mask all interrupts |
xor ecx, ecx |
mov eax, IOAPIC_REDTBL |
@@: |
mov ebx, eax |
call IOAPIC_read |
mov ah, 0x09 ; Delivery Mode: Lowest Priority, Destination Mode: Logical |
mov al, cl |
add al, 0x20 ; vector |
or eax, 0x10000 ; Mask Interrupt |
cmp ecx, 16 |
jb .set |
or eax, 0xa000 ;<<< level-triggered active-low for IRQ16+ |
.set: |
xchg eax, ebx |
call IOAPIC_write |
inc eax |
mov ebx, eax |
call IOAPIC_read |
or eax, 0xff000000 ; Destination Field |
xchg eax, ebx |
call IOAPIC_write |
inc eax |
inc ecx |
cmp ecx, [IRQ_COUNT] |
jb @b |
call LAPIC_init |
mov [irq_mode], IRQ_APIC |
mov al, 0x70 |
out 0x22, al |
mov al, 1 |
out 0x23, al |
call pci_irq_fixup |
.no_apic: |
ret |
;=========================================================== |
align 4 |
LAPIC_init: |
; Check MSR support |
;.... |
; Get LAPIC base address |
; mov ecx, 0x1b |
; rdmsr ; it may be replaced to |
; and ax, 0xf000 ; mov eax, 0xfee00000 |
stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_SW |
mov [LAPIC_BASE], eax |
mov esi, eax |
; Program Destination Format Register for Flat mode. |
mov eax, [esi + APIC_DFR] |
or eax, 0xf0000000 |
mov [esi + APIC_DFR], eax |
; Program Logical Destination Register. |
mov eax, [esi + APIC_LDR] |
;and eax, 0xff000000 |
and eax, 0x00ffffff |
or eax, 0x01000000 ;!!!!!!!!!!!! |
mov [esi + APIC_LDR], eax |
; Task Priority Register initialization. |
mov eax, [esi + APIC_TPR] |
and eax, 0xffffff00 |
mov [esi + APIC_TPR], eax |
; Flush the queue |
mov edx, 0 |
.nxt2: |
mov ecx, 32 |
mov eax, [esi + APIC_ISR + edx] |
.nxt: |
shr eax, 1 |
jnc @f |
mov dword [esi + APIC_EOI], 0 ; EOI |
@@: |
loop .nxt |
add edx, 0x10 |
cmp edx, 0x170 |
jbe .nxt2 |
; Spurious-Interrupt Vector Register initialization. |
mov eax, [esi + APIC_SVR] |
or eax, 0x1ff |
and eax, 0xfffffdff |
mov [esi + APIC_SVR], eax |
; Initialize LVT LINT0 register. (INTR) |
mov eax, 0x00700 |
; mov eax, 0x10700 |
mov [esi + APIC_LVT_LINT0], eax |
; Initialize LVT LINT1 register. (NMI) |
mov eax, 0x00400 |
mov [esi + APIC_LVT_LINT1], eax |
; Initialize LVT Error register. |
mov eax, [esi + APIC_LVT_err] |
or eax, 0x10000 ; bit 16 |
mov [esi + APIC_LVT_err], eax |
; LAPIC timer |
; pre init |
mov dword[esi + APIC_timer_div], 1011b ; 1 |
mov dword[esi + APIC_timer_init], 0xffffffff ; max val |
push esi |
mov esi, 640 ; wait 0.64 sec |
call delay_ms |
pop esi |
mov eax, [esi + APIC_timer_cur] ; read current tick couner |
xor eax, 0xffffffff ; eax = 0xffffffff - eax |
shr eax, 6 ; eax /= 64; APIC ticks per 0.01 sec |
; Start (every 0.01 sec) |
mov dword[esi + APIC_LVT_timer], 0x30020 ; periodic int 0x20 |
mov dword[esi + APIC_timer_init], eax |
ret |
;=========================================================== |
; IOAPIC implementation |
align 4 |
IOAPIC_read: |
; in : EAX - IOAPIC register |
; out: EAX - readed value |
push esi |
mov esi, [IOAPIC_base] |
mov [esi], eax |
mov eax, [esi + 0x10] |
pop esi |
ret |
align 4 |
IOAPIC_write: |
; in : EAX - IOAPIC register |
; EBX - value |
; out: none |
push esi |
mov esi, [IOAPIC_base] |
mov [esi], eax |
mov [esi + 0x10], ebx |
pop esi |
ret |
;=========================================================== |
; Remap all IRQ to 0x20+ Vectors |
; IRQ0 to vector 0x20, IRQ1 to vector 0x21.... |
align 4 |
PIC_init: |
cli |
mov al,0x11 ; icw4, edge triggered |
out 0x20,al |
out 0xA0,al |
mov al,0x20 ; generate 0x20 + |
out 0x21,al |
mov al,0x28 ; generate 0x28 + |
out 0xA1,al |
mov al,0x04 ; slave at irq2 |
out 0x21,al |
mov al,0x02 ; at irq9 |
out 0xA1,al |
mov al,0x01 ; 8086 mode |
out 0x21,al |
out 0xA1,al |
call IRQ_mask_all |
; mov dword[irq_type_to_set], IRQ_TYPE_PIC |
ret |
; ----------------------------------------- |
; TIMER SET TO 1/100 S |
align 4 |
PIT_init: |
mov al,0x34 ; set to 100Hz |
out 0x43,al |
mov al,0x9b ; lsb 1193180 / 1193 |
out 0x40,al |
mov al,0x2e ; msb |
out 0x40,al |
ret |
; ----------------------------------------- |
align 4 |
unmask_timer: |
cmp [irq_mode], IRQ_APIC |
je @f |
stdcall enable_irq, 0 |
ret |
@@: |
; use PIT |
; in some systems PIT no connected to IOAPIC |
; mov eax, 0x14 |
; call IOAPIC_read |
; mov ah, 0x09 ; Delivery Mode: Lowest Priority, Destination Mode: Logical |
; mov al, 0x20 |
; or eax, 0x10000 ; Mask Interrupt |
; mov ebx, eax |
; mov eax, 0x14 |
; call IOAPIC_write |
; stdcall enable_irq, 2 |
; ret |
; use LAPIC timer |
mov esi, [LAPIC_BASE] |
mov eax, [esi + APIC_LVT_timer] |
and eax, 0xfffeffff |
mov [esi + APIC_LVT_timer], eax |
ret |
; ----------------------------------------- |
; Disable all IRQ |
align 4 |
IRQ_mask_all: |
cmp [irq_mode], IRQ_APIC |
je .APIC |
mov al, 0xFF |
out 0x21, al |
out 0xA1, al |
mov ecx,0x1000 |
ret |
.APIC: |
mov ecx, [IRQ_COUNT] |
mov eax, 0x10 |
@@: |
mov ebx, eax |
call IOAPIC_read |
or eax, 0x10000 ; bit 16 |
xchg eax, ebx |
call IOAPIC_write |
inc eax |
inc eax |
loop @b |
ret |
; ----------------------------------------- |
; End Of Interrupt |
; cl - IRQ number |
align 4 |
irq_eoi: ; __fastcall |
cmp [irq_mode], IRQ_APIC |
je .APIC |
cmp cl, 8 |
mov al, 0x20 |
jb @f |
out 0xa0, al |
@@: |
out 0x20, al |
ret |
.APIC: |
mov eax, [LAPIC_BASE] |
mov dword [eax + APIC_EOI], 0 ; EOI |
ret |
; ----------------------------------------- |
; from dll.inc |
align 4 |
proc enable_irq stdcall, irq_line:dword |
mov ebx, [irq_line] |
cmp [irq_mode], IRQ_APIC |
je .APIC |
mov edx, 0x21 |
cmp ebx, 8 |
jb @F |
mov edx, 0xA1 |
sub ebx,8 |
@@: |
in al,dx |
btr eax, ebx |
out dx, al |
ret |
.APIC: |
shl ebx, 1 |
add ebx, 0x10 |
mov eax, ebx |
call IOAPIC_read |
and eax, 0xfffeffff ; bit 16 |
xchg eax, ebx |
call IOAPIC_write |
ret |
endp |
align 4 |
pci_irq_fixup: |
push ebp |
mov esi, [acpi_dev_data] |
mov ebx, [acpi_dev_size] |
lea edi, [esi+ebx] |
.iterate: |
cmp esi, edi |
jae .done |
mov eax, [esi] |
cmp eax, -1 |
je .done |
movzx ebx, al |
movzx ebp, ah |
stdcall pci_read32, ebp, ebx, 0 |
cmp eax, [esi+4] |
jne .skip |
mov eax, [esi+8] |
stdcall pci_write8, ebp, ebx, 0x3C, eax |
.skip: |
add esi, 16 |
jmp .iterate |
.done: |
.fail: |
pop ebp |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
iglobal |
IRQ_COUNT dd 24 |
endg |
uglobal |
irq_mode rd 1 |
IOAPIC_base rd 1 |
LAPIC_BASE rd 1 |
endg |
APIC_ID equ 0x20 |
APIC_TPR equ 0x80 |
APIC_EOI equ 0xb0 |
APIC_LDR equ 0xd0 |
APIC_DFR equ 0xe0 |
APIC_SVR equ 0xf0 |
APIC_ISR equ 0x100 |
APIC_ESR equ 0x280 |
APIC_ICRL equ 0x300 |
APIC_ICRH equ 0x310 |
APIC_LVT_LINT0 equ 0x350 |
APIC_LVT_LINT1 equ 0x360 |
APIC_LVT_err equ 0x370 |
; APIC timer |
APIC_LVT_timer equ 0x320 |
APIC_timer_div equ 0x3e0 |
APIC_timer_init equ 0x380 |
APIC_timer_cur equ 0x390 |
; IOAPIC |
IOAPIC_ID equ 0x0 |
IOAPIC_VER equ 0x1 |
IOAPIC_ARB equ 0x2 |
IOAPIC_REDTBL equ 0x10 |
align 4 |
APIC_init: |
mov [irq_mode], IRQ_PIC |
cmp [acpi_ioapic_base], 0 |
jz .no_apic |
cmp [acpi_lapic_base], 0 |
jz .no_apic |
stdcall load_file, dev_data_path |
test eax, eax |
jz .no_apic |
mov [acpi_dev_data], eax |
mov [acpi_dev_size], ebx |
call IRQ_mask_all |
; IOAPIC init |
stdcall map_io_mem, [acpi_ioapic_base], 0x20, PG_SW |
mov [IOAPIC_base], eax |
mov eax, IOAPIC_VER |
call IOAPIC_read |
shr eax, 16 |
inc al |
movzx eax, al |
cmp al, IRQ_RESERVED |
jbe @f |
mov al, IRQ_RESERVED |
@@: |
mov [IRQ_COUNT], eax |
; Reroute IOAPIC & mask all interrupts |
xor ecx, ecx |
mov eax, IOAPIC_REDTBL |
@@: |
mov ebx, eax |
call IOAPIC_read |
mov ah, 0x09; Delivery Mode: Lowest Priority, Destination Mode: Logical |
mov al, cl |
add al, 0x20; vector |
or eax, 0x10000; Mask Interrupt |
cmp ecx, 16 |
jb .set |
or eax, 0xa000;<<< level-triggered active-low for IRQ16+ |
.set: |
xchg eax, ebx |
call IOAPIC_write |
inc eax |
mov ebx, eax |
call IOAPIC_read |
or eax, 0xff000000; Destination Field |
xchg eax, ebx |
call IOAPIC_write |
inc eax |
inc ecx |
cmp ecx, [IRQ_COUNT] |
jb @b |
call LAPIC_init |
mov [irq_mode], IRQ_APIC |
mov al, 0x70 |
out 0x22, al |
mov al, 1 |
out 0x23, al |
call pci_irq_fixup |
.no_apic: |
ret |
;=========================================================== |
align 4 |
LAPIC_init: |
; Check MSR support |
;.... |
; Get LAPIC base address |
; mov ecx, 0x1b |
; rdmsr ; it may be replaced to |
; and ax, 0xf000 ; mov eax, 0xfee00000 |
stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_SW |
mov [LAPIC_BASE], eax |
mov esi, eax |
; Program Destination Format Register for Flat mode. |
mov eax, [esi + APIC_DFR] |
or eax, 0xf0000000 |
mov [esi + APIC_DFR], eax |
; Program Logical Destination Register. |
mov eax, [esi + APIC_LDR] |
;and eax, 0xff000000 |
and eax, 0x00ffffff |
or eax, 0x01000000;!!!!!!!!!!!! |
mov [esi + APIC_LDR], eax |
; Task Priority Register initialization. |
mov eax, [esi + APIC_TPR] |
and eax, 0xffffff00 |
mov [esi + APIC_TPR], eax |
; Flush the queue |
mov edx, 0 |
.nxt2: |
mov ecx, 32 |
mov eax, [esi + APIC_ISR + edx] |
.nxt: |
shr eax, 1 |
jnc @f |
mov dword [esi + APIC_EOI], 0; EOI |
@@: |
loop .nxt |
add edx, 0x10 |
cmp edx, 0x170 |
jbe .nxt2 |
; Spurious-Interrupt Vector Register initialization. |
mov eax, [esi + APIC_SVR] |
or eax, 0x1ff |
and eax, 0xfffffdff |
mov [esi + APIC_SVR], eax |
; Initialize LVT LINT0 register. (INTR) |
mov eax, 0x00700 |
; mov eax, 0x10700 |
mov [esi + APIC_LVT_LINT0], eax |
; Initialize LVT LINT1 register. (NMI) |
mov eax, 0x00400 |
mov [esi + APIC_LVT_LINT1], eax |
; Initialize LVT Error register. |
mov eax, [esi + APIC_LVT_err] |
or eax, 0x10000; bit 16 |
mov [esi + APIC_LVT_err], eax |
; LAPIC timer |
; pre init |
mov dword[esi + APIC_timer_div], 1011b; 1 |
mov dword[esi + APIC_timer_init], 0xffffffff; max val |
push esi |
mov esi, 640 ; wait 0.64 sec |
call delay_ms |
pop esi |
mov eax, [esi + APIC_timer_cur]; read current tick couner |
xor eax, 0xffffffff ; eax = 0xffffffff - eax |
shr eax, 6 ; eax /= 64; APIC ticks per 0.01 sec |
; Start (every 0.01 sec) |
mov dword[esi + APIC_LVT_timer], 0x30020; periodic int 0x20 |
mov dword[esi + APIC_timer_init], eax |
ret |
;=========================================================== |
; IOAPIC implementation |
align 4 |
IOAPIC_read: |
; in : EAX - IOAPIC register |
; out: EAX - readed value |
push esi |
mov esi, [IOAPIC_base] |
mov [esi], eax |
mov eax, [esi + 0x10] |
pop esi |
ret |
align 4 |
IOAPIC_write: |
; in : EAX - IOAPIC register |
; EBX - value |
; out: none |
push esi |
mov esi, [IOAPIC_base] |
mov [esi], eax |
mov [esi + 0x10], ebx |
pop esi |
ret |
;=========================================================== |
; Remap all IRQ to 0x20+ Vectors |
; IRQ0 to vector 0x20, IRQ1 to vector 0x21.... |
align 4 |
PIC_init: |
cli |
mov al, 0x11 ; icw4, edge triggered |
out 0x20, al |
out 0xA0, al |
mov al, 0x20 ; generate 0x20 + |
out 0x21, al |
mov al, 0x28 ; generate 0x28 + |
out 0xA1, al |
mov al, 0x04 ; slave at irq2 |
out 0x21, al |
mov al, 0x02 ; at irq9 |
out 0xA1, al |
mov al, 0x01 ; 8086 mode |
out 0x21, al |
out 0xA1, al |
call IRQ_mask_all |
; mov dword[irq_type_to_set], IRQ_TYPE_PIC |
ret |
; ----------------------------------------- |
; TIMER SET TO 1/100 S |
align 4 |
PIT_init: |
mov al, 0x34 ; set to 100Hz |
out 0x43, al |
mov al, 0x9b ; lsb 1193180 / 1193 |
out 0x40, al |
mov al, 0x2e ; msb |
out 0x40, al |
ret |
; ----------------------------------------- |
align 4 |
unmask_timer: |
cmp [irq_mode], IRQ_APIC |
je @f |
stdcall enable_irq, 0 |
ret |
@@: |
; use PIT |
; in some systems PIT no connected to IOAPIC |
; mov eax, 0x14 |
; call IOAPIC_read |
; mov ah, 0x09 ; Delivery Mode: Lowest Priority, Destination Mode: Logical |
; mov al, 0x20 |
; or eax, 0x10000 ; Mask Interrupt |
; mov ebx, eax |
; mov eax, 0x14 |
; call IOAPIC_write |
; stdcall enable_irq, 2 |
; ret |
; use LAPIC timer |
mov esi, [LAPIC_BASE] |
mov eax, [esi + APIC_LVT_timer] |
and eax, 0xfffeffff |
mov [esi + APIC_LVT_timer], eax |
ret |
; ----------------------------------------- |
; Disable all IRQ |
align 4 |
IRQ_mask_all: |
cmp [irq_mode], IRQ_APIC |
je .APIC |
mov al, 0xFF |
out 0x21, al |
out 0xA1, al |
mov ecx, 0x1000 |
ret |
.APIC: |
mov ecx, [IRQ_COUNT] |
mov eax, 0x10 |
@@: |
mov ebx, eax |
call IOAPIC_read |
or eax, 0x10000; bit 16 |
xchg eax, ebx |
call IOAPIC_write |
inc eax |
inc eax |
loop @b |
ret |
; ----------------------------------------- |
; End Of Interrupt |
; cl - IRQ number |
align 4 |
irq_eoi: ; __fastcall |
cmp [irq_mode], IRQ_APIC |
je .APIC |
cmp cl, 8 |
mov al, 0x20 |
jb @f |
out 0xa0, al |
@@: |
out 0x20, al |
ret |
.APIC: |
mov eax, [LAPIC_BASE] |
mov dword [eax + APIC_EOI], 0; EOI |
ret |
; ----------------------------------------- |
; from dll.inc |
align 4 |
proc enable_irq stdcall, irq_line:dword |
mov ebx, [irq_line] |
cmp [irq_mode], IRQ_APIC |
je .APIC |
mov edx, 0x21 |
cmp ebx, 8 |
jb @F |
mov edx, 0xA1 |
sub ebx, 8 |
@@: |
in al, dx |
btr eax, ebx |
out dx, al |
ret |
.APIC: |
shl ebx, 1 |
add ebx, 0x10 |
mov eax, ebx |
call IOAPIC_read |
and eax, 0xfffeffff; bit 16 |
xchg eax, ebx |
call IOAPIC_write |
ret |
endp |
align 4 |
pci_irq_fixup: |
push ebp |
mov esi, [acpi_dev_data] |
mov ebx, [acpi_dev_size] |
lea edi, [esi+ebx] |
.iterate: |
cmp esi, edi |
jae .done |
mov eax, [esi] |
cmp eax, -1 |
je .done |
movzx ebx, al |
movzx ebp, ah |
stdcall pci_read32, ebp, ebx, 0 |
cmp eax, [esi+4] |
jne .skip |
mov eax, [esi+8] |
stdcall pci_write8, ebp, ebx, 0x3C, eax |
.skip: |
add esi, 16 |
jmp .iterate |
.done: |
.fail: |
pop ebp |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/conf_lib.inc |
---|
1,297 → 1,298 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;------------------------------------------------------------------------- |
;Loading configuration from ini file |
; {SPraid.simba} |
;------------------------------------------------------------------------- |
$Revision$ |
iglobal |
conf_path_sect: db 'path',0 |
conf_fname db '/sys/sys.conf',0 |
endg |
; set soke kernel configuration |
proc set_kernel_conf |
locals |
par db 30 dup(?) |
endl |
pushad |
;[gui] |
;mouse_speed |
lea eax,[par] |
push eax |
invoke ini.get_str,conf_fname, ugui, ugui_mouse_speed,\ |
eax,30, ugui_mouse_speed_def |
pop eax |
stdcall strtoint,eax |
mov [mouse_speed_factor], ax |
;mouse_delay |
lea eax,[par] |
push eax |
invoke ini.get_str,conf_fname, ugui, ugui_mouse_delay,\ |
eax,30, ugui_mouse_delay_def |
pop eax |
stdcall strtoint,eax |
mov [mouse_delay], eax |
;midibase |
lea eax,[par] |
push eax |
invoke ini.get_str,conf_fname, udev, udev_midibase, eax,30, udev_midibase_def |
pop eax |
stdcall strtoint,eax |
cmp eax, 0x100 |
jb @f |
cmp eax, 0x10000 |
jae @f |
mov [midi_base], ax |
mov [mididp], eax |
inc eax |
mov [midisp], eax |
@@: |
popad |
ret |
endp |
iglobal |
ugui db 'gui',0 |
ugui_mouse_speed db 'mouse_speed',0 |
ugui_mouse_speed_def db '2',0 |
ugui_mouse_delay db 'mouse_delay',0 |
ugui_mouse_delay_def db '0x00A',0 |
udev db 'dev',0 |
udev_midibase db 'midibase',0 |
udev_midibase_def db '0x320',0 |
endg |
;set up netvork configuration |
proc set_network_conf |
locals |
par db 30 dup(?) |
endl |
pushad |
;[net] |
;active |
lea eax,[par] |
invoke ini.get_int,conf_fname, unet, unet_active, 0 |
or eax,eax |
jz .do_not_set_net |
mov eax, [stack_config] |
and eax, 0xFFFFFF80 |
add eax, 3 |
mov [stack_config], eax |
call ash_eth_enable |
;addr |
lea eax,[par] |
push eax |
invoke ini.get_str,conf_fname, unet, unet_addr, eax,30, unet_def |
pop eax |
stdcall do_inet_adr,eax |
mov [stack_ip], eax |
;mask |
lea eax,[par] |
push eax |
invoke ini.get_str,conf_fname, unet, unet_mask, eax,30, unet_def |
pop eax |
stdcall do_inet_adr,eax |
mov [subnet_mask], eax |
;gate |
lea eax,[par] |
push eax |
invoke ini.get_str,conf_fname, unet, unet_gate, eax,30, unet_def |
pop eax |
stdcall do_inet_adr,eax |
mov [gateway_ip], eax |
.do_not_set_net: |
popad |
ret |
endp |
iglobal |
unet db 'net',0 |
unet_active db 'active',0 |
unet_addr db 'addr',0 |
unet_mask db 'mask',0 |
unet_gate db 'gate',0 |
unet_def db 0 |
endg |
; convert string to DWord |
proc strtoint stdcall,strs |
pushad |
mov eax,[strs] |
inc eax |
mov bl,[eax] |
cmp bl,'x' |
je .hex |
cmp bl,'X' |
je .hex |
jmp .dec |
.hex: |
inc eax |
stdcall strtoint_hex,eax |
jmp .exit |
.dec: |
dec eax |
stdcall strtoint_dec,eax |
.exit: |
mov [esp+28],eax |
popad |
ret |
endp |
; convert string to DWord for decimal value |
proc strtoint_dec stdcall,strs |
pushad |
xor edx,edx |
; ¯®¨áª ª®æ |
mov esi,[strs] |
@@: |
lodsb |
or al,al |
jnz @b |
mov ebx,esi |
mov esi,[strs] |
dec ebx |
sub ebx,esi |
mov ecx,1 |
@@: |
dec ebx |
or ebx,ebx |
jz @f |
imul ecx,ecx,10 ; ¯®à冷ª |
jmp @b |
@@: |
xchg ebx,ecx |
xor ecx,ecx |
@@: |
xor eax,eax |
lodsb |
cmp al,0 |
je .eend |
sub al,30h |
imul ebx |
add ecx,eax |
push ecx |
xchg eax,ebx |
mov ecx,10 |
div ecx |
xchg eax,ebx |
pop ecx |
jmp @b |
.eend: |
mov [esp+28],ecx |
popad |
ret |
endp |
;convert string to DWord for hex value |
proc strtoint_hex stdcall,strs |
pushad |
xor edx,edx |
mov esi,[strs] |
mov ebx,1 |
add esi,1 |
@@: |
lodsb |
or al,al |
jz @f |
shl ebx,4 |
jmp @b |
@@: |
xor ecx,ecx |
mov esi,[strs] |
@@: |
xor eax,eax |
lodsb |
cmp al,0 |
je .eend |
cmp al,'a' |
jae .bm |
cmp al,'A' |
jae .bb |
jmp .cc |
.bm: ; 57h |
sub al,57h |
jmp .do |
.bb: ; 37h |
sub al,37h |
jmp .do |
.cc: ; 30h |
sub al,30h |
.do: |
imul ebx |
add ecx,eax |
shr ebx,4 |
jmp @b |
.eend: |
mov [esp+28],ecx |
popad |
ret |
endp |
; convert string to DWord for IP addres |
proc do_inet_adr stdcall,strs |
pushad |
mov esi,[strs] |
mov ebx,0 |
.next: |
push esi |
@@: |
lodsb |
or al,al |
jz @f |
cmp al,'.' |
jz @f |
jmp @b |
@@: |
mov cl, al |
mov [esi-1],byte 0 |
;pop eax |
call strtoint_dec |
rol eax,24 |
ror ebx,8 |
add ebx,eax |
or cl,cl |
jz @f |
jmp .next |
@@: |
mov [esp+28],ebx |
popad |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;------------------------------------------------------------------------- |
;Loading configuration from ini file |
; {SPraid.simba} |
;------------------------------------------------------------------------- |
$Revision$ |
iglobal |
conf_path_sect: |
db 'path',0 |
conf_fname db '/sys/sys.conf',0 |
endg |
; set soke kernel configuration |
proc set_kernel_conf |
locals |
par db 30 dup(?) |
endl |
pushad |
;[gui] |
;mouse_speed |
lea eax, [par] |
push eax |
invoke ini.get_str, conf_fname, ugui, ugui_mouse_speed, \ |
eax,30, ugui_mouse_speed_def |
pop eax |
stdcall strtoint, eax |
mov [mouse_speed_factor], ax |
;mouse_delay |
lea eax, [par] |
push eax |
invoke ini.get_str, conf_fname, ugui, ugui_mouse_delay, \ |
eax,30, ugui_mouse_delay_def |
pop eax |
stdcall strtoint, eax |
mov [mouse_delay], eax |
;midibase |
lea eax, [par] |
push eax |
invoke ini.get_str, conf_fname, udev, udev_midibase, eax, 30, udev_midibase_def |
pop eax |
stdcall strtoint, eax |
cmp eax, 0x100 |
jb @f |
cmp eax, 0x10000 |
jae @f |
mov [midi_base], ax |
mov [mididp], eax |
inc eax |
mov [midisp], eax |
@@: |
popad |
ret |
endp |
iglobal |
ugui db 'gui',0 |
ugui_mouse_speed db 'mouse_speed',0 |
ugui_mouse_speed_def db '2',0 |
ugui_mouse_delay db 'mouse_delay',0 |
ugui_mouse_delay_def db '0x00A',0 |
udev db 'dev',0 |
udev_midibase db 'midibase',0 |
udev_midibase_def db '0x320',0 |
endg |
;set up netvork configuration |
proc set_network_conf |
locals |
par db 30 dup(?) |
endl |
pushad |
;[net] |
;active |
lea eax, [par] |
invoke ini.get_int, conf_fname, unet, unet_active, 0 |
or eax, eax |
jz .do_not_set_net |
mov eax, [stack_config] |
and eax, 0xFFFFFF80 |
add eax, 3 |
mov [stack_config], eax |
call ash_eth_enable |
;addr |
lea eax, [par] |
push eax |
invoke ini.get_str, conf_fname, unet, unet_addr, eax, 30, unet_def |
pop eax |
stdcall do_inet_adr, eax |
mov [stack_ip], eax |
;mask |
lea eax, [par] |
push eax |
invoke ini.get_str, conf_fname, unet, unet_mask, eax, 30, unet_def |
pop eax |
stdcall do_inet_adr, eax |
mov [subnet_mask], eax |
;gate |
lea eax, [par] |
push eax |
invoke ini.get_str, conf_fname, unet, unet_gate, eax, 30, unet_def |
pop eax |
stdcall do_inet_adr, eax |
mov [gateway_ip], eax |
.do_not_set_net: |
popad |
ret |
endp |
iglobal |
unet db 'net',0 |
unet_active db 'active',0 |
unet_addr db 'addr',0 |
unet_mask db 'mask',0 |
unet_gate db 'gate',0 |
unet_def db 0 |
endg |
; convert string to DWord |
proc strtoint stdcall,strs |
pushad |
mov eax, [strs] |
inc eax |
mov bl, [eax] |
cmp bl, 'x' |
je .hex |
cmp bl, 'X' |
je .hex |
jmp .dec |
.hex: |
inc eax |
stdcall strtoint_hex, eax |
jmp .exit |
.dec: |
dec eax |
stdcall strtoint_dec, eax |
.exit: |
mov [esp+28], eax |
popad |
ret |
endp |
; convert string to DWord for decimal value |
proc strtoint_dec stdcall,strs |
pushad |
xor edx, edx |
; ¯®¨áª ª®æ |
mov esi, [strs] |
@@: |
lodsb |
or al, al |
jnz @b |
mov ebx, esi |
mov esi, [strs] |
dec ebx |
sub ebx, esi |
mov ecx, 1 |
@@: |
dec ebx |
or ebx, ebx |
jz @f |
imul ecx, ecx, 10; ¯®à冷ª |
jmp @b |
@@: |
xchg ebx, ecx |
xor ecx, ecx |
@@: |
xor eax, eax |
lodsb |
cmp al, 0 |
je .eend |
sub al, 30h |
imul ebx |
add ecx, eax |
push ecx |
xchg eax, ebx |
mov ecx, 10 |
div ecx |
xchg eax, ebx |
pop ecx |
jmp @b |
.eend: |
mov [esp+28], ecx |
popad |
ret |
endp |
;convert string to DWord for hex value |
proc strtoint_hex stdcall,strs |
pushad |
xor edx, edx |
mov esi, [strs] |
mov ebx, 1 |
add esi, 1 |
@@: |
lodsb |
or al, al |
jz @f |
shl ebx, 4 |
jmp @b |
@@: |
xor ecx, ecx |
mov esi, [strs] |
@@: |
xor eax, eax |
lodsb |
cmp al, 0 |
je .eend |
cmp al, 'a' |
jae .bm |
cmp al, 'A' |
jae .bb |
jmp .cc |
.bm: ; 57h |
sub al, 57h |
jmp .do |
.bb: ; 37h |
sub al, 37h |
jmp .do |
.cc: ; 30h |
sub al, 30h |
.do: |
imul ebx |
add ecx, eax |
shr ebx, 4 |
jmp @b |
.eend: |
mov [esp+28], ecx |
popad |
ret |
endp |
; convert string to DWord for IP addres |
proc do_inet_adr stdcall,strs |
pushad |
mov esi, [strs] |
mov ebx, 0 |
.next: |
push esi |
@@: |
lodsb |
or al, al |
jz @f |
cmp al, '.' |
jz @f |
jmp @b |
@@: |
mov cl, al |
mov [esi-1], byte 0 |
;pop eax |
call strtoint_dec |
rol eax, 24 |
ror ebx, 8 |
add ebx, eax |
or cl, cl |
jz @f |
jmp .next |
@@: |
mov [esp+28], ebx |
popad |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/debug.inc |
---|
1,429 → 1,435 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; diamond, 2006 |
sys_debug_services: |
cmp ebx, 9 |
ja @f |
jmp dword [sys_debug_services_table+ebx*4] |
@@: ret |
iglobal |
align 4 |
sys_debug_services_table: |
dd debug_set_event_data |
dd debug_getcontext |
dd debug_setcontext |
dd debug_detach |
dd debug_suspend |
dd debug_resume |
dd debug_read_process_memory |
dd debug_write_process_memory |
dd debug_terminate |
dd debug_set_drx |
endg |
debug_set_event_data: |
; in: ecx = pointer |
; destroys eax |
mov eax, [current_slot] |
mov [eax+APPDATA.dbg_event_mem], ecx |
ret |
get_debuggee_slot: |
; in: ecx=PID |
; out: CF=1 if error |
; CF=0 and eax=slot*0x20 if ok |
; out: interrupts disabled |
cli |
mov eax, ecx |
call pid_to_slot |
test eax, eax |
jz .ret_bad |
shl eax, 5 |
push ebx |
mov ebx, [CURRENT_TASK] |
cmp [SLOT_BASE+eax*8+APPDATA.debugger_slot], ebx |
pop ebx |
jnz .ret_bad |
; clc ; automatically |
ret |
.ret_bad: |
stc |
ret |
debug_detach: |
; in: ecx=pid |
; destroys eax,ebx |
call get_debuggee_slot |
jc .ret |
and dword [eax*8+SLOT_BASE+APPDATA.debugger_slot], 0 |
call do_resume |
.ret: |
sti |
ret |
debug_terminate: |
; in: ecx=pid |
call get_debuggee_slot |
jc debug_detach.ret |
mov ecx, eax |
shr ecx, 5 |
; push 2 |
; pop ebx |
mov edx,esi |
jmp sysfn_terminate |
debug_suspend: |
; in: ecx=pid |
; destroys eax,ecx |
cli |
mov eax, ecx |
call pid_to_slot |
shl eax, 5 |
jz .ret |
mov cl, [CURRENT_TASK+eax+TASKDATA.state] ; process state |
test cl, cl |
jz .1 |
cmp cl, 5 |
jnz .ret |
mov cl, 2 |
.2: mov [CURRENT_TASK+eax+TASKDATA.state], cl |
.ret: |
sti |
ret |
.1: |
inc ecx |
jmp .2 |
do_resume: |
mov cl, [CURRENT_TASK+eax+TASKDATA.state] |
cmp cl, 1 |
jz .1 |
cmp cl, 2 |
jnz .ret |
mov cl, 5 |
.2: mov [CURRENT_TASK+eax+TASKDATA.state], cl |
.ret: ret |
.1: dec ecx |
jmp .2 |
debug_resume: |
; in: ecx=pid |
; destroys eax,ebx |
cli |
mov eax, ecx |
call pid_to_slot |
shl eax, 5 |
jz .ret |
call do_resume |
.ret: sti |
ret |
debug_getcontext: |
; in: |
; ecx=pid |
; edx=sizeof(CONTEXT) |
; esi->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp edx, 28h |
jnz .ret |
; push ecx |
; mov ecx, esi |
call check_region |
; pop ecx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .ret |
mov edi, esi |
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] |
lea esi, [eax+RING0_STACK_SIZE] |
.ring0: |
; note that following code assumes that all interrupt/exception handlers |
; saves ring-3 context by pushad in this order |
; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), pushad |
sub esi, 8+12+20h |
lodsd ;edi |
mov [edi+24h], eax |
lodsd ;esi |
mov [edi+20h], eax |
lodsd ; ebp |
mov [edi+1Ch], eax |
lodsd ;esp |
lodsd ;ebx |
mov [edi+14h], eax |
lodsd ;edx |
mov [edi+10h], eax |
lodsd ;ecx |
mov [edi+0Ch], eax |
lodsd ;eax |
mov [edi+8], eax |
lodsd ;eip |
mov [edi], eax |
lodsd ;cs |
lodsd ;eflags |
mov [edi+4], eax |
lodsd ;esp |
mov [edi+18h], eax |
.ret: |
sti |
ret |
debug_setcontext: |
; in: |
; ecx=pid |
; edx=sizeof(CONTEXT) |
; esi->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp edx, 28h |
jnz .ret |
; push ebx |
; mov ebx, edx |
call check_region |
; pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .stiret |
; mov esi, edx |
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] |
lea edi, [eax+RING0_STACK_SIZE] |
.ring0: |
sub edi, 8+12+20h |
mov eax, [esi+24h] ;edi |
stosd |
mov eax, [esi+20h] ;esi |
stosd |
mov eax, [esi+1Ch] ;ebp |
stosd |
scasd |
mov eax, [esi+14h] ;ebx |
stosd |
mov eax, [esi+10h] ;edx |
stosd |
mov eax, [esi+0Ch] ;ecx |
stosd |
mov eax, [esi+8] ;eax |
stosd |
mov eax, [esi] ;eip |
stosd |
scasd |
mov eax, [esi+4] ;eflags |
stosd |
mov eax, [esi+18h] ;esp |
stosd |
.stiret: |
sti |
.ret: |
ret |
debug_set_drx: |
call get_debuggee_slot |
jc .errret |
mov ebp, eax |
lea eax, [eax*8+SLOT_BASE+APPDATA.dbg_regs] |
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3 |
; [eax+10]=dr7 |
cmp esi, OS_BASE |
jae .errret |
cmp dl, 3 |
ja .errret |
mov ecx, dr7 |
;fix me |
xchg ecx,edx |
shr edx, cl |
shr edx, cl |
xchg ecx,edx |
test ecx, 2 ; bit 1+2*index = G0..G3, global break enable |
jnz .errret2 |
test dh, dh |
jns .new |
; clear breakpoint |
movzx edx, dl |
add edx, edx |
and dword [eax+edx*2], 0 ; clear DR<i> |
btr dword [eax+10h], edx ; clear L<i> bit |
test byte [eax+10h], 55h |
jnz .okret |
; imul eax, ebp, tss_step/32 |
; and byte [eax + tss_data + TSS._trap], not 1 |
and [ebp*8 + SLOT_BASE+APPDATA.dbg_state], not 1 |
.okret: |
and dword [esp+32], 0 |
sti |
ret |
.errret: |
sti |
mov dword [esp+32], 1 |
ret |
.errret2: |
sti |
mov dword [esp+32], 2 |
ret |
.new: |
; add new breakpoint |
; dl=index; dh=flags; esi=address |
test dh, 0xF0 |
jnz .errret |
mov cl, dh |
and cl, 3 |
cmp cl, 2 |
jz .errret |
mov cl, dh |
shr cl, 2 |
cmp cl, 2 |
jz .errret |
mov ebx,esi |
test bl, dl |
jnz .errret |
or byte [eax+10h+1], 3 ; set GE and LE flags |
movzx edx, dh |
movzx ecx, dl |
add ecx, ecx |
bts dword [eax+10h], ecx ; set L<i> flag |
add ecx, ecx |
mov [eax+ecx], ebx;esi ; set DR<i> |
shl edx, cl |
mov ebx, 0xF |
shl ebx, cl |
not ebx |
and [eax+10h+2], bx |
or [eax+10h+2], dx ; set R/W and LEN fields |
; imul eax, ebp, tss_step/32 |
; or byte [eax + tss_data + TSS._trap], 1 |
or [ebp*8 + SLOT_BASE+APPDATA.dbg_state], 1 |
jmp .okret |
debug_read_process_memory: |
; in: |
; ecx=pid |
; edx=length |
; edi->buffer in debugger |
; esi=address in debuggee |
; out: [esp+36]=sizeof(read) |
; destroys all |
; push ebx |
; mov ebx, esi |
call check_region |
; pop ebx |
dec eax |
jnz .err |
call get_debuggee_slot |
jc .err |
shr eax, 5 |
mov ecx, edi |
call read_process_memory |
sti |
mov dword [esp+32], eax |
ret |
.err: |
or dword [esp+32], -1 |
ret |
debug_write_process_memory: |
; in: |
; ecx=pid |
; edx=length |
; edi->buffer in debugger |
; esi=address in debuggee |
; out: [esp+36]=sizeof(write) |
; destroys all |
; push ebx |
; mov ebx, esi |
call check_region |
; pop ebx |
dec eax |
jnz debug_read_process_memory.err |
call get_debuggee_slot |
jc debug_read_process_memory.err |
shr eax, 5 |
mov ecx, edi |
call write_process_memory |
sti |
mov [esp+32], eax |
ret |
debugger_notify: |
; in: eax=debugger slot |
; ecx=size of debug message |
; [esp+4]..[esp+4+ecx]=message |
; interrupts must be disabled! |
; destroys all general registers |
; interrupts remain disabled |
xchg ebp, eax |
mov edi, [timer_ticks] |
add edi, 500 ; 5 sec timeout |
.1: |
mov eax, ebp |
shl eax, 8 |
mov esi, [SLOT_BASE+eax+APPDATA.dbg_event_mem] |
test esi, esi |
jz .ret |
; read buffer header |
push ecx |
push eax |
push eax |
mov eax, ebp |
mov ecx, esp |
mov edx, 8 |
call read_process_memory |
cmp eax, edx |
jz @f |
add esp, 12 |
jmp .ret |
@@: |
cmp dword [ecx], 0 |
jg @f |
.2: |
pop ecx |
pop ecx |
pop ecx |
cmp dword [CURRENT_TASK], 1 |
jnz .notos |
cmp [timer_ticks], edi |
jae .ret |
.notos: |
sti |
call change_task |
cli |
jmp .1 |
@@: |
mov edx, [ecx+8] |
add edx, [ecx+4] |
cmp edx, [ecx] |
ja .2 |
; advance buffer position |
push edx |
mov edx, 4 |
sub ecx, edx |
mov eax, ebp |
add esi, edx |
call write_process_memory |
pop eax |
; write message |
mov eax, ebp |
add esi, edx |
add esi, [ecx+8] |
add ecx, 20 |
pop edx |
pop edx |
pop edx |
call write_process_memory |
; new debug event |
mov eax, ebp |
shl eax, 8 |
or byte [SLOT_BASE+eax+APPDATA.event_mask+1], 1 ; set flag 100h |
.ret: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; diamond, 2006 |
sys_debug_services: |
cmp ebx, 9 |
ja @f |
jmp dword [sys_debug_services_table+ebx*4] |
@@: |
ret |
iglobal |
align 4 |
sys_debug_services_table: |
dd debug_set_event_data |
dd debug_getcontext |
dd debug_setcontext |
dd debug_detach |
dd debug_suspend |
dd debug_resume |
dd debug_read_process_memory |
dd debug_write_process_memory |
dd debug_terminate |
dd debug_set_drx |
endg |
debug_set_event_data: |
; in: ecx = pointer |
; destroys eax |
mov eax, [current_slot] |
mov [eax+APPDATA.dbg_event_mem], ecx |
ret |
get_debuggee_slot: |
; in: ecx=PID |
; out: CF=1 if error |
; CF=0 and eax=slot*0x20 if ok |
; out: interrupts disabled |
cli |
mov eax, ecx |
call pid_to_slot |
test eax, eax |
jz .ret_bad |
shl eax, 5 |
push ebx |
mov ebx, [CURRENT_TASK] |
cmp [SLOT_BASE+eax*8+APPDATA.debugger_slot], ebx |
pop ebx |
jnz .ret_bad |
; clc ; automatically |
ret |
.ret_bad: |
stc |
ret |
debug_detach: |
; in: ecx=pid |
; destroys eax,ebx |
call get_debuggee_slot |
jc .ret |
and dword [eax*8+SLOT_BASE+APPDATA.debugger_slot], 0 |
call do_resume |
.ret: |
sti |
ret |
debug_terminate: |
; in: ecx=pid |
call get_debuggee_slot |
jc debug_detach.ret |
mov ecx, eax |
shr ecx, 5 |
; push 2 |
; pop ebx |
mov edx, esi |
jmp sysfn_terminate |
debug_suspend: |
; in: ecx=pid |
; destroys eax,ecx |
cli |
mov eax, ecx |
call pid_to_slot |
shl eax, 5 |
jz .ret |
mov cl, [CURRENT_TASK+eax+TASKDATA.state] ; process state |
test cl, cl |
jz .1 |
cmp cl, 5 |
jnz .ret |
mov cl, 2 |
.2: |
mov [CURRENT_TASK+eax+TASKDATA.state], cl |
.ret: |
sti |
ret |
.1: |
inc ecx |
jmp .2 |
do_resume: |
mov cl, [CURRENT_TASK+eax+TASKDATA.state] |
cmp cl, 1 |
jz .1 |
cmp cl, 2 |
jnz .ret |
mov cl, 5 |
.2: |
mov [CURRENT_TASK+eax+TASKDATA.state], cl |
.ret: |
ret |
.1: |
dec ecx |
jmp .2 |
debug_resume: |
; in: ecx=pid |
; destroys eax,ebx |
cli |
mov eax, ecx |
call pid_to_slot |
shl eax, 5 |
jz .ret |
call do_resume |
.ret: |
sti |
ret |
debug_getcontext: |
; in: |
; ecx=pid |
; edx=sizeof(CONTEXT) |
; esi->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp edx, 28h |
jnz .ret |
; push ecx |
; mov ecx, esi |
call check_region |
; pop ecx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .ret |
mov edi, esi |
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] |
lea esi, [eax+RING0_STACK_SIZE] |
.ring0: |
; note that following code assumes that all interrupt/exception handlers |
; saves ring-3 context by pushad in this order |
; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), pushad |
sub esi, 8+12+20h |
lodsd ;edi |
mov [edi+24h], eax |
lodsd ;esi |
mov [edi+20h], eax |
lodsd ; ebp |
mov [edi+1Ch], eax |
lodsd ;esp |
lodsd ;ebx |
mov [edi+14h], eax |
lodsd ;edx |
mov [edi+10h], eax |
lodsd ;ecx |
mov [edi+0Ch], eax |
lodsd ;eax |
mov [edi+8], eax |
lodsd ;eip |
mov [edi], eax |
lodsd ;cs |
lodsd ;eflags |
mov [edi+4], eax |
lodsd ;esp |
mov [edi+18h], eax |
.ret: |
sti |
ret |
debug_setcontext: |
; in: |
; ecx=pid |
; edx=sizeof(CONTEXT) |
; esi->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp edx, 28h |
jnz .ret |
; push ebx |
; mov ebx, edx |
call check_region |
; pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .stiret |
; mov esi, edx |
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] |
lea edi, [eax+RING0_STACK_SIZE] |
.ring0: |
sub edi, 8+12+20h |
mov eax, [esi+24h] ;edi |
stosd |
mov eax, [esi+20h] ;esi |
stosd |
mov eax, [esi+1Ch] ;ebp |
stosd |
scasd |
mov eax, [esi+14h] ;ebx |
stosd |
mov eax, [esi+10h] ;edx |
stosd |
mov eax, [esi+0Ch] ;ecx |
stosd |
mov eax, [esi+8] ;eax |
stosd |
mov eax, [esi] ;eip |
stosd |
scasd |
mov eax, [esi+4] ;eflags |
stosd |
mov eax, [esi+18h] ;esp |
stosd |
.stiret: |
sti |
.ret: |
ret |
debug_set_drx: |
call get_debuggee_slot |
jc .errret |
mov ebp, eax |
lea eax, [eax*8+SLOT_BASE+APPDATA.dbg_regs] |
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3 |
; [eax+10]=dr7 |
cmp esi, OS_BASE |
jae .errret |
cmp dl, 3 |
ja .errret |
mov ecx, dr7 |
;fix me |
xchg ecx, edx |
shr edx, cl |
shr edx, cl |
xchg ecx, edx |
test ecx, 2 ; bit 1+2*index = G0..G3, global break enable |
jnz .errret2 |
test dh, dh |
jns .new |
; clear breakpoint |
movzx edx, dl |
add edx, edx |
and dword [eax+edx*2], 0 ; clear DR<i> |
btr dword [eax+10h], edx ; clear L<i> bit |
test byte [eax+10h], 55h |
jnz .okret |
; imul eax, ebp, tss_step/32 |
; and byte [eax + tss_data + TSS._trap], not 1 |
and [ebp*8 + SLOT_BASE+APPDATA.dbg_state], not 1 |
.okret: |
and dword [esp+32], 0 |
sti |
ret |
.errret: |
sti |
mov dword [esp+32], 1 |
ret |
.errret2: |
sti |
mov dword [esp+32], 2 |
ret |
.new: |
; add new breakpoint |
; dl=index; dh=flags; esi=address |
test dh, 0xF0 |
jnz .errret |
mov cl, dh |
and cl, 3 |
cmp cl, 2 |
jz .errret |
mov cl, dh |
shr cl, 2 |
cmp cl, 2 |
jz .errret |
mov ebx, esi |
test bl, dl |
jnz .errret |
or byte [eax+10h+1], 3 ; set GE and LE flags |
movzx edx, dh |
movzx ecx, dl |
add ecx, ecx |
bts dword [eax+10h], ecx ; set L<i> flag |
add ecx, ecx |
mov [eax+ecx], ebx;esi ; set DR<i> |
shl edx, cl |
mov ebx, 0xF |
shl ebx, cl |
not ebx |
and [eax+10h+2], bx |
or [eax+10h+2], dx ; set R/W and LEN fields |
; imul eax, ebp, tss_step/32 |
; or byte [eax + tss_data + TSS._trap], 1 |
or [ebp*8 + SLOT_BASE+APPDATA.dbg_state], 1 |
jmp .okret |
debug_read_process_memory: |
; in: |
; ecx=pid |
; edx=length |
; edi->buffer in debugger |
; esi=address in debuggee |
; out: [esp+36]=sizeof(read) |
; destroys all |
; push ebx |
; mov ebx, esi |
call check_region |
; pop ebx |
dec eax |
jnz .err |
call get_debuggee_slot |
jc .err |
shr eax, 5 |
mov ecx, edi |
call read_process_memory |
sti |
mov dword [esp+32], eax |
ret |
.err: |
or dword [esp+32], -1 |
ret |
debug_write_process_memory: |
; in: |
; ecx=pid |
; edx=length |
; edi->buffer in debugger |
; esi=address in debuggee |
; out: [esp+36]=sizeof(write) |
; destroys all |
; push ebx |
; mov ebx, esi |
call check_region |
; pop ebx |
dec eax |
jnz debug_read_process_memory.err |
call get_debuggee_slot |
jc debug_read_process_memory.err |
shr eax, 5 |
mov ecx, edi |
call write_process_memory |
sti |
mov [esp+32], eax |
ret |
debugger_notify: |
; in: eax=debugger slot |
; ecx=size of debug message |
; [esp+4]..[esp+4+ecx]=message |
; interrupts must be disabled! |
; destroys all general registers |
; interrupts remain disabled |
xchg ebp, eax |
mov edi, [timer_ticks] |
add edi, 500 ; 5 sec timeout |
.1: |
mov eax, ebp |
shl eax, 8 |
mov esi, [SLOT_BASE+eax+APPDATA.dbg_event_mem] |
test esi, esi |
jz .ret |
; read buffer header |
push ecx |
push eax |
push eax |
mov eax, ebp |
mov ecx, esp |
mov edx, 8 |
call read_process_memory |
cmp eax, edx |
jz @f |
add esp, 12 |
jmp .ret |
@@: |
cmp dword [ecx], 0 |
jg @f |
.2: |
pop ecx |
pop ecx |
pop ecx |
cmp dword [CURRENT_TASK], 1 |
jnz .notos |
cmp [timer_ticks], edi |
jae .ret |
.notos: |
sti |
call change_task |
cli |
jmp .1 |
@@: |
mov edx, [ecx+8] |
add edx, [ecx+4] |
cmp edx, [ecx] |
ja .2 |
; advance buffer position |
push edx |
mov edx, 4 |
sub ecx, edx |
mov eax, ebp |
add esi, edx |
call write_process_memory |
pop eax |
; write message |
mov eax, ebp |
add esi, edx |
add esi, [ecx+8] |
add ecx, 20 |
pop edx |
pop edx |
pop edx |
call write_process_memory |
; new debug event |
mov eax, ebp |
shl eax, 8 |
or byte [SLOT_BASE+eax+APPDATA.event_mask+1], 1 ; set flag 100h |
.ret: |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/dll.inc |
---|
1,1447 → 1,1447 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
DRV_COMPAT equ 5 ;minimal required drivers version |
DRV_CURRENT equ 6 ;current drivers model version |
DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT |
PID_KERNEL equ 1 ;os_idle thread |
align 4 |
proc get_notify stdcall, p_ev:dword |
.wait: |
mov ebx,[current_slot] |
test dword [ebx+APPDATA.event_mask],EVENT_NOTIFY |
jz @f |
and dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY |
mov edi, [p_ev] |
mov dword [edi], EV_INTR |
mov eax, [ebx+APPDATA.event] |
mov dword [edi+4], eax |
ret |
@@: |
call change_task |
jmp .wait |
endp |
align 4 |
proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 6 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
call pci_read_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 5 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
call pci_read_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 4 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
call pci_read_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 8 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
mov ecx, [val] |
call pci_write_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 9 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
mov ecx, [val] |
call pci_write_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 10 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
mov ecx, [val] |
call pci_write_reg |
pop ebx |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc srv_handler stdcall, ioctl:dword |
mov esi, [ioctl] |
test esi, esi |
jz .err |
mov edi, [esi+handle] |
cmp [edi+SRV.magic], ' SRV' |
jne .fail |
cmp [edi+SRV.size], SRV.sizeof |
jne .fail |
stdcall [edi+SRV.srv_proc], esi |
ret |
.fail: |
xor eax, eax |
not eax |
mov [esi+output], eax |
mov [esi+out_size], 4 |
ret |
.err: |
xor eax, eax |
not eax |
ret |
endp |
; param |
; ecx= io_control |
; |
; retval |
; eax= error code |
align 4 |
srv_handlerEx: |
cmp ecx, OS_BASE |
jae .fail |
mov eax, [ecx+handle] |
cmp [eax+SRV.magic], ' SRV' |
jne .fail |
cmp [eax+SRV.size], SRV.sizeof |
jne .fail |
stdcall [eax+SRV.srv_proc], ecx |
ret |
.fail: |
or eax, -1 |
ret |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc get_service stdcall, sz_name:dword |
mov eax, [sz_name] |
test eax, eax |
jnz @F |
ret |
@@: |
mov edx, [srv.fd] |
@@: |
cmp edx, srv.fd-SRV_FD_OFFSET |
je .not_load |
stdcall strncmp, edx, [sz_name], 16 |
test eax, eax |
je .ok |
mov edx, [edx+SRV.fd] |
jmp @B |
.not_load: |
pop ebp |
jmp load_driver |
.ok: |
mov eax, edx |
ret |
endp |
align 4 |
proc reg_service stdcall, name:dword, handler:dword |
push ebx |
xor eax, eax |
cmp [name], eax |
je .fail |
cmp [handler], eax |
je .fail |
mov eax, SRV.sizeof |
call malloc |
test eax, eax |
jz .fail |
push esi |
push edi |
mov edi, eax |
mov esi, [name] |
movsd |
movsd |
movsd |
movsd |
pop edi |
pop esi |
mov [eax+SRV.magic], ' SRV' |
mov [eax+SRV.size], SRV.sizeof |
mov ebx, srv.fd-SRV_FD_OFFSET |
mov edx, [ebx+SRV.fd] |
mov [eax+SRV.fd], edx |
mov [eax+SRV.bk], ebx |
mov [ebx+SRV.fd], eax |
mov [edx+SRV.bk], eax |
mov ecx, [handler] |
mov [eax+SRV.srv_proc], ecx |
pop ebx |
ret |
.fail: |
xor eax, eax |
pop ebx |
ret |
endp |
align 4 |
proc get_proc stdcall, exp:dword, sz_name:dword |
mov edx, [exp] |
.next: |
mov eax, [edx] |
test eax, eax |
jz .end |
push edx |
stdcall strncmp, eax, [sz_name], 16 |
pop edx |
test eax, eax |
jz .ok |
add edx,8 |
jmp .next |
.ok: |
mov eax, [edx+4] |
.end: |
ret |
endp |
align 4 |
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword |
@@: |
stdcall strncmp, [pSym], [sz_sym], 8 |
test eax,eax |
jz .ok |
add [pSym], 18 |
dec [count] |
jnz @b |
xor eax, eax |
ret |
.ok: |
mov eax, [pSym] |
mov eax, [eax+8] |
ret |
endp |
align 4 |
proc get_curr_task |
mov eax,[CURRENT_TASK] |
shl eax, 8 |
ret |
endp |
align 4 |
proc get_fileinfo stdcall, file_name:dword, info:dword |
locals |
cmd dd ? |
offset dd ? |
dd ? |
count dd ? |
buff dd ? |
db ? |
name dd ? |
endl |
xor eax, eax |
mov ebx, [file_name] |
mov ecx, [info] |
mov [cmd], 5 |
mov [offset], eax |
mov [offset+4], eax |
mov [count], eax |
mov [buff], ecx |
mov byte [buff+4], al |
mov [name], ebx |
mov eax, 70 |
lea ebx, [cmd] |
int 0x40 |
ret |
endp |
align 4 |
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\ |
bytes:dword |
locals |
cmd dd ? |
offset dd ? |
dd ? |
count dd ? |
buff dd ? |
db ? |
name dd ? |
endl |
xor eax, eax |
mov ebx, [file_name] |
mov ecx, [off] |
mov edx, [bytes] |
mov esi, [buffer] |
mov [cmd], eax |
mov [offset], ecx |
mov [offset+4], eax |
mov [count], edx |
mov [buff], esi |
mov byte [buff+4], al |
mov [name], ebx |
pushad |
lea ebx, [cmd] |
call file_system_lfn |
popad |
ret |
endp |
; description |
; allocate kernel memory and loads the specified file |
; |
; param |
; file_name= full path to file |
; |
; retval |
; eax= file image in kernel memory |
; ebx= size of file |
; |
; warging |
; You mast call kernel_free() to delete each file |
; loaded by the load_file() function |
align 4 |
proc load_file stdcall, file_name:dword |
locals |
attr dd ? |
flags dd ? |
cr_time dd ? |
cr_date dd ? |
acc_time dd ? |
acc_date dd ? |
mod_time dd ? |
mod_date dd ? |
file_size dd ? |
file dd ? |
file2 dd ? |
endl |
push esi |
push edi |
lea eax, [attr] |
stdcall get_fileinfo, [file_name], eax |
test eax, eax |
jnz .fail |
mov eax, [file_size] |
cmp eax, 1024*1024*16 |
ja .fail |
stdcall kernel_alloc, [file_size] |
mov [file], eax |
test eax, eax |
jz .fail |
stdcall read_file, [file_name], eax, dword 0, [file_size] |
cmp ebx, [file_size] |
jne .cleanup |
mov eax, [file] |
cmp dword [eax], 0x4B43504B |
jne .exit |
mov ebx, [eax+4] |
mov [file_size], ebx |
stdcall kernel_alloc, ebx |
test eax, eax |
jz .cleanup |
mov [file2], eax |
pushfd |
cli |
stdcall unpack, [file], eax |
popfd |
stdcall kernel_free, [file] |
mov eax, [file2] |
mov ebx, [file_size] |
.exit: |
push eax |
lea edi, [eax+ebx] ;cleanup remain space |
mov ecx, 4096 ;from file end |
and ebx, 4095 |
jz @f |
sub ecx, ebx |
xor eax, eax |
cld |
rep stosb |
@@: |
mov ebx, [file_size] |
pop eax |
pop edi |
pop esi |
ret |
.cleanup: |
stdcall kernel_free, [file] |
.fail: |
xor eax, eax |
xor ebx, ebx |
pop edi |
pop esi |
ret |
endp |
align 4 |
proc get_proc_ex stdcall, proc_name:dword, imports:dword |
.look_up: |
mov edx, [imports] |
test edx, edx |
jz .end |
mov edx, [edx] |
test edx, edx |
jz .end |
.next: |
mov eax, [edx] |
test eax, eax |
jz .next_table |
push edx |
stdcall strncmp, eax, [proc_name], 256 |
pop edx |
test eax, eax |
jz .ok |
add edx,8 |
jmp .next |
.next_table: |
add [imports], 4 |
jmp .look_up |
.ok: |
mov eax, [edx+4] |
ret |
.end: |
xor eax, eax |
ret |
endp |
align 4 |
proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\ |
sym_count:dword, strings:dword, imports:dword |
locals |
retval dd ? |
endl |
mov edi, [symbols] |
mov [retval], 1 |
.fix: |
movzx ebx, [edi+CSYM.SectionNumber] |
test ebx, ebx |
jnz .internal |
mov eax, dword [edi+CSYM.Name] |
test eax, eax |
jnz @F |
mov edi, [edi+4] |
add edi, [strings] |
@@: |
push edi |
stdcall get_proc_ex, edi,[imports] |
pop edi |
xor ebx, ebx |
test eax, eax |
jnz @F |
mov esi, msg_unresolved |
call sys_msg_board_str |
mov esi, edi |
call sys_msg_board_str |
mov esi, msg_CR |
call sys_msg_board_str |
mov [retval],0 |
@@: |
mov edi, [symbols] |
mov [edi+CSYM.Value], eax |
jmp .next |
.internal: |
cmp bx, -1 |
je .next |
cmp bx, -2 |
je .next |
dec ebx |
shl ebx, 3 |
lea ebx, [ebx+ebx*4] |
add ebx, [sec] |
mov eax, [ebx+CFS.VirtualAddress] |
add [edi+CSYM.Value], eax |
.next: |
add edi, CSYM_SIZE |
mov [symbols], edi |
dec [sym_count] |
jnz .fix |
mov eax, [retval] |
ret |
endp |
align 4 |
proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \ |
delta:dword |
locals |
n_sec dd ? |
endl |
mov eax, [coff] |
movzx ebx, [eax+CFH.nSections] |
mov [n_sec], ebx |
lea esi, [eax+20] |
.fix_sec: |
mov edi, [esi+CFS.PtrReloc] |
add edi, [coff] |
movzx ecx, [esi+CFS.NumReloc] |
test ecx, ecx |
jz .next |
.reloc_loop: |
mov ebx, [edi+CRELOC.SymIndex] |
add ebx,ebx |
lea ebx,[ebx+ebx*8] |
add ebx, [sym] |
mov edx, [ebx+CSYM.Value] |
cmp [edi+CRELOC.Type], 6 |
je .dir_32 |
cmp [edi+CRELOC.Type], 20 |
jne .next_reloc |
.rel_32: |
mov eax, [edi+CRELOC.VirtualAddress] |
add eax, [esi+CFS.VirtualAddress] |
sub edx, eax |
sub edx, 4 |
jmp .fix |
.dir_32: |
mov eax, [edi+CRELOC.VirtualAddress] |
add eax, [esi+CFS.VirtualAddress] |
.fix: |
add eax, [delta] |
add [eax], edx |
.next_reloc: |
add edi, 10 |
dec ecx |
jnz .reloc_loop |
.next: |
add esi, COFF_SECTION_SIZE |
dec [n_sec] |
jnz .fix_sec |
.exit: |
ret |
endp |
align 4 |
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \ |
delta:dword |
locals |
n_sec dd ? |
endl |
mov eax, [coff] |
movzx ebx, [eax+CFH.nSections] |
mov [n_sec], ebx |
lea esi, [eax+20] |
mov edx, [delta] |
.fix_sec: |
mov edi, [esi+CFS.PtrReloc] |
add edi, [coff] |
movzx ecx, [esi+CFS.NumReloc] |
test ecx, ecx |
jz .next |
.reloc_loop: |
cmp [edi+CRELOC.Type], 6 |
jne .next_reloc |
.dir_32: |
mov eax, [edi+CRELOC.VirtualAddress] |
add eax, [esi+CFS.VirtualAddress] |
add [eax+edx], edx |
.next_reloc: |
add edi, 10 |
dec ecx |
jnz .reloc_loop |
.next: |
add esi, COFF_SECTION_SIZE |
dec [n_sec] |
jnz .fix_sec |
.exit: |
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 ? |
exports dd ? ;fake exports table |
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+CFH.nSections] |
xor ebx, ebx |
lea edx, [eax+20] |
@@: |
add ebx, [edx+CFS.SizeOfRawData] |
add ebx, 15 |
and ebx, not 15 |
add edx, COFF_SECTION_SIZE |
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+CFH.nSections] |
mov edi, [img_base] |
lea eax, [edx+20] |
@@: |
mov [eax+CFS.VirtualAddress], edi |
mov esi, [eax+CFS.PtrRawData] |
test esi, esi |
jnz .copy |
add edi, [eax+CFS.SizeOfRawData] |
jmp .next |
.copy: |
add esi, edx |
mov ecx, [eax+CFS.SizeOfRawData] |
cld |
rep movsb |
.next: |
add edi, 15 |
and edi, not 15 |
add eax, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
mov ebx, [edx+CFH.pSymTable] |
add ebx, edx |
mov [sym], ebx |
mov ecx, [edx+CFH.nSymbols] |
add ecx,ecx |
lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE |
add ecx, [sym] |
mov [strings], ecx |
lea ebx, [exports] |
mov dword [ebx], kernel_export |
mov dword [ebx+4], 0 |
lea eax, [edx+20] |
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\ |
[strings], ebx |
test eax, eax |
jz .link_fail |
mov ebx, [coff] |
stdcall fix_coff_relocs, ebx, [sym], 0 |
stdcall get_coff_sym,[sym],[ebx+CFH.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+CFH.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] |
cmp dword [file_name+13], 'SOUN' |
jnz @f |
cmp dword [file_name+17], 'D.ob' |
jnz @f |
cmp word [file_name+21], 'j' |
jnz @f |
mov esi, aSis |
jmp .redo |
@@: |
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: |
; Rules: |
; - if alignment is not given, use default = 4K; |
; - if alignment is given and is no more than 4K, use it; |
; - if alignment is more than 4K, revert to 4K. |
push ecx |
mov cl, byte [edx+CFS.Characteristics+2] |
mov eax, 1 |
shr cl, 4 |
dec cl |
js .default |
cmp cl, 12 |
jbe @f |
.default: |
mov cl, 12 |
@@: |
shl eax, cl |
pop ecx |
dec eax |
ret |
align 4 |
proc load_library stdcall, file_name:dword |
locals |
fullname rb 260 |
fileinfo rb 40 |
coff dd ? |
img_base dd ? |
endl |
cli |
; resolve file name |
mov ebx, [file_name] |
lea edi, [fullname+1] |
mov byte [edi-1], '/' |
stdcall get_full_file_name, edi, 259 |
test al, al |
jz .fail |
; scan for required DLL in list of already loaded for this process, |
; ignore timestamp |
mov esi, [CURRENT_TASK] |
shl esi, 8 |
lea edi, [fullname] |
mov ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr] |
test ebx, ebx |
jz .not_in_process |
mov esi, [ebx+HDLL.fd] |
.scan_in_process: |
cmp esi, ebx |
jz .not_in_process |
mov eax, [esi+HDLL.parent] |
add eax, DLLDESCR.name |
stdcall strncmp, eax, edi, -1 |
test eax, eax |
jnz .next_in_process |
; simple variant: load DLL which is already loaded in this process |
; just increment reference counters and return address of exports table |
inc [esi+HDLL.refcount] |
mov ecx, [esi+HDLL.parent] |
inc [ecx+DLLDESCR.refcount] |
mov eax, [ecx+DLLDESCR.exports] |
sub eax, [ecx+DLLDESCR.defaultbase] |
add eax, [esi+HDLL.base] |
ret |
.next_in_process: |
mov esi, [esi+HDLL.fd] |
jmp .scan_in_process |
.not_in_process: |
; scan in full list, compare timestamp |
lea eax, [fileinfo] |
stdcall get_fileinfo, edi, eax |
test eax, eax |
jnz .fail |
mov esi, [dll_list.fd] |
.scan_for_dlls: |
cmp esi, dll_list |
jz .load_new |
lea eax, [esi+DLLDESCR.name] |
stdcall strncmp, eax, edi, -1 |
test eax, eax |
jnz .continue_scan |
.test_prev_dll: |
mov eax, dword [fileinfo+24] ; last modified time |
mov edx, dword [fileinfo+28] ; last modified date |
cmp dword [esi+DLLDESCR.timestamp], eax |
jnz .continue_scan |
cmp dword [esi+DLLDESCR.timestamp+4], edx |
jz .dll_already_loaded |
.continue_scan: |
mov esi, [esi+DLLDESCR.fd] |
jmp .scan_for_dlls |
; new DLL |
.load_new: |
; load file |
stdcall load_file, edi |
test eax, eax |
jz .fail |
mov [coff], eax |
mov dword [fileinfo+32], ebx |
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name |
mov esi, edi |
mov ecx, -1 |
xor eax, eax |
repnz scasb |
not ecx |
lea eax, [ecx+DLLDESCR.sizeof] |
push ecx |
call malloc |
pop ecx |
test eax, eax |
jz .fail_and_free_coff |
; save timestamp |
lea edi, [eax+DLLDESCR.name] |
rep movsb |
mov esi, eax |
mov eax, dword [fileinfo+24] |
mov dword [esi+DLLDESCR.timestamp], eax |
mov eax, dword [fileinfo+28] |
mov dword [esi+DLLDESCR.timestamp+4], eax |
; initialize DLLDESCR struct |
and dword [esi+DLLDESCR.refcount], 0 ; no HDLLs yet; later it will be incremented |
mov [esi+DLLDESCR.fd], dll_list |
mov eax, [dll_list.bk] |
mov [dll_list.bk], esi |
mov [esi+DLLDESCR.bk], eax |
mov [eax+DLLDESCR.fd], esi |
; calculate size of loaded DLL |
mov edx, [coff] |
movzx ecx, [edx+CFH.nSections] |
xor ebx, ebx |
add edx, 20 |
@@: |
call coff_get_align |
add ebx, eax |
not eax |
and ebx, eax |
add ebx, [edx+CFS.SizeOfRawData] |
add edx, COFF_SECTION_SIZE |
dec ecx |
jnz @B |
; it must be nonzero and not too big |
mov [esi+DLLDESCR.size], ebx |
test ebx, ebx |
jz .fail_and_free_dll |
cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR |
ja .fail_and_free_dll |
; allocate memory for kernel-side image |
stdcall kernel_alloc, ebx |
test eax, eax |
jz .fail_and_free_dll |
mov [esi+DLLDESCR.data], eax |
; calculate preferred base address |
add ebx, 0x1FFF |
and ebx, not 0xFFF |
mov ecx, [dll_cur_addr] |
lea edx, [ecx+ebx] |
cmp edx, MAX_DEFAULT_DLL_ADDR |
jb @f |
mov ecx, MIN_DEFAULT_DLL_ADDR |
lea edx, [ecx+ebx] |
@@: |
mov [esi+DLLDESCR.defaultbase], ecx |
mov [dll_cur_addr], edx |
; copy sections and set correct values for VirtualAddress'es in headers |
push esi |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, eax |
add edx, 20 |
cld |
@@: |
call coff_get_align |
add ecx, eax |
add edi, eax |
not eax |
and ecx, eax |
and edi, eax |
mov [edx+CFS.VirtualAddress], ecx |
add ecx, [edx+CFS.SizeOfRawData] |
mov esi, [edx+CFS.PtrRawData] |
push ecx |
mov ecx, [edx+CFS.SizeOfRawData] |
test esi, esi |
jnz .copy |
xor eax, eax |
rep stosb |
jmp .next |
.copy: |
add esi, [coff] |
rep movsb |
.next: |
pop ecx |
add edx, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
pop esi |
; save some additional data from COFF file |
; later we will use COFF header, headers for sections and symbol table |
; and also relocations table for all sections |
mov edx, [coff] |
mov ebx, [edx+CFH.pSymTable] |
mov edi, dword [fileinfo+32] |
sub edi, ebx |
jc .fail_and_free_data |
mov [esi+DLLDESCR.symbols_lim], edi |
add ebx, edx |
movzx ecx, [edx+CFH.nSections] |
lea ecx, [ecx*5] |
lea edi, [edi+ecx*8+20] |
add edx, 20 |
@@: |
movzx eax, [edx+CFS.NumReloc] |
lea eax, [eax*5] |
lea edi, [edi+eax*2] |
add edx, COFF_SECTION_SIZE |
sub ecx, 5 |
jnz @b |
stdcall kernel_alloc, edi |
test eax, eax |
jz .fail_and_free_data |
mov edx, [coff] |
movzx ecx, [edx+CFH.nSections] |
lea ecx, [ecx*5] |
lea ecx, [ecx*2+5] |
mov [esi+DLLDESCR.coff_hdr], eax |
push esi |
mov esi, edx |
mov edi, eax |
rep movsd |
pop esi |
mov [esi+DLLDESCR.symbols_ptr], edi |
push esi |
mov ecx, [edx+CFH.nSymbols] |
mov [esi+DLLDESCR.symbols_num], ecx |
mov ecx, [esi+DLLDESCR.symbols_lim] |
mov esi, ebx |
rep movsb |
pop esi |
mov ebx, [esi+DLLDESCR.coff_hdr] |
push esi |
movzx eax, [edx+CFH.nSections] |
lea edx, [ebx+20] |
@@: |
movzx ecx, [edx+CFS.NumReloc] |
lea ecx, [ecx*5] |
mov esi, [edx+CFS.PtrReloc] |
mov [edx+CFS.PtrReloc], edi |
sub [edx+CFS.PtrReloc], ebx |
add esi, [coff] |
shr ecx, 1 |
rep movsd |
adc ecx, ecx |
rep movsw |
add edx, COFF_SECTION_SIZE |
dec eax |
jnz @b |
pop esi |
; fixup symbols |
mov edx, ebx |
mov eax, [ebx+CFH.nSymbols] |
add edx, 20 |
mov ecx, [esi+DLLDESCR.symbols_num] |
lea ecx, [ecx*9] |
add ecx, ecx |
add ecx, [esi+DLLDESCR.symbols_ptr] |
stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax,\ |
ecx, 0 |
; test eax, eax |
; jnz @F |
; |
;@@: |
stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],szEXPORTS |
test eax, eax |
jnz @F |
stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],sz_EXPORTS |
@@: |
mov [esi+DLLDESCR.exports], eax |
; fix relocs in the hidden copy in kernel memory to default address |
; it is first fix; usually this will be enough, but second fix |
; can be necessary if real load address will not equal assumption |
mov eax, [esi+DLLDESCR.data] |
sub eax, [esi+DLLDESCR.defaultbase] |
stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax |
stdcall kernel_free, [coff] |
.dll_already_loaded: |
inc [esi+DLLDESCR.refcount] |
push esi |
call init_heap |
pop esi |
mov edi, [esi+DLLDESCR.size] |
stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi |
test eax, eax |
jnz @f |
stdcall user_alloc, edi |
test eax, eax |
jz .fail_and_dereference |
@@: |
mov [img_base], eax |
mov eax, HDLL.sizeof |
call malloc |
test eax, eax |
jz .fail_and_free_user |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov edx, [CURRENT_TASK+ebx+TASKDATA.pid] |
mov [eax+HDLL.pid], edx |
push eax |
call init_dlls_in_thread |
pop ebx |
test eax, eax |
jz .fail_and_free_user |
mov edx, [eax+HDLL.fd] |
mov [ebx+HDLL.fd], edx |
mov [ebx+HDLL.bk], eax |
mov [eax+HDLL.fd], ebx |
mov [edx+HDLL.bk], ebx |
mov eax, ebx |
mov ebx, [img_base] |
mov [eax+HDLL.base], ebx |
mov [eax+HDLL.size], edi |
mov [eax+HDLL.refcount], 1 |
mov [eax+HDLL.parent], esi |
mov edx, ebx |
shr edx, 12 |
or dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK |
; copy entries of page table from kernel-side image to usermode |
; use copy-on-write for user-mode image, so map as readonly |
xor edi, edi |
mov ecx, [esi+DLLDESCR.data] |
shr ecx, 12 |
.map_pages_loop: |
mov eax, [page_tabs+ecx*4] |
and eax, not 0xFFF |
or al, PG_USER |
xchg eax, [page_tabs+edx*4] |
test al, 1 |
jz @f |
call free_page |
@@: |
invlpg [ebx+edi] |
inc ecx |
inc edx |
add edi, 0x1000 |
cmp edi, [esi+DLLDESCR.size] |
jb .map_pages_loop |
; if real user-mode base is not equal to preferred base, relocate image |
sub ebx, [esi+DLLDESCR.defaultbase] |
jz @f |
stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx |
@@: |
mov eax, [esi+DLLDESCR.exports] |
sub eax, [esi+DLLDESCR.defaultbase] |
add eax, [img_base] |
ret |
.fail_and_free_data: |
stdcall kernel_free, [esi+DLLDESCR.data] |
.fail_and_free_dll: |
mov eax, esi |
call free |
.fail_and_free_coff: |
stdcall kernel_free, [coff] |
.fail: |
xor eax, eax |
ret |
.fail_and_free_user: |
stdcall user_free, [img_base] |
.fail_and_dereference: |
mov eax, 1 ; delete 1 reference |
call dereference_dll |
xor eax, eax |
ret |
endp |
; initialize [APPDATA.dlls_list_ptr] for given thread |
; DLL is per-process object, so APPDATA.dlls_list_ptr must be |
; kept in sync for all threads of one process. |
; 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] |
test eax, eax |
jnz .ret |
push [ebx+APPDATA.dir_table] |
mov eax, 8 |
call malloc |
pop edx |
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 |
.ret: |
ret |
; in: eax = number of references to delete, esi -> DLLDESCR struc |
dereference_dll: |
sub [esi+DLLDESCR.refcount], eax |
jnz .ret |
mov eax, [esi+DLLDESCR.fd] |
mov edx, [esi+DLLDESCR.bk] |
mov [eax+DLLDESCR.bk], edx |
mov [edx+DLLDESCR.fd], eax |
stdcall kernel_free, [esi+DLLDESCR.coff_hdr] |
stdcall kernel_free, [esi+DLLDESCR.data] |
mov eax, esi |
call free |
.ret: |
ret |
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 |
pop eax |
mov edx, [eax+HDLL.bk] |
mov ebx, [eax+HDLL.fd] |
mov [ebx+HDLL.bk], edx |
mov [edx+HDLL.fd], ebx |
call free |
pop edi esi ecx ebx |
ret |
; ecx -> APPDATA for slot, esi = dlls_list_ptr |
destroy_all_hdlls: |
test esi, esi |
jz .ret |
.loop: |
mov eax, [esi+HDLL.fd] |
cmp eax, esi |
jz free |
call destroy_hdll |
jmp .loop |
.ret: |
ret |
align 4 |
stop_all_services: |
push ebp |
mov edx, [srv.fd] |
.next: |
cmp edx, srv.fd-SRV_FD_OFFSET |
je .done |
cmp [edx+SRV.magic], ' SRV' |
jne .next |
cmp [edx+SRV.size], SRV.sizeof |
jne .next |
mov ebx, [edx+SRV.entry] |
mov edx, [edx+SRV.fd] |
test ebx, ebx |
jz .next |
push edx |
mov ebp, esp |
push 0 |
push -1 |
call ebx |
mov esp, ebp |
pop edx |
jmp .next |
.done: |
pop ebp |
ret |
; param |
; eax= size |
; ebx= pid |
align 4 |
create_kernel_object: |
push ebx |
call malloc |
pop ebx |
test eax, eax |
jz .fail |
mov ecx,[current_slot] |
add ecx, APP_OBJ_OFFSET |
pushfd |
cli |
mov edx, [ecx+APPOBJ.fd] |
mov [eax+APPOBJ.fd], edx |
mov [eax+APPOBJ.bk], ecx |
mov [eax+APPOBJ.pid], ebx |
mov [ecx+APPOBJ.fd], eax |
mov [edx+APPOBJ.bk], eax |
popfd |
.fail: |
ret |
; param |
; eax= object |
align 4 |
destroy_kernel_object: |
pushfd |
cli |
mov ebx, [eax+APPOBJ.fd] |
mov ecx, [eax+APPOBJ.bk] |
mov [ebx+APPOBJ.bk], ecx |
mov [ecx+APPOBJ.fd], ebx |
popfd |
xor edx, edx ;clear common header |
mov [eax], edx |
mov [eax+4], edx |
mov [eax+8], edx |
mov [eax+12], edx |
mov [eax+16], edx |
call free ;release object memory |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
DRV_COMPAT equ 5 ;minimal required drivers version |
DRV_CURRENT equ 6 ;current drivers model version |
DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT |
PID_KERNEL equ 1 ;os_idle thread |
align 4 |
proc get_notify stdcall, p_ev:dword |
.wait: |
mov ebx, [current_slot] |
test dword [ebx+APPDATA.event_mask], EVENT_NOTIFY |
jz @f |
and dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY |
mov edi, [p_ev] |
mov dword [edi], EV_INTR |
mov eax, [ebx+APPDATA.event] |
mov dword [edi+4], eax |
ret |
@@: |
call change_task |
jmp .wait |
endp |
align 4 |
proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 6 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
call pci_read_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 5 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
call pci_read_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 4 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
call pci_read_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 8 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
mov ecx, [val] |
call pci_write_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 9 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
mov ecx, [val] |
call pci_write_reg |
pop ebx |
ret |
endp |
align 4 |
proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword |
push ebx |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 10 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
mov ecx, [val] |
call pci_write_reg |
pop ebx |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc srv_handler stdcall, ioctl:dword |
mov esi, [ioctl] |
test esi, esi |
jz .err |
mov edi, [esi+handle] |
cmp [edi+SRV.magic], ' SRV' |
jne .fail |
cmp [edi+SRV.size], SRV.sizeof |
jne .fail |
stdcall [edi+SRV.srv_proc], esi |
ret |
.fail: |
xor eax, eax |
not eax |
mov [esi+output], eax |
mov [esi+out_size], 4 |
ret |
.err: |
xor eax, eax |
not eax |
ret |
endp |
; param |
; ecx= io_control |
; |
; retval |
; eax= error code |
align 4 |
srv_handlerEx: |
cmp ecx, OS_BASE |
jae .fail |
mov eax, [ecx+handle] |
cmp [eax+SRV.magic], ' SRV' |
jne .fail |
cmp [eax+SRV.size], SRV.sizeof |
jne .fail |
stdcall [eax+SRV.srv_proc], ecx |
ret |
.fail: |
or eax, -1 |
ret |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc get_service stdcall, sz_name:dword |
mov eax, [sz_name] |
test eax, eax |
jnz @F |
ret |
@@: |
mov edx, [srv.fd] |
@@: |
cmp edx, srv.fd-SRV_FD_OFFSET |
je .not_load |
stdcall strncmp, edx, [sz_name], 16 |
test eax, eax |
je .ok |
mov edx, [edx+SRV.fd] |
jmp @B |
.not_load: |
pop ebp |
jmp load_driver |
.ok: |
mov eax, edx |
ret |
endp |
align 4 |
proc reg_service stdcall, name:dword, handler:dword |
push ebx |
xor eax, eax |
cmp [name], eax |
je .fail |
cmp [handler], eax |
je .fail |
mov eax, SRV.sizeof |
call malloc |
test eax, eax |
jz .fail |
push esi |
push edi |
mov edi, eax |
mov esi, [name] |
movsd |
movsd |
movsd |
movsd |
pop edi |
pop esi |
mov [eax+SRV.magic], ' SRV' |
mov [eax+SRV.size], SRV.sizeof |
mov ebx, srv.fd-SRV_FD_OFFSET |
mov edx, [ebx+SRV.fd] |
mov [eax+SRV.fd], edx |
mov [eax+SRV.bk], ebx |
mov [ebx+SRV.fd], eax |
mov [edx+SRV.bk], eax |
mov ecx, [handler] |
mov [eax+SRV.srv_proc], ecx |
pop ebx |
ret |
.fail: |
xor eax, eax |
pop ebx |
ret |
endp |
align 4 |
proc get_proc stdcall, exp:dword, sz_name:dword |
mov edx, [exp] |
.next: |
mov eax, [edx] |
test eax, eax |
jz .end |
push edx |
stdcall strncmp, eax, [sz_name], 16 |
pop edx |
test eax, eax |
jz .ok |
add edx, 8 |
jmp .next |
.ok: |
mov eax, [edx+4] |
.end: |
ret |
endp |
align 4 |
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword |
@@: |
stdcall strncmp, [pSym], [sz_sym], 8 |
test eax, eax |
jz .ok |
add [pSym], 18 |
dec [count] |
jnz @b |
xor eax, eax |
ret |
.ok: |
mov eax, [pSym] |
mov eax, [eax+8] |
ret |
endp |
align 4 |
proc get_curr_task |
mov eax, [CURRENT_TASK] |
shl eax, 8 |
ret |
endp |
align 4 |
proc get_fileinfo stdcall, file_name:dword, info:dword |
locals |
cmd dd ? |
offset dd ? |
dd ? |
count dd ? |
buff dd ? |
db ? |
name dd ? |
endl |
xor eax, eax |
mov ebx, [file_name] |
mov ecx, [info] |
mov [cmd], 5 |
mov [offset], eax |
mov [offset+4], eax |
mov [count], eax |
mov [buff], ecx |
mov byte [buff+4], al |
mov [name], ebx |
mov eax, 70 |
lea ebx, [cmd] |
int 0x40 |
ret |
endp |
align 4 |
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\ |
bytes:dword |
locals |
cmd dd ? |
offset dd ? |
dd ? |
count dd ? |
buff dd ? |
db ? |
name dd ? |
endl |
xor eax, eax |
mov ebx, [file_name] |
mov ecx, [off] |
mov edx, [bytes] |
mov esi, [buffer] |
mov [cmd], eax |
mov [offset], ecx |
mov [offset+4], eax |
mov [count], edx |
mov [buff], esi |
mov byte [buff+4], al |
mov [name], ebx |
pushad |
lea ebx, [cmd] |
call file_system_lfn |
popad |
ret |
endp |
; description |
; allocate kernel memory and loads the specified file |
; |
; param |
; file_name= full path to file |
; |
; retval |
; eax= file image in kernel memory |
; ebx= size of file |
; |
; warging |
; You mast call kernel_free() to delete each file |
; loaded by the load_file() function |
align 4 |
proc load_file stdcall, file_name:dword |
locals |
attr dd ? |
flags dd ? |
cr_time dd ? |
cr_date dd ? |
acc_time dd ? |
acc_date dd ? |
mod_time dd ? |
mod_date dd ? |
file_size dd ? |
file dd ? |
file2 dd ? |
endl |
push esi |
push edi |
lea eax, [attr] |
stdcall get_fileinfo, [file_name], eax |
test eax, eax |
jnz .fail |
mov eax, [file_size] |
cmp eax, 1024*1024*16 |
ja .fail |
stdcall kernel_alloc, [file_size] |
mov [file], eax |
test eax, eax |
jz .fail |
stdcall read_file, [file_name], eax, dword 0, [file_size] |
cmp ebx, [file_size] |
jne .cleanup |
mov eax, [file] |
cmp dword [eax], 0x4B43504B |
jne .exit |
mov ebx, [eax+4] |
mov [file_size], ebx |
stdcall kernel_alloc, ebx |
test eax, eax |
jz .cleanup |
mov [file2], eax |
pushfd |
cli |
stdcall unpack, [file], eax |
popfd |
stdcall kernel_free, [file] |
mov eax, [file2] |
mov ebx, [file_size] |
.exit: |
push eax |
lea edi, [eax+ebx] ;cleanup remain space |
mov ecx, 4096 ;from file end |
and ebx, 4095 |
jz @f |
sub ecx, ebx |
xor eax, eax |
cld |
rep stosb |
@@: |
mov ebx, [file_size] |
pop eax |
pop edi |
pop esi |
ret |
.cleanup: |
stdcall kernel_free, [file] |
.fail: |
xor eax, eax |
xor ebx, ebx |
pop edi |
pop esi |
ret |
endp |
align 4 |
proc get_proc_ex stdcall, proc_name:dword, imports:dword |
.look_up: |
mov edx, [imports] |
test edx, edx |
jz .end |
mov edx, [edx] |
test edx, edx |
jz .end |
.next: |
mov eax, [edx] |
test eax, eax |
jz .next_table |
push edx |
stdcall strncmp, eax, [proc_name], 256 |
pop edx |
test eax, eax |
jz .ok |
add edx, 8 |
jmp .next |
.next_table: |
add [imports], 4 |
jmp .look_up |
.ok: |
mov eax, [edx+4] |
ret |
.end: |
xor eax, eax |
ret |
endp |
align 4 |
proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\ |
sym_count:dword, strings:dword, imports:dword |
locals |
retval dd ? |
endl |
mov edi, [symbols] |
mov [retval], 1 |
.fix: |
movzx ebx, [edi+CSYM.SectionNumber] |
test ebx, ebx |
jnz .internal |
mov eax, dword [edi+CSYM.Name] |
test eax, eax |
jnz @F |
mov edi, [edi+4] |
add edi, [strings] |
@@: |
push edi |
stdcall get_proc_ex, edi, [imports] |
pop edi |
xor ebx, ebx |
test eax, eax |
jnz @F |
mov esi, msg_unresolved |
call sys_msg_board_str |
mov esi, edi |
call sys_msg_board_str |
mov esi, msg_CR |
call sys_msg_board_str |
mov [retval], 0 |
@@: |
mov edi, [symbols] |
mov [edi+CSYM.Value], eax |
jmp .next |
.internal: |
cmp bx, -1 |
je .next |
cmp bx, -2 |
je .next |
dec ebx |
shl ebx, 3 |
lea ebx, [ebx+ebx*4] |
add ebx, [sec] |
mov eax, [ebx+CFS.VirtualAddress] |
add [edi+CSYM.Value], eax |
.next: |
add edi, CSYM_SIZE |
mov [symbols], edi |
dec [sym_count] |
jnz .fix |
mov eax, [retval] |
ret |
endp |
align 4 |
proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \ |
delta:dword |
locals |
n_sec dd ? |
endl |
mov eax, [coff] |
movzx ebx, [eax+CFH.nSections] |
mov [n_sec], ebx |
lea esi, [eax+20] |
.fix_sec: |
mov edi, [esi+CFS.PtrReloc] |
add edi, [coff] |
movzx ecx, [esi+CFS.NumReloc] |
test ecx, ecx |
jz .next |
.reloc_loop: |
mov ebx, [edi+CRELOC.SymIndex] |
add ebx, ebx |
lea ebx, [ebx+ebx*8] |
add ebx, [sym] |
mov edx, [ebx+CSYM.Value] |
cmp [edi+CRELOC.Type], 6 |
je .dir_32 |
cmp [edi+CRELOC.Type], 20 |
jne .next_reloc |
.rel_32: |
mov eax, [edi+CRELOC.VirtualAddress] |
add eax, [esi+CFS.VirtualAddress] |
sub edx, eax |
sub edx, 4 |
jmp .fix |
.dir_32: |
mov eax, [edi+CRELOC.VirtualAddress] |
add eax, [esi+CFS.VirtualAddress] |
.fix: |
add eax, [delta] |
add [eax], edx |
.next_reloc: |
add edi, 10 |
dec ecx |
jnz .reloc_loop |
.next: |
add esi, COFF_SECTION_SIZE |
dec [n_sec] |
jnz .fix_sec |
.exit: |
ret |
endp |
align 4 |
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \ |
delta:dword |
locals |
n_sec dd ? |
endl |
mov eax, [coff] |
movzx ebx, [eax+CFH.nSections] |
mov [n_sec], ebx |
lea esi, [eax+20] |
mov edx, [delta] |
.fix_sec: |
mov edi, [esi+CFS.PtrReloc] |
add edi, [coff] |
movzx ecx, [esi+CFS.NumReloc] |
test ecx, ecx |
jz .next |
.reloc_loop: |
cmp [edi+CRELOC.Type], 6 |
jne .next_reloc |
.dir_32: |
mov eax, [edi+CRELOC.VirtualAddress] |
add eax, [esi+CFS.VirtualAddress] |
add [eax+edx], edx |
.next_reloc: |
add edi, 10 |
dec ecx |
jnz .reloc_loop |
.next: |
add esi, COFF_SECTION_SIZE |
dec [n_sec] |
jnz .fix_sec |
.exit: |
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 ? |
exports dd ? ;fake exports table |
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+CFH.nSections] |
xor ebx, ebx |
lea edx, [eax+20] |
@@: |
add ebx, [edx+CFS.SizeOfRawData] |
add ebx, 15 |
and ebx, not 15 |
add edx, COFF_SECTION_SIZE |
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+CFH.nSections] |
mov edi, [img_base] |
lea eax, [edx+20] |
@@: |
mov [eax+CFS.VirtualAddress], edi |
mov esi, [eax+CFS.PtrRawData] |
test esi, esi |
jnz .copy |
add edi, [eax+CFS.SizeOfRawData] |
jmp .next |
.copy: |
add esi, edx |
mov ecx, [eax+CFS.SizeOfRawData] |
cld |
rep movsb |
.next: |
add edi, 15 |
and edi, not 15 |
add eax, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
mov ebx, [edx+CFH.pSymTable] |
add ebx, edx |
mov [sym], ebx |
mov ecx, [edx+CFH.nSymbols] |
add ecx, ecx |
lea ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE |
add ecx, [sym] |
mov [strings], ecx |
lea ebx, [exports] |
mov dword [ebx], kernel_export |
mov dword [ebx+4], 0 |
lea eax, [edx+20] |
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols], \ |
[strings], ebx |
test eax, eax |
jz .link_fail |
mov ebx, [coff] |
stdcall fix_coff_relocs, ebx, [sym], 0 |
stdcall get_coff_sym, [sym], [ebx+CFH.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+CFH.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] |
cmp dword [file_name+13], 'SOUN' |
jnz @f |
cmp dword [file_name+17], 'D.ob' |
jnz @f |
cmp word [file_name+21], 'j' |
jnz @f |
mov esi, aSis |
jmp .redo |
@@: |
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: |
; Rules: |
; - if alignment is not given, use default = 4K; |
; - if alignment is given and is no more than 4K, use it; |
; - if alignment is more than 4K, revert to 4K. |
push ecx |
mov cl, byte [edx+CFS.Characteristics+2] |
mov eax, 1 |
shr cl, 4 |
dec cl |
js .default |
cmp cl, 12 |
jbe @f |
.default: |
mov cl, 12 |
@@: |
shl eax, cl |
pop ecx |
dec eax |
ret |
align 4 |
proc load_library stdcall, file_name:dword |
locals |
fullname rb 260 |
fileinfo rb 40 |
coff dd ? |
img_base dd ? |
endl |
cli |
; resolve file name |
mov ebx, [file_name] |
lea edi, [fullname+1] |
mov byte [edi-1], '/' |
stdcall get_full_file_name, edi, 259 |
test al, al |
jz .fail |
; scan for required DLL in list of already loaded for this process, |
; ignore timestamp |
mov esi, [CURRENT_TASK] |
shl esi, 8 |
lea edi, [fullname] |
mov ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr] |
test ebx, ebx |
jz .not_in_process |
mov esi, [ebx+HDLL.fd] |
.scan_in_process: |
cmp esi, ebx |
jz .not_in_process |
mov eax, [esi+HDLL.parent] |
add eax, DLLDESCR.name |
stdcall strncmp, eax, edi, -1 |
test eax, eax |
jnz .next_in_process |
; simple variant: load DLL which is already loaded in this process |
; just increment reference counters and return address of exports table |
inc [esi+HDLL.refcount] |
mov ecx, [esi+HDLL.parent] |
inc [ecx+DLLDESCR.refcount] |
mov eax, [ecx+DLLDESCR.exports] |
sub eax, [ecx+DLLDESCR.defaultbase] |
add eax, [esi+HDLL.base] |
ret |
.next_in_process: |
mov esi, [esi+HDLL.fd] |
jmp .scan_in_process |
.not_in_process: |
; scan in full list, compare timestamp |
lea eax, [fileinfo] |
stdcall get_fileinfo, edi, eax |
test eax, eax |
jnz .fail |
mov esi, [dll_list.fd] |
.scan_for_dlls: |
cmp esi, dll_list |
jz .load_new |
lea eax, [esi+DLLDESCR.name] |
stdcall strncmp, eax, edi, -1 |
test eax, eax |
jnz .continue_scan |
.test_prev_dll: |
mov eax, dword [fileinfo+24]; last modified time |
mov edx, dword [fileinfo+28]; last modified date |
cmp dword [esi+DLLDESCR.timestamp], eax |
jnz .continue_scan |
cmp dword [esi+DLLDESCR.timestamp+4], edx |
jz .dll_already_loaded |
.continue_scan: |
mov esi, [esi+DLLDESCR.fd] |
jmp .scan_for_dlls |
; new DLL |
.load_new: |
; load file |
stdcall load_file, edi |
test eax, eax |
jz .fail |
mov [coff], eax |
mov dword [fileinfo+32], ebx |
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name |
mov esi, edi |
mov ecx, -1 |
xor eax, eax |
repnz scasb |
not ecx |
lea eax, [ecx+DLLDESCR.sizeof] |
push ecx |
call malloc |
pop ecx |
test eax, eax |
jz .fail_and_free_coff |
; save timestamp |
lea edi, [eax+DLLDESCR.name] |
rep movsb |
mov esi, eax |
mov eax, dword [fileinfo+24] |
mov dword [esi+DLLDESCR.timestamp], eax |
mov eax, dword [fileinfo+28] |
mov dword [esi+DLLDESCR.timestamp+4], eax |
; initialize DLLDESCR struct |
and dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented |
mov [esi+DLLDESCR.fd], dll_list |
mov eax, [dll_list.bk] |
mov [dll_list.bk], esi |
mov [esi+DLLDESCR.bk], eax |
mov [eax+DLLDESCR.fd], esi |
; calculate size of loaded DLL |
mov edx, [coff] |
movzx ecx, [edx+CFH.nSections] |
xor ebx, ebx |
add edx, 20 |
@@: |
call coff_get_align |
add ebx, eax |
not eax |
and ebx, eax |
add ebx, [edx+CFS.SizeOfRawData] |
add edx, COFF_SECTION_SIZE |
dec ecx |
jnz @B |
; it must be nonzero and not too big |
mov [esi+DLLDESCR.size], ebx |
test ebx, ebx |
jz .fail_and_free_dll |
cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR |
ja .fail_and_free_dll |
; allocate memory for kernel-side image |
stdcall kernel_alloc, ebx |
test eax, eax |
jz .fail_and_free_dll |
mov [esi+DLLDESCR.data], eax |
; calculate preferred base address |
add ebx, 0x1FFF |
and ebx, not 0xFFF |
mov ecx, [dll_cur_addr] |
lea edx, [ecx+ebx] |
cmp edx, MAX_DEFAULT_DLL_ADDR |
jb @f |
mov ecx, MIN_DEFAULT_DLL_ADDR |
lea edx, [ecx+ebx] |
@@: |
mov [esi+DLLDESCR.defaultbase], ecx |
mov [dll_cur_addr], edx |
; copy sections and set correct values for VirtualAddress'es in headers |
push esi |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, eax |
add edx, 20 |
cld |
@@: |
call coff_get_align |
add ecx, eax |
add edi, eax |
not eax |
and ecx, eax |
and edi, eax |
mov [edx+CFS.VirtualAddress], ecx |
add ecx, [edx+CFS.SizeOfRawData] |
mov esi, [edx+CFS.PtrRawData] |
push ecx |
mov ecx, [edx+CFS.SizeOfRawData] |
test esi, esi |
jnz .copy |
xor eax, eax |
rep stosb |
jmp .next |
.copy: |
add esi, [coff] |
rep movsb |
.next: |
pop ecx |
add edx, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
pop esi |
; save some additional data from COFF file |
; later we will use COFF header, headers for sections and symbol table |
; and also relocations table for all sections |
mov edx, [coff] |
mov ebx, [edx+CFH.pSymTable] |
mov edi, dword [fileinfo+32] |
sub edi, ebx |
jc .fail_and_free_data |
mov [esi+DLLDESCR.symbols_lim], edi |
add ebx, edx |
movzx ecx, [edx+CFH.nSections] |
lea ecx, [ecx*5] |
lea edi, [edi+ecx*8+20] |
add edx, 20 |
@@: |
movzx eax, [edx+CFS.NumReloc] |
lea eax, [eax*5] |
lea edi, [edi+eax*2] |
add edx, COFF_SECTION_SIZE |
sub ecx, 5 |
jnz @b |
stdcall kernel_alloc, edi |
test eax, eax |
jz .fail_and_free_data |
mov edx, [coff] |
movzx ecx, [edx+CFH.nSections] |
lea ecx, [ecx*5] |
lea ecx, [ecx*2+5] |
mov [esi+DLLDESCR.coff_hdr], eax |
push esi |
mov esi, edx |
mov edi, eax |
rep movsd |
pop esi |
mov [esi+DLLDESCR.symbols_ptr], edi |
push esi |
mov ecx, [edx+CFH.nSymbols] |
mov [esi+DLLDESCR.symbols_num], ecx |
mov ecx, [esi+DLLDESCR.symbols_lim] |
mov esi, ebx |
rep movsb |
pop esi |
mov ebx, [esi+DLLDESCR.coff_hdr] |
push esi |
movzx eax, [edx+CFH.nSections] |
lea edx, [ebx+20] |
@@: |
movzx ecx, [edx+CFS.NumReloc] |
lea ecx, [ecx*5] |
mov esi, [edx+CFS.PtrReloc] |
mov [edx+CFS.PtrReloc], edi |
sub [edx+CFS.PtrReloc], ebx |
add esi, [coff] |
shr ecx, 1 |
rep movsd |
adc ecx, ecx |
rep movsw |
add edx, COFF_SECTION_SIZE |
dec eax |
jnz @b |
pop esi |
; fixup symbols |
mov edx, ebx |
mov eax, [ebx+CFH.nSymbols] |
add edx, 20 |
mov ecx, [esi+DLLDESCR.symbols_num] |
lea ecx, [ecx*9] |
add ecx, ecx |
add ecx, [esi+DLLDESCR.symbols_ptr] |
stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \ |
ecx, 0 |
; test eax, eax |
; jnz @F |
; |
;@@: |
stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+CFH.nSymbols], szEXPORTS |
test eax, eax |
jnz @F |
stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+CFH.nSymbols], sz_EXPORTS |
@@: |
mov [esi+DLLDESCR.exports], eax |
; fix relocs in the hidden copy in kernel memory to default address |
; it is first fix; usually this will be enough, but second fix |
; can be necessary if real load address will not equal assumption |
mov eax, [esi+DLLDESCR.data] |
sub eax, [esi+DLLDESCR.defaultbase] |
stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax |
stdcall kernel_free, [coff] |
.dll_already_loaded: |
inc [esi+DLLDESCR.refcount] |
push esi |
call init_heap |
pop esi |
mov edi, [esi+DLLDESCR.size] |
stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi |
test eax, eax |
jnz @f |
stdcall user_alloc, edi |
test eax, eax |
jz .fail_and_dereference |
@@: |
mov [img_base], eax |
mov eax, HDLL.sizeof |
call malloc |
test eax, eax |
jz .fail_and_free_user |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov edx, [CURRENT_TASK+ebx+TASKDATA.pid] |
mov [eax+HDLL.pid], edx |
push eax |
call init_dlls_in_thread |
pop ebx |
test eax, eax |
jz .fail_and_free_user |
mov edx, [eax+HDLL.fd] |
mov [ebx+HDLL.fd], edx |
mov [ebx+HDLL.bk], eax |
mov [eax+HDLL.fd], ebx |
mov [edx+HDLL.bk], ebx |
mov eax, ebx |
mov ebx, [img_base] |
mov [eax+HDLL.base], ebx |
mov [eax+HDLL.size], edi |
mov [eax+HDLL.refcount], 1 |
mov [eax+HDLL.parent], esi |
mov edx, ebx |
shr edx, 12 |
or dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK |
; copy entries of page table from kernel-side image to usermode |
; use copy-on-write for user-mode image, so map as readonly |
xor edi, edi |
mov ecx, [esi+DLLDESCR.data] |
shr ecx, 12 |
.map_pages_loop: |
mov eax, [page_tabs+ecx*4] |
and eax, not 0xFFF |
or al, PG_USER |
xchg eax, [page_tabs+edx*4] |
test al, 1 |
jz @f |
call free_page |
@@: |
invlpg [ebx+edi] |
inc ecx |
inc edx |
add edi, 0x1000 |
cmp edi, [esi+DLLDESCR.size] |
jb .map_pages_loop |
; if real user-mode base is not equal to preferred base, relocate image |
sub ebx, [esi+DLLDESCR.defaultbase] |
jz @f |
stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx |
@@: |
mov eax, [esi+DLLDESCR.exports] |
sub eax, [esi+DLLDESCR.defaultbase] |
add eax, [img_base] |
ret |
.fail_and_free_data: |
stdcall kernel_free, [esi+DLLDESCR.data] |
.fail_and_free_dll: |
mov eax, esi |
call free |
.fail_and_free_coff: |
stdcall kernel_free, [coff] |
.fail: |
xor eax, eax |
ret |
.fail_and_free_user: |
stdcall user_free, [img_base] |
.fail_and_dereference: |
mov eax, 1 ; delete 1 reference |
call dereference_dll |
xor eax, eax |
ret |
endp |
; initialize [APPDATA.dlls_list_ptr] for given thread |
; DLL is per-process object, so APPDATA.dlls_list_ptr must be |
; kept in sync for all threads of one process. |
; 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] |
test eax, eax |
jnz .ret |
push [ebx+APPDATA.dir_table] |
mov eax, 8 |
call malloc |
pop edx |
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 |
.ret: |
ret |
; in: eax = number of references to delete, esi -> DLLDESCR struc |
dereference_dll: |
sub [esi+DLLDESCR.refcount], eax |
jnz .ret |
mov eax, [esi+DLLDESCR.fd] |
mov edx, [esi+DLLDESCR.bk] |
mov [eax+DLLDESCR.bk], edx |
mov [edx+DLLDESCR.fd], eax |
stdcall kernel_free, [esi+DLLDESCR.coff_hdr] |
stdcall kernel_free, [esi+DLLDESCR.data] |
mov eax, esi |
call free |
.ret: |
ret |
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 |
pop eax |
mov edx, [eax+HDLL.bk] |
mov ebx, [eax+HDLL.fd] |
mov [ebx+HDLL.bk], edx |
mov [edx+HDLL.fd], ebx |
call free |
pop edi esi ecx ebx |
ret |
; ecx -> APPDATA for slot, esi = dlls_list_ptr |
destroy_all_hdlls: |
test esi, esi |
jz .ret |
.loop: |
mov eax, [esi+HDLL.fd] |
cmp eax, esi |
jz free |
call destroy_hdll |
jmp .loop |
.ret: |
ret |
align 4 |
stop_all_services: |
push ebp |
mov edx, [srv.fd] |
.next: |
cmp edx, srv.fd-SRV_FD_OFFSET |
je .done |
cmp [edx+SRV.magic], ' SRV' |
jne .next |
cmp [edx+SRV.size], SRV.sizeof |
jne .next |
mov ebx, [edx+SRV.entry] |
mov edx, [edx+SRV.fd] |
test ebx, ebx |
jz .next |
push edx |
mov ebp, esp |
push 0 |
push -1 |
call ebx |
mov esp, ebp |
pop edx |
jmp .next |
.done: |
pop ebp |
ret |
; param |
; eax= size |
; ebx= pid |
align 4 |
create_kernel_object: |
push ebx |
call malloc |
pop ebx |
test eax, eax |
jz .fail |
mov ecx, [current_slot] |
add ecx, APP_OBJ_OFFSET |
pushfd |
cli |
mov edx, [ecx+APPOBJ.fd] |
mov [eax+APPOBJ.fd], edx |
mov [eax+APPOBJ.bk], ecx |
mov [eax+APPOBJ.pid], ebx |
mov [ecx+APPOBJ.fd], eax |
mov [edx+APPOBJ.bk], eax |
popfd |
.fail: |
ret |
; param |
; eax= object |
align 4 |
destroy_kernel_object: |
pushfd |
cli |
mov ebx, [eax+APPOBJ.fd] |
mov ecx, [eax+APPOBJ.bk] |
mov [ebx+APPOBJ.bk], ecx |
mov [ecx+APPOBJ.fd], ebx |
popfd |
xor edx, edx ;clear common header |
mov [eax], edx |
mov [eax+4], edx |
mov [eax+8], edx |
mov [eax+12], edx |
mov [eax+16], edx |
call free ;release object memory |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/export.inc |
---|
1,39 → 1,40 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Macroinstruction for making export section |
macro export dllname,[label,string] |
{ common |
local module,addresses,names,ordinal,count |
count = 0 |
forward |
count = count+1 |
common |
dd 0,0,0, (module-OS_BASE) , 1 |
dd count,count,(addresses-OS_BASE),(names-OS_BASE),(ordinal-OS_BASE) |
addresses: |
forward |
dd (label-OS_BASE) |
common |
names: |
forward |
local name |
dd (name-OS_BASE) |
common |
ordinal: count = 0 |
forward |
dw count |
count = count+1 |
common |
module db dllname,0 |
forward |
name db string,0 |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Macroinstruction for making export section |
macro export dllname,[label,string] |
{ common |
local module,addresses,names,ordinal,count |
count = 0 |
forward |
count = count+1 |
common |
dd 0,0,0, (module-OS_BASE) , 1 |
dd count,count,(addresses-OS_BASE),(names-OS_BASE),(ordinal-OS_BASE) |
addresses: |
forward |
dd (label-OS_BASE) |
common |
names: |
forward |
local name |
dd (name-OS_BASE) |
common |
ordinal: |
count = 0 |
forward |
dw count |
count = count+1 |
common |
module db dllname,0 |
forward |
name db string,0 |
} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/exports.inc |
---|
1,181 → 1,181 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
szKernel db 'KERNEL', 0 |
szVersion db 'version',0 |
szRegService db 'RegService',0 |
szGetService db 'GetService',0 |
szServiceHandler db 'ServiceHandler',0 |
szAttachIntHandler db 'AttachIntHandler',0 |
; szGetIntHandler db 'GetIntHandler', 0 |
szFpuSave db 'FpuSave',0 |
szFpuRestore db 'FpuRestore',0 |
szReservePortArea db 'ReservePortArea',0 |
szBoot_Log db 'Boot_Log',0 |
szMutexInit db 'MutexInit',0 |
szMutexLock db 'MutexLock',0 |
szMutexUnlock db 'MutexUnlock',0 |
szPciApi db 'PciApi', 0 |
szPciRead32 db 'PciRead32', 0 |
szPciRead16 db 'PciRead16', 0 |
szPciRead8 db 'PciRead8', 0 |
szPciWrite8 db 'PciWrite8',0 |
szPciWrite16 db 'PciWrite16',0 |
szPciWrite32 db 'PciWrite32',0 |
szAllocPage db 'AllocPage',0 |
szAllocPages db 'AllocPages',0 |
szFreePage db 'FreePage',0 |
szGetPgAddr db 'GetPgAddr',0 |
szMapPage db 'MapPage',0 |
szMapSpace db 'MapSpace',0 |
szMapIoMem db 'MapIoMem',0 |
szCommitPages db 'CommitPages',0 |
szReleasePages db 'ReleasePages',0 |
szAllocKernelSpace db 'AllocKernelSpace',0 |
szFreeKernelSpace db 'FreeKernelSpace',0 |
szKernelAlloc db 'KernelAlloc',0 |
szKernelFree db 'KernelFree',0 |
szUserAlloc db 'UserAlloc',0 |
szUserFree db 'UserFree',0 |
szKmalloc db 'Kmalloc',0 |
szKfree db 'Kfree',0 |
szCreateRingBuffer db 'CreateRingBuffer',0 |
szGetPid db 'GetPid',0 |
szCreateObject db 'CreateObject',0 |
szDestroyObject db 'DestroyObject',0 |
szCreateEvent db 'CreateEvent',0 |
szRaiseEvent db 'RaiseEvent',0 |
szWaitEvent db 'WaitEvent',0 |
szDestroyEvent db 'DestroyEvent',0 |
szClearEvent db 'ClearEvent',0 |
szLoadCursor db 'LoadCursor',0 |
szSysMsgBoardStr db 'SysMsgBoardStr', 0 |
szSysMsgBoardChar db 'SysMsgBoardChar', 0 |
szGetCurrentTask db 'GetCurrentTask',0 |
szLFBAddress db 'LFBAddress',0 |
szLoadFile db 'LoadFile',0 |
szSendEvent db 'SendEvent',0 |
szSetMouseData db 'SetMouseData',0 |
szSleep db 'Sleep',0 |
szGetTimerTicks db 'GetTimerTicks',0 |
szGetDisplay db 'GetDisplay',0 |
szSetScreen db 'SetScreen',0 |
szStrncat db 'strncat',0 |
szStrncpy db 'strncpy',0 |
szstrncmp db 'strncmp',0 |
szStrnlen db 'strnlen',0 |
szStrchr db 'strchr',0 |
szStrrchr db 'strrchr',0 |
szDiskAdd db 'DiskAdd',0 |
szDiskDel db 'DiskDel',0 |
szDiskMediaChanged db 'DiskMediaChanged',0 |
szTimerHS db 'TimerHS',0 |
szCancelTimerHS db 'CancelTimerHS',0 |
align 16 |
kernel_export: |
dd szRegService , reg_service |
dd szGetService , get_service |
dd szServiceHandler , srv_handler |
dd szAttachIntHandler, attach_int_handler |
; dd szGetIntHandler , get_int_handler |
dd szFpuSave , fpu_save |
dd szFpuRestore , fpu_restore |
dd szReservePortArea , r_f_port_area |
dd szBoot_Log , boot_log |
dd szMutexInit , mutex_init ;gcc fastcall |
dd szMutexLock , mutex_lock ;gcc fastcall |
dd szMutexUnlock , mutex_unlock ;gcc fastcall |
dd szPciApi , pci_api_drv |
dd szPciRead32 , pci_read32 |
dd szPciRead16 , pci_read16 |
dd szPciRead8 , pci_read8 |
dd szPciWrite8 , pci_write8 |
dd szPciWrite16 , pci_write16 |
dd szPciWrite32 , pci_write32 |
dd szAllocPage , alloc_page ;stdcall |
dd szAllocPages , alloc_pages ;stdcall |
dd szFreePage , free_page |
dd szMapPage , map_page ;stdcall |
dd szMapSpace , map_space |
dd szMapIoMem , map_io_mem ;stdcall |
dd szGetPgAddr , get_pg_addr |
dd szCommitPages , commit_pages ;not implemented |
dd szReleasePages , release_pages |
dd szAllocKernelSpace, alloc_kernel_space ;stdcall |
dd szFreeKernelSpace , free_kernel_space ;stdcall |
dd szKernelAlloc , kernel_alloc ;stdcall |
dd szKernelFree , kernel_free ;stdcall |
dd szUserAlloc , user_alloc ;stdcall |
dd szUserFree , user_free ;stdcall |
dd szKmalloc , malloc |
dd szKfree , free |
dd szCreateRingBuffer, create_ring_buffer ;stdcall |
dd szGetPid , get_pid |
dd szCreateObject , create_kernel_object |
dd szDestroyObject , destroy_kernel_object |
dd szCreateEvent , create_event ;see EVENT.inc for specification |
dd szRaiseEvent , raise_event ;see EVENT.inc for specification |
dd szWaitEvent , wait_event ;see EVENT.inc for specification |
dd szDestroyEvent , destroy_event ;see EVENT.inc for specification |
dd szClearEvent , clear_event ;see EVENT.inc for specification |
dd szLoadCursor , load_cursor ;stdcall |
dd szSysMsgBoardStr , sys_msg_board_str |
dd szSysMsgBoardChar , sys_msg_board |
dd szGetCurrentTask , get_curr_task |
dd szLoadFile , load_file ;retval eax, ebx |
dd szSendEvent , send_event ;see EVENT.inc for specification |
dd szSetMouseData , set_mouse_data ;stdcall |
dd szSleep , delay_ms |
dd szGetTimerTicks , get_timer_ticks |
dd szGetDisplay , get_display |
dd szSetScreen , set_screen |
dd szStrncat , strncat |
dd szStrncpy , strncpy |
dd szstrncmp , strncmp |
dd szStrnlen , strnlen |
dd szStrchr , strchr |
dd szStrrchr , strrchr |
dd szDiskAdd , disk_add |
dd szDiskDel , disk_del |
dd szDiskMediaChanged, disk_media_changed |
dd szTimerHS , timer_hs |
dd szCancelTimerHS , cancel_timer_hs |
exp_lfb: |
dd szLFBAddress , 0 |
dd 0 ;terminator, must be zero |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
szKernel db 'KERNEL', 0 |
szVersion db 'version',0 |
szRegService db 'RegService',0 |
szGetService db 'GetService',0 |
szServiceHandler db 'ServiceHandler',0 |
szAttachIntHandler db 'AttachIntHandler',0 |
; szGetIntHandler db 'GetIntHandler', 0 |
szFpuSave db 'FpuSave',0 |
szFpuRestore db 'FpuRestore',0 |
szReservePortArea db 'ReservePortArea',0 |
szBoot_Log db 'Boot_Log',0 |
szMutexInit db 'MutexInit',0 |
szMutexLock db 'MutexLock',0 |
szMutexUnlock db 'MutexUnlock',0 |
szPciApi db 'PciApi', 0 |
szPciRead32 db 'PciRead32', 0 |
szPciRead16 db 'PciRead16', 0 |
szPciRead8 db 'PciRead8', 0 |
szPciWrite8 db 'PciWrite8',0 |
szPciWrite16 db 'PciWrite16',0 |
szPciWrite32 db 'PciWrite32',0 |
szAllocPage db 'AllocPage',0 |
szAllocPages db 'AllocPages',0 |
szFreePage db 'FreePage',0 |
szGetPgAddr db 'GetPgAddr',0 |
szMapPage db 'MapPage',0 |
szMapSpace db 'MapSpace',0 |
szMapIoMem db 'MapIoMem',0 |
szCommitPages db 'CommitPages',0 |
szReleasePages db 'ReleasePages',0 |
szAllocKernelSpace db 'AllocKernelSpace',0 |
szFreeKernelSpace db 'FreeKernelSpace',0 |
szKernelAlloc db 'KernelAlloc',0 |
szKernelFree db 'KernelFree',0 |
szUserAlloc db 'UserAlloc',0 |
szUserFree db 'UserFree',0 |
szKmalloc db 'Kmalloc',0 |
szKfree db 'Kfree',0 |
szCreateRingBuffer db 'CreateRingBuffer',0 |
szGetPid db 'GetPid',0 |
szCreateObject db 'CreateObject',0 |
szDestroyObject db 'DestroyObject',0 |
szCreateEvent db 'CreateEvent',0 |
szRaiseEvent db 'RaiseEvent',0 |
szWaitEvent db 'WaitEvent',0 |
szDestroyEvent db 'DestroyEvent',0 |
szClearEvent db 'ClearEvent',0 |
szLoadCursor db 'LoadCursor',0 |
szSysMsgBoardStr db 'SysMsgBoardStr', 0 |
szSysMsgBoardChar db 'SysMsgBoardChar', 0 |
szGetCurrentTask db 'GetCurrentTask',0 |
szLFBAddress db 'LFBAddress',0 |
szLoadFile db 'LoadFile',0 |
szSendEvent db 'SendEvent',0 |
szSetMouseData db 'SetMouseData',0 |
szSleep db 'Sleep',0 |
szGetTimerTicks db 'GetTimerTicks',0 |
szGetDisplay db 'GetDisplay',0 |
szSetScreen db 'SetScreen',0 |
szStrncat db 'strncat',0 |
szStrncpy db 'strncpy',0 |
szstrncmp db 'strncmp',0 |
szStrnlen db 'strnlen',0 |
szStrchr db 'strchr',0 |
szStrrchr db 'strrchr',0 |
szDiskAdd db 'DiskAdd',0 |
szDiskDel db 'DiskDel',0 |
szDiskMediaChanged db 'DiskMediaChanged',0 |
szTimerHS db 'TimerHS',0 |
szCancelTimerHS db 'CancelTimerHS',0 |
align 16 |
kernel_export: |
dd szRegService , reg_service |
dd szGetService , get_service |
dd szServiceHandler , srv_handler |
dd szAttachIntHandler, attach_int_handler |
; dd szGetIntHandler , get_int_handler |
dd szFpuSave , fpu_save |
dd szFpuRestore , fpu_restore |
dd szReservePortArea , r_f_port_area |
dd szBoot_Log , boot_log |
dd szMutexInit , mutex_init ;gcc fastcall |
dd szMutexLock , mutex_lock ;gcc fastcall |
dd szMutexUnlock , mutex_unlock ;gcc fastcall |
dd szPciApi , pci_api_drv |
dd szPciRead32 , pci_read32 |
dd szPciRead16 , pci_read16 |
dd szPciRead8 , pci_read8 |
dd szPciWrite8 , pci_write8 |
dd szPciWrite16 , pci_write16 |
dd szPciWrite32 , pci_write32 |
dd szAllocPage , alloc_page ;stdcall |
dd szAllocPages , alloc_pages ;stdcall |
dd szFreePage , free_page |
dd szMapPage , map_page ;stdcall |
dd szMapSpace , map_space |
dd szMapIoMem , map_io_mem ;stdcall |
dd szGetPgAddr , get_pg_addr |
dd szCommitPages , commit_pages ;not implemented |
dd szReleasePages , release_pages |
dd szAllocKernelSpace, alloc_kernel_space ;stdcall |
dd szFreeKernelSpace , free_kernel_space ;stdcall |
dd szKernelAlloc , kernel_alloc ;stdcall |
dd szKernelFree , kernel_free ;stdcall |
dd szUserAlloc , user_alloc ;stdcall |
dd szUserFree , user_free ;stdcall |
dd szKmalloc , malloc |
dd szKfree , free |
dd szCreateRingBuffer, create_ring_buffer ;stdcall |
dd szGetPid , get_pid |
dd szCreateObject , create_kernel_object |
dd szDestroyObject , destroy_kernel_object |
dd szCreateEvent , create_event ;see EVENT.inc for specification |
dd szRaiseEvent , raise_event ;see EVENT.inc for specification |
dd szWaitEvent , wait_event ;see EVENT.inc for specification |
dd szDestroyEvent , destroy_event ;see EVENT.inc for specification |
dd szClearEvent , clear_event ;see EVENT.inc for specification |
dd szLoadCursor , load_cursor ;stdcall |
dd szSysMsgBoardStr , sys_msg_board_str |
dd szSysMsgBoardChar , sys_msg_board |
dd szGetCurrentTask , get_curr_task |
dd szLoadFile , load_file ;retval eax, ebx |
dd szSendEvent , send_event ;see EVENT.inc for specification |
dd szSetMouseData , set_mouse_data ;stdcall |
dd szSleep , delay_ms |
dd szGetTimerTicks , get_timer_ticks |
dd szGetDisplay , get_display |
dd szSetScreen , set_screen |
dd szStrncat , strncat |
dd szStrncpy , strncpy |
dd szstrncmp , strncmp |
dd szStrnlen , strnlen |
dd szStrchr , strchr |
dd szStrrchr , strrchr |
dd szDiskAdd , disk_add |
dd szDiskDel , disk_del |
dd szDiskMediaChanged, disk_media_changed |
dd szTimerHS , timer_hs |
dd szCancelTimerHS , cancel_timer_hs |
exp_lfb: |
dd szLFBAddress , 0 |
dd 0 ;terminator, must be zero |
endg |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/ext_lib.inc |
---|
1,320 → 1,333 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;============================================================================ |
; |
; External kernel dependencies (libraries) loading |
; |
;============================================================================ |
$Revision$ |
if 0 |
; The code currently does not work. Kill "if 0/end if" only after correcting |
; to current kernel (dll.inc). |
macro library [name,fname] |
{ |
forward |
dd __#name#_library_table__,__#name#_library_name__ |
common |
dd 0 |
forward |
__#name#_library_name__ db fname,0 |
} |
macro import lname,[name,sname] |
{ |
common |
align 4 |
__#lname#_library_table__: |
forward |
name dd __#name#_import_name__ |
common |
dd 0 |
forward |
__#name#_import_name__ db sname,0 |
} |
macro export [name,sname] |
{ |
align 4 |
forward |
dd __#name#_export_name__,name |
common |
dd 0 |
forward |
__#name#_export_name__ db sname,0 |
} |
align 4 ; loading library (use kernel functions) |
proc load_k_library stdcall, file_name:dword |
locals |
coff dd ? |
sym dd ? |
strings dd ? |
img_size dd ? |
img_base dd ? |
exports dd ? |
endl |
cli |
stdcall load_file, [file_name] |
test eax, eax |
jz .fail |
mov [coff], eax |
movzx ecx, [eax+CFH.nSections] |
xor ebx, ebx |
lea edx, [eax+20] |
@@: |
add ebx, [edx+CFS.SizeOfRawData] |
add ebx, 15 |
and ebx, not 15 |
add edx, COFF_SECTION_SIZE |
dec ecx |
jnz @B |
mov [img_size], ebx |
stdcall kernel_alloc, [img_size] |
test eax, eax |
jz .fail |
mov [img_base], eax |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, [img_base] |
lea eax, [edx+20] |
@@: |
mov [eax+CFS.VirtualAddress], edi |
mov esi, [eax+CFS.PtrRawData] |
test esi, esi |
jnz .copy |
add edi, [eax+CFS.SizeOfRawData] |
jmp .next |
.copy: |
add esi, edx |
mov ecx, [eax+CFS.SizeOfRawData] |
cld |
rep movsb |
.next: |
add edi, 15 |
and edi, not 15 |
add eax, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
mov ebx, [edx+CFH.pSymTable] |
add ebx, edx |
mov [sym], ebx |
mov ecx, [edx+CFH.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+CFH.nSymbols],\ |
[strings], dword 0 |
test eax, eax |
jnz @F |
@@: |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, 0 |
lea eax, [edx+20] |
@@: |
add [eax+CFS.VirtualAddress], edi ;patch user space offset |
add eax, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
add edx, 20 |
stdcall fix_coff_relocs, [coff], edx, [sym] |
mov ebx, [coff] |
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szEXPORTS |
mov [exports], eax |
stdcall kernel_free, [coff] |
mov eax, [exports] |
ret |
.fail: |
xor eax, eax |
ret |
endp |
proc dll.Load, import_table:dword |
mov esi,[import_table] |
.next_lib: mov edx,[esi] |
or edx,edx |
jz .exit |
push esi |
mov edi,s_libname |
mov al, '/' |
stosb |
mov esi,sysdir_path |
@@: lodsb |
stosb |
or al,al |
jnz @b |
dec edi |
mov [edi], dword '/lib' |
mov [edi+4],byte '/' |
add edi,5 |
pop esi |
push esi |
mov esi,[esi+4] |
@@: lodsb |
stosb |
or al,al |
jnz @b |
pushad |
stdcall load_k_library,s_libname |
mov [esp+28],eax |
popad |
or eax,eax |
jz .fail |
stdcall dll.Link,eax,edx |
stdcall dll.Init,[eax+4] |
pop esi |
add esi,8 |
jmp .next_lib |
.exit: xor eax,eax |
ret |
.fail: add esp,4 |
xor eax,eax |
inc eax |
ret |
endp |
proc dll.Link, exp:dword,imp:dword |
push eax |
mov esi,[imp] |
test esi,esi |
jz .done |
.next: lodsd |
test eax,eax |
jz .done |
stdcall dll.GetProcAddress,[exp],eax |
or eax,eax |
jz @f |
mov [esi-4],eax |
jmp .next |
@@: mov dword[esp],0 |
.done: pop eax |
ret |
endp |
proc dll.Init, dllentry:dword |
pushad |
mov eax,mem.Alloc |
mov ebx,mem.Free |
mov ecx,mem.ReAlloc |
mov edx,dll.Load |
stdcall [dllentry] |
popad |
ret |
endp |
proc dll.GetProcAddress, exp:dword,sz_name:dword |
mov edx,[exp] |
.next: test edx,edx |
jz .end |
stdcall strncmp,[edx],[sz_name], dword -1 |
test eax,eax |
jz .ok |
add edx,8 |
jmp .next |
.ok: mov eax,[edx+4] |
.end: ret |
endp |
;----------------------------------------------------------------------------- |
proc mem.Alloc size ;///////////////////////////////////////////////////////// |
;----------------------------------------------------------------------------- |
push ebx ecx |
; mov eax,[size] |
; lea ecx,[eax+4+4095] |
; and ecx,not 4095 |
; stdcall kernel_alloc, ecx |
; add ecx,-4 |
; mov [eax],ecx |
; add eax,4 |
stdcall kernel_alloc, [size] |
pop ecx ebx |
ret |
endp |
;----------------------------------------------------------------------------- |
proc mem.ReAlloc mptr,size;/////////////////////////////////////////////////// |
;----------------------------------------------------------------------------- |
push ebx ecx esi edi eax |
mov eax,[mptr] |
mov ebx,[size] |
or eax,eax |
jz @f |
lea ecx,[ebx+4+4095] |
and ecx,not 4095 |
add ecx,-4 |
cmp ecx,[eax-4] |
je .exit |
@@: mov eax,ebx |
call mem.Alloc |
xchg eax,[esp] |
or eax,eax |
jz .exit |
mov esi,eax |
xchg eax,[esp] |
mov edi,eax |
mov ecx,[esi-4] |
cmp ecx,[edi-4] |
jbe @f |
mov ecx,[edi-4] |
@@: add ecx,3 |
shr ecx,2 |
cld |
rep movsd |
xchg eax,[esp] |
call mem.Free |
.exit: |
pop eax edi esi ecx ebx |
ret |
endp |
;----------------------------------------------------------------------------- |
proc mem.Free mptr ;////////////////////////////////////////////////////////// |
;----------------------------------------------------------------------------- |
; mov eax,[mptr] |
; or eax,eax |
; jz @f |
; push ebx ecx |
; lea ecx,[eax-4] |
; stdcall kernel_free, ecx |
; pop ecx ebx |
; @@: ret |
stdcall kernel_free, [mptr] |
ret |
endp |
uglobal |
s_libname db 64 dup (0) |
endg |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;============================================================================ |
; |
; External kernel dependencies (libraries) loading |
; |
;============================================================================ |
$Revision$ |
if 0 |
; The code currently does not work. Kill "if 0/end if" only after correcting |
; to current kernel (dll.inc). |
macro library [name,fname] |
{ |
forward |
dd __#name#_library_table__,__#name#_library_name__ |
common |
dd 0 |
forward |
__#name#_library_name__ db fname,0 |
} |
macro import lname,[name,sname] |
{ |
common |
align 4 |
__#lname#_library_table__: |
forward |
name dd __#name#_import_name__ |
common |
dd 0 |
forward |
__#name#_import_name__ db sname,0 |
} |
macro export [name,sname] |
{ |
align 4 |
forward |
dd __#name#_export_name__,name |
common |
dd 0 |
forward |
__#name#_export_name__ db sname,0 |
} |
align 4 ; loading library (use kernel functions) |
proc load_k_library stdcall, file_name:dword |
locals |
coff dd ? |
sym dd ? |
strings dd ? |
img_size dd ? |
img_base dd ? |
exports dd ? |
endl |
cli |
stdcall load_file, [file_name] |
test eax, eax |
jz .fail |
mov [coff], eax |
movzx ecx, [eax+CFH.nSections] |
xor ebx, ebx |
lea edx, [eax+20] |
@@: |
add ebx, [edx+CFS.SizeOfRawData] |
add ebx, 15 |
and ebx, not 15 |
add edx, COFF_SECTION_SIZE |
dec ecx |
jnz @B |
mov [img_size], ebx |
stdcall kernel_alloc, [img_size] |
test eax, eax |
jz .fail |
mov [img_base], eax |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, [img_base] |
lea eax, [edx+20] |
@@: |
mov [eax+CFS.VirtualAddress], edi |
mov esi, [eax+CFS.PtrRawData] |
test esi, esi |
jnz .copy |
add edi, [eax+CFS.SizeOfRawData] |
jmp .next |
.copy: |
add esi, edx |
mov ecx, [eax+CFS.SizeOfRawData] |
cld |
rep movsb |
.next: |
add edi, 15 |
and edi, not 15 |
add eax, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
mov ebx, [edx+CFH.pSymTable] |
add ebx, edx |
mov [sym], ebx |
mov ecx, [edx+CFH.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+CFH.nSymbols], \ |
[strings], dword 0 |
test eax, eax |
jnz @F |
@@: |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, 0 |
lea eax, [edx+20] |
@@: |
add [eax+CFS.VirtualAddress], edi ;patch user space offset |
add eax, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
add edx, 20 |
stdcall fix_coff_relocs, [coff], edx, [sym] |
mov ebx, [coff] |
stdcall get_coff_sym, [sym], [ebx+CFH.nSymbols], szEXPORTS |
mov [exports], eax |
stdcall kernel_free, [coff] |
mov eax, [exports] |
ret |
.fail: |
xor eax, eax |
ret |
endp |
proc dll.Load, import_table:dword |
mov esi, [import_table] |
.next_lib: |
mov edx, [esi] |
or edx, edx |
jz .exit |
push esi |
mov edi, s_libname |
mov al, '/' |
stosb |
mov esi, sysdir_path |
@@: |
lodsb |
stosb |
or al, al |
jnz @b |
dec edi |
mov [edi], dword '/lib' |
mov [edi+4], byte '/' |
add edi, 5 |
pop esi |
push esi |
mov esi, [esi+4] |
@@: |
lodsb |
stosb |
or al, al |
jnz @b |
pushad |
stdcall load_k_library, s_libname |
mov [esp+28], eax |
popad |
or eax, eax |
jz .fail |
stdcall dll.Link, eax, edx |
stdcall dll.Init, [eax+4] |
pop esi |
add esi, 8 |
jmp .next_lib |
.exit: |
xor eax, eax |
ret |
.fail: |
add esp, 4 |
xor eax, eax |
inc eax |
ret |
endp |
proc dll.Link, exp:dword,imp:dword |
push eax |
mov esi, [imp] |
test esi, esi |
jz .done |
.next: |
lodsd |
test eax, eax |
jz .done |
stdcall dll.GetProcAddress, [exp], eax |
or eax, eax |
jz @f |
mov [esi-4], eax |
jmp .next |
@@: |
mov dword[esp], 0 |
.done: |
pop eax |
ret |
endp |
proc dll.Init, dllentry:dword |
pushad |
mov eax, mem.Alloc |
mov ebx, mem.Free |
mov ecx, mem.ReAlloc |
mov edx, dll.Load |
stdcall [dllentry] |
popad |
ret |
endp |
proc dll.GetProcAddress, exp:dword,sz_name:dword |
mov edx, [exp] |
.next: |
test edx, edx |
jz .end |
stdcall strncmp, [edx], [sz_name], dword -1 |
test eax, eax |
jz .ok |
add edx, 8 |
jmp .next |
.ok: |
mov eax, [edx+4] |
.end: |
ret |
endp |
;----------------------------------------------------------------------------- |
proc mem.Alloc size ;///////////////////////////////////////////////////////// |
;----------------------------------------------------------------------------- |
push ebx ecx |
; mov eax,[size] |
; lea ecx,[eax+4+4095] |
; and ecx,not 4095 |
; stdcall kernel_alloc, ecx |
; add ecx,-4 |
; mov [eax],ecx |
; add eax,4 |
stdcall kernel_alloc, [size] |
pop ecx ebx |
ret |
endp |
;----------------------------------------------------------------------------- |
proc mem.ReAlloc mptr,size;/////////////////////////////////////////////////// |
;----------------------------------------------------------------------------- |
push ebx ecx esi edi eax |
mov eax, [mptr] |
mov ebx, [size] |
or eax, eax |
jz @f |
lea ecx, [ebx+4+4095] |
and ecx, not 4095 |
add ecx, -4 |
cmp ecx, [eax-4] |
je .exit |
@@: |
mov eax, ebx |
call mem.Alloc |
xchg eax, [esp] |
or eax, eax |
jz .exit |
mov esi, eax |
xchg eax, [esp] |
mov edi, eax |
mov ecx, [esi-4] |
cmp ecx, [edi-4] |
jbe @f |
mov ecx, [edi-4] |
@@: |
add ecx, 3 |
shr ecx, 2 |
cld |
rep movsd |
xchg eax, [esp] |
call mem.Free |
.exit: |
pop eax edi esi ecx ebx |
ret |
endp |
;----------------------------------------------------------------------------- |
proc mem.Free mptr ;////////////////////////////////////////////////////////// |
;----------------------------------------------------------------------------- |
; mov eax,[mptr] |
; or eax,eax |
; jz @f |
; push ebx ecx |
; lea ecx,[eax-4] |
; stdcall kernel_free, ecx |
; pop ecx ebx |
; @@: ret |
stdcall kernel_free, [mptr] |
ret |
endp |
uglobal |
s_libname db 64 dup (0) |
endg |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/fpu.inc |
---|
1,183 → 1,183 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
init_fpu: |
clts |
fninit |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
mov ebx, cr4 |
mov ecx, cr0 |
or ebx, CR4_OSFXSR+CR4_OSXMMEXPT |
mov cr4, ebx |
and ecx, not (CR0_MP+CR0_EM) |
or ecx, CR0_NE |
mov cr0, ecx |
mov dword [esp-4], SSE_INIT |
ldmxcsr [esp-4] |
xorps xmm0, xmm0 |
xorps xmm1, xmm1 |
xorps xmm2, xmm2 |
xorps xmm3, xmm3 |
xorps xmm4, xmm4 |
xorps xmm5, xmm5 |
xorps xmm6, xmm6 |
xorps xmm7, xmm7 |
fxsave [fpu_data] ;[eax] |
ret |
.no_SSE: |
mov ecx, cr0 |
and ecx, not CR0_EM |
or ecx, CR0_MP+CR0_NE |
mov cr0, ecx |
fnsave [fpu_data] |
ret |
; param |
; eax= 512 bytes memory area |
align 4 |
fpu_save: |
push ecx |
push esi |
push edi |
pushfd |
cli |
clts |
mov edi, eax |
mov ecx, [fpu_owner] |
mov esi, [CURRENT_TASK] |
cmp ecx, esi |
jne .save |
call save_context |
jmp .exit |
.save: |
mov [fpu_owner], esi |
shl ecx, 8 |
mov eax, [ecx+SLOT_BASE+APPDATA.fpu_state] |
call save_context |
shl esi, 8 |
mov esi, [esi+SLOT_BASE+APPDATA.fpu_state] |
mov ecx, 512/4 |
cld |
rep movsd |
fninit |
.exit: |
popfd |
pop edi |
pop esi |
pop ecx |
ret |
align 4 |
save_context: |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxsave [eax] |
ret |
.no_SSE: |
fnsave [eax] |
ret |
align 4 |
fpu_restore: |
push ecx |
push esi |
mov esi, eax |
pushfd |
cli |
mov ecx, [fpu_owner] |
mov eax, [CURRENT_TASK] |
cmp ecx, eax |
jne .copy |
clts |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxrstor [esi] |
popfd |
pop esi |
pop ecx |
ret |
.no_SSE: |
fnclex ;fix possible problems |
frstor [esi] |
popfd |
pop esi |
pop ecx |
ret |
.copy: |
shl eax, 8 |
mov edi, [eax+SLOT_BASE+APPDATA.fpu_state] |
mov ecx, 512/4 |
cld |
rep movsd |
popfd |
pop esi |
pop ecx |
ret |
align 4 |
except_7: ;#NM exception handler |
save_ring3_context |
clts |
mov ax, app_data ; |
mov ds, ax |
mov es, ax |
mov ebx, [fpu_owner] |
cmp ebx, [CURRENT_TASK] |
je .exit |
shl ebx, 8 |
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxsave [eax] |
mov ebx, [CURRENT_TASK] |
mov [fpu_owner], ebx |
shl ebx, 8 |
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] |
fxrstor [eax] |
.exit: |
restore_ring3_context |
iret |
.no_SSE: |
fnsave [eax] |
mov ebx, [CURRENT_TASK] |
mov [fpu_owner], ebx |
shl ebx, 8 |
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] |
frstor [eax] |
restore_ring3_context |
iret |
iglobal |
fpu_owner dd 0 |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
init_fpu: |
clts |
fninit |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
mov ebx, cr4 |
mov ecx, cr0 |
or ebx, CR4_OSFXSR+CR4_OSXMMEXPT |
mov cr4, ebx |
and ecx, not (CR0_MP+CR0_EM) |
or ecx, CR0_NE |
mov cr0, ecx |
mov dword [esp-4], SSE_INIT |
ldmxcsr [esp-4] |
xorps xmm0, xmm0 |
xorps xmm1, xmm1 |
xorps xmm2, xmm2 |
xorps xmm3, xmm3 |
xorps xmm4, xmm4 |
xorps xmm5, xmm5 |
xorps xmm6, xmm6 |
xorps xmm7, xmm7 |
fxsave [fpu_data] ;[eax] |
ret |
.no_SSE: |
mov ecx, cr0 |
and ecx, not CR0_EM |
or ecx, CR0_MP+CR0_NE |
mov cr0, ecx |
fnsave [fpu_data] |
ret |
; param |
; eax= 512 bytes memory area |
align 4 |
fpu_save: |
push ecx |
push esi |
push edi |
pushfd |
cli |
clts |
mov edi, eax |
mov ecx, [fpu_owner] |
mov esi, [CURRENT_TASK] |
cmp ecx, esi |
jne .save |
call save_context |
jmp .exit |
.save: |
mov [fpu_owner], esi |
shl ecx, 8 |
mov eax, [ecx+SLOT_BASE+APPDATA.fpu_state] |
call save_context |
shl esi, 8 |
mov esi, [esi+SLOT_BASE+APPDATA.fpu_state] |
mov ecx, 512/4 |
cld |
rep movsd |
fninit |
.exit: |
popfd |
pop edi |
pop esi |
pop ecx |
ret |
align 4 |
save_context: |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxsave [eax] |
ret |
.no_SSE: |
fnsave [eax] |
ret |
align 4 |
fpu_restore: |
push ecx |
push esi |
mov esi, eax |
pushfd |
cli |
mov ecx, [fpu_owner] |
mov eax, [CURRENT_TASK] |
cmp ecx, eax |
jne .copy |
clts |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxrstor [esi] |
popfd |
pop esi |
pop ecx |
ret |
.no_SSE: |
fnclex ;fix possible problems |
frstor [esi] |
popfd |
pop esi |
pop ecx |
ret |
.copy: |
shl eax, 8 |
mov edi, [eax+SLOT_BASE+APPDATA.fpu_state] |
mov ecx, 512/4 |
cld |
rep movsd |
popfd |
pop esi |
pop ecx |
ret |
align 4 |
except_7: ;#NM exception handler |
save_ring3_context |
clts |
mov ax, app_data; |
mov ds, ax |
mov es, ax |
mov ebx, [fpu_owner] |
cmp ebx, [CURRENT_TASK] |
je .exit |
shl ebx, 8 |
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxsave [eax] |
mov ebx, [CURRENT_TASK] |
mov [fpu_owner], ebx |
shl ebx, 8 |
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] |
fxrstor [eax] |
.exit: |
restore_ring3_context |
iret |
.no_SSE: |
fnsave [eax] |
mov ebx, [CURRENT_TASK] |
mov [fpu_owner], ebx |
shl ebx, 8 |
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] |
frstor [eax] |
restore_ring3_context |
iret |
iglobal |
fpu_owner dd 0 |
endg |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/heap.inc |
---|
1,1474 → 1,1474 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
struc MEM_BLOCK |
{ |
.list LHEAD |
.next_block dd ? ;+8 |
.prev_block dd ? ;+4 |
.base dd ? ;+16 |
.size dd ? ;+20 |
.flags dd ? ;+24 |
.handle dd ? ;+28 |
.sizeof: |
} |
FREE_BLOCK equ 4 |
USED_BLOCK equ 8 |
DONT_FREE_BLOCK equ 10h |
virtual at 0 |
MEM_BLOCK MEM_BLOCK |
end virtual |
block_next equ MEM_BLOCK.next_block |
block_prev equ MEM_BLOCK.prev_block |
list_fd equ MEM_BLOCK.list.next |
list_bk equ MEM_BLOCK.list.prev |
block_base equ MEM_BLOCK.base |
block_size equ MEM_BLOCK.size |
block_flags equ MEM_BLOCK.flags |
macro calc_index op |
{ shr op, 12 |
dec op |
cmp op, 63 |
jna @f |
mov op, 63 |
@@: |
} |
align 4 |
md: |
.add_to_used: |
mov eax, [esi+block_base] |
mov ebx, [esi+block_base] |
shr ebx, 6 |
add eax, ebx |
shr ebx, 6 |
add eax, ebx |
shr eax, 12 |
and eax, 63 |
inc [mem_hash_cnt+eax*4] |
lea ecx, [mem_used_list+eax*8] |
list_add esi, ecx |
mov [esi+block_flags], USED_BLOCK |
mov eax, [esi+block_size] |
sub [heap_free], eax |
ret |
align 4 |
.find_used: |
mov ecx, eax |
mov ebx, eax |
shr ebx, 6 |
add ecx, ebx |
shr ebx, 6 |
add ecx, ebx |
shr ecx, 12 |
and ecx, 63 |
lea ebx, [mem_used_list+ecx*8] |
mov esi, ebx |
.next: |
mov esi, [esi+list_fd] |
cmp esi, ebx |
je .fail |
cmp eax, [esi+block_base] |
jne .next |
ret |
.fail: |
xor esi, esi |
ret |
align 4 |
.del_from_used: |
call .find_used |
test esi, esi |
jz .done |
cmp [esi+block_flags], USED_BLOCK |
jne .fatal |
dec [mem_hash_cnt+ecx*4] |
list_del esi |
.done: |
ret |
.fatal: ;FIXME panic here |
xor esi, esi |
ret |
;Initial heap state |
; |
;+heap_size terminator USED_BLOCK |
;+4096*MEM_BLOCK.sizeof free space FREE_BLOCK |
;HEAP_BASE heap_descriptors USED_BLOCK |
; |
align 4 |
proc init_kernel_heap |
mov ecx, 64 |
mov edi, mem_block_list |
@@: |
mov eax, edi |
stosd |
stosd |
loop @B |
mov ecx, 64 |
mov edi, mem_used_list |
@@: |
mov eax, edi |
stosd |
stosd |
loop @B |
stdcall alloc_pages, dword 32 |
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 |
mov edi, HEAP_BASE ;descriptors |
mov ebx, HEAP_BASE+MEM_BLOCK.sizeof ;free space |
mov ecx, HEAP_BASE+MEM_BLOCK.sizeof*2 ;terminator |
xor eax, eax |
mov [edi+block_next], ebx |
mov [edi+block_prev], eax |
mov [edi+list_fd], eax |
mov [edi+list_bk], eax |
mov [edi+block_base], HEAP_BASE |
mov [edi+block_size], 4096*MEM_BLOCK.sizeof |
mov [edi+block_flags], USED_BLOCK |
mov [ecx+block_next], eax |
mov [ecx+block_prev], ebx |
mov [edi+list_fd], eax |
mov [edi+list_bk], eax |
mov [edi+block_base], eax |
mov [edi+block_size], eax |
mov [edi+block_flags], USED_BLOCK |
mov [ebx+block_next], ecx |
mov [ebx+block_prev], edi |
mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK.sizeof |
mov ecx, [pg_data.kernel_pages] |
shl ecx, 12 |
sub ecx, HEAP_BASE-OS_BASE+4096*MEM_BLOCK.sizeof |
mov [heap_size], ecx |
mov [heap_free], ecx |
mov [ebx+block_size], ecx |
mov [ebx+block_flags], FREE_BLOCK |
mov [mem_block_mask], eax |
mov [mem_block_mask+4],0x80000000 |
mov ecx, mem_block_list+63*8 |
list_add ebx, ecx |
mov ecx, 4096-3-1 |
mov eax, HEAP_BASE+MEM_BLOCK.sizeof*4 |
mov [next_memblock], HEAP_BASE+MEM_BLOCK.sizeof*3 |
@@: |
mov [eax-MEM_BLOCK.sizeof], eax |
add eax, MEM_BLOCK.sizeof |
loop @B |
mov [eax-MEM_BLOCK.sizeof], dword 0 |
mov ecx, heap_mutex |
call mutex_init |
mov [heap_blocks], 4094 |
mov [free_blocks], 4093 |
ret |
endp |
; param |
; eax= required size |
; |
; retval |
; edi= memory block descriptor |
; ebx= descriptor index |
align 4 |
get_small_block: |
mov ecx, eax |
shr ecx, 12 |
dec ecx |
cmp ecx, 63 |
jle .get_index |
mov ecx, 63 |
.get_index: |
lea esi, [mem_block_mask] |
xor ebx, ebx |
or edx, -1 |
cmp ecx, 32 |
jb .bit_test |
sub ecx, 32 |
add ebx, 32 |
add esi, 4 |
.bit_test: |
shl edx, cl |
and edx, [esi] |
.find: |
bsf edi, edx |
jz .high_mask |
add ebx, edi |
lea ecx, [mem_block_list+ebx*8] |
mov edi, ecx |
.next: |
mov edi, [edi+list_fd] |
cmp edi, ecx |
je .err |
cmp eax, [edi+block_size] |
ja .next |
ret |
.err: |
xor edi, edi |
ret |
.high_mask: |
add esi, 4 |
cmp esi, mem_block_mask+8 |
jae .err |
add ebx, 32 |
mov edx, [esi] |
jmp .find |
align 4 |
free_mem_block: |
mov ebx, [next_memblock] |
mov [eax], ebx |
mov [next_memblock], eax |
xor ebx, ebx |
mov dword [eax+4], ebx |
mov dword [eax+8], ebx |
mov dword [eax+12], ebx |
mov dword [eax+16], ebx |
; mov dword [eax+20], 0 ;don't clear block size |
mov dword [eax+24], ebx |
mov dword [eax+28], ebx |
inc [free_blocks] |
ret |
align 4 |
proc alloc_kernel_space stdcall, size:dword |
local block_ind:DWORD |
push ebx |
push esi |
push edi |
mov eax, [size] |
add eax, 4095 |
and eax, not 4095 |
mov [size], eax |
cmp eax, [heap_free] |
ja .error |
mov ecx, heap_mutex |
call mutex_lock |
mov eax, [size] |
call get_small_block ; eax |
test edi, edi |
jz .error_unlock |
cmp [edi+block_flags], FREE_BLOCK |
jne .error_unlock |
mov [block_ind], ebx ;index of allocated block |
mov eax, [edi+block_size] |
cmp eax, [size] |
je .m_eq_size |
mov esi, [next_memblock] ;new memory block |
test esi, esi |
jz .error_unlock |
dec [free_blocks] |
mov eax, [esi] |
mov [next_memblock], eax |
mov [esi+block_next], edi |
mov eax, [edi+block_prev] |
mov [esi+block_prev], eax |
mov [edi+block_prev], esi |
mov [esi+list_fd], 0 |
mov [esi+list_bk], 0 |
mov [eax+block_next], esi |
mov ebx, [edi+block_base] |
mov [esi+block_base], ebx |
mov edx, [size] |
mov [esi+block_size], edx |
add [edi+block_base], edx |
sub [edi+block_size], edx |
mov eax, [edi+block_size] |
calc_index eax |
cmp eax, [block_ind] |
je .add_used |
list_del edi |
mov ecx, [block_ind] |
lea edx, [mem_block_list+ecx*8] |
cmp edx, [edx] |
jnz @f |
btr [mem_block_mask], ecx |
@@: |
bts [mem_block_mask], eax |
lea edx, [mem_block_list+eax*8] ;edx= list head |
list_add edi, edx |
.add_used: |
call md.add_to_used |
mov ecx, heap_mutex |
call mutex_unlock |
mov eax, [esi+block_base] |
pop edi |
pop esi |
pop ebx |
ret |
.m_eq_size: |
list_del edi |
lea edx, [mem_block_list+ebx*8] |
cmp edx, [edx] |
jnz @f |
btr [mem_block_mask], ebx |
@@: |
mov esi, edi |
jmp .add_used |
.error_unlock: |
mov ecx, heap_mutex |
call mutex_unlock |
.error: |
xor eax, eax |
pop edi |
pop esi |
pop ebx |
ret |
endp |
align 4 |
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword |
mov ecx, heap_mutex |
call mutex_lock |
mov eax, [base] |
call md.del_from_used |
test esi, esi |
jz .fail |
mov eax, [esi+block_size] |
add [heap_free], eax |
mov edi, [esi+block_next] |
cmp [edi+block_flags], FREE_BLOCK |
jne .prev |
list_del edi |
mov edx, [edi+block_next] |
mov [esi+block_next], edx |
mov [edx+block_prev], esi |
mov ecx, [edi+block_size] |
add [esi+block_size], ecx |
calc_index ecx |
lea edx, [mem_block_list+ecx*8] |
cmp edx, [edx] |
jne @F |
btr [mem_block_mask], ecx |
@@: |
mov eax, edi |
call free_mem_block |
.prev: |
mov edi, [esi+block_prev] |
cmp [edi+block_flags], FREE_BLOCK |
jne .insert |
mov edx, [esi+block_next] |
mov [edi+block_next], edx |
mov [edx+block_prev], edi |
mov eax, esi |
call free_mem_block |
mov ecx, [edi+block_size] |
mov eax, [esi+block_size] |
add eax, ecx |
mov [edi+block_size], eax |
calc_index eax ;new index |
calc_index ecx ;old index |
cmp eax, ecx |
je .m_eq |
push ecx |
list_del edi |
pop ecx |
lea edx, [mem_block_list+ecx*8] |
cmp edx, [edx] |
jne .add_block |
btr [mem_block_mask], ecx |
.add_block: |
bts [mem_block_mask], eax |
lea edx, [mem_block_list+eax*8] |
list_add edi, edx |
.m_eq: |
mov ecx, heap_mutex |
call mutex_unlock |
xor eax, eax |
not eax |
ret |
.insert: |
mov [esi+block_flags], FREE_BLOCK |
mov eax, [esi+block_size] |
calc_index eax |
mov edi, esi |
jmp .add_block |
.fail: |
mov ecx, heap_mutex |
call mutex_unlock |
xor eax, eax |
ret |
endp |
align 4 |
proc kernel_alloc stdcall, size:dword |
locals |
lin_addr dd ? |
pages_count dd ? |
endl |
push ebx |
push edi |
mov eax, [size] |
add eax, 4095 |
and eax, not 4095; |
mov [size], eax |
and eax, eax |
jz .err |
mov ebx, eax |
shr ebx, 12 |
mov [pages_count], ebx |
stdcall alloc_kernel_space, eax |
test eax, eax |
jz .err |
mov [lin_addr], eax |
mov ecx, [pages_count] |
mov edx, eax |
mov ebx, ecx |
shr ecx, 3 |
jz .next |
and ebx, not 7 |
push ebx |
stdcall alloc_pages, ebx |
pop ecx ; yes ecx!!! |
and 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 |
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 |
jnz @B |
.end: |
mov eax, [lin_addr] |
pop edi |
pop ebx |
ret |
.err: |
xor eax, eax |
pop edi |
pop ebx |
ret |
endp |
align 4 |
proc kernel_free stdcall, base:dword |
push ebx esi |
mov ecx, heap_mutex |
call mutex_lock |
mov eax, [base] |
call md.find_used |
mov ecx, heap_mutex |
cmp [esi+block_flags], USED_BLOCK |
jne .fail |
call mutex_unlock |
mov eax, [esi+block_base] |
mov ecx, [esi+block_size] |
shr ecx, 12 |
call release_pages ;eax, ecx |
stdcall free_kernel_space, [base] |
pop esi ebx |
ret |
.fail: |
call mutex_unlock |
xor eax, eax |
pop esi ebx |
ret |
endp |
restore block_next |
restore block_prev |
restore block_list |
restore block_base |
restore block_size |
restore block_flags |
;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;; |
HEAP_TOP equ 0x5FC00000 |
align 4 |
proc init_heap |
mov ebx,[current_slot] |
mov eax, [ebx+APPDATA.heap_top] |
test eax, eax |
jz @F |
sub eax,[ebx+APPDATA.heap_base] |
sub eax, 4096 |
ret |
@@: |
mov esi, [ebx+APPDATA.mem_size] |
add esi, 4095 |
and esi, not 4095 |
mov [ebx+APPDATA.mem_size], esi |
mov eax, HEAP_TOP |
mov [ebx+APPDATA.heap_base], esi |
mov [ebx+APPDATA.heap_top], eax |
sub eax, esi |
shr esi, 10 |
mov ecx, eax |
sub eax, 4096 |
or ecx, FREE_BLOCK |
mov [page_tabs+esi], ecx |
ret |
endp |
align 4 |
proc user_alloc stdcall, alloc_size:dword |
push ebx |
push esi |
push edi |
mov ecx, [alloc_size] |
add ecx, (4095+4096) |
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: |
cmp esi, edi |
jae m_exit |
mov ebx, esi |
shr ebx, 12 |
mov eax, [page_tabs+ebx*4] |
test al, FREE_BLOCK |
jz test_used |
and eax, 0xFFFFF000 |
cmp eax, ecx ;alloc_size |
jb m_next |
jz @f |
lea edx, [esi+ecx] |
sub eax, ecx |
or al, FREE_BLOCK |
shr edx, 12 |
mov [page_tabs+edx*4], eax |
@@: |
or ecx, USED_BLOCK |
mov [page_tabs+ebx*4], ecx |
shr ecx, 12 |
inc ebx |
dec ecx |
jz .no |
@@: |
mov dword [page_tabs+ebx*4], 2 |
inc ebx |
dec ecx |
jnz @B |
.no: |
mov edx, [current_slot] |
mov ebx, [alloc_size] |
add ebx, 0xFFF |
and ebx, not 0xFFF |
add ebx, [edx+APPDATA.mem_size] |
call update_mem_size |
lea eax, [esi+4096] |
pop edi |
pop esi |
pop ebx |
ret |
test_used: |
test al, USED_BLOCK |
jz m_exit |
and eax, 0xFFFFF000 |
m_next: |
add esi, eax |
jmp l_0 |
m_exit: |
xor eax, eax |
pop edi |
pop esi |
pop ebx |
ret |
endp |
align 4 |
proc user_alloc_at stdcall, address:dword, alloc_size:dword |
push ebx |
push esi |
push edi |
mov ebx, [current_slot] |
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] |
cmp edx, esi |
jb .error |
.scan: |
cmp esi, edi |
jae .error |
mov ebx, esi |
shr ebx, 12 |
mov eax, [page_tabs+ebx*4] |
mov ecx, eax |
and ecx, 0xFFFFF000 |
add ecx, esi |
cmp edx, ecx |
jb .found |
mov esi, ecx |
jmp .scan |
.error: |
xor eax, eax |
pop edi |
pop esi |
pop ebx |
ret |
.found: |
test al, FREE_BLOCK |
jz .error |
mov eax, ecx |
sub eax, edx |
sub eax, 0x1000 |
cmp eax, [alloc_size] |
jb .error |
; Here we have 1 big free block which includes requested area. |
; In general, 3 other blocks must be created instead: |
; free at [esi, edx); |
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000)); |
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx) |
; First or third block (or both) may be absent. |
mov eax, edx |
sub eax, esi |
jz .nofirst |
or al, FREE_BLOCK |
mov [page_tabs+ebx*4], eax |
.nofirst: |
mov eax, [alloc_size] |
add eax, 0x1FFF |
and eax, not 0xFFF |
mov ebx, edx |
add edx, eax |
shr ebx, 12 |
or al, USED_BLOCK |
mov [page_tabs+ebx*4], eax |
shr eax, 12 |
dec eax |
jz .second_nofill |
inc ebx |
.fill: |
mov dword [page_tabs+ebx*4], 2 |
inc ebx |
dec eax |
jnz .fill |
.second_nofill: |
sub ecx, edx |
jz .nothird |
or cl, FREE_BLOCK |
mov [page_tabs+ebx*4], ecx |
.nothird: |
mov edx, [current_slot] |
mov ebx, [alloc_size] |
add ebx, 0xFFF |
and ebx, not 0xFFF |
add ebx, [edx+APPDATA.mem_size] |
call update_mem_size |
mov eax, [address] |
pop edi |
pop esi |
pop ebx |
ret |
endp |
align 4 |
proc user_free stdcall, base:dword |
push esi |
mov esi, [base] |
test esi, esi |
jz .exit |
push ebx |
xor ebx, ebx |
shr esi, 12 |
mov eax, [page_tabs+(esi-1)*4] |
test al, USED_BLOCK |
jz .cantfree |
test al, DONT_FREE_BLOCK |
jnz .cantfree |
and eax, not 4095 |
mov ecx, eax |
or al, FREE_BLOCK |
mov [page_tabs+(esi-1)*4], eax |
sub ecx, 4096 |
mov ebx, ecx |
shr ecx, 12 |
jz .released |
.release: |
xor eax, eax |
xchg eax, [page_tabs+esi*4] |
test al, 1 |
jz @F |
test eax, PG_SHARED |
jnz @F |
call free_page |
mov eax, esi |
shl eax, 12 |
invlpg [eax] |
@@: |
inc esi |
dec ecx |
jnz .release |
.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] |
neg ebx |
call update_mem_size |
call user_normalize |
pop edi |
pop ebx |
pop esi |
ret |
.exit: |
xor eax, eax |
inc eax |
pop esi |
ret |
.cantfree: |
xor eax, eax |
pop ebx |
pop esi |
ret |
endp |
user_normalize: |
; in: esi=heap_base, edi=heap_top |
; out: eax=0 <=> OK |
; destroys: ebx,edx,esi,edi |
shr esi, 12 |
shr edi, 12 |
@@: |
mov eax, [page_tabs+esi*4] |
test al, USED_BLOCK |
jz .test_free |
shr eax, 12 |
add esi, eax |
jmp @B |
.test_free: |
test al, FREE_BLOCK |
jz .err |
mov edx, eax |
shr edx, 12 |
add edx, esi |
cmp edx, edi |
jae .exit |
mov ebx, [page_tabs+edx*4] |
test bl, USED_BLOCK |
jz .next_free |
shr ebx, 12 |
add edx, ebx |
mov esi, edx |
jmp @B |
.next_free: |
test bl, FREE_BLOCK |
jz .err |
and dword [page_tabs+edx*4], 0 |
add eax, ebx |
and eax, not 4095 |
or eax, FREE_BLOCK |
mov [page_tabs+esi*4], eax |
jmp @B |
.exit: |
xor eax, eax |
inc eax |
ret |
.err: |
xor eax, eax |
ret |
user_realloc: |
; in: eax = pointer, ebx = new size |
; out: eax = new pointer or NULL |
test eax, eax |
jnz @f |
; realloc(NULL,sz) - same as malloc(sz) |
push ebx |
call user_alloc |
ret |
@@: |
push ecx edx |
lea ecx, [eax - 0x1000] |
shr ecx, 12 |
mov edx, [page_tabs+ecx*4] |
test dl, USED_BLOCK |
jnz @f |
; attempt to realloc invalid pointer |
.ret0: |
pop edx ecx |
xor eax, eax |
ret |
@@: |
test dl, DONT_FREE_BLOCK |
jnz .ret0 |
add ebx, 0x1FFF |
shr edx, 12 |
shr ebx, 12 |
; edx = allocated size, ebx = new size |
add edx, ecx |
add ebx, ecx |
cmp edx, ebx |
jb .realloc_add |
; release part of allocated memory |
.loop: |
cmp edx, ebx |
jz .release_done |
dec edx |
xor eax, eax |
xchg eax, [page_tabs+edx*4] |
test al, 1 |
jz .loop |
call free_page |
mov eax, edx |
shl eax, 12 |
invlpg [eax] |
jmp .loop |
.release_done: |
sub ebx, ecx |
cmp ebx, 1 |
jnz .nofreeall |
mov eax, [page_tabs+ecx*4] |
and eax, not 0xFFF |
mov edx, [current_slot] |
mov ebx, [APPDATA.mem_size+edx] |
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 |
call user_normalize |
pop edi esi |
jmp .ret0 ; all freed |
.nofreeall: |
sub edx, ecx |
shl ebx, 12 |
or ebx, USED_BLOCK |
xchg [page_tabs+ecx*4], ebx |
shr ebx, 12 |
sub ebx, edx |
push ebx ecx edx |
mov edx, [current_slot] |
shl ebx, 12 |
sub ebx, [APPDATA.mem_size+edx] |
neg ebx |
call update_mem_size |
pop edx ecx ebx |
lea eax, [ecx+1] |
shl eax, 12 |
push eax |
add ecx, edx |
lea edx, [ecx+ebx] |
shl ebx, 12 |
jz .ret |
push esi |
mov esi, [current_slot] |
mov esi, [APPDATA.heap_top+esi] |
shr esi, 12 |
@@: |
cmp edx, esi |
jae .merge_done |
mov eax, [page_tabs+edx*4] |
test al, USED_BLOCK |
jnz .merge_done |
and dword [page_tabs+edx*4], 0 |
shr eax, 12 |
add edx, eax |
shl eax, 12 |
add ebx, eax |
jmp @b |
.merge_done: |
pop esi |
or ebx, FREE_BLOCK |
mov [page_tabs+ecx*4], ebx |
.ret: |
pop eax edx ecx |
ret |
.realloc_add: |
; get some additional memory |
mov eax, [current_slot] |
mov eax, [APPDATA.heap_top+eax] |
shr eax, 12 |
cmp edx, eax |
jae .cant_inplace |
mov eax, [page_tabs+edx*4] |
test al, FREE_BLOCK |
jz .cant_inplace |
shr eax, 12 |
add eax, edx |
sub eax, ebx |
jb .cant_inplace |
jz @f |
shl eax, 12 |
or al, FREE_BLOCK |
mov [page_tabs+ebx*4], eax |
@@: |
mov eax, ebx |
sub eax, ecx |
shl eax, 12 |
or al, USED_BLOCK |
mov [page_tabs+ecx*4], eax |
lea eax, [ecx+1] |
shl eax, 12 |
push eax |
push edi |
lea edi, [page_tabs+edx*4] |
mov eax, 2 |
sub ebx, edx |
mov ecx, ebx |
cld |
rep stosd |
pop edi |
mov edx, [current_slot] |
shl ebx, 12 |
add ebx, [APPDATA.mem_size+edx] |
call update_mem_size |
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] |
shr esi, 12 |
shr edi, 12 |
sub ebx, ecx |
.find_place: |
cmp esi, edi |
jae .place_not_found |
mov eax, [page_tabs+esi*4] |
test al, FREE_BLOCK |
jz .next_place |
shr eax, 12 |
cmp eax, ebx |
jae .place_found |
add esi, eax |
jmp .find_place |
.next_place: |
shr eax, 12 |
add esi, eax |
jmp .find_place |
.place_not_found: |
pop edi esi |
jmp .ret0 |
.place_found: |
sub eax, ebx |
jz @f |
push esi |
add esi, ebx |
shl eax, 12 |
or al, FREE_BLOCK |
mov [page_tabs+esi*4], eax |
pop esi |
@@: |
mov eax, ebx |
shl eax, 12 |
or al, USED_BLOCK |
mov [page_tabs+esi*4], eax |
inc esi |
mov eax, esi |
shl eax, 12 |
push eax |
mov eax, [page_tabs+ecx*4] |
and eax, not 0xFFF |
or al, FREE_BLOCK |
sub edx, ecx |
mov [page_tabs+ecx*4], eax |
inc ecx |
dec ebx |
dec edx |
jz .no |
@@: |
xor eax, eax |
xchg eax, [page_tabs+ecx*4] |
mov [page_tabs+esi*4], eax |
mov eax, ecx |
shl eax, 12 |
invlpg [eax] |
inc esi |
inc ecx |
dec ebx |
dec edx |
jnz @b |
.no: |
push ebx |
mov edx, [current_slot] |
shl ebx, 12 |
add ebx, [APPDATA.mem_size+edx] |
call update_mem_size |
pop ebx |
@@: |
mov dword [page_tabs+esi*4], 2 |
inc esi |
dec ebx |
jnz @b |
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 ;;;;;;;;;;;;;;;;; |
; param |
; eax= shm_map object |
align 4 |
destroy_smap: |
pushfd |
cli |
push esi |
push edi |
mov edi, eax |
mov esi, [eax+SMAP.parent] |
test esi, esi |
jz .done |
lock dec [esi+SMEM.refcount] |
jnz .done |
mov ecx, [esi+SMEM.bk] |
mov edx, [esi+SMEM.fd] |
mov [ecx+SMEM.fd], edx |
mov [edx+SMEM.bk], ecx |
stdcall kernel_free, [esi+SMEM.base] |
mov eax, esi |
call free |
.done: |
mov eax, edi |
call destroy_kernel_object |
pop edi |
pop esi |
popfd |
ret |
E_NOTFOUND equ 5 |
E_ACCESS equ 10 |
E_NOMEM equ 30 |
E_PARAM equ 33 |
SHM_READ equ 0 |
SHM_WRITE equ 1 |
SHM_ACCESS_MASK equ 3 |
SHM_OPEN equ (0 shl 2) |
SHM_OPEN_ALWAYS equ (1 shl 2) |
SHM_CREATE equ (2 shl 2) |
SHM_OPEN_MASK equ (3 shl 2) |
align 4 |
proc shmem_open stdcall name:dword, size:dword, access:dword |
locals |
action dd ? |
owner_access dd ? |
mapped dd ? |
endl |
push ebx |
push esi |
push edi |
mov [mapped], 0 |
mov [owner_access], 0 |
pushfd ;mutex required |
cli |
mov eax, [access] |
and eax, SHM_OPEN_MASK |
mov [action], eax |
mov ebx, [name] |
test ebx, ebx |
mov edx, E_PARAM |
jz .fail |
mov esi, [shmem_list.fd] |
align 4 |
@@: |
cmp esi, shmem_list |
je .not_found |
lea edx, [esi+SMEM.name] ; link , base, size |
stdcall strncmp, edx, ebx, 32 |
test eax, eax |
je .found |
mov esi, [esi+SMEM.fd] |
jmp @B |
.not_found: |
mov eax, [action] |
cmp eax, SHM_OPEN |
mov edx, E_NOTFOUND |
je .fail |
cmp eax, SHM_CREATE |
mov edx, E_PARAM |
je .create_shm |
cmp eax, SHM_OPEN_ALWAYS |
jne .fail |
.create_shm: |
mov ecx, [size] |
test ecx, ecx |
jz .fail |
add ecx, 4095 |
and ecx, -4096 |
mov [size], ecx |
mov eax, SMEM.sizeof |
call malloc |
test eax, eax |
mov esi, eax |
mov edx, E_NOMEM |
jz .fail |
stdcall kernel_alloc, [size] |
test eax, eax |
mov [mapped], eax |
mov edx, E_NOMEM |
jz .cleanup |
mov ecx, [size] |
mov edx, [access] |
and edx, SHM_ACCESS_MASK |
mov [esi+SMEM.base], eax |
mov [esi+SMEM.size], ecx |
mov [esi+SMEM.access], edx |
mov [esi+SMEM.refcount], 0 |
mov [esi+SMEM.name+28], 0 |
lea eax, [esi+SMEM.name] |
stdcall strncpy, eax, [name], 31 |
mov eax, [shmem_list.fd] |
mov [esi+SMEM.bk], shmem_list |
mov [esi+SMEM.fd], eax |
mov [eax+SMEM.bk], esi |
mov [shmem_list.fd], esi |
mov [action], SHM_OPEN |
mov [owner_access], SHM_WRITE |
.found: |
mov eax, [action] |
cmp eax, SHM_CREATE |
mov edx, E_ACCESS |
je .exit |
cmp eax, SHM_OPEN |
mov edx, E_PARAM |
je .create_map |
cmp eax, SHM_OPEN_ALWAYS |
jne .fail |
.create_map: |
mov eax, [access] |
and eax, SHM_ACCESS_MASK |
cmp eax, [esi+SMEM.access] |
mov [access], eax |
mov edx, E_ACCESS |
ja .fail |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov ebx, [CURRENT_TASK+ebx+4] |
mov eax, SMAP.sizeof |
call create_kernel_object |
test eax, eax |
mov edi, eax |
mov edx, E_NOMEM |
jz .fail |
inc [esi+SMEM.refcount] |
mov [edi+SMAP.magic], 'SMAP' |
mov [edi+SMAP.destroy], destroy_smap |
mov [edi+SMAP.parent], esi |
mov [edi+SMAP.base], 0 |
stdcall user_alloc, [esi+SMEM.size] |
test eax, eax |
mov [mapped], eax |
mov edx, E_NOMEM |
jz .cleanup2 |
mov [edi+SMAP.base], eax |
mov ecx, [esi+SMEM.size] |
mov [size], ecx |
shr ecx, 12 |
shr eax, 10 |
mov esi, [esi+SMEM.base] |
shr esi, 10 |
lea edi, [page_tabs+eax] |
add esi, page_tabs |
mov edx, [access] |
or edx, [owner_access] |
shl edx, 1 |
or edx, PG_USER+PG_SHARED |
@@: |
lodsd |
and eax, 0xFFFFF000 |
or eax, edx |
stosd |
loop @B |
xor edx, edx |
cmp [owner_access], 0 |
jne .fail |
.exit: |
mov edx, [size] |
.fail: |
mov eax, [mapped] |
popfd |
pop edi |
pop esi |
pop ebx |
ret |
.cleanup: |
mov [size], edx |
mov eax, esi |
call free |
jmp .exit |
.cleanup2: |
mov [size], edx |
mov eax, edi |
call destroy_smap |
jmp .exit |
endp |
align 4 |
proc shmem_close stdcall, name:dword |
mov eax, [name] |
test eax, eax |
jz .fail |
push esi |
push edi |
pushfd |
cli |
mov esi, [current_slot] |
add esi, APP_OBJ_OFFSET |
.next: |
mov eax, [esi+APPOBJ.fd] |
test eax, eax |
jz @F |
cmp eax, esi |
mov esi, eax |
je @F |
cmp [eax+SMAP.magic], 'SMAP' |
jne .next |
mov edi, [eax+SMAP.parent] |
test edi, edi |
jz .next |
lea edi, [edi+SMEM.name] |
stdcall strncmp, [name], edi, 32 |
test eax, eax |
jne .next |
stdcall user_free, [esi+SMAP.base] |
mov eax,esi |
call [esi+APPOBJ.destroy] |
@@: |
popfd |
pop edi |
pop esi |
.fail: |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
struc MEM_BLOCK |
{ |
.list LHEAD |
.next_block dd ? ;+8 |
.prev_block dd ? ;+4 |
.base dd ? ;+16 |
.size dd ? ;+20 |
.flags dd ? ;+24 |
.handle dd ? ;+28 |
.sizeof: |
} |
FREE_BLOCK equ 4 |
USED_BLOCK equ 8 |
DONT_FREE_BLOCK equ 10h |
virtual at 0 |
MEM_BLOCK MEM_BLOCK |
end virtual |
block_next equ MEM_BLOCK.next_block |
block_prev equ MEM_BLOCK.prev_block |
list_fd equ MEM_BLOCK.list.next |
list_bk equ MEM_BLOCK.list.prev |
block_base equ MEM_BLOCK.base |
block_size equ MEM_BLOCK.size |
block_flags equ MEM_BLOCK.flags |
macro calc_index op |
{ shr op, 12 |
dec op |
cmp op, 63 |
jna @f |
mov op, 63 |
@@: |
} |
align 4 |
md: |
.add_to_used: |
mov eax, [esi+block_base] |
mov ebx, [esi+block_base] |
shr ebx, 6 |
add eax, ebx |
shr ebx, 6 |
add eax, ebx |
shr eax, 12 |
and eax, 63 |
inc [mem_hash_cnt+eax*4] |
lea ecx, [mem_used_list+eax*8] |
list_add esi, ecx |
mov [esi+block_flags], USED_BLOCK |
mov eax, [esi+block_size] |
sub [heap_free], eax |
ret |
align 4 |
.find_used: |
mov ecx, eax |
mov ebx, eax |
shr ebx, 6 |
add ecx, ebx |
shr ebx, 6 |
add ecx, ebx |
shr ecx, 12 |
and ecx, 63 |
lea ebx, [mem_used_list+ecx*8] |
mov esi, ebx |
.next: |
mov esi, [esi+list_fd] |
cmp esi, ebx |
je .fail |
cmp eax, [esi+block_base] |
jne .next |
ret |
.fail: |
xor esi, esi |
ret |
align 4 |
.del_from_used: |
call .find_used |
test esi, esi |
jz .done |
cmp [esi+block_flags], USED_BLOCK |
jne .fatal |
dec [mem_hash_cnt+ecx*4] |
list_del esi |
.done: |
ret |
.fatal: ;FIXME panic here |
xor esi, esi |
ret |
;Initial heap state |
; |
;+heap_size terminator USED_BLOCK |
;+4096*MEM_BLOCK.sizeof free space FREE_BLOCK |
;HEAP_BASE heap_descriptors USED_BLOCK |
; |
align 4 |
proc init_kernel_heap |
mov ecx, 64 |
mov edi, mem_block_list |
@@: |
mov eax, edi |
stosd |
stosd |
loop @B |
mov ecx, 64 |
mov edi, mem_used_list |
@@: |
mov eax, edi |
stosd |
stosd |
loop @B |
stdcall alloc_pages, dword 32 |
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 |
mov edi, HEAP_BASE ;descriptors |
mov ebx, HEAP_BASE+MEM_BLOCK.sizeof ;free space |
mov ecx, HEAP_BASE+MEM_BLOCK.sizeof*2 ;terminator |
xor eax, eax |
mov [edi+block_next], ebx |
mov [edi+block_prev], eax |
mov [edi+list_fd], eax |
mov [edi+list_bk], eax |
mov [edi+block_base], HEAP_BASE |
mov [edi+block_size], 4096*MEM_BLOCK.sizeof |
mov [edi+block_flags], USED_BLOCK |
mov [ecx+block_next], eax |
mov [ecx+block_prev], ebx |
mov [edi+list_fd], eax |
mov [edi+list_bk], eax |
mov [edi+block_base], eax |
mov [edi+block_size], eax |
mov [edi+block_flags], USED_BLOCK |
mov [ebx+block_next], ecx |
mov [ebx+block_prev], edi |
mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK.sizeof |
mov ecx, [pg_data.kernel_pages] |
shl ecx, 12 |
sub ecx, HEAP_BASE-OS_BASE+4096*MEM_BLOCK.sizeof |
mov [heap_size], ecx |
mov [heap_free], ecx |
mov [ebx+block_size], ecx |
mov [ebx+block_flags], FREE_BLOCK |
mov [mem_block_mask], eax |
mov [mem_block_mask+4], 0x80000000 |
mov ecx, mem_block_list+63*8 |
list_add ebx, ecx |
mov ecx, 4096-3-1 |
mov eax, HEAP_BASE+MEM_BLOCK.sizeof*4 |
mov [next_memblock], HEAP_BASE+MEM_BLOCK.sizeof*3 |
@@: |
mov [eax-MEM_BLOCK.sizeof], eax |
add eax, MEM_BLOCK.sizeof |
loop @B |
mov [eax-MEM_BLOCK.sizeof], dword 0 |
mov ecx, heap_mutex |
call mutex_init |
mov [heap_blocks], 4094 |
mov [free_blocks], 4093 |
ret |
endp |
; param |
; eax= required size |
; |
; retval |
; edi= memory block descriptor |
; ebx= descriptor index |
align 4 |
get_small_block: |
mov ecx, eax |
shr ecx, 12 |
dec ecx |
cmp ecx, 63 |
jle .get_index |
mov ecx, 63 |
.get_index: |
lea esi, [mem_block_mask] |
xor ebx, ebx |
or edx, -1 |
cmp ecx, 32 |
jb .bit_test |
sub ecx, 32 |
add ebx, 32 |
add esi, 4 |
.bit_test: |
shl edx, cl |
and edx, [esi] |
.find: |
bsf edi, edx |
jz .high_mask |
add ebx, edi |
lea ecx, [mem_block_list+ebx*8] |
mov edi, ecx |
.next: |
mov edi, [edi+list_fd] |
cmp edi, ecx |
je .err |
cmp eax, [edi+block_size] |
ja .next |
ret |
.err: |
xor edi, edi |
ret |
.high_mask: |
add esi, 4 |
cmp esi, mem_block_mask+8 |
jae .err |
add ebx, 32 |
mov edx, [esi] |
jmp .find |
align 4 |
free_mem_block: |
mov ebx, [next_memblock] |
mov [eax], ebx |
mov [next_memblock], eax |
xor ebx, ebx |
mov dword [eax+4], ebx |
mov dword [eax+8], ebx |
mov dword [eax+12], ebx |
mov dword [eax+16], ebx |
; mov dword [eax+20], 0 ;don't clear block size |
mov dword [eax+24], ebx |
mov dword [eax+28], ebx |
inc [free_blocks] |
ret |
align 4 |
proc alloc_kernel_space stdcall, size:dword |
local block_ind:DWORD |
push ebx |
push esi |
push edi |
mov eax, [size] |
add eax, 4095 |
and eax, not 4095 |
mov [size], eax |
cmp eax, [heap_free] |
ja .error |
mov ecx, heap_mutex |
call mutex_lock |
mov eax, [size] |
call get_small_block ; eax |
test edi, edi |
jz .error_unlock |
cmp [edi+block_flags], FREE_BLOCK |
jne .error_unlock |
mov [block_ind], ebx ;index of allocated block |
mov eax, [edi+block_size] |
cmp eax, [size] |
je .m_eq_size |
mov esi, [next_memblock] ;new memory block |
test esi, esi |
jz .error_unlock |
dec [free_blocks] |
mov eax, [esi] |
mov [next_memblock], eax |
mov [esi+block_next], edi |
mov eax, [edi+block_prev] |
mov [esi+block_prev], eax |
mov [edi+block_prev], esi |
mov [esi+list_fd], 0 |
mov [esi+list_bk], 0 |
mov [eax+block_next], esi |
mov ebx, [edi+block_base] |
mov [esi+block_base], ebx |
mov edx, [size] |
mov [esi+block_size], edx |
add [edi+block_base], edx |
sub [edi+block_size], edx |
mov eax, [edi+block_size] |
calc_index eax |
cmp eax, [block_ind] |
je .add_used |
list_del edi |
mov ecx, [block_ind] |
lea edx, [mem_block_list+ecx*8] |
cmp edx, [edx] |
jnz @f |
btr [mem_block_mask], ecx |
@@: |
bts [mem_block_mask], eax |
lea edx, [mem_block_list+eax*8] ;edx= list head |
list_add edi, edx |
.add_used: |
call md.add_to_used |
mov ecx, heap_mutex |
call mutex_unlock |
mov eax, [esi+block_base] |
pop edi |
pop esi |
pop ebx |
ret |
.m_eq_size: |
list_del edi |
lea edx, [mem_block_list+ebx*8] |
cmp edx, [edx] |
jnz @f |
btr [mem_block_mask], ebx |
@@: |
mov esi, edi |
jmp .add_used |
.error_unlock: |
mov ecx, heap_mutex |
call mutex_unlock |
.error: |
xor eax, eax |
pop edi |
pop esi |
pop ebx |
ret |
endp |
align 4 |
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword |
mov ecx, heap_mutex |
call mutex_lock |
mov eax, [base] |
call md.del_from_used |
test esi, esi |
jz .fail |
mov eax, [esi+block_size] |
add [heap_free], eax |
mov edi, [esi+block_next] |
cmp [edi+block_flags], FREE_BLOCK |
jne .prev |
list_del edi |
mov edx, [edi+block_next] |
mov [esi+block_next], edx |
mov [edx+block_prev], esi |
mov ecx, [edi+block_size] |
add [esi+block_size], ecx |
calc_index ecx |
lea edx, [mem_block_list+ecx*8] |
cmp edx, [edx] |
jne @F |
btr [mem_block_mask], ecx |
@@: |
mov eax, edi |
call free_mem_block |
.prev: |
mov edi, [esi+block_prev] |
cmp [edi+block_flags], FREE_BLOCK |
jne .insert |
mov edx, [esi+block_next] |
mov [edi+block_next], edx |
mov [edx+block_prev], edi |
mov eax, esi |
call free_mem_block |
mov ecx, [edi+block_size] |
mov eax, [esi+block_size] |
add eax, ecx |
mov [edi+block_size], eax |
calc_index eax ;new index |
calc_index ecx ;old index |
cmp eax, ecx |
je .m_eq |
push ecx |
list_del edi |
pop ecx |
lea edx, [mem_block_list+ecx*8] |
cmp edx, [edx] |
jne .add_block |
btr [mem_block_mask], ecx |
.add_block: |
bts [mem_block_mask], eax |
lea edx, [mem_block_list+eax*8] |
list_add edi, edx |
.m_eq: |
mov ecx, heap_mutex |
call mutex_unlock |
xor eax, eax |
not eax |
ret |
.insert: |
mov [esi+block_flags], FREE_BLOCK |
mov eax, [esi+block_size] |
calc_index eax |
mov edi, esi |
jmp .add_block |
.fail: |
mov ecx, heap_mutex |
call mutex_unlock |
xor eax, eax |
ret |
endp |
align 4 |
proc kernel_alloc stdcall, size:dword |
locals |
lin_addr dd ? |
pages_count dd ? |
endl |
push ebx |
push edi |
mov eax, [size] |
add eax, 4095 |
and eax, not 4095; |
mov [size], eax |
and eax, eax |
jz .err |
mov ebx, eax |
shr ebx, 12 |
mov [pages_count], ebx |
stdcall alloc_kernel_space, eax |
test eax, eax |
jz .err |
mov [lin_addr], eax |
mov ecx, [pages_count] |
mov edx, eax |
mov ebx, ecx |
shr ecx, 3 |
jz .next |
and ebx, not 7 |
push ebx |
stdcall alloc_pages, ebx |
pop ecx ; yes ecx!!! |
and 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 |
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 |
jnz @B |
.end: |
mov eax, [lin_addr] |
pop edi |
pop ebx |
ret |
.err: |
xor eax, eax |
pop edi |
pop ebx |
ret |
endp |
align 4 |
proc kernel_free stdcall, base:dword |
push ebx esi |
mov ecx, heap_mutex |
call mutex_lock |
mov eax, [base] |
call md.find_used |
mov ecx, heap_mutex |
cmp [esi+block_flags], USED_BLOCK |
jne .fail |
call mutex_unlock |
mov eax, [esi+block_base] |
mov ecx, [esi+block_size] |
shr ecx, 12 |
call release_pages ;eax, ecx |
stdcall free_kernel_space, [base] |
pop esi ebx |
ret |
.fail: |
call mutex_unlock |
xor eax, eax |
pop esi ebx |
ret |
endp |
restore block_next |
restore block_prev |
restore block_list |
restore block_base |
restore block_size |
restore block_flags |
;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;; |
HEAP_TOP equ 0x5FC00000 |
align 4 |
proc init_heap |
mov ebx, [current_slot] |
mov eax, [ebx+APPDATA.heap_top] |
test eax, eax |
jz @F |
sub eax, [ebx+APPDATA.heap_base] |
sub eax, 4096 |
ret |
@@: |
mov esi, [ebx+APPDATA.mem_size] |
add esi, 4095 |
and esi, not 4095 |
mov [ebx+APPDATA.mem_size], esi |
mov eax, HEAP_TOP |
mov [ebx+APPDATA.heap_base], esi |
mov [ebx+APPDATA.heap_top], eax |
sub eax, esi |
shr esi, 10 |
mov ecx, eax |
sub eax, 4096 |
or ecx, FREE_BLOCK |
mov [page_tabs+esi], ecx |
ret |
endp |
align 4 |
proc user_alloc stdcall, alloc_size:dword |
push ebx |
push esi |
push edi |
mov ecx, [alloc_size] |
add ecx, (4095+4096) |
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: |
cmp esi, edi |
jae m_exit |
mov ebx, esi |
shr ebx, 12 |
mov eax, [page_tabs+ebx*4] |
test al, FREE_BLOCK |
jz test_used |
and eax, 0xFFFFF000 |
cmp eax, ecx ;alloc_size |
jb m_next |
jz @f |
lea edx, [esi+ecx] |
sub eax, ecx |
or al, FREE_BLOCK |
shr edx, 12 |
mov [page_tabs+edx*4], eax |
@@: |
or ecx, USED_BLOCK |
mov [page_tabs+ebx*4], ecx |
shr ecx, 12 |
inc ebx |
dec ecx |
jz .no |
@@: |
mov dword [page_tabs+ebx*4], 2 |
inc ebx |
dec ecx |
jnz @B |
.no: |
mov edx, [current_slot] |
mov ebx, [alloc_size] |
add ebx, 0xFFF |
and ebx, not 0xFFF |
add ebx, [edx+APPDATA.mem_size] |
call update_mem_size |
lea eax, [esi+4096] |
pop edi |
pop esi |
pop ebx |
ret |
test_used: |
test al, USED_BLOCK |
jz m_exit |
and eax, 0xFFFFF000 |
m_next: |
add esi, eax |
jmp l_0 |
m_exit: |
xor eax, eax |
pop edi |
pop esi |
pop ebx |
ret |
endp |
align 4 |
proc user_alloc_at stdcall, address:dword, alloc_size:dword |
push ebx |
push esi |
push edi |
mov ebx, [current_slot] |
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] |
cmp edx, esi |
jb .error |
.scan: |
cmp esi, edi |
jae .error |
mov ebx, esi |
shr ebx, 12 |
mov eax, [page_tabs+ebx*4] |
mov ecx, eax |
and ecx, 0xFFFFF000 |
add ecx, esi |
cmp edx, ecx |
jb .found |
mov esi, ecx |
jmp .scan |
.error: |
xor eax, eax |
pop edi |
pop esi |
pop ebx |
ret |
.found: |
test al, FREE_BLOCK |
jz .error |
mov eax, ecx |
sub eax, edx |
sub eax, 0x1000 |
cmp eax, [alloc_size] |
jb .error |
; Here we have 1 big free block which includes requested area. |
; In general, 3 other blocks must be created instead: |
; free at [esi, edx); |
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000)); |
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx) |
; First or third block (or both) may be absent. |
mov eax, edx |
sub eax, esi |
jz .nofirst |
or al, FREE_BLOCK |
mov [page_tabs+ebx*4], eax |
.nofirst: |
mov eax, [alloc_size] |
add eax, 0x1FFF |
and eax, not 0xFFF |
mov ebx, edx |
add edx, eax |
shr ebx, 12 |
or al, USED_BLOCK |
mov [page_tabs+ebx*4], eax |
shr eax, 12 |
dec eax |
jz .second_nofill |
inc ebx |
.fill: |
mov dword [page_tabs+ebx*4], 2 |
inc ebx |
dec eax |
jnz .fill |
.second_nofill: |
sub ecx, edx |
jz .nothird |
or cl, FREE_BLOCK |
mov [page_tabs+ebx*4], ecx |
.nothird: |
mov edx, [current_slot] |
mov ebx, [alloc_size] |
add ebx, 0xFFF |
and ebx, not 0xFFF |
add ebx, [edx+APPDATA.mem_size] |
call update_mem_size |
mov eax, [address] |
pop edi |
pop esi |
pop ebx |
ret |
endp |
align 4 |
proc user_free stdcall, base:dword |
push esi |
mov esi, [base] |
test esi, esi |
jz .exit |
push ebx |
xor ebx, ebx |
shr esi, 12 |
mov eax, [page_tabs+(esi-1)*4] |
test al, USED_BLOCK |
jz .cantfree |
test al, DONT_FREE_BLOCK |
jnz .cantfree |
and eax, not 4095 |
mov ecx, eax |
or al, FREE_BLOCK |
mov [page_tabs+(esi-1)*4], eax |
sub ecx, 4096 |
mov ebx, ecx |
shr ecx, 12 |
jz .released |
.release: |
xor eax, eax |
xchg eax, [page_tabs+esi*4] |
test al, 1 |
jz @F |
test eax, PG_SHARED |
jnz @F |
call free_page |
mov eax, esi |
shl eax, 12 |
invlpg [eax] |
@@: |
inc esi |
dec ecx |
jnz .release |
.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] |
neg ebx |
call update_mem_size |
call user_normalize |
pop edi |
pop ebx |
pop esi |
ret |
.exit: |
xor eax, eax |
inc eax |
pop esi |
ret |
.cantfree: |
xor eax, eax |
pop ebx |
pop esi |
ret |
endp |
user_normalize: |
; in: esi=heap_base, edi=heap_top |
; out: eax=0 <=> OK |
; destroys: ebx,edx,esi,edi |
shr esi, 12 |
shr edi, 12 |
@@: |
mov eax, [page_tabs+esi*4] |
test al, USED_BLOCK |
jz .test_free |
shr eax, 12 |
add esi, eax |
jmp @B |
.test_free: |
test al, FREE_BLOCK |
jz .err |
mov edx, eax |
shr edx, 12 |
add edx, esi |
cmp edx, edi |
jae .exit |
mov ebx, [page_tabs+edx*4] |
test bl, USED_BLOCK |
jz .next_free |
shr ebx, 12 |
add edx, ebx |
mov esi, edx |
jmp @B |
.next_free: |
test bl, FREE_BLOCK |
jz .err |
and dword [page_tabs+edx*4], 0 |
add eax, ebx |
and eax, not 4095 |
or eax, FREE_BLOCK |
mov [page_tabs+esi*4], eax |
jmp @B |
.exit: |
xor eax, eax |
inc eax |
ret |
.err: |
xor eax, eax |
ret |
user_realloc: |
; in: eax = pointer, ebx = new size |
; out: eax = new pointer or NULL |
test eax, eax |
jnz @f |
; realloc(NULL,sz) - same as malloc(sz) |
push ebx |
call user_alloc |
ret |
@@: |
push ecx edx |
lea ecx, [eax - 0x1000] |
shr ecx, 12 |
mov edx, [page_tabs+ecx*4] |
test dl, USED_BLOCK |
jnz @f |
; attempt to realloc invalid pointer |
.ret0: |
pop edx ecx |
xor eax, eax |
ret |
@@: |
test dl, DONT_FREE_BLOCK |
jnz .ret0 |
add ebx, 0x1FFF |
shr edx, 12 |
shr ebx, 12 |
; edx = allocated size, ebx = new size |
add edx, ecx |
add ebx, ecx |
cmp edx, ebx |
jb .realloc_add |
; release part of allocated memory |
.loop: |
cmp edx, ebx |
jz .release_done |
dec edx |
xor eax, eax |
xchg eax, [page_tabs+edx*4] |
test al, 1 |
jz .loop |
call free_page |
mov eax, edx |
shl eax, 12 |
invlpg [eax] |
jmp .loop |
.release_done: |
sub ebx, ecx |
cmp ebx, 1 |
jnz .nofreeall |
mov eax, [page_tabs+ecx*4] |
and eax, not 0xFFF |
mov edx, [current_slot] |
mov ebx, [APPDATA.mem_size+edx] |
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 |
call user_normalize |
pop edi esi |
jmp .ret0 ; all freed |
.nofreeall: |
sub edx, ecx |
shl ebx, 12 |
or ebx, USED_BLOCK |
xchg [page_tabs+ecx*4], ebx |
shr ebx, 12 |
sub ebx, edx |
push ebx ecx edx |
mov edx, [current_slot] |
shl ebx, 12 |
sub ebx, [APPDATA.mem_size+edx] |
neg ebx |
call update_mem_size |
pop edx ecx ebx |
lea eax, [ecx+1] |
shl eax, 12 |
push eax |
add ecx, edx |
lea edx, [ecx+ebx] |
shl ebx, 12 |
jz .ret |
push esi |
mov esi, [current_slot] |
mov esi, [APPDATA.heap_top+esi] |
shr esi, 12 |
@@: |
cmp edx, esi |
jae .merge_done |
mov eax, [page_tabs+edx*4] |
test al, USED_BLOCK |
jnz .merge_done |
and dword [page_tabs+edx*4], 0 |
shr eax, 12 |
add edx, eax |
shl eax, 12 |
add ebx, eax |
jmp @b |
.merge_done: |
pop esi |
or ebx, FREE_BLOCK |
mov [page_tabs+ecx*4], ebx |
.ret: |
pop eax edx ecx |
ret |
.realloc_add: |
; get some additional memory |
mov eax, [current_slot] |
mov eax, [APPDATA.heap_top+eax] |
shr eax, 12 |
cmp edx, eax |
jae .cant_inplace |
mov eax, [page_tabs+edx*4] |
test al, FREE_BLOCK |
jz .cant_inplace |
shr eax, 12 |
add eax, edx |
sub eax, ebx |
jb .cant_inplace |
jz @f |
shl eax, 12 |
or al, FREE_BLOCK |
mov [page_tabs+ebx*4], eax |
@@: |
mov eax, ebx |
sub eax, ecx |
shl eax, 12 |
or al, USED_BLOCK |
mov [page_tabs+ecx*4], eax |
lea eax, [ecx+1] |
shl eax, 12 |
push eax |
push edi |
lea edi, [page_tabs+edx*4] |
mov eax, 2 |
sub ebx, edx |
mov ecx, ebx |
cld |
rep stosd |
pop edi |
mov edx, [current_slot] |
shl ebx, 12 |
add ebx, [APPDATA.mem_size+edx] |
call update_mem_size |
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] |
shr esi, 12 |
shr edi, 12 |
sub ebx, ecx |
.find_place: |
cmp esi, edi |
jae .place_not_found |
mov eax, [page_tabs+esi*4] |
test al, FREE_BLOCK |
jz .next_place |
shr eax, 12 |
cmp eax, ebx |
jae .place_found |
add esi, eax |
jmp .find_place |
.next_place: |
shr eax, 12 |
add esi, eax |
jmp .find_place |
.place_not_found: |
pop edi esi |
jmp .ret0 |
.place_found: |
sub eax, ebx |
jz @f |
push esi |
add esi, ebx |
shl eax, 12 |
or al, FREE_BLOCK |
mov [page_tabs+esi*4], eax |
pop esi |
@@: |
mov eax, ebx |
shl eax, 12 |
or al, USED_BLOCK |
mov [page_tabs+esi*4], eax |
inc esi |
mov eax, esi |
shl eax, 12 |
push eax |
mov eax, [page_tabs+ecx*4] |
and eax, not 0xFFF |
or al, FREE_BLOCK |
sub edx, ecx |
mov [page_tabs+ecx*4], eax |
inc ecx |
dec ebx |
dec edx |
jz .no |
@@: |
xor eax, eax |
xchg eax, [page_tabs+ecx*4] |
mov [page_tabs+esi*4], eax |
mov eax, ecx |
shl eax, 12 |
invlpg [eax] |
inc esi |
inc ecx |
dec ebx |
dec edx |
jnz @b |
.no: |
push ebx |
mov edx, [current_slot] |
shl ebx, 12 |
add ebx, [APPDATA.mem_size+edx] |
call update_mem_size |
pop ebx |
@@: |
mov dword [page_tabs+esi*4], 2 |
inc esi |
dec ebx |
jnz @b |
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 ;;;;;;;;;;;;;;;;; |
; param |
; eax= shm_map object |
align 4 |
destroy_smap: |
pushfd |
cli |
push esi |
push edi |
mov edi, eax |
mov esi, [eax+SMAP.parent] |
test esi, esi |
jz .done |
lock dec [esi+SMEM.refcount] |
jnz .done |
mov ecx, [esi+SMEM.bk] |
mov edx, [esi+SMEM.fd] |
mov [ecx+SMEM.fd], edx |
mov [edx+SMEM.bk], ecx |
stdcall kernel_free, [esi+SMEM.base] |
mov eax, esi |
call free |
.done: |
mov eax, edi |
call destroy_kernel_object |
pop edi |
pop esi |
popfd |
ret |
E_NOTFOUND equ 5 |
E_ACCESS equ 10 |
E_NOMEM equ 30 |
E_PARAM equ 33 |
SHM_READ equ 0 |
SHM_WRITE equ 1 |
SHM_ACCESS_MASK equ 3 |
SHM_OPEN equ (0 shl 2) |
SHM_OPEN_ALWAYS equ (1 shl 2) |
SHM_CREATE equ (2 shl 2) |
SHM_OPEN_MASK equ (3 shl 2) |
align 4 |
proc shmem_open stdcall name:dword, size:dword, access:dword |
locals |
action dd ? |
owner_access dd ? |
mapped dd ? |
endl |
push ebx |
push esi |
push edi |
mov [mapped], 0 |
mov [owner_access], 0 |
pushfd ;mutex required |
cli |
mov eax, [access] |
and eax, SHM_OPEN_MASK |
mov [action], eax |
mov ebx, [name] |
test ebx, ebx |
mov edx, E_PARAM |
jz .fail |
mov esi, [shmem_list.fd] |
align 4 |
@@: |
cmp esi, shmem_list |
je .not_found |
lea edx, [esi+SMEM.name]; link , base, size |
stdcall strncmp, edx, ebx, 32 |
test eax, eax |
je .found |
mov esi, [esi+SMEM.fd] |
jmp @B |
.not_found: |
mov eax, [action] |
cmp eax, SHM_OPEN |
mov edx, E_NOTFOUND |
je .fail |
cmp eax, SHM_CREATE |
mov edx, E_PARAM |
je .create_shm |
cmp eax, SHM_OPEN_ALWAYS |
jne .fail |
.create_shm: |
mov ecx, [size] |
test ecx, ecx |
jz .fail |
add ecx, 4095 |
and ecx, -4096 |
mov [size], ecx |
mov eax, SMEM.sizeof |
call malloc |
test eax, eax |
mov esi, eax |
mov edx, E_NOMEM |
jz .fail |
stdcall kernel_alloc, [size] |
test eax, eax |
mov [mapped], eax |
mov edx, E_NOMEM |
jz .cleanup |
mov ecx, [size] |
mov edx, [access] |
and edx, SHM_ACCESS_MASK |
mov [esi+SMEM.base], eax |
mov [esi+SMEM.size], ecx |
mov [esi+SMEM.access], edx |
mov [esi+SMEM.refcount], 0 |
mov [esi+SMEM.name+28], 0 |
lea eax, [esi+SMEM.name] |
stdcall strncpy, eax, [name], 31 |
mov eax, [shmem_list.fd] |
mov [esi+SMEM.bk], shmem_list |
mov [esi+SMEM.fd], eax |
mov [eax+SMEM.bk], esi |
mov [shmem_list.fd], esi |
mov [action], SHM_OPEN |
mov [owner_access], SHM_WRITE |
.found: |
mov eax, [action] |
cmp eax, SHM_CREATE |
mov edx, E_ACCESS |
je .exit |
cmp eax, SHM_OPEN |
mov edx, E_PARAM |
je .create_map |
cmp eax, SHM_OPEN_ALWAYS |
jne .fail |
.create_map: |
mov eax, [access] |
and eax, SHM_ACCESS_MASK |
cmp eax, [esi+SMEM.access] |
mov [access], eax |
mov edx, E_ACCESS |
ja .fail |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov ebx, [CURRENT_TASK+ebx+4] |
mov eax, SMAP.sizeof |
call create_kernel_object |
test eax, eax |
mov edi, eax |
mov edx, E_NOMEM |
jz .fail |
inc [esi+SMEM.refcount] |
mov [edi+SMAP.magic], 'SMAP' |
mov [edi+SMAP.destroy], destroy_smap |
mov [edi+SMAP.parent], esi |
mov [edi+SMAP.base], 0 |
stdcall user_alloc, [esi+SMEM.size] |
test eax, eax |
mov [mapped], eax |
mov edx, E_NOMEM |
jz .cleanup2 |
mov [edi+SMAP.base], eax |
mov ecx, [esi+SMEM.size] |
mov [size], ecx |
shr ecx, 12 |
shr eax, 10 |
mov esi, [esi+SMEM.base] |
shr esi, 10 |
lea edi, [page_tabs+eax] |
add esi, page_tabs |
mov edx, [access] |
or edx, [owner_access] |
shl edx, 1 |
or edx, PG_USER+PG_SHARED |
@@: |
lodsd |
and eax, 0xFFFFF000 |
or eax, edx |
stosd |
loop @B |
xor edx, edx |
cmp [owner_access], 0 |
jne .fail |
.exit: |
mov edx, [size] |
.fail: |
mov eax, [mapped] |
popfd |
pop edi |
pop esi |
pop ebx |
ret |
.cleanup: |
mov [size], edx |
mov eax, esi |
call free |
jmp .exit |
.cleanup2: |
mov [size], edx |
mov eax, edi |
call destroy_smap |
jmp .exit |
endp |
align 4 |
proc shmem_close stdcall, name:dword |
mov eax, [name] |
test eax, eax |
jz .fail |
push esi |
push edi |
pushfd |
cli |
mov esi, [current_slot] |
add esi, APP_OBJ_OFFSET |
.next: |
mov eax, [esi+APPOBJ.fd] |
test eax, eax |
jz @F |
cmp eax, esi |
mov esi, eax |
je @F |
cmp [eax+SMAP.magic], 'SMAP' |
jne .next |
mov edi, [eax+SMAP.parent] |
test edi, edi |
jz .next |
lea edi, [edi+SMEM.name] |
stdcall strncmp, [name], edi, 32 |
test eax, eax |
jne .next |
stdcall user_free, [esi+SMAP.base] |
mov eax, esi |
call [esi+APPOBJ.destroy] |
@@: |
popfd |
pop edi |
pop esi |
.fail: |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/irq.inc |
---|
1,229 → 1,229 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
IRQ_RESERVED equ 24 |
IRQ_POOL_SIZE equ 48 |
uglobal |
align 16 |
irqh_tab rd LHEAD.sizeof * IRQ_RESERVED / 4 |
irqh_pool rd IRQH.sizeof * IRQ_POOL_SIZE /4 |
next_irqh rd 1 |
irq_active_set rd 1 |
irq_failed rd IRQ_RESERVED |
endg |
align 4 |
init_irqs: |
mov ecx, IRQ_RESERVED |
mov edi, irqh_tab |
@@: |
mov eax, edi |
stosd |
stosd |
loop @B |
mov ecx, IRQ_POOL_SIZE-1 |
mov eax, irqh_pool+IRQH.sizeof |
mov [next_irqh], irqh_pool |
@@: |
mov [eax-IRQH.sizeof], eax |
add eax, IRQH.sizeof |
loop @B |
mov [eax-IRQH.sizeof], dword 0 |
ret |
align 4 |
proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword |
locals |
.irqh dd ? |
endl |
and [.irqh], 0 |
push ebx |
mov ebx, [irq] ;irq num |
test ebx, ebx |
jz .err |
cmp ebx, IRQ_RESERVED |
jae .err |
mov edx, [handler] |
test edx, edx |
jz .err |
pushfd |
cli |
;allocate handler |
mov ecx, [next_irqh] |
test ecx, ecx |
jz .fail |
mov eax, [ecx] |
mov [next_irqh], eax |
mov [.irqh], ecx |
mov [irq_failed+ebx*4], 0 ;clear counter |
mov eax, [user_data] |
mov [ecx+IRQH.handler], edx |
mov [ecx+IRQH.data], eax |
lea edx, [irqh_tab+ebx*8] |
list_add_tail ecx, edx ;clobber eax |
stdcall enable_irq, ebx |
.fail: |
popfd |
.err: |
pop ebx |
mov eax, [.irqh] |
ret |
endp |
if 0 |
align 4 |
proc get_int_handler stdcall, irq:dword |
mov eax, [irq] |
cmp eax, 15 |
ja .fail |
mov eax, [irq_tab + 4 * eax] |
ret |
.fail: |
xor eax, eax |
ret |
endp |
end if |
align 4 |
proc detach_int_handler |
ret |
endp |
macro irq_serv_h [num] { |
forward |
align 4 |
.irq_#num : |
push num |
jmp .main |
} |
align 16 |
irq_serv: |
; .irq_1: |
; push 1 |
; jmp .main |
; etc... |
irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15 |
irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23 |
purge irq_serv_h |
align 16 |
.main: |
save_ring3_context |
mov ebp, [esp + 32] |
mov bx, app_data ;os_data |
mov ds, bx |
mov es, bx |
cmp [v86_irqhooks+ebp*8], 0 |
jnz v86_irq |
cmp bp, 6 |
jnz @f |
push ebp |
call [fdc_irq_func] |
pop ebp |
@@: |
cmp bp, 14 |
jnz @f |
push ebp |
call [irq14_func] |
pop ebp |
@@: |
cmp bp, 15 |
jnz @f |
push ebp |
call [irq15_func] |
pop ebp |
@@: |
bts [irq_active_set], ebp |
lea esi, [irqh_tab+ebp*8] ; esi= list head |
mov ebx, esi |
.next: |
mov ebx, [ebx+IRQH.list.next] ; ebx= irqh pointer |
cmp ebx, esi |
je .done |
push ebx ; FIX THIS |
push edi |
push esi |
push [ebx+IRQH.data] |
call [ebx+IRQH.handler] |
add esp, 4 |
pop esi |
pop edi |
pop ebx |
test eax, eax |
jz .next |
btr [irq_active_set], ebp |
jmp .next |
.done: |
btr [irq_active_set], ebp |
jnc .exit |
inc [irq_failed+ebp*4] |
.exit: |
mov [check_idle_semaphore],5 |
mov ecx, ebp |
call irq_eoi |
restore_ring3_context |
add esp, 4 |
iret |
align 4 |
irqD: |
push eax |
push ecx |
xor eax,eax |
out 0xf0,al |
mov cl, 13 |
call irq_eoi |
pop ecx |
pop eax |
iret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
IRQ_RESERVED equ 24 |
IRQ_POOL_SIZE equ 48 |
uglobal |
align 16 |
irqh_tab rd LHEAD.sizeof * IRQ_RESERVED / 4 |
irqh_pool rd IRQH.sizeof * IRQ_POOL_SIZE /4 |
next_irqh rd 1 |
irq_active_set rd 1 |
irq_failed rd IRQ_RESERVED |
endg |
align 4 |
init_irqs: |
mov ecx, IRQ_RESERVED |
mov edi, irqh_tab |
@@: |
mov eax, edi |
stosd |
stosd |
loop @B |
mov ecx, IRQ_POOL_SIZE-1 |
mov eax, irqh_pool+IRQH.sizeof |
mov [next_irqh], irqh_pool |
@@: |
mov [eax-IRQH.sizeof], eax |
add eax, IRQH.sizeof |
loop @B |
mov [eax-IRQH.sizeof], dword 0 |
ret |
align 4 |
proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword |
locals |
.irqh dd ? |
endl |
and [.irqh], 0 |
push ebx |
mov ebx, [irq] ;irq num |
test ebx, ebx |
jz .err |
cmp ebx, IRQ_RESERVED |
jae .err |
mov edx, [handler] |
test edx, edx |
jz .err |
pushfd |
cli |
;allocate handler |
mov ecx, [next_irqh] |
test ecx, ecx |
jz .fail |
mov eax, [ecx] |
mov [next_irqh], eax |
mov [.irqh], ecx |
mov [irq_failed+ebx*4], 0;clear counter |
mov eax, [user_data] |
mov [ecx+IRQH.handler], edx |
mov [ecx+IRQH.data], eax |
lea edx, [irqh_tab+ebx*8] |
list_add_tail ecx, edx ;clobber eax |
stdcall enable_irq, ebx |
.fail: |
popfd |
.err: |
pop ebx |
mov eax, [.irqh] |
ret |
endp |
if 0 |
align 4 |
proc get_int_handler stdcall, irq:dword |
mov eax, [irq] |
cmp eax, 15 |
ja .fail |
mov eax, [irq_tab + 4 * eax] |
ret |
.fail: |
xor eax, eax |
ret |
endp |
end if |
align 4 |
proc detach_int_handler |
ret |
endp |
macro irq_serv_h [num] { |
forward |
align 4 |
.irq_#num : |
push num |
jmp .main |
} |
align 16 |
irq_serv: |
; .irq_1: |
; push 1 |
; jmp .main |
; etc... |
irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15 |
irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23 |
purge irq_serv_h |
align 16 |
.main: |
save_ring3_context |
mov ebp, [esp + 32] |
mov bx, app_data;os_data |
mov ds, bx |
mov es, bx |
cmp [v86_irqhooks+ebp*8], 0 |
jnz v86_irq |
cmp bp, 6 |
jnz @f |
push ebp |
call [fdc_irq_func] |
pop ebp |
@@: |
cmp bp, 14 |
jnz @f |
push ebp |
call [irq14_func] |
pop ebp |
@@: |
cmp bp, 15 |
jnz @f |
push ebp |
call [irq15_func] |
pop ebp |
@@: |
bts [irq_active_set], ebp |
lea esi, [irqh_tab+ebp*8] ; esi= list head |
mov ebx, esi |
.next: |
mov ebx, [ebx+IRQH.list.next]; ebx= irqh pointer |
cmp ebx, esi |
je .done |
push ebx ; FIX THIS |
push edi |
push esi |
push [ebx+IRQH.data] |
call [ebx+IRQH.handler] |
add esp, 4 |
pop esi |
pop edi |
pop ebx |
test eax, eax |
jz .next |
btr [irq_active_set], ebp |
jmp .next |
.done: |
btr [irq_active_set], ebp |
jnc .exit |
inc [irq_failed+ebp*4] |
.exit: |
mov [check_idle_semaphore], 5 |
mov ecx, ebp |
call irq_eoi |
restore_ring3_context |
add esp, 4 |
iret |
align 4 |
irqD: |
push eax |
push ecx |
xor eax, eax |
out 0xf0, al |
mov cl, 13 |
call irq_eoi |
pop ecx |
pop eax |
iret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/malloc.inc |
---|
1,1042 → 1,1042 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Small heap based on malloc/free/realloc written by Doug Lea |
; Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) |
; Source ftp://gee.cs.oswego.edu/pub/misc/malloc.c |
; License http://creativecommons.org/licenses/publicdomain. |
; eax= size |
; temp |
; esi= nb |
; ebx= idx |
; |
align 4 |
malloc: |
push esi |
; nb = ((size+7)&~7)+8; |
mov esi, eax ;size |
add esi, 7 |
and esi, -8 |
add esi, 8 |
mov ecx, mst.mutex |
call mutex_lock |
cmp esi, 256 |
jae .large |
mov ecx, esi |
shr ecx, 3 |
or eax, -1 |
shl eax, cl |
and eax, [mst.smallmap] |
jz .small |
push ebp |
push edi |
bsf eax, eax |
mov ebx, eax |
; psize= idx<<3; |
; B = &ms.smallbins[idx]; |
; p = B->fd; |
; F = p->fd; |
; rsize= psize-nb; |
lea ebp, [eax*8] ;ebp= psize |
shl eax, 4 |
lea edi, [mst.smallbins+eax] ;edi= B |
mov edx, [edi+8] ;edx= p |
mov eax, [edx+8] ;eax= F |
mov ecx, ebp |
sub ecx, esi ;ecx= rsize |
; if (B == F) |
cmp edi, eax |
jne @F |
btr [mst.smallmap], ebx |
@@: |
; B->fd = F; |
; F->bk = B; |
; if(rsize<16) |
cmp ecx, 16 |
mov [edi+8], eax |
mov [eax+12], edi |
jae .split |
; p->head = psize|PINUSE_BIT|CINUSE_BIT; |
; (p + psize)->head |= PINUSE_BIT; |
lea eax, [edx+8] |
or dword [edx+ebp+4], 1 |
or ebp, 3 |
mov [edx+4], ebp |
pop edi |
pop ebp |
.done: |
mov esi, eax |
mov ecx, mst.mutex |
call mutex_unlock |
mov eax, esi |
pop esi |
ret |
.split: |
lea ebx, [edx+8] ;ebx=mem |
; r = chunk_plus_offset(p, nb); |
; p->head = nb|PINUSE_BIT|CINUSE_BIT; |
; r->head = rsize|PINUSE_BIT; |
lea eax, [edx+esi] ;eax= r |
or esi, 3 |
mov [edx+4], esi |
mov edx, ecx |
or edx, 1 |
mov [eax+4], edx |
; (r + rsize)->prev_foot = rsize; |
mov [eax+ecx], ecx |
; I = rsize>>3; |
shr ecx, 3 |
; ms.smallmap |= 1<< I; |
bts [mst.smallmap], ecx |
; B = &ms.smallbins[I]; |
shl ecx, 4 |
pop edi |
pop ebp |
add ecx, mst.smallbins ;ecx= B |
mov edx, [ecx+8] ; F = B->fd; |
mov [ecx+8], eax ; B->fd = r; |
mov [edx+12], eax ; F->bk = r; |
mov [eax+8], edx ; r->fd = F; |
mov [eax+12], ecx ; r->bk = B; |
mov eax, ebx |
jmp .done |
.small: |
; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0) |
;;;;;;;;;;; start a change <lrz> |
mov eax,[mst.treemap] |
test eax,eax |
;;;;;;;;;;; end the change <lrz> |
; cmp [mst.treemap], 0 |
jz .from_top |
mov eax, esi |
call malloc_small |
test eax, eax |
jz .from_top |
jmp .done |
.large: |
; if (ms.treemap != 0 && (mem = malloc_large(nb)) != 0) |
cmp [mst.treemap], 0 |
je .from_top |
call malloc_large ;esi= nb |
test eax, eax |
jne .done |
.from_top: |
; if (nb < ms.topsize) |
mov eax, [mst.topsize] |
cmp esi, eax |
jae .fail |
; rsize = ms.topsize -= nb; |
; p = ms.top; |
mov ecx, [mst.top] |
sub eax, esi |
mov [mst.topsize], eax |
; r = ms.top = chunk_plus_offset(p, nb); |
; r->head = rsize | PINUSE_BIT; |
; p->head = nb |PINUSE_BIT|CINUSE_BIT; |
lea edx, [ecx+esi] |
or eax, 1 |
mov [mst.top], edx |
or esi, 3 |
mov [edx+4], eax |
mov [ecx+4], esi |
lea eax, [ecx+8] |
jmp .done |
.fail: |
xor eax, eax |
jmp .done |
; param |
; eax= mem |
align 4 |
free: |
test eax, eax |
jz .exit |
push edi |
mov edi, eax |
add edi, -8 |
; if(p->head & CINUSE_BIT) |
test byte [edi+4], 2 |
je .fail |
mov ecx, mst.mutex |
call mutex_lock |
; psize = p->head & (~3); |
mov eax, [edi+4] |
push esi |
mov esi, eax |
and esi, -4 |
; next = chunk_plus_offset(p, psize); |
; if(!(p->head & PINUSE_BIT)) |
test al, 1 |
lea ebx, [esi+edi] |
jne .next |
; prevsize = p->prev_foot; |
; prev=p - prevsize; |
; psize += prevsize; |
; p = prev; |
mov ecx, [edi] ;ecx= prevsize |
add esi, ecx ;esi= psize |
sub edi, ecx ;edi= p |
; if (prevsize < 256) |
cmp ecx, 256 |
jae .unlink_large |
mov eax, [edi+8] ;F = p->fd; |
mov edx, [edi+12] ;B = p->bk; |
; if (F == B) |
; ms.smallmap &= ~(1<< I); |
shr ecx, 3 |
cmp eax, edx |
jne @F |
btr [mst.smallmap], ecx |
@@: |
mov [eax+12], edx ;F->bk = B; |
mov [edx+8], eax ;B->fd = F |
jmp .next |
.unlink_large: |
mov edx, edi |
call unlink_large_chunk |
.next: |
; if(next->head & PINUSE_BIT) |
mov eax, [ebx+4] |
test al, 1 |
jz .fail2 |
; if (! (next->head & CINUSE_BIT)) |
test al, 2 |
jnz .fix_next |
; if (next == ms.top) |
cmp ebx, [mst.top] |
jne @F |
; tsize = ms.topsize += psize; |
mov eax, [mst.topsize] |
add eax, esi |
mov [mst.topsize], eax |
; ms.top = p; |
; p->head = tsize | PINUSE_BIT; |
or eax, 1 |
mov [mst.top], edi |
mov [edi+4], eax |
.fail2: |
mov esi, eax |
mov ecx, mst.mutex |
call mutex_unlock |
mov eax, esi |
pop esi |
.fail: |
pop edi |
.exit: |
ret |
@@: |
; nsize = next->head & ~INUSE_BITS; |
and eax, -4 |
add esi, eax ;psize += nsize; |
; if (nsize < 256) |
cmp eax, 256 |
jae .unl_large |
mov edx, [ebx+8] ;F = next->fd |
mov ebx, [ebx+12] ;B = next->bk |
; if (F == B) |
cmp edx, ebx |
jne @F |
mov ecx, eax |
shr ecx, 3 |
btr [mst.smallmap], ecx |
@@: |
mov [edx+12], ebx ;F->bk = B |
; p->head = psize|PINUSE_BIT; |
mov ecx, esi |
mov [ebx+8], edx |
or ecx, 1 |
mov [edi+4], ecx |
; (p+psize)->prev_foot = psize; |
mov [esi+edi], esi |
; insert_chunk(p,psize); |
mov eax, esi |
pop esi |
mov ecx, edi |
pop edi |
jmp insert_chunk |
.unl_large: |
; unlink_large_chunk((tchunkptr)next); |
mov edx, ebx |
call unlink_large_chunk |
; p->head = psize|PINUSE_BIT; |
mov ecx, esi |
or ecx, 1 |
mov [edi+4], ecx |
; (p+psize)->prev_foot = psize; |
mov [esi+edi], esi |
; insert_chunk(p,psize); |
mov eax, esi |
pop esi |
mov ecx, edi |
pop edi |
jmp insert_chunk |
.fix_next: |
; (p+psize)->prev_foot = psize; |
; next->head &= ~PINUSE_BIT; |
; p->head = psize|PINUSE_BIT; |
and eax, -2 |
mov edx, esi |
mov [ebx+4], eax |
or edx, 1 |
mov [edi+4], edx |
; (p+psize)->prev_foot = psize; |
mov [esi+edi], esi |
; insert_chunk(p,psize); |
mov eax, esi |
pop esi |
mov ecx, edi |
pop edi |
jmp insert_chunk |
; param |
; ecx = chunk |
; eax = size |
insert_chunk: |
cmp eax, 256 |
push esi |
mov esi, ecx |
jae .large |
; I = S>>3; |
; ms.smallmap |= 1<< I; |
shr eax, 3 |
bts [mst.smallmap], eax |
; B = &ms.smallbins[I]; |
shl eax, 4 |
add eax, mst.smallbins |
mov edx, [eax+8] ;F = B->fd |
mov [eax+8], esi ;B->fd = P |
mov [edx+12], esi ;F->bk = P |
mov [esi+8], edx ;P->fd = F |
mov [esi+12], eax ;P->bk = B |
pop esi |
mov ecx, mst.mutex |
call mutex_unlock |
ret |
.large: |
mov ebx, eax |
call insert_large_chunk |
pop esi |
mov ecx, mst.mutex |
call mutex_unlock |
ret |
; param |
; esi= chunk |
; ebx= size |
insert_large_chunk: |
; I = compute_tree_index(S); |
mov edx, ebx |
shr edx, 8 |
bsr eax, edx |
lea ecx, [eax+7] |
mov edx, ebx |
shr edx, cl |
and edx, 1 |
lea ecx, [edx+eax*2] |
; X->index = I; |
mov dword [esi+28], ecx |
; X->child[0] = X->child[1] = 0; |
and dword [esi+20], 0 |
and dword [esi+16], 0 |
; H = &ms.treebins[I]; |
mov eax, ecx |
lea edx, [mst.treebins+eax*4] |
; if (!(ms.treemap & 1<<I)) |
bt [mst.treemap], ecx |
jc .tree |
; ms.treemap |= 1<<I; |
bts [mst.treemap], ecx |
; *H = X; |
mov dword [edx], esi |
jmp .done |
.tree: |
; T = *H; |
mov edx, [edx] |
; K = S << leftshift_for_tree_index(I); |
mov eax, ecx |
shr eax, 1 |
sub ecx, 31 |
mov edi, 37 |
sub edi, eax |
neg ecx |
sbb ecx, ecx |
and ecx, edi |
mov eax, ebx |
shl eax, cl ;eax= K |
jmp .loop |
.not_eq_size: |
; C = &(T->child[(K >> 31) & 1]); |
mov ecx, eax |
shr ecx, 31 |
lea ecx, [edx+ecx*4+16] |
; K <<= 1; |
; if (*C != 0) |
mov edi, [ecx] |
add eax, eax |
test edi, edi |
jz .insert_child |
; T = *C; |
mov edx, edi |
.loop: |
; for (;;) |
; if ((T->head & ~INUSE_BITS) != S) |
mov ecx, [edx+4] |
and ecx, not 3 |
cmp ecx, ebx |
jne .not_eq_size |
; F = T->fd; |
mov eax, [edx+8] |
; T->fd = F->bk = X; |
mov [eax+12], esi |
mov [edx+8], esi |
; X->fd = F; |
; X->bk = T; |
; X->parent = 0; |
and dword [esi+24], 0 |
mov [esi+8], eax |
mov [esi+12], edx |
ret |
.insert_child: |
; *C = X; |
mov [ecx], esi |
.done: |
; X->parent = T; |
mov [esi+24], edx |
; X->fd = X->bk = X; |
mov [esi+12], esi |
mov [esi+8], esi |
ret |
; param |
; edx= chunk |
unlink_large_chunk: |
mov eax, [edx+12] |
cmp eax, edx |
push edi |
mov edi, [edx+24] |
je @F |
mov ecx, [edx+8] ;F = X->fd |
mov [ecx+12], eax ;F->bk = R; |
mov [eax+8], ecx ;R->fd = F |
jmp .parent |
@@: |
mov eax, [edx+20] |
test eax, eax |
push esi |
lea esi, [edx+20] |
jne .loop |
mov eax, [edx+16] |
test eax, eax |
lea esi, [edx+16] |
je .l2 |
.loop: |
cmp dword [eax+20], 0 |
lea ecx, [eax+20] |
jne @F |
cmp dword [eax+16], 0 |
lea ecx, [eax+16] |
je .l1 |
@@: |
mov eax, [ecx] |
mov esi, ecx |
jmp .loop |
.l1: |
mov dword [esi], 0 |
.l2: |
pop esi |
.parent: |
test edi, edi |
je .done |
mov ecx, [edx+28] |
cmp edx, [mst.treebins+ecx*4] |
lea ecx, [mst.treebins+ecx*4] |
jne .l3 |
test eax, eax |
mov [ecx], eax |
jne .l5 |
mov ecx, [edx+28] |
btr [mst.treemap], ecx |
pop edi |
ret |
.l3: |
cmp [edi+16], edx |
jne @F |
mov [edi+16], eax |
jmp .l4 |
@@: |
mov [edi+20], eax |
.l4: |
test eax, eax |
je .done |
.l5: |
mov [eax+24], edi |
mov ecx, [edx+16] |
test ecx, ecx |
je .l6 |
mov [eax+16], ecx |
mov [ecx+24], eax |
.l6: |
mov edx, [edx+20] |
test edx, edx |
je .done |
mov [eax+20], edx |
mov [edx+24], eax |
.done: |
pop edi |
ret |
; param |
; esi= nb |
malloc_small: |
push ebp |
mov ebp, esi |
push edi |
bsf eax,[mst.treemap] |
mov ecx, [mst.treebins+eax*4] |
; rsize = (t->head & ~INUSE_BITS) - nb; |
mov edi, [ecx+4] |
and edi, -4 |
sub edi, esi |
.loop: |
mov ebx, ecx |
.loop_1: |
; while ((t = leftmost_child(t)) != 0) |
mov eax, [ecx+16] |
test eax, eax |
jz @F |
mov ecx, eax |
jmp .l1 |
@@: |
mov ecx, [ecx+20] |
.l1: |
test ecx, ecx |
jz .unlink |
; trem = (t->head & ~INUSE_BITS) - nb; |
mov eax, [ecx+4] |
and eax, -4 |
sub eax, ebp |
; if (trem < rsize) |
cmp eax, edi |
jae .loop_1 |
; rsize = trem; |
mov edi, eax |
jmp .loop |
.unlink: |
; r = chunk_plus_offset((mchunkptr)v, nb); |
; unlink_large_chunk(v); |
mov edx, ebx |
lea esi, [ebx+ebp] |
call unlink_large_chunk |
; if (rsize < 16) |
cmp edi, 16 |
jae .split |
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; |
lea ecx, [edi+ebp] |
; (v+rsize + nb)->head |= PINUSE_BIT; |
add edi, ebx |
lea eax, [edi+ebp+4] |
pop edi |
or ecx, 3 |
mov [ebx+4], ecx |
or dword [eax], 1 |
pop ebp |
lea eax, [ebx+8] |
ret |
.split: |
; v->head = nb|PINUSE_BIT|CINUSE_BIT; |
; r->head = rsize|PINUSE_BIT; |
; (r+rsize)->prev_foot = rsize; |
or ebp, 3 |
mov edx, edi |
or edx, 1 |
cmp edi, 256 |
mov [ebx+4], ebp |
mov [esi+4], edx |
mov [esi+edi], edi |
jae .large |
shr edi, 3 |
bts [mst.smallmap], edi |
mov eax, edi |
shl eax, 4 |
add eax, mst.smallbins |
mov edx, [eax+8] |
mov [eax+8], esi |
mov [edx+12], esi |
pop edi |
mov [esi+12], eax |
mov [esi+8], edx |
pop ebp |
lea eax, [ebx+8] |
ret |
.large: |
lea eax, [ebx+8] |
push eax |
mov ebx, edi |
call insert_large_chunk |
pop eax |
pop edi |
pop ebp |
ret |
; param |
; esi= nb |
malloc_large: |
.idx equ esp+4 |
.rst equ esp |
push ebp |
push esi |
push edi |
sub esp, 8 |
; v = 0; |
; rsize = -nb; |
mov edi, esi |
mov ebx, esi |
xor ebp, ebp |
neg edi |
; idx = compute_tree_index(nb); |
mov edx, esi |
shr edx, 8 |
bsr eax, edx |
lea ecx, [eax+7] |
shr esi, cl |
and esi, 1 |
lea ecx, [esi+eax*2] |
mov [.idx], ecx |
; if ((t = ms.treebins[idx]) != 0) |
mov eax, [mst.treebins+ecx*4] |
test eax, eax |
jz .l3 |
; sizebits = nb << leftshift_for_tree_index(idx); |
cmp ecx, 31 |
jne @F |
xor ecx, ecx |
jmp .l1 |
@@: |
mov edx, ecx |
shr edx, 1 |
mov ecx, 37 |
sub ecx, edx |
.l1: |
mov edx, ebx |
shl edx, cl |
; rst = 0; |
mov [.rst], ebp |
.loop: |
; trem = (t->head & ~INUSE_BITS) - nb; |
mov ecx, [eax+4] |
and ecx, -4 |
sub ecx, ebx |
; if (trem < rsize) |
cmp ecx, edi |
jae @F |
; v = t; |
; if ((rsize = trem) == 0) |
test ecx, ecx |
mov ebp, eax |
mov edi, ecx |
je .l2 |
@@: |
; rt = t->child[1]; |
mov ecx, [eax+20] |
; t = t->child[(sizebits >> 31) & 1]; |
mov esi, edx |
shr esi, 31 |
; if (rt != 0 && rt != t) |
test ecx, ecx |
mov eax, [eax+esi*4+16] |
jz @F |
cmp ecx, eax |
jz @F |
; rst = rt; |
mov [.rst], ecx |
@@: |
; if (t == 0) |
test eax, eax |
jz @F |
; sizebits <<= 1; |
add edx, edx |
jmp .loop |
@@: |
; t = rst; |
mov eax, [.rst] |
.l2: |
; if (t == 0 && v == 0) |
test eax, eax |
jne .l4 |
test ebp, ebp |
jne .l7 |
mov ecx, [.idx] |
.l3: |
; leftbits = (-1<<idx) & ms.treemap; |
; if (leftbits != 0) |
or edx, -1 |
shl edx, cl |
and edx, [mst.treemap] |
jz @F |
bsf eax, edx |
; t = ms.treebins[i]; |
mov eax, [mst.treebins+eax*4] |
@@: |
; while (t != 0) |
test eax, eax |
jz .l5 |
.l4: |
; trem = (t->head & ~INUSE_BITS) - nb; |
mov ecx, [eax+4] |
and ecx, -4 |
sub ecx, ebx |
; if (trem < rsize) |
cmp ecx, edi |
jae @F |
; rsize = trem; |
mov edi, ecx |
; v = t; |
mov ebp, eax |
@@: |
; t = leftmost_child(t); |
mov ecx, [eax+16] |
test ecx, ecx |
je @F |
mov eax, ecx |
jmp .l6 |
@@: |
mov eax, [eax+20] |
.l6: |
; while (t != 0) |
test eax, eax |
jne .l4 |
.l5: |
; if (v != 0) |
test ebp, ebp |
jz .done |
.l7: |
; r = chunk_plus_offset((mchunkptr)v, nb); |
; unlink_large_chunk(v); |
mov edx, ebp |
lea esi, [ebx+ebp] |
call unlink_large_chunk |
; if (rsize < 16) |
cmp edi, 16 |
jae .large |
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; |
lea ecx, [edi+ebx] |
; (v+rsize + nb)->head |= PINUSE_BIT; |
add edi, ebp |
lea eax, [edi+ebx+4] |
or ecx, 3 |
mov [ebp+4], ecx |
or dword [eax], 1 |
lea eax, [ebp+8] |
add esp, 8 |
pop edi |
pop esi |
pop ebp |
ret |
.large: |
; v->head = nb|PINUSE_BIT|CINUSE_BIT; |
; r->head = rsize|PINUSE_BIT; |
mov edx, edi |
or ebx, 3 |
mov [ebp+4], ebx |
or edx, 1 |
mov [esi+4], edx |
; (r+rsize)->prev_foot = rsize; |
; insert_large_chunk((tchunkptr)r, rsize); |
mov [esi+edi], edi |
mov eax, edi |
mov ecx, esi |
call insert_chunk |
lea eax, [ebp+8] |
add esp, 8 |
pop edi |
pop esi |
pop ebp |
ret |
.done: |
add esp, 8 |
pop edi |
pop esi |
pop ebp |
xor eax, eax |
ret |
init_malloc: |
stdcall kernel_alloc, 0x40000 |
mov [mst.top], eax |
mov [mst.topsize], 128*1024 |
mov dword [eax+4], (128*1024) or 1 |
mov eax, mst.smallbins |
@@: |
mov [eax+8], eax |
mov [eax+12], eax |
add eax, 16 |
cmp eax, mst.smallbins+512 |
jb @B |
mov ecx, mst.mutex |
call mutex_init |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Small heap based on malloc/free/realloc written by Doug Lea |
; Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) |
; Source ftp://gee.cs.oswego.edu/pub/misc/malloc.c |
; License http://creativecommons.org/licenses/publicdomain. |
; eax= size |
; temp |
; esi= nb |
; ebx= idx |
; |
align 4 |
malloc: |
push esi |
; nb = ((size+7)&~7)+8; |
mov esi, eax ;size |
add esi, 7 |
and esi, -8 |
add esi, 8 |
mov ecx, mst.mutex |
call mutex_lock |
cmp esi, 256 |
jae .large |
mov ecx, esi |
shr ecx, 3 |
or eax, -1 |
shl eax, cl |
and eax, [mst.smallmap] |
jz .small |
push ebp |
push edi |
bsf eax, eax |
mov ebx, eax |
; psize= idx<<3; |
; B = &ms.smallbins[idx]; |
; p = B->fd; |
; F = p->fd; |
; rsize= psize-nb; |
lea ebp, [eax*8] ;ebp= psize |
shl eax, 4 |
lea edi, [mst.smallbins+eax] ;edi= B |
mov edx, [edi+8] ;edx= p |
mov eax, [edx+8] ;eax= F |
mov ecx, ebp |
sub ecx, esi ;ecx= rsize |
; if (B == F) |
cmp edi, eax |
jne @F |
btr [mst.smallmap], ebx |
@@: |
; B->fd = F; |
; F->bk = B; |
; if(rsize<16) |
cmp ecx, 16 |
mov [edi+8], eax |
mov [eax+12], edi |
jae .split |
; p->head = psize|PINUSE_BIT|CINUSE_BIT; |
; (p + psize)->head |= PINUSE_BIT; |
lea eax, [edx+8] |
or dword [edx+ebp+4], 1 |
or ebp, 3 |
mov [edx+4], ebp |
pop edi |
pop ebp |
.done: |
mov esi, eax |
mov ecx, mst.mutex |
call mutex_unlock |
mov eax, esi |
pop esi |
ret |
.split: |
lea ebx, [edx+8] ;ebx=mem |
; r = chunk_plus_offset(p, nb); |
; p->head = nb|PINUSE_BIT|CINUSE_BIT; |
; r->head = rsize|PINUSE_BIT; |
lea eax, [edx+esi] ;eax= r |
or esi, 3 |
mov [edx+4], esi |
mov edx, ecx |
or edx, 1 |
mov [eax+4], edx |
; (r + rsize)->prev_foot = rsize; |
mov [eax+ecx], ecx |
; I = rsize>>3; |
shr ecx, 3 |
; ms.smallmap |= 1<< I; |
bts [mst.smallmap], ecx |
; B = &ms.smallbins[I]; |
shl ecx, 4 |
pop edi |
pop ebp |
add ecx, mst.smallbins ;ecx= B |
mov edx, [ecx+8] ; F = B->fd; |
mov [ecx+8], eax ; B->fd = r; |
mov [edx+12], eax ; F->bk = r; |
mov [eax+8], edx ; r->fd = F; |
mov [eax+12], ecx ; r->bk = B; |
mov eax, ebx |
jmp .done |
.small: |
; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0) |
;;;;;;;;;;; start a change <lrz> |
mov eax, [mst.treemap] |
test eax, eax |
;;;;;;;;;;; end the change <lrz> |
; cmp [mst.treemap], 0 |
jz .from_top |
mov eax, esi |
call malloc_small |
test eax, eax |
jz .from_top |
jmp .done |
.large: |
; if (ms.treemap != 0 && (mem = malloc_large(nb)) != 0) |
cmp [mst.treemap], 0 |
je .from_top |
call malloc_large ;esi= nb |
test eax, eax |
jne .done |
.from_top: |
; if (nb < ms.topsize) |
mov eax, [mst.topsize] |
cmp esi, eax |
jae .fail |
; rsize = ms.topsize -= nb; |
; p = ms.top; |
mov ecx, [mst.top] |
sub eax, esi |
mov [mst.topsize], eax |
; r = ms.top = chunk_plus_offset(p, nb); |
; r->head = rsize | PINUSE_BIT; |
; p->head = nb |PINUSE_BIT|CINUSE_BIT; |
lea edx, [ecx+esi] |
or eax, 1 |
mov [mst.top], edx |
or esi, 3 |
mov [edx+4], eax |
mov [ecx+4], esi |
lea eax, [ecx+8] |
jmp .done |
.fail: |
xor eax, eax |
jmp .done |
; param |
; eax= mem |
align 4 |
free: |
test eax, eax |
jz .exit |
push edi |
mov edi, eax |
add edi, -8 |
; if(p->head & CINUSE_BIT) |
test byte [edi+4], 2 |
je .fail |
mov ecx, mst.mutex |
call mutex_lock |
; psize = p->head & (~3); |
mov eax, [edi+4] |
push esi |
mov esi, eax |
and esi, -4 |
; next = chunk_plus_offset(p, psize); |
; if(!(p->head & PINUSE_BIT)) |
test al, 1 |
lea ebx, [esi+edi] |
jne .next |
; prevsize = p->prev_foot; |
; prev=p - prevsize; |
; psize += prevsize; |
; p = prev; |
mov ecx, [edi] ;ecx= prevsize |
add esi, ecx ;esi= psize |
sub edi, ecx ;edi= p |
; if (prevsize < 256) |
cmp ecx, 256 |
jae .unlink_large |
mov eax, [edi+8] ;F = p->fd; |
mov edx, [edi+12] ;B = p->bk; |
; if (F == B) |
; ms.smallmap &= ~(1<< I); |
shr ecx, 3 |
cmp eax, edx |
jne @F |
btr [mst.smallmap], ecx |
@@: |
mov [eax+12], edx ;F->bk = B; |
mov [edx+8], eax ;B->fd = F |
jmp .next |
.unlink_large: |
mov edx, edi |
call unlink_large_chunk |
.next: |
; if(next->head & PINUSE_BIT) |
mov eax, [ebx+4] |
test al, 1 |
jz .fail2 |
; if (! (next->head & CINUSE_BIT)) |
test al, 2 |
jnz .fix_next |
; if (next == ms.top) |
cmp ebx, [mst.top] |
jne @F |
; tsize = ms.topsize += psize; |
mov eax, [mst.topsize] |
add eax, esi |
mov [mst.topsize], eax |
; ms.top = p; |
; p->head = tsize | PINUSE_BIT; |
or eax, 1 |
mov [mst.top], edi |
mov [edi+4], eax |
.fail2: |
mov esi, eax |
mov ecx, mst.mutex |
call mutex_unlock |
mov eax, esi |
pop esi |
.fail: |
pop edi |
.exit: |
ret |
@@: |
; nsize = next->head & ~INUSE_BITS; |
and eax, -4 |
add esi, eax ;psize += nsize; |
; if (nsize < 256) |
cmp eax, 256 |
jae .unl_large |
mov edx, [ebx+8] ;F = next->fd |
mov ebx, [ebx+12] ;B = next->bk |
; if (F == B) |
cmp edx, ebx |
jne @F |
mov ecx, eax |
shr ecx, 3 |
btr [mst.smallmap], ecx |
@@: |
mov [edx+12], ebx ;F->bk = B |
; p->head = psize|PINUSE_BIT; |
mov ecx, esi |
mov [ebx+8], edx |
or ecx, 1 |
mov [edi+4], ecx |
; (p+psize)->prev_foot = psize; |
mov [esi+edi], esi |
; insert_chunk(p,psize); |
mov eax, esi |
pop esi |
mov ecx, edi |
pop edi |
jmp insert_chunk |
.unl_large: |
; unlink_large_chunk((tchunkptr)next); |
mov edx, ebx |
call unlink_large_chunk |
; p->head = psize|PINUSE_BIT; |
mov ecx, esi |
or ecx, 1 |
mov [edi+4], ecx |
; (p+psize)->prev_foot = psize; |
mov [esi+edi], esi |
; insert_chunk(p,psize); |
mov eax, esi |
pop esi |
mov ecx, edi |
pop edi |
jmp insert_chunk |
.fix_next: |
; (p+psize)->prev_foot = psize; |
; next->head &= ~PINUSE_BIT; |
; p->head = psize|PINUSE_BIT; |
and eax, -2 |
mov edx, esi |
mov [ebx+4], eax |
or edx, 1 |
mov [edi+4], edx |
; (p+psize)->prev_foot = psize; |
mov [esi+edi], esi |
; insert_chunk(p,psize); |
mov eax, esi |
pop esi |
mov ecx, edi |
pop edi |
jmp insert_chunk |
; param |
; ecx = chunk |
; eax = size |
insert_chunk: |
cmp eax, 256 |
push esi |
mov esi, ecx |
jae .large |
; I = S>>3; |
; ms.smallmap |= 1<< I; |
shr eax, 3 |
bts [mst.smallmap], eax |
; B = &ms.smallbins[I]; |
shl eax, 4 |
add eax, mst.smallbins |
mov edx, [eax+8] ;F = B->fd |
mov [eax+8], esi ;B->fd = P |
mov [edx+12], esi ;F->bk = P |
mov [esi+8], edx ;P->fd = F |
mov [esi+12], eax ;P->bk = B |
pop esi |
mov ecx, mst.mutex |
call mutex_unlock |
ret |
.large: |
mov ebx, eax |
call insert_large_chunk |
pop esi |
mov ecx, mst.mutex |
call mutex_unlock |
ret |
; param |
; esi= chunk |
; ebx= size |
insert_large_chunk: |
; I = compute_tree_index(S); |
mov edx, ebx |
shr edx, 8 |
bsr eax, edx |
lea ecx, [eax+7] |
mov edx, ebx |
shr edx, cl |
and edx, 1 |
lea ecx, [edx+eax*2] |
; X->index = I; |
mov dword [esi+28], ecx |
; X->child[0] = X->child[1] = 0; |
and dword [esi+20], 0 |
and dword [esi+16], 0 |
; H = &ms.treebins[I]; |
mov eax, ecx |
lea edx, [mst.treebins+eax*4] |
; if (!(ms.treemap & 1<<I)) |
bt [mst.treemap], ecx |
jc .tree |
; ms.treemap |= 1<<I; |
bts [mst.treemap], ecx |
; *H = X; |
mov dword [edx], esi |
jmp .done |
.tree: |
; T = *H; |
mov edx, [edx] |
; K = S << leftshift_for_tree_index(I); |
mov eax, ecx |
shr eax, 1 |
sub ecx, 31 |
mov edi, 37 |
sub edi, eax |
neg ecx |
sbb ecx, ecx |
and ecx, edi |
mov eax, ebx |
shl eax, cl ;eax= K |
jmp .loop |
.not_eq_size: |
; C = &(T->child[(K >> 31) & 1]); |
mov ecx, eax |
shr ecx, 31 |
lea ecx, [edx+ecx*4+16] |
; K <<= 1; |
; if (*C != 0) |
mov edi, [ecx] |
add eax, eax |
test edi, edi |
jz .insert_child |
; T = *C; |
mov edx, edi |
.loop: |
; for (;;) |
; if ((T->head & ~INUSE_BITS) != S) |
mov ecx, [edx+4] |
and ecx, not 3 |
cmp ecx, ebx |
jne .not_eq_size |
; F = T->fd; |
mov eax, [edx+8] |
; T->fd = F->bk = X; |
mov [eax+12], esi |
mov [edx+8], esi |
; X->fd = F; |
; X->bk = T; |
; X->parent = 0; |
and dword [esi+24], 0 |
mov [esi+8], eax |
mov [esi+12], edx |
ret |
.insert_child: |
; *C = X; |
mov [ecx], esi |
.done: |
; X->parent = T; |
mov [esi+24], edx |
; X->fd = X->bk = X; |
mov [esi+12], esi |
mov [esi+8], esi |
ret |
; param |
; edx= chunk |
unlink_large_chunk: |
mov eax, [edx+12] |
cmp eax, edx |
push edi |
mov edi, [edx+24] |
je @F |
mov ecx, [edx+8] ;F = X->fd |
mov [ecx+12], eax ;F->bk = R; |
mov [eax+8], ecx ;R->fd = F |
jmp .parent |
@@: |
mov eax, [edx+20] |
test eax, eax |
push esi |
lea esi, [edx+20] |
jne .loop |
mov eax, [edx+16] |
test eax, eax |
lea esi, [edx+16] |
je .l2 |
.loop: |
cmp dword [eax+20], 0 |
lea ecx, [eax+20] |
jne @F |
cmp dword [eax+16], 0 |
lea ecx, [eax+16] |
je .l1 |
@@: |
mov eax, [ecx] |
mov esi, ecx |
jmp .loop |
.l1: |
mov dword [esi], 0 |
.l2: |
pop esi |
.parent: |
test edi, edi |
je .done |
mov ecx, [edx+28] |
cmp edx, [mst.treebins+ecx*4] |
lea ecx, [mst.treebins+ecx*4] |
jne .l3 |
test eax, eax |
mov [ecx], eax |
jne .l5 |
mov ecx, [edx+28] |
btr [mst.treemap], ecx |
pop edi |
ret |
.l3: |
cmp [edi+16], edx |
jne @F |
mov [edi+16], eax |
jmp .l4 |
@@: |
mov [edi+20], eax |
.l4: |
test eax, eax |
je .done |
.l5: |
mov [eax+24], edi |
mov ecx, [edx+16] |
test ecx, ecx |
je .l6 |
mov [eax+16], ecx |
mov [ecx+24], eax |
.l6: |
mov edx, [edx+20] |
test edx, edx |
je .done |
mov [eax+20], edx |
mov [edx+24], eax |
.done: |
pop edi |
ret |
; param |
; esi= nb |
malloc_small: |
push ebp |
mov ebp, esi |
push edi |
bsf eax, [mst.treemap] |
mov ecx, [mst.treebins+eax*4] |
; rsize = (t->head & ~INUSE_BITS) - nb; |
mov edi, [ecx+4] |
and edi, -4 |
sub edi, esi |
.loop: |
mov ebx, ecx |
.loop_1: |
; while ((t = leftmost_child(t)) != 0) |
mov eax, [ecx+16] |
test eax, eax |
jz @F |
mov ecx, eax |
jmp .l1 |
@@: |
mov ecx, [ecx+20] |
.l1: |
test ecx, ecx |
jz .unlink |
; trem = (t->head & ~INUSE_BITS) - nb; |
mov eax, [ecx+4] |
and eax, -4 |
sub eax, ebp |
; if (trem < rsize) |
cmp eax, edi |
jae .loop_1 |
; rsize = trem; |
mov edi, eax |
jmp .loop |
.unlink: |
; r = chunk_plus_offset((mchunkptr)v, nb); |
; unlink_large_chunk(v); |
mov edx, ebx |
lea esi, [ebx+ebp] |
call unlink_large_chunk |
; if (rsize < 16) |
cmp edi, 16 |
jae .split |
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; |
lea ecx, [edi+ebp] |
; (v+rsize + nb)->head |= PINUSE_BIT; |
add edi, ebx |
lea eax, [edi+ebp+4] |
pop edi |
or ecx, 3 |
mov [ebx+4], ecx |
or dword [eax], 1 |
pop ebp |
lea eax, [ebx+8] |
ret |
.split: |
; v->head = nb|PINUSE_BIT|CINUSE_BIT; |
; r->head = rsize|PINUSE_BIT; |
; (r+rsize)->prev_foot = rsize; |
or ebp, 3 |
mov edx, edi |
or edx, 1 |
cmp edi, 256 |
mov [ebx+4], ebp |
mov [esi+4], edx |
mov [esi+edi], edi |
jae .large |
shr edi, 3 |
bts [mst.smallmap], edi |
mov eax, edi |
shl eax, 4 |
add eax, mst.smallbins |
mov edx, [eax+8] |
mov [eax+8], esi |
mov [edx+12], esi |
pop edi |
mov [esi+12], eax |
mov [esi+8], edx |
pop ebp |
lea eax, [ebx+8] |
ret |
.large: |
lea eax, [ebx+8] |
push eax |
mov ebx, edi |
call insert_large_chunk |
pop eax |
pop edi |
pop ebp |
ret |
; param |
; esi= nb |
malloc_large: |
.idx equ esp+4 |
.rst equ esp |
push ebp |
push esi |
push edi |
sub esp, 8 |
; v = 0; |
; rsize = -nb; |
mov edi, esi |
mov ebx, esi |
xor ebp, ebp |
neg edi |
; idx = compute_tree_index(nb); |
mov edx, esi |
shr edx, 8 |
bsr eax, edx |
lea ecx, [eax+7] |
shr esi, cl |
and esi, 1 |
lea ecx, [esi+eax*2] |
mov [.idx], ecx |
; if ((t = ms.treebins[idx]) != 0) |
mov eax, [mst.treebins+ecx*4] |
test eax, eax |
jz .l3 |
; sizebits = nb << leftshift_for_tree_index(idx); |
cmp ecx, 31 |
jne @F |
xor ecx, ecx |
jmp .l1 |
@@: |
mov edx, ecx |
shr edx, 1 |
mov ecx, 37 |
sub ecx, edx |
.l1: |
mov edx, ebx |
shl edx, cl |
; rst = 0; |
mov [.rst], ebp |
.loop: |
; trem = (t->head & ~INUSE_BITS) - nb; |
mov ecx, [eax+4] |
and ecx, -4 |
sub ecx, ebx |
; if (trem < rsize) |
cmp ecx, edi |
jae @F |
; v = t; |
; if ((rsize = trem) == 0) |
test ecx, ecx |
mov ebp, eax |
mov edi, ecx |
je .l2 |
@@: |
; rt = t->child[1]; |
mov ecx, [eax+20] |
; t = t->child[(sizebits >> 31) & 1]; |
mov esi, edx |
shr esi, 31 |
; if (rt != 0 && rt != t) |
test ecx, ecx |
mov eax, [eax+esi*4+16] |
jz @F |
cmp ecx, eax |
jz @F |
; rst = rt; |
mov [.rst], ecx |
@@: |
; if (t == 0) |
test eax, eax |
jz @F |
; sizebits <<= 1; |
add edx, edx |
jmp .loop |
@@: |
; t = rst; |
mov eax, [.rst] |
.l2: |
; if (t == 0 && v == 0) |
test eax, eax |
jne .l4 |
test ebp, ebp |
jne .l7 |
mov ecx, [.idx] |
.l3: |
; leftbits = (-1<<idx) & ms.treemap; |
; if (leftbits != 0) |
or edx, -1 |
shl edx, cl |
and edx, [mst.treemap] |
jz @F |
bsf eax, edx |
; t = ms.treebins[i]; |
mov eax, [mst.treebins+eax*4] |
@@: |
; while (t != 0) |
test eax, eax |
jz .l5 |
.l4: |
; trem = (t->head & ~INUSE_BITS) - nb; |
mov ecx, [eax+4] |
and ecx, -4 |
sub ecx, ebx |
; if (trem < rsize) |
cmp ecx, edi |
jae @F |
; rsize = trem; |
mov edi, ecx |
; v = t; |
mov ebp, eax |
@@: |
; t = leftmost_child(t); |
mov ecx, [eax+16] |
test ecx, ecx |
je @F |
mov eax, ecx |
jmp .l6 |
@@: |
mov eax, [eax+20] |
.l6: |
; while (t != 0) |
test eax, eax |
jne .l4 |
.l5: |
; if (v != 0) |
test ebp, ebp |
jz .done |
.l7: |
; r = chunk_plus_offset((mchunkptr)v, nb); |
; unlink_large_chunk(v); |
mov edx, ebp |
lea esi, [ebx+ebp] |
call unlink_large_chunk |
; if (rsize < 16) |
cmp edi, 16 |
jae .large |
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; |
lea ecx, [edi+ebx] |
; (v+rsize + nb)->head |= PINUSE_BIT; |
add edi, ebp |
lea eax, [edi+ebx+4] |
or ecx, 3 |
mov [ebp+4], ecx |
or dword [eax], 1 |
lea eax, [ebp+8] |
add esp, 8 |
pop edi |
pop esi |
pop ebp |
ret |
.large: |
; v->head = nb|PINUSE_BIT|CINUSE_BIT; |
; r->head = rsize|PINUSE_BIT; |
mov edx, edi |
or ebx, 3 |
mov [ebp+4], ebx |
or edx, 1 |
mov [esi+4], edx |
; (r+rsize)->prev_foot = rsize; |
; insert_large_chunk((tchunkptr)r, rsize); |
mov [esi+edi], edi |
mov eax, edi |
mov ecx, esi |
call insert_chunk |
lea eax, [ebp+8] |
add esp, 8 |
pop edi |
pop esi |
pop ebp |
ret |
.done: |
add esp, 8 |
pop edi |
pop esi |
pop ebp |
xor eax, eax |
ret |
init_malloc: |
stdcall kernel_alloc, 0x40000 |
mov [mst.top], eax |
mov [mst.topsize], 128*1024 |
mov dword [eax+4], (128*1024) or 1 |
mov eax, mst.smallbins |
@@: |
mov [eax+8], eax |
mov [eax+12], eax |
add eax, 16 |
cmp eax, mst.smallbins+512 |
jb @B |
mov ecx, mst.mutex |
call mutex_init |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/memory.inc |
---|
1,1541 → 1,1545 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
align 4 |
proc alloc_page |
pushfd |
cli |
push ebx |
;//- |
cmp [pg_data.pages_free], 1 |
jle .out_of_memory |
;//- |
mov ebx, [page_start] |
mov ecx, [page_end] |
.l1: |
bsf eax,[ebx]; |
jnz .found |
add ebx,4 |
cmp ebx, ecx |
jb .l1 |
pop ebx |
popfd |
xor eax,eax |
ret |
.found: |
;//- |
dec [pg_data.pages_free] |
jz .out_of_memory |
;//- |
btr [ebx], eax |
mov [page_start],ebx |
sub ebx, sys_pgmap |
lea eax, [eax+ebx*8] |
shl eax, 12 |
;//- dec [pg_data.pages_free] |
pop ebx |
popfd |
ret |
;//- |
.out_of_memory: |
mov [pg_data.pages_free], 1 |
xor eax, eax |
pop ebx |
popfd |
ret |
;//- |
endp |
align 4 |
proc alloc_pages stdcall, count:dword |
pushfd |
push ebx |
push edi |
cli |
mov eax, [count] |
add eax, 7 |
shr eax, 3 |
mov [count], eax |
;//- |
mov ebx, [pg_data.pages_free] |
sub ebx, 9 |
js .out_of_memory |
shr ebx, 3 |
cmp eax, ebx |
jg .out_of_memory |
;//- |
mov ecx, [page_start] |
mov ebx, [page_end] |
.find: |
mov edx, [count] |
mov edi, ecx |
.match: |
cmp byte [ecx], 0xFF |
jne .next |
dec edx |
jz .ok |
inc ecx |
cmp ecx,ebx |
jb .match |
.out_of_memory: |
.fail: |
xor eax, eax |
pop edi |
pop ebx |
popfd |
ret |
.next: |
inc ecx |
cmp ecx, ebx |
jb .find |
pop edi |
pop ebx |
popfd |
xor eax, eax |
ret |
.ok: |
sub ecx, edi |
inc ecx |
push esi |
mov esi, edi |
xor eax, eax |
rep stosb |
sub esi, sys_pgmap |
shl esi, 3+12 |
mov eax, esi |
mov ebx, [count] |
shl ebx, 3 |
sub [pg_data.pages_free], ebx |
pop esi |
pop edi |
pop ebx |
popfd |
ret |
endp |
align 4 |
proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword |
push ebx |
mov eax, [phis_addr] |
and eax, not 0xFFF |
or eax, [flags] |
mov ebx, [lin_addr] |
shr ebx, 12 |
mov [page_tabs+ebx*4], eax |
mov eax, [lin_addr] |
invlpg [eax] |
pop ebx |
ret |
endp |
align 4 |
map_space: ;not implemented |
ret |
align 4 |
proc free_page |
;arg: eax page address |
pushfd |
cli |
shr eax, 12 ;page index |
bts dword [sys_pgmap], eax ;that's all! |
cmc |
adc [pg_data.pages_free], 0 |
shr eax, 3 |
and eax, not 3 ;dword offset from page_map |
add eax, sys_pgmap |
cmp [page_start], eax |
ja @f |
popfd |
ret |
@@: |
mov [page_start], eax |
popfd |
ret |
endp |
proc map_io_mem stdcall, base:dword, size:dword, flags:dword |
push ebx |
push edi |
mov eax, [size] |
add eax, [base] |
add eax, 4095 |
and eax, -4096 |
mov ecx, [base] |
and ecx, -4096 |
sub eax, ecx |
mov [size], eax |
stdcall alloc_kernel_space, eax |
test eax, eax |
jz .fail |
push eax |
mov edi, 0x1000 |
mov ebx, eax |
mov ecx,[size] |
mov edx, [base] |
shr eax, 12 |
shr ecx, 12 |
and edx, -4096 |
or edx, [flags] |
@@: |
mov [page_tabs+eax*4], edx |
invlpg [ebx] |
inc eax |
add ebx, edi |
add edx, edi |
loop @B |
pop eax |
mov edx, [base] |
and edx, 4095 |
add eax, edx |
.fail: |
pop edi |
pop ebx |
ret |
endp |
; param |
; eax= page base + page flags |
; ebx= linear address |
; ecx= count |
align 4 |
commit_pages: |
test ecx, ecx |
jz .fail |
push edi |
push eax |
push ecx |
mov ecx, pg_data.mutex |
call mutex_lock |
pop ecx |
pop eax |
mov edi, ebx |
shr edi, 12 |
lea edi, [page_tabs+edi*4] |
@@: |
stosd |
invlpg [ebx] |
add eax, 0x1000 |
add ebx, 0x1000 |
loop @B |
pop edi |
mov ecx, pg_data.mutex |
call mutex_unlock |
.fail: |
ret |
; param |
; eax= base |
; ecx= count |
align 4 |
release_pages: |
push ebp |
push esi |
push edi |
push ebx |
mov esi, eax |
mov edi, eax |
shr esi, 12 |
lea esi, [page_tabs+esi*4] |
push ecx |
mov ecx, pg_data.mutex |
call mutex_lock |
pop ecx |
mov ebp, [pg_data.pages_free] |
mov ebx, [page_start] |
mov edx, sys_pgmap |
@@: |
xor eax, eax |
xchg eax, [esi] |
invlpg [edi] |
test eax, 1 |
jz .next |
shr eax, 12 |
bts [edx], eax |
cmc |
adc ebp, 0 |
shr eax, 3 |
and eax, -4 |
add eax, edx |
cmp eax, ebx |
jae .next |
mov ebx, eax |
.next: |
add edi, 0x1000 |
add esi, 4 |
loop @B |
mov [pg_data.pages_free], ebp |
mov ecx, pg_data.mutex |
call mutex_unlock |
pop ebx |
pop edi |
pop esi |
pop ebp |
ret |
; param |
; eax= base |
; ecx= count |
align 4 |
unmap_pages: |
push edi |
mov edi, eax |
mov edx, eax |
shr edi, 10 |
add edi, page_tabs |
xor eax, eax |
@@: |
stosd |
invlpg [edx] |
add edx, 0x1000 |
loop @b |
pop edi |
ret |
align 4 |
proc map_page_table stdcall, lin_addr:dword, phis_addr:dword |
push ebx |
mov ebx, [lin_addr] |
shr ebx, 22 |
mov eax, [phis_addr] |
and eax, not 0xFFF |
or eax, PG_UW ;+PG_NOCACHE |
mov dword [master_tab+ebx*4], eax |
mov eax, [lin_addr] |
shr eax, 10 |
add eax, page_tabs |
invlpg [eax] |
pop ebx |
ret |
endp |
align 4 |
proc init_LFB |
locals |
pg_count dd ? |
endl |
cmp dword [LFBAddress], -1 |
jne @f |
mov [BOOT_VAR+0x901c],byte 2 |
stdcall alloc_pages, (0x280000 / 4096) |
push eax |
call alloc_page |
stdcall map_page_table, LFB_BASE, eax |
pop eax |
or eax, PG_UW |
mov ebx, LFB_BASE |
mov ecx, 0x280000 / 4096 |
call commit_pages |
mov [LFBAddress], dword LFB_BASE |
ret |
@@: |
test [SCR_MODE],word 0100000000000000b |
jnz @f |
mov [BOOT_VAR+0x901c],byte 2 |
ret |
@@: |
call init_mtrr |
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_pgdir+(LFB_BASE shr 20) |
@@: |
mov [edx], esi |
add edx, 4 |
add esi, 0x00400000 |
dec edi |
jnz @B |
bt [cpu_caps], CAPS_PGE |
jnc @F |
or dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL |
@@: |
mov dword [LFBAddress], LFB_BASE |
mov eax, cr3 ;flush TLB |
mov cr3, eax |
ret |
.map_page_tables: |
@@: |
call alloc_page |
stdcall map_page_table, edx, eax |
add edx, 0x00400000 |
dec edi |
jnz @B |
mov eax, [LFBAddress] |
mov edi, page_tabs + (LFB_BASE shr 10) |
or eax, PG_UW |
mov ecx, [pg_count] |
cld |
@@: |
stosd |
add eax, 0x1000 |
dec ecx |
jnz @B |
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 |
mov ecx, pg_data.mutex |
call mutex_lock |
mov edi, [new_size] |
add edi,4095 |
and edi,not 4095 |
mov [new_size], edi |
mov edx,[current_slot] |
cmp [edx+APPDATA.heap_base],0 |
jne .exit |
mov esi, [edx+APPDATA.mem_size] |
add esi, 4095 |
and esi, not 4095 |
cmp edi, esi |
jae .expand |
shr edi, 12 |
shr esi, 12 |
@@: |
mov eax, [app_page_tabs+edi*4] |
test eax, 1 |
jz .next |
mov dword [app_page_tabs+edi*4], 2 |
mov ebx, edi |
shl ebx, 12 |
push eax |
invlpg [ebx] |
pop eax |
call free_page |
.next: add edi, 1 |
cmp edi, esi |
jb @B |
.update_size: |
mov ebx, [new_size] |
call update_mem_size |
mov ecx, pg_data.mutex |
call mutex_unlock |
xor eax, eax |
ret |
.expand: |
push esi |
push edi |
add edi, 0x3FFFFF |
and edi, not(0x3FFFFF) |
add esi, 0x3FFFFF |
and esi, not(0x3FFFFF) |
cmp esi, edi |
jae .grow |
xchg esi, edi |
@@: |
call alloc_page |
test eax, eax |
jz .exit_pop |
stdcall map_page_table, edi, eax |
push edi |
shr edi, 10 |
add edi, page_tabs |
mov ecx, 1024 |
xor eax, eax |
cld |
rep stosd |
pop edi |
add edi, 0x00400000 |
cmp edi, esi |
jb @B |
.grow: |
;//- |
pop edi |
push edi |
mov esi, [pg_data.pages_free] |
sub esi, 1 |
shr edi, 12 |
cmp esi, edi |
jle .out_of_memory |
;//- |
pop edi |
pop esi |
@@: |
call alloc_page |
test eax, eax |
jz .exit |
stdcall map_page,esi,eax,dword PG_UW |
push edi |
mov edi, esi |
xor eax, eax |
mov ecx, 1024 |
cld |
rep stosd |
pop edi |
add esi, 0x1000 |
cmp esi, edi |
jb @B |
jmp .update_size |
;//- |
.exit_pop: |
.out_of_memory: |
;//- |
pop edi |
pop esi |
.exit: |
mov ecx, pg_data.mutex |
call mutex_unlock |
xor eax, eax |
inc eax |
ret |
endp |
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 |
; |
; retval |
; eax= phisical page address |
align 4 |
get_pg_addr: |
shr eax, 12 |
mov eax, [page_tabs+eax*4] |
and eax, 0xFFFFF000 |
ret |
align 4 |
; Now it is called from core/sys32::exc_c (see stack frame there) |
proc page_fault_handler |
.err_addr equ ebp-4 |
push ebx ;save exception number (#PF) |
mov ebp, esp |
mov ebx, cr2 |
push ebx ;that is locals: .err_addr = cr2 |
inc [pg_data.pages_faults] |
mov eax, [pf_err_code] |
cmp ebx, OS_BASE ;ebx == .err_addr |
jb .user_space ;ñòðàíèöà â ïàìÿòè ïðèëîæåíèÿ ; |
cmp ebx, page_tabs |
jb .kernel_space ;ñòðàíèöà â ïàìÿòè ÿäðà |
cmp ebx, kernel_tabs |
jb .alloc;.app_tabs ;òàáëèöû ñòðàíèö ïðèëîæåíèÿ ; |
;ïðîñòî ñîçäàäèì îäíó |
if 0 ;ïîêà ýòî ïðîñòî ëèøíåå |
cmp ebx, LFB_BASE |
jb .core_tabs ;òàáëèöû ñòðàíèö ÿäðà |
;Îøèáêà |
.lfb: |
;îáëàñòü LFB |
;Îøèáêà |
jmp .fail |
end if |
.core_tabs: |
.fail: ;simply return to caller |
mov esp, ebp |
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 ;Ñòðàíèöà ïðèñóòñòâóåò |
;Îøèáêà äîñòóïà ? |
shr ebx, 12 |
mov ecx, ebx |
shr ecx, 10 |
mov edx, [master_tab+ecx*4] |
test edx, PG_MAP |
jz .fail ;òàáëèöà ñòðàíèö íå ñîçäàíà |
;íåâåðíûé àäðåñ â ïðîãðàììå |
mov eax, [page_tabs+ebx*4] |
test eax, 2 |
jz .fail ;àäðåñ íå çàðåçåðâèðîâàí äëÿ ; |
;èñïîëüçîâàíèÿ. Îøèáêà |
.alloc: |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page,[.err_addr],eax,PG_UW |
mov edi, [.err_addr] |
and edi, 0xFFFFF000 |
mov ecx, 1024 |
xor eax, eax |
;cld ;caller is duty for this |
rep stosd |
.exit: ;iret with repeat fault instruction |
add esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller |
restore_ring3_context |
iretd |
.err_access: |
; 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] |
test eax, eax |
jz .fail |
mov esi, [eax+HDLL.fd] |
.scan_hdll: |
cmp esi, eax |
jz .fail |
mov edx, ebx |
sub edx, [esi+HDLL.base] |
cmp edx, [esi+HDLL.size] |
jb .fault_in_hdll |
.scan_hdll.next: |
mov esi, [esi+HDLL.fd] |
jmp .scan_hdll |
.fault_in_hdll: |
; allocate new page, map it as rw and copy data |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page,ebx,eax,PG_UW |
mov edi, ebx |
mov ecx, 1024 |
sub ebx, [esi+HDLL.base] |
mov esi, [esi+HDLL.parent] |
mov esi, [esi+DLLDESCR.data] |
add esi, ebx |
rep movsd |
jmp .exit |
.kernel_space: |
test eax, PG_MAP |
jz .fail ;ñòðàíèöà íå ïðèñóòñòâóåò |
test eax,12 ;U/S (+below) |
jnz .fail ;ïðèëîæåíèå îáðàòèëîñü ê ïàìÿòè |
;ÿäðà |
;test eax, 8 |
;jnz .fail ;óñòàíîâëåí çàðåçåðâèðîâàííûé áèò |
;â òàáëèöàõ ñòðàíèö. äîáàâëåíî â P4/Xeon |
;ïîïûòêà çàïèñè â çàùèù¸ííóþ ñòðàíèöó ÿäðà |
cmp ebx, tss._io_map_0 |
jb .fail |
cmp ebx, tss._io_map_0+8192 |
jae .fail |
; io permission map |
; copy-on-write protection |
call alloc_page |
test eax, eax |
jz .fail |
push eax |
stdcall map_page,[.err_addr],eax,dword PG_SW |
pop eax |
mov edi, [.err_addr] |
and edi, -4096 |
lea esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0 |
mov ebx, esi |
shr ebx, 12 |
mov edx, [current_slot] |
or eax, PG_SW |
mov [edx+APPDATA.io_map+ebx*4], eax |
add esi, [default_io_map] |
mov ecx, 4096/4 |
;cld ;caller is duty for this |
rep movsd |
jmp .exit |
endp |
; returns number of mapped bytes |
proc map_mem stdcall, lin_addr:dword,slot:dword,\ |
ofs:dword,buf_size:dword,req_access:dword |
push 0 ; initialize number of mapped bytes |
cmp [buf_size], 0 |
jz .exit |
mov eax, [slot] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dir_table] |
and eax, 0xFFFFF000 |
stdcall map_page,[ipc_pdir],eax,PG_UW |
mov ebx, [ofs] |
shr ebx, 22 |
mov esi, [ipc_pdir] |
mov edi, [ipc_ptab] |
mov eax, [esi+ebx*4] |
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 |
@@: mov edi, [lin_addr] |
and edi, 0xFFFFF000 |
mov ecx, [buf_size] |
add ecx, 4095 |
shr ecx, 12 |
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 |
dec ecx |
jz .exit |
add edi, 0x1000 |
inc edx |
cmp edx, 0x400 |
jnz .map |
inc ebx |
mov eax, [ipc_pdir] |
mov eax, [eax+ebx*4] |
and eax, 0xFFFFF000 |
jz .exit |
stdcall map_page,esi,eax,PG_UW |
xor edx, edx |
jmp .map |
.exit: |
pop eax |
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 |
cmp [buf_size], 0 |
jz .exit |
mov eax, [slot] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dir_table] |
and eax, 0xFFFFF000 |
stdcall map_page,[proc_mem_pdir],eax,PG_UW |
mov ebx, [ofs] |
shr ebx, 22 |
mov esi, [proc_mem_pdir] |
mov edi, [proc_mem_tab] |
mov eax, [esi+ebx*4] |
and eax, 0xFFFFF000 |
test eax, eax |
jz .exit |
stdcall map_page,edi,eax,PG_UW |
@@: mov edi, [lin_addr] |
and edi, 0xFFFFF000 |
mov ecx, [buf_size] |
add ecx, 4095 |
shr ecx, 12 |
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 |
inc edx |
dec ecx |
jnz .map |
.exit: |
pop eax |
ret |
endp |
; in: esi+edx*4 = pointer to page table entry |
; in: [slot], [req_access], [ofs] on the stack |
; in: edi = linear address to map |
; out: CF cleared <=> failed |
; destroys: only eax |
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword |
mov eax, [esi+edx*4] |
test al, PG_MAP |
jz .not_present |
test al, PG_WRITE |
jz .resolve_readonly |
; normal case: writable page, just map with requested access |
.map: |
stdcall map_page, edi, eax, [req_access] |
stc |
.fail: |
ret |
.not_present: |
; check for alloc-on-demand page |
test al, 2 |
jz .fail |
; allocate new page, save it to source page table |
push ecx |
call alloc_page |
pop ecx |
test eax, eax |
jz .fail |
or al, PG_UW |
mov [esi+edx*4], eax |
jmp .map |
.resolve_readonly: |
; readonly page, probably copy-on-write |
; check: readonly request of readonly page is ok |
test [req_access], PG_WRITE |
jz .map |
; find control structure for this page |
pushf |
cli |
cld |
push ebx ecx |
mov eax, [slot] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] |
test eax, eax |
jz .no_hdll |
mov ecx, [eax+HDLL.fd] |
.scan_hdll: |
cmp ecx, eax |
jz .no_hdll |
mov ebx, [ofs] |
and ebx, not 0xFFF |
sub ebx, [ecx+HDLL.base] |
cmp ebx, [ecx+HDLL.size] |
jb .hdll_found |
mov ecx, [ecx+HDLL.fd] |
jmp .scan_hdll |
.no_hdll: |
pop ecx ebx |
popf |
clc |
ret |
.hdll_found: |
; allocate page, save it in page table, map it, copy contents from base |
mov eax, [ecx+HDLL.parent] |
add ebx, [eax+DLLDESCR.data] |
call alloc_page |
test eax, eax |
jz .no_hdll |
or al, PG_UW |
mov [esi+edx*4], eax |
stdcall map_page, edi, eax, [req_access] |
push esi edi |
mov esi, ebx |
mov ecx, 4096/4 |
rep movsd |
pop edi esi |
pop ecx ebx |
popf |
stc |
ret |
endp |
sys_IPC: |
;input: |
; ebx=1 - set ipc buffer area |
; ecx=address of buffer |
; edx=size of buffer |
; eax=2 - send message |
; ebx=PID |
; ecx=address of message |
; edx=size of message |
dec ebx |
jnz @f |
mov eax,[current_slot] |
pushf |
cli |
mov [eax+APPDATA.ipc_start],ecx ;set fields in extended information area |
mov [eax+APPDATA.ipc_size],edx |
add edx, ecx |
add edx, 4095 |
and edx, not 4095 |
.touch: mov eax, [ecx] |
add ecx, 0x1000 |
cmp ecx, edx |
jb .touch |
popf |
mov [esp+32], ebx ;ebx=0 |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;2 |
@@: |
dec ebx |
jnz @f |
stdcall sys_ipc_send, ecx, edx, esi |
mov [esp+32], eax |
ret |
@@: |
or eax,-1 |
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 ? |
dst_offset dd ? |
buf_size dd ? |
used_buf dd ? |
endl |
pushf |
cli |
mov eax, [PID] |
call pid_to_slot |
test eax,eax |
jz .no_pid |
mov [dst_slot], eax |
shl eax,8 |
mov edi,[eax+SLOT_BASE+0xa0] ;is ipc area defined? |
test edi,edi |
jz .no_ipc_area |
mov ebx, edi |
and ebx, 0xFFF |
mov [dst_offset], ebx |
mov esi, [eax+SLOT_BASE+0xa4] |
mov [buf_size], esi |
mov ecx, [ipc_tmp] |
cmp esi, 0x40000-0x1000 ; size of [ipc_tmp] minus one page |
jbe @f |
push esi edi |
add esi,0x1000 |
stdcall alloc_kernel_space,esi |
mov ecx, eax |
pop edi esi |
@@: |
mov [used_buf], ecx |
stdcall map_mem, ecx, [dst_slot],\ |
edi, esi, PG_SW |
mov edi, [dst_offset] |
add edi, [used_buf] |
cmp dword [edi], 0 |
jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now |
mov edx, dword [edi+4] |
lea ebx, [edx+8] |
add ebx, [msg_size] |
cmp ebx, [buf_size] |
ja .buffer_overflow ;esi<0 - not enough memory in buffer |
mov dword [edi+4], ebx |
mov eax,[TASK_BASE] |
mov eax, [eax+0x04] ;eax - our PID |
add edi, edx |
mov [edi], eax |
mov ecx, [msg_size] |
mov [edi+4], ecx |
add edi, 8 |
mov esi, [msg_addr] |
; add esi, new_app_base |
cld |
rep movsb |
mov ebx, [ipc_tmp] |
mov edx, ebx |
shr ebx, 12 |
xor eax, eax |
mov [page_tabs+ebx*4], eax |
invlpg [edx] |
mov ebx, [ipc_pdir] |
mov edx, ebx |
shr ebx, 12 |
xor eax, eax |
mov [page_tabs+ebx*4], eax |
invlpg [edx] |
mov ebx, [ipc_ptab] |
mov edx, ebx |
shr ebx, 12 |
xor eax, eax |
mov [page_tabs+ebx*4], eax |
invlpg [edx] |
mov eax, [dst_slot] |
shl eax, 8 |
or [eax+SLOT_BASE+0xA8],dword 0x40 |
cmp dword [check_idle_semaphore],20 |
jge .ipc_no_cis |
mov dword [check_idle_semaphore],5 |
.ipc_no_cis: |
push 0 |
jmp .ret |
.no_pid: |
popf |
mov eax, 4 |
ret |
.no_ipc_area: |
popf |
xor eax, eax |
inc eax |
ret |
.ipc_blocked: |
push 2 |
jmp .ret |
.buffer_overflow: |
push 3 |
.ret: |
mov eax, [used_buf] |
cmp eax, [ipc_tmp] |
jz @f |
stdcall free_kernel_space,eax |
@@: |
pop eax |
popf |
ret |
endp |
align 4 |
sysfn_meminfo: |
; add ecx, new_app_base |
cmp ecx, OS_BASE |
jae .fail |
mov eax, [pg_data.pages_count] |
mov [ecx], eax |
shl eax, 12 |
mov [esp+32], eax |
mov eax, [pg_data.pages_free] |
mov [ecx+4], eax |
mov eax, [pg_data.pages_faults] |
mov [ecx+8], eax |
mov eax, [heap_size] |
mov [ecx+12], eax |
mov eax, [heap_free] |
mov [ecx+16], eax |
mov eax, [heap_blocks] |
mov [ecx+20], eax |
mov eax, [free_blocks] |
mov [ecx+24], eax |
ret |
.fail: |
or dword [esp+32], -1 |
ret |
align 4 |
f68: |
cmp ebx,4 |
jbe sys_sheduler |
cmp ebx, 11 |
jb .fail |
cmp ebx, 25 |
ja .fail |
jmp dword [f68call+ebx*4-11*4] |
.11: |
call init_heap |
mov [esp+32], eax |
ret |
.12: |
stdcall user_alloc, ecx |
mov [esp+32], eax |
ret |
.13: |
stdcall user_free, ecx |
mov [esp+32], eax |
ret |
.14: |
cmp ecx, OS_BASE |
jae .fail |
mov edi,ecx |
call get_event_ex |
mov [esp+32], eax |
ret |
.16: |
test ecx, ecx |
jz .fail |
cmp ecx, OS_BASE |
jae .fail |
stdcall get_service, ecx |
mov [esp+32], eax |
ret |
.17: |
call srv_handlerEx ;ecx |
mov [esp+32], eax |
ret |
.19: |
cmp ecx, OS_BASE |
jae .fail |
stdcall load_library, ecx |
mov [esp+32], eax |
ret |
.20: |
mov eax, edx |
mov ebx, ecx |
call user_realloc ;in: eax = pointer, ebx = new size |
mov [esp+32], eax |
ret |
.21: |
cmp ecx, OS_BASE |
jae .fail |
cmp ebx, OS_BASE |
jae .fail |
mov edi, edx |
stdcall load_PE, ecx |
mov esi, eax |
test eax, eax |
jz @F |
push edi |
push DRV_ENTRY |
call eax |
add esp, 8 |
test eax, eax |
jz @F |
mov [eax+SRV.entry], esi |
@@: |
mov [esp+32], eax |
ret |
.22: |
cmp ecx, OS_BASE |
jae .fail |
stdcall shmem_open, ecx, edx, esi |
mov [esp+24], edx |
mov [esp+32], eax |
ret |
.23: |
cmp ecx, OS_BASE |
jae .fail |
stdcall shmem_close, ecx |
mov [esp+32], eax |
ret |
.24: |
mov eax, [current_slot] |
xchg ecx, [eax+APPDATA.exc_handler] |
xchg edx, [eax+APPDATA.except_mask] |
mov [esp+32], ecx ; reg_eax+8 |
mov [esp+20], edx ; reg_ebx+8 |
ret |
.25: |
cmp ecx,32 |
jae .fail |
mov eax, [current_slot] |
btr [eax+APPDATA.except_mask],ecx |
setc byte[esp+32] |
jecxz @f |
bts [eax+APPDATA.except_mask],ecx |
@@: |
ret |
.fail: |
xor eax, eax |
mov [esp+32], eax |
ret |
align 4 |
f68call: ; keep this table closer to main code |
dd f68.11 ; init_heap |
dd f68.12 ; user_alloc |
dd f68.13 ; user_free |
dd f68.14 ; get_event_ex |
dd f68.fail ; moved to f68.24 |
dd f68.16 ; get_service |
dd f68.17 ; call_service |
dd f68.fail ; moved to f68.25 |
dd f68.19 ; load_dll |
dd f68.20 ; user_realloc |
dd f68.21 ; load_driver |
dd f68.22 ; shmem_open |
dd f68.23 ; shmem_close |
dd f68.24 |
dd f68.25 |
align 4 |
proc load_pe_driver stdcall, file:dword |
stdcall load_PE, [file] |
test eax, eax |
jz .fail |
mov esi, eax |
stdcall eax, DRV_ENTRY |
test eax, eax |
jz .fail |
mov [eax+SRV.entry], esi |
ret |
.fail: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_mtrr |
cmp [BOOT_VAR+0x901c],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 |
@@: |
wrmsr |
inc ecx |
cmp ecx, 0x210 |
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 stall stdcall, delay:dword |
push ecx |
push edx |
push ebx |
push eax |
mov eax, [delay] |
mul [stall_mcs] |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx,edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
jb @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
align 4 |
proc create_ring_buffer stdcall, size:dword, flags:dword |
locals |
buf_ptr dd ? |
endl |
mov eax, [size] |
test eax, eax |
jz .fail |
add eax, eax |
stdcall alloc_kernel_space, eax |
test eax, eax |
jz .fail |
push ebx |
mov [buf_ptr], eax |
mov ebx, [size] |
shr ebx, 12 |
push ebx |
stdcall alloc_pages, ebx |
pop ecx |
test eax, eax |
jz .mm_fail |
push edi |
or eax, [flags] |
mov edi, [buf_ptr] |
mov ebx, [buf_ptr] |
mov edx, ecx |
shl edx, 2 |
shr edi, 10 |
@@: |
mov [page_tabs+edi], eax |
mov [page_tabs+edi+edx], eax |
invlpg [ebx] |
invlpg [ebx+0x10000] |
add eax, 0x1000 |
add ebx, 0x1000 |
add edi, 4 |
dec ecx |
jnz @B |
mov eax, [buf_ptr] |
pop edi |
pop ebx |
ret |
.mm_fail: |
stdcall free_kernel_space, [buf_ptr] |
xor eax, eax |
pop ebx |
.fail: |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
align 4 |
proc alloc_page |
pushfd |
cli |
push ebx |
;//- |
cmp [pg_data.pages_free], 1 |
jle .out_of_memory |
;//- |
mov ebx, [page_start] |
mov ecx, [page_end] |
.l1: |
bsf eax, [ebx]; |
jnz .found |
add ebx, 4 |
cmp ebx, ecx |
jb .l1 |
pop ebx |
popfd |
xor eax, eax |
ret |
.found: |
;//- |
dec [pg_data.pages_free] |
jz .out_of_memory |
;//- |
btr [ebx], eax |
mov [page_start], ebx |
sub ebx, sys_pgmap |
lea eax, [eax+ebx*8] |
shl eax, 12 |
;//- dec [pg_data.pages_free] |
pop ebx |
popfd |
ret |
;//- |
.out_of_memory: |
mov [pg_data.pages_free], 1 |
xor eax, eax |
pop ebx |
popfd |
ret |
;//- |
endp |
align 4 |
proc alloc_pages stdcall, count:dword |
pushfd |
push ebx |
push edi |
cli |
mov eax, [count] |
add eax, 7 |
shr eax, 3 |
mov [count], eax |
;//- |
mov ebx, [pg_data.pages_free] |
sub ebx, 9 |
js .out_of_memory |
shr ebx, 3 |
cmp eax, ebx |
jg .out_of_memory |
;//- |
mov ecx, [page_start] |
mov ebx, [page_end] |
.find: |
mov edx, [count] |
mov edi, ecx |
.match: |
cmp byte [ecx], 0xFF |
jne .next |
dec edx |
jz .ok |
inc ecx |
cmp ecx, ebx |
jb .match |
.out_of_memory: |
.fail: |
xor eax, eax |
pop edi |
pop ebx |
popfd |
ret |
.next: |
inc ecx |
cmp ecx, ebx |
jb .find |
pop edi |
pop ebx |
popfd |
xor eax, eax |
ret |
.ok: |
sub ecx, edi |
inc ecx |
push esi |
mov esi, edi |
xor eax, eax |
rep stosb |
sub esi, sys_pgmap |
shl esi, 3+12 |
mov eax, esi |
mov ebx, [count] |
shl ebx, 3 |
sub [pg_data.pages_free], ebx |
pop esi |
pop edi |
pop ebx |
popfd |
ret |
endp |
align 4 |
proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword |
push ebx |
mov eax, [phis_addr] |
and eax, not 0xFFF |
or eax, [flags] |
mov ebx, [lin_addr] |
shr ebx, 12 |
mov [page_tabs+ebx*4], eax |
mov eax, [lin_addr] |
invlpg [eax] |
pop ebx |
ret |
endp |
align 4 |
map_space: ;not implemented |
ret |
align 4 |
proc free_page |
;arg: eax page address |
pushfd |
cli |
shr eax, 12 ;page index |
bts dword [sys_pgmap], eax ;that's all! |
cmc |
adc [pg_data.pages_free], 0 |
shr eax, 3 |
and eax, not 3 ;dword offset from page_map |
add eax, sys_pgmap |
cmp [page_start], eax |
ja @f |
popfd |
ret |
@@: |
mov [page_start], eax |
popfd |
ret |
endp |
proc map_io_mem stdcall, base:dword, size:dword, flags:dword |
push ebx |
push edi |
mov eax, [size] |
add eax, [base] |
add eax, 4095 |
and eax, -4096 |
mov ecx, [base] |
and ecx, -4096 |
sub eax, ecx |
mov [size], eax |
stdcall alloc_kernel_space, eax |
test eax, eax |
jz .fail |
push eax |
mov edi, 0x1000 |
mov ebx, eax |
mov ecx, [size] |
mov edx, [base] |
shr eax, 12 |
shr ecx, 12 |
and edx, -4096 |
or edx, [flags] |
@@: |
mov [page_tabs+eax*4], edx |
invlpg [ebx] |
inc eax |
add ebx, edi |
add edx, edi |
loop @B |
pop eax |
mov edx, [base] |
and edx, 4095 |
add eax, edx |
.fail: |
pop edi |
pop ebx |
ret |
endp |
; param |
; eax= page base + page flags |
; ebx= linear address |
; ecx= count |
align 4 |
commit_pages: |
test ecx, ecx |
jz .fail |
push edi |
push eax |
push ecx |
mov ecx, pg_data.mutex |
call mutex_lock |
pop ecx |
pop eax |
mov edi, ebx |
shr edi, 12 |
lea edi, [page_tabs+edi*4] |
@@: |
stosd |
invlpg [ebx] |
add eax, 0x1000 |
add ebx, 0x1000 |
loop @B |
pop edi |
mov ecx, pg_data.mutex |
call mutex_unlock |
.fail: |
ret |
; param |
; eax= base |
; ecx= count |
align 4 |
release_pages: |
push ebp |
push esi |
push edi |
push ebx |
mov esi, eax |
mov edi, eax |
shr esi, 12 |
lea esi, [page_tabs+esi*4] |
push ecx |
mov ecx, pg_data.mutex |
call mutex_lock |
pop ecx |
mov ebp, [pg_data.pages_free] |
mov ebx, [page_start] |
mov edx, sys_pgmap |
@@: |
xor eax, eax |
xchg eax, [esi] |
invlpg [edi] |
test eax, 1 |
jz .next |
shr eax, 12 |
bts [edx], eax |
cmc |
adc ebp, 0 |
shr eax, 3 |
and eax, -4 |
add eax, edx |
cmp eax, ebx |
jae .next |
mov ebx, eax |
.next: |
add edi, 0x1000 |
add esi, 4 |
loop @B |
mov [pg_data.pages_free], ebp |
mov ecx, pg_data.mutex |
call mutex_unlock |
pop ebx |
pop edi |
pop esi |
pop ebp |
ret |
; param |
; eax= base |
; ecx= count |
align 4 |
unmap_pages: |
push edi |
mov edi, eax |
mov edx, eax |
shr edi, 10 |
add edi, page_tabs |
xor eax, eax |
@@: |
stosd |
invlpg [edx] |
add edx, 0x1000 |
loop @b |
pop edi |
ret |
align 4 |
proc map_page_table stdcall, lin_addr:dword, phis_addr:dword |
push ebx |
mov ebx, [lin_addr] |
shr ebx, 22 |
mov eax, [phis_addr] |
and eax, not 0xFFF |
or eax, PG_UW ;+PG_NOCACHE |
mov dword [master_tab+ebx*4], eax |
mov eax, [lin_addr] |
shr eax, 10 |
add eax, page_tabs |
invlpg [eax] |
pop ebx |
ret |
endp |
align 4 |
proc init_LFB |
locals |
pg_count dd ? |
endl |
cmp dword [LFBAddress], -1 |
jne @f |
mov [BOOT_VAR+0x901c], byte 2 |
stdcall alloc_pages, (0x280000 / 4096) |
push eax |
call alloc_page |
stdcall map_page_table, LFB_BASE, eax |
pop eax |
or eax, PG_UW |
mov ebx, LFB_BASE |
mov ecx, 0x280000 / 4096 |
call commit_pages |
mov [LFBAddress], dword LFB_BASE |
ret |
@@: |
test [SCR_MODE], word 0100000000000000b |
jnz @f |
mov [BOOT_VAR+0x901c], byte 2 |
ret |
@@: |
call init_mtrr |
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_pgdir+(LFB_BASE shr 20) |
@@: |
mov [edx], esi |
add edx, 4 |
add esi, 0x00400000 |
dec edi |
jnz @B |
bt [cpu_caps], CAPS_PGE |
jnc @F |
or dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL |
@@: |
mov dword [LFBAddress], LFB_BASE |
mov eax, cr3 ;flush TLB |
mov cr3, eax |
ret |
.map_page_tables: |
@@: |
call alloc_page |
stdcall map_page_table, edx, eax |
add edx, 0x00400000 |
dec edi |
jnz @B |
mov eax, [LFBAddress] |
mov edi, page_tabs + (LFB_BASE shr 10) |
or eax, PG_UW |
mov ecx, [pg_count] |
cld |
@@: |
stosd |
add eax, 0x1000 |
dec ecx |
jnz @B |
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 |
mov ecx, pg_data.mutex |
call mutex_lock |
mov edi, [new_size] |
add edi, 4095 |
and edi, not 4095 |
mov [new_size], edi |
mov edx, [current_slot] |
cmp [edx+APPDATA.heap_base], 0 |
jne .exit |
mov esi, [edx+APPDATA.mem_size] |
add esi, 4095 |
and esi, not 4095 |
cmp edi, esi |
jae .expand |
shr edi, 12 |
shr esi, 12 |
@@: |
mov eax, [app_page_tabs+edi*4] |
test eax, 1 |
jz .next |
mov dword [app_page_tabs+edi*4], 2 |
mov ebx, edi |
shl ebx, 12 |
push eax |
invlpg [ebx] |
pop eax |
call free_page |
.next: |
add edi, 1 |
cmp edi, esi |
jb @B |
.update_size: |
mov ebx, [new_size] |
call update_mem_size |
mov ecx, pg_data.mutex |
call mutex_unlock |
xor eax, eax |
ret |
.expand: |
push esi |
push edi |
add edi, 0x3FFFFF |
and edi, not(0x3FFFFF) |
add esi, 0x3FFFFF |
and esi, not(0x3FFFFF) |
cmp esi, edi |
jae .grow |
xchg esi, edi |
@@: |
call alloc_page |
test eax, eax |
jz .exit_pop |
stdcall map_page_table, edi, eax |
push edi |
shr edi, 10 |
add edi, page_tabs |
mov ecx, 1024 |
xor eax, eax |
cld |
rep stosd |
pop edi |
add edi, 0x00400000 |
cmp edi, esi |
jb @B |
.grow: |
;//- |
pop edi |
push edi |
mov esi, [pg_data.pages_free] |
sub esi, 1 |
shr edi, 12 |
cmp esi, edi |
jle .out_of_memory |
;//- |
pop edi |
pop esi |
@@: |
call alloc_page |
test eax, eax |
jz .exit |
stdcall map_page, esi, eax, dword PG_UW |
push edi |
mov edi, esi |
xor eax, eax |
mov ecx, 1024 |
cld |
rep stosd |
pop edi |
add esi, 0x1000 |
cmp esi, edi |
jb @B |
jmp .update_size |
;//- |
.exit_pop: |
.out_of_memory: |
;//- |
pop edi |
pop esi |
.exit: |
mov ecx, pg_data.mutex |
call mutex_unlock |
xor eax, eax |
inc eax |
ret |
endp |
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 |
; |
; retval |
; eax= phisical page address |
align 4 |
get_pg_addr: |
shr eax, 12 |
mov eax, [page_tabs+eax*4] |
and eax, 0xFFFFF000 |
ret |
align 4 |
; Now it is called from core/sys32::exc_c (see stack frame there) |
proc page_fault_handler |
.err_addr equ ebp-4 |
push ebx ;save exception number (#PF) |
mov ebp, esp |
mov ebx, cr2 |
push ebx ;that is locals: .err_addr = cr2 |
inc [pg_data.pages_faults] |
mov eax, [pf_err_code] |
cmp ebx, OS_BASE ;ebx == .err_addr |
jb .user_space ;ñòðàíèöà â ïàìÿòè ïðèëîæåíèÿ ; |
cmp ebx, page_tabs |
jb .kernel_space ;ñòðàíèöà â ïàìÿòè ÿäðà |
cmp ebx, kernel_tabs |
jb .alloc;.app_tabs ;òàáëèöû ñòðàíèö ïðèëîæåíèÿ ; |
;ïðîñòî ñîçäàäèì îäíó |
if 0 ;ïîêà ýòî ïðîñòî ëèøíåå |
cmp ebx, LFB_BASE |
jb .core_tabs ;òàáëèöû ñòðàíèö ÿäðà |
;Îøèáêà |
.lfb: |
;îáëàñòü LFB |
;Îøèáêà |
jmp .fail |
end if |
.core_tabs: |
.fail: ;simply return to caller |
mov esp, ebp |
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 ;Ñòðàíèöà ïðèñóòñòâóåò |
;Îøèáêà äîñòóïà ? |
shr ebx, 12 |
mov ecx, ebx |
shr ecx, 10 |
mov edx, [master_tab+ecx*4] |
test edx, PG_MAP |
jz .fail ;òàáëèöà ñòðàíèö íå ñîçäàíà |
;íåâåðíûé àäðåñ â ïðîãðàììå |
mov eax, [page_tabs+ebx*4] |
test eax, 2 |
jz .fail ;àäðåñ íå çàðåçåðâèðîâàí äëÿ ; |
;èñïîëüçîâàíèÿ. Îøèáêà |
.alloc: |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page, [.err_addr], eax, PG_UW |
mov edi, [.err_addr] |
and edi, 0xFFFFF000 |
mov ecx, 1024 |
xor eax, eax |
;cld ;caller is duty for this |
rep stosd |
.exit: ;iret with repeat fault instruction |
add esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller |
restore_ring3_context |
iretd |
.err_access: |
; 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] |
test eax, eax |
jz .fail |
mov esi, [eax+HDLL.fd] |
.scan_hdll: |
cmp esi, eax |
jz .fail |
mov edx, ebx |
sub edx, [esi+HDLL.base] |
cmp edx, [esi+HDLL.size] |
jb .fault_in_hdll |
.scan_hdll.next: |
mov esi, [esi+HDLL.fd] |
jmp .scan_hdll |
.fault_in_hdll: |
; allocate new page, map it as rw and copy data |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page, ebx, eax, PG_UW |
mov edi, ebx |
mov ecx, 1024 |
sub ebx, [esi+HDLL.base] |
mov esi, [esi+HDLL.parent] |
mov esi, [esi+DLLDESCR.data] |
add esi, ebx |
rep movsd |
jmp .exit |
.kernel_space: |
test eax, PG_MAP |
jz .fail ;ñòðàíèöà íå ïðèñóòñòâóåò |
test eax, 12 ;U/S (+below) |
jnz .fail ;ïðèëîæåíèå îáðàòèëîñü ê ïàìÿòè |
;ÿäðà |
;test eax, 8 |
;jnz .fail ;óñòàíîâëåí çàðåçåðâèðîâàííûé áèò |
;â òàáëèöàõ ñòðàíèö. äîáàâëåíî â P4/Xeon |
;ïîïûòêà çàïèñè â çàùèù¸ííóþ ñòðàíèöó ÿäðà |
cmp ebx, tss._io_map_0 |
jb .fail |
cmp ebx, tss._io_map_0+8192 |
jae .fail |
; io permission map |
; copy-on-write protection |
call alloc_page |
test eax, eax |
jz .fail |
push eax |
stdcall map_page, [.err_addr], eax, dword PG_SW |
pop eax |
mov edi, [.err_addr] |
and edi, -4096 |
lea esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0 |
mov ebx, esi |
shr ebx, 12 |
mov edx, [current_slot] |
or eax, PG_SW |
mov [edx+APPDATA.io_map+ebx*4], eax |
add esi, [default_io_map] |
mov ecx, 4096/4 |
;cld ;caller is duty for this |
rep movsd |
jmp .exit |
endp |
; returns number of mapped bytes |
proc map_mem stdcall, lin_addr:dword,slot:dword,\ |
ofs:dword,buf_size:dword,req_access:dword |
push 0 ; initialize number of mapped bytes |
cmp [buf_size], 0 |
jz .exit |
mov eax, [slot] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dir_table] |
and eax, 0xFFFFF000 |
stdcall map_page, [ipc_pdir], eax, PG_UW |
mov ebx, [ofs] |
shr ebx, 22 |
mov esi, [ipc_pdir] |
mov edi, [ipc_ptab] |
mov eax, [esi+ebx*4] |
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 |
@@: |
mov edi, [lin_addr] |
and edi, 0xFFFFF000 |
mov ecx, [buf_size] |
add ecx, 4095 |
shr ecx, 12 |
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 |
dec ecx |
jz .exit |
add edi, 0x1000 |
inc edx |
cmp edx, 0x400 |
jnz .map |
inc ebx |
mov eax, [ipc_pdir] |
mov eax, [eax+ebx*4] |
and eax, 0xFFFFF000 |
jz .exit |
stdcall map_page, esi, eax, PG_UW |
xor edx, edx |
jmp .map |
.exit: |
pop eax |
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 |
cmp [buf_size], 0 |
jz .exit |
mov eax, [slot] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dir_table] |
and eax, 0xFFFFF000 |
stdcall map_page, [proc_mem_pdir], eax, PG_UW |
mov ebx, [ofs] |
shr ebx, 22 |
mov esi, [proc_mem_pdir] |
mov edi, [proc_mem_tab] |
mov eax, [esi+ebx*4] |
and eax, 0xFFFFF000 |
test eax, eax |
jz .exit |
stdcall map_page, edi, eax, PG_UW |
@@: |
mov edi, [lin_addr] |
and edi, 0xFFFFF000 |
mov ecx, [buf_size] |
add ecx, 4095 |
shr ecx, 12 |
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 |
inc edx |
dec ecx |
jnz .map |
.exit: |
pop eax |
ret |
endp |
; in: esi+edx*4 = pointer to page table entry |
; in: [slot], [req_access], [ofs] on the stack |
; in: edi = linear address to map |
; out: CF cleared <=> failed |
; destroys: only eax |
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword |
mov eax, [esi+edx*4] |
test al, PG_MAP |
jz .not_present |
test al, PG_WRITE |
jz .resolve_readonly |
; normal case: writable page, just map with requested access |
.map: |
stdcall map_page, edi, eax, [req_access] |
stc |
.fail: |
ret |
.not_present: |
; check for alloc-on-demand page |
test al, 2 |
jz .fail |
; allocate new page, save it to source page table |
push ecx |
call alloc_page |
pop ecx |
test eax, eax |
jz .fail |
or al, PG_UW |
mov [esi+edx*4], eax |
jmp .map |
.resolve_readonly: |
; readonly page, probably copy-on-write |
; check: readonly request of readonly page is ok |
test [req_access], PG_WRITE |
jz .map |
; find control structure for this page |
pushf |
cli |
cld |
push ebx ecx |
mov eax, [slot] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] |
test eax, eax |
jz .no_hdll |
mov ecx, [eax+HDLL.fd] |
.scan_hdll: |
cmp ecx, eax |
jz .no_hdll |
mov ebx, [ofs] |
and ebx, not 0xFFF |
sub ebx, [ecx+HDLL.base] |
cmp ebx, [ecx+HDLL.size] |
jb .hdll_found |
mov ecx, [ecx+HDLL.fd] |
jmp .scan_hdll |
.no_hdll: |
pop ecx ebx |
popf |
clc |
ret |
.hdll_found: |
; allocate page, save it in page table, map it, copy contents from base |
mov eax, [ecx+HDLL.parent] |
add ebx, [eax+DLLDESCR.data] |
call alloc_page |
test eax, eax |
jz .no_hdll |
or al, PG_UW |
mov [esi+edx*4], eax |
stdcall map_page, edi, eax, [req_access] |
push esi edi |
mov esi, ebx |
mov ecx, 4096/4 |
rep movsd |
pop edi esi |
pop ecx ebx |
popf |
stc |
ret |
endp |
sys_IPC: |
;input: |
; ebx=1 - set ipc buffer area |
; ecx=address of buffer |
; edx=size of buffer |
; eax=2 - send message |
; ebx=PID |
; ecx=address of message |
; edx=size of message |
dec ebx |
jnz @f |
mov eax, [current_slot] |
pushf |
cli |
mov [eax+APPDATA.ipc_start], ecx ;set fields in extended information area |
mov [eax+APPDATA.ipc_size], edx |
add edx, ecx |
add edx, 4095 |
and edx, not 4095 |
.touch: |
mov eax, [ecx] |
add ecx, 0x1000 |
cmp ecx, edx |
jb .touch |
popf |
mov [esp+32], ebx ;ebx=0 |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;2 |
@@: |
dec ebx |
jnz @f |
stdcall sys_ipc_send, ecx, edx, esi |
mov [esp+32], eax |
ret |
@@: |
or eax, -1 |
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 ? |
dst_offset dd ? |
buf_size dd ? |
used_buf dd ? |
endl |
pushf |
cli |
mov eax, [PID] |
call pid_to_slot |
test eax, eax |
jz .no_pid |
mov [dst_slot], eax |
shl eax, 8 |
mov edi, [eax+SLOT_BASE+0xa0] ;is ipc area defined? |
test edi, edi |
jz .no_ipc_area |
mov ebx, edi |
and ebx, 0xFFF |
mov [dst_offset], ebx |
mov esi, [eax+SLOT_BASE+0xa4] |
mov [buf_size], esi |
mov ecx, [ipc_tmp] |
cmp esi, 0x40000-0x1000; size of [ipc_tmp] minus one page |
jbe @f |
push esi edi |
add esi, 0x1000 |
stdcall alloc_kernel_space, esi |
mov ecx, eax |
pop edi esi |
@@: |
mov [used_buf], ecx |
stdcall map_mem, ecx, [dst_slot], \ |
edi, esi, PG_SW |
mov edi, [dst_offset] |
add edi, [used_buf] |
cmp dword [edi], 0 |
jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now |
mov edx, dword [edi+4] |
lea ebx, [edx+8] |
add ebx, [msg_size] |
cmp ebx, [buf_size] |
ja .buffer_overflow ;esi<0 - not enough memory in buffer |
mov dword [edi+4], ebx |
mov eax, [TASK_BASE] |
mov eax, [eax+0x04] ;eax - our PID |
add edi, edx |
mov [edi], eax |
mov ecx, [msg_size] |
mov [edi+4], ecx |
add edi, 8 |
mov esi, [msg_addr] |
; add esi, new_app_base |
cld |
rep movsb |
mov ebx, [ipc_tmp] |
mov edx, ebx |
shr ebx, 12 |
xor eax, eax |
mov [page_tabs+ebx*4], eax |
invlpg [edx] |
mov ebx, [ipc_pdir] |
mov edx, ebx |
shr ebx, 12 |
xor eax, eax |
mov [page_tabs+ebx*4], eax |
invlpg [edx] |
mov ebx, [ipc_ptab] |
mov edx, ebx |
shr ebx, 12 |
xor eax, eax |
mov [page_tabs+ebx*4], eax |
invlpg [edx] |
mov eax, [dst_slot] |
shl eax, 8 |
or [eax+SLOT_BASE+0xA8], dword 0x40 |
cmp dword [check_idle_semaphore], 20 |
jge .ipc_no_cis |
mov dword [check_idle_semaphore], 5 |
.ipc_no_cis: |
push 0 |
jmp .ret |
.no_pid: |
popf |
mov eax, 4 |
ret |
.no_ipc_area: |
popf |
xor eax, eax |
inc eax |
ret |
.ipc_blocked: |
push 2 |
jmp .ret |
.buffer_overflow: |
push 3 |
.ret: |
mov eax, [used_buf] |
cmp eax, [ipc_tmp] |
jz @f |
stdcall free_kernel_space, eax |
@@: |
pop eax |
popf |
ret |
endp |
align 4 |
sysfn_meminfo: |
; add ecx, new_app_base |
cmp ecx, OS_BASE |
jae .fail |
mov eax, [pg_data.pages_count] |
mov [ecx], eax |
shl eax, 12 |
mov [esp+32], eax |
mov eax, [pg_data.pages_free] |
mov [ecx+4], eax |
mov eax, [pg_data.pages_faults] |
mov [ecx+8], eax |
mov eax, [heap_size] |
mov [ecx+12], eax |
mov eax, [heap_free] |
mov [ecx+16], eax |
mov eax, [heap_blocks] |
mov [ecx+20], eax |
mov eax, [free_blocks] |
mov [ecx+24], eax |
ret |
.fail: |
or dword [esp+32], -1 |
ret |
align 4 |
f68: |
cmp ebx, 4 |
jbe sys_sheduler |
cmp ebx, 11 |
jb .fail |
cmp ebx, 25 |
ja .fail |
jmp dword [f68call+ebx*4-11*4] |
.11: |
call init_heap |
mov [esp+32], eax |
ret |
.12: |
stdcall user_alloc, ecx |
mov [esp+32], eax |
ret |
.13: |
stdcall user_free, ecx |
mov [esp+32], eax |
ret |
.14: |
cmp ecx, OS_BASE |
jae .fail |
mov edi, ecx |
call get_event_ex |
mov [esp+32], eax |
ret |
.16: |
test ecx, ecx |
jz .fail |
cmp ecx, OS_BASE |
jae .fail |
stdcall get_service, ecx |
mov [esp+32], eax |
ret |
.17: |
call srv_handlerEx ;ecx |
mov [esp+32], eax |
ret |
.19: |
cmp ecx, OS_BASE |
jae .fail |
stdcall load_library, ecx |
mov [esp+32], eax |
ret |
.20: |
mov eax, edx |
mov ebx, ecx |
call user_realloc ;in: eax = pointer, ebx = new size |
mov [esp+32], eax |
ret |
.21: |
cmp ecx, OS_BASE |
jae .fail |
cmp ebx, OS_BASE |
jae .fail |
mov edi, edx |
stdcall load_PE, ecx |
mov esi, eax |
test eax, eax |
jz @F |
push edi |
push DRV_ENTRY |
call eax |
add esp, 8 |
test eax, eax |
jz @F |
mov [eax+SRV.entry], esi |
@@: |
mov [esp+32], eax |
ret |
.22: |
cmp ecx, OS_BASE |
jae .fail |
stdcall shmem_open, ecx, edx, esi |
mov [esp+24], edx |
mov [esp+32], eax |
ret |
.23: |
cmp ecx, OS_BASE |
jae .fail |
stdcall shmem_close, ecx |
mov [esp+32], eax |
ret |
.24: |
mov eax, [current_slot] |
xchg ecx, [eax+APPDATA.exc_handler] |
xchg edx, [eax+APPDATA.except_mask] |
mov [esp+32], ecx ; reg_eax+8 |
mov [esp+20], edx ; reg_ebx+8 |
ret |
.25: |
cmp ecx, 32 |
jae .fail |
mov eax, [current_slot] |
btr [eax+APPDATA.except_mask], ecx |
setc byte[esp+32] |
jecxz @f |
bts [eax+APPDATA.except_mask], ecx |
@@: |
ret |
.fail: |
xor eax, eax |
mov [esp+32], eax |
ret |
align 4 |
f68call: ; keep this table closer to main code |
dd f68.11 ; init_heap |
dd f68.12 ; user_alloc |
dd f68.13 ; user_free |
dd f68.14 ; get_event_ex |
dd f68.fail ; moved to f68.24 |
dd f68.16 ; get_service |
dd f68.17 ; call_service |
dd f68.fail ; moved to f68.25 |
dd f68.19 ; load_dll |
dd f68.20 ; user_realloc |
dd f68.21 ; load_driver |
dd f68.22 ; shmem_open |
dd f68.23 ; shmem_close |
dd f68.24 |
dd f68.25 |
align 4 |
proc load_pe_driver stdcall, file:dword |
stdcall load_PE, [file] |
test eax, eax |
jz .fail |
mov esi, eax |
stdcall eax, DRV_ENTRY |
test eax, eax |
jz .fail |
mov [eax+SRV.entry], esi |
ret |
.fail: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_mtrr |
cmp [BOOT_VAR+0x901c], 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 |
@@: |
wrmsr |
inc ecx |
cmp ecx, 0x210 |
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 stall stdcall, delay:dword |
push ecx |
push edx |
push ebx |
push eax |
mov eax, [delay] |
mul [stall_mcs] |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
jb @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
align 4 |
proc create_ring_buffer stdcall, size:dword, flags:dword |
locals |
buf_ptr dd ? |
endl |
mov eax, [size] |
test eax, eax |
jz .fail |
add eax, eax |
stdcall alloc_kernel_space, eax |
test eax, eax |
jz .fail |
push ebx |
mov [buf_ptr], eax |
mov ebx, [size] |
shr ebx, 12 |
push ebx |
stdcall alloc_pages, ebx |
pop ecx |
test eax, eax |
jz .mm_fail |
push edi |
or eax, [flags] |
mov edi, [buf_ptr] |
mov ebx, [buf_ptr] |
mov edx, ecx |
shl edx, 2 |
shr edi, 10 |
@@: |
mov [page_tabs+edi], eax |
mov [page_tabs+edi+edx], eax |
invlpg [ebx] |
invlpg [ebx+0x10000] |
add eax, 0x1000 |
add ebx, 0x1000 |
add edi, 4 |
dec ecx |
jnz @B |
mov eax, [buf_ptr] |
pop edi |
pop ebx |
ret |
.mm_fail: |
stdcall free_kernel_space, [buf_ptr] |
xor eax, eax |
pop ebx |
.fail: |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/peload.inc |
---|
1,332 → 1,332 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
include 'export.inc' |
align 4 |
proc load_PE stdcall, file_name:dword |
locals |
image dd ? |
entry dd ? |
base dd ? |
endl |
stdcall load_file, [file_name] |
test eax, eax |
jz .fail |
mov [image], eax |
mov edx, [eax+60] |
stdcall kernel_alloc, [eax+80+edx] |
test eax, eax |
jz .cleanup |
mov [base], eax |
stdcall map_PE, eax, [image] |
mov [entry], eax |
test eax, eax |
jnz .cleanup |
stdcall kernel_free, [base] |
.cleanup: |
stdcall kernel_free, [image] |
mov eax, [entry] |
ret |
.fail: |
xor eax, eax |
ret |
endp |
DWORD equ dword |
PTR equ |
align 4 |
map_PE: ;stdcall base:dword, image:dword |
cld |
push ebp |
push edi |
push esi |
push ebx |
sub esp, 60 |
mov ebx, DWORD PTR [esp+84] |
mov ebp, DWORD PTR [esp+80] |
mov edx, ebx |
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] |
test eax, eax |
je L4 |
mov esi, ebx |
mov edi, ebp |
add esi, DWORD PTR [edx+268] |
mov ecx, eax |
add edi, DWORD PTR [edx+260] |
shr ecx, 2 |
rep movsd |
L4: |
mov ecx, DWORD PTR [edx+256] |
add ecx, 4095 |
and ecx, -4096 |
cmp ecx, eax |
jbe L6 |
sub ecx, eax |
add eax, DWORD PTR [edx+260] |
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 |
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+12], eax |
jmp L11 |
L12: |
lea ebx, [eax-8] |
xor edi, edi |
shr ebx,1 |
jmp L13 |
L14: |
movzx eax, WORD PTR [ecx+8+edi*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+12] |
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: |
mov eax, DWORD PTR [ecx+4] |
test eax, eax |
jne L12 |
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] |
mov DWORD PTR [esp+52], 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] |
test eax, eax |
je L27 |
test eax, eax |
js L27 |
lea edi, [ebp+eax] |
mov eax, DWORD PTR [esp+28] |
mov DWORD PTR [eax+esi*4], 0 |
lea esi, [edi+2] |
push eax |
push 32 |
movzx eax, WORD PTR [edi] |
mov edx, DWORD PTR [esp+56] |
mov eax, DWORD PTR [edx+eax*4] |
add eax, OS_BASE |
push eax |
push esi |
call strncmp |
pop ebx |
xor ebx, ebx |
test eax, eax |
jne L32 |
jmp L30 |
L33: |
push ecx |
push 32 |
mov ecx, DWORD PTR [esp+28] |
mov eax, DWORD PTR [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: |
inc ebx |
L32: |
cmp ebx, DWORD PTR [__exports+24] |
jb L33 |
L36: |
cmp ebx, DWORD PTR [__exports+24] |
jne L37 |
mov esi, msg_unresolved |
call sys_msg_board_str |
lea esi, [edi+2] |
call sys_msg_board_str |
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] |
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: |
xor eax, eax |
cmp DWORD PTR [esp+40], 0 |
jne L40 |
L20: |
mov ecx, DWORD PTR [esp+32] |
mov eax, ebp |
add eax, DWORD PTR [ecx+40] |
L40: |
add esp, 60 |
pop ebx |
pop esi |
pop edi |
pop ebp |
ret 8 |
align 16 |
__exports: |
export 'KERNEL', \ |
alloc_kernel_space, 'AllocKernelSpace', \ ; stdcall |
alloc_page, 'AllocPage', \ ; gcc ABI |
alloc_pages, 'AllocPages', \ ; stdcall |
commit_pages, 'CommitPages', \ ; eax, ebx, ecx |
\ |
create_event, 'CreateEvent', \ ; ecx, esi |
raise_event, 'RaiseEvent', \ ; eax, ebx, edx, esi |
wait_event, 'WaitEvent', \ ; eax, ebx |
get_event_ex, 'GetEvent', \ ; edi |
\ |
create_kernel_object, 'CreateObject', \ |
create_ring_buffer, 'CreateRingBuffer', \ ; stdcall |
destroy_kernel_object, 'DestroyObject', \ |
free_kernel_space, 'FreeKernelSpace', \ ; stdcall |
kernel_alloc, 'KernelAlloc', \ ; stdcall |
kernel_free, 'KernelFree', \ ; stdcall |
malloc, 'Kmalloc', \ |
free, 'Kfree', \ |
map_io_mem, 'MapIoMem', \ ; stdcall |
get_pg_addr, 'GetPgAddr', \ ; eax |
\ |
mutex_init, 'MutexInit', \ ; gcc fastcall |
mutex_lock, 'MutexLock', \ ; gcc fastcall |
mutex_unlock, 'MutexUnlock', \ ; gcc fastcall |
\ |
get_display, 'GetDisplay', \ |
set_screen, 'SetScreen', \ |
pci_api_drv, 'PciApi', \ |
pci_read8, 'PciRead8', \ ; stdcall |
pci_read16, 'PciRead16', \ ; stdcall |
pci_read32, 'PciRead32', \ ; stdcall |
pci_write8, 'PciWrite8', \ ; stdcall |
pci_write16, 'PciWrite16', \ ; stdcall |
pci_write32, 'PciWrite32', \ ; stdcall |
\ |
get_pid, 'GetPid', \ |
get_service, 'GetService', \ ; |
reg_service, 'RegService', \ ; stdcall |
attach_int_handler, 'AttachIntHandler', \ ; stdcall |
user_alloc, 'UserAlloc', \ ; stdcall |
user_free, 'UserFree', \ ; stdcall |
unmap_pages, 'UnmapPages', \ ; eax, ecx |
sys_msg_board_str, 'SysMsgBoardStr', \ |
get_timer_ticks, 'GetTimerTicks', \ |
get_stack_base, 'GetStackBase', \ |
delay_hs, 'Delay', \ ; ebx |
set_mouse_data, 'SetMouseData', \ ; |
set_keyboard_data, 'SetKeyboardData' ; gcc fastcall |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
include 'export.inc' |
align 4 |
proc load_PE stdcall, file_name:dword |
locals |
image dd ? |
entry dd ? |
base dd ? |
endl |
stdcall load_file, [file_name] |
test eax, eax |
jz .fail |
mov [image], eax |
mov edx, [eax+60] |
stdcall kernel_alloc, [eax+80+edx] |
test eax, eax |
jz .cleanup |
mov [base], eax |
stdcall map_PE, eax, [image] |
mov [entry], eax |
test eax, eax |
jnz .cleanup |
stdcall kernel_free, [base] |
.cleanup: |
stdcall kernel_free, [image] |
mov eax, [entry] |
ret |
.fail: |
xor eax, eax |
ret |
endp |
DWORD equ dword |
PTR equ |
align 4 |
map_PE: ;stdcall base:dword, image:dword |
cld |
push ebp |
push edi |
push esi |
push ebx |
sub esp, 60 |
mov ebx, DWORD PTR [esp+84] |
mov ebp, DWORD PTR [esp+80] |
mov edx, ebx |
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] |
test eax, eax |
je L4 |
mov esi, ebx |
mov edi, ebp |
add esi, DWORD PTR [edx+268] |
mov ecx, eax |
add edi, DWORD PTR [edx+260] |
shr ecx, 2 |
rep movsd |
L4: |
mov ecx, DWORD PTR [edx+256] |
add ecx, 4095 |
and ecx, -4096 |
cmp ecx, eax |
jbe L6 |
sub ecx, eax |
add eax, DWORD PTR [edx+260] |
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 |
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+12], eax |
jmp L11 |
L12: |
lea ebx, [eax-8] |
xor edi, edi |
shr ebx, 1 |
jmp L13 |
L14: |
movzx eax, WORD PTR [ecx+8+edi*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+12] |
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: |
mov eax, DWORD PTR [ecx+4] |
test eax, eax |
jne L12 |
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] |
mov DWORD PTR [esp+52], 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] |
test eax, eax |
je L27 |
test eax, eax |
js L27 |
lea edi, [ebp+eax] |
mov eax, DWORD PTR [esp+28] |
mov DWORD PTR [eax+esi*4], 0 |
lea esi, [edi+2] |
push eax |
push 32 |
movzx eax, WORD PTR [edi] |
mov edx, DWORD PTR [esp+56] |
mov eax, DWORD PTR [edx+eax*4] |
add eax, OS_BASE |
push eax |
push esi |
call strncmp |
pop ebx |
xor ebx, ebx |
test eax, eax |
jne L32 |
jmp L30 |
L33: |
push ecx |
push 32 |
mov ecx, DWORD PTR [esp+28] |
mov eax, DWORD PTR [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: |
inc ebx |
L32: |
cmp ebx, DWORD PTR [__exports+24] |
jb L33 |
L36: |
cmp ebx, DWORD PTR [__exports+24] |
jne L37 |
mov esi, msg_unresolved |
call sys_msg_board_str |
lea esi, [edi+2] |
call sys_msg_board_str |
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] |
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: |
xor eax, eax |
cmp DWORD PTR [esp+40], 0 |
jne L40 |
L20: |
mov ecx, DWORD PTR [esp+32] |
mov eax, ebp |
add eax, DWORD PTR [ecx+40] |
L40: |
add esp, 60 |
pop ebx |
pop esi |
pop edi |
pop ebp |
ret 8 |
align 16 |
__exports: |
export 'KERNEL', \ |
alloc_kernel_space, 'AllocKernelSpace', \ ; stdcall |
alloc_page, 'AllocPage', \ ; gcc ABI |
alloc_pages, 'AllocPages', \ ; stdcall |
commit_pages, 'CommitPages', \ ; eax, ebx, ecx |
\ |
create_event, 'CreateEvent', \ ; ecx, esi |
raise_event, 'RaiseEvent', \ ; eax, ebx, edx, esi |
wait_event, 'WaitEvent', \ ; eax, ebx |
get_event_ex, 'GetEvent', \ ; edi |
\ |
create_kernel_object, 'CreateObject', \ |
create_ring_buffer, 'CreateRingBuffer', \ ; stdcall |
destroy_kernel_object, 'DestroyObject', \ |
free_kernel_space, 'FreeKernelSpace', \ ; stdcall |
kernel_alloc, 'KernelAlloc', \ ; stdcall |
kernel_free, 'KernelFree', \ ; stdcall |
malloc, 'Kmalloc', \ |
free, 'Kfree', \ |
map_io_mem, 'MapIoMem', \ ; stdcall |
get_pg_addr, 'GetPgAddr', \ ; eax |
\ |
mutex_init, 'MutexInit', \ ; gcc fastcall |
mutex_lock, 'MutexLock', \ ; gcc fastcall |
mutex_unlock, 'MutexUnlock', \ ; gcc fastcall |
\ |
get_display, 'GetDisplay', \ |
set_screen, 'SetScreen', \ |
pci_api_drv, 'PciApi', \ |
pci_read8, 'PciRead8', \ ; stdcall |
pci_read16, 'PciRead16', \ ; stdcall |
pci_read32, 'PciRead32', \ ; stdcall |
pci_write8, 'PciWrite8', \ ; stdcall |
pci_write16, 'PciWrite16', \ ; stdcall |
pci_write32, 'PciWrite32', \ ; stdcall |
\ |
get_pid, 'GetPid', \ |
get_service, 'GetService', \ ; |
reg_service, 'RegService', \ ; stdcall |
attach_int_handler, 'AttachIntHandler', \ ; stdcall |
user_alloc, 'UserAlloc', \ ; stdcall |
user_free, 'UserFree', \ ; stdcall |
unmap_pages, 'UnmapPages', \ ; eax, ecx |
sys_msg_board_str, 'SysMsgBoardStr', \ |
get_timer_ticks, 'GetTimerTicks', \ |
get_stack_base, 'GetStackBase', \ |
delay_hs, 'Delay', \ ; ebx |
set_mouse_data, 'SetMouseData', \ ; |
set_keyboard_data, 'SetKeyboardData' ; gcc fastcall |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/sched.inc |
---|
1,402 → 1,406 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; IRQ0 HANDLER (TIMER INTERRUPT) ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
irq0: |
pushad |
Mov ds, ax, app_data |
mov es, ax |
inc [timer_ticks] |
mov eax, [timer_ticks] |
call playNote ; <<<--- Speaker driver |
sub eax,[next_usage_update] |
cmp eax,100 |
jb .nocounter |
add [next_usage_update],100 |
call updatecputimes |
.nocounter: |
xor ecx, ecx ; send End Of Interrupt signal |
call irq_eoi |
btr dword[DONT_SWITCH], 0 |
jc .return |
call find_next_task |
jz .return ; if there is only one running process |
call do_change_task |
.return: |
popad |
iretd |
align 4 |
change_task: |
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 |
call find_next_task |
jz .return ; the same task -> skip switch |
@@: mov byte[DONT_SWITCH], 1 |
call do_change_task |
.return: |
popad |
popfd |
ret |
uglobal |
align 4 |
; far_jump: |
; .offs dd ? |
; .sel dw ? |
context_counter dd 0 ;noname & halyavin |
next_usage_update dd 0 |
timer_ticks dd 0 |
; prev_slot dd ? |
; event_sched dd ? |
endg |
align 4 |
update_counters: |
mov edi, [TASK_BASE] |
rdtsc |
sub eax, [edi+TASKDATA.counter_add] ; time stamp counter add |
add [edi+TASKDATA.counter_sum], eax ; counter sum |
ret |
align 4 |
updatecputimes: |
xor eax,eax |
xchg eax,[idleuse] |
mov [idleusesec],eax |
mov ecx, [TASK_COUNT] |
mov edi, TASK_DATA |
.newupdate: |
xor eax,eax |
xchg eax,[edi+TASKDATA.counter_sum] |
mov [edi+TASKDATA.cpu_usage],eax |
add edi,0x20 |
loop .newupdate |
ret |
align 4 |
find_next_task: |
;info: |
; Find next task to execute |
;retval: |
; ebx = address of the APPDATA for the selected task (slot-base) |
; esi = previous slot-base ([current_slot] at the begin) |
; edi = address of the TASKDATA for the selected task |
; ZF = 1 if the task is the same |
;warning: |
; [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result |
; [current_slot] is not set to new value (ebx)!!! |
;scratched: eax,ecx |
call update_counters ; edi := [TASK_BASE] |
Mov esi, ebx, [current_slot] |
.loop: |
cmp bh,[TASK_COUNT] |
jb @f |
xor bh, bh |
mov edi,CURRENT_TASK |
@@: inc bh ; ebx += APPDATA.size |
add edi,0x20 ; edi += TASKDATA.size |
mov al, [edi+TASKDATA.state] |
test al, al |
jz .found ; state == 0 |
cmp al, 5 |
jne .loop ; state == 1,2,3,4,9 |
; state == 5 |
pushad ; more freedom for [APPDATA.wait_test] |
call [ebx+APPDATA.wait_test] |
mov [esp+28],eax |
popad |
or eax,eax |
jnz @f |
; testing for timeout |
mov ecx, [timer_ticks] |
sub ecx, [ebx+APPDATA.wait_begin] |
cmp ecx, [ebx+APPDATA.wait_timeout] |
jb .loop |
@@: mov [ebx+APPDATA.wait_param], eax ; retval for wait |
mov [edi+TASKDATA.state], 0 |
.found: |
mov [CURRENT_TASK],bh |
mov [TASK_BASE],edi |
rdtsc ;call _rdtsc |
mov [edi+TASKDATA.counter_add],eax ; for next using update_counters |
cmp ebx, esi ;esi - previous slot-base |
ret |
;TODO: Íàäî áû óáðàòü èñïîëüçîâàíèå do_change_task èç V86... |
; è ïîñëå ýòîãî ïåðåíåñòè îáðàáîòêó TASKDATA.counter_add/sum â do_change_task |
align 4 |
do_change_task: |
;param: |
; ebx = address of the APPDATA for incoming task (new) |
;warning: |
; [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task) |
; [current_slot] is the outcoming (old), and set here to a new value (ebx) |
;scratched: eax,ecx,esi |
mov esi,ebx |
xchg esi,[current_slot] |
; set new stack after saving old |
mov [esi+APPDATA.saved_esp], esp |
mov esp, [ebx+APPDATA.saved_esp] |
; set new thread io-map |
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 |
je @f |
mov cr3, eax |
@@: |
; set tss.esp0 |
Mov [tss._esp0],eax,[ebx+APPDATA.saved_esp0] |
mov edx, [ebx+APPDATA.tls_base] |
cmp edx, [esi+APPDATA.tls_base] |
je @f |
mov [tls_data_l+2],dx |
shr edx,16 |
mov [tls_data_l+4],dl |
mov [tls_data_l+7],dh |
mov dx, app_tls |
mov fs, dx |
@@: |
; set gs selector unconditionally |
Mov gs,ax,graph_data |
; set CR0.TS |
cmp bh, byte[fpu_owner] ;bh == incoming task (new) |
clts ;clear a task switch flag |
je @f |
mov eax, cr0 ;and set it again if the owner |
or eax, CR0_TS ;of a fpu has changed |
mov cr0, eax |
@@: ; set context_counter (only for user pleasure ???) |
inc [context_counter] ;noname & halyavin |
; set debug-registers, if it's necessary |
test byte[ebx+APPDATA.dbg_state], 1 |
jz @f |
xor eax, eax |
mov dr6, eax |
lea esi,[ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table] ;offset>0x7F |
cld |
macro lodsReg [reg] { |
lodsd |
mov reg,eax |
} lodsReg dr0, dr1, dr2, dr3, dr7 |
purge lodsReg |
@@: ret |
;end. |
struc MUTEX_WAITER |
{ |
.list LHEAD |
.task rd 1 |
.sizeof: |
}; |
virtual at 0 |
MUTEX_WAITER MUTEX_WAITER |
end virtual |
;void __fastcall mutex_init(struct mutex *lock) |
align 4 |
mutex_init: |
mov [ecx+MUTEX.wait.next], ecx |
mov [ecx+MUTEX.wait.prev], ecx |
mov [ecx+MUTEX.count],1 |
ret |
;void __fastcall mutex_lock(struct mutex *lock) |
align 4 |
mutex_lock: |
dec [ecx+MUTEX.count] |
jns .done |
pushfd |
cli |
sub esp, MUTEX_WAITER.sizeof |
list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
mov edx, [TASK_BASE] |
mov [esp+MUTEX_WAITER.task], edx |
.forever: |
mov eax, -1 |
xchg eax, [ecx+MUTEX.count] |
dec eax |
jz @F |
mov [edx+TASKDATA.state], 1 |
call change_task |
jmp .forever |
@@: |
mov edx, [esp+MUTEX_WAITER.list.next] |
mov eax, [esp+MUTEX_WAITER.list.prev] |
mov [eax+MUTEX_WAITER.list.next], edx |
mov [edx+MUTEX_WAITER.list.prev], eax |
cmp [ecx+MUTEX.wait.next], ecx |
jne @F |
mov [ecx+MUTEX.count], 0 |
@@: |
add esp, MUTEX_WAITER.sizeof |
popfd |
.done: |
ret |
;void __fastcall mutex_unlock(struct mutex *lock) |
align 4 |
mutex_unlock: |
pushfd |
cli |
mov eax, [ecx+MUTEX.wait.next] |
cmp eax, ecx |
mov [ecx+MUTEX.count], 1 |
je @F |
mov eax, [eax+MUTEX_WAITER.task] |
mov [eax+TASKDATA.state], 0 |
@@: |
popfd |
ret |
purge MUTEX_WAITER |
if 0 |
struc TIMER |
{ |
.next dd ? |
.exp_time dd ? |
.func dd ? |
.arg dd ? |
} |
MAX_PROIRITY 0 ; highest, used for kernel tasks |
MAX_USER_PRIORITY 0 ; highest priority for user processes |
USER_PRIORITY 7 ; default (should correspond to nice 0) |
MIN_USER_PRIORITY 14 ; minimum priority for user processes |
IDLE_PRIORITY 15 ; lowest, only IDLE process goes here |
NR_SCHED_QUEUES 16 ; MUST equal IDLE_PRIORYTY + 1 |
uglobal |
rdy_head rd 16 |
endg |
align 4 |
pick_task: |
xor eax, eax |
.pick: |
mov ebx, [rdy_head+eax*4] |
test ebx, ebx |
jz .next |
mov [next_task], ebx |
test [ebx+flags.billable] |
jz @F |
mov [bill_task], ebx |
@@: |
ret |
.next: |
inc eax |
jmp .pick |
; param |
; eax= task |
; |
; retval |
; eax= task |
; ebx= queue |
; ecx= front if 1 or back if 0 |
align 4 |
shed: |
cmp [eax+.tics_left], 0 ;signed compare |
mov ebx, [eax+.priority] |
setg ecx |
jg @F |
mov edx, [eax+.tics_quantum] |
mov [eax+.ticks_left], edx |
cmp ebx, (IDLE_PRIORITY-1) |
je @F |
inc ebx |
@@: |
ret |
; param |
; eax= task |
align 4 |
enqueue: |
call shed ;eax |
cmp [rdy_head+ebx*4],0 |
jnz @F |
mov [rdy_head+ebx*4], eax |
mov [rdy_tail+ebx*4], eax |
mov [eax+.next_ready], 0 |
jmp .pick |
@@: |
test ecx, ecx |
jz .back |
mov ecx, [rdy_head+ebx*4] |
mov [eax+.next_ready], ecx |
mov [rdy_head+ebx*4], eax |
jmp .pick |
.back: |
mov ecx, [rdy_tail+ebx*4] |
mov [ecx+.next_ready], eax |
mov [rdy_tail+ebx*4], eax |
mov [eax+.next_ready], 0 |
.pick: |
call pick_proc ;select next task |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; IRQ0 HANDLER (TIMER INTERRUPT) ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
irq0: |
pushad |
Mov ds, ax, app_data |
mov es, ax |
inc [timer_ticks] |
mov eax, [timer_ticks] |
call playNote ; <<<--- Speaker driver |
sub eax, [next_usage_update] |
cmp eax, 100 |
jb .nocounter |
add [next_usage_update], 100 |
call updatecputimes |
.nocounter: |
xor ecx, ecx ; send End Of Interrupt signal |
call irq_eoi |
btr dword[DONT_SWITCH], 0 |
jc .return |
call find_next_task |
jz .return ; if there is only one running process |
call do_change_task |
.return: |
popad |
iretd |
align 4 |
change_task: |
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 |
call find_next_task |
jz .return ; the same task -> skip switch |
@@: |
mov byte[DONT_SWITCH], 1 |
call do_change_task |
.return: |
popad |
popfd |
ret |
uglobal |
align 4 |
; far_jump: |
; .offs dd ? |
; .sel dw ? |
context_counter dd 0 ;noname & halyavin |
next_usage_update dd 0 |
timer_ticks dd 0 |
; prev_slot dd ? |
; event_sched dd ? |
endg |
align 4 |
update_counters: |
mov edi, [TASK_BASE] |
rdtsc |
sub eax, [edi+TASKDATA.counter_add] ; time stamp counter add |
add [edi+TASKDATA.counter_sum], eax ; counter sum |
ret |
align 4 |
updatecputimes: |
xor eax, eax |
xchg eax, [idleuse] |
mov [idleusesec], eax |
mov ecx, [TASK_COUNT] |
mov edi, TASK_DATA |
.newupdate: |
xor eax, eax |
xchg eax, [edi+TASKDATA.counter_sum] |
mov [edi+TASKDATA.cpu_usage], eax |
add edi, 0x20 |
loop .newupdate |
ret |
align 4 |
find_next_task: |
;info: |
; Find next task to execute |
;retval: |
; ebx = address of the APPDATA for the selected task (slot-base) |
; esi = previous slot-base ([current_slot] at the begin) |
; edi = address of the TASKDATA for the selected task |
; ZF = 1 if the task is the same |
;warning: |
; [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result |
; [current_slot] is not set to new value (ebx)!!! |
;scratched: eax,ecx |
call update_counters ; edi := [TASK_BASE] |
Mov esi, ebx, [current_slot] |
.loop: |
cmp bh, [TASK_COUNT] |
jb @f |
xor bh, bh |
mov edi, CURRENT_TASK |
@@: |
inc bh ; ebx += APPDATA.size |
add edi, 0x20; edi += TASKDATA.size |
mov al, [edi+TASKDATA.state] |
test al, al |
jz .found ; state == 0 |
cmp al, 5 |
jne .loop ; state == 1,2,3,4,9 |
; state == 5 |
pushad ; more freedom for [APPDATA.wait_test] |
call [ebx+APPDATA.wait_test] |
mov [esp+28], eax |
popad |
or eax, eax |
jnz @f |
; testing for timeout |
mov ecx, [timer_ticks] |
sub ecx, [ebx+APPDATA.wait_begin] |
cmp ecx, [ebx+APPDATA.wait_timeout] |
jb .loop |
@@: |
mov [ebx+APPDATA.wait_param], eax ; retval for wait |
mov [edi+TASKDATA.state], 0 |
.found: |
mov [CURRENT_TASK], bh |
mov [TASK_BASE], edi |
rdtsc ;call _rdtsc |
mov [edi+TASKDATA.counter_add], eax; for next using update_counters |
cmp ebx, esi ;esi - previous slot-base |
ret |
;TODO: Íàäî áû óáðàòü èñïîëüçîâàíèå do_change_task èç V86... |
; è ïîñëå ýòîãî ïåðåíåñòè îáðàáîòêó TASKDATA.counter_add/sum â do_change_task |
align 4 |
do_change_task: |
;param: |
; ebx = address of the APPDATA for incoming task (new) |
;warning: |
; [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task) |
; [current_slot] is the outcoming (old), and set here to a new value (ebx) |
;scratched: eax,ecx,esi |
mov esi, ebx |
xchg esi, [current_slot] |
; set new stack after saving old |
mov [esi+APPDATA.saved_esp], esp |
mov esp, [ebx+APPDATA.saved_esp] |
; set new thread io-map |
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 |
je @f |
mov cr3, eax |
@@: |
; set tss.esp0 |
Mov [tss._esp0],eax,[ebx+APPDATA.saved_esp0] |
mov edx, [ebx+APPDATA.tls_base] |
cmp edx, [esi+APPDATA.tls_base] |
je @f |
mov [tls_data_l+2], dx |
shr edx, 16 |
mov [tls_data_l+4], dl |
mov [tls_data_l+7], dh |
mov dx, app_tls |
mov fs, dx |
@@: |
; set gs selector unconditionally |
Mov gs,ax,graph_data |
; set CR0.TS |
cmp bh, byte[fpu_owner] ;bh == incoming task (new) |
clts ;clear a task switch flag |
je @f |
mov eax, cr0 ;and set it again if the owner |
or eax, CR0_TS ;of a fpu has changed |
mov cr0, eax |
@@: ; set context_counter (only for user pleasure ???) |
inc [context_counter] ;noname & halyavin |
; set debug-registers, if it's necessary |
test byte[ebx+APPDATA.dbg_state], 1 |
jz @f |
xor eax, eax |
mov dr6, eax |
lea esi, [ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table];offset>0x7F |
cld |
macro lodsReg [reg] { |
lodsd |
mov reg, eax |
} lodsReg dr0, dr1, dr2, dr3, dr7 |
purge lodsReg |
@@: |
ret |
;end. |
struc MUTEX_WAITER |
{ |
.list LHEAD |
.task rd 1 |
.sizeof: |
}; |
virtual at 0 |
MUTEX_WAITER MUTEX_WAITER |
end virtual |
;void __fastcall mutex_init(struct mutex *lock) |
align 4 |
mutex_init: |
mov [ecx+MUTEX.wait.next], ecx |
mov [ecx+MUTEX.wait.prev], ecx |
mov [ecx+MUTEX.count], 1 |
ret |
;void __fastcall mutex_lock(struct mutex *lock) |
align 4 |
mutex_lock: |
dec [ecx+MUTEX.count] |
jns .done |
pushfd |
cli |
sub esp, MUTEX_WAITER.sizeof |
list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
mov edx, [TASK_BASE] |
mov [esp+MUTEX_WAITER.task], edx |
.forever: |
mov eax, -1 |
xchg eax, [ecx+MUTEX.count] |
dec eax |
jz @F |
mov [edx+TASKDATA.state], 1 |
call change_task |
jmp .forever |
@@: |
mov edx, [esp+MUTEX_WAITER.list.next] |
mov eax, [esp+MUTEX_WAITER.list.prev] |
mov [eax+MUTEX_WAITER.list.next], edx |
mov [edx+MUTEX_WAITER.list.prev], eax |
cmp [ecx+MUTEX.wait.next], ecx |
jne @F |
mov [ecx+MUTEX.count], 0 |
@@: |
add esp, MUTEX_WAITER.sizeof |
popfd |
.done: |
ret |
;void __fastcall mutex_unlock(struct mutex *lock) |
align 4 |
mutex_unlock: |
pushfd |
cli |
mov eax, [ecx+MUTEX.wait.next] |
cmp eax, ecx |
mov [ecx+MUTEX.count], 1 |
je @F |
mov eax, [eax+MUTEX_WAITER.task] |
mov [eax+TASKDATA.state], 0 |
@@: |
popfd |
ret |
purge MUTEX_WAITER |
if 0 |
struc TIMER |
{ |
.next dd ? |
.exp_time dd ? |
.func dd ? |
.arg dd ? |
} |
MAX_PROIRITY 0 ; highest, used for kernel tasks |
MAX_USER_PRIORITY 0 ; highest priority for user processes |
USER_PRIORITY 7 ; default (should correspond to nice 0) |
MIN_USER_PRIORITY 14 ; minimum priority for user processes |
IDLE_PRIORITY 15 ; lowest, only IDLE process goes here |
NR_SCHED_QUEUES 16 ; MUST equal IDLE_PRIORYTY + 1 |
uglobal |
rdy_head rd 16 |
endg |
align 4 |
pick_task: |
xor eax, eax |
.pick: |
mov ebx, [rdy_head+eax*4] |
test ebx, ebx |
jz .next |
mov [next_task], ebx |
test [ebx+flags.billable] |
jz @F |
mov [bill_task], ebx |
@@: |
ret |
.next: |
inc eax |
jmp .pick |
; param |
; eax= task |
; |
; retval |
; eax= task |
; ebx= queue |
; ecx= front if 1 or back if 0 |
align 4 |
shed: |
cmp [eax+.tics_left], 0;signed compare |
mov ebx, [eax+.priority] |
setg ecx |
jg @F |
mov edx, [eax+.tics_quantum] |
mov [eax+.ticks_left], edx |
cmp ebx, (IDLE_PRIORITY-1) |
je @F |
inc ebx |
@@: |
ret |
; param |
; eax= task |
align 4 |
enqueue: |
call shed;eax |
cmp [rdy_head+ebx*4], 0 |
jnz @F |
mov [rdy_head+ebx*4], eax |
mov [rdy_tail+ebx*4], eax |
mov [eax+.next_ready], 0 |
jmp .pick |
@@: |
test ecx, ecx |
jz .back |
mov ecx, [rdy_head+ebx*4] |
mov [eax+.next_ready], ecx |
mov [rdy_head+ebx*4], eax |
jmp .pick |
.back: |
mov ecx, [rdy_tail+ebx*4] |
mov [ecx+.next_ready], eax |
mov [rdy_tail+ebx*4], eax |
mov [eax+.next_ready], 0 |
.pick: |
call pick_proc;select next task |
ret |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/string.inc |
---|
1,188 → 1,188 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; Author: Kees J. Bot 1 Jan 1994 ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; size_t strncat(char *s1, const char *s2, size_t n) |
; Append string s2 to s1. |
; char *strchr(const char *s, int c) |
; int strncmp(const char *s1, const char *s2, size_t n) |
; Compare two strings. |
; char *strncpy(char *s1, const char *s2, size_t n) |
; Copy string s2 to s1. |
; size_t strnlen(const char *s, size_t n) |
; Return the length of a string. |
; proc strrchr stdcall, s:dword, c:dword |
; Look for the last occurrence a character in a string. |
proc strncat stdcall, s1:dword, s2:dword, n:dword |
push esi |
push edi |
mov edi, [s1] ; String s1 |
mov edx, [n] ; Maximum length |
mov ecx, -1 |
xor al, al ; Null byte |
cld |
repne scasb ; Look for the zero byte in s1 |
dec edi ; Back one up (and clear 'Z' flag) |
push edi ; Save end of s1 |
mov edi, [s2] ; edi = string s2 |
mov ecx, edx ; Maximum count |
repne scasb ; Look for the end of s2 |
jne @F |
inc ecx ; Exclude null byte |
@@: |
sub edx, ecx ; Number of bytes in s2 |
mov ecx, edx |
mov esi, [s2] ; esi = string s2 |
pop edi ; edi = end of string s1 |
rep movsb ; Copy bytes |
stosb ; Add a terminating null |
mov eax, [s1] ; Return s1 |
pop edi |
pop esi |
ret |
endp |
align 4 |
proc strncmp stdcall, s1:dword, s2:dword, n:dword |
push esi |
push edi |
mov ecx, [n] |
test ecx, ecx ; Max length is zero? |
je .done |
mov esi, [s1] ; esi = string s1 |
mov edi, [s2] ; edi = string s2 |
cld |
.compare: |
cmpsb ; Compare two bytes |
jne .done |
cmp byte [esi-1], 0 ; End of string? |
je .done |
dec ecx ; Length limit reached? |
jne .compare |
.done: |
seta al ; al = (s1 > s2) |
setb ah ; ah = (s1 < s2) |
sub al, ah |
movsx eax, al ; eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 |
pop edi |
pop esi |
ret |
endp |
align 4 |
proc strncpy stdcall, s1:dword, s2:dword, n:dword |
push esi |
push edi |
mov ecx, [n] ; Maximum length |
mov edi, [s2] ; edi = string s2 |
xor al, al ; Look for a zero byte |
mov edx, ecx ; Save maximum count |
cld |
repne scasb ; Look for end of s2 |
sub edx, ecx ; Number of bytes in s2 including null |
xchg ecx, edx |
mov esi, [s2] ; esi = string s2 |
mov edi, [s1] ; edi = string s1 |
rep movsb ; Copy bytes |
mov ecx, edx ; Number of bytes not copied |
rep stosb ; strncpy always copies n bytes by null padding |
mov eax, [s1] ; Return s1 |
pop edi |
pop esi |
ret |
endp |
align 4 |
proc strnlen stdcall, s:dword, n:dword |
push edi |
mov edi, [s] ; edi = string |
xor al, al ; Look for a zero byte |
mov edx, ecx ; Save maximum count |
cmp cl, 1 ; 'Z' bit must be clear if ecx = 0 |
cld |
repne scasb ; Look for zero |
jne @F |
inc ecx ; Don't count zero byte |
@@: |
mov eax, edx |
sub eax, ecx ; Compute bytes scanned |
pop edi |
ret |
endp |
align 4 |
proc strchr stdcall, s:dword, c:dword |
push edi |
cld |
mov edi, [s] ; edi = string |
mov edx, 16 ; Look at small chunks of the string |
.next: |
shl edx, 1 ; Chunks become bigger each time |
mov ecx, edx |
xor al, al ; Look for the zero at the end |
repne scasb |
pushf ; Remember the flags |
sub ecx, edx |
neg ecx ; Some or all of the chunk |
sub edi, ecx ; Step back |
mov eax, [c] ; The character to look for |
repne scasb |
je .found |
popf ; Did we find the end of string earlier? |
jne .next ; No, try again |
xor eax, eax ; Return NULL |
pop edi |
ret |
.found: |
pop eax ; Get rid of those flags |
lea eax, [edi-1] ; Address of byte found |
pop edi |
ret |
endp |
proc strrchr stdcall, s:dword, c:dword |
push edi |
mov edi, [s] ; edi = string |
mov ecx, -1 |
xor al, al |
cld |
repne scasb ; Look for the end of the string |
not ecx ; -1 - ecx = Length of the string + null |
dec edi ; Put edi back on the zero byte |
mov eax, [c] ; The character to look for |
std ; Downwards search |
repne scasb |
cld ; Direction bit back to default |
jne .fail |
lea eax, [edi+1] ; Found it |
pop edi |
ret |
.fail: |
xor eax, eax ; Not there |
pop edi |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; Author: Kees J. Bot 1 Jan 1994 ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; size_t strncat(char *s1, const char *s2, size_t n) |
; Append string s2 to s1. |
; char *strchr(const char *s, int c) |
; int strncmp(const char *s1, const char *s2, size_t n) |
; Compare two strings. |
; char *strncpy(char *s1, const char *s2, size_t n) |
; Copy string s2 to s1. |
; size_t strnlen(const char *s, size_t n) |
; Return the length of a string. |
; proc strrchr stdcall, s:dword, c:dword |
; Look for the last occurrence a character in a string. |
proc strncat stdcall, s1:dword, s2:dword, n:dword |
push esi |
push edi |
mov edi, [s1] ; String s1 |
mov edx, [n] ; Maximum length |
mov ecx, -1 |
xor al, al ; Null byte |
cld |
repne scasb ; Look for the zero byte in s1 |
dec edi ; Back one up (and clear 'Z' flag) |
push edi ; Save end of s1 |
mov edi, [s2] ; edi = string s2 |
mov ecx, edx ; Maximum count |
repne scasb ; Look for the end of s2 |
jne @F |
inc ecx ; Exclude null byte |
@@: |
sub edx, ecx ; Number of bytes in s2 |
mov ecx, edx |
mov esi, [s2] ; esi = string s2 |
pop edi ; edi = end of string s1 |
rep movsb ; Copy bytes |
stosb ; Add a terminating null |
mov eax, [s1] ; Return s1 |
pop edi |
pop esi |
ret |
endp |
align 4 |
proc strncmp stdcall, s1:dword, s2:dword, n:dword |
push esi |
push edi |
mov ecx, [n] |
test ecx, ecx ; Max length is zero? |
je .done |
mov esi, [s1] ; esi = string s1 |
mov edi, [s2] ; edi = string s2 |
cld |
.compare: |
cmpsb ; Compare two bytes |
jne .done |
cmp byte [esi-1], 0 ; End of string? |
je .done |
dec ecx ; Length limit reached? |
jne .compare |
.done: |
seta al ; al = (s1 > s2) |
setb ah ; ah = (s1 < s2) |
sub al, ah |
movsx eax, al ; eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 |
pop edi |
pop esi |
ret |
endp |
align 4 |
proc strncpy stdcall, s1:dword, s2:dword, n:dword |
push esi |
push edi |
mov ecx, [n] ; Maximum length |
mov edi, [s2] ; edi = string s2 |
xor al, al ; Look for a zero byte |
mov edx, ecx ; Save maximum count |
cld |
repne scasb ; Look for end of s2 |
sub edx, ecx ; Number of bytes in s2 including null |
xchg ecx, edx |
mov esi, [s2] ; esi = string s2 |
mov edi, [s1] ; edi = string s1 |
rep movsb ; Copy bytes |
mov ecx, edx ; Number of bytes not copied |
rep stosb ; strncpy always copies n bytes by null padding |
mov eax, [s1] ; Return s1 |
pop edi |
pop esi |
ret |
endp |
align 4 |
proc strnlen stdcall, s:dword, n:dword |
push edi |
mov edi, [s] ; edi = string |
xor al, al ; Look for a zero byte |
mov edx, ecx ; Save maximum count |
cmp cl, 1 ; 'Z' bit must be clear if ecx = 0 |
cld |
repne scasb ; Look for zero |
jne @F |
inc ecx ; Don't count zero byte |
@@: |
mov eax, edx |
sub eax, ecx ; Compute bytes scanned |
pop edi |
ret |
endp |
align 4 |
proc strchr stdcall, s:dword, c:dword |
push edi |
cld |
mov edi, [s] ; edi = string |
mov edx, 16 ; Look at small chunks of the string |
.next: |
shl edx, 1 ; Chunks become bigger each time |
mov ecx, edx |
xor al, al ; Look for the zero at the end |
repne scasb |
pushf ; Remember the flags |
sub ecx, edx |
neg ecx ; Some or all of the chunk |
sub edi, ecx ; Step back |
mov eax, [c] ; The character to look for |
repne scasb |
je .found |
popf ; Did we find the end of string earlier? |
jne .next ; No, try again |
xor eax, eax ; Return NULL |
pop edi |
ret |
.found: |
pop eax ; Get rid of those flags |
lea eax, [edi-1] ; Address of byte found |
pop edi |
ret |
endp |
proc strrchr stdcall, s:dword, c:dword |
push edi |
mov edi, [s] ; edi = string |
mov ecx, -1 |
xor al, al |
cld |
repne scasb ; Look for the end of the string |
not ecx ; -1 - ecx = Length of the string + null |
dec edi ; Put edi back on the zero byte |
mov eax, [c] ; The character to look for |
std ; Downwards search |
repne scasb |
cld ; Direction bit back to default |
jne .fail |
lea eax, [edi+1] ; Found it |
pop edi |
ret |
.fail: |
xor eax, eax ; Not there |
pop edi |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/sync.inc |
---|
1,119 → 1,119 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Synhronization for MenuetOS. ;; |
;; Author: Halyavin Andrey, halyavin@land.ru ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
if ~defined sync_inc |
sync_inc_fix: |
sync_inc fix sync_inc_fix |
;simplest mutex. |
macro SimpleMutex name |
{ |
; iglobal |
name dd 0 |
name#.type = 1 |
; endg |
} |
macro WaitSimpleMutex name |
{ |
local start_wait,ok |
start_wait=$ |
cli |
cmp [name],dword 0 |
jz ok |
sti |
call change_task |
jmp start_wait |
ok=$ |
push eax |
mov eax,dword [TASK_BASE+second_base_address] |
mov eax,[eax+TASKDATA.pid] |
mov [name],eax |
pop eax |
sti |
} |
macro ReleaseSimpleMutex name |
{ |
mov [name],dword 0 |
} |
macro TryWaitSimpleMutex name ;result in eax and in flags |
{ |
local ok,try_end |
cmp [name],dword 0 |
jz ok |
xor eax,eax |
jmp try_end |
ok=$ |
xor eax,eax |
inc eax |
try_end=$ |
} |
macro SimpleCriticalSection name |
{ |
; iglobal |
name dd 0 |
dd 0 |
name#.type=2 |
; endg |
} |
macro WaitSimpleCriticalSection name |
{ |
local start_wait,first_wait,inc_counter,end_wait |
push eax |
mov eax,[TASK_BASE+second_base_address] |
mov eax,[eax+TASKDATA.pid] |
start_wait=$ |
cli |
cmp [name],dword 0 |
jz first_wait |
cmp [name],eax |
jz inc_counter |
sti |
call change_task |
jmp start_wait |
first_wait=$ |
mov [name],eax |
mov [name+4],dword 1 |
jmp end_wait |
inc_counter=$ |
inc dword [name+4] |
end_wait=$ |
sti |
pop eax |
} |
macro ReleaseSimpleCriticalSection name |
{ |
local release_end |
dec dword [name+4] |
jnz release_end |
mov [name],dword 0 |
release_end=$ |
} |
macro TryWaitSimpleCriticalSection name ;result in eax and in flags |
{ |
local ok,try_end |
mov eax,[CURRENT_TASK+second_base_address] |
mov eax,[eax+TASKDATA.pid] |
cmp [name],eax |
jz ok |
cmp [name],0 |
jz ok |
xor eax,eax |
jmp try_end |
ok=$ |
xor eax,eax |
inc eax |
try_end=$ |
} |
_cli equ call MEM_HeapLock |
_sti equ call MEM_HeapUnLock |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Synhronization for MenuetOS. ;; |
;; Author: Halyavin Andrey, halyavin@land.ru ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
if ~defined sync_inc |
sync_inc_fix: |
sync_inc fix sync_inc_fix |
;simplest mutex. |
macro SimpleMutex name |
{ |
; iglobal |
name dd 0 |
name#.type = 1 |
; endg |
} |
macro WaitSimpleMutex name |
{ |
local start_wait,ok |
start_wait=$ |
cli |
cmp [name], dword 0 |
jz ok |
sti |
call change_task |
jmp start_wait |
ok=$ |
push eax |
mov eax, dword [TASK_BASE+second_base_address] |
mov eax, [eax+TASKDATA.pid] |
mov [name], eax |
pop eax |
sti |
} |
macro ReleaseSimpleMutex name |
{ |
mov [name], dword 0 |
} |
macro TryWaitSimpleMutex name ;result in eax and in flags |
{ |
local ok,try_end |
cmp [name], dword 0 |
jz ok |
xor eax, eax |
jmp try_end |
ok=$ |
xor eax, eax |
inc eax |
try_end=$ |
} |
macro SimpleCriticalSection name |
{ |
; iglobal |
name dd 0 |
dd 0 |
name#.type=2 |
; endg |
} |
macro WaitSimpleCriticalSection name |
{ |
local start_wait,first_wait,inc_counter,end_wait |
push eax |
mov eax, [TASK_BASE+second_base_address] |
mov eax, [eax+TASKDATA.pid] |
start_wait=$ |
cli |
cmp [name], dword 0 |
jz first_wait |
cmp [name], eax |
jz inc_counter |
sti |
call change_task |
jmp start_wait |
first_wait=$ |
mov [name], eax |
mov [name+4], dword 1 |
jmp end_wait |
inc_counter=$ |
inc dword [name+4] |
end_wait=$ |
sti |
pop eax |
} |
macro ReleaseSimpleCriticalSection name |
{ |
local release_end |
dec dword [name+4] |
jnz release_end |
mov [name], dword 0 |
release_end=$ |
} |
macro TryWaitSimpleCriticalSection name ;result in eax and in flags |
{ |
local ok,try_end |
mov eax, [CURRENT_TASK+second_base_address] |
mov eax, [eax+TASKDATA.pid] |
cmp [name], eax |
jz ok |
cmp [name], 0 |
jz ok |
xor eax, eax |
jmp try_end |
ok=$ |
xor eax, eax |
inc eax |
try_end=$ |
} |
_cli equ call MEM_HeapLock |
_sti equ call MEM_HeapUnLock |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/sys32.inc |
---|
1,692 → 1,700 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; MenuetOS process management, protected ring3 ;; |
;; ;; |
;; Distributed under GPL. See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
align 4 ;3A08 |
build_interrupt_table: |
mov edi, idts |
mov esi, sys_int |
mov ecx, 0x40 |
mov eax, (10001110b shl 24) + os_code |
@@: movsw ;low word of code-entry |
stosd ;interrupt gate type : os_code selector |
movsw ;high word of code-entry |
loop @b |
movsd ;copy low dword of trap gate for int 0x40 |
movsd ;copy high dword of trap gate for int 0x40 |
lidt [esi] |
ret |
iglobal |
align 4 |
sys_int: |
;exception handlers addresses (for interrupt gate construction) |
dd e0,e1,e2,e3,e4,e5,e6,except_7 ; SEE: core/fpu.inc |
dd e8,e9,e10,e11,e12,e13,page_fault_exc,e15 |
dd e16, e17,e18, e19 |
times 12 dd unknown_interrupt ;int_20..int_31 |
;interrupt handlers addresses (for interrupt gate construction) |
; 0x20 .. 0x2F - IRQ handlers |
dd irq0, irq_serv.irq_1, irq_serv.irq_2 |
dd irq_serv.irq_3, irq_serv.irq_4 |
dd irq_serv.irq_5, irq_serv.irq_6, irq_serv.irq_7 |
dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10 |
dd irq_serv.irq_11, irq_serv.irq_12, irqD, irq_serv.irq_14, irq_serv.irq_15 |
dd irq_serv.irq_16 |
dd irq_serv.irq_17 |
dd irq_serv.irq_18 |
dd irq_serv.irq_19 |
dd irq_serv.irq_20 |
dd irq_serv.irq_21 |
dd irq_serv.irq_22 |
dd irq_serv.irq_23 |
times 32 - IRQ_RESERVED dd unknown_interrupt |
;int_0x40 gate trap (for directly copied) |
dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16 |
idtreg: ; data for LIDT instruction (!!! must be immediately below sys_int data) |
dw 2*($-sys_int-4)-1 |
dd idts ;0x8000B100 |
dw 0 ;ïðîñòî âûðàâíèâàíèå |
msg_fault_sel dd msg_exc_8,msg_exc_u,msg_exc_a,msg_exc_b |
dd msg_exc_c,msg_exc_d,msg_exc_e |
msg_exc_8 db "Double fault", 0 |
msg_exc_u db "Undefined Exception", 0 |
msg_exc_a db "Invalid TSS", 0 |
msg_exc_b db "Segment not present", 0 |
msg_exc_c db "Stack fault", 0 |
msg_exc_d db "General protection fault", 0 |
msg_exc_e db "Page fault", 0 |
msg_sel_ker db "kernel", 0 |
msg_sel_app db "application", 0 |
endg |
macro save_ring3_context { |
pushad |
} |
macro restore_ring3_context { |
popad |
} |
macro exc_wo_code [num] { |
e#num : |
save_ring3_context |
mov bl, num |
jmp exc_c |
} exc_wo_code 0,1,2,3,4,5,6,15,16,19 |
macro exc_w_code [num] { |
e#num : |
add esp, 4 |
save_ring3_context |
mov bl, num |
jmp exc_c |
} exc_w_code 8,9,10,11,12,13,17,18 |
uglobal |
pf_err_code dd ? |
endg |
page_fault_exc: ; äóðàêîóñòî÷èâîñòü: ñåëåêòîðû èñïîð÷åíû... |
pop [ss:pf_err_code]; äåéñòâèòåëüíî äî ñëåäóþùåãî #PF |
save_ring3_context |
mov bl,14 |
exc_c: ; èñêëþ÷åíèÿ (âñå, êðîìå 7-ãî - #NM) |
; Ôðýéì ñòåêà ïðè èñêëþ÷åíèè/ïðåðûâàíèè èç 3-ãî êîëüöà + pushad (ò.å., èìåííî çäåñü) |
reg_ss equ esp+0x30 |
reg_esp3 equ esp+0x2C |
reg_eflags equ esp+0x28 |
reg_cs3 equ esp+0x24 |
reg_eip equ esp+0x20 |
; ýòî ôðýéì îò pushad |
reg_eax equ esp+0x1C |
reg_ecx equ esp+0x18 |
reg_edx equ esp+0x14 |
reg_ebx equ esp+0x10 |
reg_esp0 equ esp+0x0C |
reg_ebp equ esp+0x08 |
reg_esi equ esp+0x04 |
reg_edi equ esp+0x00 |
mov ax, app_data ;èñêëþ÷åíèå |
mov ds, ax ;çàãðóçèì ïðàâèëüíûå çíà÷åíèÿ |
mov es, ax ;â ðåãèñòðû |
cld ; è ïðèâîäèì DF ê ñòàíäàðòó |
movzx ebx,bl |
; redirect to V86 manager? (EFLAGS & 0x20000) != 0? |
test byte[reg_eflags+2],2 |
jnz v86_exc_c |
cmp bl,14 ; #PF |
jne @f |
call page_fault_handler ; SEE: core/memory.inc |
@@: mov esi, [current_slot] |
btr [esi+APPDATA.except_mask], ebx |
jnc @f |
mov eax,[esi+APPDATA.exc_handler] |
test eax, eax |
jnz IRetToUserHook |
@@: cli |
mov eax, [esi+APPDATA.debugger_slot] |
test eax, eax |
jnz .debug |
sti |
; not debuggee => say error and terminate |
call show_error_parameters ;; only ONE using, inline ??? |
;mov edx, [TASK_BASE] |
mov [edx + TASKDATA.state], byte 4 ; terminate |
jmp change_task ; stack - here it does not matter at all, SEE: core/shed.inc |
.debug: |
; we are debugged process, notify debugger and suspend ourself |
; eax=debugger PID |
mov ecx,1 ; debug_message code=other_exception |
cmp bl,1 ; #DB |
jne .notify ; notify debugger and suspend ourself |
mov ebx, dr6 ; debug_message data=DR6_image |
xor edx, edx |
mov dr6, edx |
mov edx, dr7 |
mov cl, not 8 |
.l1: shl dl,2 |
jc @f |
and bl, cl |
@@: sar cl,1 |
jc .l1 |
mov cl, 3 ; debug_message code=debug_exception |
.notify: |
push ebx ; debug_message data |
mov ebx, [TASK_BASE] |
push [ebx+TASKDATA.pid] ; PID |
push ecx ; debug_message code ((here: ecx==1/3)) |
mov cl, 12 ; debug_message size |
call debugger_notify ;; only ONE using, inline ??? SEE: core/debug.inc |
add esp,12 |
mov edx, [TASK_BASE] |
mov byte [edx+TASKDATA.state], 1 ; suspended |
call change_task ; SEE: core/shed.inc |
restore_ring3_context |
iretd |
IRetToUserHook: |
xchg eax, [reg_eip] |
sub dword[reg_esp3], 8 |
mov edi, [reg_esp3] |
stosd |
mov [edi], ebx |
restore_ring3_context |
; simply return control to interrupted process |
unknown_interrupt: |
iretd |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
; bl - error vector |
show_error_parameters: |
cmp bl, 0x06 |
jnz .no_ud |
push ebx |
mov ebx, ud_user_message |
mov ebp, notifyapp |
call fs_execute_from_sysdir_param |
pop ebx |
.no_ud: |
mov edx,[TASK_BASE] ;not scratched below |
DEBUGF 1, "K : Process - forced terminate PID: %x\n", [edx+TASKDATA.pid] |
cmp bl, 0x08 |
jb .l0 |
cmp bl, 0x0e |
jbe .l1 |
.l0: mov bl, 0x09 |
.l1: mov eax,[msg_fault_sel+ebx*4 - 0x08*4] |
DEBUGF 1, "K : %s\n", eax |
mov eax, [reg_cs3+4] |
mov edi, msg_sel_app |
mov ebx, [reg_esp3+4] |
cmp eax, app_code |
je @f |
mov edi, msg_sel_ker |
mov ebx, [reg_esp0+4] |
@@: DEBUGF 1, "K : EAX : %x EBX : %x ECX : %x\n", [reg_eax+4], [reg_ebx+4], [reg_ecx+4] |
DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [reg_edx+4], [reg_esi+4], [reg_edi+4] |
DEBUGF 1, "K : EBP : %x EIP : %x ESP : %x\n", [reg_ebp+4], [reg_eip+4], ebx |
DEBUGF 1, "K : Flags : %x CS : %x (%s)\n", [reg_eflags+4], eax, edi |
ret |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
restore reg_ss |
restore reg_esp3 |
restore reg_eflags |
restore reg_cs |
restore reg_eip |
restore reg_eax |
restore reg_ecx |
restore reg_edx |
restore reg_ebx |
restore reg_esp0 |
restore reg_ebp |
restore reg_esi |
restore reg_edi |
align 4 |
set_application_table_status: |
push eax |
mov eax,[CURRENT_TASK] |
shl eax, 5 |
add eax,CURRENT_TASK+TASKDATA.pid |
mov eax,[eax] |
mov [application_table_status],eax |
pop eax |
ret |
align 4 |
clear_application_table_status: |
push eax |
mov eax,[CURRENT_TASK] |
shl eax, 5 |
add eax,CURRENT_TASK+TASKDATA.pid |
mov eax,[eax] |
cmp eax,[application_table_status] |
jne apptsl1 |
xor eax,eax |
mov [application_table_status],eax |
apptsl1: |
pop eax |
ret |
; * eax = 64 - íîìåð ôóíêöèè |
; * ebx = 1 - åäèíñòâåííàÿ ïîäôóíêöèÿ |
; * ecx = íîâûé ðàçìåð ïàìÿòè |
;Âîçâðàùàåìîå çíà÷åíèå: |
; * eax = 0 - óñïåøíî |
; * eax = 1 - íåäîñòàòî÷íî ïàìÿòè |
align 4 |
sys_resize_app_memory: |
; ebx = 1 - resize |
; ecx = new amount of memory |
; cmp eax,1 |
dec ebx |
jnz .no_application_mem_resize |
stdcall new_mem_resize, ecx |
mov [esp+32], eax |
.no_application_mem_resize: |
ret |
iglobal |
; process_terminating db 'K : Process - terminating',13,10,0 |
; process_terminated db 'K : Process - done',13,10,0 |
msg_obj_destroy db 'K : destroy app object',13,10,0 |
endg |
; param |
; esi= slot |
align 4 |
terminate: ; terminate application |
.slot equ esp ;locals |
push esi ;save .slot |
shl esi, 8 |
cmp [SLOT_BASE+esi+APPDATA.dir_table], 0 |
jne @F |
pop esi |
shl esi, 5 |
mov [CURRENT_TASK+esi+TASKDATA.state], 9 |
ret |
@@: |
;mov esi,process_terminating |
;call sys_msg_board_str |
@@: |
cli |
cmp [application_table_status],0 |
je term9 |
sti |
call change_task |
jmp @b |
term9: |
call set_application_table_status |
; if the process is in V86 mode... |
mov eax, [.slot] |
shl eax, 8 |
mov esi, [eax+SLOT_BASE+APPDATA.pl0_stack] |
add esi, RING0_STACK_SIZE |
cmp [eax+SLOT_BASE+APPDATA.saved_esp0], esi |
jz .nov86 |
; ...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 |
; ...and I/O permission map for V86 mode |
mov ecx, [esi+12] |
mov [eax+SLOT_BASE+APPDATA.io_map], ecx |
mov ecx, [esi+8] |
mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx |
.nov86: |
mov esi, [.slot] |
shl esi,8 |
add esi, SLOT_BASE+APP_OBJ_OFFSET |
@@: |
mov eax, [esi+APPOBJ.fd] |
test eax, eax |
jz @F |
cmp eax, esi |
je @F |
push esi |
call [eax+APPOBJ.destroy] |
DEBUGF 1,"%s",msg_obj_destroy |
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 = 1 |
jne @F |
mov [fpu_owner],1 |
mov eax, [256+SLOT_BASE+APPDATA.fpu_state] |
clts |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxrstor [eax] |
jmp @F |
.no_SSE: |
fnclex |
frstor [eax] |
@@: |
mov [KEY_COUNT],byte 0 ; empty keyboard buffer |
mov [BTN_COUNT],byte 0 ; empty button buffer |
; remove defined hotkeys |
mov eax, hotkey_list |
.loop: |
cmp [eax+8], esi |
jnz .cont |
mov ecx, [eax] |
jecxz @f |
push dword [eax+12] |
pop dword [ecx+12] |
@@: |
mov ecx, [eax+12] |
push dword [eax] |
pop dword [ecx] |
xor ecx, ecx |
mov [eax], ecx |
mov [eax+4], ecx |
mov [eax+8], ecx |
mov [eax+12], ecx |
.cont: |
add eax, 16 |
cmp eax, hotkey_list+256*16 |
jb .loop |
; remove hotkeys in buffer |
mov eax, hotkey_buffer |
.loop2: |
cmp [eax], esi |
jnz .cont2 |
and dword [eax+4], 0 |
and dword [eax], 0 |
.cont2: |
add eax, 8 |
cmp eax, hotkey_buffer+120*8 |
jb .loop2 |
mov ecx,esi ; remove buttons |
bnewba2: |
mov edi,[BTN_ADDR] |
mov eax,edi |
cld |
movzx ebx,word [edi] |
inc bx |
bnewba: |
dec bx |
jz bnmba |
add eax,0x10 |
cmp cx,[eax] |
jnz bnewba |
pusha |
mov ecx,ebx |
inc ecx |
shl ecx,4 |
mov ebx,eax |
add eax,0x10 |
call memmove |
dec dword [edi] |
popa |
jmp bnewba2 |
bnmba: |
pusha ; save window coordinates for window restoring |
cld |
shl esi,5 |
add esi,window_data |
mov eax,[esi+WDATA.box.left] |
mov [draw_limits.left],eax |
add eax,[esi+WDATA.box.width] |
mov [draw_limits.right],eax |
mov eax,[esi+WDATA.box.top] |
mov [draw_limits.top],eax |
add eax,[esi+WDATA.box.height] |
mov [draw_limits.bottom],eax |
xor eax, eax |
mov [esi+WDATA.box.left],eax |
mov [esi+WDATA.box.width],eax |
mov [esi+WDATA.box.top],eax |
mov [esi+WDATA.box.height],eax |
mov [esi+WDATA.cl_workarea],eax |
mov [esi+WDATA.cl_titlebar],eax |
mov [esi+WDATA.cl_frames],eax |
mov dword [esi+WDATA.reserved],eax ; clear all flags: wstate, redraw, wdrawn |
lea edi, [esi-window_data+draw_data] |
mov ecx,32/4 |
rep stosd |
popa |
; debuggee test |
pushad |
mov edi, esi |
shl edi, 5 |
mov eax, [SLOT_BASE+edi*8+APPDATA.debugger_slot] |
test eax, eax |
jz .nodebug |
push 8 |
pop ecx |
push dword [CURRENT_TASK+edi+TASKDATA.pid] ; PID |
push 2 |
call debugger_notify |
pop ecx |
pop ecx |
.nodebug: |
popad |
mov ebx, [.slot] |
shl ebx, 8 |
push ebx |
mov ebx,[SLOT_BASE+ebx+APPDATA.pl0_stack] |
stdcall kernel_free, ebx |
pop ebx |
mov ebx,[SLOT_BASE+ebx+APPDATA.cur_dir] |
stdcall kernel_free, ebx |
mov edi, [.slot] |
shl edi,8 |
add edi,SLOT_BASE |
mov eax, [edi+APPDATA.io_map] |
cmp eax, [SLOT_BASE+256+APPDATA.io_map] |
je @F |
call free_page |
@@: |
mov eax, [edi+APPDATA.io_map+4] |
cmp eax, [SLOT_BASE+256+APPDATA.io_map+4] |
je @F |
call free_page |
@@: |
mov eax, 0x20202020 |
stosd |
stosd |
stosd |
mov ecx,244/4 |
xor eax, eax |
rep stosd |
; activate window |
movzx eax, word [WIN_STACK + esi*2] |
cmp eax, [TASK_COUNT] |
jne .dont_activate |
pushad |
.check_next_window: |
dec eax |
cmp eax, 1 |
jbe .nothing_to_activate |
lea esi, [WIN_POS+eax*2] |
movzx edi, word [esi] ; edi = process |
shl edi, 5 |
cmp [CURRENT_TASK + edi + TASKDATA.state], byte 9 ; skip dead slots |
je .check_next_window |
add edi, window_data |
; \begin{diamond}[19.09.2006] |
; skip minimized windows |
test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED |
jnz .check_next_window |
; \end{diamond} |
call waredraw |
.nothing_to_activate: |
popad |
.dont_activate: |
push esi ; remove hd1 & cd & flp reservation |
shl esi, 5 |
mov esi, [esi+CURRENT_TASK+TASKDATA.pid] |
cmp [hd1_status], esi |
jnz @f |
call free_hd_channel |
and [hd1_status], 0 |
@@: |
cmp [cd_status], esi |
jnz @f |
call free_cd_channel |
and [cd_status], 0 |
@@: |
cmp [flp_status], esi |
jnz @f |
and [flp_status], 0 |
@@: |
pop esi |
cmp [bgrlockpid], esi |
jnz @f |
and [bgrlockpid], 0 |
and [bgrlock], 0 |
@@: |
pusha ; remove all port reservations |
mov edx,esi |
shl edx, 5 |
add edx,CURRENT_TASK |
mov edx,[edx+TASKDATA.pid] |
rmpr0: |
mov esi,[RESERVED_PORTS] |
test esi,esi |
jz rmpr9 |
rmpr3: |
mov edi,esi |
shl edi,4 |
add edi,RESERVED_PORTS |
cmp edx,[edi] |
je rmpr4 |
dec esi |
jnz rmpr3 |
jmp rmpr9 |
rmpr4: |
mov ecx,256 |
sub ecx,esi |
shl ecx,4 |
mov esi,edi |
add esi,16 |
cld |
rep movsb |
dec dword [RESERVED_PORTS] |
jmp rmpr0 |
rmpr9: |
popa |
mov edi,esi ; do not run this process slot |
shl edi, 5 |
mov [edi+CURRENT_TASK + TASKDATA.state],byte 9 |
; debugger test - terminate all debuggees |
mov eax, 2 |
mov ecx, SLOT_BASE+2*0x100+APPDATA.debugger_slot |
.xd0: |
cmp eax, [TASK_COUNT] |
ja .xd1 |
cmp dword [ecx], esi |
jnz @f |
and dword [ecx], 0 |
pushad |
xchg eax, ecx |
mov ebx, 2 |
call sys_system |
popad |
@@: |
inc eax |
add ecx, 0x100 |
jmp .xd0 |
.xd1: |
; call systest |
sti ; .. and life goes on |
mov eax, [draw_limits.left] |
mov ebx, [draw_limits.top] |
mov ecx, [draw_limits.right] |
mov edx, [draw_limits.bottom] |
call calculatescreen |
xor eax, eax |
xor esi, esi |
call redrawscreen |
mov [MOUSE_BACKGROUND],byte 0 ; no mouse background |
mov [DONT_DRAW_MOUSE],byte 0 ; draw mouse |
and [application_table_status],0 |
;mov esi,process_terminated |
;call sys_msg_board_str |
add esp, 4 |
ret |
restore .slot |
iglobal |
if lang eq ru |
boot_sched_1 db '®§¤ ¨¥ GDT TSS 㪠§ ⥫ï',0 |
boot_sched_2 db '®§¤ ¨¥ IDT â ¡«¨æë',0 |
else |
boot_sched_1 db 'Building gdt tss pointer',0 |
boot_sched_2 db 'Building IDT table',0 |
end if |
endg |
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 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; MenuetOS process management, protected ring3 ;; |
;; ;; |
;; Distributed under GPL. See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
align 4 ;3A08 |
build_interrupt_table: |
mov edi, idts |
mov esi, sys_int |
mov ecx, 0x40 |
mov eax, (10001110b shl 24) + os_code |
@@: |
movsw ;low word of code-entry |
stosd ;interrupt gate type : os_code selector |
movsw ;high word of code-entry |
loop @b |
movsd ;copy low dword of trap gate for int 0x40 |
movsd ;copy high dword of trap gate for int 0x40 |
lidt [esi] |
ret |
iglobal |
align 4 |
sys_int: |
;exception handlers addresses (for interrupt gate construction) |
dd e0,e1,e2,e3,e4,e5,e6,except_7 ; SEE: core/fpu.inc |
dd e8,e9,e10,e11,e12,e13,page_fault_exc,e15 |
dd e16, e17,e18, e19 |
times 12 dd unknown_interrupt ;int_20..int_31 |
;interrupt handlers addresses (for interrupt gate construction) |
; 0x20 .. 0x2F - IRQ handlers |
dd irq0, irq_serv.irq_1, irq_serv.irq_2 |
dd irq_serv.irq_3, irq_serv.irq_4 |
dd irq_serv.irq_5, irq_serv.irq_6, irq_serv.irq_7 |
dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10 |
dd irq_serv.irq_11, irq_serv.irq_12, irqD, irq_serv.irq_14, irq_serv.irq_15 |
dd irq_serv.irq_16 |
dd irq_serv.irq_17 |
dd irq_serv.irq_18 |
dd irq_serv.irq_19 |
dd irq_serv.irq_20 |
dd irq_serv.irq_21 |
dd irq_serv.irq_22 |
dd irq_serv.irq_23 |
times 32 - IRQ_RESERVED dd unknown_interrupt |
;int_0x40 gate trap (for directly copied) |
dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16 |
idtreg: ; data for LIDT instruction (!!! must be immediately below sys_int data) |
dw 2*($-sys_int-4)-1 |
dd idts ;0x8000B100 |
dw 0 ;ïðîñòî âûðàâíèâàíèå |
msg_fault_sel dd msg_exc_8,msg_exc_u,msg_exc_a,msg_exc_b |
dd msg_exc_c,msg_exc_d,msg_exc_e |
msg_exc_8 db "Double fault", 0 |
msg_exc_u db "Undefined Exception", 0 |
msg_exc_a db "Invalid TSS", 0 |
msg_exc_b db "Segment not present", 0 |
msg_exc_c db "Stack fault", 0 |
msg_exc_d db "General protection fault", 0 |
msg_exc_e db "Page fault", 0 |
msg_sel_ker db "kernel", 0 |
msg_sel_app db "application", 0 |
endg |
macro save_ring3_context { |
pushad |
} |
macro restore_ring3_context { |
popad |
} |
macro exc_wo_code [num] { |
e#num : |
save_ring3_context |
mov bl, num |
jmp exc_c |
} exc_wo_code 0,1,2,3,4,5,6,15,16,19 |
macro exc_w_code [num] { |
e#num : |
add esp, 4 |
save_ring3_context |
mov bl, num |
jmp exc_c |
} exc_w_code 8,9,10,11,12,13,17,18 |
uglobal |
pf_err_code dd ? |
endg |
page_fault_exc: ; äóðàêîóñòî÷èâîñòü: ñåëåêòîðû èñïîð÷åíû... |
pop [ss:pf_err_code]; äåéñòâèòåëüíî äî ñëåäóþùåãî #PF |
save_ring3_context |
mov bl, 14 |
exc_c: ; èñêëþ÷åíèÿ (âñå, êðîìå 7-ãî - #NM) |
; Ôðýéì ñòåêà ïðè èñêëþ÷åíèè/ïðåðûâàíèè èç 3-ãî êîëüöà + pushad (ò.å., èìåííî çäåñü) |
reg_ss equ esp+0x30 |
reg_esp3 equ esp+0x2C |
reg_eflags equ esp+0x28 |
reg_cs3 equ esp+0x24 |
reg_eip equ esp+0x20 |
; ýòî ôðýéì îò pushad |
reg_eax equ esp+0x1C |
reg_ecx equ esp+0x18 |
reg_edx equ esp+0x14 |
reg_ebx equ esp+0x10 |
reg_esp0 equ esp+0x0C |
reg_ebp equ esp+0x08 |
reg_esi equ esp+0x04 |
reg_edi equ esp+0x00 |
mov ax, app_data ;èñêëþ÷åíèå |
mov ds, ax ;çàãðóçèì ïðàâèëüíûå çíà÷åíèÿ |
mov es, ax ;â ðåãèñòðû |
cld ; è ïðèâîäèì DF ê ñòàíäàðòó |
movzx ebx, bl |
; redirect to V86 manager? (EFLAGS & 0x20000) != 0? |
test byte[reg_eflags+2], 2 |
jnz v86_exc_c |
cmp bl, 14 ; #PF |
jne @f |
call page_fault_handler ; SEE: core/memory.inc |
@@: |
mov esi, [current_slot] |
btr [esi+APPDATA.except_mask], ebx |
jnc @f |
mov eax, [esi+APPDATA.exc_handler] |
test eax, eax |
jnz IRetToUserHook |
@@: |
cli |
mov eax, [esi+APPDATA.debugger_slot] |
test eax, eax |
jnz .debug |
sti |
; not debuggee => say error and terminate |
call show_error_parameters ;; only ONE using, inline ??? |
;mov edx, [TASK_BASE] |
mov [edx + TASKDATA.state], byte 4 ; terminate |
jmp change_task ; stack - here it does not matter at all, SEE: core/shed.inc |
.debug: |
; we are debugged process, notify debugger and suspend ourself |
; eax=debugger PID |
mov ecx, 1 ; debug_message code=other_exception |
cmp bl, 1 ; #DB |
jne .notify ; notify debugger and suspend ourself |
mov ebx, dr6 ; debug_message data=DR6_image |
xor edx, edx |
mov dr6, edx |
mov edx, dr7 |
mov cl, not 8 |
.l1: |
shl dl, 2 |
jc @f |
and bl, cl |
@@: |
sar cl, 1 |
jc .l1 |
mov cl, 3 ; debug_message code=debug_exception |
.notify: |
push ebx ; debug_message data |
mov ebx, [TASK_BASE] |
push [ebx+TASKDATA.pid] ; PID |
push ecx ; debug_message code ((here: ecx==1/3)) |
mov cl, 12 ; debug_message size |
call debugger_notify ;; only ONE using, inline ??? SEE: core/debug.inc |
add esp, 12 |
mov edx, [TASK_BASE] |
mov byte [edx+TASKDATA.state], 1 ; suspended |
call change_task ; SEE: core/shed.inc |
restore_ring3_context |
iretd |
IRetToUserHook: |
xchg eax, [reg_eip] |
sub dword[reg_esp3], 8 |
mov edi, [reg_esp3] |
stosd |
mov [edi], ebx |
restore_ring3_context |
; simply return control to interrupted process |
unknown_interrupt: |
iretd |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
; bl - error vector |
show_error_parameters: |
cmp bl, 0x06 |
jnz .no_ud |
push ebx |
mov ebx, ud_user_message |
mov ebp, notifyapp |
call fs_execute_from_sysdir_param |
pop ebx |
.no_ud: |
mov edx, [TASK_BASE];not scratched below |
DEBUGF 1, "K : Process - forced terminate PID: %x\n", [edx+TASKDATA.pid] |
cmp bl, 0x08 |
jb .l0 |
cmp bl, 0x0e |
jbe .l1 |
.l0: |
mov bl, 0x09 |
.l1: |
mov eax, [msg_fault_sel+ebx*4 - 0x08*4] |
DEBUGF 1, "K : %s\n", eax |
mov eax, [reg_cs3+4] |
mov edi, msg_sel_app |
mov ebx, [reg_esp3+4] |
cmp eax, app_code |
je @f |
mov edi, msg_sel_ker |
mov ebx, [reg_esp0+4] |
@@: |
DEBUGF 1, "K : EAX : %x EBX : %x ECX : %x\n", [reg_eax+4], [reg_ebx+4], [reg_ecx+4] |
DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [reg_edx+4], [reg_esi+4], [reg_edi+4] |
DEBUGF 1, "K : EBP : %x EIP : %x ESP : %x\n", [reg_ebp+4], [reg_eip+4], ebx |
DEBUGF 1, "K : Flags : %x CS : %x (%s)\n", [reg_eflags+4], eax, edi |
ret |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
restore reg_ss |
restore reg_esp3 |
restore reg_eflags |
restore reg_cs |
restore reg_eip |
restore reg_eax |
restore reg_ecx |
restore reg_edx |
restore reg_ebx |
restore reg_esp0 |
restore reg_ebp |
restore reg_esi |
restore reg_edi |
align 4 |
set_application_table_status: |
push eax |
mov eax, [CURRENT_TASK] |
shl eax, 5 |
add eax, CURRENT_TASK+TASKDATA.pid |
mov eax, [eax] |
mov [application_table_status], eax |
pop eax |
ret |
align 4 |
clear_application_table_status: |
push eax |
mov eax, [CURRENT_TASK] |
shl eax, 5 |
add eax, CURRENT_TASK+TASKDATA.pid |
mov eax, [eax] |
cmp eax, [application_table_status] |
jne apptsl1 |
xor eax, eax |
mov [application_table_status], eax |
apptsl1: |
pop eax |
ret |
; * eax = 64 - íîìåð ôóíêöèè |
; * ebx = 1 - åäèíñòâåííàÿ ïîäôóíêöèÿ |
; * ecx = íîâûé ðàçìåð ïàìÿòè |
;Âîçâðàùàåìîå çíà÷åíèå: |
; * eax = 0 - óñïåøíî |
; * eax = 1 - íåäîñòàòî÷íî ïàìÿòè |
align 4 |
sys_resize_app_memory: |
; ebx = 1 - resize |
; ecx = new amount of memory |
; cmp eax,1 |
dec ebx |
jnz .no_application_mem_resize |
stdcall new_mem_resize, ecx |
mov [esp+32], eax |
.no_application_mem_resize: |
ret |
iglobal |
; process_terminating db 'K : Process - terminating',13,10,0 |
; process_terminated db 'K : Process - done',13,10,0 |
msg_obj_destroy db 'K : destroy app object',13,10,0 |
endg |
; param |
; esi= slot |
align 4 |
terminate: ; terminate application |
.slot equ esp ;locals |
push esi ;save .slot |
shl esi, 8 |
cmp [SLOT_BASE+esi+APPDATA.dir_table], 0 |
jne @F |
pop esi |
shl esi, 5 |
mov [CURRENT_TASK+esi+TASKDATA.state], 9 |
ret |
@@: |
;mov esi,process_terminating |
;call sys_msg_board_str |
@@: |
cli |
cmp [application_table_status], 0 |
je term9 |
sti |
call change_task |
jmp @b |
term9: |
call set_application_table_status |
; if the process is in V86 mode... |
mov eax, [.slot] |
shl eax, 8 |
mov esi, [eax+SLOT_BASE+APPDATA.pl0_stack] |
add esi, RING0_STACK_SIZE |
cmp [eax+SLOT_BASE+APPDATA.saved_esp0], esi |
jz .nov86 |
; ...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 |
; ...and I/O permission map for V86 mode |
mov ecx, [esi+12] |
mov [eax+SLOT_BASE+APPDATA.io_map], ecx |
mov ecx, [esi+8] |
mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx |
.nov86: |
mov esi, [.slot] |
shl esi, 8 |
add esi, SLOT_BASE+APP_OBJ_OFFSET |
@@: |
mov eax, [esi+APPOBJ.fd] |
test eax, eax |
jz @F |
cmp eax, esi |
je @F |
push esi |
call [eax+APPOBJ.destroy] |
DEBUGF 1,"%s",msg_obj_destroy |
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 = 1 |
jne @F |
mov [fpu_owner], 1 |
mov eax, [256+SLOT_BASE+APPDATA.fpu_state] |
clts |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxrstor [eax] |
jmp @F |
.no_SSE: |
fnclex |
frstor [eax] |
@@: |
mov [KEY_COUNT], byte 0 ; empty keyboard buffer |
mov [BTN_COUNT], byte 0 ; empty button buffer |
; remove defined hotkeys |
mov eax, hotkey_list |
.loop: |
cmp [eax+8], esi |
jnz .cont |
mov ecx, [eax] |
jecxz @f |
push dword [eax+12] |
pop dword [ecx+12] |
@@: |
mov ecx, [eax+12] |
push dword [eax] |
pop dword [ecx] |
xor ecx, ecx |
mov [eax], ecx |
mov [eax+4], ecx |
mov [eax+8], ecx |
mov [eax+12], ecx |
.cont: |
add eax, 16 |
cmp eax, hotkey_list+256*16 |
jb .loop |
; remove hotkeys in buffer |
mov eax, hotkey_buffer |
.loop2: |
cmp [eax], esi |
jnz .cont2 |
and dword [eax+4], 0 |
and dword [eax], 0 |
.cont2: |
add eax, 8 |
cmp eax, hotkey_buffer+120*8 |
jb .loop2 |
mov ecx, esi ; remove buttons |
bnewba2: |
mov edi, [BTN_ADDR] |
mov eax, edi |
cld |
movzx ebx, word [edi] |
inc bx |
bnewba: |
dec bx |
jz bnmba |
add eax, 0x10 |
cmp cx, [eax] |
jnz bnewba |
pusha |
mov ecx, ebx |
inc ecx |
shl ecx, 4 |
mov ebx, eax |
add eax, 0x10 |
call memmove |
dec dword [edi] |
popa |
jmp bnewba2 |
bnmba: |
pusha ; save window coordinates for window restoring |
cld |
shl esi, 5 |
add esi, window_data |
mov eax, [esi+WDATA.box.left] |
mov [draw_limits.left], eax |
add eax, [esi+WDATA.box.width] |
mov [draw_limits.right], eax |
mov eax, [esi+WDATA.box.top] |
mov [draw_limits.top], eax |
add eax, [esi+WDATA.box.height] |
mov [draw_limits.bottom], eax |
xor eax, eax |
mov [esi+WDATA.box.left], eax |
mov [esi+WDATA.box.width], eax |
mov [esi+WDATA.box.top], eax |
mov [esi+WDATA.box.height], eax |
mov [esi+WDATA.cl_workarea], eax |
mov [esi+WDATA.cl_titlebar], eax |
mov [esi+WDATA.cl_frames], eax |
mov dword [esi+WDATA.reserved], eax; clear all flags: wstate, redraw, wdrawn |
lea edi, [esi-window_data+draw_data] |
mov ecx, 32/4 |
rep stosd |
popa |
; debuggee test |
pushad |
mov edi, esi |
shl edi, 5 |
mov eax, [SLOT_BASE+edi*8+APPDATA.debugger_slot] |
test eax, eax |
jz .nodebug |
push 8 |
pop ecx |
push dword [CURRENT_TASK+edi+TASKDATA.pid]; PID |
push 2 |
call debugger_notify |
pop ecx |
pop ecx |
.nodebug: |
popad |
mov ebx, [.slot] |
shl ebx, 8 |
push ebx |
mov ebx, [SLOT_BASE+ebx+APPDATA.pl0_stack] |
stdcall kernel_free, ebx |
pop ebx |
mov ebx, [SLOT_BASE+ebx+APPDATA.cur_dir] |
stdcall kernel_free, ebx |
mov edi, [.slot] |
shl edi, 8 |
add edi, SLOT_BASE |
mov eax, [edi+APPDATA.io_map] |
cmp eax, [SLOT_BASE+256+APPDATA.io_map] |
je @F |
call free_page |
@@: |
mov eax, [edi+APPDATA.io_map+4] |
cmp eax, [SLOT_BASE+256+APPDATA.io_map+4] |
je @F |
call free_page |
@@: |
mov eax, 0x20202020 |
stosd |
stosd |
stosd |
mov ecx, 244/4 |
xor eax, eax |
rep stosd |
; activate window |
movzx eax, word [WIN_STACK + esi*2] |
cmp eax, [TASK_COUNT] |
jne .dont_activate |
pushad |
.check_next_window: |
dec eax |
cmp eax, 1 |
jbe .nothing_to_activate |
lea esi, [WIN_POS+eax*2] |
movzx edi, word [esi] ; edi = process |
shl edi, 5 |
cmp [CURRENT_TASK + edi + TASKDATA.state], byte 9 ; skip dead slots |
je .check_next_window |
add edi, window_data |
; \begin{diamond}[19.09.2006] |
; skip minimized windows |
test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED |
jnz .check_next_window |
; \end{diamond} |
call waredraw |
.nothing_to_activate: |
popad |
.dont_activate: |
push esi ; remove hd1 & cd & flp reservation |
shl esi, 5 |
mov esi, [esi+CURRENT_TASK+TASKDATA.pid] |
cmp [hd1_status], esi |
jnz @f |
call free_hd_channel |
and [hd1_status], 0 |
@@: |
cmp [cd_status], esi |
jnz @f |
call free_cd_channel |
and [cd_status], 0 |
@@: |
cmp [flp_status], esi |
jnz @f |
and [flp_status], 0 |
@@: |
pop esi |
cmp [bgrlockpid], esi |
jnz @f |
and [bgrlockpid], 0 |
and [bgrlock], 0 |
@@: |
pusha ; remove all port reservations |
mov edx, esi |
shl edx, 5 |
add edx, CURRENT_TASK |
mov edx, [edx+TASKDATA.pid] |
rmpr0: |
mov esi, [RESERVED_PORTS] |
test esi, esi |
jz rmpr9 |
rmpr3: |
mov edi, esi |
shl edi, 4 |
add edi, RESERVED_PORTS |
cmp edx, [edi] |
je rmpr4 |
dec esi |
jnz rmpr3 |
jmp rmpr9 |
rmpr4: |
mov ecx, 256 |
sub ecx, esi |
shl ecx, 4 |
mov esi, edi |
add esi, 16 |
cld |
rep movsb |
dec dword [RESERVED_PORTS] |
jmp rmpr0 |
rmpr9: |
popa |
mov edi, esi ; do not run this process slot |
shl edi, 5 |
mov [edi+CURRENT_TASK + TASKDATA.state], byte 9 |
; debugger test - terminate all debuggees |
mov eax, 2 |
mov ecx, SLOT_BASE+2*0x100+APPDATA.debugger_slot |
.xd0: |
cmp eax, [TASK_COUNT] |
ja .xd1 |
cmp dword [ecx], esi |
jnz @f |
and dword [ecx], 0 |
pushad |
xchg eax, ecx |
mov ebx, 2 |
call sys_system |
popad |
@@: |
inc eax |
add ecx, 0x100 |
jmp .xd0 |
.xd1: |
; call systest |
sti ; .. and life goes on |
mov eax, [draw_limits.left] |
mov ebx, [draw_limits.top] |
mov ecx, [draw_limits.right] |
mov edx, [draw_limits.bottom] |
call calculatescreen |
xor eax, eax |
xor esi, esi |
call redrawscreen |
mov [MOUSE_BACKGROUND], byte 0; no mouse background |
mov [DONT_DRAW_MOUSE], byte 0; draw mouse |
and [application_table_status], 0 |
;mov esi,process_terminated |
;call sys_msg_board_str |
add esp, 4 |
ret |
restore .slot |
iglobal |
if lang eq ru |
boot_sched_1 db '®§¤ ¨¥ GDT TSS 㪠§ ⥫ï',0 |
boot_sched_2 db '®§¤ ¨¥ IDT â ¡«¨æë',0 |
else |
boot_sched_1 db 'Building gdt tss pointer',0 |
boot_sched_2 db 'Building IDT table',0 |
end if |
endg |
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 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/syscall.inc |
---|
1,200 → 1,200 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Old style system call converter |
align 16 |
cross_order: |
; load all registers in crossed order |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov edx, esi |
mov esi, edi |
movzx edi, byte[esp+28 + 4] |
sub edi,53 |
call dword [servetable+edi*4] |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSENTER ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
sysenter_entry: |
; Íàñòðàèâàåì ñòåê |
mov esp, [ss:tss._esp0] |
sti |
push ebp ; save app esp + 4 |
mov ebp, [ebp] ; ebp - original ebp |
;------------------ |
pushad |
cld |
movzx eax, al |
call dword [servetable2 + eax * 4] |
popad |
;------------------ |
xchg ecx, [ss:esp] ; â âåðøèí ñòåêà - app ecx, ecx - app esp + 4 |
sub ecx, 4 |
xchg edx, [ecx] ; edx - return point, & save original edx |
push edx |
mov edx, [ss:esp + 4] |
mov [ecx + 4], edx ; save original ecx |
pop edx |
sysexit |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSTEM CALL ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 16 |
i40: |
pushad |
cld |
movzx eax, al |
call dword [servetable2 + eax * 4] |
popad |
iretd |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSCALL ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
syscall_entry: |
; cli syscall clear IF |
xchg esp, [ss:tss._esp0] |
push ecx |
lea ecx, [esp+4] |
xchg ecx, [ss:tss._esp0] |
sti |
push ecx |
mov ecx, [ecx] |
;------------------ |
pushad |
cld |
movzx eax, al |
call dword [servetable2 + eax * 4] |
popad |
;------------------ |
mov ecx, [ss:esp+4] |
pop esp |
sysret |
iglobal |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; SYSTEM FUNCTIONS TABLE ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
servetable: |
dd socket ; 53-Socket interface |
dd 0 |
dd 0 |
dd 0 |
dd 0 |
dd file_system ; 58-Common file system interface |
dd 0 |
dd 0 |
dd 0 |
dd 0 ; 62-PCI functions |
dd sys_msg_board ; 63-System message board |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; NEW SYSTEM FUNCTIONS TABLE ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
servetable2: |
dd syscall_draw_window ; 0-DrawWindow |
dd syscall_setpixel ; 1-SetPixel |
dd sys_getkey ; 2-GetKey |
dd sys_clock ; 3-GetTime |
dd syscall_writetext ; 4-WriteText |
dd delay_hs ; 5-DelayHs |
dd syscall_openramdiskfile ; 6-OpenRamdiskFile |
dd syscall_putimage ; 7-PutImage |
dd syscall_button ; 8-DefineButton |
dd sys_cpuusage ; 9-GetProcessInfo |
dd sys_waitforevent ; 10-WaitForEvent |
dd sys_getevent ; 11-CheckForEvent |
dd sys_redrawstat ; 12-BeginDraw and EndDraw |
dd syscall_drawrect ; 13-DrawRect |
dd syscall_getscreensize ; 14-GetScreenSize |
dd sys_background ; 15-bgr |
dd sys_cachetodiskette ; 16-FlushFloppyCache |
dd sys_getbutton ; 17-GetButton |
dd sys_system ; 18-System Services |
dd paleholder ; 19-reserved |
dd sys_midi ; 20-ResetMidi and OutputMidi |
dd sys_setup ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,. |
dd sys_settime ; 22-setting date,time,clock and alarm-clock |
dd sys_wait_event_timeout ; 23-TimeOutWaitForEvent |
dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist |
dd undefined_syscall ; 25-reserved |
dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,. |
dd undefined_syscall ; 27-reserved |
dd undefined_syscall ; 28-reserved |
dd sys_date ; 29-GetDate |
dd sys_current_directory ; 30-Get/SetCurrentDirectory |
dd undefined_syscall ; 31-reserved |
dd undefined_syscall ; 32-reserved |
dd undefined_syscall ; 33-reserved |
dd undefined_syscall ; 34-reserved |
dd syscall_getpixel ; 35-GetPixel |
dd syscall_getarea ; 36-GetArea |
dd readmousepos ; 37-GetMousePosition_ScreenRelative,. |
dd syscall_drawline ; 38-DrawLine |
dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,. |
dd set_app_param ; 40-WantEvents |
dd undefined_syscall ; 41- deprecated GetIrqOwner |
dd undefined_syscall ; 42- deprecated ReadIrqData |
dd sys_outport ; 43-SendDeviceData |
dd undefined_syscall ; 44- deprecated ProgramIrqs |
dd undefined_syscall ; 45- deprecated ReserveIrq and FreeIrq |
dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea |
dd display_number ; 47-WriteNum |
dd syscall_display_settings ; 48-SetRedrawType and SetButtonType |
dd sys_apm ; 49-Advanced Power Management (APM) |
dd syscall_set_window_shape ; 50-Window shape & scale |
dd syscall_threads ; 51-Threads |
dd stack_driver_stat ; 52-Stack driver status |
dd cross_order ; 53-Socket interface |
dd undefined_syscall ; 54-reserved |
dd sound_interface ; 55-Sound interface |
dd undefined_syscall ; 56-reserved |
dd sys_pcibios ; 57-PCI BIOS32 |
dd cross_order ; 58-Common file system interface |
dd undefined_syscall ; 59-reserved |
dd sys_IPC ; 60-Inter Process Communication |
dd sys_gs ; 61-Direct graphics access |
dd pci_api ;cross_order ; 62-PCI functions |
dd cross_order ; 63-System message board |
dd sys_resize_app_memory ; 64-Resize application memory usage |
dd sys_putimage_palette ; 65-PutImagePalette |
dd sys_process_def ; 66-Process definitions - keyboard |
dd syscall_move_window ; 67-Window move or resize |
dd f68 ; 68-Some internal services |
dd sys_debug_services ; 69-Debug |
dd file_system_lfn ; 70-Common file system interface, version 2 |
dd syscall_window_settings ; 71-Window settings |
dd sys_sendwindowmsg ; 72-Send window message |
dd blit_32 ; 73-blitter; |
times 255 - ( ($-servetable2) /4 ) dd undefined_syscall |
dd sys_end ; -1-end application |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Old style system call converter |
align 16 |
cross_order: |
; load all registers in crossed order |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov edx, esi |
mov esi, edi |
movzx edi, byte[esp+28 + 4] |
sub edi, 53 |
call dword [servetable+edi*4] |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSENTER ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
sysenter_entry: |
; Íàñòðàèâàåì ñòåê |
mov esp, [ss:tss._esp0] |
sti |
push ebp ; save app esp + 4 |
mov ebp, [ebp] ; ebp - original ebp |
;------------------ |
pushad |
cld |
movzx eax, al |
call dword [servetable2 + eax * 4] |
popad |
;------------------ |
xchg ecx, [ss:esp] ; â âåðøèí ñòåêà - app ecx, ecx - app esp + 4 |
sub ecx, 4 |
xchg edx, [ecx] ; edx - return point, & save original edx |
push edx |
mov edx, [ss:esp + 4] |
mov [ecx + 4], edx ; save original ecx |
pop edx |
sysexit |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSTEM CALL ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 16 |
i40: |
pushad |
cld |
movzx eax, al |
call dword [servetable2 + eax * 4] |
popad |
iretd |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSCALL ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
syscall_entry: |
; cli syscall clear IF |
xchg esp, [ss:tss._esp0] |
push ecx |
lea ecx, [esp+4] |
xchg ecx, [ss:tss._esp0] |
sti |
push ecx |
mov ecx, [ecx] |
;------------------ |
pushad |
cld |
movzx eax, al |
call dword [servetable2 + eax * 4] |
popad |
;------------------ |
mov ecx, [ss:esp+4] |
pop esp |
sysret |
iglobal |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; SYSTEM FUNCTIONS TABLE ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
servetable: |
dd socket ; 53-Socket interface |
dd 0 |
dd 0 |
dd 0 |
dd 0 |
dd file_system ; 58-Common file system interface |
dd 0 |
dd 0 |
dd 0 |
dd 0 ; 62-PCI functions |
dd sys_msg_board ; 63-System message board |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; NEW SYSTEM FUNCTIONS TABLE ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
servetable2: |
dd syscall_draw_window ; 0-DrawWindow |
dd syscall_setpixel ; 1-SetPixel |
dd sys_getkey ; 2-GetKey |
dd sys_clock ; 3-GetTime |
dd syscall_writetext ; 4-WriteText |
dd delay_hs ; 5-DelayHs |
dd syscall_openramdiskfile ; 6-OpenRamdiskFile |
dd syscall_putimage ; 7-PutImage |
dd syscall_button ; 8-DefineButton |
dd sys_cpuusage ; 9-GetProcessInfo |
dd sys_waitforevent ; 10-WaitForEvent |
dd sys_getevent ; 11-CheckForEvent |
dd sys_redrawstat ; 12-BeginDraw and EndDraw |
dd syscall_drawrect ; 13-DrawRect |
dd syscall_getscreensize ; 14-GetScreenSize |
dd sys_background ; 15-bgr |
dd sys_cachetodiskette ; 16-FlushFloppyCache |
dd sys_getbutton ; 17-GetButton |
dd sys_system ; 18-System Services |
dd paleholder ; 19-reserved |
dd sys_midi ; 20-ResetMidi and OutputMidi |
dd sys_setup ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,. |
dd sys_settime ; 22-setting date,time,clock and alarm-clock |
dd sys_wait_event_timeout ; 23-TimeOutWaitForEvent |
dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist |
dd undefined_syscall ; 25-reserved |
dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,. |
dd undefined_syscall ; 27-reserved |
dd undefined_syscall ; 28-reserved |
dd sys_date ; 29-GetDate |
dd sys_current_directory ; 30-Get/SetCurrentDirectory |
dd undefined_syscall ; 31-reserved |
dd undefined_syscall ; 32-reserved |
dd undefined_syscall ; 33-reserved |
dd undefined_syscall ; 34-reserved |
dd syscall_getpixel ; 35-GetPixel |
dd syscall_getarea ; 36-GetArea |
dd readmousepos ; 37-GetMousePosition_ScreenRelative,. |
dd syscall_drawline ; 38-DrawLine |
dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,. |
dd set_app_param ; 40-WantEvents |
dd undefined_syscall ; 41- deprecated GetIrqOwner |
dd undefined_syscall ; 42- deprecated ReadIrqData |
dd sys_outport ; 43-SendDeviceData |
dd undefined_syscall ; 44- deprecated ProgramIrqs |
dd undefined_syscall ; 45- deprecated ReserveIrq and FreeIrq |
dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea |
dd display_number ; 47-WriteNum |
dd syscall_display_settings ; 48-SetRedrawType and SetButtonType |
dd sys_apm ; 49-Advanced Power Management (APM) |
dd syscall_set_window_shape ; 50-Window shape & scale |
dd syscall_threads ; 51-Threads |
dd stack_driver_stat ; 52-Stack driver status |
dd cross_order ; 53-Socket interface |
dd undefined_syscall ; 54-reserved |
dd sound_interface ; 55-Sound interface |
dd undefined_syscall ; 56-reserved |
dd sys_pcibios ; 57-PCI BIOS32 |
dd cross_order ; 58-Common file system interface |
dd undefined_syscall ; 59-reserved |
dd sys_IPC ; 60-Inter Process Communication |
dd sys_gs ; 61-Direct graphics access |
dd pci_api ;cross_order ; 62-PCI functions |
dd cross_order ; 63-System message board |
dd sys_resize_app_memory ; 64-Resize application memory usage |
dd sys_putimage_palette ; 65-PutImagePalette |
dd sys_process_def ; 66-Process definitions - keyboard |
dd syscall_move_window ; 67-Window move or resize |
dd f68 ; 68-Some internal services |
dd sys_debug_services ; 69-Debug |
dd file_system_lfn ; 70-Common file system interface, version 2 |
dd syscall_window_settings ; 71-Window settings |
dd sys_sendwindowmsg ; 72-Send window message |
dd blit_32 ; 73-blitter; |
times 255 - ( ($-servetable2) /4 ) dd undefined_syscall |
dd sys_end ; -1-end application |
endg |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/taskman.inc |
---|
1,1161 → 1,1161 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
GREEDY_KERNEL equ 0 |
struc APP_HEADER_00 |
{ .banner dq ? |
.version dd ? ;+8 |
.start dd ? ;+12 |
.i_end dd ? ;+16 |
.mem_size dd ? ;+20 |
.i_param dd ? ;+24 |
} |
struc APP_HEADER_01 |
{ .banner dq ? |
.version dd ? ;+8 |
.start dd ? ;+12 |
.i_end dd ? ;+16 |
.mem_size dd ? ;+20 |
.stack_top dd ? ;+24 |
.i_param dd ? ;+28 |
.i_icon dd ? ;+32 |
} |
struc APP_PARAMS |
{ .app_cmdline ;0x00 |
.app_path ;0x04 |
.app_eip ;0x08 |
.app_esp ;0x0C |
.app_mem ;0x10 |
} |
macro _clear_ op |
{ mov ecx, op/4 |
xor eax, eax |
cld |
rep stosd |
} |
fs_execute_from_sysdir: |
xor ebx, ebx |
fs_execute_from_sysdir_param: |
xor edx, edx |
mov esi, sysdir_path |
align 4 |
proc fs_execute |
;fn_read:dword, file_size:dword, cluster:dword |
; ebx - cmdline |
; edx - flags |
; ebp - full filename |
; [esp+4] = procedure DoRead, [esp+8] = filesize & [esp+12]... - arguments for it |
locals |
cmdline rd 64 ;256/4 |
filename rd 256 ;1024/4 |
flags dd ? |
save_cr3 dd ? |
slot dd ? |
slot_base dd ? |
file_base dd ? |
file_size dd ? |
;app header data |
hdr_cmdline dd ? ;0x00 |
hdr_path dd ? ;0x04 |
hdr_eip dd ? ;0x08 |
hdr_esp dd ? ;0x0C |
hdr_mem dd ? ;0x10 |
hdr_i_end dd ? ;0x14 |
endl |
pushad |
mov [flags], edx |
; [ebp] pointer to filename |
lea edi, [filename] |
lea ecx, [edi+1024] |
mov al, '/' |
stosb |
@@: |
cmp edi, ecx |
jae .bigfilename |
lodsb |
stosb |
test al, al |
jnz @b |
mov esi, [ebp] |
test esi, esi |
jz .namecopied |
mov byte [edi-1], '/' |
@@: |
cmp edi, ecx |
jae .bigfilename |
lodsb |
stosb |
test al, al |
jnz @b |
jmp .namecopied |
.bigfilename: |
popad |
mov eax, -ERROR_FILE_NOT_FOUND |
ret |
.namecopied: |
mov [cmdline], ebx |
test ebx, ebx |
jz @F |
lea eax, [cmdline] |
mov dword [eax+252], 0 |
stdcall strncpy, eax, ebx, 255 |
@@: |
lea eax, [filename] |
stdcall load_file, eax |
mov esi, -ERROR_FILE_NOT_FOUND |
test eax, eax |
jz .err_file |
mov [file_base], eax |
mov [file_size], ebx |
lea ebx, [hdr_cmdline] |
call test_app_header |
mov esi, -0x1F |
test eax, eax |
jz .err_hdr |
.wait_lock: |
cmp [application_table_status],0 |
je .get_lock |
call change_task |
jmp .wait_lock |
.get_lock: |
mov eax, 1 |
xchg eax, [application_table_status] |
test eax, eax |
jnz .wait_lock |
call set_application_table_status |
call get_new_process_place |
test eax, eax |
mov esi, -0x20 ; too many processes |
jz .err |
mov [slot], eax |
shl eax, 8 |
add eax, SLOT_BASE |
mov [slot_base], eax |
mov edi, eax |
_clear_ 256 ;clean extended information about process |
; write application name |
lea eax, [filename] |
stdcall strrchr, eax, '/' ; now eax points to name without path |
lea esi, [eax+1] |
test eax, eax |
jnz @F |
lea esi, [filename] |
@@: |
mov ecx, 8 ; 8 chars for name |
mov edi, [slot_base] |
.copy_process_name_loop: |
lodsb |
cmp al, '.' |
jz .copy_process_name_done |
test al, al |
jz .copy_process_name_done |
stosb |
loop .copy_process_name_loop |
.copy_process_name_done: |
mov ebx, cr3 |
mov [save_cr3], ebx |
stdcall create_app_space,[hdr_mem],[file_base],[file_size] |
mov esi, -30 ; no memory |
test eax, eax |
jz .failed |
mov ebx,[slot_base] |
mov [ebx+APPDATA.dir_table],eax |
mov eax,[hdr_mem] |
mov [ebx+APPDATA.mem_size],eax |
xor edx, edx |
cmp word [6], '02' |
jne @f |
not edx |
@@: |
mov [ebx+APPDATA.tls_base],edx |
if GREEDY_KERNEL |
else |
mov ecx, [hdr_mem] |
mov edi, [file_size] |
add edi, 4095 |
and edi, not 4095 |
sub ecx, edi |
jna @F |
xor eax, eax |
cld |
rep stosb |
@@: |
end if |
; release only virtual space, not phisical memory |
stdcall free_kernel_space, [file_base] |
lea eax, [hdr_cmdline] |
lea ebx, [cmdline] |
lea ecx, [filename] |
stdcall set_app_params ,[slot],eax,ebx,ecx,[flags] |
mov eax, [save_cr3] |
call set_cr3 |
xor ebx, ebx |
mov [application_table_status],ebx ;unlock application_table_status mutex |
mov eax,[process_number] ;set result |
ret |
.failed: |
mov eax, [save_cr3] |
call set_cr3 |
.err: |
.err_hdr: |
stdcall kernel_free,[file_base] |
.err_file: |
xor eax, eax |
mov [application_table_status],eax |
mov eax, esi |
ret |
endp |
align 4 |
test_app_header: |
virtual at eax |
APP_HEADER_00 APP_HEADER_00 |
end virtual |
virtual at eax |
APP_HEADER_01 APP_HEADER_01 |
end virtual |
cmp dword [eax], 'MENU' |
jne .fail |
cmp word [eax+4],'ET' |
jne .fail |
cmp [eax+6], word '00' |
jne .check_01_header |
mov ecx,[APP_HEADER_00.start] |
mov [ebx+0x08], ecx ;app_eip |
mov edx,[APP_HEADER_00.mem_size] |
mov [ebx+0x10], edx ;app_mem |
shr edx,1 |
sub edx,0x10 |
mov [ebx+0x0C], edx ;app_esp |
mov ecx,[APP_HEADER_00.i_param] |
mov [ebx], ecx ;app_cmdline |
mov [ebx+4], dword 0 ;app_path |
mov edx, [APP_HEADER_00.i_end] |
mov [ebx+0x14], edx |
ret |
.check_01_header: |
cmp [eax+6], word '01' |
je @f |
cmp [eax+6], word '02' |
jne .fail |
@@: |
mov ecx,[APP_HEADER_01.start] |
mov [ebx+0x08], ecx ;app_eip |
mov edx,[APP_HEADER_01.mem_size] |
; \begin{diamond}[20.08.2006] |
; sanity check (functions 19,58 load app_i_end bytes and that must |
; fit in allocated memory to prevent kernel faults) |
cmp edx,[APP_HEADER_01.i_end] |
jb .fail |
; \end{diamond}[20.08.2006] |
mov [ebx+0x10], edx ;app_mem |
mov ecx,[APP_HEADER_01.stack_top] |
mov [ebx+0x0C], ecx ;app_esp |
mov edx,[APP_HEADER_01.i_param] |
mov [ebx], edx ;app_cmdline |
mov ecx,[APP_HEADER_01.i_icon] |
mov [ebx+4], ecx ;app_path |
mov edx, [APP_HEADER_01.i_end] |
mov [ebx+0x14], edx |
ret |
.fail: |
xor eax, eax |
ret |
align 4 |
proc get_new_process_place |
;input: |
; none |
;result: |
; eax=[new_process_place]<>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: |
xor eax,eax |
ret |
endp |
align 4 |
proc create_app_space stdcall, app_size:dword,img_base:dword,img_size:dword |
locals |
app_pages dd ? |
img_pages dd ? |
dir_addr dd ? |
app_tabs dd ? |
endl |
mov ecx, pg_data.mutex |
call mutex_lock |
xor eax, eax |
mov [dir_addr], eax |
mov eax, [app_size] |
add eax, 4095 |
and eax, NOT(4095) |
mov [app_size], eax |
mov ebx, eax |
shr eax, 12 |
mov [app_pages], eax |
add ebx, 0x3FFFFF |
and ebx, NOT(0x3FFFFF) |
shr ebx, 22 |
mov [app_tabs], ebx |
mov ecx, [img_size] |
add ecx, 4095 |
and ecx, NOT(4095) |
mov [img_size], ecx |
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 |
test eax, eax |
jz .fail |
mov [dir_addr], eax |
stdcall map_page,[tmp_task_pdir],eax,dword PG_SW |
mov edi, [tmp_task_pdir] |
mov ecx, (OS_BASE shr 20)/4 |
xor eax, eax |
cld |
rep stosd |
mov ecx, (OS_BASE shr 20)/4 |
mov esi, sys_pgdir+(OS_BASE shr 20) |
rep movsd |
mov eax, [dir_addr] |
or eax, PG_SW |
mov [edi-4096+(page_tabs shr 20)], eax |
and eax, -4096 |
call set_cr3 |
mov edx, [app_tabs] |
mov edi, new_app_base |
@@: |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page_table, edi, eax |
add edi, 0x00400000 |
dec edx |
jnz @B |
mov edi, new_app_base |
shr edi, 10 |
add edi, page_tabs |
mov ecx, [app_tabs] |
shl ecx, 10 |
xor eax, eax |
rep stosd |
mov ecx, [img_pages] |
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 |
.remap: |
lodsd |
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 |
jz .done |
if GREEDY_KERNEL |
mov eax, 0x02 |
rep stosd |
else |
.alloc: |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page,edx,eax,dword PG_UW |
add edx, 0x1000 |
dec [app_pages] |
jnz .alloc |
end if |
.done: |
stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP |
mov ecx, pg_data.mutex |
call mutex_unlock |
mov eax, [dir_addr] |
ret |
.fail: |
mov ecx, pg_data.mutex |
call mutex_unlock |
cmp [dir_addr], 0 |
je @f |
stdcall destroy_app_space, [dir_addr], 0 |
@@: |
xor eax, eax |
ret |
endp |
align 4 |
set_cr3: |
mov ebx, [current_slot] |
mov [ebx+APPDATA.dir_table], eax |
mov cr3, eax |
ret |
align 4 |
proc destroy_page_table stdcall, pg_tab:dword |
push esi |
mov esi, [pg_tab] |
mov ecx, 1024 |
.free: |
mov eax, [esi] |
test eax, 1 |
jz .next |
test eax, 1 shl 9 |
jnz .next ;skip shared pages |
call free_page |
.next: |
add esi, 4 |
dec ecx |
jnz .free |
pop esi |
ret |
endp |
align 4 |
proc destroy_app_space stdcall, pg_dir:dword, dlls_list:dword |
xor edx,edx |
push edx |
mov eax,0x2 |
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 |
;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 |
mov ecx, pg_data.mutex |
call mutex_lock |
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 |
.destroy: |
mov eax, [esi] |
test eax, 1 |
jz .next |
and eax, not 0xFFF |
stdcall map_page,[tmp_task_ptab],eax,PG_SW |
stdcall destroy_page_table, [tmp_task_ptab] |
mov eax, [esi] |
call free_page |
.next: |
add esi, 4 |
dec edi |
jnz .destroy |
mov eax, [pg_dir] |
call free_page |
.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: |
mov eax, [TASK_BASE] |
mov eax, [eax+TASKDATA.pid] |
ret |
pid_to_slot: |
;Input: |
; eax - pid of process |
;Output: |
; eax - slot of process or 0 if process don't exists |
;Search process by PID. |
push ebx |
push ecx |
mov ebx,[TASK_COUNT] |
shl ebx,5 |
mov ecx,2*32 |
.loop: |
;ecx=offset of current process info entry |
;ebx=maximum permitted offset |
cmp byte [CURRENT_TASK+ecx+0xa],9 |
jz .endloop ;skip empty slots |
cmp [CURRENT_TASK+ecx+0x4],eax ;check PID |
jz .pid_found |
.endloop: |
add ecx,32 |
cmp ecx,ebx |
jle .loop |
pop ecx |
pop ebx |
xor eax,eax |
ret |
.pid_found: |
shr ecx,5 |
mov eax,ecx ;convert offset to index of slot |
pop ecx |
pop ebx |
ret |
check_region: |
;input: |
; esi - start of buffer |
; edx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
mov eax,[CURRENT_TASK] |
; jmp check_process_region |
;----------------------------------------------------------------------------- |
;check_process_region: |
;input: |
; eax - slot |
; esi - start of buffer |
; edx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
test edx,edx |
jle .ok |
shl eax,5 |
cmp word [CURRENT_TASK+eax+0xa],0 |
jnz .failed |
shl eax,3 |
mov eax,[SLOT_BASE+eax+0xb8] |
test eax,eax |
jz .failed |
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 |
align 4 |
proc read_process_memory |
;Input: |
; eax - process slot |
; ecx - buffer address |
; edx - buffer size |
; esi - start address in other process |
;Output: |
; eax - number of bytes read. |
locals |
slot dd ? |
buff dd ? |
r_count dd ? |
offset dd ? |
tmp_r_cnt dd ? |
endl |
mov [slot], eax |
mov [buff], ecx |
and [r_count], 0 |
mov [tmp_r_cnt], edx |
mov [offset], esi |
pushad |
.read_mem: |
mov edx, [offset] |
mov ebx, [tmp_r_cnt] |
mov ecx, 0x400000 |
and edx, 0x3FFFFF |
sub ecx, edx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
cmp ecx, 0x8000 |
jna @F |
mov ecx, 0x8000 |
@@: |
mov ebx, [offset] |
push ecx |
stdcall map_memEx, [proc_mem_map],\ |
[slot], ebx, ecx, PG_MAP |
pop ecx |
mov esi, [offset] |
and esi, 0xfff |
sub eax, esi |
jbe .ret |
cmp ecx, eax |
jbe @f |
mov ecx, eax |
mov [tmp_r_cnt], eax |
@@: |
add esi, [proc_mem_map] |
mov edi, [buff] |
mov edx, ecx |
rep movsb |
add [r_count], edx |
add [offset], edx |
sub [tmp_r_cnt], edx |
jnz .read_mem |
.ret: |
popad |
mov eax, [r_count] |
ret |
endp |
align 4 |
proc write_process_memory |
;Input: |
; eax - process slot |
; ecx - buffer address |
; edx - buffer size |
; esi - start address in other process |
;Output: |
; eax - number of bytes written |
locals |
slot dd ? |
buff dd ? |
w_count dd ? |
offset dd ? |
tmp_w_cnt dd ? |
endl |
mov [slot], eax |
mov [buff], ecx |
and [w_count], 0 |
mov [tmp_w_cnt], edx |
mov [offset], esi |
pushad |
.read_mem: |
mov edx, [offset] |
mov ebx, [tmp_w_cnt] |
mov ecx, 0x400000 |
and edx, 0x3FFFFF |
sub ecx, edx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
cmp ecx, 0x8000 |
jna @F |
mov ecx, 0x8000 |
@@: |
mov ebx, [offset] |
; add ebx, new_app_base |
push ecx |
stdcall map_memEx, [proc_mem_map],\ |
[slot], ebx, ecx, PG_SW |
pop ecx |
mov edi, [offset] |
and edi, 0xfff |
sub eax, edi |
jbe .ret |
cmp ecx, eax |
jbe @f |
mov ecx, eax |
mov [tmp_w_cnt], eax |
@@: |
add edi, [proc_mem_map] |
mov esi, [buff] |
mov edx, ecx |
rep movsb |
add [w_count], edx |
add [offset], edx |
sub [tmp_w_cnt], edx |
jnz .read_mem |
.ret: |
popad |
mov eax, [w_count] |
ret |
endp |
align 4 |
proc new_sys_threads |
locals |
slot dd ? |
app_cmdline dd ? ;0x00 |
app_path dd ? ;0x04 |
app_eip dd ? ;0x08 |
app_esp dd ? ;0x0C |
app_mem dd ? ;0x10 |
endl |
cmp ebx,1 |
jne .failed ;other subfunctions |
xor eax,eax |
mov [app_eip], ecx |
mov [app_cmdline], eax |
mov [app_esp], edx |
mov [app_path], eax |
;mov esi,new_process_loading |
;call sys_msg_board_str |
.wait_lock: |
cmp [application_table_status],0 |
je .get_lock |
call change_task |
jmp .wait_lock |
.get_lock: |
mov eax, 1 |
xchg eax, [application_table_status] |
test eax, eax |
jnz .wait_lock |
call set_application_table_status |
call get_new_process_place |
test eax, eax |
jz .failed |
mov [slot], eax |
mov esi,[current_slot] |
mov ebx,esi ;ebx=esi - pointer to extended information about current thread |
mov edi, eax |
shl edi,8 |
add edi,SLOT_BASE |
mov edx,edi ;edx=edi - pointer to extended infomation about new thread |
mov ecx,256/4 |
xor eax, eax |
cld |
rep stosd ;clean extended information about new thread |
mov esi,ebx |
mov edi,edx |
mov ecx,11 |
rep movsb ;copy process name |
mov eax,[ebx+APPDATA.heap_base] |
mov [edx+APPDATA.heap_base], eax |
mov ecx,[ebx+APPDATA.heap_top] |
mov [edx+APPDATA.heap_top], ecx |
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 |
push edx |
stdcall user_alloc, 4096 |
pop edx |
test eax, eax |
jz .failed1 ;eax=0 |
@@: |
mov [edx+APPDATA.tls_base], eax |
lea eax, [app_cmdline] |
stdcall set_app_params ,[slot],eax,dword 0,\ |
dword 0,dword 0 |
;mov esi,new_process_running |
;call sys_msg_board_str ;output information about succefull startup |
xor eax,eax |
mov [application_table_status],eax ;unlock application_table_status mutex |
mov eax,[process_number] ;set result |
ret |
.failed: |
xor eax,eax |
.failed1: |
mov [application_table_status],eax |
dec eax ;-1 |
ret |
endp |
align 4 |
tls_app_entry: |
call init_heap |
stdcall user_alloc, 4096 |
mov edx, [current_slot] |
mov [edx+APPDATA.tls_base], eax |
mov [tls_data_l+2],ax |
shr eax,16 |
mov [tls_data_l+4],al |
mov [tls_data_l+7],ah |
mov dx, app_tls |
mov fs, dx |
popad |
iretd |
EFL_IF equ 0x0200 |
EFL_IOPL1 equ 0x1000 |
EFL_IOPL2 equ 0x2000 |
EFL_IOPL3 equ 0x3000 |
align 4 |
proc set_app_params stdcall,slot:dword, params:dword,\ |
cmd_line:dword, app_path:dword, flags:dword |
locals |
pl0_stack dd ? |
endl |
stdcall kernel_alloc, RING0_STACK_SIZE+512 |
mov [pl0_stack], eax |
lea edi, [eax+RING0_STACK_SIZE] |
mov eax, [slot] |
mov ebx, eax |
shl eax, 8 |
mov [eax+SLOT_BASE+APPDATA.fpu_state], edi |
mov [eax+SLOT_BASE+APPDATA.exc_handler], 0 |
mov [eax+SLOT_BASE+APPDATA.except_mask], 0 |
;set default io permission map |
mov ecx, [SLOT_BASE+256+APPDATA.io_map] |
mov [eax+SLOT_BASE+APPDATA.io_map], ecx |
mov ecx, [SLOT_BASE+256+APPDATA.io_map+4] |
mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx |
mov esi, fpu_data |
mov ecx, 512/4 |
rep movsd |
cmp ebx,[TASK_COUNT] |
jle .noinc |
inc dword [TASK_COUNT] ;update number of processes |
.noinc: |
shl ebx,8 |
lea edx, [ebx+SLOT_BASE+APP_EV_OFFSET] |
mov [SLOT_BASE+APPDATA.fd_ev+ebx],edx |
mov [SLOT_BASE+APPDATA.bk_ev+ebx],edx |
add edx, APP_OBJ_OFFSET-APP_EV_OFFSET |
mov [SLOT_BASE+APPDATA.fd_obj+ebx],edx |
mov [SLOT_BASE+APPDATA.bk_obj+ebx],edx |
mov ecx, [def_cursor] |
mov [SLOT_BASE+APPDATA.cursor+ebx],ecx |
mov eax, [pl0_stack] |
mov [SLOT_BASE+APPDATA.pl0_stack+ebx],eax |
add eax, RING0_STACK_SIZE |
mov [SLOT_BASE+APPDATA.saved_esp0+ebx], eax |
push ebx |
stdcall kernel_alloc, 0x1000 |
pop ebx |
mov esi,[current_slot] |
mov esi,[esi+APPDATA.cur_dir] |
mov ecx,0x1000/4 |
mov edi,eax |
mov [ebx+SLOT_BASE+APPDATA.cur_dir],eax |
rep movsd |
shr ebx,3 |
mov eax, new_app_base |
mov dword [CURRENT_TASK+ebx+0x10],eax |
.add_command_line: |
mov edx,[params] |
mov edx,[edx] ;app_cmdline |
test edx,edx |
jz @f ;application doesn't need parameters |
mov eax, edx |
add eax, 256 |
jc @f |
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8] |
ja @f |
mov byte [edx], 0 ;force empty string if no cmdline given |
mov eax, [cmd_line] |
test eax, eax |
jz @f |
stdcall strncpy, edx, eax, 256 |
@@: |
mov edx,[params] |
mov edx, [edx+4] ;app_path |
test edx,edx |
jz @F ;application don't need path of file |
mov eax, edx |
add eax, 1024 |
jc @f |
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8] |
ja @f |
stdcall strncpy, edx, [app_path], 1024 |
@@: |
mov ebx,[slot] |
mov eax,ebx |
shl ebx,5 |
lea ecx,[draw_data+ebx] ;ecx - pointer to draw data |
mov edx, irq0.return |
cmp [ebx*8+SLOT_BASE+APPDATA.tls_base], -1 |
jne @F |
mov edx, tls_app_entry |
@@: |
; set window state to 'normal' (non-minimized/maximized/rolled-up) state |
mov [ebx+window_data+WDATA.fl_wstate], WSTATE_NORMAL |
mov [ebx+window_data+WDATA.fl_redraw], 1 |
add ebx,CURRENT_TASK ;ebx - pointer to information about process |
mov [ebx+TASKDATA.wnd_number],al;set window number on screen = process slot |
mov [ebx+TASKDATA.event_mask],dword 1+2+4 ;set default event flags (see 40 function) |
inc dword [process_number] |
mov eax,[process_number] |
mov [ebx+4],eax ;set PID |
;set draw data to full screen |
xor eax,eax |
mov [ecx+0],dword eax |
mov [ecx+4],dword eax |
mov eax,[Screen_Max_X] |
mov [ecx+8],eax |
mov eax,[Screen_Max_Y] |
mov [ecx+12],eax |
mov ebx, [pl0_stack] |
mov esi,[params] |
lea ecx, [ebx+REG_EIP] |
xor eax, eax |
mov [ebx+REG_RET], edx |
mov [ebx+REG_EDI], eax |
mov [ebx+REG_ESI], eax |
mov [ebx+REG_EBP], eax |
mov [ebx+REG_ESP], ecx ;ebx+REG_EIP |
mov [ebx+REG_EBX], eax |
mov [ebx+REG_EDX], eax |
mov [ebx+REG_ECX], eax |
mov [ebx+REG_EAX], eax |
mov eax, [esi+0x08] ;app_eip |
mov [ebx+REG_EIP], eax ;app_entry |
mov [ebx+REG_CS], dword app_code |
mov [ebx+REG_EFLAGS], dword EFL_IOPL1+EFL_IF |
mov eax, [esi+0x0C] ;app_esp |
mov [ebx+REG_APP_ESP], eax ;app_stack |
mov [ebx+REG_SS], dword app_data |
lea ecx, [ebx+REG_RET] |
mov ebx, [slot] |
shl ebx, 5 |
mov [ebx*8+SLOT_BASE+APPDATA.saved_esp], ecx |
xor ecx, ecx ; process state - running |
; set if debuggee |
test byte [flags], 1 |
jz .no_debug |
inc ecx ; process state - suspended |
mov eax,[CURRENT_TASK] |
mov [SLOT_BASE+ebx*8+APPDATA.debugger_slot],eax |
.no_debug: |
mov [CURRENT_TASK+ebx+TASKDATA.state], cl |
;mov esi,new_process_running |
;call sys_msg_board_str ;output information about succefull startup |
ret |
endp |
align 4 |
get_stack_base: |
mov eax,[current_slot] |
mov eax,[eax+APPDATA.pl0_stack] |
ret |
include "debug.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
GREEDY_KERNEL equ 0 |
struc APP_HEADER_00 |
{ .banner dq ? |
.version dd ? ;+8 |
.start dd ? ;+12 |
.i_end dd ? ;+16 |
.mem_size dd ? ;+20 |
.i_param dd ? ;+24 |
} |
struc APP_HEADER_01 |
{ .banner dq ? |
.version dd ? ;+8 |
.start dd ? ;+12 |
.i_end dd ? ;+16 |
.mem_size dd ? ;+20 |
.stack_top dd ? ;+24 |
.i_param dd ? ;+28 |
.i_icon dd ? ;+32 |
} |
struc APP_PARAMS |
{ .app_cmdline ;0x00 |
.app_path ;0x04 |
.app_eip ;0x08 |
.app_esp ;0x0C |
.app_mem ;0x10 |
} |
macro _clear_ op |
{ mov ecx, op/4 |
xor eax, eax |
cld |
rep stosd |
} |
fs_execute_from_sysdir: |
xor ebx, ebx |
fs_execute_from_sysdir_param: |
xor edx, edx |
mov esi, sysdir_path |
align 4 |
proc fs_execute |
;fn_read:dword, file_size:dword, cluster:dword |
; ebx - cmdline |
; edx - flags |
; ebp - full filename |
; [esp+4] = procedure DoRead, [esp+8] = filesize & [esp+12]... - arguments for it |
locals |
cmdline rd 64 ;256/4 |
filename rd 256 ;1024/4 |
flags dd ? |
save_cr3 dd ? |
slot dd ? |
slot_base dd ? |
file_base dd ? |
file_size dd ? |
;app header data |
hdr_cmdline dd ? ;0x00 |
hdr_path dd ? ;0x04 |
hdr_eip dd ? ;0x08 |
hdr_esp dd ? ;0x0C |
hdr_mem dd ? ;0x10 |
hdr_i_end dd ? ;0x14 |
endl |
pushad |
mov [flags], edx |
; [ebp] pointer to filename |
lea edi, [filename] |
lea ecx, [edi+1024] |
mov al, '/' |
stosb |
@@: |
cmp edi, ecx |
jae .bigfilename |
lodsb |
stosb |
test al, al |
jnz @b |
mov esi, [ebp] |
test esi, esi |
jz .namecopied |
mov byte [edi-1], '/' |
@@: |
cmp edi, ecx |
jae .bigfilename |
lodsb |
stosb |
test al, al |
jnz @b |
jmp .namecopied |
.bigfilename: |
popad |
mov eax, -ERROR_FILE_NOT_FOUND |
ret |
.namecopied: |
mov [cmdline], ebx |
test ebx, ebx |
jz @F |
lea eax, [cmdline] |
mov dword [eax+252], 0 |
stdcall strncpy, eax, ebx, 255 |
@@: |
lea eax, [filename] |
stdcall load_file, eax |
mov esi, -ERROR_FILE_NOT_FOUND |
test eax, eax |
jz .err_file |
mov [file_base], eax |
mov [file_size], ebx |
lea ebx, [hdr_cmdline] |
call test_app_header |
mov esi, -0x1F |
test eax, eax |
jz .err_hdr |
.wait_lock: |
cmp [application_table_status], 0 |
je .get_lock |
call change_task |
jmp .wait_lock |
.get_lock: |
mov eax, 1 |
xchg eax, [application_table_status] |
test eax, eax |
jnz .wait_lock |
call set_application_table_status |
call get_new_process_place |
test eax, eax |
mov esi, -0x20 ; too many processes |
jz .err |
mov [slot], eax |
shl eax, 8 |
add eax, SLOT_BASE |
mov [slot_base], eax |
mov edi, eax |
_clear_ 256 ;clean extended information about process |
; write application name |
lea eax, [filename] |
stdcall strrchr, eax, '/' ; now eax points to name without path |
lea esi, [eax+1] |
test eax, eax |
jnz @F |
lea esi, [filename] |
@@: |
mov ecx, 8; 8 chars for name |
mov edi, [slot_base] |
.copy_process_name_loop: |
lodsb |
cmp al, '.' |
jz .copy_process_name_done |
test al, al |
jz .copy_process_name_done |
stosb |
loop .copy_process_name_loop |
.copy_process_name_done: |
mov ebx, cr3 |
mov [save_cr3], ebx |
stdcall create_app_space, [hdr_mem], [file_base], [file_size] |
mov esi, -30; no memory |
test eax, eax |
jz .failed |
mov ebx, [slot_base] |
mov [ebx+APPDATA.dir_table], eax |
mov eax, [hdr_mem] |
mov [ebx+APPDATA.mem_size], eax |
xor edx, edx |
cmp word [6], '02' |
jne @f |
not edx |
@@: |
mov [ebx+APPDATA.tls_base], edx |
if GREEDY_KERNEL |
else |
mov ecx, [hdr_mem] |
mov edi, [file_size] |
add edi, 4095 |
and edi, not 4095 |
sub ecx, edi |
jna @F |
xor eax, eax |
cld |
rep stosb |
@@: |
end if |
; release only virtual space, not phisical memory |
stdcall free_kernel_space, [file_base] |
lea eax, [hdr_cmdline] |
lea ebx, [cmdline] |
lea ecx, [filename] |
stdcall set_app_params , [slot], eax, ebx, ecx, [flags] |
mov eax, [save_cr3] |
call set_cr3 |
xor ebx, ebx |
mov [application_table_status], ebx;unlock application_table_status mutex |
mov eax, [process_number];set result |
ret |
.failed: |
mov eax, [save_cr3] |
call set_cr3 |
.err: |
.err_hdr: |
stdcall kernel_free, [file_base] |
.err_file: |
xor eax, eax |
mov [application_table_status], eax |
mov eax, esi |
ret |
endp |
align 4 |
test_app_header: |
virtual at eax |
APP_HEADER_00 APP_HEADER_00 |
end virtual |
virtual at eax |
APP_HEADER_01 APP_HEADER_01 |
end virtual |
cmp dword [eax], 'MENU' |
jne .fail |
cmp word [eax+4], 'ET' |
jne .fail |
cmp [eax+6], word '00' |
jne .check_01_header |
mov ecx, [APP_HEADER_00.start] |
mov [ebx+0x08], ecx ;app_eip |
mov edx, [APP_HEADER_00.mem_size] |
mov [ebx+0x10], edx ;app_mem |
shr edx, 1 |
sub edx, 0x10 |
mov [ebx+0x0C], edx ;app_esp |
mov ecx, [APP_HEADER_00.i_param] |
mov [ebx], ecx ;app_cmdline |
mov [ebx+4], dword 0 ;app_path |
mov edx, [APP_HEADER_00.i_end] |
mov [ebx+0x14], edx |
ret |
.check_01_header: |
cmp [eax+6], word '01' |
je @f |
cmp [eax+6], word '02' |
jne .fail |
@@: |
mov ecx, [APP_HEADER_01.start] |
mov [ebx+0x08], ecx ;app_eip |
mov edx, [APP_HEADER_01.mem_size] |
; \begin{diamond}[20.08.2006] |
; sanity check (functions 19,58 load app_i_end bytes and that must |
; fit in allocated memory to prevent kernel faults) |
cmp edx, [APP_HEADER_01.i_end] |
jb .fail |
; \end{diamond}[20.08.2006] |
mov [ebx+0x10], edx ;app_mem |
mov ecx, [APP_HEADER_01.stack_top] |
mov [ebx+0x0C], ecx ;app_esp |
mov edx, [APP_HEADER_01.i_param] |
mov [ebx], edx ;app_cmdline |
mov ecx, [APP_HEADER_01.i_icon] |
mov [ebx+4], ecx ;app_path |
mov edx, [APP_HEADER_01.i_end] |
mov [ebx+0x14], edx |
ret |
.fail: |
xor eax, eax |
ret |
align 4 |
proc get_new_process_place |
;input: |
; none |
;result: |
; eax=[new_process_place]<>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: |
xor eax, eax |
ret |
endp |
align 4 |
proc create_app_space stdcall, app_size:dword,img_base:dword,img_size:dword |
locals |
app_pages dd ? |
img_pages dd ? |
dir_addr dd ? |
app_tabs dd ? |
endl |
mov ecx, pg_data.mutex |
call mutex_lock |
xor eax, eax |
mov [dir_addr], eax |
mov eax, [app_size] |
add eax, 4095 |
and eax, NOT(4095) |
mov [app_size], eax |
mov ebx, eax |
shr eax, 12 |
mov [app_pages], eax |
add ebx, 0x3FFFFF |
and ebx, NOT(0x3FFFFF) |
shr ebx, 22 |
mov [app_tabs], ebx |
mov ecx, [img_size] |
add ecx, 4095 |
and ecx, NOT(4095) |
mov [img_size], ecx |
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 |
test eax, eax |
jz .fail |
mov [dir_addr], eax |
stdcall map_page, [tmp_task_pdir], eax, dword PG_SW |
mov edi, [tmp_task_pdir] |
mov ecx, (OS_BASE shr 20)/4 |
xor eax, eax |
cld |
rep stosd |
mov ecx, (OS_BASE shr 20)/4 |
mov esi, sys_pgdir+(OS_BASE shr 20) |
rep movsd |
mov eax, [dir_addr] |
or eax, PG_SW |
mov [edi-4096+(page_tabs shr 20)], eax |
and eax, -4096 |
call set_cr3 |
mov edx, [app_tabs] |
mov edi, new_app_base |
@@: |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page_table, edi, eax |
add edi, 0x00400000 |
dec edx |
jnz @B |
mov edi, new_app_base |
shr edi, 10 |
add edi, page_tabs |
mov ecx, [app_tabs] |
shl ecx, 10 |
xor eax, eax |
rep stosd |
mov ecx, [img_pages] |
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 |
.remap: |
lodsd |
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 |
jz .done |
if GREEDY_KERNEL |
mov eax, 0x02 |
rep stosd |
else |
.alloc: |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page, edx, eax, dword PG_UW |
add edx, 0x1000 |
dec [app_pages] |
jnz .alloc |
end if |
.done: |
stdcall map_page, [tmp_task_pdir], dword 0, dword PG_UNMAP |
mov ecx, pg_data.mutex |
call mutex_unlock |
mov eax, [dir_addr] |
ret |
.fail: |
mov ecx, pg_data.mutex |
call mutex_unlock |
cmp [dir_addr], 0 |
je @f |
stdcall destroy_app_space, [dir_addr], 0 |
@@: |
xor eax, eax |
ret |
endp |
align 4 |
set_cr3: |
mov ebx, [current_slot] |
mov [ebx+APPDATA.dir_table], eax |
mov cr3, eax |
ret |
align 4 |
proc destroy_page_table stdcall, pg_tab:dword |
push esi |
mov esi, [pg_tab] |
mov ecx, 1024 |
.free: |
mov eax, [esi] |
test eax, 1 |
jz .next |
test eax, 1 shl 9 |
jnz .next ;skip shared pages |
call free_page |
.next: |
add esi, 4 |
dec ecx |
jnz .free |
pop esi |
ret |
endp |
align 4 |
proc destroy_app_space stdcall, pg_dir:dword, dlls_list:dword |
xor edx, edx |
push edx |
mov eax, 0x2 |
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 |
;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 |
mov ecx, pg_data.mutex |
call mutex_lock |
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 |
.destroy: |
mov eax, [esi] |
test eax, 1 |
jz .next |
and eax, not 0xFFF |
stdcall map_page, [tmp_task_ptab], eax, PG_SW |
stdcall destroy_page_table, [tmp_task_ptab] |
mov eax, [esi] |
call free_page |
.next: |
add esi, 4 |
dec edi |
jnz .destroy |
mov eax, [pg_dir] |
call free_page |
.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: |
mov eax, [TASK_BASE] |
mov eax, [eax+TASKDATA.pid] |
ret |
pid_to_slot: |
;Input: |
; eax - pid of process |
;Output: |
; eax - slot of process or 0 if process don't exists |
;Search process by PID. |
push ebx |
push ecx |
mov ebx, [TASK_COUNT] |
shl ebx, 5 |
mov ecx, 2*32 |
.loop: |
;ecx=offset of current process info entry |
;ebx=maximum permitted offset |
cmp byte [CURRENT_TASK+ecx+0xa], 9 |
jz .endloop ;skip empty slots |
cmp [CURRENT_TASK+ecx+0x4], eax;check PID |
jz .pid_found |
.endloop: |
add ecx, 32 |
cmp ecx, ebx |
jle .loop |
pop ecx |
pop ebx |
xor eax, eax |
ret |
.pid_found: |
shr ecx, 5 |
mov eax, ecx ;convert offset to index of slot |
pop ecx |
pop ebx |
ret |
check_region: |
;input: |
; esi - start of buffer |
; edx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
mov eax, [CURRENT_TASK] |
; jmp check_process_region |
;----------------------------------------------------------------------------- |
;check_process_region: |
;input: |
; eax - slot |
; esi - start of buffer |
; edx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
test edx, edx |
jle .ok |
shl eax, 5 |
cmp word [CURRENT_TASK+eax+0xa], 0 |
jnz .failed |
shl eax, 3 |
mov eax, [SLOT_BASE+eax+0xb8] |
test eax, eax |
jz .failed |
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 |
align 4 |
proc read_process_memory |
;Input: |
; eax - process slot |
; ecx - buffer address |
; edx - buffer size |
; esi - start address in other process |
;Output: |
; eax - number of bytes read. |
locals |
slot dd ? |
buff dd ? |
r_count dd ? |
offset dd ? |
tmp_r_cnt dd ? |
endl |
mov [slot], eax |
mov [buff], ecx |
and [r_count], 0 |
mov [tmp_r_cnt], edx |
mov [offset], esi |
pushad |
.read_mem: |
mov edx, [offset] |
mov ebx, [tmp_r_cnt] |
mov ecx, 0x400000 |
and edx, 0x3FFFFF |
sub ecx, edx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
cmp ecx, 0x8000 |
jna @F |
mov ecx, 0x8000 |
@@: |
mov ebx, [offset] |
push ecx |
stdcall map_memEx, [proc_mem_map], \ |
[slot], ebx, ecx, PG_MAP |
pop ecx |
mov esi, [offset] |
and esi, 0xfff |
sub eax, esi |
jbe .ret |
cmp ecx, eax |
jbe @f |
mov ecx, eax |
mov [tmp_r_cnt], eax |
@@: |
add esi, [proc_mem_map] |
mov edi, [buff] |
mov edx, ecx |
rep movsb |
add [r_count], edx |
add [offset], edx |
sub [tmp_r_cnt], edx |
jnz .read_mem |
.ret: |
popad |
mov eax, [r_count] |
ret |
endp |
align 4 |
proc write_process_memory |
;Input: |
; eax - process slot |
; ecx - buffer address |
; edx - buffer size |
; esi - start address in other process |
;Output: |
; eax - number of bytes written |
locals |
slot dd ? |
buff dd ? |
w_count dd ? |
offset dd ? |
tmp_w_cnt dd ? |
endl |
mov [slot], eax |
mov [buff], ecx |
and [w_count], 0 |
mov [tmp_w_cnt], edx |
mov [offset], esi |
pushad |
.read_mem: |
mov edx, [offset] |
mov ebx, [tmp_w_cnt] |
mov ecx, 0x400000 |
and edx, 0x3FFFFF |
sub ecx, edx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
cmp ecx, 0x8000 |
jna @F |
mov ecx, 0x8000 |
@@: |
mov ebx, [offset] |
; add ebx, new_app_base |
push ecx |
stdcall map_memEx, [proc_mem_map], \ |
[slot], ebx, ecx, PG_SW |
pop ecx |
mov edi, [offset] |
and edi, 0xfff |
sub eax, edi |
jbe .ret |
cmp ecx, eax |
jbe @f |
mov ecx, eax |
mov [tmp_w_cnt], eax |
@@: |
add edi, [proc_mem_map] |
mov esi, [buff] |
mov edx, ecx |
rep movsb |
add [w_count], edx |
add [offset], edx |
sub [tmp_w_cnt], edx |
jnz .read_mem |
.ret: |
popad |
mov eax, [w_count] |
ret |
endp |
align 4 |
proc new_sys_threads |
locals |
slot dd ? |
app_cmdline dd ? ;0x00 |
app_path dd ? ;0x04 |
app_eip dd ? ;0x08 |
app_esp dd ? ;0x0C |
app_mem dd ? ;0x10 |
endl |
cmp ebx, 1 |
jne .failed ;other subfunctions |
xor eax, eax |
mov [app_eip], ecx |
mov [app_cmdline], eax |
mov [app_esp], edx |
mov [app_path], eax |
;mov esi,new_process_loading |
;call sys_msg_board_str |
.wait_lock: |
cmp [application_table_status], 0 |
je .get_lock |
call change_task |
jmp .wait_lock |
.get_lock: |
mov eax, 1 |
xchg eax, [application_table_status] |
test eax, eax |
jnz .wait_lock |
call set_application_table_status |
call get_new_process_place |
test eax, eax |
jz .failed |
mov [slot], eax |
mov esi, [current_slot] |
mov ebx, esi ;ebx=esi - pointer to extended information about current thread |
mov edi, eax |
shl edi, 8 |
add edi, SLOT_BASE |
mov edx, edi ;edx=edi - pointer to extended infomation about new thread |
mov ecx, 256/4 |
xor eax, eax |
cld |
rep stosd ;clean extended information about new thread |
mov esi, ebx |
mov edi, edx |
mov ecx, 11 |
rep movsb ;copy process name |
mov eax, [ebx+APPDATA.heap_base] |
mov [edx+APPDATA.heap_base], eax |
mov ecx, [ebx+APPDATA.heap_top] |
mov [edx+APPDATA.heap_top], ecx |
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 |
push edx |
stdcall user_alloc, 4096 |
pop edx |
test eax, eax |
jz .failed1;eax=0 |
@@: |
mov [edx+APPDATA.tls_base], eax |
lea eax, [app_cmdline] |
stdcall set_app_params , [slot], eax, dword 0, \ |
dword 0,dword 0 |
;mov esi,new_process_running |
;call sys_msg_board_str ;output information about succefull startup |
xor eax, eax |
mov [application_table_status], eax ;unlock application_table_status mutex |
mov eax, [process_number] ;set result |
ret |
.failed: |
xor eax, eax |
.failed1: |
mov [application_table_status], eax |
dec eax ;-1 |
ret |
endp |
align 4 |
tls_app_entry: |
call init_heap |
stdcall user_alloc, 4096 |
mov edx, [current_slot] |
mov [edx+APPDATA.tls_base], eax |
mov [tls_data_l+2], ax |
shr eax, 16 |
mov [tls_data_l+4], al |
mov [tls_data_l+7], ah |
mov dx, app_tls |
mov fs, dx |
popad |
iretd |
EFL_IF equ 0x0200 |
EFL_IOPL1 equ 0x1000 |
EFL_IOPL2 equ 0x2000 |
EFL_IOPL3 equ 0x3000 |
align 4 |
proc set_app_params stdcall,slot:dword, params:dword,\ |
cmd_line:dword, app_path:dword, flags:dword |
locals |
pl0_stack dd ? |
endl |
stdcall kernel_alloc, RING0_STACK_SIZE+512 |
mov [pl0_stack], eax |
lea edi, [eax+RING0_STACK_SIZE] |
mov eax, [slot] |
mov ebx, eax |
shl eax, 8 |
mov [eax+SLOT_BASE+APPDATA.fpu_state], edi |
mov [eax+SLOT_BASE+APPDATA.exc_handler], 0 |
mov [eax+SLOT_BASE+APPDATA.except_mask], 0 |
;set default io permission map |
mov ecx, [SLOT_BASE+256+APPDATA.io_map] |
mov [eax+SLOT_BASE+APPDATA.io_map], ecx |
mov ecx, [SLOT_BASE+256+APPDATA.io_map+4] |
mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx |
mov esi, fpu_data |
mov ecx, 512/4 |
rep movsd |
cmp ebx, [TASK_COUNT] |
jle .noinc |
inc dword [TASK_COUNT] ;update number of processes |
.noinc: |
shl ebx, 8 |
lea edx, [ebx+SLOT_BASE+APP_EV_OFFSET] |
mov [SLOT_BASE+APPDATA.fd_ev+ebx], edx |
mov [SLOT_BASE+APPDATA.bk_ev+ebx], edx |
add edx, APP_OBJ_OFFSET-APP_EV_OFFSET |
mov [SLOT_BASE+APPDATA.fd_obj+ebx], edx |
mov [SLOT_BASE+APPDATA.bk_obj+ebx], edx |
mov ecx, [def_cursor] |
mov [SLOT_BASE+APPDATA.cursor+ebx], ecx |
mov eax, [pl0_stack] |
mov [SLOT_BASE+APPDATA.pl0_stack+ebx], eax |
add eax, RING0_STACK_SIZE |
mov [SLOT_BASE+APPDATA.saved_esp0+ebx], eax |
push ebx |
stdcall kernel_alloc, 0x1000 |
pop ebx |
mov esi, [current_slot] |
mov esi, [esi+APPDATA.cur_dir] |
mov ecx, 0x1000/4 |
mov edi, eax |
mov [ebx+SLOT_BASE+APPDATA.cur_dir], eax |
rep movsd |
shr ebx, 3 |
mov eax, new_app_base |
mov dword [CURRENT_TASK+ebx+0x10], eax |
.add_command_line: |
mov edx, [params] |
mov edx, [edx] ;app_cmdline |
test edx, edx |
jz @f ;application doesn't need parameters |
mov eax, edx |
add eax, 256 |
jc @f |
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8] |
ja @f |
mov byte [edx], 0 ;force empty string if no cmdline given |
mov eax, [cmd_line] |
test eax, eax |
jz @f |
stdcall strncpy, edx, eax, 256 |
@@: |
mov edx, [params] |
mov edx, [edx+4];app_path |
test edx, edx |
jz @F ;application don't need path of file |
mov eax, edx |
add eax, 1024 |
jc @f |
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8] |
ja @f |
stdcall strncpy, edx, [app_path], 1024 |
@@: |
mov ebx, [slot] |
mov eax, ebx |
shl ebx, 5 |
lea ecx, [draw_data+ebx];ecx - pointer to draw data |
mov edx, irq0.return |
cmp [ebx*8+SLOT_BASE+APPDATA.tls_base], -1 |
jne @F |
mov edx, tls_app_entry |
@@: |
; set window state to 'normal' (non-minimized/maximized/rolled-up) state |
mov [ebx+window_data+WDATA.fl_wstate], WSTATE_NORMAL |
mov [ebx+window_data+WDATA.fl_redraw], 1 |
add ebx, CURRENT_TASK ;ebx - pointer to information about process |
mov [ebx+TASKDATA.wnd_number], al;set window number on screen = process slot |
mov [ebx+TASKDATA.event_mask], dword 1+2+4;set default event flags (see 40 function) |
inc dword [process_number] |
mov eax, [process_number] |
mov [ebx+4], eax ;set PID |
;set draw data to full screen |
xor eax, eax |
mov [ecx+0], dword eax |
mov [ecx+4], dword eax |
mov eax, [Screen_Max_X] |
mov [ecx+8], eax |
mov eax, [Screen_Max_Y] |
mov [ecx+12], eax |
mov ebx, [pl0_stack] |
mov esi, [params] |
lea ecx, [ebx+REG_EIP] |
xor eax, eax |
mov [ebx+REG_RET], edx |
mov [ebx+REG_EDI], eax |
mov [ebx+REG_ESI], eax |
mov [ebx+REG_EBP], eax |
mov [ebx+REG_ESP], ecx;ebx+REG_EIP |
mov [ebx+REG_EBX], eax |
mov [ebx+REG_EDX], eax |
mov [ebx+REG_ECX], eax |
mov [ebx+REG_EAX], eax |
mov eax, [esi+0x08] ;app_eip |
mov [ebx+REG_EIP], eax;app_entry |
mov [ebx+REG_CS], dword app_code |
mov [ebx+REG_EFLAGS], dword EFL_IOPL1+EFL_IF |
mov eax, [esi+0x0C] ;app_esp |
mov [ebx+REG_APP_ESP], eax;app_stack |
mov [ebx+REG_SS], dword app_data |
lea ecx, [ebx+REG_RET] |
mov ebx, [slot] |
shl ebx, 5 |
mov [ebx*8+SLOT_BASE+APPDATA.saved_esp], ecx |
xor ecx, ecx; process state - running |
; set if debuggee |
test byte [flags], 1 |
jz .no_debug |
inc ecx ; process state - suspended |
mov eax, [CURRENT_TASK] |
mov [SLOT_BASE+ebx*8+APPDATA.debugger_slot], eax |
.no_debug: |
mov [CURRENT_TASK+ebx+TASKDATA.state], cl |
;mov esi,new_process_running |
;call sys_msg_board_str ;output information about succefull startup |
ret |
endp |
align 4 |
get_stack_base: |
mov eax, [current_slot] |
mov eax, [eax+APPDATA.pl0_stack] |
ret |
include "debug.inc" |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/test_malloc.asm |
---|
1,223 → 1,223 |
; Tests of malloc()/free() from the kernel heap. |
; This file is not included in the kernel, it is just test application. |
use32 |
db 'MENUET01' |
dd 1, start, i_end, mem, mem, 0, 0 |
start: |
; Zero-initialize uglobals (as in kernel at boot) |
mov ecx, (zeroend - zerostart + 3) / 4 |
xor eax, eax |
mov edi, zerostart |
rep stosd |
; Initialize small heap (as in kernel at boot) |
call init_malloc |
; Run tests |
call run_test1 |
call run_test2 |
call run_test3 |
; All is OK, return |
or eax, -1 |
int 0x40 |
run_test1: |
; basic test |
mov eax, 1 |
call malloc_with_test |
mov byte [eax], 0xDD |
mov esi, eax |
mov eax, 1 |
call malloc_with_test |
cmp byte [esi], 0xDD |
jnz memory_destroyed |
mov byte [eax], 0xEE |
xchg eax, esi |
call free |
cmp byte [esi], 0xEE |
jnz memory_destroyed |
xchg eax, esi |
call free |
ret |
run_test2: |
ret |
run_test3: |
; 1024000 times run random operation. |
; Randomly select malloc(random size from 1 to 1023) |
; or free(random of previously allocated areas) |
mov edi, 0x12345678 |
xor esi, esi ; 0 areas allocated |
mov ebx, 1024000 |
.loop: |
imul edi, 1103515245 |
add edi, 12345 |
mov eax, edi |
shr eax, 16 |
test ebx, 64 |
jz .prefer_free |
.prefer_malloc: |
test eax, 3 |
jz .free |
jmp @f |
.prefer_free: |
test eax, 3 |
jnz .free |
@@: |
shr eax, 2 |
and eax, 1023 |
jz .loop |
push ebx |
push eax |
; mov ecx, [saved_state_num] |
; mov [saved_state+ecx*8], eax |
call malloc_with_test |
; mov ecx, [saved_state_num] |
; mov [saved_state+ecx*8+4], eax |
; inc [saved_state_num] |
pop ecx |
pop ebx |
inc esi |
push ecx eax |
push edi |
mov edi, eax |
mov eax, esi |
rep stosb |
pop edi |
jmp .common |
.free: |
test esi, esi |
jz .loop |
xor edx, edx |
div esi |
sub edx, esi |
neg edx |
dec edx |
mov eax, [esp+edx*8] |
; mov ecx, [saved_state_num] |
; mov [saved_state+ecx*8], -1 |
; mov [saved_state+ecx*8+4], eax |
; inc [saved_state_num] |
mov ecx, [esp+edx*8+4] |
push edi eax |
mov edi, eax |
mov al, [edi] |
repz scasb |
jnz memory_destroyed |
pop eax edi |
push ebx edx |
call free |
pop edx ebx |
dec esi |
pop eax ecx |
push edi |
lea edi, [esp+4] |
@@: |
dec edx |
js @f |
xchg eax, [edi] |
xchg ecx, [edi+4] |
add edi, 8 |
jmp @b |
@@: |
pop edi |
.common: |
dec ebx |
jnz .loop |
@@: |
dec esi |
js @f |
pop eax ecx |
call free |
jmp @b |
@@: |
ret |
malloc_with_test: |
; calls malloc() and checks returned value |
call malloc |
test eax, eax |
jz generic_malloc_fail |
call check_mutex |
call check_range |
ret |
; Stubs for kernel procedures used by heap code |
wait_mutex: |
inc dword [ebx] |
ret |
kernel_alloc: |
cmp dword [esp+4], bufsize |
jnz error1 |
mov eax, buffer |
ret 4 |
macro $Revision [args] |
{ |
} |
; Error handlers |
error1: |
mov eax, 1 |
jmp error_with_code |
generic_malloc_fail: |
mov eax, 2 |
jmp error_with_code |
check_mutex: |
cmp [mst.mutex], 0 |
jnz @f |
ret |
@@: |
mov eax, 3 |
jmp error_with_code |
check_range: |
cmp eax, buffer |
jb @f |
cmp eax, buffer+bufsize |
jae @f |
ret |
@@: |
mov eax, 4 |
jmp error_with_code |
memory_destroyed: |
mov eax, 5 |
jmp error_with_code |
error_with_code: |
mov edx, saved_state_num |
; eax = error code |
; 1 signals error in testing code (wrong bufsize) |
; 2 = malloc() returned NULL |
; 3 = mutex not released |
; 4 = weird returned value from malloc() |
; 5 = memory destroyed by malloc() or free() |
int3 ; simplest way to report error |
jmp $-1 ; just in case |
; Include main heap code |
include '../proc32.inc' |
include '../const.inc' |
include 'malloc.inc' |
i_end: |
align 4 |
zerostart: |
mst MEM_STATE |
align 16 |
bufsize = 0x40000 ; change if malloc.inc changes |
buffer rb bufsize |
zeroend: |
saved_state_num dd ? |
saved_state rd 0x10000 |
align 4 |
rb 0x10000 ; for stack |
mem: |
; Tests of malloc()/free() from the kernel heap. |
; This file is not included in the kernel, it is just test application. |
use32 |
db 'MENUET01' |
dd 1, start, i_end, mem, mem, 0, 0 |
start: |
; Zero-initialize uglobals (as in kernel at boot) |
mov ecx, (zeroend - zerostart + 3) / 4 |
xor eax, eax |
mov edi, zerostart |
rep stosd |
; Initialize small heap (as in kernel at boot) |
call init_malloc |
; Run tests |
call run_test1 |
call run_test2 |
call run_test3 |
; All is OK, return |
or eax, -1 |
int 0x40 |
run_test1: |
; basic test |
mov eax, 1 |
call malloc_with_test |
mov byte [eax], 0xDD |
mov esi, eax |
mov eax, 1 |
call malloc_with_test |
cmp byte [esi], 0xDD |
jnz memory_destroyed |
mov byte [eax], 0xEE |
xchg eax, esi |
call free |
cmp byte [esi], 0xEE |
jnz memory_destroyed |
xchg eax, esi |
call free |
ret |
run_test2: |
ret |
run_test3: |
; 1024000 times run random operation. |
; Randomly select malloc(random size from 1 to 1023) |
; or free(random of previously allocated areas) |
mov edi, 0x12345678 |
xor esi, esi ; 0 areas allocated |
mov ebx, 1024000 |
.loop: |
imul edi, 1103515245 |
add edi, 12345 |
mov eax, edi |
shr eax, 16 |
test ebx, 64 |
jz .prefer_free |
.prefer_malloc: |
test eax, 3 |
jz .free |
jmp @f |
.prefer_free: |
test eax, 3 |
jnz .free |
@@: |
shr eax, 2 |
and eax, 1023 |
jz .loop |
push ebx |
push eax |
; mov ecx, [saved_state_num] |
; mov [saved_state+ecx*8], eax |
call malloc_with_test |
; mov ecx, [saved_state_num] |
; mov [saved_state+ecx*8+4], eax |
; inc [saved_state_num] |
pop ecx |
pop ebx |
inc esi |
push ecx eax |
push edi |
mov edi, eax |
mov eax, esi |
rep stosb |
pop edi |
jmp .common |
.free: |
test esi, esi |
jz .loop |
xor edx, edx |
div esi |
sub edx, esi |
neg edx |
dec edx |
mov eax, [esp+edx*8] |
; mov ecx, [saved_state_num] |
; mov [saved_state+ecx*8], -1 |
; mov [saved_state+ecx*8+4], eax |
; inc [saved_state_num] |
mov ecx, [esp+edx*8+4] |
push edi eax |
mov edi, eax |
mov al, [edi] |
repz scasb |
jnz memory_destroyed |
pop eax edi |
push ebx edx |
call free |
pop edx ebx |
dec esi |
pop eax ecx |
push edi |
lea edi, [esp+4] |
@@: |
dec edx |
js @f |
xchg eax, [edi] |
xchg ecx, [edi+4] |
add edi, 8 |
jmp @b |
@@: |
pop edi |
.common: |
dec ebx |
jnz .loop |
@@: |
dec esi |
js @f |
pop eax ecx |
call free |
jmp @b |
@@: |
ret |
malloc_with_test: |
; calls malloc() and checks returned value |
call malloc |
test eax, eax |
jz generic_malloc_fail |
call check_mutex |
call check_range |
ret |
; Stubs for kernel procedures used by heap code |
wait_mutex: |
inc dword [ebx] |
ret |
kernel_alloc: |
cmp dword [esp+4], bufsize |
jnz error1 |
mov eax, buffer |
ret 4 |
macro $Revision [args] |
{ |
} |
; Error handlers |
error1: |
mov eax, 1 |
jmp error_with_code |
generic_malloc_fail: |
mov eax, 2 |
jmp error_with_code |
check_mutex: |
cmp [mst.mutex], 0 |
jnz @f |
ret |
@@: |
mov eax, 3 |
jmp error_with_code |
check_range: |
cmp eax, buffer |
jb @f |
cmp eax, buffer+bufsize |
jae @f |
ret |
@@: |
mov eax, 4 |
jmp error_with_code |
memory_destroyed: |
mov eax, 5 |
jmp error_with_code |
error_with_code: |
mov edx, saved_state_num |
; eax = error code |
; 1 signals error in testing code (wrong bufsize) |
; 2 = malloc() returned NULL |
; 3 = mutex not released |
; 4 = weird returned value from malloc() |
; 5 = memory destroyed by malloc() or free() |
int3 ; simplest way to report error |
jmp $-1 ; just in case |
; Include main heap code |
include '../proc32.inc' |
include '../const.inc' |
include 'malloc.inc' |
i_end: |
align 4 |
zerostart: |
mst MEM_STATE |
align 16 |
bufsize = 0x40000 ; change if malloc.inc changes |
buffer rb bufsize |
zeroend: |
saved_state_num dd ? |
saved_state rd 0x10000 |
align 4 |
rb 0x10000 ; for stack |
mem: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/timers.inc |
---|
1,205 → 1,205 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Simple implementation of timers. All timers are organized in a double-linked |
; list, and the OS loop after every timer tick processes the list. |
; This structure describes a timer for the kernel. |
struct TIMER |
.Next dd ? |
.Prev dd ? |
; These fields organize a double-linked list of all timers. |
.TimerFunc dd ? |
; Function to be called when the timer is activated. |
.UserData dd ? |
; The value that is passed as is to .TimerFunc. |
.Time dd ? |
; Time at which the timer should be activated. |
.Interval dd ? |
; Interval between activations of the timer, in 0.01s. |
ends |
iglobal |
align 4 |
; The head of timer list. |
timer_list: |
dd timer_list |
dd timer_list |
endg |
uglobal |
; These two variables are used to synchronize access to the global list. |
; Logically, they form an recursive mutex. Physically, the first variable holds |
; the slot number of the current owner or 0, the second variable holds the |
; recursion count. |
; The mutex should be recursive to allow a timer function to add/delete other |
; timers or itself. |
timer_list_owner dd 0 |
timer_list_numlocks dd 0 |
; A timer function can delete any timer, including itself and the next timer in |
; the chain. To handle such situation correctly, we keep the next timer in a |
; global variable, so the removing operation can update it. |
timer_next dd 0 |
endg |
; This internal function acquires the lock for the global list. |
lock_timer_list: |
mov edx, [CURRENT_TASK] |
@@: |
xor eax, eax |
lock cmpxchg [timer_list_owner], edx |
jz @f |
cmp eax, edx |
jz @f |
call change_task |
jmp @b |
@@: |
inc [timer_list_numlocks] |
ret |
; This internal function releases the lock for the global list. |
unlock_timer_list: |
dec [timer_list_numlocks] |
jnz .nothing |
mov [timer_list_owner], 0 |
.nothing: |
ret |
; This function adds a timer. |
; If deltaStart is nonzero, the timer is activated after deltaStart hundredths |
; of seconds starting from the current time. If interval is nonzero, the timer |
; is activated every deltaWork hundredths of seconds starting from the first |
; activation. The activated timer calls timerFunc as stdcall function with one |
; argument userData. |
; Return value is NULL if something has failed or some value which is opaque |
; for the caller. Later this value can be used for cancel_timer_hs. |
proc timer_hs stdcall uses ebx, deltaStart:dword, interval:dword, \ |
timerFunc:dword, userData:dword |
; 1. Allocate memory for the TIMER structure. |
; 1a. Call the allocator. |
push sizeof.TIMER |
pop eax |
call malloc |
; 1b. If allocation failed, return (go to 5) with eax = 0. |
test eax, eax |
jz .nothing |
; 2. Setup the TIMER structure. |
xchg ebx, eax |
; 2a. Copy values from the arguments. |
mov ecx, [interval] |
mov [ebx+TIMER.Interval], ecx |
mov ecx, [timerFunc] |
mov [ebx+TIMER.TimerFunc], ecx |
mov ecx, [userData] |
mov [ebx+TIMER.UserData], ecx |
; 2b. Get time of the next activation. |
mov ecx, [deltaStart] |
test ecx, ecx |
jnz @f |
mov ecx, [interval] |
@@: |
add ecx, [timer_ticks] |
mov [ebx+TIMER.Time], ecx |
; 3. Insert the TIMER structure to the global list. |
; 3a. Acquire the lock. |
call lock_timer_list |
; 3b. Insert an item at ebx to the tail of the timer_list. |
mov eax, timer_list |
mov ecx, [eax+TIMER.Prev] |
mov [ebx+TIMER.Next], eax |
mov [ebx+TIMER.Prev], ecx |
mov [eax+TIMER.Prev], ebx |
mov [ecx+TIMER.Next], ebx |
; 3c. Release the lock. |
call unlock_timer_list |
; 4. Return with eax = pointer to TIMER structure. |
xchg ebx, eax |
.nothing: |
; 5. Returning. |
ret |
endp |
; This function removes a timer. |
; The only argument is [esp+4] = the value which was returned from timer_hs. |
cancel_timer_hs: |
push ebx ; save used register to be stdcall |
; 1. Remove the TIMER structure from the global list. |
; 1a. Acquire the lock. |
call lock_timer_list |
mov ebx, [esp+4+4] |
; 1b. Delete an item at ebx from the double-linked list. |
mov eax, [ebx+TIMER.Next] |
mov ecx, [ebx+TIMER.Prev] |
mov [eax+TIMER.Prev], ecx |
mov [ecx+TIMER.Next], eax |
; 1c. If we are removing the next timer in currently processing chain, |
; the next timer for this timer becomes new next timer. |
cmp ebx, [timer_next] |
jnz @f |
mov [timer_next], eax |
@@: |
; 1d. Release the lock. |
call unlock_timer_list |
; 2. Free the TIMER structure. |
xchg eax, ebx |
call free |
; 3. Return. |
pop ebx ; restore used register to be stdcall |
ret 4 ; purge one dword argument to be stdcall |
; This function is regularly called from osloop. It processes the global list |
; and activates the corresponding timers. |
check_timers: |
; 1. Acquire the lock. |
call lock_timer_list |
; 2. Loop over all registered timers, checking time. |
; 2a. Get the first item. |
mov eax, [timer_list+TIMER.Next] |
mov [timer_next], eax |
.loop: |
; 2b. Check for end of list. |
cmp eax, timer_list |
jz .done |
; 2c. Get and store the next timer. |
mov edx, [eax+TIMER.Next] |
mov [timer_next], edx |
; 2d. Check time for timer activation. |
; We can't just compare [timer_ticks] and [TIMER.Time], since overflows are |
; possible: if the current time is 0FFFFFFFFh ticks and timer should be |
; activated in 3 ticks, the simple comparison will produce incorrect result. |
; So we calculate the difference [timer_ticks] - [TIMER.Time]; if it is |
; non-negative, the time is over; if it is negative, then either the time is |
; not over or we have not processed this timer for 2^31 ticks, what is very |
; unlikely. |
mov edx, [timer_ticks] |
sub edx, [eax+TIMER.Time] |
js .next |
; The timer should be activated now. |
; 2e. Store the timer data in the stack. This is required since 2f can delete |
; the timer, invalidating the content. |
push [eax+TIMER.UserData] ; parameter for TimerFunc |
push [eax+TIMER.TimerFunc] ; to be restored in 2g |
; 2f. Calculate time of next activation or delete the timer if it is one-shot. |
mov ecx, [eax+TIMER.Interval] |
add [eax+TIMER.Time], ecx |
test ecx, ecx |
jnz .nodelete |
stdcall cancel_timer_hs, eax |
.nodelete: |
; 2g. Activate timer, using data from the stack. |
pop eax |
call eax |
.next: |
; 2h. Advance to the next timer and continue the loop. |
mov eax, [timer_next] |
jmp .loop |
.done: |
; 3. Release the lock. |
call unlock_timer_list |
; 4. Return. |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Simple implementation of timers. All timers are organized in a double-linked |
; list, and the OS loop after every timer tick processes the list. |
; This structure describes a timer for the kernel. |
struct TIMER |
.Next dd ? |
.Prev dd ? |
; These fields organize a double-linked list of all timers. |
.TimerFunc dd ? |
; Function to be called when the timer is activated. |
.UserData dd ? |
; The value that is passed as is to .TimerFunc. |
.Time dd ? |
; Time at which the timer should be activated. |
.Interval dd ? |
; Interval between activations of the timer, in 0.01s. |
ends |
iglobal |
align 4 |
; The head of timer list. |
timer_list: |
dd timer_list |
dd timer_list |
endg |
uglobal |
; These two variables are used to synchronize access to the global list. |
; Logically, they form an recursive mutex. Physically, the first variable holds |
; the slot number of the current owner or 0, the second variable holds the |
; recursion count. |
; The mutex should be recursive to allow a timer function to add/delete other |
; timers or itself. |
timer_list_owner dd 0 |
timer_list_numlocks dd 0 |
; A timer function can delete any timer, including itself and the next timer in |
; the chain. To handle such situation correctly, we keep the next timer in a |
; global variable, so the removing operation can update it. |
timer_next dd 0 |
endg |
; This internal function acquires the lock for the global list. |
lock_timer_list: |
mov edx, [CURRENT_TASK] |
@@: |
xor eax, eax |
lock cmpxchg [timer_list_owner], edx |
jz @f |
cmp eax, edx |
jz @f |
call change_task |
jmp @b |
@@: |
inc [timer_list_numlocks] |
ret |
; This internal function releases the lock for the global list. |
unlock_timer_list: |
dec [timer_list_numlocks] |
jnz .nothing |
mov [timer_list_owner], 0 |
.nothing: |
ret |
; This function adds a timer. |
; If deltaStart is nonzero, the timer is activated after deltaStart hundredths |
; of seconds starting from the current time. If interval is nonzero, the timer |
; is activated every deltaWork hundredths of seconds starting from the first |
; activation. The activated timer calls timerFunc as stdcall function with one |
; argument userData. |
; Return value is NULL if something has failed or some value which is opaque |
; for the caller. Later this value can be used for cancel_timer_hs. |
proc timer_hs stdcall uses ebx, deltaStart:dword, interval:dword, \ |
timerFunc:dword, userData:dword |
; 1. Allocate memory for the TIMER structure. |
; 1a. Call the allocator. |
push sizeof.TIMER |
pop eax |
call malloc |
; 1b. If allocation failed, return (go to 5) with eax = 0. |
test eax, eax |
jz .nothing |
; 2. Setup the TIMER structure. |
xchg ebx, eax |
; 2a. Copy values from the arguments. |
mov ecx, [interval] |
mov [ebx+TIMER.Interval], ecx |
mov ecx, [timerFunc] |
mov [ebx+TIMER.TimerFunc], ecx |
mov ecx, [userData] |
mov [ebx+TIMER.UserData], ecx |
; 2b. Get time of the next activation. |
mov ecx, [deltaStart] |
test ecx, ecx |
jnz @f |
mov ecx, [interval] |
@@: |
add ecx, [timer_ticks] |
mov [ebx+TIMER.Time], ecx |
; 3. Insert the TIMER structure to the global list. |
; 3a. Acquire the lock. |
call lock_timer_list |
; 3b. Insert an item at ebx to the tail of the timer_list. |
mov eax, timer_list |
mov ecx, [eax+TIMER.Prev] |
mov [ebx+TIMER.Next], eax |
mov [ebx+TIMER.Prev], ecx |
mov [eax+TIMER.Prev], ebx |
mov [ecx+TIMER.Next], ebx |
; 3c. Release the lock. |
call unlock_timer_list |
; 4. Return with eax = pointer to TIMER structure. |
xchg ebx, eax |
.nothing: |
; 5. Returning. |
ret |
endp |
; This function removes a timer. |
; The only argument is [esp+4] = the value which was returned from timer_hs. |
cancel_timer_hs: |
push ebx ; save used register to be stdcall |
; 1. Remove the TIMER structure from the global list. |
; 1a. Acquire the lock. |
call lock_timer_list |
mov ebx, [esp+4+4] |
; 1b. Delete an item at ebx from the double-linked list. |
mov eax, [ebx+TIMER.Next] |
mov ecx, [ebx+TIMER.Prev] |
mov [eax+TIMER.Prev], ecx |
mov [ecx+TIMER.Next], eax |
; 1c. If we are removing the next timer in currently processing chain, |
; the next timer for this timer becomes new next timer. |
cmp ebx, [timer_next] |
jnz @f |
mov [timer_next], eax |
@@: |
; 1d. Release the lock. |
call unlock_timer_list |
; 2. Free the TIMER structure. |
xchg eax, ebx |
call free |
; 3. Return. |
pop ebx ; restore used register to be stdcall |
ret 4 ; purge one dword argument to be stdcall |
; This function is regularly called from osloop. It processes the global list |
; and activates the corresponding timers. |
check_timers: |
; 1. Acquire the lock. |
call lock_timer_list |
; 2. Loop over all registered timers, checking time. |
; 2a. Get the first item. |
mov eax, [timer_list+TIMER.Next] |
mov [timer_next], eax |
.loop: |
; 2b. Check for end of list. |
cmp eax, timer_list |
jz .done |
; 2c. Get and store the next timer. |
mov edx, [eax+TIMER.Next] |
mov [timer_next], edx |
; 2d. Check time for timer activation. |
; We can't just compare [timer_ticks] and [TIMER.Time], since overflows are |
; possible: if the current time is 0FFFFFFFFh ticks and timer should be |
; activated in 3 ticks, the simple comparison will produce incorrect result. |
; So we calculate the difference [timer_ticks] - [TIMER.Time]; if it is |
; non-negative, the time is over; if it is negative, then either the time is |
; not over or we have not processed this timer for 2^31 ticks, what is very |
; unlikely. |
mov edx, [timer_ticks] |
sub edx, [eax+TIMER.Time] |
js .next |
; The timer should be activated now. |
; 2e. Store the timer data in the stack. This is required since 2f can delete |
; the timer, invalidating the content. |
push [eax+TIMER.UserData] ; parameter for TimerFunc |
push [eax+TIMER.TimerFunc] ; to be restored in 2g |
; 2f. Calculate time of next activation or delete the timer if it is one-shot. |
mov ecx, [eax+TIMER.Interval] |
add [eax+TIMER.Time], ecx |
test ecx, ecx |
jnz .nodelete |
stdcall cancel_timer_hs, eax |
.nodelete: |
; 2g. Activate timer, using data from the stack. |
pop eax |
call eax |
.next: |
; 2h. Advance to the next timer and continue the loop. |
mov eax, [timer_next] |
jmp .loop |
.done: |
; 3. Release the lock. |
call unlock_timer_list |
; 4. Return. |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/core/v86.inc |
---|
1,931 → 1,932 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Virtual-8086 mode manager |
; diamond, 2007, 2008 |
DEBUG_SHOW_IO = 0 |
struc V86_machine |
{ |
; page directory |
.pagedir dd ? |
; translation table: V86 address -> flat linear address |
.pages dd ? |
; mutex to protect all data from writing by multiple threads at one time |
.mutex dd ? |
; i/o permission map |
.iopm dd ? |
.size = $ |
} |
virtual at 0 |
V86_machine V86_machine |
end virtual |
; Create V86 machine |
; in: nothing |
; out: eax = handle (pointer to struc V86_machine) |
; eax = NULL => failure |
; destroys: ebx, ecx, edx (due to malloc) |
v86_create: |
; allocate V86_machine structure |
mov eax, V86_machine.size |
call malloc |
test eax, eax |
jz .fail |
; initialize mutex |
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 |
call kernel_alloc |
test eax, eax |
jz .fail2 |
mov [ebx+V86_machine.pagedir], eax |
push edi eax |
mov edi, eax |
add eax, 1800h |
mov [ebx+V86_machine.pages], eax |
; initialize tables |
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 |
pop esi |
; 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] |
@@: |
lea eax, [edx + OS_BASE] |
mov [edi+800h], eax |
lea eax, [edx + 111b] |
stosd |
add edx, 0x1000 |
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 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 |
mov eax, ebx |
ret |
.fail2: |
mov eax, ebx |
call free |
.fail: |
xor eax, eax |
ret |
; 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 |
; Translate V86-address to linear address |
; in: eax=V86 address |
; esi=handle |
; out: eax=linear address |
; destroys: nothing |
v86_get_lin_addr: |
push ecx edx |
mov ecx, eax |
mov edx, [esi+V86_machine.pages] |
shr ecx, 12 |
and eax, 0xFFF |
add eax, [edx+ecx*4] ; atomic operation, no mutex needed |
pop edx ecx |
ret |
; Sets linear address for V86-page |
; in: eax=linear address (must be page-aligned) |
; ecx=V86 page (NOT address!) |
; 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 |
; Allocate memory in V86 machine |
; in: eax=size (in bytes) |
; esi=handle |
; out: eax=V86 address, para-aligned (0x10 multiple) |
; destroys: nothing |
; ¥¤®¯¨á !!! |
;v86_alloc: |
; push ebx ecx edx edi |
; lea ebx, [esi+V86_machine.mutex] |
; call wait_mutex |
; add eax, 0x1F |
; shr eax, 4 |
; mov ebx, 0x1000 ; start with address 0x1000 (second page) |
; mov edi, [esi+V86_machine.tables] |
;.l: |
; mov ecx, ebx |
; shr ecx, 12 |
; mov edx, [edi+0x1000+ecx*4] ; get linear address |
; test edx, edx ; page allocated? |
; jz .unalloc |
; mov ecx, ebx |
; and ecx, 0xFFF |
; add edx, ecx |
; cmp dword [edx], 0 ; free block? |
; jnz .n |
; cmp dword [edx+4], |
; and [esi+V86_machine.mutex], 0 |
; pop edi edx ecx ebx |
; ret |
uglobal |
sys_v86_machine dd ? |
endg |
; Called from kernel.asm at first stages of loading |
; Initialize system V86 machine (used to simulate BIOS int 13h) |
init_sys_v86: |
call v86_create |
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] |
xor eax, eax |
mov edi, ecx |
mov ecx, 10000h/8/4 |
rep stosd |
end if |
.ret: |
ret |
struc v86_regs |
{ |
; don't change the order, it is important |
.edi dd ? |
.esi dd ? |
.ebp dd ? |
dd ? ; ignored |
.ebx dd ? |
.edx dd ? |
.ecx dd ? |
.eax dd ? |
.eip dd ? |
.cs dd ? |
.eflags dd ? ; VM flag must be set! |
.esp dd ? |
.ss dd ? |
.es dd ? |
.ds dd ? |
.fs dd ? |
.gs dd ? |
.size = $ |
} |
virtual at 0 |
v86_regs v86_regs |
end virtual |
; Run V86 machine |
; in: ebx -> registers for V86 (two structures: in and out) |
; esi = handle |
; ecx = expected end address (CS:IP) |
; edx = IRQ to hook or -1 if not required |
; out: structure pointed to by ebx is filled with new values |
; eax = 1 - exception has occured, cl contains code |
; eax = 2 - access to disabled i/o port, ecx contains port address |
; 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 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 |
add eax, 0x1000 |
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 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. |
; sti |
mov eax, esi |
sub esp, v86_regs.size |
mov esi, ebx |
mov edi, esp |
mov ecx, v86_regs.size/4 |
rep movsd |
cmp edx, -1 |
jz .noirqhook |
uglobal |
v86_irqhooks rd IRQ_RESERVED * 2 |
endg |
cmp [v86_irqhooks+edx*8], 0 |
jz @f |
cmp [v86_irqhooks+edx*8], eax |
jz @f |
mov esi, v86_irqerr |
call sys_msg_board_str |
inc [v86_irqhooks+edx*8+4] |
mov eax, 3 |
jmp v86_exc_c.exit |
@@: |
mov [v86_irqhooks+edx*8], eax |
inc [v86_irqhooks+edx*8+4] |
.noirqhook: |
popad |
iretd |
; It is only possible to leave virtual-8086 mode by faulting to |
; a protected-mode interrupt handler (typically the general-protection |
; exception handler, which in turn calls the virtual 8086-mode monitor). |
iglobal |
v86_exc_str1 db 'V86 : unexpected exception ',0 |
v86_exc_str2 db ' at ',0 |
v86_exc_str3 db ':',0 |
v86_exc_str4 db 13,10,'V86 : faulted code:',0 |
v86_exc_str5 db ' (unavailable)',0 |
v86_newline db 13,10,0 |
v86_io_str1 db 'V86 : access to disabled i/o port ',0 |
v86_io_byte db ' (byte)',13,10,0 |
v86_io_word db ' (word)',13,10,0 |
v86_io_dword db ' (dword)',13,10,0 |
v86_irqerr db 'V86 : IRQ already hooked',13,10,0 |
endg |
v86_exc_c: |
; Did we all that we have wanted to do? |
cmp bl,1 |
jne @f |
xor eax, eax |
mov dr6, eax |
@@: mov eax, [esp+v86_regs.size+10h+18h] |
cmp word [esp+v86_regs.eip], ax |
jnz @f |
shr eax, 16 |
cmp word [esp+v86_regs.cs], ax |
jz .done |
@@: |
; Various system events, which must be handled, result in #GP |
cmp bl, 13 |
jnz .nogp |
; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error |
cmp word [esp+v86_regs.eip+2], 0 |
jnz .nogp |
; Otherwise we can safely access byte at CS:IP |
; (because it is #GP, not #PF handler) |
; ᫨ ¡ë ¬ë ¬®£«¨ áå«®¯®â âì ¨áª«î票¥ ⮫쪮 ¨§-§ çâ¥¨ï ¡ ©â®¢ ª®¤ , |
; ¬ë ¡ë ¥£® 㦥 áå«®¯®â «¨ ¨ íâ® ¡ë«® ¡ë ¥ #GP |
movzx esi, word [esp+v86_regs.cs] |
shl esi, 4 |
add esi, [esp+v86_regs.eip] |
lodsb |
cmp al, 0xCD ; int xx command = CD xx |
jz .handle_int |
cmp al, 0xCF |
jz .handle_iret |
cmp al, 0xF3 |
jz .handle_rep |
cmp al, 0xEC |
jz .handle_in |
cmp al, 0xED |
jz .handle_in_word |
cmp al, 0xEE |
jz .handle_out |
cmp al, 0xEF |
jz .handle_out_word |
cmp al, 0xE4 |
jz .handle_in_imm |
cmp al, 0xE6 |
jz .handle_out_imm |
cmp al, 0x9C |
jz .handle_pushf |
cmp al, 0x9D |
jz .handle_popf |
cmp al, 0xFA |
jz .handle_cli |
cmp al, 0xFB |
jz .handle_sti |
cmp al, 0x66 |
jz .handle_66 |
jmp .nogp |
.handle_int: |
cmp word [esp+v86_regs.eip], 0xFFFF |
jae .nogp |
xor eax, eax |
lodsb |
; call sys_msg_board_byte |
; simulate INT command |
; N.B. It is possible that some checks need to be corrected, |
; but at least in case of normal execution the code works. |
.simulate_int: |
cmp word [esp+v86_regs.esp], 6 |
jae @f |
mov bl, 12 ; #SS exception |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
push eax |
movzx eax, word [esp+4+v86_regs.esp] |
sub eax, 6 |
add edx, eax |
mov eax, edx |
mov esi, [esp+4+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
lea eax, [edx+5] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
sub word [esp+4+v86_regs.esp], 6 |
mov eax, [esp+4+v86_regs.eip] |
cmp byte [esp+1], 0 |
jnz @f |
inc eax |
inc eax |
@@: |
mov word [edx], ax |
mov eax, [esp+4+v86_regs.cs] |
mov word [edx+2], ax |
mov eax, [esp+4+v86_regs.eflags] |
mov word [edx+4], ax |
pop eax |
mov ah, 0 |
mov cx, [eax*4] |
mov word [esp+v86_regs.eip], cx |
mov cx, [eax*4+2] |
mov word [esp+v86_regs.cs], cx |
; note that interrupts will be disabled globally at IRET |
and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags |
; continue V86 execution |
popad |
iretd |
.handle_iret: |
cmp word [esp+v86_regs.esp], 0x10000 - 6 |
jbe @f |
mov bl, 12 |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
movzx eax, word [esp+v86_regs.esp] |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
lea eax, [edx+5] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
mov ax, [edx] |
mov word [esp+v86_regs.eip], ax |
mov ax, [edx+2] |
mov word [esp+v86_regs.cs], ax |
mov ax, [edx+4] |
mov word [esp+v86_regs.eflags], ax |
add word [esp+v86_regs.esp], 6 |
popad |
iretd |
.handle_pushf: |
cmp word [esp+v86_regs.esp], 1 |
jnz @f |
mov bl, 12 |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
mov eax, [esp+v86_regs.esp] |
sub eax, 2 |
movzx eax, ax |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
lea eax, [edx+1] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
sub word [esp+v86_regs.esp], 2 |
mov eax, [esp+v86_regs.eflags] |
mov [edx], ax |
inc word [esp+v86_regs.eip] |
popad |
iretd |
.handle_pushfd: |
cmp word [esp+v86_regs.esp], 4 |
jae @f |
mov bl, 12 ; #SS exception |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
movzx eax, word [esp+v86_regs.esp] |
sub eax, 4 |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
lea eax, [edx+3] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
sub word [esp+v86_regs.esp], 4 |
movzx eax, word [esp+v86_regs.eflags] |
mov [edx], eax |
add word [esp+v86_regs.eip], 2 |
popad |
iretd |
.handle_popf: |
cmp word [esp+v86_regs.esp], 0xFFFF |
jnz @f |
mov bl, 12 |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
movzx eax, word [esp+v86_regs.esp] |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
lea eax, [edx+1] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
mov ax, [edx] |
mov word [esp+v86_regs.eflags], ax |
add word [esp+v86_regs.esp], 2 |
inc word [esp+v86_regs.eip] |
popad |
iretd |
.handle_popfd: |
cmp word [esp+v86_regs.esp], 0x10000 - 4 |
jbe @f |
mov bl, 12 |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
movzx eax, word [esp+v86_regs.esp] |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
lea eax, [edx+3] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
mov eax, [edx] |
mov word [esp+v86_regs.eflags], ax |
add word [esp+v86_regs.esp], 4 |
add word [esp+v86_regs.eip], 2 |
popad |
iretd |
.handle_cli: |
and byte [esp+v86_regs.eflags+1], not 2 |
inc word [esp+v86_regs.eip] |
popad |
iretd |
.handle_sti: |
or byte [esp+v86_regs.eflags+1], 2 |
inc word [esp+v86_regs.eip] |
popad |
iretd |
.handle_rep: |
cmp word [esp+v86_regs.eip], 0xFFFF |
jae .nogp |
lodsb |
cmp al, 6Eh |
jz .handle_rep_outsb |
jmp .nogp |
.handle_rep_outsb: |
.handle_in: |
.handle_out: |
.invalid_io_byte: |
movzx ebx, word [esp+v86_regs.edx] |
mov ecx, 1 |
jmp .invalid_io |
.handle_in_imm: |
.handle_out_imm: |
cmp word [esp+v86_regs.eip], 0xFFFF |
jae .nogp |
lodsb |
movzx ebx, al |
mov ecx, 1 |
jmp .invalid_io |
.handle_66: |
cmp word [esp+v86_regs.eip], 0xFFFF |
jae .nogp |
lodsb |
cmp al, 0x9C |
jz .handle_pushfd |
cmp al, 0x9D |
jz .handle_popfd |
cmp al, 0xEF |
jz .handle_out_dword |
cmp al, 0xED |
jz .handle_in_dword |
jmp .nogp |
.handle_in_word: |
.handle_out_word: |
movzx ebx, word [esp+v86_regs.edx] |
mov ecx, 2 |
jmp .invalid_io |
.handle_in_dword: |
.handle_out_dword: |
.invalid_io_dword: |
movzx ebx, word [esp+v86_regs.edx] |
mov ecx, 4 |
.invalid_io: |
mov esi, v86_io_str1 |
call sys_msg_board_str |
mov eax, ebx |
call sys_msg_board_dword |
mov esi, v86_io_byte |
cmp ecx, 1 |
jz @f |
mov esi, v86_io_word |
cmp ecx, 2 |
jz @f |
mov esi, v86_io_dword |
@@: |
call sys_msg_board_str |
if DEBUG_SHOW_IO |
mov edx, ebx |
mov ebx, 200 |
call delay_hs |
mov esi, [esp+v86_regs.size+10h+4] |
mov eax, [esi+V86_machine.iopm] |
@@: |
btr [eax], edx |
inc edx |
loop @b |
popad |
iretd |
else |
mov eax, 2 |
jmp .exit |
end if |
.nogp: |
mov esi, v86_exc_str1 |
call sys_msg_board_str |
mov al, bl |
call sys_msg_board_byte |
mov esi, v86_exc_str2 |
call sys_msg_board_str |
mov ax, [esp+32+4] |
call sys_msg_board_word |
mov esi, v86_exc_str3 |
call sys_msg_board_str |
mov ax, [esp+32] |
call sys_msg_board_word |
mov esi, v86_exc_str4 |
call sys_msg_board_str |
mov ecx, 8 |
movzx edx, word [esp+32+4] |
shl edx, 4 |
add edx, [esp+32] |
@@: |
mov esi, [esp+v86_regs.size+10h+4] |
mov eax, edx |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jb .nopage |
mov esi, v86_exc_str3-2 |
call sys_msg_board_str |
mov al, [edx] |
call sys_msg_board_byte |
inc edx |
loop @b |
jmp @f |
.nopage: |
mov esi, v86_exc_str5 |
call sys_msg_board_str |
@@: |
mov esi, v86_newline |
call sys_msg_board_str |
mov eax, 1 |
jmp .exit |
.done: |
xor eax, eax |
.exit: |
mov [esp+v86_regs.size+10h+1Ch], eax |
mov [esp+v86_regs.size+10h+18h], ebx |
mov edx, [esp+v86_regs.size+10h+14h] |
cmp edx, -1 |
jz @f |
dec [v86_irqhooks+edx*8+4] |
jnz @f |
and [v86_irqhooks+edx*8], 0 |
@@: |
mov esi, esp |
mov edi, [esi+v86_regs.size+10h+10h] |
add edi, v86_regs.size |
mov ecx, v86_regs.size/4 |
rep movsd |
mov esp, esi |
cli |
mov ecx, [CURRENT_TASK] |
shl ecx, 8 |
pop eax |
mov [SLOT_BASE+ecx+APPDATA.saved_esp0], eax |
mov [tss._esp0], eax |
pop eax |
mov [SLOT_BASE+ecx+APPDATA.dir_table], eax |
pop ebx |
mov dword [SLOT_BASE+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 [page_tabs + (tss._io_map_0 shr 10)], ebx |
mov cr3, eax |
sti |
popad |
ret |
;my05: |
; mov dx, 30C2h |
; mov cx, 4 |
;.0: |
; in al, dx |
; cmp al, 0FFh |
; jz @f |
; test al, 4 |
; jnz .1 |
;@@: |
; add dx, 8 |
; in al, dx |
; cmp al, 0FFh |
; jz @f |
; test al, 4 |
; jnz .1 |
;@@: |
; loop .0 |
; ret |
;.1: |
; or al, 84h |
; out dx, al |
;.2: |
; mov dx, 30F7h |
; in al, dx |
; mov byte [BOOT_VAR + 48Eh], 0FFh |
; ret |
align 4 |
v86_irq: |
; push irq/pushad/jmp v86_irq |
; ebp = irq |
lea esi, [esp+1Ch] |
lea edi, [esi+4] |
mov ecx, 8 |
std |
rep movsd |
cld |
mov edi, ebp |
pop eax |
v86_irq2: |
mov esi, [v86_irqhooks+edi*8] ; get VM handle |
mov eax, [esi+V86_machine.pagedir] |
call get_pg_addr |
mov ecx, [CURRENT_TASK] |
shl ecx, 8 |
cmp [SLOT_BASE+ecx+APPDATA.dir_table], eax |
jnz .notcurrent |
lea eax, [edi+8] |
cmp al, 10h |
mov ah, 1 |
jb @f |
add al, 60h |
@@: |
jmp v86_exc_c.simulate_int |
.notcurrent: |
mov ebx, SLOT_BASE + 0x100 |
mov ecx, [TASK_COUNT] |
.scan: |
cmp [ebx+APPDATA.dir_table], eax |
jnz .cont |
push ecx |
mov ecx, [ebx+APPDATA.saved_esp0] |
cmp word [ecx-v86_regs.size+v86_regs.esp], 6 |
jb .cont2 |
movzx edx, word [ecx-v86_regs.size+v86_regs.ss] |
shl edx, 4 |
push eax |
movzx eax, word [ecx-v86_regs.size+v86_regs.esp] |
sub eax, 6 |
add edx, eax |
mov eax, edx |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jb .cont3 |
lea eax, [edx+5] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jb .cont3 |
pop eax |
pop ecx |
jmp .found |
.cont3: |
pop eax |
.cont2: |
pop ecx |
.cont: |
loop .scan |
mov ecx, edi |
call irq_eoi |
popad |
iretd |
.found: |
mov cr3, eax |
sub word [esi-v86_regs.size+v86_regs.esp], 6 |
mov ecx, [esi-v86_regs.size+v86_regs.eip] |
mov word [edx], cx |
mov ecx, [esi-v86_regs.size+v86_regs.cs] |
mov word [edx+2], cx |
mov ecx, [esi-v86_regs.size+v86_regs.eflags] |
mov word [edx+4], cx |
lea eax, [edi+8] |
cmp al, 10h |
jb @f |
add al, 60h |
@@: |
mov cx, [eax*4] |
mov word [esi-v86_regs.size+v86_regs.eip], cx |
mov cx, [eax*4+2] |
mov word [esi-v86_regs.size+v86_regs.cs], cx |
and byte [esi-v86_regs.size+v86_regs.eflags+1], not 3 |
call update_counters |
lea edi, [ebx + 0x100000000 - SLOT_BASE] |
shr edi, 3 |
add edi, TASK_DATA |
call find_next_task.found |
call do_change_task |
popad |
iretd |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; Virtual-8086 mode manager |
; diamond, 2007, 2008 |
DEBUG_SHOW_IO = 0 |
struc V86_machine |
{ |
; page directory |
.pagedir dd ? |
; translation table: V86 address -> flat linear address |
.pages dd ? |
; mutex to protect all data from writing by multiple threads at one time |
.mutex dd ? |
; i/o permission map |
.iopm dd ? |
.size = $ |
} |
virtual at 0 |
V86_machine V86_machine |
end virtual |
; Create V86 machine |
; in: nothing |
; out: eax = handle (pointer to struc V86_machine) |
; eax = NULL => failure |
; destroys: ebx, ecx, edx (due to malloc) |
v86_create: |
; allocate V86_machine structure |
mov eax, V86_machine.size |
call malloc |
test eax, eax |
jz .fail |
; initialize mutex |
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 |
call kernel_alloc |
test eax, eax |
jz .fail2 |
mov [ebx+V86_machine.pagedir], eax |
push edi eax |
mov edi, eax |
add eax, 1800h |
mov [ebx+V86_machine.pages], eax |
; initialize tables |
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 |
pop esi |
; 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] |
@@: |
lea eax, [edx + OS_BASE] |
mov [edi+800h], eax |
lea eax, [edx + 111b] |
stosd |
add edx, 0x1000 |
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 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 |
mov eax, ebx |
ret |
.fail2: |
mov eax, ebx |
call free |
.fail: |
xor eax, eax |
ret |
; 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 |
; Translate V86-address to linear address |
; in: eax=V86 address |
; esi=handle |
; out: eax=linear address |
; destroys: nothing |
v86_get_lin_addr: |
push ecx edx |
mov ecx, eax |
mov edx, [esi+V86_machine.pages] |
shr ecx, 12 |
and eax, 0xFFF |
add eax, [edx+ecx*4] ; atomic operation, no mutex needed |
pop edx ecx |
ret |
; Sets linear address for V86-page |
; in: eax=linear address (must be page-aligned) |
; ecx=V86 page (NOT address!) |
; 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 |
; Allocate memory in V86 machine |
; in: eax=size (in bytes) |
; esi=handle |
; out: eax=V86 address, para-aligned (0x10 multiple) |
; destroys: nothing |
; ¥¤®¯¨á !!! |
;v86_alloc: |
; push ebx ecx edx edi |
; lea ebx, [esi+V86_machine.mutex] |
; call wait_mutex |
; add eax, 0x1F |
; shr eax, 4 |
; mov ebx, 0x1000 ; start with address 0x1000 (second page) |
; mov edi, [esi+V86_machine.tables] |
;.l: |
; mov ecx, ebx |
; shr ecx, 12 |
; mov edx, [edi+0x1000+ecx*4] ; get linear address |
; test edx, edx ; page allocated? |
; jz .unalloc |
; mov ecx, ebx |
; and ecx, 0xFFF |
; add edx, ecx |
; cmp dword [edx], 0 ; free block? |
; jnz .n |
; cmp dword [edx+4], |
; and [esi+V86_machine.mutex], 0 |
; pop edi edx ecx ebx |
; ret |
uglobal |
sys_v86_machine dd ? |
endg |
; Called from kernel.asm at first stages of loading |
; Initialize system V86 machine (used to simulate BIOS int 13h) |
init_sys_v86: |
call v86_create |
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] |
xor eax, eax |
mov edi, ecx |
mov ecx, 10000h/8/4 |
rep stosd |
end if |
.ret: |
ret |
struc v86_regs |
{ |
; don't change the order, it is important |
.edi dd ? |
.esi dd ? |
.ebp dd ? |
dd ? ; ignored |
.ebx dd ? |
.edx dd ? |
.ecx dd ? |
.eax dd ? |
.eip dd ? |
.cs dd ? |
.eflags dd ? ; VM flag must be set! |
.esp dd ? |
.ss dd ? |
.es dd ? |
.ds dd ? |
.fs dd ? |
.gs dd ? |
.size = $ |
} |
virtual at 0 |
v86_regs v86_regs |
end virtual |
; Run V86 machine |
; in: ebx -> registers for V86 (two structures: in and out) |
; esi = handle |
; ecx = expected end address (CS:IP) |
; edx = IRQ to hook or -1 if not required |
; out: structure pointed to by ebx is filled with new values |
; eax = 1 - exception has occured, cl contains code |
; eax = 2 - access to disabled i/o port, ecx contains port address |
; 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 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 |
add eax, 0x1000 |
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 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. |
; sti |
mov eax, esi |
sub esp, v86_regs.size |
mov esi, ebx |
mov edi, esp |
mov ecx, v86_regs.size/4 |
rep movsd |
cmp edx, -1 |
jz .noirqhook |
uglobal |
v86_irqhooks rd IRQ_RESERVED * 2 |
endg |
cmp [v86_irqhooks+edx*8], 0 |
jz @f |
cmp [v86_irqhooks+edx*8], eax |
jz @f |
mov esi, v86_irqerr |
call sys_msg_board_str |
inc [v86_irqhooks+edx*8+4] |
mov eax, 3 |
jmp v86_exc_c.exit |
@@: |
mov [v86_irqhooks+edx*8], eax |
inc [v86_irqhooks+edx*8+4] |
.noirqhook: |
popad |
iretd |
; It is only possible to leave virtual-8086 mode by faulting to |
; a protected-mode interrupt handler (typically the general-protection |
; exception handler, which in turn calls the virtual 8086-mode monitor). |
iglobal |
v86_exc_str1 db 'V86 : unexpected exception ',0 |
v86_exc_str2 db ' at ',0 |
v86_exc_str3 db ':',0 |
v86_exc_str4 db 13,10,'V86 : faulted code:',0 |
v86_exc_str5 db ' (unavailable)',0 |
v86_newline db 13,10,0 |
v86_io_str1 db 'V86 : access to disabled i/o port ',0 |
v86_io_byte db ' (byte)',13,10,0 |
v86_io_word db ' (word)',13,10,0 |
v86_io_dword db ' (dword)',13,10,0 |
v86_irqerr db 'V86 : IRQ already hooked',13,10,0 |
endg |
v86_exc_c: |
; Did we all that we have wanted to do? |
cmp bl, 1 |
jne @f |
xor eax, eax |
mov dr6, eax |
@@: |
mov eax, [esp+v86_regs.size+10h+18h] |
cmp word [esp+v86_regs.eip], ax |
jnz @f |
shr eax, 16 |
cmp word [esp+v86_regs.cs], ax |
jz .done |
@@: |
; Various system events, which must be handled, result in #GP |
cmp bl, 13 |
jnz .nogp |
; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error |
cmp word [esp+v86_regs.eip+2], 0 |
jnz .nogp |
; Otherwise we can safely access byte at CS:IP |
; (because it is #GP, not #PF handler) |
; ᫨ ¡ë ¬ë ¬®£«¨ áå«®¯®â âì ¨áª«î票¥ ⮫쪮 ¨§-§ çâ¥¨ï ¡ ©â®¢ ª®¤ , |
; ¬ë ¡ë ¥£® 㦥 áå«®¯®â «¨ ¨ íâ® ¡ë«® ¡ë ¥ #GP |
movzx esi, word [esp+v86_regs.cs] |
shl esi, 4 |
add esi, [esp+v86_regs.eip] |
lodsb |
cmp al, 0xCD ; int xx command = CD xx |
jz .handle_int |
cmp al, 0xCF |
jz .handle_iret |
cmp al, 0xF3 |
jz .handle_rep |
cmp al, 0xEC |
jz .handle_in |
cmp al, 0xED |
jz .handle_in_word |
cmp al, 0xEE |
jz .handle_out |
cmp al, 0xEF |
jz .handle_out_word |
cmp al, 0xE4 |
jz .handle_in_imm |
cmp al, 0xE6 |
jz .handle_out_imm |
cmp al, 0x9C |
jz .handle_pushf |
cmp al, 0x9D |
jz .handle_popf |
cmp al, 0xFA |
jz .handle_cli |
cmp al, 0xFB |
jz .handle_sti |
cmp al, 0x66 |
jz .handle_66 |
jmp .nogp |
.handle_int: |
cmp word [esp+v86_regs.eip], 0xFFFF |
jae .nogp |
xor eax, eax |
lodsb |
; call sys_msg_board_byte |
; simulate INT command |
; N.B. It is possible that some checks need to be corrected, |
; but at least in case of normal execution the code works. |
.simulate_int: |
cmp word [esp+v86_regs.esp], 6 |
jae @f |
mov bl, 12 ; #SS exception |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
push eax |
movzx eax, word [esp+4+v86_regs.esp] |
sub eax, 6 |
add edx, eax |
mov eax, edx |
mov esi, [esp+4+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
lea eax, [edx+5] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
sub word [esp+4+v86_regs.esp], 6 |
mov eax, [esp+4+v86_regs.eip] |
cmp byte [esp+1], 0 |
jnz @f |
inc eax |
inc eax |
@@: |
mov word [edx], ax |
mov eax, [esp+4+v86_regs.cs] |
mov word [edx+2], ax |
mov eax, [esp+4+v86_regs.eflags] |
mov word [edx+4], ax |
pop eax |
mov ah, 0 |
mov cx, [eax*4] |
mov word [esp+v86_regs.eip], cx |
mov cx, [eax*4+2] |
mov word [esp+v86_regs.cs], cx |
; note that interrupts will be disabled globally at IRET |
and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags |
; continue V86 execution |
popad |
iretd |
.handle_iret: |
cmp word [esp+v86_regs.esp], 0x10000 - 6 |
jbe @f |
mov bl, 12 |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
movzx eax, word [esp+v86_regs.esp] |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
lea eax, [edx+5] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
mov ax, [edx] |
mov word [esp+v86_regs.eip], ax |
mov ax, [edx+2] |
mov word [esp+v86_regs.cs], ax |
mov ax, [edx+4] |
mov word [esp+v86_regs.eflags], ax |
add word [esp+v86_regs.esp], 6 |
popad |
iretd |
.handle_pushf: |
cmp word [esp+v86_regs.esp], 1 |
jnz @f |
mov bl, 12 |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
mov eax, [esp+v86_regs.esp] |
sub eax, 2 |
movzx eax, ax |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
lea eax, [edx+1] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
sub word [esp+v86_regs.esp], 2 |
mov eax, [esp+v86_regs.eflags] |
mov [edx], ax |
inc word [esp+v86_regs.eip] |
popad |
iretd |
.handle_pushfd: |
cmp word [esp+v86_regs.esp], 4 |
jae @f |
mov bl, 12 ; #SS exception |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
movzx eax, word [esp+v86_regs.esp] |
sub eax, 4 |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
lea eax, [edx+3] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
sub word [esp+v86_regs.esp], 4 |
movzx eax, word [esp+v86_regs.eflags] |
mov [edx], eax |
add word [esp+v86_regs.eip], 2 |
popad |
iretd |
.handle_popf: |
cmp word [esp+v86_regs.esp], 0xFFFF |
jnz @f |
mov bl, 12 |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
movzx eax, word [esp+v86_regs.esp] |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 ; #PF exception |
jmp .nogp |
@@: |
lea eax, [edx+1] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
mov ax, [edx] |
mov word [esp+v86_regs.eflags], ax |
add word [esp+v86_regs.esp], 2 |
inc word [esp+v86_regs.eip] |
popad |
iretd |
.handle_popfd: |
cmp word [esp+v86_regs.esp], 0x10000 - 4 |
jbe @f |
mov bl, 12 |
jmp .nogp |
@@: |
movzx edx, word [esp+v86_regs.ss] |
shl edx, 4 |
movzx eax, word [esp+v86_regs.esp] |
add edx, eax |
mov eax, edx |
mov esi, [esp+v86_regs.size+10h+4] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
lea eax, [edx+3] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jae @f |
mov bl, 14 |
jmp .nogp |
@@: |
mov eax, [edx] |
mov word [esp+v86_regs.eflags], ax |
add word [esp+v86_regs.esp], 4 |
add word [esp+v86_regs.eip], 2 |
popad |
iretd |
.handle_cli: |
and byte [esp+v86_regs.eflags+1], not 2 |
inc word [esp+v86_regs.eip] |
popad |
iretd |
.handle_sti: |
or byte [esp+v86_regs.eflags+1], 2 |
inc word [esp+v86_regs.eip] |
popad |
iretd |
.handle_rep: |
cmp word [esp+v86_regs.eip], 0xFFFF |
jae .nogp |
lodsb |
cmp al, 6Eh |
jz .handle_rep_outsb |
jmp .nogp |
.handle_rep_outsb: |
.handle_in: |
.handle_out: |
.invalid_io_byte: |
movzx ebx, word [esp+v86_regs.edx] |
mov ecx, 1 |
jmp .invalid_io |
.handle_in_imm: |
.handle_out_imm: |
cmp word [esp+v86_regs.eip], 0xFFFF |
jae .nogp |
lodsb |
movzx ebx, al |
mov ecx, 1 |
jmp .invalid_io |
.handle_66: |
cmp word [esp+v86_regs.eip], 0xFFFF |
jae .nogp |
lodsb |
cmp al, 0x9C |
jz .handle_pushfd |
cmp al, 0x9D |
jz .handle_popfd |
cmp al, 0xEF |
jz .handle_out_dword |
cmp al, 0xED |
jz .handle_in_dword |
jmp .nogp |
.handle_in_word: |
.handle_out_word: |
movzx ebx, word [esp+v86_regs.edx] |
mov ecx, 2 |
jmp .invalid_io |
.handle_in_dword: |
.handle_out_dword: |
.invalid_io_dword: |
movzx ebx, word [esp+v86_regs.edx] |
mov ecx, 4 |
.invalid_io: |
mov esi, v86_io_str1 |
call sys_msg_board_str |
mov eax, ebx |
call sys_msg_board_dword |
mov esi, v86_io_byte |
cmp ecx, 1 |
jz @f |
mov esi, v86_io_word |
cmp ecx, 2 |
jz @f |
mov esi, v86_io_dword |
@@: |
call sys_msg_board_str |
if DEBUG_SHOW_IO |
mov edx, ebx |
mov ebx, 200 |
call delay_hs |
mov esi, [esp+v86_regs.size+10h+4] |
mov eax, [esi+V86_machine.iopm] |
@@: |
btr [eax], edx |
inc edx |
loop @b |
popad |
iretd |
else |
mov eax, 2 |
jmp .exit |
end if |
.nogp: |
mov esi, v86_exc_str1 |
call sys_msg_board_str |
mov al, bl |
call sys_msg_board_byte |
mov esi, v86_exc_str2 |
call sys_msg_board_str |
mov ax, [esp+32+4] |
call sys_msg_board_word |
mov esi, v86_exc_str3 |
call sys_msg_board_str |
mov ax, [esp+32] |
call sys_msg_board_word |
mov esi, v86_exc_str4 |
call sys_msg_board_str |
mov ecx, 8 |
movzx edx, word [esp+32+4] |
shl edx, 4 |
add edx, [esp+32] |
@@: |
mov esi, [esp+v86_regs.size+10h+4] |
mov eax, edx |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jb .nopage |
mov esi, v86_exc_str3-2 |
call sys_msg_board_str |
mov al, [edx] |
call sys_msg_board_byte |
inc edx |
loop @b |
jmp @f |
.nopage: |
mov esi, v86_exc_str5 |
call sys_msg_board_str |
@@: |
mov esi, v86_newline |
call sys_msg_board_str |
mov eax, 1 |
jmp .exit |
.done: |
xor eax, eax |
.exit: |
mov [esp+v86_regs.size+10h+1Ch], eax |
mov [esp+v86_regs.size+10h+18h], ebx |
mov edx, [esp+v86_regs.size+10h+14h] |
cmp edx, -1 |
jz @f |
dec [v86_irqhooks+edx*8+4] |
jnz @f |
and [v86_irqhooks+edx*8], 0 |
@@: |
mov esi, esp |
mov edi, [esi+v86_regs.size+10h+10h] |
add edi, v86_regs.size |
mov ecx, v86_regs.size/4 |
rep movsd |
mov esp, esi |
cli |
mov ecx, [CURRENT_TASK] |
shl ecx, 8 |
pop eax |
mov [SLOT_BASE+ecx+APPDATA.saved_esp0], eax |
mov [tss._esp0], eax |
pop eax |
mov [SLOT_BASE+ecx+APPDATA.dir_table], eax |
pop ebx |
mov dword [SLOT_BASE+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 [page_tabs + (tss._io_map_0 shr 10)], ebx |
mov cr3, eax |
sti |
popad |
ret |
;my05: |
; mov dx, 30C2h |
; mov cx, 4 |
;.0: |
; in al, dx |
; cmp al, 0FFh |
; jz @f |
; test al, 4 |
; jnz .1 |
;@@: |
; add dx, 8 |
; in al, dx |
; cmp al, 0FFh |
; jz @f |
; test al, 4 |
; jnz .1 |
;@@: |
; loop .0 |
; ret |
;.1: |
; or al, 84h |
; out dx, al |
;.2: |
; mov dx, 30F7h |
; in al, dx |
; mov byte [BOOT_VAR + 48Eh], 0FFh |
; ret |
align 4 |
v86_irq: |
; push irq/pushad/jmp v86_irq |
; ebp = irq |
lea esi, [esp+1Ch] |
lea edi, [esi+4] |
mov ecx, 8 |
std |
rep movsd |
cld |
mov edi, ebp |
pop eax |
v86_irq2: |
mov esi, [v86_irqhooks+edi*8] ; get VM handle |
mov eax, [esi+V86_machine.pagedir] |
call get_pg_addr |
mov ecx, [CURRENT_TASK] |
shl ecx, 8 |
cmp [SLOT_BASE+ecx+APPDATA.dir_table], eax |
jnz .notcurrent |
lea eax, [edi+8] |
cmp al, 10h |
mov ah, 1 |
jb @f |
add al, 60h |
@@: |
jmp v86_exc_c.simulate_int |
.notcurrent: |
mov ebx, SLOT_BASE + 0x100 |
mov ecx, [TASK_COUNT] |
.scan: |
cmp [ebx+APPDATA.dir_table], eax |
jnz .cont |
push ecx |
mov ecx, [ebx+APPDATA.saved_esp0] |
cmp word [ecx-v86_regs.size+v86_regs.esp], 6 |
jb .cont2 |
movzx edx, word [ecx-v86_regs.size+v86_regs.ss] |
shl edx, 4 |
push eax |
movzx eax, word [ecx-v86_regs.size+v86_regs.esp] |
sub eax, 6 |
add edx, eax |
mov eax, edx |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jb .cont3 |
lea eax, [edx+5] |
call v86_get_lin_addr |
cmp eax, 0x1000 |
jb .cont3 |
pop eax |
pop ecx |
jmp .found |
.cont3: |
pop eax |
.cont2: |
pop ecx |
.cont: |
loop .scan |
mov ecx, edi |
call irq_eoi |
popad |
iretd |
.found: |
mov cr3, eax |
sub word [esi-v86_regs.size+v86_regs.esp], 6 |
mov ecx, [esi-v86_regs.size+v86_regs.eip] |
mov word [edx], cx |
mov ecx, [esi-v86_regs.size+v86_regs.cs] |
mov word [edx+2], cx |
mov ecx, [esi-v86_regs.size+v86_regs.eflags] |
mov word [edx+4], cx |
lea eax, [edi+8] |
cmp al, 10h |
jb @f |
add al, 60h |
@@: |
mov cx, [eax*4] |
mov word [esi-v86_regs.size+v86_regs.eip], cx |
mov cx, [eax*4+2] |
mov word [esi-v86_regs.size+v86_regs.cs], cx |
and byte [esi-v86_regs.size+v86_regs.eflags+1], not 3 |
call update_counters |
lea edi, [ebx + 0x100000000 - SLOT_BASE] |
shr edi, 3 |
add edi, TASK_DATA |
call find_next_task.found |
call do_change_task |
popad |
iretd |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/data16.inc |
---|
1,90 → 1,91 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
flm db 0 |
preboot_lfb db 0 |
preboot_bootlog db 0 |
boot_drive db 0 |
bx_from_load: dw 'r1' ; ñòðóêòóðà äëÿ õðàíåíèÿ ïàðàìåòðîâ- îòêóäà ãàøðóçèëèñü, áåðåòñÿ íèæå èç bx ; {SPraid}[13.03.2007] |
; a,b,c,d - âèí÷åñòåðû, r - ðàì äèñê |
; # äèñêà... ñèìâîë, à íå áàéò. '1', à íå 1 |
align 4 |
old_ints_h: |
dw 0x400 |
dd 0 |
dw 0 |
if ~ defined extended_primary_loader ; restart from memory is not supported in extended primary loader cfg |
kernel_restart_bootblock: |
db 1 ; version |
dw 1 ; floppy image is in memory |
dd 0 ; cannot save parameters |
end if |
; table for move to extended memory (int 15h, ah=87h) |
align 8 |
movedesc: |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 |
db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
fwmovedesc: |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 |
db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
if defined extended_primary_loader |
; look in PrimaryLoader.txt for the description |
bootdevice dw 0 ; ax from primary loader |
bootfs dw 0 ; bx from primary loader |
bootcallback dd 0 ; ds:si from primary loader |
; data for configuration file loading, look in PrimaryLoader.txt |
config_file_struct: |
dw 0, 4000h ; load to 4000:0000 |
dw 16 ; read no more than 16*4K = 64K |
db 'config.ini',0 |
; data for configuration file parsing |
macro config_variable string,parser |
{ |
local len |
len dw 0 |
db string |
store word $ - len - 2 at len |
dw parser |
} |
config_file_variables: |
config_variable 'timeout', parse_timeout |
config_variable 'resolution', parse_resolution |
config_variable 'vbemode', parse_vbemode |
; config_variable 'vrr', parse_vrr |
config_variable 'biosdisks', parse_biosdisks |
config_variable 'imgfrom', parse_imgfrom |
dw 0 |
; data for image file loading, look in PrimaryLoader.txt |
image_file_struct: |
dw 0, 4000h ; load to 4000:0000 |
dw 16 ; read no more than 16*4K = 64K |
db 'kolibri.img',0 |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
flm db 0 |
preboot_lfb db 0 |
preboot_bootlog db 0 |
boot_drive db 0 |
bx_from_load: |
dw 'r1' ; ñòðóêòóðà äëÿ õðàíåíèÿ ïàðàìåòðîâ- îòêóäà ãàøðóçèëèñü, áåðåòñÿ íèæå èç bx ; {SPraid}[13.03.2007] |
; a,b,c,d - âèí÷åñòåðû, r - ðàì äèñê |
; # äèñêà... ñèìâîë, à íå áàéò. '1', à íå 1 |
align 4 |
old_ints_h: |
dw 0x400 |
dd 0 |
dw 0 |
if ~ defined extended_primary_loader ; restart from memory is not supported in extended primary loader cfg |
kernel_restart_bootblock: |
db 1 ; version |
dw 1 ; floppy image is in memory |
dd 0 ; cannot save parameters |
end if |
; table for move to extended memory (int 15h, ah=87h) |
align 8 |
movedesc: |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 |
db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
fwmovedesc: |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 |
db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
if defined extended_primary_loader |
; look in PrimaryLoader.txt for the description |
bootdevice dw 0 ; ax from primary loader |
bootfs dw 0 ; bx from primary loader |
bootcallback dd 0 ; ds:si from primary loader |
; data for configuration file loading, look in PrimaryLoader.txt |
config_file_struct: |
dw 0, 4000h ; load to 4000:0000 |
dw 16 ; read no more than 16*4K = 64K |
db 'config.ini',0 |
; data for configuration file parsing |
macro config_variable string,parser |
{ |
local len |
len dw 0 |
db string |
store word $ - len - 2 at len |
dw parser |
} |
config_file_variables: |
config_variable 'timeout', parse_timeout |
config_variable 'resolution', parse_resolution |
config_variable 'vbemode', parse_vbemode |
; config_variable 'vrr', parse_vrr |
config_variable 'biosdisks', parse_biosdisks |
config_variable 'imgfrom', parse_imgfrom |
dw 0 |
; data for image file loading, look in PrimaryLoader.txt |
image_file_struct: |
dw 0, 4000h ; load to 4000:0000 |
dw 16 ; read no more than 16*4K = 64K |
db 'kolibri.img',0 |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/data32.inc |
---|
83,7 → 83,7 |
boot_bgr db 'Calculating background',0 |
boot_resirqports db 'Reserving IRQs & ports',0 |
boot_setostask db 'Setting OS task',0 |
boot_allirqs db 'Unmasking IRQs',0 |
boot_allirqs db 'Unmasking IRQs',0 |
boot_tsc db 'Reading TSC',0 |
boot_cpufreq db 'CPU frequency is ',' ',' MHz',0 |
boot_pal_ega db 'Setting EGA/CGA 320x200 palette',0 |
95,8 → 95,8 |
end if |
end if |
boot_APIC_found db 'APIC enabled', 0 |
boot_APIC_nfound db 'APIC not found', 0 |
boot_APIC_found db 'APIC enabled', 0 |
boot_APIC_nfound db 'APIC not found', 0 |
;new_process_loading db 'K : New Process - loading',13,10,0 |
;new_process_running db 'K : New Process - done',13,10,0 |
293,7 → 293,8 |
align 16 |
cur_saved_data rb 4096 |
fpu_data: rb 512 |
fpu_data: |
rb 512 |
mem_block_list rd 64*2 |
mem_used_list rd 64*2 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/detect/biosdisk.inc |
---|
1,81 → 1,81 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Detect all BIOS hard drives. |
; diamond, 2008 |
xor cx, cx |
mov es, cx |
mov di, 0x9080 |
mov byte [es:di-1], cl |
cmp [preboot_biosdisk], 1 |
jnz bdde |
mov dl, 80h |
bdds: |
mov ah, 15h |
push cx dx di |
int 13h |
pop di dx cx |
jc bddc |
test ah, ah |
jz bddc |
inc cx |
mov ah, 48h |
push ds |
push es |
pop ds |
mov si, 0xA000 |
mov word [si], 1Eh |
mov ah, 48h |
int 13h |
pop ds |
jc bddc2 |
inc byte [es:0x907F] |
cmp word [es:si], 1Eh |
jb bddl |
cmp word [es:si+1Ah], 0xFFFF |
jz bddl |
mov al, dl |
stosb |
push ds |
lds si, [es:si+1Ah] |
mov al, [si+6] |
and al, 0xF |
stosb |
mov al, byte [si+4] |
shr al, 4 |
and ax, 1 |
cmp word [si], 1F0h |
jz @f |
inc ax |
inc ax |
cmp word [si], 170h |
jz @f |
or ax,-1 |
; mov ax, -1 |
@@: |
stosw |
pop ds |
jmp bddc2 |
bddl: |
mov al, dl |
stosb |
xor ax,ax |
stosb |
dec ax |
stosw |
; mov al, 0 |
; stosb |
; mov ax, -1 |
; stosw |
bddc2: |
cmp cl, [es:0x475] |
jae bdde |
bddc: |
inc dl |
jnz bdds |
bdde: |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Detect all BIOS hard drives. |
; diamond, 2008 |
xor cx, cx |
mov es, cx |
mov di, 0x9080 |
mov byte [es:di-1], cl |
cmp [preboot_biosdisk], 1 |
jnz bdde |
mov dl, 80h |
bdds: |
mov ah, 15h |
push cx dx di |
int 13h |
pop di dx cx |
jc bddc |
test ah, ah |
jz bddc |
inc cx |
mov ah, 48h |
push ds |
push es |
pop ds |
mov si, 0xA000 |
mov word [si], 1Eh |
mov ah, 48h |
int 13h |
pop ds |
jc bddc2 |
inc byte [es:0x907F] |
cmp word [es:si], 1Eh |
jb bddl |
cmp word [es:si+1Ah], 0xFFFF |
jz bddl |
mov al, dl |
stosb |
push ds |
lds si, [es:si+1Ah] |
mov al, [si+6] |
and al, 0xF |
stosb |
mov al, byte [si+4] |
shr al, 4 |
and ax, 1 |
cmp word [si], 1F0h |
jz @f |
inc ax |
inc ax |
cmp word [si], 170h |
jz @f |
or ax, -1 |
; mov ax, -1 |
@@: |
stosw |
pop ds |
jmp bddc2 |
bddl: |
mov al, dl |
stosb |
xor ax, ax |
stosb |
dec ax |
stosw |
; mov al, 0 |
; stosb |
; mov ax, -1 |
; stosw |
bddc2: |
cmp cl, [es:0x475] |
jae bdde |
bddc: |
inc dl |
jnz bdds |
bdde: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/detect/biosmem.inc |
---|
1,43 → 1,43 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Query physical memory map from BIOS. |
; diamond, 2009 |
push ds |
; first call to fn E820 |
mov eax, 0xE820 |
xor ebx, ebx |
mov es, bx |
mov ds, bx |
mov di, 0x9104 |
mov [di-4], ebx ; no blocks yet |
mov ecx, 20 |
mov edx, 0x534D4150 |
int 15h |
jc no_E820 |
cmp eax, 0x534D4150 |
jnz no_E820 |
e820_mem_loop: |
cmp byte [di+16], 1 ; ignore non-free areas |
jnz e820_mem_next |
inc byte [0x9100] |
add di, 20 |
e820_mem_next: |
; consequent calls to fn E820 |
test ebx, ebx |
jz e820_test_done |
cmp byte [0x9100], 32 |
jae e820_test_done |
mov eax, 0xE820 |
int 15h |
jc e820_test_done |
jmp e820_mem_loop |
no_E820: |
; let's hope for mem_test from init.inc |
e820_test_done: |
pop ds |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Query physical memory map from BIOS. |
; diamond, 2009 |
push ds |
; first call to fn E820 |
mov eax, 0xE820 |
xor ebx, ebx |
mov es, bx |
mov ds, bx |
mov di, 0x9104 |
mov [di-4], ebx ; no blocks yet |
mov ecx, 20 |
mov edx, 0x534D4150 |
int 15h |
jc no_E820 |
cmp eax, 0x534D4150 |
jnz no_E820 |
e820_mem_loop: |
cmp byte [di+16], 1 ; ignore non-free areas |
jnz e820_mem_next |
inc byte [0x9100] |
add di, 20 |
e820_mem_next: |
; consequent calls to fn E820 |
test ebx, ebx |
jz e820_test_done |
cmp byte [0x9100], 32 |
jae e820_test_done |
mov eax, 0xE820 |
int 15h |
jc e820_test_done |
jmp e820_mem_loop |
no_E820: |
; let's hope for mem_test from init.inc |
e820_test_done: |
pop ds |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/detect/dev_fd.inc |
---|
1,37 → 1,37 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;*************************************************** |
; ïðåäâàðèòåëüíàÿ î÷èñòêà îáëàñòè òàáëèöû |
; ïîèñê è çàíåñåíèå â òàáëèöó ïðèâîäîâ FDD |
; àâòîð Mario79 |
;*************************************************** |
xor eax,eax |
mov edi,DRIVE_DATA |
mov ecx,16384 |
cld |
rep stosd |
mov al,0x10 |
out 0x70,al |
mov cx,0xff |
wait_cmos: |
dec cx |
test cx,cx |
jnz wait_cmos |
in al,0x71 |
mov [DRIVE_DATA],al |
test al,al |
jz @f |
in al,0x21 |
and al,10111111b ; Enable IRQ6 |
out 0x21,al |
@@: |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;*************************************************** |
; ïðåäâàðèòåëüíàÿ î÷èñòêà îáëàñòè òàáëèöû |
; ïîèñê è çàíåñåíèå â òàáëèöó ïðèâîäîâ FDD |
; àâòîð Mario79 |
;*************************************************** |
xor eax, eax |
mov edi, DRIVE_DATA |
mov ecx, 16384 |
cld |
rep stosd |
mov al, 0x10 |
out 0x70, al |
mov cx, 0xff |
wait_cmos: |
dec cx |
test cx, cx |
jnz wait_cmos |
in al, 0x71 |
mov [DRIVE_DATA], al |
test al, al |
jz @f |
in al, 0x21 |
and al, 10111111b ; Enable IRQ6 |
out 0x21, al |
@@: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/detect/dev_hdcd.inc |
---|
1,385 → 1,394 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;****************************************************** |
; ïîèñê ïðèâîäîâ HDD è CD |
; àâòîð èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷. |
; àäàïòàöèÿ è äîðàáîòêà Mario79 |
;****************************************************** |
;**************************************************** |
;* ÏÎÈÑÊ HDD è CD * |
;**************************************************** |
FindHDD: |
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 |
mov [DiskNumber],1 |
call FindHDD_3 |
; mov al,[Sector512+176] |
; mov [DRIVE_DATA+7],al |
inc [ChannelNumber] |
mov [DiskNumber],0 |
call FindHDD_3 |
; mov al,[Sector512+176] |
; mov [DRIVE_DATA+8],al |
mov [DiskNumber],1 |
call FindHDD_1 |
; mov al,[Sector512+176] |
; mov [DRIVE_DATA+9],al |
jmp EndFindHDD |
FindHDD_1: |
call ReadHDD_ID |
cmp [DevErrorCode],0 |
jne FindHDD_2 |
cmp [Sector512+6],word 16 |
ja FindHDD_2 |
cmp [Sector512+12],word 255 |
ja FindHDD_2 |
inc byte [DRIVE_DATA+1] |
jmp FindHDD_2_2 |
FindHDD_2: |
call DeviceReset |
cmp [DevErrorCode],0 |
jne FindHDD_2_2 |
call ReadCD_ID |
cmp [DevErrorCode],0 |
jne FindHDD_2_2 |
inc byte [DRIVE_DATA+1] |
inc byte [DRIVE_DATA+1] |
FindHDD_2_2: |
ret |
FindHDD_3: |
call FindHDD_1 |
shl byte [DRIVE_DATA+1],2 |
ret |
; Àäðåñ ñ÷èòûâàåìîãî ñåêòîðà â ðåæèìå LBA |
uglobal |
SectorAddress DD ? |
endg |
;************************************************* |
;* ×ÒÅÍÈÅ ÈÄÅÍÒÈÔÈÊÀÒÎÐÀ ÆÅÑÒÊÎÃÎ ÄÈÑÊÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå (0 èëè 1). * |
;* Èäåíòèôèêàöèîííûé áëîê äàííûõ ñ÷èòûâàåòñÿ * |
;* â ìàññèâ Sector512. * |
;************************************************* |
ReadHDD_ID: |
; Çàäàòü ðåæèì CHS |
mov [ATAAddressMode],0 |
; Ïîñëàòü êîìàíäó èäåíòèôèêàöèè óñòðîéñòâà |
mov [ATAFeatures],0 |
mov [ATAHead],0 |
mov [ATACommand],0ECh |
call SendCommandToHDD |
cmp [DevErrorCode],0 ;ïðîâåðèòü êîä îøèáêè |
jne @@End ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè |
mov DX,[ATABasePortAddr] |
add DX,7 ;àäðåñ ðåãèñòðà ñîñòîÿíè |
mov ecx,0xffff |
@@WaitCompleet: |
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû |
dec ecx |
; cmp ecx,0 |
jz @@Error1 ;îøèáêà òàéì-àóòà |
; Ïðîâåðèòü ãîòîâíîñòü |
in AL,DX |
test AL,80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitCompleet |
test AL,1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Error6 |
test AL,08h ;ñîñòîÿíèå ñèãíàëà DRQ |
jz @@WaitCompleet |
; Ïðèíÿòü áëîê äàííûõ îò êîíòðîëëåðà |
; mov AX,DS |
; mov ES,AX |
mov EDI,Sector512 ;offset Sector512 |
mov DX,[ATABasePortAddr] ;ðåãèñòð äàííûõ |
mov CX,256 ;÷èñëî ñ÷èòûâàåìûõ ñëîâ |
rep insw ;ïðèíÿòü áëîê äàííûõ |
ret |
; Çàïèñàòü êîä îøèáêè |
@@Error1: |
mov [DevErrorCode],1 |
ret |
@@Error6: |
mov [DevErrorCode],6 |
@@End: ret |
iglobal |
; Ñòàíäàðòíûå áàçîâûå àäðåñà êàíàëîâ 1 è 2 |
StandardATABases DW 1F0h, 170h |
endg |
uglobal |
; Íîìåð êàíàëà |
ChannelNumber DW ? |
; Íîìåð äèñêà |
DiskNumber DB ? |
; Áàçîâûé àäðåñ ãðóïïû ïîðòîâ êîíòðîëëåðà ATA |
ATABasePortAddr DW ? |
; Ïàðàìåòðû ATA-êîìàíäû |
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 - îøèáêà ïðè âûïîëíåíèè |
; êîìàíäû) |
DevErrorCode dd ? |
endg |
;**************************************************** |
;* ÏÎÑËÀÒÜ ÊÎÌÀÍÄÓ ÇÀÄÀÍÍÎÌÓ ÄÈÑÊÓ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); * |
;* DiskNumber - íîìåð äèñêà (0 èëè 1); * |
;* ATAFeatures - "îñîáåííîñòè"; * |
;* ATASectorCount - êîëè÷åñòâî ñåêòîðîâ; * |
;* ATASectorNumber - íîìåð íà÷àëüíîãî ñåêòîðà; * |
;* ATACylinder - íîìåð íà÷àëüíîãî öèëèíäðà; * |
;* ATAHead - íîìåð íà÷àëüíîé ãîëîâêè; * |
;* ATAAddressMode - ðåæèì àäðåñàöèè (0-CHS, 1-LBA); * |
;* ATACommand - êîä êîìàíäû. * |
;* Ïîñëå óñïåøíîãî âûïîëíåíèÿ ôóíêöèè: * |
;* â ATABasePortAddr - áàçîâûé àäðåñ HDD; * |
;* â DevErrorCode - íîëü. * |
;* Ïðè âîçíèêíîâåíèè îøèáêè â DevErrorCode áóäåò * |
;* âîçâðàùåí êîä îøèáêè. * |
;**************************************************** |
SendCommandToHDD: |
; Ïðîâåðèòü çíà÷åíèå êîäà ðåæèìà |
cmp [ATAAddressMode],1 |
ja @@Err2 |
; Ïðîâåðèòü êîððåêòíîñòü íîìåðà êàíàëà |
mov BX,[ChannelNumber] |
cmp BX,1 |
jb @@Err3 |
cmp BX,2 |
ja @@Err3 |
; Óñòàíîâèòü áàçîâûé àäðåñ |
dec BX |
shl BX,1 |
movzx ebx,bx |
mov AX,[ebx+StandardATABases] |
mov [ATABasePortAddr],AX |
; Îæèäàíèå ãîòîâíîñòè HDD ê ïðèåìó êîìàíäû |
; Âûáðàòü íóæíûé äèñê |
mov DX,[ATABasePortAddr] |
add DX,6 ;àäðåñ ðåãèñòðà ãîëîâîê |
mov AL,[DiskNumber] |
cmp AL,1 ;ïðîâåðèòü íîìåðà äèñêà |
ja @@Err4 |
shl AL,4 |
or AL,10100000b |
out DX,AL |
; Îæèäàòü, ïîêà äèñê íå áóäåò ãîòîâ |
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 |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY |
test AL,80h |
jnz @@WaitHDReady |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà DRQ |
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 ;ïðîâåðèòü íîìåð ãîëîâêè |
ja @@Err5 |
or AL,[ATAHead] |
or AL,10100000b |
mov AH,[ATAAddressMode] |
shl AH,6 |
or AL,AH |
out DX,AL |
; Ïîñëàòü êîìàíäó |
mov AL,[ATACommand] |
inc DX ;ðåãèñòð êîìàíä |
out DX,AL |
sti |
; Ñáðîñèòü ïðèçíàê îøèáêè |
mov [DevErrorCode],0 |
ret |
; Çàïèñàòü êîä îøèáêè |
@@Err1: mov [DevErrorCode],1 |
ret |
@@Err2: mov [DevErrorCode],2 |
ret |
@@Err3: mov [DevErrorCode],3 |
ret |
@@Err4: mov [DevErrorCode],4 |
ret |
@@Err5: mov [DevErrorCode],5 |
; Çàâåðøåíèå ðàáîòû ïðîãðàììû |
ret |
;************************************************* |
;* ×ÒÅÍÈÅ ÈÄÅÍÒÈÔÈÊÀÒÎÐÀ ÓÑÒÐÎÉÑÒÂÀ ATAPI * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;* Èäåíòèôèêàöèîííûé áëîê äàííûõ ñ÷èòûâàåòñÿ * |
;* â ìàññèâ Sector512. * |
;************************************************* |
ReadCD_ID: |
; Çàäàòü ðåæèì CHS |
mov [ATAAddressMode],0 |
; Ïîñëàòü êîìàíäó èäåíòèôèêàöèè óñòðîéñòâà |
mov [ATAFeatures],0 |
mov [ATASectorCount],0 |
mov [ATASectorNumber],0 |
mov [ATACylinder],0 |
mov [ATAHead],0 |
mov [ATACommand],0A1h |
call SendCommandToHDD |
cmp [DevErrorCode],0 ;ïðîâåðèòü êîä îøèáêè |
jne @@End_1 ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè |
; Îæèäàòü ãîòîâíîñòü äàííûõ HDD |
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 |
jnz @@WaitCompleet_1 |
test AL,1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Error6_1 |
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 ;÷èñëî ñ÷èòûâàåìûõ ñëîâ |
rep insw |
ret |
; Çàïèñàòü êîä îøèáêè |
@@Error1_1: |
mov [DevErrorCode],1 |
ret |
@@Error6_1: |
mov [DevErrorCode],6 |
@@End_1: |
ret |
;************************************************* |
;* ÑÁÐÎÑ ÓÑÒÐÎÉÑÒÂÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); * |
;* DiskNumber - íîìåð äèñêà (0 èëè 1). * |
;************************************************* |
DeviceReset: |
; Ïðîâåðèòü êîððåêòíîñòü íîìåðà êàíàëà |
mov BX,[ChannelNumber] |
cmp BX,1 |
jb @@Err3_2 |
cmp BX,2 |
ja @@Err3_2 |
; Óñòàíîâèòü áàçîâûé àäðåñ |
dec BX |
shl BX,1 |
movzx ebx,bx |
mov DX,[ebx+StandardATABases] |
mov [ATABasePortAddr],DX |
; Âûáðàòü íóæíûé äèñê |
add DX,6 ;àäðåñ ðåãèñòðà ãîëîâîê |
mov AL,[DiskNumber] |
cmp AL,1 ;ïðîâåðèòü íîìåðà äèñêà |
ja @@Err4_2 |
shl AL,4 |
or AL,10100000b |
out DX,AL |
; Ïîñëàòü êîìàíäó "Ñáðîñ" |
mov AL,08h |
inc DX ;ðåãèñòð êîìàíä |
out DX,AL |
mov ecx,0x80000 |
@@WaitHDReady_1: |
; Ïðîâåðèòü âðåìÿ îæèäàíè |
dec ecx |
; cmp ecx,0 |
je @@Err1_2 ;îøèáêà òàéì-àóòà |
; Ïðî÷èòàòü ðåãèñòð ñîñòîÿíè |
in AL,DX |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY |
test AL,80h |
jnz @@WaitHDReady_1 |
; Ñáðîñèòü ïðèçíàê îøèáêè |
mov [DevErrorCode],0 |
ret |
; Îáðàáîòêà îøèáîê |
@@Err1_2: mov [DevErrorCode],1 |
ret |
@@Err3_2: mov [DevErrorCode],3 |
ret |
@@Err4_2: mov [DevErrorCode],4 |
; Çàïèñàòü êîä îøèáêè |
ret |
EndFindHDD: |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;****************************************************** |
; ïîèñê ïðèâîäîâ HDD è CD |
; àâòîð èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷. |
; àäàïòàöèÿ è äîðàáîòêà Mario79 |
;****************************************************** |
;**************************************************** |
;* ÏÎÈÑÊ HDD è CD * |
;**************************************************** |
FindHDD: |
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 |
mov [DiskNumber], 1 |
call FindHDD_3 |
; mov al,[Sector512+176] |
; mov [DRIVE_DATA+7],al |
inc [ChannelNumber] |
mov [DiskNumber], 0 |
call FindHDD_3 |
; mov al,[Sector512+176] |
; mov [DRIVE_DATA+8],al |
mov [DiskNumber], 1 |
call FindHDD_1 |
; mov al,[Sector512+176] |
; mov [DRIVE_DATA+9],al |
jmp EndFindHDD |
FindHDD_1: |
call ReadHDD_ID |
cmp [DevErrorCode], 0 |
jne FindHDD_2 |
cmp [Sector512+6], word 16 |
ja FindHDD_2 |
cmp [Sector512+12], word 255 |
ja FindHDD_2 |
inc byte [DRIVE_DATA+1] |
jmp FindHDD_2_2 |
FindHDD_2: |
call DeviceReset |
cmp [DevErrorCode], 0 |
jne FindHDD_2_2 |
call ReadCD_ID |
cmp [DevErrorCode], 0 |
jne FindHDD_2_2 |
inc byte [DRIVE_DATA+1] |
inc byte [DRIVE_DATA+1] |
FindHDD_2_2: |
ret |
FindHDD_3: |
call FindHDD_1 |
shl byte [DRIVE_DATA+1], 2 |
ret |
; Àäðåñ ñ÷èòûâàåìîãî ñåêòîðà â ðåæèìå LBA |
uglobal |
SectorAddress DD ? |
endg |
;************************************************* |
;* ×ÒÅÍÈÅ ÈÄÅÍÒÈÔÈÊÀÒÎÐÀ ÆÅÑÒÊÎÃÎ ÄÈÑÊÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå (0 èëè 1). * |
;* Èäåíòèôèêàöèîííûé áëîê äàííûõ ñ÷èòûâàåòñÿ * |
;* â ìàññèâ Sector512. * |
;************************************************* |
ReadHDD_ID: |
; Çàäàòü ðåæèì CHS |
mov [ATAAddressMode], 0 |
; Ïîñëàòü êîìàíäó èäåíòèôèêàöèè óñòðîéñòâà |
mov [ATAFeatures], 0 |
mov [ATAHead], 0 |
mov [ATACommand], 0ECh |
call SendCommandToHDD |
cmp [DevErrorCode], 0;ïðîâåðèòü êîä îøèáêè |
jne @@End ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè |
mov DX, [ATABasePortAddr] |
add DX, 7 ;àäðåñ ðåãèñòðà ñîñòîÿíè |
mov ecx, 0xffff |
@@WaitCompleet: |
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû |
dec ecx |
; cmp ecx,0 |
jz @@Error1 ;îøèáêà òàéì-àóòà |
; Ïðîâåðèòü ãîòîâíîñòü |
in AL, DX |
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY |
jnz @@WaitCompleet |
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Error6 |
test AL, 08h ;ñîñòîÿíèå ñèãíàëà DRQ |
jz @@WaitCompleet |
; Ïðèíÿòü áëîê äàííûõ îò êîíòðîëëåðà |
; mov AX,DS |
; mov ES,AX |
mov EDI, Sector512 ;offset Sector512 |
mov DX, [ATABasePortAddr];ðåãèñòð äàííûõ |
mov CX, 256 ;÷èñëî ñ÷èòûâàåìûõ ñëîâ |
rep insw ;ïðèíÿòü áëîê äàííûõ |
ret |
; Çàïèñàòü êîä îøèáêè |
@@Error1: |
mov [DevErrorCode], 1 |
ret |
@@Error6: |
mov [DevErrorCode], 6 |
@@End: |
ret |
iglobal |
; Ñòàíäàðòíûå áàçîâûå àäðåñà êàíàëîâ 1 è 2 |
StandardATABases DW 1F0h, 170h |
endg |
uglobal |
; Íîìåð êàíàëà |
ChannelNumber DW ? |
; Íîìåð äèñêà |
DiskNumber DB ? |
; Áàçîâûé àäðåñ ãðóïïû ïîðòîâ êîíòðîëëåðà ATA |
ATABasePortAddr DW ? |
; Ïàðàìåòðû ATA-êîìàíäû |
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 - îøèáêà ïðè âûïîëíåíèè |
; êîìàíäû) |
DevErrorCode dd ? |
endg |
;**************************************************** |
;* ÏÎÑËÀÒÜ ÊÎÌÀÍÄÓ ÇÀÄÀÍÍÎÌÓ ÄÈÑÊÓ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); * |
;* DiskNumber - íîìåð äèñêà (0 èëè 1); * |
;* ATAFeatures - "îñîáåííîñòè"; * |
;* ATASectorCount - êîëè÷åñòâî ñåêòîðîâ; * |
;* ATASectorNumber - íîìåð íà÷àëüíîãî ñåêòîðà; * |
;* ATACylinder - íîìåð íà÷àëüíîãî öèëèíäðà; * |
;* ATAHead - íîìåð íà÷àëüíîé ãîëîâêè; * |
;* ATAAddressMode - ðåæèì àäðåñàöèè (0-CHS, 1-LBA); * |
;* ATACommand - êîä êîìàíäû. * |
;* Ïîñëå óñïåøíîãî âûïîëíåíèÿ ôóíêöèè: * |
;* â ATABasePortAddr - áàçîâûé àäðåñ HDD; * |
;* â DevErrorCode - íîëü. * |
;* Ïðè âîçíèêíîâåíèè îøèáêè â DevErrorCode áóäåò * |
;* âîçâðàùåí êîä îøèáêè. * |
;**************************************************** |
SendCommandToHDD: |
; Ïðîâåðèòü çíà÷åíèå êîäà ðåæèìà |
cmp [ATAAddressMode], 1 |
ja @@Err2 |
; Ïðîâåðèòü êîððåêòíîñòü íîìåðà êàíàëà |
mov BX, [ChannelNumber] |
cmp BX, 1 |
jb @@Err3 |
cmp BX, 2 |
ja @@Err3 |
; Óñòàíîâèòü áàçîâûé àäðåñ |
dec BX |
shl BX, 1 |
movzx ebx, bx |
mov AX, [ebx+StandardATABases] |
mov [ATABasePortAddr], AX |
; Îæèäàíèå ãîòîâíîñòè HDD ê ïðèåìó êîìàíäû |
; Âûáðàòü íóæíûé äèñê |
mov DX, [ATABasePortAddr] |
add DX, 6 ;àäðåñ ðåãèñòðà ãîëîâîê |
mov AL, [DiskNumber] |
cmp AL, 1 ;ïðîâåðèòü íîìåðà äèñêà |
ja @@Err4 |
shl AL, 4 |
or AL, 10100000b |
out DX, AL |
; Îæèäàòü, ïîêà äèñê íå áóäåò ãîòîâ |
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 |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY |
test AL, 80h |
jnz @@WaitHDReady |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà DRQ |
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;ïðîâåðèòü íîìåð ãîëîâêè |
ja @@Err5 |
or AL, [ATAHead] |
or AL, 10100000b |
mov AH, [ATAAddressMode] |
shl AH, 6 |
or AL, AH |
out DX, AL |
; Ïîñëàòü êîìàíäó |
mov AL, [ATACommand] |
inc DX ;ðåãèñòð êîìàíä |
out DX, AL |
sti |
; Ñáðîñèòü ïðèçíàê îøèáêè |
mov [DevErrorCode], 0 |
ret |
; Çàïèñàòü êîä îøèáêè |
@@Err1: |
mov [DevErrorCode], 1 |
ret |
@@Err2: |
mov [DevErrorCode], 2 |
ret |
@@Err3: |
mov [DevErrorCode], 3 |
ret |
@@Err4: |
mov [DevErrorCode], 4 |
ret |
@@Err5: |
mov [DevErrorCode], 5 |
; Çàâåðøåíèå ðàáîòû ïðîãðàììû |
ret |
;************************************************* |
;* ×ÒÅÍÈÅ ÈÄÅÍÒÈÔÈÊÀÒÎÐÀ ÓÑÒÐÎÉÑÒÂÀ ATAPI * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà; * |
;* DiskNumber - íîìåð äèñêà íà êàíàëå. * |
;* Èäåíòèôèêàöèîííûé áëîê äàííûõ ñ÷èòûâàåòñÿ * |
;* â ìàññèâ Sector512. * |
;************************************************* |
ReadCD_ID: |
; Çàäàòü ðåæèì CHS |
mov [ATAAddressMode], 0 |
; Ïîñëàòü êîìàíäó èäåíòèôèêàöèè óñòðîéñòâà |
mov [ATAFeatures], 0 |
mov [ATASectorCount], 0 |
mov [ATASectorNumber], 0 |
mov [ATACylinder], 0 |
mov [ATAHead], 0 |
mov [ATACommand], 0A1h |
call SendCommandToHDD |
cmp [DevErrorCode], 0;ïðîâåðèòü êîä îøèáêè |
jne @@End_1 ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè |
; Îæèäàòü ãîòîâíîñòü äàííûõ HDD |
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 |
jnz @@WaitCompleet_1 |
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR |
jnz @@Error6_1 |
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;÷èñëî ñ÷èòûâàåìûõ ñëîâ |
rep insw |
ret |
; Çàïèñàòü êîä îøèáêè |
@@Error1_1: |
mov [DevErrorCode], 1 |
ret |
@@Error6_1: |
mov [DevErrorCode], 6 |
@@End_1: |
ret |
;************************************************* |
;* ÑÁÐÎÑ ÓÑÒÐÎÉÑÒÂÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); * |
;* DiskNumber - íîìåð äèñêà (0 èëè 1). * |
;************************************************* |
DeviceReset: |
; Ïðîâåðèòü êîððåêòíîñòü íîìåðà êàíàëà |
mov BX, [ChannelNumber] |
cmp BX, 1 |
jb @@Err3_2 |
cmp BX, 2 |
ja @@Err3_2 |
; Óñòàíîâèòü áàçîâûé àäðåñ |
dec BX |
shl BX, 1 |
movzx ebx, bx |
mov DX, [ebx+StandardATABases] |
mov [ATABasePortAddr], DX |
; Âûáðàòü íóæíûé äèñê |
add DX, 6 ;àäðåñ ðåãèñòðà ãîëîâîê |
mov AL, [DiskNumber] |
cmp AL, 1 ;ïðîâåðèòü íîìåðà äèñêà |
ja @@Err4_2 |
shl AL, 4 |
or AL, 10100000b |
out DX, AL |
; Ïîñëàòü êîìàíäó "Ñáðîñ" |
mov AL, 08h |
inc DX ;ðåãèñòð êîìàíä |
out DX, AL |
mov ecx, 0x80000 |
@@WaitHDReady_1: |
; Ïðîâåðèòü âðåìÿ îæèäàíè |
dec ecx |
; cmp ecx,0 |
je @@Err1_2 ;îøèáêà òàéì-àóòà |
; Ïðî÷èòàòü ðåãèñòð ñîñòîÿíè |
in AL, DX |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY |
test AL, 80h |
jnz @@WaitHDReady_1 |
; Ñáðîñèòü ïðèçíàê îøèáêè |
mov [DevErrorCode], 0 |
ret |
; Îáðàáîòêà îøèáîê |
@@Err1_2: |
mov [DevErrorCode], 1 |
ret |
@@Err3_2: |
mov [DevErrorCode], 3 |
ret |
@@Err4_2: |
mov [DevErrorCode], 4 |
; Çàïèñàòü êîä îøèáêè |
ret |
EndFindHDD: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/detect/disks.inc |
---|
1,15 → 1,15 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
include 'dev_fd.inc' |
include 'dev_hdcd.inc' |
include 'getcache.inc' |
include 'sear_par.inc' |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
include 'dev_fd.inc' |
include 'dev_hdcd.inc' |
include 'getcache.inc' |
include 'sear_par.inc' |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/detect/getcache.inc |
---|
1,212 → 1,212 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
pusha |
mov eax,[pg_data.pages_free] |
; 1/32 |
shr eax,5 |
; round off up to 8 pages |
shr eax,3 |
shl eax,3 |
; translate pages in butes *4096 |
shl eax,12 |
; 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 |
mov eax,128*1024 |
@@: |
.continue: |
mov [cache_ide0_size],eax |
mov [cache_ide1_size],eax |
mov [cache_ide2_size],eax |
mov [cache_ide3_size],eax |
xor eax,eax |
mov [hdd_appl_data],1 ;al |
mov [cd_appl_data],1 |
mov ch,[DRIVE_DATA+1] |
mov cl,ch |
and cl,11b |
je .ide2 |
mov esi,cache_ide3 |
call get_cache_ide |
.ide2: |
mov cl,ch |
shr cl,2 |
and cl,11b |
je .ide1 |
mov esi,cache_ide2 |
call get_cache_ide |
.ide1: |
mov cl,ch |
shr cl,4 |
and cl,11b |
je .ide0 |
mov esi,cache_ide1 |
call get_cache_ide |
.ide0: |
mov cl,ch |
shr cl,6 |
and cl,11b |
je @f |
mov esi,cache_ide0 |
call get_cache_ide |
@@: |
xor ecx,ecx |
cmp [NumBiosDisks],ecx |
jz .endbd |
mov esi,BiosDiskCaches |
.loopbd: |
push ecx |
movsx ecx,byte [BiosDisksData+ecx*4+2] |
inc ecx |
jz .getbd |
add ecx,ecx |
movzx eax,byte [DRIVE_DATA+1] |
shl eax,cl |
and ah,3 |
cmp ah,1 |
jz .contbd |
pop ecx |
mov byte [BiosDisksData+ecx*4+2], -1 |
push ecx |
.getbd: |
mov eax,[cache_ide0_size] |
mov [esi+cache_ide0_size-cache_ide0],eax |
mov cl,1 |
call get_cache_ide |
.contbd: |
pop ecx |
add esi,cache_ide1-cache_ide0 |
inc ecx |
cmp ecx,[NumBiosDisks] |
jb .loopbd |
.endbd: |
jmp end_get_cache |
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 |
pop ecx |
mov edx,eax |
mov eax,[esi+cache_ide0_size-cache_ide0] |
shr eax,3 |
mov [esi+cache_ide0_system_data_size-cache_ide0],eax |
mov ebx,eax |
imul eax,7 |
mov [esi+cache_ide0_appl_data_size-cache_ide0],eax |
add ebx,edx |
mov [esi+cache_ide0_data_pointer-cache_ide0],ebx |
cmp cl,10b |
je .cd |
push ecx |
mov eax,[esi+cache_ide0_system_data_size-cache_ide0] |
call calculate_for_hd |
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 |
push edi |
mov edi,[esi+cache_ide0_pointer-cache_ide0] |
call clear_ide_cache |
pop edi |
mov eax,[esi+cache_ide0_appl_data_size-cache_ide0] |
call calculate_for_hd |
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 |
push edi |
mov edi,[esi+cache_ide0_data_pointer-cache_ide0] |
call clear_ide_cache |
pop edi |
pop ecx |
ret |
.cd: |
push ecx |
mov eax,[esi+cache_ide0_system_data_size-cache_ide0] |
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 |
push edi |
mov edi,[esi+cache_ide0_pointer-cache_ide0] |
call clear_ide_cache |
pop edi |
mov eax,[esi+cache_ide0_appl_data_size-cache_ide0] |
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 |
push edi |
mov edi,[esi+cache_ide0_data_pointer-cache_ide0] |
call clear_ide_cache |
pop edi |
pop ecx |
ret |
calculate_for_hd: |
push eax |
mov ebx,eax |
shr eax,9 |
shl eax,3 |
sub ebx,eax |
shr ebx,9 |
mov ecx,ebx |
shl ebx,9 |
pop eax |
sub eax,ebx |
dec ecx |
ret |
calculate_for_cd: |
push eax |
mov ebx,eax |
shr eax,11 |
shl eax,3 |
sub ebx,eax |
shr ebx,11 |
mov ecx,ebx |
shl ebx,11 |
pop eax |
sub eax,ebx |
dec ecx |
ret |
clear_ide_cache: |
push eax |
shl ecx,1 |
xor eax,eax |
cld |
rep stosd |
pop eax |
ret |
end_get_cache: |
; mov [cache_ide0_pointer],HD_CACHE |
; mov [cache_ide0_system_data],HD_CACHE+65536 |
; mov [cache_ide0_system_sad_size],1919 |
popa |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
pusha |
mov eax, [pg_data.pages_free] |
; 1/32 |
shr eax, 5 |
; round off up to 8 pages |
shr eax, 3 |
shl eax, 3 |
; translate pages in butes *4096 |
shl eax, 12 |
; 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 |
mov eax, 128*1024 |
@@: |
.continue: |
mov [cache_ide0_size], eax |
mov [cache_ide1_size], eax |
mov [cache_ide2_size], eax |
mov [cache_ide3_size], eax |
xor eax, eax |
mov [hdd_appl_data], 1;al |
mov [cd_appl_data], 1 |
mov ch, [DRIVE_DATA+1] |
mov cl, ch |
and cl, 11b |
je .ide2 |
mov esi, cache_ide3 |
call get_cache_ide |
.ide2: |
mov cl, ch |
shr cl, 2 |
and cl, 11b |
je .ide1 |
mov esi, cache_ide2 |
call get_cache_ide |
.ide1: |
mov cl, ch |
shr cl, 4 |
and cl, 11b |
je .ide0 |
mov esi, cache_ide1 |
call get_cache_ide |
.ide0: |
mov cl, ch |
shr cl, 6 |
and cl, 11b |
je @f |
mov esi, cache_ide0 |
call get_cache_ide |
@@: |
xor ecx, ecx |
cmp [NumBiosDisks], ecx |
jz .endbd |
mov esi, BiosDiskCaches |
.loopbd: |
push ecx |
movsx ecx, byte [BiosDisksData+ecx*4+2] |
inc ecx |
jz .getbd |
add ecx, ecx |
movzx eax, byte [DRIVE_DATA+1] |
shl eax, cl |
and ah, 3 |
cmp ah, 1 |
jz .contbd |
pop ecx |
mov byte [BiosDisksData+ecx*4+2], -1 |
push ecx |
.getbd: |
mov eax, [cache_ide0_size] |
mov [esi+cache_ide0_size-cache_ide0], eax |
mov cl, 1 |
call get_cache_ide |
.contbd: |
pop ecx |
add esi, cache_ide1-cache_ide0 |
inc ecx |
cmp ecx, [NumBiosDisks] |
jb .loopbd |
.endbd: |
jmp end_get_cache |
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 |
pop ecx |
mov edx, eax |
mov eax, [esi+cache_ide0_size-cache_ide0] |
shr eax, 3 |
mov [esi+cache_ide0_system_data_size-cache_ide0], eax |
mov ebx, eax |
imul eax, 7 |
mov [esi+cache_ide0_appl_data_size-cache_ide0], eax |
add ebx, edx |
mov [esi+cache_ide0_data_pointer-cache_ide0], ebx |
cmp cl, 10b |
je .cd |
push ecx |
mov eax, [esi+cache_ide0_system_data_size-cache_ide0] |
call calculate_for_hd |
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 |
push edi |
mov edi, [esi+cache_ide0_pointer-cache_ide0] |
call clear_ide_cache |
pop edi |
mov eax, [esi+cache_ide0_appl_data_size-cache_ide0] |
call calculate_for_hd |
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 |
push edi |
mov edi, [esi+cache_ide0_data_pointer-cache_ide0] |
call clear_ide_cache |
pop edi |
pop ecx |
ret |
.cd: |
push ecx |
mov eax, [esi+cache_ide0_system_data_size-cache_ide0] |
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 |
push edi |
mov edi, [esi+cache_ide0_pointer-cache_ide0] |
call clear_ide_cache |
pop edi |
mov eax, [esi+cache_ide0_appl_data_size-cache_ide0] |
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 |
push edi |
mov edi, [esi+cache_ide0_data_pointer-cache_ide0] |
call clear_ide_cache |
pop edi |
pop ecx |
ret |
calculate_for_hd: |
push eax |
mov ebx, eax |
shr eax, 9 |
shl eax, 3 |
sub ebx, eax |
shr ebx, 9 |
mov ecx, ebx |
shl ebx, 9 |
pop eax |
sub eax, ebx |
dec ecx |
ret |
calculate_for_cd: |
push eax |
mov ebx, eax |
shr eax, 11 |
shl eax, 3 |
sub ebx, eax |
shr ebx, 11 |
mov ecx, ebx |
shl ebx, 11 |
pop eax |
sub eax, ebx |
dec ecx |
ret |
clear_ide_cache: |
push eax |
shl ecx, 1 |
xor eax, eax |
cld |
rep stosd |
pop eax |
ret |
end_get_cache: |
; mov [cache_ide0_pointer],HD_CACHE |
; mov [cache_ide0_system_data],HD_CACHE+65536 |
; mov [cache_ide0_system_sad_size],1919 |
popa |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/detect/sear_par.inc |
---|
1,157 → 1,157 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;**************************************************** |
; ïîèñê ëîãè÷åñêèõ äèñêîâ íà îáíàðóæåííûõ HDD |
; è çàíåñåíèå äàííûõ â îáëàñòü òàáëèöû |
; àâòîð Mario79 |
;**************************************************** |
mov [transfer_adress],DRIVE_DATA+0xa |
search_partitions_ide0: |
test [DRIVE_DATA+1],byte 0x40 |
jz search_partitions_ide1 |
mov [hdbase],0x1f0 |
mov [hdid],0x0 |
mov [hdpos],1 |
mov [known_part],1 |
search_partitions_ide0_1: |
call set_PARTITION_variables |
test [problem_partition],2 |
jnz search_partitions_ide1 ; not found part |
test [problem_partition],1 |
jnz @F ; not found known_part |
;cmp [problem_partition],0 |
;jne search_partitions_ide1 |
inc byte [DRIVE_DATA+2] |
call partition_data_transfer |
add [transfer_adress],100 |
@@: |
inc [known_part] |
jmp search_partitions_ide0_1 |
search_partitions_ide1: |
test [DRIVE_DATA+1],byte 0x10 |
jz search_partitions_ide2 |
mov [hdbase],0x1f0 |
mov [hdid],0x10 |
mov [hdpos],2 |
mov [known_part],1 |
search_partitions_ide1_1: |
call set_PARTITION_variables |
test [problem_partition],2 |
jnz search_partitions_ide2 |
test [problem_partition],1 |
jnz @F |
;cmp [problem_partition],0 |
;jne search_partitions_ide2 |
inc byte [DRIVE_DATA+3] |
call partition_data_transfer |
add [transfer_adress],100 |
@@: |
inc [known_part] |
jmp search_partitions_ide1_1 |
search_partitions_ide2: |
test [DRIVE_DATA+1],byte 0x4 |
jz search_partitions_ide3 |
mov [hdbase],0x170 |
mov [hdid],0x0 |
mov [hdpos],3 |
mov [known_part],1 |
search_partitions_ide2_1: |
call set_PARTITION_variables |
test [problem_partition],2 |
jnz search_partitions_ide3 |
test [problem_partition],1 |
jnz @F |
;cmp [problem_partition],0 |
;jne search_partitions_ide3 |
inc byte [DRIVE_DATA+4] |
call partition_data_transfer |
add [transfer_adress],100 |
@@: |
inc [known_part] |
jmp search_partitions_ide2_1 |
search_partitions_ide3: |
test [DRIVE_DATA+1],byte 0x1 |
jz end_search_partitions_ide |
mov [hdbase],0x170 |
mov [hdid],0x10 |
mov [hdpos],4 |
mov [known_part],1 |
search_partitions_ide3_1: |
call set_PARTITION_variables |
test [problem_partition],2 |
jnz end_search_partitions_ide |
test [problem_partition],1 |
jnz @F |
;cmp [problem_partition],0 |
;jne end_search_partitions_ide |
inc byte [DRIVE_DATA+5] |
call partition_data_transfer |
add [transfer_adress],100 |
@@: |
inc [known_part] |
jmp search_partitions_ide3_1 |
end_search_partitions_ide: |
mov [hdpos], 80h |
mov ecx, [NumBiosDisks] |
test ecx, ecx |
jz end_search_partitions |
start_search_partitions_bd: |
push ecx |
mov eax, [hdpos] |
and [BiosDiskPartitions+(eax-80h)*4], 0 |
mov [known_part], 1 |
search_partitions_bd: |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;**************************************************** |
; ïîèñê ëîãè÷åñêèõ äèñêîâ íà îáíàðóæåííûõ HDD |
; è çàíåñåíèå äàííûõ â îáëàñòü òàáëèöû |
; àâòîð Mario79 |
;**************************************************** |
mov [transfer_adress], DRIVE_DATA+0xa |
search_partitions_ide0: |
test [DRIVE_DATA+1], byte 0x40 |
jz search_partitions_ide1 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x0 |
mov [hdpos], 1 |
mov [known_part], 1 |
search_partitions_ide0_1: |
call set_PARTITION_variables |
test [problem_partition],2 |
test [problem_partition], 2 |
jnz search_partitions_ide1 ; not found part |
test [problem_partition], 1 |
jnz @F ; not found known_part |
;cmp [problem_partition],0 |
;jne search_partitions_ide1 |
inc byte [DRIVE_DATA+2] |
call partition_data_transfer |
add [transfer_adress], 100 |
@@: |
inc [known_part] |
jmp search_partitions_ide0_1 |
search_partitions_ide1: |
test [DRIVE_DATA+1], byte 0x10 |
jz search_partitions_ide2 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x10 |
mov [hdpos], 2 |
mov [known_part], 1 |
search_partitions_ide1_1: |
call set_PARTITION_variables |
test [problem_partition], 2 |
jnz search_partitions_ide2 |
test [problem_partition], 1 |
jnz @F |
;cmp [problem_partition],0 |
;jne search_partitions_ide2 |
inc byte [DRIVE_DATA+3] |
call partition_data_transfer |
add [transfer_adress], 100 |
@@: |
inc [known_part] |
jmp search_partitions_ide1_1 |
search_partitions_ide2: |
test [DRIVE_DATA+1], byte 0x4 |
jz search_partitions_ide3 |
mov [hdbase], 0x170 |
mov [hdid], 0x0 |
mov [hdpos], 3 |
mov [known_part], 1 |
search_partitions_ide2_1: |
call set_PARTITION_variables |
test [problem_partition], 2 |
jnz search_partitions_ide3 |
test [problem_partition], 1 |
jnz @F |
;cmp [problem_partition],0 |
;jne search_partitions_ide3 |
inc byte [DRIVE_DATA+4] |
call partition_data_transfer |
add [transfer_adress], 100 |
@@: |
inc [known_part] |
jmp search_partitions_ide2_1 |
search_partitions_ide3: |
test [DRIVE_DATA+1], byte 0x1 |
jz end_search_partitions_ide |
mov [hdbase], 0x170 |
mov [hdid], 0x10 |
mov [hdpos], 4 |
mov [known_part], 1 |
search_partitions_ide3_1: |
call set_PARTITION_variables |
test [problem_partition], 2 |
jnz end_search_partitions_ide |
test [problem_partition], 1 |
jnz @F |
;cmp [problem_partition],0 |
;jne end_search_partitions_ide |
inc byte [DRIVE_DATA+5] |
call partition_data_transfer |
add [transfer_adress], 100 |
@@: |
inc [known_part] |
jmp search_partitions_ide3_1 |
end_search_partitions_ide: |
mov [hdpos], 80h |
mov ecx, [NumBiosDisks] |
test ecx, ecx |
jz end_search_partitions |
start_search_partitions_bd: |
push ecx |
mov eax, [hdpos] |
and [BiosDiskPartitions+(eax-80h)*4], 0 |
mov [known_part], 1 |
search_partitions_bd: |
call set_PARTITION_variables |
test [problem_partition], 2 |
jnz end_search_partitions_bd |
test [problem_partition],1 |
jnz @F |
;cmp [problem_partition], 0 |
;jne end_search_partitions_bd |
mov eax, [hdpos] |
inc [BiosDiskPartitions+(eax-80h)*4] |
call partition_data_transfer |
test [problem_partition], 1 |
jnz @F |
;cmp [problem_partition], 0 |
;jne end_search_partitions_bd |
mov eax, [hdpos] |
inc [BiosDiskPartitions+(eax-80h)*4] |
call partition_data_transfer |
add [transfer_adress], 100 |
@@: |
inc [known_part] |
jmp search_partitions_bd |
end_search_partitions_bd: |
pop ecx |
inc [hdpos] |
loop start_search_partitions_bd |
jmp end_search_partitions |
partition_data_transfer: |
mov edi,[transfer_adress] |
mov esi,PARTITION_START ;start of file_system_data |
mov ecx,(file_system_data_size+3)/4 |
rep movsd |
ret |
uglobal |
transfer_adress dd 0 |
endg |
partition_data_transfer_1: |
; cli |
push edi |
mov edi,PARTITION_START |
mov esi,[transfer_adress] |
mov ecx,(file_system_data_size+3)/4 |
rep movsd |
pop edi |
; sti |
ret |
@@: |
inc [known_part] |
jmp search_partitions_bd |
end_search_partitions_bd: |
pop ecx |
inc [hdpos] |
loop start_search_partitions_bd |
jmp end_search_partitions |
partition_data_transfer: |
mov edi, [transfer_adress] |
mov esi, PARTITION_START ;start of file_system_data |
mov ecx, (file_system_data_size+3)/4 |
rep movsd |
ret |
uglobal |
transfer_adress dd 0 |
endg |
partition_data_transfer_1: |
; cli |
push edi |
mov edi, PARTITION_START |
mov esi, [transfer_adress] |
mov ecx, (file_system_data_size+3)/4 |
rep movsd |
pop edi |
; sti |
ret |
end_search_partitions: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/apm.asm |
---|
1,295 → 1,343 |
; 11.09.2009 staper@inbox.ru |
; see kernel\docs\apm.txt |
use32 |
org 0x0 |
db 'MENUET01' |
dd 0x1 |
dd START |
dd I_END |
dd (I_END+100) and not 3 |
dd (I_END+100) and not 3 |
dd 0x0,0x0 |
include 'macros.inc' |
START: |
mcall 40,0x7 |
mcall 49,0x0001,0x0001,0x5308 ;CX = FFFFh APM v1.0 |
; mcall 49,0x0001,0x0001,0x530d |
; mcall 49,0x0001,0x0001,0x530f |
; mcall 49,0x0000,,0x5310 ;bl - number of batteries |
redraw: |
mcall 49,0x0000,,0x530c |
dec cl |
jz still |
mcall 49,0x0001,0x0001,0x5308 |
mcall 49,0x01ff,,0x530c |
test cl,cl |
jz @f |
mcall 49,0x0000,0x0001,0x530d |
mcall 49,0x0000,0x0000,0x5307 |
mcall 49,0x0000,0x0001,0x5308 |
@@: |
mcall 12,1 |
mcall 0,100*65536+235,100*65536+90,0x34ffffff,0x000000,title |
mcall 49,0x0000,,0x5300 |
jnc @f |
mcall 4,10*65536+3,0x80000000,text.4 |
bts [flags],1 |
jmp .end |
@@: cmp al,0 |
jne @f |
mov edx,text.1 |
jmp .0 |
@@: cmp al,1 |
jne @f |
mov edx,text.2 |
jmp .0 |
@@: mov edx,text.3 |
.0: push edx |
mcall 4,169*65536+3,0x80dddddd,text.0 |
pop edx |
add ebx,47*65536 |
mcall |
mcall 49,0x0001,,0x530a |
jc .error |
push si dx cx bx ;time of battery life, b. flag, b. status, AC line status |
;AC line status |
cmp bh,0 |
jne @f |
mov edx,text.01 |
jmp .1 |
@@: cmp bh,1 |
jne @f |
mov edx,text.02 |
jmp .1 |
@@: cmp bh,2 |
jne @f |
mov edx,text.03 |
jmp .1 |
@@: mov edx,text.04 |
.1: push edx |
mcall 4,10*65536+10,0x80000000,text.00 |
pop edx |
mcall ,100*65536+10,;0x80000000 |
;battery status |
pop bx |
cmp bl,0 |
jne @f |
mov edx,text.11 |
jmp .2 |
@@: cmp bl,1 |
jne @f |
mov edx,text.12 |
jmp .2 |
@@: cmp bl,2 |
jne @f |
mov edx,text.13 |
jmp .2 |
@@: cmp bl,3 |
jne @f |
mov edx,text.14 |
jmp .2 |
@@: mov edx,text.04 |
.2: push edx |
mcall 4,10*65536+20,0x80000000,text.10 |
pop edx |
mcall ,100*65536+20, |
;battery life, percentage and minutes/seconds |
mcall ,10*65536+30,,text.20 |
pop cx |
cmp cl,0xff |
jne @f |
mcall ,100*65536+30,0x80000000,text.04 |
pop eax |
jmp .end |
@@: shl ecx,24 |
shr ecx,24 |
mcall 47,0x80030000,,100*65536+30,0x347636 |
.3: mcall 4,115*65536+30,0x80000000,text.15 |
mov dx,[esp] |
shl edx,17 |
shr edx,17 |
mov ecx,edx |
mcall 47,0x80030000,,140*65536+30 |
pop cx |
mov edx,text.21 |
bt cx,15 |
jc @f |
mov edx,text.22 |
@@: mcall 4,160*65536+30,0x80000000 |
pop si |
.error: |
.end: |
;buttons |
mcall 8,148*65536+16,45*65536+15,3,0x00677ab0 |
mcall ,166*65536+16,,4, |
mcall ,184*65536+16,,5, |
mcall ,202*65536+16,,6, |
bt [flags],1 |
jc @f |
mcall ,65*65536+45,,2, |
@@: mcall 4,10*65536+50,0x80564242,text.30 |
mcall 12,2 |
still: |
; mcall 10 |
mcall 23,12000 |
test eax,eax |
jz redraw |
dec al |
jz redraw |
dec al |
jz key |
dec al |
jz button |
jmp still |
key: |
mcall 2 |
jmp still |
button: |
mcall 17 |
cmp ah,1 |
jne @f |
mcall -1 |
@@: cmp ah,2 |
jne @f |
mcall 5,50 |
mcall 49,0x0001,0x0001,0x5307 |
jmp redraw |
@@: cmp ah,4 |
jg @f |
mov edx,0x01f7 ;primary chan. |
call reserv_ports |
jc redraw |
sub bh,3 |
.1: call set_drive |
btc [flags],2 |
jnc .2 |
call device_reset |
jmp .3 |
.2: call standby_hdd |
.3: call free_ports |
jmp redraw |
@@: cmp ah,6 |
jg redraw |
mov edx,0x0177 ;secondary chan. |
call reserv_ports |
jc redraw |
sub bh,5 |
jmp .1 |
set_drive: |
dec dx |
in al,dx |
test bh,bh |
jnz @f |
btr ax,4 |
.1: out dx,al |
inc dx |
ret |
@@: bts ax,4 |
jmp .1 |
standby_hdd: |
; 94h E0h nondata standby immediate |
; 95h E1h nondata idle immediate |
; 96h E2h nondata standby |
; 97h E3h nondata idle |
; 98h E5h nondata check power mode |
; 99h E6h nondata set sleep mode |
xor ecx,ecx |
@@: in al,dx |
dec cx |
jz @f |
bt ax,6 |
jnc @b |
mov al,0x96 |
out dx,al |
mov al,0xe2 |
out dx,al |
@@: |
ret |
reserv_ports: |
mov ecx,edx |
dec ecx |
push ax |
mcall 46,0 |
test al,al |
jnz @f |
pop bx |
clc |
ret |
@@: pop bx |
stc |
ret |
device_reset: |
xor ecx,ecx |
@@: in al,dx |
dec cx |
jz @f |
bt ax,6 |
jnc @b |
mov al,0x10 |
out dx,al |
@@: |
ret |
free_ports: |
mov ecx,edx |
dec ecx |
mcall 46,1 |
ret |
; |
title db '',0 |
flags dw 0 |
text: |
.0: db 'APM v.1.',0 |
.1: db '0',0 |
.2: db '1',0 |
.3: db '2',0 |
.4: db 'APM not supported',0 |
.00: db 'power status:',0 |
.01: db 'off-line',0 |
.02: db 'on-line',0 |
.03: db 'on backup power',0 |
.04: db 'unknown',0 |
.10: db 'battery flag:',0 |
.11: db 'high',0 |
.12: db 'low',0 |
.13: db 'critical',0 |
.14: db 'charging',0 |
.15: db ' % ,',0 |
.20: db 'battery life:',0 |
.21: db 'min',0 |
.22: db 'sec',0 |
.30: db 'STAND-BY: SYSTEM HDD: 0 1 2 3',0 |
I_END: |
; 11.09.2009 staper@inbox.ru |
; see kernel\docs\apm.txt |
use32 |
org 0x0 |
db 'MENUET01' |
dd 0x1 |
dd START |
dd I_END |
dd (I_END+100) and not 3 |
dd (I_END+100) and not 3 |
dd 0x0,0x0 |
include 'macros.inc' |
START: |
mcall 40,0x7 |
mcall 49,0x0001,0x0001,0x5308 ;CX = FFFFh APM v1.0 |
; mcall 49,0x0001,0x0001,0x530d |
; mcall 49,0x0001,0x0001,0x530f |
; mcall 49,0x0000,,0x5310 ;bl - number of batteries |
redraw: |
mcall 49,0x0000,,0x530c |
dec cl |
jz still |
mcall 49,0x0001,0x0001,0x5308 |
mcall 49,0x01ff,,0x530c |
test cl, cl |
jz @f |
mcall 49,0x0000,0x0001,0x530d |
mcall 49,0x0000,0x0000,0x5307 |
mcall 49,0x0000,0x0001,0x5308 |
@@: |
mcall 12,1 |
mcall 0,100*65536+235,100*65536+90,0x34ffffff,0x000000,title |
mcall 49,0x0000,,0x5300 |
jnc @f |
mcall 4,10*65536+3,0x80000000,text.4 |
bts [flags], 1 |
jmp .end |
@@: |
cmp al, 0 |
jne @f |
mov edx, text.1 |
jmp .0 |
@@: |
cmp al, 1 |
jne @f |
mov edx, text.2 |
jmp .0 |
@@: |
mov edx, text.3 |
.0: |
push edx |
mcall 4,169*65536+3,0x80dddddd,text.0 |
pop edx |
add ebx, 47*65536 |
mcall |
mcall 49,0x0001,,0x530a |
jc .error |
push si dx cx bx ;time of battery life, b. flag, b. status, AC line status |
;AC line status |
cmp bh, 0 |
jne @f |
mov edx, text.01 |
jmp .1 |
@@: |
cmp bh, 1 |
jne @f |
mov edx, text.02 |
jmp .1 |
@@: |
cmp bh, 2 |
jne @f |
mov edx, text.03 |
jmp .1 |
@@: |
mov edx, text.04 |
.1: |
push edx |
mcall 4,10*65536+10,0x80000000,text.00 |
pop edx |
mcall ,100*65536+10,;0x80000000 |
;battery status |
pop bx |
cmp bl, 0 |
jne @f |
mov edx, text.11 |
jmp .2 |
@@: |
cmp bl, 1 |
jne @f |
mov edx, text.12 |
jmp .2 |
@@: |
cmp bl, 2 |
jne @f |
mov edx, text.13 |
jmp .2 |
@@: |
cmp bl, 3 |
jne @f |
mov edx, text.14 |
jmp .2 |
@@: |
mov edx, text.04 |
.2: |
push edx |
mcall 4,10*65536+20,0x80000000,text.10 |
pop edx |
mcall ,100*65536+20, |
;battery life, percentage and minutes/seconds |
mcall ,10*65536+30,,text.20 |
pop cx |
cmp cl, 0xff |
jne @f |
mcall ,100*65536+30,0x80000000,text.04 |
pop eax |
jmp .end |
@@: |
shl ecx, 24 |
shr ecx, 24 |
mcall 47,0x80030000,,100*65536+30,0x347636 |
.3: |
mcall 4,115*65536+30,0x80000000,text.15 |
mov dx, [esp] |
shl edx, 17 |
shr edx, 17 |
mov ecx, edx |
mcall 47,0x80030000,,140*65536+30 |
pop cx |
mov edx, text.21 |
bt cx, 15 |
jc @f |
mov edx, text.22 |
@@: |
mcall 4,160*65536+30,0x80000000 |
pop si |
.error: |
.end: |
;buttons |
mcall 8,148*65536+16,45*65536+15,3,0x00677ab0 |
mcall ,166*65536+16,,4, |
mcall ,184*65536+16,,5, |
mcall ,202*65536+16,,6, |
bt [flags], 1 |
jc @f |
mcall ,65*65536+45,,2, |
@@: |
mcall 4,10*65536+50,0x80564242,text.30 |
mcall 12,2 |
still: |
; mcall 10 |
mcall 23,12000 |
test eax, eax |
jz redraw |
dec al |
jz redraw |
dec al |
jz key |
dec al |
jz button |
jmp still |
key: |
mcall 2 |
jmp still |
button: |
mcall 17 |
cmp ah, 1 |
jne @f |
mcall -1 |
@@: |
cmp ah, 2 |
jne @f |
mcall 5,50 |
mcall 49,0x0001,0x0001,0x5307 |
jmp redraw |
@@: |
cmp ah, 4 |
jg @f |
mov edx, 0x01f7 ;primary chan. |
call reserv_ports |
jc redraw |
sub bh, 3 |
.1: |
call set_drive |
btc [flags], 2 |
jnc .2 |
call device_reset |
jmp .3 |
.2: |
call standby_hdd |
.3: |
call free_ports |
jmp redraw |
@@: |
cmp ah, 6 |
jg redraw |
mov edx, 0x0177 ;secondary chan. |
call reserv_ports |
jc redraw |
sub bh, 5 |
jmp .1 |
set_drive: |
dec dx |
in al, dx |
test bh, bh |
jnz @f |
btr ax, 4 |
.1: |
out dx, al |
inc dx |
ret |
@@: |
bts ax, 4 |
jmp .1 |
standby_hdd: |
; 94h E0h nondata standby immediate |
; 95h E1h nondata idle immediate |
; 96h E2h nondata standby |
; 97h E3h nondata idle |
; 98h E5h nondata check power mode |
; 99h E6h nondata set sleep mode |
xor ecx, ecx |
@@: |
in al, dx |
dec cx |
jz @f |
bt ax, 6 |
jnc @b |
mov al, 0x96 |
out dx, al |
mov al, 0xe2 |
out dx, al |
@@: |
ret |
reserv_ports: |
mov ecx, edx |
dec ecx |
push ax |
mcall 46,0 |
test al, al |
jnz @f |
pop bx |
clc |
ret |
@@: |
pop bx |
stc |
ret |
device_reset: |
xor ecx, ecx |
@@: |
in al, dx |
dec cx |
jz @f |
bt ax, 6 |
jnc @b |
mov al, 0x10 |
out dx, al |
@@: |
ret |
free_ports: |
mov ecx, edx |
dec ecx |
mcall 46,1 |
ret |
; |
title db '',0 |
flags dw 0 |
text: |
.0: |
db 'APM v.1.',0 |
.1: |
db '0',0 |
.2: |
db '1',0 |
.3: |
db '2',0 |
.4: |
db 'APM not supported',0 |
.00: |
db 'power status:',0 |
.01: |
db 'off-line',0 |
.02: |
db 'on-line',0 |
.03: |
db 'on backup power',0 |
.04: |
db 'unknown',0 |
.10: |
db 'battery flag:',0 |
.11: |
db 'high',0 |
.12: |
db 'low',0 |
.13: |
db 'critical',0 |
.14: |
db 'charging',0 |
.15: |
db ' % ,',0 |
.20: |
db 'battery life:',0 |
.21: |
db 'min',0 |
.22: |
db 'sec',0 |
.30: |
db 'STAND-BY: SYSTEM HDD: 0 1 2 3',0 |
I_END: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/codec.inc |
---|
1,326 → 1,326 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
AD_LOSEL equ BIT5 |
AD_HPSEL equ BIT10 |
align 4 |
proc detect_codec |
locals |
codec_id dd ? |
endl |
stdcall codec_read, dword 0x7C |
shl eax, 16 |
mov [codec_id], eax |
stdcall codec_read, dword 0x7E |
or eax, [codec_id] |
mov [codec.chip_id], eax |
and eax, 0xFFFFFF00 |
mov edi, codecs |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .unknown |
cmp eax, ebx |
jne .next |
mov eax, [edi+4] |
mov [codec.ac_vendor_ids], eax |
mov esi, eax |
call SysMsgBoardStr |
stdcall detect_chip, [edi+8] |
ret |
.next: |
add edi, 12 |
jmp @B |
.unknown: |
mov [codec.ac_vendor_ids], ac_unknown |
mov [codec.chip_ids], chip_unknown |
mov esi, chip_unknown |
call SysMsgBoardStr |
mov eax, [codec.chip_id] |
call dword2str |
call SysMsgBoardStr |
ret |
endp |
align 4 |
proc detect_chip stdcall, chip_tab:dword |
mov eax, [codec.chip_id] |
and eax, 0xFF |
mov edi, [chip_tab] |
@@: |
mov ebx, [edi] |
cmp ebx, 0xFF |
je .unknown |
cmp eax,ebx |
jne .next |
mov eax, [edi+4] |
mov [codec.chip_ids], eax |
mov esi, eax |
call SysMsgBoardStr |
ret |
.next: |
add edi, 8 |
jmp @b |
.unknown: |
mov [codec.chip_ids], chip_unknown |
mov esi, chip_unknown |
call SysMsgBoardStr |
mov eax, [codec.chip_id] |
call dword2str |
call SysMsgBoardStr |
ret |
endp |
align 4 |
proc setup_codec |
xor eax, eax |
stdcall codec_write, dword CODEC_AUX_VOL |
mov eax, 0x0B0B |
stdcall codec_write, dword CODEC_MASTER_VOL_REG |
mov ax, 0x08 |
stdcall codec_write, dword 0x0C |
mov ax, 0x0808 |
stdcall codec_write, dword CODEC_PCM_OUT_REG |
mov ax, 0x0808 |
stdcall codec_write, dword 0x10 |
mov ax, 0x0808 |
stdcall codec_write, dword 0x12 |
mov ax, 0x0808 |
stdcall codec_write, dword 0x16 |
stdcall codec_read, dword CODEC_EXT_AUDIO_CTRL_REG |
and eax, 0FFFFh - BIT1 ; clear DRA (BIT1) |
or eax, BIT0 ; set VRA (BIT0) |
stdcall codec_write, dword CODEC_EXT_AUDIO_CTRL_REG |
stdcall set_sample_rate, dword 48000 |
.init_error: |
xor eax, eax ; exit with error |
ret |
endp |
; param |
; eax= volume -10000 - 0 for both channels |
align 4 |
set_master_vol: |
cmp eax, 0 |
jl @F |
xor eax, eax |
jmp .set |
@@: |
cmp eax, -9450 |
jg .set |
mov eax, -9450 ;clamp into 6 bits |
.set: |
cdq |
mov ebx, -150 |
idiv ebx |
mov ah, al |
stdcall codec_write, dword CODEC_MASTER_VOL_REG |
xor eax, eax |
ret |
align 4 |
proc get_master_vol stdcall, pvol:dword |
stdcall codec_read, dword CODEC_MASTER_VOL_REG |
and eax, 0x3F |
imul eax, -150 |
mov ebx, [pvol] |
mov [ebx], eax |
xor eax, eax |
ret |
endp |
align 4 |
proc set_sample_rate stdcall, rate:dword |
mov eax, [rate] |
stdcall codec_write, dword CODEC_PCM_FRONT_DACRATE_REG |
ret |
endp |
patch_AD: |
stdcall codec_read, 0x76 |
or ax, BIT5+BIT10 |
stdcall codec_write, 0x76 |
ret |
align 16 |
ac_unknown db 'unknown manufacturer',13,10,0 |
ac_Realtek db 'Realtek Semiconductor',13,10,0 |
ac_Analog db 'Analog Devices',13,10,0 |
ac_CMedia db 'C-Media Electronics',13,10,0 |
ac_Cirrus db 'Cirrus Logic',13,10,0 |
ac_Wolfson db 'Wolfson Microelectronics',13,10,0 |
ac_VIA db 'VIA Technologies',13,10,0 |
ac_SigmaTel db 'SigmaTel',13,10,0 |
ac_eMicro db 'eMicro',13,10,0 |
chip_unknown db 'unknown codec id ', 0 |
CHIP_ANALOG equ 0x41445300 |
CHIP_REALTEK equ 0x414C4700 |
CHIP_CMEDIA equ 0x434D4900 |
CHIP_CIRRUS equ 0x43525900 |
CHIP_WOLFSON equ 0x574D4C00 |
CHIP_VIA equ 0x56494100 |
CHIP_SIGMATEL equ 0x83847600 |
CHIP_EMICRO equ 0x454D4300 |
align 16 |
codecs dd CHIP_ANALOG, ac_Analog, chips_Analog |
dd CHIP_CMEDIA, ac_CMedia, chips_CMedia |
dd CHIP_REALTEK,ac_Realtek, chips_Realtek |
dd CHIP_CIRRUS, ac_Cirrus, chips_Cirrus |
dd CHIP_WOLFSON,ac_Wolfson, chips_Wolfson |
dd CHIP_VIA, ac_VIA, chips_VIA |
dd CHIP_SIGMATEL, ac_SigmaTel, chips_SigmaTel |
dd CHIP_EMICRO, ac_eMicro, chips_eMicro |
dd 0 |
align 16 |
chips_Analog dd 0x03, chip_AD1819 |
dd 0x40, chip_AD1881 |
dd 0x48, chip_AD1881A |
dd 0x60, chip_AD1884 |
dd 0x61, chip_AD1886 |
dd 0x62, chip_AD1887 |
dd 0x63, chip_AD1886A |
dd 0x70, chip_AD1980 |
dd 0x72, chip_AD1981A |
dd 0x74, chip_AD1981B |
dd 0x75, chip_AD1985 |
dd 0xFF |
chips_Realtek: |
dd 0x10, chip_ALC201a |
dd 0x20, chip_ALC650 |
dd 0x21, chip_ALC650D |
dd 0x22, chip_ALC650E |
dd 0x23, chip_ALC650F |
dd 0x60, chip_ALC655 |
dd 0x80, chip_ALC658 |
dd 0x81, chip_ALC658D |
dd 0x90, chip_ALC850 |
dd 0xFF |
chips_CMedia dd 0x41, chip_CM9738 |
dd 0x61, chip_CM9739 |
dd 0x69, chip_CM9780 |
dd 0x78, chip_CM9761 |
dd 0x82, chip_CM9761 |
dd 0x83, chip_CM9761 |
dd 0xFF |
chips_Cirrus dd 0x00, chip_CS4297 |
dd 0x10, chip_CS4297A |
dd 0x20, chip_CS4298 |
dd 0x28, chip_CS4294 |
dd 0x30, chip_CS4299 |
dd 0x34, chip_CS4299D |
dd 0x48, chip_CS4201 |
dd 0x58, chip_CS4205 |
dd 0x60, chip_CS4291 |
dd 0x70, chip_CS4202 |
dd 0xFF |
chips_Wolfson dd 0x00, chip_WM9700 |
dd 0x03, chip_WM9703 |
dd 0x04, chip_WM9704 |
dd 0xFF |
chips_VIA dd 0x61, chip_VIA1612A |
dd 0xFF |
chips_SigmaTel dd 0x58, chip_STAC9758 |
dd 0xFF |
chips_eMicro dd 0x28, chip_EM28028 |
dd 0xFF |
align 16 |
;Analog Devices |
chip_AD1819 db 'AD1819 ',0dh,0ah,00h |
chip_AD1881 db 'AD1881 ',0dh,0ah,00h |
chip_AD1881A db 'AD1881A',0dh,0ah,00h |
chip_AD1884 db 'AD1885 ',0dh,0ah,00h |
chip_AD1885 db 'AD1885 ',0dh,0ah,00h |
chip_AD1886 db 'AD1886 ',0dh,0ah,00h |
chip_AD1886A db 'AD1886A',0dh,0ah,00h |
chip_AD1887 db 'AD1887 ',0dh,0ah,00h |
chip_AD1980 db 'AD1980 ',0dh,0ah,00h |
chip_AD1981A db 'AD1981A',0dh,0ah,00h |
chip_AD1981B db 'AD1981B',0dh,0ah,00h |
chip_AD1985 db 'AD1985 ',0dh,0ah,00h |
;Realtek |
chip_ALC201a db 'ALC201a',0dh,0ah,00h |
chip_ALC650 db 'ALC650 ',0dh,0ah,00h |
chip_ALC650D db 'ALC650D',0dh,0ah,00h |
chip_ALC650E db 'ALC650E',0dh,0ah,00h |
chip_ALC650F db 'ALC650F',0dh,0ah,00h |
chip_ALC655 db 'ALC655 ',0dh,0ah,00h |
chip_ALC658 db 'ALC658 ',0dh,0ah,00h |
chip_ALC658D db 'ALC658D',0dh,0ah,00h |
chip_ALC850 db 'ALC850 ',0dh,0ah,00h |
;CMedia |
chip_CM9738 db 'CMI9738', 0dh,0ah,0 |
chip_CM9739 db 'CMI9739', 0dh,0ah,0 |
chip_CM9780 db 'CMI9780', 0dh,0ah,0 |
chip_CM9761 db 'CMI9761', 0dh,0ah,0 |
;Cirrus |
chip_CS4297 db 'CS4297',13,10,0 |
chip_CS4297A db 'CS4297A',13,10,0 |
chip_CS4298 db 'CS4298',13,10,0 |
chip_CS4294 db 'CS4294',13,10,0 |
chip_CS4299 db 'CS4299',13,10,0 |
chip_CS4299D db 'CS4299D',13,10,0 |
chip_CS4201 db 'CS4201',13,10,0 |
chip_CS4205 db 'CS4205',13,10,0 |
chip_CS4291 db 'CS4291',13,10,0 |
chip_CS4202 db 'CS4202',13,10,0 |
;Wolfson |
chip_WM9700 db 'WM9704',13,10,0 |
chip_WM9703 db 'WM9703/9704',13,10,0 |
chip_WM9704 db 'WM9704 (quad)',13,10,0 |
;VIA |
chip_VIA1612A db 'VIA1612A',13,10,0 |
;SigmaTel |
chip_STAC9758 db 'STAC9758,59',13,10,0 |
;eMicro |
chip_EM28028 db 'EM28028',13,10,0 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
AD_LOSEL equ BIT5 |
AD_HPSEL equ BIT10 |
align 4 |
proc detect_codec |
locals |
codec_id dd ? |
endl |
stdcall codec_read, dword 0x7C |
shl eax, 16 |
mov [codec_id], eax |
stdcall codec_read, dword 0x7E |
or eax, [codec_id] |
mov [codec.chip_id], eax |
and eax, 0xFFFFFF00 |
mov edi, codecs |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .unknown |
cmp eax, ebx |
jne .next |
mov eax, [edi+4] |
mov [codec.ac_vendor_ids], eax |
mov esi, eax |
call SysMsgBoardStr |
stdcall detect_chip, [edi+8] |
ret |
.next: |
add edi, 12 |
jmp @B |
.unknown: |
mov [codec.ac_vendor_ids], ac_unknown |
mov [codec.chip_ids], chip_unknown |
mov esi, chip_unknown |
call SysMsgBoardStr |
mov eax, [codec.chip_id] |
call dword2str |
call SysMsgBoardStr |
ret |
endp |
align 4 |
proc detect_chip stdcall, chip_tab:dword |
mov eax, [codec.chip_id] |
and eax, 0xFF |
mov edi, [chip_tab] |
@@: |
mov ebx, [edi] |
cmp ebx, 0xFF |
je .unknown |
cmp eax, ebx |
jne .next |
mov eax, [edi+4] |
mov [codec.chip_ids], eax |
mov esi, eax |
call SysMsgBoardStr |
ret |
.next: |
add edi, 8 |
jmp @b |
.unknown: |
mov [codec.chip_ids], chip_unknown |
mov esi, chip_unknown |
call SysMsgBoardStr |
mov eax, [codec.chip_id] |
call dword2str |
call SysMsgBoardStr |
ret |
endp |
align 4 |
proc setup_codec |
xor eax, eax |
stdcall codec_write, dword CODEC_AUX_VOL |
mov eax, 0x0B0B |
stdcall codec_write, dword CODEC_MASTER_VOL_REG |
mov ax, 0x08 |
stdcall codec_write, dword 0x0C |
mov ax, 0x0808 |
stdcall codec_write, dword CODEC_PCM_OUT_REG |
mov ax, 0x0808 |
stdcall codec_write, dword 0x10 |
mov ax, 0x0808 |
stdcall codec_write, dword 0x12 |
mov ax, 0x0808 |
stdcall codec_write, dword 0x16 |
stdcall codec_read, dword CODEC_EXT_AUDIO_CTRL_REG |
and eax, 0FFFFh - BIT1 ; clear DRA (BIT1) |
or eax, BIT0 ; set VRA (BIT0) |
stdcall codec_write, dword CODEC_EXT_AUDIO_CTRL_REG |
stdcall set_sample_rate, dword 48000 |
.init_error: |
xor eax, eax ; exit with error |
ret |
endp |
; param |
; eax= volume -10000 - 0 for both channels |
align 4 |
set_master_vol: |
cmp eax, 0 |
jl @F |
xor eax, eax |
jmp .set |
@@: |
cmp eax, -9450 |
jg .set |
mov eax, -9450 ;clamp into 6 bits |
.set: |
cdq |
mov ebx, -150 |
idiv ebx |
mov ah, al |
stdcall codec_write, dword CODEC_MASTER_VOL_REG |
xor eax, eax |
ret |
align 4 |
proc get_master_vol stdcall, pvol:dword |
stdcall codec_read, dword CODEC_MASTER_VOL_REG |
and eax, 0x3F |
imul eax, -150 |
mov ebx, [pvol] |
mov [ebx], eax |
xor eax, eax |
ret |
endp |
align 4 |
proc set_sample_rate stdcall, rate:dword |
mov eax, [rate] |
stdcall codec_write, dword CODEC_PCM_FRONT_DACRATE_REG |
ret |
endp |
patch_AD: |
stdcall codec_read, 0x76 |
or ax, BIT5+BIT10 |
stdcall codec_write, 0x76 |
ret |
align 16 |
ac_unknown db 'unknown manufacturer',13,10,0 |
ac_Realtek db 'Realtek Semiconductor',13,10,0 |
ac_Analog db 'Analog Devices',13,10,0 |
ac_CMedia db 'C-Media Electronics',13,10,0 |
ac_Cirrus db 'Cirrus Logic',13,10,0 |
ac_Wolfson db 'Wolfson Microelectronics',13,10,0 |
ac_VIA db 'VIA Technologies',13,10,0 |
ac_SigmaTel db 'SigmaTel',13,10,0 |
ac_eMicro db 'eMicro',13,10,0 |
chip_unknown db 'unknown codec id ', 0 |
CHIP_ANALOG equ 0x41445300 |
CHIP_REALTEK equ 0x414C4700 |
CHIP_CMEDIA equ 0x434D4900 |
CHIP_CIRRUS equ 0x43525900 |
CHIP_WOLFSON equ 0x574D4C00 |
CHIP_VIA equ 0x56494100 |
CHIP_SIGMATEL equ 0x83847600 |
CHIP_EMICRO equ 0x454D4300 |
align 16 |
codecs dd CHIP_ANALOG, ac_Analog, chips_Analog |
dd CHIP_CMEDIA, ac_CMedia, chips_CMedia |
dd CHIP_REALTEK,ac_Realtek, chips_Realtek |
dd CHIP_CIRRUS, ac_Cirrus, chips_Cirrus |
dd CHIP_WOLFSON,ac_Wolfson, chips_Wolfson |
dd CHIP_VIA, ac_VIA, chips_VIA |
dd CHIP_SIGMATEL, ac_SigmaTel, chips_SigmaTel |
dd CHIP_EMICRO, ac_eMicro, chips_eMicro |
dd 0 |
align 16 |
chips_Analog dd 0x03, chip_AD1819 |
dd 0x40, chip_AD1881 |
dd 0x48, chip_AD1881A |
dd 0x60, chip_AD1884 |
dd 0x61, chip_AD1886 |
dd 0x62, chip_AD1887 |
dd 0x63, chip_AD1886A |
dd 0x70, chip_AD1980 |
dd 0x72, chip_AD1981A |
dd 0x74, chip_AD1981B |
dd 0x75, chip_AD1985 |
dd 0xFF |
chips_Realtek: |
dd 0x10, chip_ALC201a |
dd 0x20, chip_ALC650 |
dd 0x21, chip_ALC650D |
dd 0x22, chip_ALC650E |
dd 0x23, chip_ALC650F |
dd 0x60, chip_ALC655 |
dd 0x80, chip_ALC658 |
dd 0x81, chip_ALC658D |
dd 0x90, chip_ALC850 |
dd 0xFF |
chips_CMedia dd 0x41, chip_CM9738 |
dd 0x61, chip_CM9739 |
dd 0x69, chip_CM9780 |
dd 0x78, chip_CM9761 |
dd 0x82, chip_CM9761 |
dd 0x83, chip_CM9761 |
dd 0xFF |
chips_Cirrus dd 0x00, chip_CS4297 |
dd 0x10, chip_CS4297A |
dd 0x20, chip_CS4298 |
dd 0x28, chip_CS4294 |
dd 0x30, chip_CS4299 |
dd 0x34, chip_CS4299D |
dd 0x48, chip_CS4201 |
dd 0x58, chip_CS4205 |
dd 0x60, chip_CS4291 |
dd 0x70, chip_CS4202 |
dd 0xFF |
chips_Wolfson dd 0x00, chip_WM9700 |
dd 0x03, chip_WM9703 |
dd 0x04, chip_WM9704 |
dd 0xFF |
chips_VIA dd 0x61, chip_VIA1612A |
dd 0xFF |
chips_SigmaTel dd 0x58, chip_STAC9758 |
dd 0xFF |
chips_eMicro dd 0x28, chip_EM28028 |
dd 0xFF |
align 16 |
;Analog Devices |
chip_AD1819 db 'AD1819 ',0dh,0ah,00h |
chip_AD1881 db 'AD1881 ',0dh,0ah,00h |
chip_AD1881A db 'AD1881A',0dh,0ah,00h |
chip_AD1884 db 'AD1885 ',0dh,0ah,00h |
chip_AD1885 db 'AD1885 ',0dh,0ah,00h |
chip_AD1886 db 'AD1886 ',0dh,0ah,00h |
chip_AD1886A db 'AD1886A',0dh,0ah,00h |
chip_AD1887 db 'AD1887 ',0dh,0ah,00h |
chip_AD1980 db 'AD1980 ',0dh,0ah,00h |
chip_AD1981A db 'AD1981A',0dh,0ah,00h |
chip_AD1981B db 'AD1981B',0dh,0ah,00h |
chip_AD1985 db 'AD1985 ',0dh,0ah,00h |
;Realtek |
chip_ALC201a db 'ALC201a',0dh,0ah,00h |
chip_ALC650 db 'ALC650 ',0dh,0ah,00h |
chip_ALC650D db 'ALC650D',0dh,0ah,00h |
chip_ALC650E db 'ALC650E',0dh,0ah,00h |
chip_ALC650F db 'ALC650F',0dh,0ah,00h |
chip_ALC655 db 'ALC655 ',0dh,0ah,00h |
chip_ALC658 db 'ALC658 ',0dh,0ah,00h |
chip_ALC658D db 'ALC658D',0dh,0ah,00h |
chip_ALC850 db 'ALC850 ',0dh,0ah,00h |
;CMedia |
chip_CM9738 db 'CMI9738', 0dh,0ah,0 |
chip_CM9739 db 'CMI9739', 0dh,0ah,0 |
chip_CM9780 db 'CMI9780', 0dh,0ah,0 |
chip_CM9761 db 'CMI9761', 0dh,0ah,0 |
;Cirrus |
chip_CS4297 db 'CS4297',13,10,0 |
chip_CS4297A db 'CS4297A',13,10,0 |
chip_CS4298 db 'CS4298',13,10,0 |
chip_CS4294 db 'CS4294',13,10,0 |
chip_CS4299 db 'CS4299',13,10,0 |
chip_CS4299D db 'CS4299D',13,10,0 |
chip_CS4201 db 'CS4201',13,10,0 |
chip_CS4205 db 'CS4205',13,10,0 |
chip_CS4291 db 'CS4291',13,10,0 |
chip_CS4202 db 'CS4202',13,10,0 |
;Wolfson |
chip_WM9700 db 'WM9704',13,10,0 |
chip_WM9703 db 'WM9703/9704',13,10,0 |
chip_WM9704 db 'WM9704 (quad)',13,10,0 |
;VIA |
chip_VIA1612A db 'VIA1612A',13,10,0 |
;SigmaTel |
chip_STAC9758 db 'STAC9758,59',13,10,0 |
;eMicro |
chip_EM28028 db 'EM28028',13,10,0 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/com_mouse.asm |
---|
1,382 → 1,382 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Includes source code by Kulakov Vladimir Gennadievich. ;; |
;; Modified by Mario79 and Rus. ;; |
;; 02.12.2009 <Lrz> ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;driver sceletone |
format MS COFF |
DEBUG equ 0 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 5 ;debug |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
public START |
public version |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
SRV_GETVERSION equ 0 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
;Detect_COM_Mouse: |
if DEBUG |
mov esi, msgInit |
call Boot_Log |
end if |
mov bx, 0x3f8 |
call MSMouseSearch |
cmp AL,'M' |
jne @f |
;mov [com1_mouse_detected],1 |
;mov [irq_owner+4*4], 1 ; IRQ4 owner is System |
mov dx, bx |
inc dx ; 0x3f8 + 1 |
mov al, 1 |
out dx, al |
stdcall AttachIntHandler, 4, irq4_handler, dword 0 |
if DEBUG |
test eax, eax |
jne .label1 |
mov esi, msg_error_attach_int_handler |
call Boot_Log |
end if |
.label1: |
; mov eax, 0 |
; mov ebx, 0x3F8 |
; mov ecx, 0x3FF |
xor ebx,ebx |
mov ecx, 0x3F8 |
mov edx, 0x3FF |
call ReservePortArea |
if DEBUG |
cmp eax, 1 |
jne .go |
mov esi, msg_error_reserve_ports |
call Boot_Log |
.go: |
mov esi,boot_setmouse_type |
call Boot_Log |
end if |
@@: |
mov bx, 0x2f8 |
call MSMouseSearch |
cmp AL,'M' |
jne .resume |
;mov [com2_mouse_detected],1 |
;mov [irq_owner+3*4], 1 ; IRQ3 owner is System |
stdcall AttachIntHandler, 3, irq3_handler, dword 0 |
; mov eax, 0 |
; mov ebx, 0x2F8 |
; mov ecx, 0x3F8 |
xor ebx,ebx |
mov ecx, 0x2F8 |
mov edx, 0x3F8 |
call ReservePortArea |
if DEBUG |
cmp eax, 1 |
jne @f |
mov esi, msg_error_reserve_ports |
call Boot_Log |
@@: |
mov esi,boot_setmouse_type + 22 |
call Boot_Log |
end if |
.resume: |
stdcall RegService, my_service, service_proc |
if DEBUG |
test eax, eax |
jne @f |
mov esi, msg_exit |
call Boot_Log |
end if |
@@: |
ret |
.fail: |
.exit: |
if DEBUG |
mov esi, msg_exit |
call Boot_Log |
end if |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
align 4 |
MSMouseSearch: |
; ÏÎÈÑÊ ÌÛØÈ ×ÅÐÅÇ COM-ÏÎÐÒÛ |
MouseSearch: |
; Óñòàíàâëèâàåì ñêîðîñòü |
; ïðèåìà/ïåðåäà÷è 1200 áîä |
; in bx COM Port Base Address |
mov DX, bx |
add DX,3 |
in AL,DX |
or AL,80h ;óñòàíîâèòü áèò DLAB |
out DX,AL |
mov DX, bx |
mov AL,60h ;1200 áîä |
out DX,AL |
inc DX |
mov AL,0 |
out DX,AL |
; Óñòàíîâèòü äëèíó ñëîâà 7 áèò, 1 ñòîïîâûé áèò, |
; ÷åòíîñòü íå êîíòðîëèðîâàòü |
mov DX, bx |
add DX,3 |
mov AL,00000010b |
out DX,AL |
; Çàïðåòèòü âñå ïðåðûâàíè |
mov dx, bx |
inc dx |
mov AL,0 |
out DX,AL |
; Ïðîâåðèòü, ÷òî óñòðîéñòâî ïîäêëþ÷åíî è ÿâëÿåòñ |
; ìûøüþ òèïà MSMouse |
; Îòêëþ÷èòü ïèòàíèå ìûøè è ïðåðûâàíè |
mov DX, bx |
add EDX,4 ;ðåãèñòð óïðàâëåíèÿ ìîäåìîì |
mov AL,0 ;ñáðîñèòü DTR, RTS è OUT2 |
out DX,AL |
; Îæèäàòü 5 "òèêîâ" (0,2 ñ) |
mov ecx, 0xFFFF |
loop $ |
; Âêëþ÷èòü ïèòàíèå ìûøè |
mov al, 1 |
out dx, al |
mov ecx, 0xFFFF |
loop $ |
; Î÷èñòèòü ðåãèñòð äàííûõ |
mov dx, bx |
in AL,DX |
add edx, 4 |
mov AL, 1011b ;óñòàíîâèòü DTR è RTS è OUT2 |
out DX,AL |
mov ecx, 0x1FFFF |
; Öèêë îïðîñà ïîðòà |
WaitData: |
; Îæèäàòü åùå 10 "òèêîâ" |
dec ecx |
; cmp ecx,0 |
jz NoMouse |
; Ïðîâåðèòü íàëè÷èå èäåíòèôèêàöèîííîãî áàéòà |
mov DX, bx |
add DX,5 |
in AL,DX |
test AL,1 ;Äàííûå ãîòîâû? |
jz WaitData |
; Ââåñòè äàííûå |
mov DX, bx |
in AL,DX |
NoMouse: |
ret |
align 4 |
irq3_handler: |
mov dx, 0x2f8 |
mov esi, com2_mouse |
jmp irq_handler |
align 4 |
irq4_handler: |
mov dx, 0x3f8 |
mov esi, com1_mouse |
irq_handler: |
; in: esi -> COM_MOUSE_DATA struc, dx = base port (xF8h) |
add edx, 5 ; xFDh |
in al, dx |
test al, 1 ; Äàííûå ãîòîâû? |
jz .Error |
; Ââåñòè äàííûå |
sub edx, 5 |
in al, dx |
; Ñáðîñèòü ñòàðøèé íåçíà÷àùèé áèò |
and al, 01111111b |
; Îïðåäåëèòü ïîðÿäêîâûé íîìåð ïðèíèìàåìîãî áàéòà |
cmp [esi+COM_MOUSE_DATA.MouseByteNumber], 2 |
ja .Error |
jz .ThirdByte |
jp .SecondByte |
; Ñîõðàíèòü ïåðâûé áàéò äàííûõ |
.FirstByte: |
test al, 1000000b ; Ïåðâûé áàéò ïîñûëêè? |
jz .Error |
mov [esi+COM_MOUSE_DATA.FirstByte], al |
inc [esi+COM_MOUSE_DATA.MouseByteNumber] |
jmp .EndMouseInterrupt |
; Ñîõðàíèòü âòîðîé áàéò äàííûõ |
.SecondByte: |
test al, 1000000b |
jnz .Error |
mov [esi+COM_MOUSE_DATA.SecondByte], al |
inc [esi+COM_MOUSE_DATA.MouseByteNumber] |
jmp .EndMouseInterrupt |
; Ñîõðàíèòü òðåòèé áàéò äàííûõ |
.ThirdByte: |
test al, 1000000b |
jnz .Error |
mov [esi+COM_MOUSE_DATA.ThirdByte], al |
mov [esi+COM_MOUSE_DATA.MouseByteNumber], 0 |
; (Ïàêåò äàííûõ îò ìûøè ïðèíÿò ïîëíîñòüþ). |
; Çàïèñàòü íîâîå çíà÷åíèå ñîñòîÿíèÿ êíîïîê ìûøè |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
mov ah, al |
shr al, 3 |
and al, 2 |
shr ah, 5 |
and ah, 1 |
add al, ah |
movzx eax, al |
mov [BTN_DOWN], eax |
; Ïðèáàâèòü ïåðåìåùåíèå ïî X ê êîîðäèíàòå X |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
shl al, 6 |
or al, [esi+COM_MOUSE_DATA.SecondByte] |
cbw |
movzx eax, ax |
mov [MOUSE_X], eax |
; Ïðèáàâèòü ïåðåìåùåíèå ïî Y ê êîîðäèíàòå Y |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
and al, 00001100b |
shl al, 4 |
or al, [esi+COM_MOUSE_DATA.ThirdByte] |
cbw |
movzx eax, ax |
neg eax |
mov [MOUSE_Y], eax |
stdcall SetMouseData, [BTN_DOWN], [MOUSE_X], [MOUSE_Y], 0, 0 |
jmp .EndMouseInterrupt |
.Error: |
; Ïðîèçîøåë ñáîé â ïîðÿäêå ïåðåäà÷è èíôîðìàöèè îò |
; ìûøè, îáíóëèòü ñ÷åò÷èê áàéòîâ ïàêåòà äàííûõ |
mov [esi+COM_MOUSE_DATA.MouseByteNumber],0 |
.EndMouseInterrupt: |
mov al, 1 |
ret |
;all initialized data place here |
align 4 |
struc COM_MOUSE_DATA { |
; Íîìåð ïðèíèìàåìîãî îò ìûøè áàéòà |
.MouseByteNumber db ? |
; Òðåõáàéòîâàÿ ñòðóêòóðà äàííûõ, ïåðåäàâàåìàÿ ìûøüþ |
.FirstByte db ? |
.SecondByte db ? |
.ThirdByte db ? |
;.timer_ticks_com dd ? |
} |
virtual at 0 |
COM_MOUSE_DATA COM_MOUSE_DATA |
end virtual |
com1_mouse COM_MOUSE_DATA |
com2_mouse COM_MOUSE_DATA |
MOUSE_X dd 0 |
MOUSE_Y dd 0 |
BTN_DOWN dd 0 |
COMPortBaseAddr dw 3F8h |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'COM_Mouse',0 ;max 16 chars include zero |
if DEBUG |
msgInit db 'Preved bugoga!',13,10,0 |
boot_setmouse_type db 'Detected - COM1 mouse',13,10,0 |
db 'Detected - COM2 mouse',13,10,0 |
msg_error_reserve_ports db 'Error reserving ports!',13,10,0 |
msg_error_attach_int_handler db 'Error attach interrupt handler!',13,10,0 |
msg_exit db 'Exit!',13,10,0 |
end if |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Includes source code by Kulakov Vladimir Gennadievich. ;; |
;; Modified by Mario79 and Rus. ;; |
;; 02.12.2009 <Lrz> ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;driver sceletone |
format MS COFF |
DEBUG equ 0 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 5 ;debug |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
public START |
public version |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
SRV_GETVERSION equ 0 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
;Detect_COM_Mouse: |
if DEBUG |
mov esi, msgInit |
call Boot_Log |
end if |
mov bx, 0x3f8 |
call MSMouseSearch |
cmp AL, 'M' |
jne @f |
;mov [com1_mouse_detected],1 |
;mov [irq_owner+4*4], 1 ; IRQ4 owner is System |
mov dx, bx |
inc dx ; 0x3f8 + 1 |
mov al, 1 |
out dx, al |
stdcall AttachIntHandler, 4, irq4_handler, dword 0 |
if DEBUG |
test eax, eax |
jne .label1 |
mov esi, msg_error_attach_int_handler |
call Boot_Log |
end if |
.label1: |
; mov eax, 0 |
; mov ebx, 0x3F8 |
; mov ecx, 0x3FF |
xor ebx, ebx |
mov ecx, 0x3F8 |
mov edx, 0x3FF |
call ReservePortArea |
if DEBUG |
cmp eax, 1 |
jne .go |
mov esi, msg_error_reserve_ports |
call Boot_Log |
.go: |
mov esi, boot_setmouse_type |
call Boot_Log |
end if |
@@: |
mov bx, 0x2f8 |
call MSMouseSearch |
cmp AL, 'M' |
jne .resume |
;mov [com2_mouse_detected],1 |
;mov [irq_owner+3*4], 1 ; IRQ3 owner is System |
stdcall AttachIntHandler, 3, irq3_handler, dword 0 |
; mov eax, 0 |
; mov ebx, 0x2F8 |
; mov ecx, 0x3F8 |
xor ebx, ebx |
mov ecx, 0x2F8 |
mov edx, 0x3F8 |
call ReservePortArea |
if DEBUG |
cmp eax, 1 |
jne @f |
mov esi, msg_error_reserve_ports |
call Boot_Log |
@@: |
mov esi, boot_setmouse_type + 22 |
call Boot_Log |
end if |
.resume: |
stdcall RegService, my_service, service_proc |
if DEBUG |
test eax, eax |
jne @f |
mov esi, msg_exit |
call Boot_Log |
end if |
@@: |
ret |
.fail: |
.exit: |
if DEBUG |
mov esi, msg_exit |
call Boot_Log |
end if |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
align 4 |
MSMouseSearch: |
; ÏÎÈÑÊ ÌÛØÈ ×ÅÐÅÇ COM-ÏÎÐÒÛ |
MouseSearch: |
; Óñòàíàâëèâàåì ñêîðîñòü |
; ïðèåìà/ïåðåäà÷è 1200 áîä |
; in bx COM Port Base Address |
mov DX, bx |
add DX, 3 |
in AL, DX |
or AL, 80h ;óñòàíîâèòü áèò DLAB |
out DX, AL |
mov DX, bx |
mov AL, 60h ;1200 áîä |
out DX, AL |
inc DX |
mov AL, 0 |
out DX, AL |
; Óñòàíîâèòü äëèíó ñëîâà 7 áèò, 1 ñòîïîâûé áèò, |
; ÷åòíîñòü íå êîíòðîëèðîâàòü |
mov DX, bx |
add DX, 3 |
mov AL, 00000010b |
out DX, AL |
; Çàïðåòèòü âñå ïðåðûâàíè |
mov dx, bx |
inc dx |
mov AL, 0 |
out DX, AL |
; Ïðîâåðèòü, ÷òî óñòðîéñòâî ïîäêëþ÷åíî è ÿâëÿåòñ |
; ìûøüþ òèïà MSMouse |
; Îòêëþ÷èòü ïèòàíèå ìûøè è ïðåðûâàíè |
mov DX, bx |
add EDX, 4 ;ðåãèñòð óïðàâëåíèÿ ìîäåìîì |
mov AL, 0 ;ñáðîñèòü DTR, RTS è OUT2 |
out DX, AL |
; Îæèäàòü 5 "òèêîâ" (0,2 ñ) |
mov ecx, 0xFFFF |
loop $ |
; Âêëþ÷èòü ïèòàíèå ìûøè |
mov al, 1 |
out dx, al |
mov ecx, 0xFFFF |
loop $ |
; Î÷èñòèòü ðåãèñòð äàííûõ |
mov dx, bx |
in AL, DX |
add edx, 4 |
mov AL, 1011b ;óñòàíîâèòü DTR è RTS è OUT2 |
out DX, AL |
mov ecx, 0x1FFFF |
; Öèêë îïðîñà ïîðòà |
WaitData: |
; Îæèäàòü åùå 10 "òèêîâ" |
dec ecx |
; cmp ecx,0 |
jz NoMouse |
; Ïðîâåðèòü íàëè÷èå èäåíòèôèêàöèîííîãî áàéòà |
mov DX, bx |
add DX, 5 |
in AL, DX |
test AL, 1 ;Äàííûå ãîòîâû? |
jz WaitData |
; Ââåñòè äàííûå |
mov DX, bx |
in AL, DX |
NoMouse: |
ret |
align 4 |
irq3_handler: |
mov dx, 0x2f8 |
mov esi, com2_mouse |
jmp irq_handler |
align 4 |
irq4_handler: |
mov dx, 0x3f8 |
mov esi, com1_mouse |
irq_handler: |
; in: esi -> COM_MOUSE_DATA struc, dx = base port (xF8h) |
add edx, 5 ; xFDh |
in al, dx |
test al, 1 ; Äàííûå ãîòîâû? |
jz .Error |
; Ââåñòè äàííûå |
sub edx, 5 |
in al, dx |
; Ñáðîñèòü ñòàðøèé íåçíà÷àùèé áèò |
and al, 01111111b |
; Îïðåäåëèòü ïîðÿäêîâûé íîìåð ïðèíèìàåìîãî áàéòà |
cmp [esi+COM_MOUSE_DATA.MouseByteNumber], 2 |
ja .Error |
jz .ThirdByte |
jp .SecondByte |
; Ñîõðàíèòü ïåðâûé áàéò äàííûõ |
.FirstByte: |
test al, 1000000b ; Ïåðâûé áàéò ïîñûëêè? |
jz .Error |
mov [esi+COM_MOUSE_DATA.FirstByte], al |
inc [esi+COM_MOUSE_DATA.MouseByteNumber] |
jmp .EndMouseInterrupt |
; Ñîõðàíèòü âòîðîé áàéò äàííûõ |
.SecondByte: |
test al, 1000000b |
jnz .Error |
mov [esi+COM_MOUSE_DATA.SecondByte], al |
inc [esi+COM_MOUSE_DATA.MouseByteNumber] |
jmp .EndMouseInterrupt |
; Ñîõðàíèòü òðåòèé áàéò äàííûõ |
.ThirdByte: |
test al, 1000000b |
jnz .Error |
mov [esi+COM_MOUSE_DATA.ThirdByte], al |
mov [esi+COM_MOUSE_DATA.MouseByteNumber], 0 |
; (Ïàêåò äàííûõ îò ìûøè ïðèíÿò ïîëíîñòüþ). |
; Çàïèñàòü íîâîå çíà÷åíèå ñîñòîÿíèÿ êíîïîê ìûøè |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
mov ah, al |
shr al, 3 |
and al, 2 |
shr ah, 5 |
and ah, 1 |
add al, ah |
movzx eax, al |
mov [BTN_DOWN], eax |
; Ïðèáàâèòü ïåðåìåùåíèå ïî X ê êîîðäèíàòå X |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
shl al, 6 |
or al, [esi+COM_MOUSE_DATA.SecondByte] |
cbw |
movzx eax, ax |
mov [MOUSE_X], eax |
; Ïðèáàâèòü ïåðåìåùåíèå ïî Y ê êîîðäèíàòå Y |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
and al, 00001100b |
shl al, 4 |
or al, [esi+COM_MOUSE_DATA.ThirdByte] |
cbw |
movzx eax, ax |
neg eax |
mov [MOUSE_Y], eax |
stdcall SetMouseData, [BTN_DOWN], [MOUSE_X], [MOUSE_Y], 0, 0 |
jmp .EndMouseInterrupt |
.Error: |
; Ïðîèçîøåë ñáîé â ïîðÿäêå ïåðåäà÷è èíôîðìàöèè îò |
; ìûøè, îáíóëèòü ñ÷åò÷èê áàéòîâ ïàêåòà äàííûõ |
mov [esi+COM_MOUSE_DATA.MouseByteNumber], 0 |
.EndMouseInterrupt: |
mov al, 1 |
ret |
;all initialized data place here |
align 4 |
struc COM_MOUSE_DATA { |
; Íîìåð ïðèíèìàåìîãî îò ìûøè áàéòà |
.MouseByteNumber db ? |
; Òðåõáàéòîâàÿ ñòðóêòóðà äàííûõ, ïåðåäàâàåìàÿ ìûøüþ |
.FirstByte db ? |
.SecondByte db ? |
.ThirdByte db ? |
;.timer_ticks_com dd ? |
} |
virtual at 0 |
COM_MOUSE_DATA COM_MOUSE_DATA |
end virtual |
com1_mouse COM_MOUSE_DATA |
com2_mouse COM_MOUSE_DATA |
MOUSE_X dd 0 |
MOUSE_Y dd 0 |
BTN_DOWN dd 0 |
COMPortBaseAddr dw 3F8h |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'COM_Mouse',0 ;max 16 chars include zero |
if DEBUG |
msgInit db 'Preved bugoga!',13,10,0 |
boot_setmouse_type db 'Detected - COM1 mouse',13,10,0 |
db 'Detected - COM2 mouse',13,10,0 |
msg_error_reserve_ports db 'Error reserving ports!',13,10,0 |
msg_error_attach_int_handler db 'Error attach interrupt handler!',13,10,0 |
msg_exit db 'Exit!',13,10,0 |
end if |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/emu10k1x.asm |
---|
7,28 → 7,28 |
format MS COFF |
DEBUG equ 1 |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0x01000100 |
API_VERSION equ 0x01000100 |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
IRQ_REMAP equ 0 |
IRQ_LINE equ 0 |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
IRQ_REMAP equ 0 |
IRQ_LINE equ 0 |
;irq 0,1,2,8,12,13 ¥¤®áâã¯ë |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
if USE_COM_IRQ |
ATTCH_IRQ equ 0000111010111000b |
ATTCH_IRQ equ 0000111010111000b |
end if |
CPU_FREQ equ 2600d |
CPU_FREQ equ 2600d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
35,15 → 35,15 |
BIT5 EQU 0x00000020 |
BIT10 EQU 0x00000400 |
VID_Creative equ 0x1102 |
VID_Creative equ 0x1102 |
CTRL_CT0200 equ 0x0006 ; Dell OEM version (EMU10K1X) |
CTRL_CT0200 equ 0x0006 ; Dell OEM version (EMU10K1X) |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate |
57,138 → 57,138 |
;; PCI function 0 registers, address = <val> + PCIBASE0 ;; |
;;**********************************************************************************************;; |
PTR equ 0x00 ;; Indexed register set pointer register ;; |
;; NOTE: The CHANNELNUM and ADDRESS words can ;; |
;; be modified independently of each other. ;; |
PTR equ 0x00 ;; Indexed register set pointer register ;; |
;; NOTE: The CHANNELNUM and ADDRESS words can ;; |
;; be modified independently of each other. ;; |
DATA equ 0x04 ;; Indexed register set data register ;; |
DATA equ 0x04 ;; Indexed register set data register ;; |
IPR equ 0x08 ;; Global interrupt pending register ;; |
;; Clear pending interrupts by writing a 1 to ;; |
;; the relevant bits and zero to the other bits ;; |
IPR_MIDITRANSBUFEMPTY equ 0x00000001 ;; MIDI UART transmit buffer empty ;; |
IPR_MIDIRECVBUFEMPTY equ 0x00000002 ;; MIDI UART receive buffer empty ;; |
IPR_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;; |
IPR_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;; |
IPR_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;; |
IPR_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;; |
IPR equ 0x08 ;; Global interrupt pending register ;; |
;; Clear pending interrupts by writing a 1 to ;; |
;; the relevant bits and zero to the other bits ;; |
IPR_MIDITRANSBUFEMPTY equ 0x00000001 ;; MIDI UART transmit buffer empty ;; |
IPR_MIDIRECVBUFEMPTY equ 0x00000002 ;; MIDI UART receive buffer empty ;; |
IPR_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;; |
IPR_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;; |
IPR_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;; |
IPR_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;; |
INTE equ 0x0c ;; Interrupt enable register ;; |
INTE_MIDITXENABLE equ 0x00000001 ;; Enable MIDI transmit-buffer-empty interrupts ;; |
INTE_MIDIRXENABLE equ 0x00000002 ;; Enable MIDI receive-buffer-empty interrupts ;; |
INTE_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;; |
INTE_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;; |
INTE_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;; |
INTE_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;; |
INTE equ 0x0c ;; Interrupt enable register ;; |
INTE_MIDITXENABLE equ 0x00000001 ;; Enable MIDI transmit-buffer-empty interrupts ;; |
INTE_MIDIRXENABLE equ 0x00000002 ;; Enable MIDI receive-buffer-empty interrupts ;; |
INTE_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;; |
INTE_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;; |
INTE_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;; |
INTE_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;; |
HCFG equ 0x14 ;; Hardware config register ;; |
HCFG equ 0x14 ;; Hardware config register ;; |
HCFG_LOCKSOUNDCACHE equ 0x00000008 ;; 1 = Cancel bustmaster accesses to soundcache ;; |
;; NOTE: This should generally never be used. ;; |
HCFG_AUDIOENABLE equ 0x00000001 ;; 0 = CODECs transmit zero-valued samples ;; |
;; Should be set to 1 when the EMU10K1 is ;; |
;; completely initialized. ;; |
GPIO equ 0x18 ;; Defaults: 00001080-Analog, 00001000-SPDIF. ;; |
HCFG_LOCKSOUNDCACHE equ 0x00000008 ;; 1 = Cancel bustmaster accesses to soundcache ;; |
;; NOTE: This should generally never be used. ;; |
HCFG_AUDIOENABLE equ 0x00000001 ;; 0 = CODECs transmit zero-valued samples ;; |
;; Should be set to 1 when the EMU10K1 is ;; |
;; completely initialized. ;; |
GPIO equ 0x18 ;; Defaults: 00001080-Analog, 00001000-SPDIF. ;; |
AC97DATA equ 0x1c ;; AC97 register set data register (16 bit) ;; |
AC97DATA equ 0x1c ;; AC97 register set data register (16 bit) ;; |
AC97ADDRESS equ 0x1e ;; AC97 register set address register (8 bit) ;; |
AC97ADDRESS equ 0x1e ;; AC97 register set address register (8 bit) ;; |
;;******************************************************************************************************;; |
;; Emu10k1x pointer-offset register set, accessed through the PTR and DATA registers ;; |
;;******************************************************************************************************;; |
PLAYBACK_LIST_ADDR equ 0x00 ;; Base DMA address of a list of pointers to each period/size ;; |
;; One list entry: 4 bytes for DMA address, |
;; 4 bytes for period_size << 16. |
;; One list entry is 8 bytes long. |
;; One list entry for each period in the buffer. |
;; |
PLAYBACK_LIST_SIZE equ 0x01 ;; Size of list in bytes << 19. E.g. 8 periods -> 0x00380000 ;; |
PLAYBACK_LIST_PTR equ 0x02 ;; Pointer to the current period being played ;; |
PLAYBACK_DMA_ADDR equ 0x04 ;; Playback DMA addresss ;; |
PLAYBACK_PERIOD_SIZE equ 0x05 ;; Playback period size ;; |
PLAYBACK_POINTER equ 0x06 ;; Playback period pointer. Sample currently in DAC ;; |
PLAYBACK_UNKNOWN1 equ 0x07 |
PLAYBACK_UNKNOWN2 equ 0x08 |
PLAYBACK_LIST_ADDR equ 0x00 ;; Base DMA address of a list of pointers to each period/size ;; |
;; One list entry: 4 bytes for DMA address, |
;; 4 bytes for period_size << 16. |
;; One list entry is 8 bytes long. |
;; One list entry for each period in the buffer. |
;; |
PLAYBACK_LIST_SIZE equ 0x01 ;; Size of list in bytes << 19. E.g. 8 periods -> 0x00380000 ;; |
PLAYBACK_LIST_PTR equ 0x02 ;; Pointer to the current period being played ;; |
PLAYBACK_DMA_ADDR equ 0x04 ;; Playback DMA addresss ;; |
PLAYBACK_PERIOD_SIZE equ 0x05 ;; Playback period size ;; |
PLAYBACK_POINTER equ 0x06 ;; Playback period pointer. Sample currently in DAC ;; |
PLAYBACK_UNKNOWN1 equ 0x07 |
PLAYBACK_UNKNOWN2 equ 0x08 |
;; Only one capture channel supported ;; |
CAPTURE_DMA_ADDR equ 0x10 ;; Capture DMA address ;; |
CAPTURE_BUFFER_SIZE equ 0x11 ;; Capture buffer size ;; |
CAPTURE_POINTER equ 0x12 ;; Capture buffer pointer. Sample currently in ADC ;; |
CAPTURE_UNKNOWN equ 0x13 |
CAPTURE_DMA_ADDR equ 0x10 ;; Capture DMA address ;; |
CAPTURE_BUFFER_SIZE equ 0x11 ;; Capture buffer size ;; |
CAPTURE_POINTER equ 0x12 ;; Capture buffer pointer. Sample currently in ADC ;; |
CAPTURE_UNKNOWN equ 0x13 |
;; From 0x20 - 0x3f, last samples played on each channel ;; |
TRIGGER_CHANNEL equ 0x40 ;; Trigger channel playback ;; |
TRIGGER_CHANNEL_0 equ 0x00000001 ;; Trigger channel 0 ;; |
TRIGGER_CHANNEL_1 equ 0x00000002 ;; Trigger channel 1 ;; |
TRIGGER_CHANNEL_2 equ 0x00000004 ;; Trigger channel 2 ;; |
TRIGGER_CAPTURE equ 0x00000100 ;; Trigger capture channel ;; |
TRIGGER_CHANNEL equ 0x40 ;; Trigger channel playback ;; |
TRIGGER_CHANNEL_0 equ 0x00000001 ;; Trigger channel 0 ;; |
TRIGGER_CHANNEL_1 equ 0x00000002 ;; Trigger channel 1 ;; |
TRIGGER_CHANNEL_2 equ 0x00000004 ;; Trigger channel 2 ;; |
TRIGGER_CAPTURE equ 0x00000100 ;; Trigger capture channel ;; |
ROUTING equ 0x41 ;; Setup sound routing ? ;; |
ROUTING_FRONT_LEFT equ 0x00000001 |
ROUTING_FRONT_RIGHT equ 0x00000002 |
ROUTING_REAR_LEFT equ 0x00000004 |
ROUTING_REAR_RIGHT equ 0x00000008 |
ROUTING_CENTER_LFE equ 0x00010000 |
ROUTING equ 0x41 ;; Setup sound routing ? ;; |
ROUTING_FRONT_LEFT equ 0x00000001 |
ROUTING_FRONT_RIGHT equ 0x00000002 |
ROUTING_REAR_LEFT equ 0x00000004 |
ROUTING_REAR_RIGHT equ 0x00000008 |
ROUTING_CENTER_LFE equ 0x00010000 |
SPCS0 equ 0x42 ;; SPDIF output Channel Status 0 register ;; |
SPCS1 equ 0x43 ;; SPDIF output Channel Status 1 register ;; |
SPCS2 equ 0x44 ;; SPDIF output Channel Status 2 register ;; |
SPCS0 equ 0x42 ;; SPDIF output Channel Status 0 register ;; |
SPCS1 equ 0x43 ;; SPDIF output Channel Status 1 register ;; |
SPCS2 equ 0x44 ;; SPDIF output Channel Status 2 register ;; |
SPCS_CLKACCYMASK equ 0x30000000 ;; Clock accuracy ;; |
SPCS_CLKACCY_1000PPM equ 0x00000000 ;; 1000 parts per million ;; |
SPCS_CLKACCY_50PPM equ 0x10000000 ;; 50 parts per million ;; |
SPCS_CLKACCY_VARIABLE equ 0x20000000 ;; Variable accuracy ;; |
SPCS_SAMPLERATEMASK equ 0x0f000000 ;; Sample rate ;; |
SPCS_SAMPLERATE_44 equ 0x00000000 ;; 44.1kHz sample rate ;; |
SPCS_SAMPLERATE_48 equ 0x02000000 ;; 48kHz sample rate ;; |
SPCS_SAMPLERATE_32 equ 0x03000000 ;; 32kHz sample rate ;; |
SPCS_CHANNELNUMMASK equ 0x00f00000 ;; Channel number ;; |
SPCS_CHANNELNUM_UNSPEC equ 0x00000000 ;; Unspecified channel number ;; |
SPCS_CHANNELNUM_LEFT equ 0x00100000 ;; Left channel ;; |
SPCS_CHANNELNUM_RIGHT equ 0x00200000 ;; Right channel ;; |
SPCS_SOURCENUMMASK equ 0x000f0000 ;; Source number ;; |
SPCS_SOURCENUM_UNSPEC equ 0x00000000 ;; Unspecified source number ;; |
SPCS_GENERATIONSTATUS equ 0x00008000 ;; Originality flag (see IEC-958 spec) ;; |
SPCS_CATEGORYCODEMASK equ 0x00007f00 ;; Category code (see IEC-958 spec) ;; |
SPCS_MODEMASK equ 0x000000c0 ;; Mode (see IEC-958 spec) ;; |
SPCS_EMPHASISMASK equ 0x00000038 ;; Emphasis ;; |
SPCS_EMPHASIS_NONE equ 0x00000000 ;; No emphasis ;; |
SPCS_EMPHASIS_50_15 equ 0x00000008 ;; 50/15 usec 2 channel ;; |
SPCS_COPYRIGHT equ 0x00000004 ;; Copyright asserted flag -- do not modify ;; |
SPCS_NOTAUDIODATA equ 0x00000002 ;; 0 = Digital audio, 1 = not audio ;; |
SPCS_PROFESSIONAL equ 0x00000001 ;; 0 = Consumer (IEC-958), 1 = pro (AES3-1992) ;; |
SPCS_CLKACCYMASK equ 0x30000000 ;; Clock accuracy ;; |
SPCS_CLKACCY_1000PPM equ 0x00000000 ;; 1000 parts per million ;; |
SPCS_CLKACCY_50PPM equ 0x10000000 ;; 50 parts per million ;; |
SPCS_CLKACCY_VARIABLE equ 0x20000000 ;; Variable accuracy ;; |
SPCS_SAMPLERATEMASK equ 0x0f000000 ;; Sample rate ;; |
SPCS_SAMPLERATE_44 equ 0x00000000 ;; 44.1kHz sample rate ;; |
SPCS_SAMPLERATE_48 equ 0x02000000 ;; 48kHz sample rate ;; |
SPCS_SAMPLERATE_32 equ 0x03000000 ;; 32kHz sample rate ;; |
SPCS_CHANNELNUMMASK equ 0x00f00000 ;; Channel number ;; |
SPCS_CHANNELNUM_UNSPEC equ 0x00000000 ;; Unspecified channel number ;; |
SPCS_CHANNELNUM_LEFT equ 0x00100000 ;; Left channel ;; |
SPCS_CHANNELNUM_RIGHT equ 0x00200000 ;; Right channel ;; |
SPCS_SOURCENUMMASK equ 0x000f0000 ;; Source number ;; |
SPCS_SOURCENUM_UNSPEC equ 0x00000000 ;; Unspecified source number ;; |
SPCS_GENERATIONSTATUS equ 0x00008000 ;; Originality flag (see IEC-958 spec) ;; |
SPCS_CATEGORYCODEMASK equ 0x00007f00 ;; Category code (see IEC-958 spec) ;; |
SPCS_MODEMASK equ 0x000000c0 ;; Mode (see IEC-958 spec) ;; |
SPCS_EMPHASISMASK equ 0x00000038 ;; Emphasis ;; |
SPCS_EMPHASIS_NONE equ 0x00000000 ;; No emphasis ;; |
SPCS_EMPHASIS_50_15 equ 0x00000008 ;; 50/15 usec 2 channel ;; |
SPCS_COPYRIGHT equ 0x00000004 ;; Copyright asserted flag -- do not modify ;; |
SPCS_NOTAUDIODATA equ 0x00000002 ;; 0 = Digital audio, 1 = not audio ;; |
SPCS_PROFESSIONAL equ 0x00000001 ;; 0 = Consumer (IEC-958), 1 = pro (AES3-1992) ;; |
SPDIF_SELECT equ 0x45 ;; Enables SPDIF or Analogue outputs 0-Analogue, 0x700-SPDIF ;; |
SPDIF_SELECT equ 0x45 ;; Enables SPDIF or Analogue outputs 0-Analogue, 0x700-SPDIF ;; |
;; This is the MPU port on the card ;; |
MUDATA equ 0x47 |
MUCMD equ 0x48 |
MUSTAT equ MUCMD |
MUDATA equ 0x47 |
MUCMD equ 0x48 |
MUSTAT equ MUCMD |
;; From 0x50 - 0x5f, last samples captured ;; |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
DEV_GET_INFO equ 8 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
195,45 → 195,45 |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
240,9 → 240,9 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
249,79 → 249,79 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
328,7 → 328,7 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
338,172 → 338,172 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
call init_controller |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call setup_codec |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call SysMsgBoardStr |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call SysMsgBoardStr |
if IRQ_REMAP |
pushf |
cli |
pushf |
cli |
mov ebx, [ctrl.int_line] |
in al, 0xA1 |
mov ah, al |
in al, 0x21 |
test ebx, ebx |
jz .skip |
bts ax, bx ;mask old line |
mov ebx, [ctrl.int_line] |
in al, 0xA1 |
mov ah, al |
in al, 0x21 |
test ebx, ebx |
jz .skip |
bts ax, bx ;mask old line |
.skip: |
bts ax, IRQ_LINE ;mask new ine |
out 0x21, al |
mov al, ah |
out 0xA1, al |
bts ax, IRQ_LINE ;mask new ine |
out 0x21, al |
mov al, ah |
out 0xA1, al |
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ |
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ |
mov dx, 0x4d0 ;8259 ELCR1 |
in al, dx |
bts ax, IRQ_LINE |
out dx, al ;set level-triggered mode |
mov [ctrl.int_line], IRQ_LINE |
popf |
mov esi, msgRemap |
call SysMsgBoardStr |
mov dx, 0x4d0 ;8259 ELCR1 |
in al, dx |
bts ax, IRQ_LINE |
out dx, al ;set level-triggered mode |
mov [ctrl.int_line], IRQ_LINE |
popf |
mov esi, msgRemap |
call SysMsgBoardStr |
end if |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail_msg |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
stdcall create |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
stdcall create |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
xor eax, eax |
ret |
.fail_msg: |
call SysMsgBoardStr |
xor eax, eax |
ret |
call SysMsgBoardStr |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_PLAY |
jne @F |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
@@: |
cmp eax, DEV_GET_INFO |
jne @F |
mov ebx, [edi+output] |
stdcall get_dev_info, ebx |
ret |
cmp eax, DEV_GET_INFO |
jne @F |
mov ebx, [edi+output] |
stdcall get_dev_info, ebx |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
or eax, -1 |
ret |
endp |
restore handle |
516,27 → 516,27 |
align 4 |
proc ac97_irq |
locals |
status dd 0 |
endl |
locals |
status dd 0 |
endl |
; status = inl(chip->port + IPR); |
mov edx, IPR |
call [ctrl.ctrl_read32] |
test eax, eax |
jz @f |
mov edx, IPR |
call [ctrl.ctrl_read32] |
test eax, eax |
jz @f |
mov dword [status], eax |
mov dword [status], eax |
mov ebx, dword [buff_list] |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
mov ebx, dword [buff_list] |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
mov eax, dword [status] ;; ack ;; |
mov edx, IPR |
call [ctrl.ctrl_write32] |
ret |
mov eax, dword [status] ;; ack ;; |
mov edx, IPR |
call [ctrl.ctrl_write32] |
ret |
endp |
543,490 → 543,490 |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov edi, pcmout_bdl |
stosd |
mov eax, 0x4000000 |
stosd |
mov edi, pcmout_bdl |
stosd |
mov eax, 0x4000000 |
stosd |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
stosd ;1.] |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
stosd ;1.] |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov eax, [ctrl.buffer] |
call GetPgAddr |
stdcall ptr_write, PLAYBACK_POINTER, 0, 0 |
stdcall ptr_write, PLAYBACK_UNKNOWN1, 0, 0 |
stdcall ptr_write, PLAYBACK_UNKNOWN2, 0, 0 |
stdcall ptr_write, PLAYBACK_DMA_ADDR, 0, eax |
stdcall ptr_write, PLAYBACK_POINTER, 0, 0 |
stdcall ptr_write, PLAYBACK_UNKNOWN1, 0, 0 |
stdcall ptr_write, PLAYBACK_UNKNOWN2, 0, 0 |
stdcall ptr_write, PLAYBACK_DMA_ADDR, 0, eax |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr |
and ebx, 0xFFF |
add eax, ebx |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr |
and ebx, 0xFFF |
add eax, ebx |
stdcall ptr_write, PLAYBACK_LIST_ADDR, 0, eax |
stdcall ptr_write, PLAYBACK_LIST_SIZE, 0, 0 |
stdcall ptr_write, PLAYBACK_LIST_PTR, 0, 0 |
stdcall ptr_write, PLAYBACK_LIST_ADDR, 0, eax |
stdcall ptr_write, PLAYBACK_LIST_SIZE, 0, 0 |
stdcall ptr_write, PLAYBACK_LIST_PTR, 0, 0 |
;mov eax, 0x00004000 |
;shl eax, 16 |
stdcall ptr_write, PLAYBACK_PERIOD_SIZE, 0, 0x40000000;eax |
;mov eax, 0x00004000 |
;shl eax, 16 |
stdcall ptr_write, PLAYBACK_PERIOD_SIZE, 0, 0x40000000 ;eax |
ret |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
cmp edx, VID_Creative |
jne @F |
mov [ctrl.vendor_ids], msg_Creative |
ret |
cmp edx, VID_Creative |
jne @F |
mov [ctrl.vendor_ids], msg_Creative |
ret |
@@: |
.err: |
xor eax, eax |
mov [ctrl.vendor_ids], eax ;something wrong ? |
ret |
xor eax, eax |
mov [ctrl.vendor_ids], eax ;something wrong ? |
ret |
endp |
align 4 |
proc init_controller |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x2C |
mov esi, msgPciSubsys |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x2C |
mov esi, msgPciSubsys |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
.default: |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
@@: |
mov [ctrl.int_line], eax |
mov [ctrl.int_line], eax |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_Creative |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
align 4 |
proc init_codec |
call reset_codec |
test eax, eax |
jz .err |
call detect_codec |
xor eax, eax |
inc eax |
ret |
call reset_codec |
test eax, eax |
jz .err |
call detect_codec |
xor eax, eax |
inc eax |
ret |
.err: |
xor eax, eax |
ret |
xor eax, eax |
ret |
endp |
align 4 |
proc reset_codec |
locals |
counter dd ? |
endl |
locals |
counter dd ? |
endl |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms |
call StallExec |
mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms |
call StallExec |
stdcall ptr_read, TRIGGER_CHANNEL, 0 |
stdcall ptr_read, TRIGGER_CHANNEL, 0 |
mov [counter], 16 ; total 20*100 ms = 2s |
mov [counter], 16 ; total 20*100 ms = 2s |
.wait: |
stdcall codec_read, dword 0x26 |
test eax, 1 |
jnz .ok |
stdcall codec_read, dword 0x26 |
test eax, 1 |
jnz .ok |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov eax, 100000 ; wait 100 ms |
call StallExec |
dec [counter] |
jnz .wait |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
stc |
ret |
.ok: |
xor eax, eax |
inc eax |
ret |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
play: |
mov eax, INTE_CH_0_LOOP |
stdcall intr_enable, eax |
mov eax, INTE_CH_0_LOOP |
stdcall intr_enable, eax |
stdcall ptr_read, TRIGGER_CHANNEL, 0 |
mov ebx, TRIGGER_CHANNEL_0 |
or eax, ebx |
stdcall ptr_write, TRIGGER_CHANNEL, 0, eax |
stdcall ptr_read, TRIGGER_CHANNEL, 0 |
mov ebx, TRIGGER_CHANNEL_0 |
or eax, ebx |
stdcall ptr_write, TRIGGER_CHANNEL, 0, eax |
xor eax, eax |
ret |
xor eax, eax |
ret |
align 4 |
stop: |
mov eax, INTE_CH_0_LOOP or INTE_CH_0_HALF_LOOP |
stdcall intr_disable, eax |
mov eax, INTE_CH_0_LOOP or INTE_CH_0_HALF_LOOP |
stdcall intr_disable, eax |
stdcall ptr_read, TRIGGER_CHANNEL, 0 |
mov ebx, TRIGGER_CHANNEL_0 |
xor ebx, -1 |
or eax, ebx |
stdcall ptr_write, TRIGGER_CHANNEL, 0, eax |
xor eax, eax |
ret |
stdcall ptr_read, TRIGGER_CHANNEL, 0 |
mov ebx, TRIGGER_CHANNEL_0 |
xor ebx, -1 |
or eax, ebx |
stdcall ptr_write, TRIGGER_CHANNEL, 0, eax |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ecx, [ctrl.ctrl_io_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ecx, [ctrl.ctrl_io_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
xor eax, eax |
mov [CTRL_INFO.codec_io_base], eax |
mov [CTRL_INFO.codec_mem_base], eax |
mov [CTRL_INFO.ctrl_mem_base], eax |
mov [CTRL_INFO.glob_cntrl], eax |
mov [CTRL_INFO.glob_sta], eax |
ret |
xor eax, eax |
mov [CTRL_INFO.codec_io_base], eax |
mov [CTRL_INFO.codec_mem_base], eax |
mov [CTRL_INFO.ctrl_mem_base], eax |
mov [CTRL_INFO.glob_cntrl], eax |
mov [CTRL_INFO.glob_sta], eax |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc create stdcall |
stdcall PciRead16, [ctrl.bus], [ctrl.devfn], dword 4 |
test eax, 4 ; test master bit |
jnz @f |
or eax, 4 |
stdcall PciWrite16, [ctrl.bus], [ctrl.devfn], dword 4, eax ; set master bit |
@@: |
stdcall PciRead16, [ctrl.bus], [ctrl.devfn], dword 4 |
test eax, 4 ; test master bit |
jnz @f |
or eax, 4 |
stdcall PciWrite16, [ctrl.bus], [ctrl.devfn], dword 4, eax ; set master bit |
@@: |
xor eax, eax |
mov edx, INTE |
call [ctrl.ctrl_write32] |
xor eax, eax |
mov edx, INTE |
call [ctrl.ctrl_write32] |
stdcall ptr_write, SPCS0, 0, \ |
SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ |
SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ |
SPCS_GENERATIONSTATUS or 0x00001200 or \ |
0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT |
stdcall ptr_write, SPCS1, 0, \ |
SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ |
SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ |
SPCS_GENERATIONSTATUS or 0x00001200 or \ |
0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT |
stdcall ptr_write, SPCS2, 0, \ |
SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ |
SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ |
SPCS_GENERATIONSTATUS or 0x00001200 or \ |
0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT |
stdcall ptr_write, SPCS0, 0, \ |
SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ |
SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ |
SPCS_GENERATIONSTATUS or 0x00001200 or \ |
0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT |
stdcall ptr_write, SPCS1, 0, \ |
SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ |
SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ |
SPCS_GENERATIONSTATUS or 0x00001200 or \ |
0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT |
stdcall ptr_write, SPCS2, 0, \ |
SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ |
SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ |
SPCS_GENERATIONSTATUS or 0x00001200 or \ |
0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT |
stdcall ptr_write, SPDIF_SELECT, 0, 0x700 ; disable SPDIF |
stdcall ptr_write, ROUTING, 0, 0x1003F ; routing |
stdcall gpio_write, 0x1080 ; analog mode |
stdcall ptr_write, SPDIF_SELECT, 0, 0x700 ; disable SPDIF |
stdcall ptr_write, ROUTING, 0, 0x1003F ; routing |
stdcall gpio_write, 0x1080 ; analog mode |
mov eax, dword HCFG_LOCKSOUNDCACHE or HCFG_AUDIOENABLE |
mov edx, HCFG |
call [ctrl.ctrl_write32] |
ret |
mov eax, dword HCFG_LOCKSOUNDCACHE or HCFG_AUDIOENABLE |
mov edx, HCFG |
call [ctrl.ctrl_write32] |
ret |
endp |
align 4 |
proc codec_read stdcall, reg:dword |
stdcall ac97_read, dword [reg] |
ret |
stdcall ac97_read, dword [reg] |
ret |
endp |
align 4 |
proc codec_write stdcall, reg:dword |
stdcall ac97_write, dword [reg], eax |
ret |
stdcall ac97_write, dword [reg], eax |
ret |
endp |
align 4 |
proc ac97_read stdcall, reg:dword |
push edx |
mov eax, dword [reg] |
mov edx, AC97ADDRESS |
call [ctrl.ctrl_write8] |
push edx |
mov eax, dword [reg] |
mov edx, AC97ADDRESS |
call [ctrl.ctrl_write8] |
mov edx, AC97DATA |
call [ctrl.ctrl_read16] |
and eax, 0xFFFF |
pop edx |
ret |
mov edx, AC97DATA |
call [ctrl.ctrl_read16] |
and eax, 0xFFFF |
pop edx |
ret |
endp |
align 4 |
proc ac97_write stdcall, reg:dword, val:dword |
push eax edx |
mov eax, dword [reg] |
mov edx, AC97ADDRESS |
call [ctrl.ctrl_write8] |
push eax edx |
mov eax, dword [reg] |
mov edx, AC97ADDRESS |
call [ctrl.ctrl_write8] |
mov eax, dword [val] |
mov edx, AC97DATA |
call [ctrl.ctrl_write16] |
pop edx eax |
ret |
mov eax, dword [val] |
mov edx, AC97DATA |
call [ctrl.ctrl_write16] |
pop edx eax |
ret |
endp |
align 4 |
proc ptr_read stdcall, reg:dword, chn:dword |
push edx |
mov eax, dword [reg] |
shl eax, 16 |
or eax, dword [chn] |
push edx |
mov eax, dword [reg] |
shl eax, 16 |
or eax, dword [chn] |
mov edx, PTR |
call [ctrl.ctrl_write32] |
mov edx, PTR |
call [ctrl.ctrl_write32] |
mov edx, DATA |
call [ctrl.ctrl_read32] |
pop edx |
ret |
mov edx, DATA |
call [ctrl.ctrl_read32] |
pop edx |
ret |
endp |
align 4 |
proc ptr_write stdcall, reg:dword, chn:dword, data:dword |
push eax edx |
mov eax, dword [reg] |
shl eax, 16 |
or eax, dword [chn] |
push eax edx |
mov eax, dword [reg] |
shl eax, 16 |
or eax, dword [chn] |
mov edx, PTR |
call [ctrl.ctrl_write32] |
mov edx, PTR |
call [ctrl.ctrl_write32] |
mov eax, dword [data] |
mov edx, DATA |
call [ctrl.ctrl_write32] |
pop edx eax |
ret |
mov eax, dword [data] |
mov edx, DATA |
call [ctrl.ctrl_write32] |
pop edx eax |
ret |
endp |
align 4 |
proc intr_enable stdcall, intrenb:dword |
push edx |
mov edx, INTE |
call [ctrl.ctrl_read32] |
push edx |
mov edx, INTE |
call [ctrl.ctrl_read32] |
or eax, dword [intrenb] |
mov edx, INTE |
call [ctrl.ctrl_write32] |
pop edx |
ret |
or eax, dword [intrenb] |
mov edx, INTE |
call [ctrl.ctrl_write32] |
pop edx |
ret |
endp |
align 4 |
proc intr_disable stdcall, intrenb:dword |
push eax ebx edx |
mov edx, INTE |
call [ctrl.ctrl_read32] |
push eax ebx edx |
mov edx, INTE |
call [ctrl.ctrl_read32] |
mov ebx, dword [intrenb] |
xor ebx, -1 |
and eax, ebx |
mov edx, INTE |
call [ctrl.ctrl_write32] |
pop edx ebx eax |
ret |
mov ebx, dword [intrenb] |
xor ebx, -1 |
and eax, ebx |
mov edx, INTE |
call [ctrl.ctrl_write32] |
pop edx ebx eax |
ret |
endp |
align 4 |
proc gpio_write stdcall, value:dword |
push eax edx |
mov eax, dword [value] |
mov edx, GPIO |
call [ctrl.ctrl_write32] |
pop edx eax |
ret |
push eax edx |
mov eax, dword [value] |
mov edx, GPIO |
call [ctrl.ctrl_write32] |
pop edx eax |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1035,76 → 1035,76 |
align 4 |
proc codec_io_r16 ;Not used. |
;mov edx, [ctrl.ctrl_io_base] |
;in eax, dx |
ret |
;mov edx, [ctrl.ctrl_io_base] |
;in eax, dx |
ret |
endp |
align 4 |
proc codec_io_w16 ;Not used. |
;mov edx, [ctrl.ctrl_io_base] |
;out dx, eax |
ret |
;mov edx, [ctrl.ctrl_io_base] |
;out dx, eax |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
align 4 |
dword2str: |
push eax ebx ecx |
mov esi, hex_buff |
mov ecx, -8 |
push eax ebx ecx |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
pop ecx ebx eax |
ret |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
pop ecx ebx eax |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
1114,16 → 1114,16 |
align 4 |
devices dd (CTRL_CT0200 shl 16)+VID_Creative,msg_CT_EMU10K1X,set_Creative |
dd 0 ;terminator |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
msg_CT_EMU10K1X db 'SB Live! Dell OEM', 13,10, 0 |
msg_Creative db 'Creative ', 0 |
msg_Creative db 'Creative ', 0 |
szKernel db 'KERNEL', 0 |
sz_sound_srv db 'SOUND',0 |
szKernel db 'KERNEL', 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
1131,7 → 1131,7 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
;msgInitCtrl db 'init controller',13,10,0 |
;msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer ...',0 |
1159,8 → 1159,8 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
/kernel/trunk/drivers/ensoniq.asm |
---|
1,1177 → 1,1177 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;alpha version |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
REMAP_IRQ equ 0 |
;irq 0,1,2,8,12,13 íåäîñòóïíû |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010101000b |
IRQ_LINE equ 0 |
CPU_FREQ equ 2600d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
BIT2 EQU 0x00000004 |
BIT3 EQU 0x00000008 |
BIT4 EQU 0x00000010 |
BIT5 EQU 0x00000020 |
BIT6 EQU 0x00000040 |
BIT7 EQU 0x00000080 |
BIT8 EQU 0x00000100 |
BIT9 EQU 0x00000200 |
BIT10 EQU 0x00000400 |
BIT11 EQU 0x00000800 |
BIT12 EQU 0x00001000 |
BIT13 EQU 0x00002000 |
BIT14 EQU 0x00004000 |
BIT15 EQU 0x00008000 |
BIT16 EQU 0x00010000 |
BIT17 EQU 0x00020000 |
BIT18 EQU 0x00040000 |
BIT19 EQU 0x00080000 |
BIT20 EQU 0x00100000 |
BIT21 EQU 0x00200000 |
BIT22 EQU 0x00400000 |
BIT23 EQU 0x00800000 |
BIT24 EQU 0x00100000 |
BIT25 EQU 0x02000000 |
BIT26 EQU 0x04000000 |
BIT27 EQU 0x08000000 |
BIT28 EQU 0x10000000 |
BIT29 EQU 0x20000000 |
BIT30 EQU 0x40000000 |
BIT31 EQU 0x80000000 |
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list |
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register |
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index |
PCM_OUT_SR_REG equ 0x16 ; PCM out Status register |
PCM_OUT_PIV_REG equ 0x1a |
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index |
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register |
MC_IN_CR_REG equ 0x2b ; MIC in Control Register |
RR equ BIT1 ; reset registers. Nukes all regs |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 18h ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 28h ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 2ah ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 2ch ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 2eh ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 30h ; LFE sample rate |
GLOB_CTRL equ 0x2C ; Global Control |
CTRL_STAT equ 0x30 ; Global Status |
CTRL_CAS equ 0x34 ; Codec Access Semiphore |
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit |
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready |
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status |
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable |
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off |
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset |
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset |
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable |
CODEC_REG_POWERDOWN equ 0x26 |
CODEC_REG_ST equ 0x26 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
OS_BASE equ 0x80000000 |
SLOT_BASE equ OS_BASE+0x0080000 |
new_app_base equ 0 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgDetect |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
jmp .fail ;force fail |
if DEBUG |
mov esi, msgInitCodec |
call SysMsgBoardStr |
end if |
call init_codec |
test eax, eax |
jz .fail |
if DEBUG |
mov esi, [codec.ac_vendor_ids] |
call SysMsgBoardStr |
mov esi, [codec.chip_ids] |
call SysMsgBoardStr |
end if |
call reset_controller |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
;@@: |
; cmp eax, DEV_GET_INFO |
; jne @F |
; mov ebx, [edi+output] |
; stdcall get_dev_info, ebx |
; ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc ac97_irq |
; if DEBUG |
; mov esi, msgIRQ |
; call SysMsgBoardStr |
; end if |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
ret |
.skip: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 ;0x1D |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov ebx, 0xC0002000 |
mov ecx, 4 |
mov edi, pcmout_bdl |
@@: |
mov [edi], eax |
mov [edi+4], ebx |
mov [edi+32], eax |
mov [edi+4+32], ebx |
mov [edi+64], eax |
mov [edi+4+64], ebx |
mov [edi+96], eax |
mov [edi+4+96], ebx |
mov [edi+128], eax |
mov [edi+4+128], ebx |
mov [edi+160], eax |
mov [edi+4+160], ebx |
mov [edi+192], eax |
mov [edi+4+192], ebx |
mov [edi+224], eax |
mov [edi+4+224], ebx |
add eax, 0x4000 |
add edi, 8 |
loop @B |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
add eax, 0x4000 |
add edi, 4 |
loop @B |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr ;eax |
and ebx, 0xFFF |
add eax, ebx |
mov edx, PCM_OUT_BDL |
call [ctrl.ctrl_write32] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
cmp ebx, 0x1274 |
jne @F |
mov [ctrl.vendor_ids], msgEnsoniq |
ret |
@@: |
mov [ctrl.vendor_ids], 0 ;something wrong ? |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_controller |
mov esi, msgPCIcmd |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
call dword2str |
call SysMsgBoardStr |
mov esi, msgIObase |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
; and eax, -16 |
mov [ctrl.ctrl_io_base], eax |
call dword2str |
call SysMsgBoardStr |
mov esi, msgIRQline |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
mov [ctrl.int_line], eax |
call dword2str |
call SysMsgBoardStr |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_ICH |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
align 4 |
proc reset_controller |
xor eax, eax |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov eax, RR |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc init_codec |
locals |
counter dd ? |
endl |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
test eax, CTRL_ST_CREADY |
jnz .ready |
call reset_codec |
and eax, eax |
jz .err |
xor edx, edx ;ac_reg_0 |
call [ctrl.codec_write16] |
xor eax, eax |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_write16] |
mov [counter], 200 ; total 200*5 ms = 1s |
.wait: |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_read16] |
and eax, 0x0F |
cmp eax, 0x0F |
jz .ready |
mov eax, 5000 ; wait 5 ms |
call StallExec |
sub [counter] , 1 |
jnz .wait |
.err: |
xor eax, eax ; timeout error |
ret |
.ready: |
call detect_codec |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 0x02 |
jz .cold |
call warm_reset |
jnc .ok |
.cold: |
call cold_reset |
jnc .ok |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call SysMsgBoardStr |
end if |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc warm_reset |
locals |
counter dd ? |
endl |
mov eax, 0x06 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgWarm |
call SysMsgBoardStr |
end if |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 4 |
jz .ok |
sub [counter], 1 |
jnz .wait |
if DEBUG |
mov esi, msgWRFail |
call SysMsgBoardStr |
end if |
stc |
ret |
.ok: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
.fail: |
stc |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
xor eax, eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 1000000 ; wait 1 s |
call StallExec |
mov eax, 2 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 4 |
jz .ok |
sub [counter], 1 |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
stc |
ret |
.ok: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
.fail: |
stc |
ret |
endp |
align 4 |
play: |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x1D |
call [ctrl.ctrl_write8] |
xor eax, eax |
ret |
align 4 |
stop: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x0 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ebx, [ctrl.codec_io_base] |
mov ecx, [ctrl.ctrl_io_base] |
mov edx, [ctrl.codec_mem_base] |
mov edi, [ctrl.ctrl_mem_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.codec_io_base], ebx |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov [CTRL_INFO.codec_mem_base], edx |
mov [CTRL_INFO.ctrl_mem_base], edi |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_cntrl], eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_sta], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
mov edx, [ac_reg] |
mov ebx, edx |
shr ebx, 1 |
bt [codec.shadow_flag], ebx |
jc .use_shadow |
call [ctrl.codec_read16] ;change edx !!! |
mov ecx, eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_RCS |
jz .read_ok |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
xor eax,eax |
not eax ;timeout |
ret |
.read_ok: |
mov edx, [ac_reg] |
mov [codec.regs+edx], cx |
bts [codec.shadow_flag], ebx |
mov eax, ecx |
ret |
.use_shadow: |
movzx eax, word [codec.regs+edx] |
ret |
endp |
align 4 |
proc codec_write stdcall, ac_reg:dword |
push eax |
call check_semafore |
and eax, eax |
jz .err |
pop eax |
mov esi, [ac_reg] |
mov edx, esi |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
shr esi, 1 |
bts [codec.shadow_flag], esi |
ret |
.err: |
pop eax |
ret |
endp |
align 4 |
proc codec_check_ready |
mov edx, CTRL_ST |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .not_ready |
xor eax, wax |
inc eax |
ret |
.not_ready: |
xor eax, eax |
ret |
endp |
align 4 |
proc check_semafore |
local counter:DWORD |
mov [counter], 100 |
.l1: |
mov edx, CTRL_CAS |
call [ctrl.ctrl_read8] |
and eax, CAS_FLAG |
jz .ok |
mov eax, 1 |
call StallExec |
sub [counter], 1 |
jnz .l1 |
xor eax, eax |
ret |
align 4 |
.ok: |
xor eax,eax |
inc eax |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx,edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
codec_io_r16: |
add edx, [ctrl.codec_io_base] |
in ax, dx |
ret |
align 4 |
codec_io_w16: |
add edx, [ctrl.codec_io_base] |
out dx, ax |
ret |
align 4 |
ctrl_io_r8: |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
align 4 |
ctrl_io_r16: |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
align 4 |
ctrl_io_r32: |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
align 4 |
ctrl_io_w8: |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
align 4 |
ctrl_io_w16: |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
align 4 |
ctrl_io_w32: |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
include "codec.inc" |
align 4 |
devices dd (0x5000 shl 16)+0x1274,msgEnsoniq,set_ICH |
dd (0x5880 shl 16)+0x1274,msgVibra128,set_ICH |
dd 0 ;terminator |
version dd 0x00040004 |
msgEnsoniq db 'Ensonic 1371',13,10,0 |
msgVibra128 db 'Sound Blaster AudioPCI Vibra 128',13,10,0 |
sz_sound_srv db 'SOUND',0 |
msgDetect db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
msgAttchIRQ db 'IRQ line not supported', 13,10, 0 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
msgNotify db 'call notify',13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgInitCtrl db 'init controller',13,10,0 |
msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer',13,10,0 |
msgReg db 'set service handler',13,10,0 |
msgOk db 'service installed',13,10,0 |
msgCold db 'cold reset',13,10,0 |
msgWarm db 'warm reset',13,10,0 |
msgWRFail db 'warm reset failed',13,10,0 |
msgCRFail db 'cold reset failed',13,10,0 |
msgCFail db 'codec not ready',13,10,0 |
msgResetOk db 'reset complete',13,10,0 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
msgPCIcmd db 'PCI command ',0 |
msgIObase db 'IO base ',0 |
msgIRQline db 'IRQ line ',0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;alpha version |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
REMAP_IRQ equ 0 |
;irq 0,1,2,8,12,13 íåäîñòóïíû |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010101000b |
IRQ_LINE equ 0 |
CPU_FREQ equ 2600d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
BIT2 EQU 0x00000004 |
BIT3 EQU 0x00000008 |
BIT4 EQU 0x00000010 |
BIT5 EQU 0x00000020 |
BIT6 EQU 0x00000040 |
BIT7 EQU 0x00000080 |
BIT8 EQU 0x00000100 |
BIT9 EQU 0x00000200 |
BIT10 EQU 0x00000400 |
BIT11 EQU 0x00000800 |
BIT12 EQU 0x00001000 |
BIT13 EQU 0x00002000 |
BIT14 EQU 0x00004000 |
BIT15 EQU 0x00008000 |
BIT16 EQU 0x00010000 |
BIT17 EQU 0x00020000 |
BIT18 EQU 0x00040000 |
BIT19 EQU 0x00080000 |
BIT20 EQU 0x00100000 |
BIT21 EQU 0x00200000 |
BIT22 EQU 0x00400000 |
BIT23 EQU 0x00800000 |
BIT24 EQU 0x00100000 |
BIT25 EQU 0x02000000 |
BIT26 EQU 0x04000000 |
BIT27 EQU 0x08000000 |
BIT28 EQU 0x10000000 |
BIT29 EQU 0x20000000 |
BIT30 EQU 0x40000000 |
BIT31 EQU 0x80000000 |
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list |
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register |
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index |
PCM_OUT_SR_REG equ 0x16 ; PCM out Status register |
PCM_OUT_PIV_REG equ 0x1a |
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index |
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register |
MC_IN_CR_REG equ 0x2b ; MIC in Control Register |
RR equ BIT1 ; reset registers. Nukes all regs |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 18h ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 28h ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 2ah ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 2ch ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 2eh ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 30h ; LFE sample rate |
GLOB_CTRL equ 0x2C ; Global Control |
CTRL_STAT equ 0x30 ; Global Status |
CTRL_CAS equ 0x34 ; Codec Access Semiphore |
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit |
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready |
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status |
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable |
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off |
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset |
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset |
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable |
CODEC_REG_POWERDOWN equ 0x26 |
CODEC_REG_ST equ 0x26 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
OS_BASE equ 0x80000000 |
SLOT_BASE equ OS_BASE+0x0080000 |
new_app_base equ 0 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgDetect |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi, [ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
jmp .fail ;force fail |
if DEBUG |
mov esi, msgInitCodec |
call SysMsgBoardStr |
end if |
call init_codec |
test eax, eax |
jz .fail |
if DEBUG |
mov esi, [codec.ac_vendor_ids] |
call SysMsgBoardStr |
mov esi, [codec.chip_ids] |
call SysMsgBoardStr |
end if |
call reset_controller |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
;@@: |
; cmp eax, DEV_GET_INFO |
; jne @F |
; mov ebx, [edi+output] |
; stdcall get_dev_info, ebx |
; ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc ac97_irq |
; if DEBUG |
; mov esi, msgIRQ |
; call SysMsgBoardStr |
; end if |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
ret |
.skip: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 ;0x1D |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov ebx, 0xC0002000 |
mov ecx, 4 |
mov edi, pcmout_bdl |
@@: |
mov [edi], eax |
mov [edi+4], ebx |
mov [edi+32], eax |
mov [edi+4+32], ebx |
mov [edi+64], eax |
mov [edi+4+64], ebx |
mov [edi+96], eax |
mov [edi+4+96], ebx |
mov [edi+128], eax |
mov [edi+4+128], ebx |
mov [edi+160], eax |
mov [edi+4+160], ebx |
mov [edi+192], eax |
mov [edi+4+192], ebx |
mov [edi+224], eax |
mov [edi+4+224], ebx |
add eax, 0x4000 |
add edi, 8 |
loop @B |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
add eax, 0x4000 |
add edi, 4 |
loop @B |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr ;eax |
and ebx, 0xFFF |
add eax, ebx |
mov edx, PCM_OUT_BDL |
call [ctrl.ctrl_write32] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
cmp ebx, 0x1274 |
jne @F |
mov [ctrl.vendor_ids], msgEnsoniq |
ret |
@@: |
mov [ctrl.vendor_ids], 0 ;something wrong ? |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_controller |
mov esi, msgPCIcmd |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
call dword2str |
call SysMsgBoardStr |
mov esi, msgIObase |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
; and eax, -16 |
mov [ctrl.ctrl_io_base], eax |
call dword2str |
call SysMsgBoardStr |
mov esi, msgIRQline |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
mov [ctrl.int_line], eax |
call dword2str |
call SysMsgBoardStr |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_ICH |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
align 4 |
proc reset_controller |
xor eax, eax |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov eax, RR |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc init_codec |
locals |
counter dd ? |
endl |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
test eax, CTRL_ST_CREADY |
jnz .ready |
call reset_codec |
and eax, eax |
jz .err |
xor edx, edx ;ac_reg_0 |
call [ctrl.codec_write16] |
xor eax, eax |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_write16] |
mov [counter], 200 ; total 200*5 ms = 1s |
.wait: |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_read16] |
and eax, 0x0F |
cmp eax, 0x0F |
jz .ready |
mov eax, 5000 ; wait 5 ms |
call StallExec |
sub [counter] , 1 |
jnz .wait |
.err: |
xor eax, eax ; timeout error |
ret |
.ready: |
call detect_codec |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 0x02 |
jz .cold |
call warm_reset |
jnc .ok |
.cold: |
call cold_reset |
jnc .ok |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call SysMsgBoardStr |
end if |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc warm_reset |
locals |
counter dd ? |
endl |
mov eax, 0x06 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgWarm |
call SysMsgBoardStr |
end if |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 4 |
jz .ok |
sub [counter], 1 |
jnz .wait |
if DEBUG |
mov esi, msgWRFail |
call SysMsgBoardStr |
end if |
stc |
ret |
.ok: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
.fail: |
stc |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
xor eax, eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 1000000 ; wait 1 s |
call StallExec |
mov eax, 2 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 4 |
jz .ok |
sub [counter], 1 |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
stc |
ret |
.ok: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
.fail: |
stc |
ret |
endp |
align 4 |
play: |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x1D |
call [ctrl.ctrl_write8] |
xor eax, eax |
ret |
align 4 |
stop: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x0 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ebx, [ctrl.codec_io_base] |
mov ecx, [ctrl.ctrl_io_base] |
mov edx, [ctrl.codec_mem_base] |
mov edi, [ctrl.ctrl_mem_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.codec_io_base], ebx |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov [CTRL_INFO.codec_mem_base], edx |
mov [CTRL_INFO.ctrl_mem_base], edi |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_cntrl], eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_sta], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
mov edx, [ac_reg] |
mov ebx, edx |
shr ebx, 1 |
bt [codec.shadow_flag], ebx |
jc .use_shadow |
call [ctrl.codec_read16] ;change edx !!! |
mov ecx, eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_RCS |
jz .read_ok |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
xor eax, eax |
not eax ;timeout |
ret |
.read_ok: |
mov edx, [ac_reg] |
mov [codec.regs+edx], cx |
bts [codec.shadow_flag], ebx |
mov eax, ecx |
ret |
.use_shadow: |
movzx eax, word [codec.regs+edx] |
ret |
endp |
align 4 |
proc codec_write stdcall, ac_reg:dword |
push eax |
call check_semafore |
and eax, eax |
jz .err |
pop eax |
mov esi, [ac_reg] |
mov edx, esi |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
shr esi, 1 |
bts [codec.shadow_flag], esi |
ret |
.err: |
pop eax |
ret |
endp |
align 4 |
proc codec_check_ready |
mov edx, CTRL_ST |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .not_ready |
xor eax, wax |
inc eax |
ret |
.not_ready: |
xor eax, eax |
ret |
endp |
align 4 |
proc check_semafore |
local counter:DWORD |
mov [counter], 100 |
.l1: |
mov edx, CTRL_CAS |
call [ctrl.ctrl_read8] |
and eax, CAS_FLAG |
jz .ok |
mov eax, 1 |
call StallExec |
sub [counter], 1 |
jnz .l1 |
xor eax, eax |
ret |
align 4 |
.ok: |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
codec_io_r16: |
add edx, [ctrl.codec_io_base] |
in ax, dx |
ret |
align 4 |
codec_io_w16: |
add edx, [ctrl.codec_io_base] |
out dx, ax |
ret |
align 4 |
ctrl_io_r8: |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
align 4 |
ctrl_io_r16: |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
align 4 |
ctrl_io_r32: |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
align 4 |
ctrl_io_w8: |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
align 4 |
ctrl_io_w16: |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
align 4 |
ctrl_io_w32: |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
include "codec.inc" |
align 4 |
devices dd (0x5000 shl 16)+0x1274,msgEnsoniq,set_ICH |
dd (0x5880 shl 16)+0x1274,msgVibra128,set_ICH |
dd 0 ;terminator |
version dd 0x00040004 |
msgEnsoniq db 'Ensonic 1371',13,10,0 |
msgVibra128 db 'Sound Blaster AudioPCI Vibra 128',13,10,0 |
sz_sound_srv db 'SOUND',0 |
msgDetect db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
msgAttchIRQ db 'IRQ line not supported', 13,10, 0 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
msgNotify db 'call notify',13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgInitCtrl db 'init controller',13,10,0 |
msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer',13,10,0 |
msgReg db 'set service handler',13,10,0 |
msgOk db 'service installed',13,10,0 |
msgCold db 'cold reset',13,10,0 |
msgWarm db 'warm reset',13,10,0 |
msgWRFail db 'warm reset failed',13,10,0 |
msgCRFail db 'cold reset failed',13,10,0 |
msgCFail db 'codec not ready',13,10,0 |
msgResetOk db 'reset complete',13,10,0 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
msgPCIcmd db 'PCI command ',0 |
msgIObase db 'IO base ',0 |
msgIRQline db 'IRQ line ',0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/fm801.asm |
---|
7,26 → 7,26 |
format MS COFF |
DEBUG equ 1 |
DEBUG_IRQ equ 0 |
DEBUG equ 1 |
DEBUG_IRQ equ 0 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0x01000100 |
API_VERSION equ 0x01000100 |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
;irq 0,1,2,8,12,13 íåäîñòóïíû |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
if USE_COM_IRQ |
ATTCH_IRQ equ 0000111010111000b |
ATTCH_IRQ equ 0000111010111000b |
end if |
CPU_FREQ equ 2000d |
CPU_FREQ equ 2000d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
61,8 → 61,8 |
BIT30 EQU 0x40000000 |
BIT31 EQU 0x80000000 |
VID_FM801 equ 0x1319 |
CTRL_FM801 equ 0x0801 |
VID_FM801 equ 0x1319 |
CTRL_FM801 equ 0x0801 |
FM_PCM_VOLUME equ 0x00 |
FM_FM_VOLUME equ 0x02 |
123,33 → 123,33 |
FM_INTSTATUS_VOL equ 0x4000 |
FM_INTSTATUS_MPU equ 0x8000 |
CODEC_MASTER_VOL_REG equ 0x02 ; |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_MASTER_VOL_REG equ 0x02 ; |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
DEV_GET_INFO equ 8 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
156,28 → 156,28 |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
184,17 → 184,17 |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
201,9 → 201,9 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
210,79 → 210,79 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
289,7 → 289,7 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
299,139 → 299,139 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov eax, START |
call dword2str |
call SysMsgBoardStr |
mov esi, msgInit |
call SysMsgBoardStr |
mov eax, START |
call dword2str |
call SysMsgBoardStr |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi, [ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
call init_controller |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call reset_controller |
call setup_codec |
call reset_controller |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call SysMsgBoardStr |
mov esi, msgDone |
call SysMsgBoardStr |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail_msg |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
xor eax, eax |
ret |
.fail_msg: |
call SysMsgBoardStr |
xor eax, eax |
ret |
call SysMsgBoardStr |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_PLAY |
jne @F |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
;@@: |
; cmp eax, DEV_GET_INFO |
; jne @F |
440,8 → 440,8 |
; ret |
@@: |
.fail: |
or eax, -1 |
ret |
or eax, -1 |
ret |
endp |
restore handle |
454,30 → 454,30 |
align 4 |
proc fill_buffer |
cmp [ctrl.user_callback], 0 |
je .exit |
cmp [ctrl.user_callback], 0 |
je .exit |
mov esi, [ctrl.buffer] |
mov eax, int_flip_flop |
inc dword [eax] |
test dword [eax],1 |
je @f |
add esi, 0x4000 |
mov esi, [ctrl.buffer] |
mov eax, int_flip_flop |
inc dword [eax] |
test dword [eax], 1 |
je @f |
add esi, 0x4000 |
@@: |
stdcall [ctrl.user_callback], esi |
stdcall [ctrl.user_callback], esi |
mov edx, FM_PLAY_DMABUF1 |
mov eax, [buffer_pgaddr] |
mov esi, int_flip_flop |
test dword [esi],1 |
je @f |
mov edx, FM_PLAY_DMABUF2 |
add eax, 0x4000 |
mov edx, FM_PLAY_DMABUF1 |
mov eax, [buffer_pgaddr] |
mov esi, int_flip_flop |
test dword [esi], 1 |
je @f |
mov edx, FM_PLAY_DMABUF2 |
add eax, 0x4000 |
@@: |
call [ctrl.ctrl_write32] |
call [ctrl.ctrl_write32] |
.exit: |
ret |
ret |
endp |
align 4 |
484,365 → 484,366 |
proc ac97_irq |
if DEBUG_IRQ |
mov esi, msgIRQ |
call SysMsgBoardStr |
mov esi, msgIRQ |
call SysMsgBoardStr |
end if |
mov edx, FM_INTSTATUS |
call [ctrl.ctrl_read16] |
mov edx, FM_INTSTATUS |
call [ctrl.ctrl_read16] |
test eax, FM_INTSTATUS_PLAY |
je .exit |
test eax, FM_INTSTATUS_PLAY |
je .exit |
push eax |
call fill_buffer |
pop eax |
push eax |
call fill_buffer |
pop eax |
.exit: |
mov edx, FM_INTSTATUS |
call [ctrl.ctrl_write16] |
mov edx, FM_INTSTATUS |
call [ctrl.ctrl_write16] |
ret |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov [buffer_pgaddr], eax |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov [buffer_pgaddr], eax |
ret |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
push eax |
stdcall PciRead32, [bus], [devfn], dword 0x09 |
and eax,0xffffff |
cmp eax, 0x060100 ;pci-isa |
jne .no_bridge |
push eax |
stdcall PciRead32, [bus], [devfn], dword 0x09 |
and eax, 0xffffff |
cmp eax, 0x060100 ;pci-isa |
jne .no_bridge |
mov eax, [bus] |
mov [brg_bus], eax |
mov eax, [devfn] |
mov [brg_devfn],eax |
.no_bridge:pop eax |
mov eax, [bus] |
mov [brg_bus], eax |
mov eax, [devfn] |
mov [brg_devfn], eax |
.no_bridge: |
pop eax |
mov edi, devices |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov [ctrl.vendor_ids], msg_FM |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov [ctrl.vendor_ids], msg_FM |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
ret |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
ret |
.err: |
xor eax, eax |
ret |
xor eax, eax |
ret |
endp |
align 4 |
proc init_controller |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
and eax,0xFFFE |
mov [ctrl.ctrl_io_base], eax |
and eax, 0xFFFE |
mov [ctrl.ctrl_io_base], eax |
mov esi, msgIrqNum |
call SysMsgBoardStr |
mov esi, msgIrqNum |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
mov [ctrl.int_line], eax |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
mov [ctrl.int_line], eax |
call dword2str |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_FM |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
align 4 |
proc reset_controller |
mov esi, msgInitCtrl |
call SysMsgBoardStr |
mov esi, msgInitCtrl |
call SysMsgBoardStr |
mov edx, FM_CARD_CTL |
call [ctrl.ctrl_read8] |
push eax |
or al,1 |
mov edx, FM_CARD_CTL |
call [ctrl.ctrl_write8] |
mov eax, 10 |
call StallExec |
pop eax |
and al,0xFE |
mov edx, FM_CARD_CTL |
call [ctrl.ctrl_write8] |
mov eax, 10 |
call StallExec |
mov edx, FM_CARD_CTL |
call [ctrl.ctrl_read8] |
push eax |
or al, 1 |
mov edx, FM_CARD_CTL |
call [ctrl.ctrl_write8] |
mov eax, 10 |
call StallExec |
pop eax |
and al, 0xFE |
mov edx, FM_CARD_CTL |
call [ctrl.ctrl_write8] |
mov eax, 10 |
call StallExec |
mov eax, 0x0404 |
mov edx, FM_PCM_VOLUME |
call [ctrl.ctrl_write16] |
mov edx, FM_FM_VOLUME |
call [ctrl.ctrl_write16] |
mov edx, FM_I2S_VOLUME |
call [ctrl.ctrl_write16] |
mov eax, 0x0404 |
mov edx, FM_PCM_VOLUME |
call [ctrl.ctrl_write16] |
mov edx, FM_FM_VOLUME |
call [ctrl.ctrl_write16] |
mov edx, FM_I2S_VOLUME |
call [ctrl.ctrl_write16] |
mov edx, FM_INTMASK |
call [ctrl.ctrl_read16] |
and eax, not FM_INTMASK_PLAY |
or eax, FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL |
mov edx, FM_INTMASK |
call [ctrl.ctrl_write16] |
mov edx, FM_INTMASK |
call [ctrl.ctrl_read16] |
and eax, not FM_INTMASK_PLAY |
or eax, FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL |
mov edx, FM_INTMASK |
call [ctrl.ctrl_write16] |
mov eax, FM_INTMASK_PLAY or FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL |
mov edx, FM_INTSTATUS |
call [ctrl.ctrl_write16] |
mov eax, FM_INTMASK_PLAY or FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL |
mov edx, FM_INTSTATUS |
call [ctrl.ctrl_write16] |
ret |
ret |
endp |
align 4 |
proc init_codec |
mov esi, msgInitCodec |
call SysMsgBoardStr |
mov esi, msgInitCodec |
call SysMsgBoardStr |
mov al, FM_CODEC_CMD_READ |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_write8] |
mov al, FM_CODEC_CMD_READ |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_write8] |
call reset_codec |
call reset_codec |
call detect_codec |
call detect_codec |
xor eax, eax |
inc eax |
ret |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
mov ecx, 255 |
mov ecx, 255 |
.L1: |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_read16] |
test ah, FM_CODEC_CMD_VALID shr 8 |
jne .L2 |
loop .L1 |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_read16] |
test ah, FM_CODEC_CMD_VALID shr 8 |
jne .L2 |
loop .L1 |
.L2: |
mov edx, FM_CODEC_CTL |
call [ctrl.ctrl_read8] |
push eax |
or al, 0x20 |
mov edx, FM_CODEC_CTL |
call [ctrl.ctrl_write8] |
pop eax |
and al,0xDF |
mov edx, FM_CODEC_CTL |
call [ctrl.ctrl_write8] |
mov edx, FM_CODEC_CTL |
call [ctrl.ctrl_read8] |
push eax |
or al, 0x20 |
mov edx, FM_CODEC_CTL |
call [ctrl.ctrl_write8] |
pop eax |
and al, 0xDF |
mov edx, FM_CODEC_CTL |
call [ctrl.ctrl_write8] |
xor eax, eax |
inc eax |
ret |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
play: |
mov eax, 0x4000-1 |
mov edx, FM_PLAY_DMALEN |
call [ctrl.ctrl_write16] |
mov eax, 0x4000-1 |
mov edx, FM_PLAY_DMALEN |
call [ctrl.ctrl_write16] |
call fill_buffer |
call fill_buffer |
mov eax, FM_PLAY_START or FM_PLAY_STOPNOW or FM_PLAY_STEREO or FM_PLAY_16BIT or 0xA00 |
mov edx, FM_PLAY_CTL |
call [ctrl.ctrl_write16] |
mov eax, FM_PLAY_START or FM_PLAY_STOPNOW or FM_PLAY_STEREO or FM_PLAY_16BIT or 0xA00 |
mov edx, FM_PLAY_CTL |
call [ctrl.ctrl_write16] |
xor eax, eax |
ret |
xor eax, eax |
ret |
align 4 |
stop: |
mov edx, FM_PLAY_CTL |
call [ctrl.ctrl_read16] |
and eax, not (FM_PLAY_START or FM_PLAY_STOPNOW) |
or eax, FM_PLAY_BUF1_LAST or FM_PLAY_BUF2_LAST |
mov edx, FM_PLAY_CTL |
call [ctrl.ctrl_write16] |
mov edx, FM_PLAY_CTL |
call [ctrl.ctrl_read16] |
and eax, not (FM_PLAY_START or FM_PLAY_STOPNOW) |
or eax, FM_PLAY_BUF1_LAST or FM_PLAY_BUF2_LAST |
mov edx, FM_PLAY_CTL |
call [ctrl.ctrl_write16] |
xor eax, eax |
ret |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ebx, [ctrl.codec_io_base] |
mov ecx, [ctrl.ctrl_io_base] |
mov edx, [ctrl.codec_mem_base] |
mov edi, [ctrl.ctrl_mem_base] |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ebx, [ctrl.codec_io_base] |
mov ecx, [ctrl.ctrl_io_base] |
mov edx, [ctrl.codec_mem_base] |
mov edi, [ctrl.ctrl_mem_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.codec_io_base], ebx |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov [CTRL_INFO.codec_mem_base], edx |
mov [CTRL_INFO.ctrl_mem_base], edi |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.codec_io_base], ebx |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov [CTRL_INFO.codec_mem_base], edx |
mov [CTRL_INFO.ctrl_mem_base], edi |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
mov edx, [ac_reg] |
mov edx, [ac_reg] |
mov ebx, edx |
shr ebx, 1 |
bt [codec.shadow_flag], ebx |
jc .use_shadow |
mov ebx, edx |
shr ebx, 1 |
bt [codec.shadow_flag], ebx |
jc .use_shadow |
call [ctrl.codec_read16] ;change edx !!! |
mov ecx, eax |
call [ctrl.codec_read16] ;change edx !!! |
mov ecx, eax |
.read_ok: |
mov edx, [ac_reg] |
mov [codec.regs+edx], cx |
bts [codec.shadow_flag], ebx |
mov eax, ecx |
ret |
mov edx, [ac_reg] |
mov [codec.regs+edx], cx |
bts [codec.shadow_flag], ebx |
mov eax, ecx |
ret |
.use_shadow: |
movzx eax, word [codec.regs+edx] |
ret |
movzx eax, word [codec.regs+edx] |
ret |
endp |
849,17 → 850,17 |
align 4 |
proc codec_write stdcall, ac_reg:dword |
mov esi, [ac_reg] |
mov esi, [ac_reg] |
mov edx, esi |
mov edx, esi |
call [ctrl.codec_write16] |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
shr esi, 1 |
bts [codec.shadow_flag], esi |
mov [codec.regs+esi], ax |
shr esi, 1 |
bts [codec.shadow_flag], esi |
ret |
ret |
endp |
align 4 |
866,36 → 867,36 |
proc check_semafore |
align 4 |
.ok: |
xor eax,eax |
inc eax |
ret |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
905,113 → 906,113 |
align 4 |
proc codec_io_r16 |
push edx |
mov ecx, 255 |
push edx |
mov ecx, 255 |
.L1: |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_read16] |
test ah, FM_CODEC_CMD_BUSY shr 8 |
je .L2 |
loop .L1 |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_read16] |
test ah, FM_CODEC_CMD_BUSY shr 8 |
je .L2 |
loop .L1 |
.L2: |
pop eax |
or al, FM_CODEC_CMD_READ |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_write8] |
pop eax |
or al, FM_CODEC_CMD_READ |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_write8] |
mov ecx, 255 |
mov ecx, 255 |
.L3: |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_read16] |
test ah, FM_CODEC_CMD_VALID shr 8 |
jne .L4 |
loop .L3 |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_read16] |
test ah, FM_CODEC_CMD_VALID shr 8 |
jne .L4 |
loop .L3 |
.L4: |
mov edx, FM_CODEC_DATA |
call [ctrl.ctrl_read16] |
mov edx, FM_CODEC_DATA |
call [ctrl.ctrl_read16] |
ret |
ret |
endp |
align 4 |
proc codec_io_w16 |
push edx |
push eax |
mov ecx, 255 |
push edx |
push eax |
mov ecx, 255 |
.L1: |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_read16] |
test ah, FM_CODEC_CMD_BUSY shr 8 |
je .L2 |
loop .L1 |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_read16] |
test ah, FM_CODEC_CMD_BUSY shr 8 |
je .L2 |
loop .L1 |
.L2: |
pop eax |
mov edx, FM_CODEC_DATA |
call [ctrl.ctrl_write16] |
pop eax |
mov edx, FM_CODEC_DATA |
call [ctrl.ctrl_write16] |
pop eax |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_write16] |
pop eax |
mov edx, FM_CODEC_CMD |
call [ctrl.ctrl_write16] |
ret |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
1021,7 → 1022,7 |
align 4 |
devices dd (CTRL_FM801 shl 16)+VID_FM801, msg_FM801, set_FM |
dd 0 |
dd 0 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
1037,13 → 1038,13 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
;msgNotify db 'call notify',13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgInitCtrl db 'init controller',13,10,0 |
msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer ...',0 |
msgDone db 'done',13,10,0 |
;msgReg db 'set service handler',13,10,0 |
;msgOk db 'service installed',13,10,0 |
;msgOk db 'service installed',13,10,0 |
;msgStatus db 'global status ',0 |
;msgControl db 'global control ',0 |
msgPciCmd db 'PCI command ',0 |
1057,5 → 1058,5 |
codec CODEC |
ctrl AC_CNTRL |
int_flip_flop rd 1 |
int_flip_flop rd 1 |
buffer_pgaddr rd 1 |
/kernel/trunk/drivers/imports.inc |
---|
1,95 → 1,95 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro kernel_export [name]{ |
forward |
if used name |
if DEBUG |
display 'uses: ',`name,#13,#10 |
end if |
extrn name |
end if |
} |
; all exported kernel functions and data |
kernel_export \ |
RegService,\ |
GetService,\ |
ServiceHandler,\ |
AttachIntHandler,\ |
GetIntHandler,\ |
FpuSave,\ |
FpuRestore,\ |
ReservePortArea,\ |
Boot_Log,\ |
\ |
MutexInit,\ |
MutexLock,\ |
MutexUnlock,\ |
\ |
PciApi,\ |
PciRead32,\ |
PciRead16,\ |
PciRead8,\ |
PciWrite8,\ |
PciWrite16,\ |
PciWrite32,\ |
\ |
AllocPage,\ |
AllocPages,\ |
FreePage,\ |
MapPage,\ |
MapSpace,\ |
MapIoMem,\ |
GetPgAddr,\ |
CommitPages,\ |
ReleasePages,\ |
\ |
AllocKernelSpace,\ |
FreeKernelSpace,\ |
KernelAlloc,\ |
KernelFree,\ |
UserAlloc,\ |
UserFree,\ |
Kmalloc,\ |
Kfree,\ |
CreateRingBuffer,\ |
\ |
GetPid,\ |
CreateObject,\ |
DestroyObject,\ |
CreateEvent,\ |
RaiseEvent,\ |
WaitEvent,\ |
DestroyEvent,\ |
ClearEvent,\ |
\ |
LoadCursor,\ |
SelectHwCursor,\ |
SetHwCursor,\ |
HwCursorRestore,\ |
HwCursorCreate,\ |
\ |
SysMsgBoardStr,\ |
SysMsgBoardChar,\ |
GetCurrentTask,\ |
LoadFile,\ |
SendEvent,\ |
SetMouseData,\ |
Sleep,\ |
GetTimerTicks,\ |
\ |
strncat,\ |
strncpy,\ |
strncmp,\ |
strnlen,\ |
strchr,\ |
strrchr,\ |
\ |
LFBAddress,\ |
GetDisplay,\ |
SetScreen |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro kernel_export [name]{ |
forward |
if used name |
if DEBUG |
display 'uses: ',`name,#13,#10 |
end if |
extrn name |
end if |
} |
; all exported kernel functions and data |
kernel_export \ |
RegService,\ |
GetService,\ |
ServiceHandler,\ |
AttachIntHandler,\ |
GetIntHandler,\ |
FpuSave,\ |
FpuRestore,\ |
ReservePortArea,\ |
Boot_Log,\ |
\ |
MutexInit,\ |
MutexLock,\ |
MutexUnlock,\ |
\ |
PciApi,\ |
PciRead32,\ |
PciRead16,\ |
PciRead8,\ |
PciWrite8,\ |
PciWrite16,\ |
PciWrite32,\ |
\ |
AllocPage,\ |
AllocPages,\ |
FreePage,\ |
MapPage,\ |
MapSpace,\ |
MapIoMem,\ |
GetPgAddr,\ |
CommitPages,\ |
ReleasePages,\ |
\ |
AllocKernelSpace,\ |
FreeKernelSpace,\ |
KernelAlloc,\ |
KernelFree,\ |
UserAlloc,\ |
UserFree,\ |
Kmalloc,\ |
Kfree,\ |
CreateRingBuffer,\ |
\ |
GetPid,\ |
CreateObject,\ |
DestroyObject,\ |
CreateEvent,\ |
RaiseEvent,\ |
WaitEvent,\ |
DestroyEvent,\ |
ClearEvent,\ |
\ |
LoadCursor,\ |
SelectHwCursor,\ |
SetHwCursor,\ |
HwCursorRestore,\ |
HwCursorCreate,\ |
\ |
SysMsgBoardStr,\ |
SysMsgBoardChar,\ |
GetCurrentTask,\ |
LoadFile,\ |
SendEvent,\ |
SetMouseData,\ |
Sleep,\ |
GetTimerTicks,\ |
\ |
strncat,\ |
strncpy,\ |
strncmp,\ |
strnlen,\ |
strchr,\ |
strrchr,\ |
\ |
LFBAddress,\ |
GetDisplay,\ |
SetScreen |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/infinity.asm |
---|
1,1435 → 1,1435 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Serge 2006-2008 |
; email: infinity_sound@mail.ru |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'main.inc' |
include 'imports.inc' |
CURRENT_API equ 0x0101 ;1.01 |
COMPATIBLE_API equ 0x0100 ;1.00 |
API_VERSION equ (COMPATIBLE_API shl 16) or CURRENT_API |
SOUND_VERSION equ CURRENT_API |
FORCE_MMX equ 0 ;set to 1 to force use mmx or |
FORCE_MMX_128 equ 0 ;integer sse2 extensions |
;and reduce driver size |
;USE_SSE equ 0 |
USE_SSE2_MIXER equ 0 ;floating point mixer. Disabled by default |
OS_BASE equ 0x80000000 |
CAPS_SSE2 equ 26 |
PG_SW equ 0x003 |
public START |
public service_proc |
public version |
RT_INP_EMPTY equ 0xFF000001 |
RT_OUT_EMPTY equ 0xFF000002 |
RT_INP_FULL equ 0xFF000003 |
RT_OUT_FULL equ 0xFF000004 |
EVENT_WATCHED equ 0x10000000 |
EVENT_SIGNALED equ 0x20000000 |
MANUAL_RESET equ 0x40000000 |
MANUAL_DESTROY equ 0x80000000 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_GET_POS equ 9 |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
stdcall GetService, szSound |
test eax, eax |
jz .fail |
mov [hSound], eax |
stdcall KernelAlloc, 16*512 |
test eax, eax |
jz .out_of_mem |
mov [mix_buff], eax |
mov eax, str.fd-FD_OFFSET |
mov [str.fd], eax |
mov [str.bk], eax |
if FORCE_MMX |
if FORCE_MMX_128 |
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 |
stop |
end if |
mov [mix_2_core], mmx_mix_2 |
mov [mix_3_core], mmx_mix_3 |
mov [mix_4_core], mmx_mix_4 |
end if |
if FORCE_MMX_128 |
if FORCE_MMX |
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 |
stop |
end if |
mov [mix_2_core], mmx128_mix_2 |
mov [mix_3_core], mmx128_mix_3 |
mov [mix_4_core], mmx128_mix_4 |
end if |
if 0 |
if ~(FORCE_MMX or FORCE_MMX_128) ;autodetect |
mov eax, 1 |
cpuid |
bt edx, CAPS_SSE2 |
jc .mmx128 |
;old 64-bit mmx |
mov [mix_2_core], mmx_mix_2 |
mov [mix_3_core], mmx_mix_3 |
mov [mix_4_core], mmx_mix_4 |
jmp @F |
.mmx128: ;128-bit integer sse2 extensions |
mov [mix_2_core], mmx128_mix_2 |
mov [mix_3_core], mmx128_mix_3 |
mov [mix_4_core], mmx128_mix_4 |
@@: |
end if |
end if |
stdcall set_handler, [hSound], new_mix |
mov [eng_state], SND_STOP |
stdcall RegService, szInfinity, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
.exit: |
xor eax, eax |
ret |
.out_of_mem: |
if DEBUG |
mov esi, msgMem |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
srv_calls dd service_proc.srv_getversion ; 0 |
dd service_proc.snd_create_buff ; 1 |
dd service_proc.snd_destroy_buff ; 2 |
dd service_proc.snd_setformat ; 3 |
dd service_proc.snd_getformat ; 4 |
dd service_proc.snd_reset ; 5 |
dd service_proc.snd_setpos ; 6 |
dd service_proc.snd_getpos ; 7 |
dd service_proc.snd_setbuff ; 8 |
dd service_proc.snd_out ; 9 |
dd service_proc.snd_play ; 10 |
dd service_proc.snd_stop ; 11 |
dd service_proc.snd_setvolume ; 12 |
dd service_proc.snd_getvolume ; 13 |
dd service_proc.snd_setpan ; 14 |
dd service_proc.snd_getpan ; 15 |
dd service_proc.snd_getbuffsize ; 16 |
dd service_proc.snd_getfreespace ; 17 |
dd service_proc.snd_settimebase ; 18 |
dd service_proc.snd_gettimestamp ; 19 |
srv_calls_end: |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, (srv_calls_end-srv_calls)/4 |
ja .fail |
cmp eax, SND_DESTROY_BUFF |
jb @F |
; cmp [edi+inp_size], 4 |
; jb .fali |
mov ebx, [edi+input] |
mov edx, [ebx] |
cmp [edx+STREAM.magic], 'WAVE' |
jne .fail |
cmp [edx+STREAM.size], STREAM.sizeof |
jne .fail |
@@: |
jmp [srv_calls+eax*4] |
.fail: |
mov eax, -1 |
ret |
align 4 |
.srv_getversion: |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov eax, [eax] |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
align 4 |
.snd_create_buff: |
mov ebx, [edi+input] |
stdcall CreateBuffer,[ebx],[ebx+4] |
mov edi, [ioctl] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], ebx |
ret |
align 4 |
.snd_destroy_buff: |
mov eax, edx |
call DestroyBuffer |
ret |
align 4 |
.snd_setformat: |
stdcall SetFormat, edx,[ebx+4] |
ret |
align 4 |
.snd_getformat: |
movzx eax, word [edx+STREAM.format] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], eax |
xor eax, eax |
ret |
align 4 |
.snd_reset: |
stdcall ResetBuffer,edx,[ebx+4] |
ret |
align 4 |
.snd_setpos: |
stdcall SetBufferPos,edx,[ebx+4] |
ret |
align 4 |
.snd_getpos: |
stdcall GetBufferPos, edx |
mov edi, [ioctl] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], ebx |
ret |
align 4 |
.snd_setbuff: |
mov eax, [ebx+4] |
stdcall set_buffer, edx,eax,[ebx+8],[ebx+12] |
ret |
align 4 |
.snd_out: |
mov eax, [ebx+4] |
stdcall wave_out, edx,eax,[ebx+8] |
ret |
align 4 |
.snd_play: |
stdcall play_buffer, edx,[ebx+4] |
ret |
align 4 |
.snd_stop: |
stdcall stop_buffer, edx |
ret |
align 4 |
.snd_setvolume: |
stdcall SetBufferVol,edx,[ebx+4],[ebx+8] |
ret |
align 4 |
.snd_getvolume: |
mov eax, [edi+output] |
mov ecx, [eax] |
mov eax, [eax+4] |
stdcall GetBufferVol,edx,ecx,eax |
ret |
align 4 |
.snd_setpan: |
stdcall SetBufferPan,edx,[ebx+4] |
ret |
align 4 |
.snd_getpan: |
mov eax, [edx+STREAM.pan] |
mov ebx, [edi+output] |
mov ebx, [ebx] |
mov [ebx], eax |
xor eax, eax |
ret |
align 4 |
.snd_getbuffsize: |
mov eax, [edx+STREAM.in_size] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], eax |
xor eax, eax |
ret |
align 4 |
.snd_getfreespace: |
test [edx+STREAM.format], PCM_OUT |
jz .fail |
mov ebx, [edx+STREAM.in_free] |
mov ecx, [edi+output] |
mov [ecx], ebx |
xor eax, eax |
ret |
align 4 |
.snd_settimebase: |
cmp [edi+inp_size], 12 |
jne .fail |
mov eax, [ebx] |
mov ebx, [ebx+4] |
mov dword [edx+STREAM.time_base], eax |
mov dword [edx+STREAM.time_base+4], ebx |
xor eax, eax |
ret |
.snd_gettimestamp: |
cmp [edi+out_size], 8 |
jne .fail |
pushfd |
cli |
xor ebx, ebx |
push 48 |
push ebx ; local storage |
cmp [edx+STREAM.flags], SND_STOP |
je @F |
mov eax, esp |
push edx |
push edi |
push 4 ;.out_size |
push eax ;.output |
push ebx ;.inp_size |
push ebx ;.input |
push DEV_GET_POS ;.code |
push dword [hSound] ;.handle |
mov eax, esp |
stdcall ServiceHandler, eax |
add esp, 6*4 |
pop edi |
pop edx |
test eax, eax |
jz @F |
mov dword [esp], 0 ; clear offset |
@@: |
mov edi, [edi+output] |
emms |
fild qword [edx+STREAM.time_stamp] |
fiadd dword [esp] ; primary buffer offset |
fidiv dword [esp+4] ; total_samples / frequency |
fadd qword [edx+STREAM.time_base] |
fstp qword [edi] |
add esp, 8 |
popfd |
xor eax, eax |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc CreateBuffer stdcall, format:dword, size:dword |
locals |
str dd ? |
ring_size dd ? |
ring_pages dd ? |
endl |
mov eax, [format] |
cmp ax, PCM_1_8_8 |
ja .fail |
test eax, PCM_OUT |
jnz .test_out |
test eax, PCM_RING |
jnz .test_ring |
;staic |
test eax, PCM_STATIC |
jz .test_out ;use PCM_OUT as default format |
jmp .test_ok |
.test_out: |
test eax, PCM_RING+PCM_STATIC |
jnz .fail |
or [format], PCM_OUT ;force set |
jmp .test_ok |
.test_ring: |
test eax, PCM_OUT+PCM_STATIC |
jnz .fail |
.test_ok: |
call GetPid |
mov ebx, eax |
mov eax, STREAM.sizeof |
call CreateObject |
test eax, eax |
jz .fail |
mov [str], eax |
mov ebx, [format] |
mov [eax+STREAM.format], ebx |
xor ecx, ecx |
movzx ebx, bx |
cmp ebx, 19 |
jb @f |
mov ecx, 0x80808080 |
@@: |
mov [eax+STREAM.r_silence], ecx |
shl ebx, 2 |
lea ebx, [ebx+ebx*2] ;ebx*=12 |
mov ecx, [resampler_params+ebx] |
mov edx, [resampler_params+ebx+4] |
mov esi, [resampler_params+ebx+8] |
mov [eax+STREAM.r_size],ecx |
mov [eax+STREAM.r_dt], edx |
mov [eax+STREAM.resample], esi |
xor ecx, ecx |
mov [eax+STREAM.l_vol], ecx |
mov [eax+STREAM.r_vol], ecx |
mov dword [eax+STREAM.l_amp], 0x7FFF7FFF |
mov [eax+STREAM.pan], ecx |
test [format], PCM_STATIC |
jnz .static |
; ring and waveout |
mov ebx, 0x10000 |
test [format], PCM_RING |
jz .waveout |
mov ebx, [eax+STREAM.r_size] |
add ebx, 4095 |
and ebx, -4096 |
add ebx, ebx |
.waveout: |
mov [ring_size], ebx |
mov eax, ebx |
shr ebx, 12 |
mov [ring_pages], ebx |
stdcall CreateRingBuffer, eax, PG_SW |
mov edi, [str] |
mov ecx, [ring_size] |
mov [edi+STREAM.in_base], eax |
mov [edi+STREAM.in_size], ecx |
add eax, 128 |
mov [edi+STREAM.in_wp], eax |
mov [edi+STREAM.in_rp], eax |
mov [edi+STREAM.in_count], 0 |
mov [edi+STREAM.in_free], ecx |
add eax, ecx |
mov [edi+STREAM.in_top], eax |
jmp .out_buff |
.static: |
mov ecx, [size] |
add ecx, 128 ;resampler required |
mov [eax+STREAM.in_size], ecx |
stdcall KernelAlloc, ecx |
mov edi, [str] |
mov [edi+STREAM.in_base], eax |
add eax, 128 |
mov [edi+STREAM.in_wp], eax |
mov [edi+STREAM.in_rp], eax |
mov ebx, [size] |
mov [edi+STREAM.in_count], ebx |
mov [edi+STREAM.in_free], ebx |
add eax, ebx |
mov [edi+STREAM.in_top], eax |
.out_buff: |
stdcall AllocKernelSpace, dword 128*1024 |
mov edi, [str] |
xor ebx, ebx |
mov [edi+STREAM.out_base], eax |
mov [edi+STREAM.out_wp], eax |
mov [edi+STREAM.out_rp], eax |
mov [edi+STREAM.out_count], ebx |
add eax, 64*1024 |
mov [edi+STREAM.out_top], eax |
mov dword [edi+STREAM.time_base], ebx |
mov dword [edi+STREAM.time_base+4], ebx |
mov dword [edi+STREAM.time_stamp], ebx |
mov dword [edi+STREAM.time_stamp+4], ebx |
mov dword [edi+STREAM.last_ts], ebx |
stdcall AllocPages, dword 64/4 |
mov edi, [str] |
mov ebx, [edi+STREAM.out_base] |
mov ecx, 16 |
or eax, PG_SW |
push eax |
push ebx |
call CommitPages ;eax, ebx, ecx |
mov ecx, 16 |
pop ebx |
pop eax |
add ebx, 64*1024 |
call CommitPages ;double mapped |
mov edi, [str] |
mov ecx, [edi+STREAM.in_top] |
mov edi, [edi+STREAM.in_base] |
sub ecx, edi |
xor eax, eax |
shr ecx, 2 |
cld |
rep stosd |
mov edi, [str] |
mov edi, [edi+STREAM.out_base] |
mov ecx, (64*1024)/4 |
rep stosd |
xor esi, esi |
mov ecx, MANUAL_DESTROY |
call CreateEvent |
mov ebx, [str] |
mov [ebx+STREAM.notify_event], eax |
mov [ebx+STREAM.notify_id], edx |
mov [ebx+STREAM.magic], 'WAVE' |
mov [ebx+STREAM.destroy], DestroyBuffer.destroy |
mov [ebx+STREAM.size], STREAM.sizeof |
mov [ebx+STREAM.flags], SND_STOP |
pushf |
cli |
mov eax, str.fd-FD_OFFSET |
mov edx, [eax+STREAM.str_fd] |
mov [ebx+STREAM.str_fd], edx |
mov [ebx+STREAM.str_bk], eax |
mov [eax+STREAM.str_fd], ebx |
mov [edx+STREAM.str_bk], ebx |
popf |
xor eax, eax |
ret |
.fail: |
xor ebx, ebx |
or eax, -1 |
ret |
endp |
;param |
; eax= buffer handle |
align 4 |
DestroyBuffer: |
.handle equ esp ;local |
mov [eax+STREAM.flags], SND_STOP |
.destroy: |
push eax |
pushfd |
cli |
mov ebx, [eax+STREAM.str_fd] |
mov ecx, [eax+STREAM.str_bk] |
mov [ebx+STREAM.str_bk], ecx |
mov [ecx+STREAM.str_fd], ebx |
popf |
stdcall KernelFree, [eax+STREAM.in_base] |
mov eax, [.handle] |
stdcall KernelFree, [eax+STREAM.out_base] |
pop eax ;restore stack |
call DestroyObject ;eax= stream |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
restore .handle |
align 4 |
proc SetFormat stdcall, str:dword, format:dword |
cmp word [format], PCM_1_8_8 |
ja .fail |
mov edx, [str] |
mov [edx+STREAM.flags], SND_STOP |
test [edx+STREAM.format], PCM_RING |
jnz .fail |
; mov eax,[edx+STREAM.out_base] |
; mov [edx+STREAM.out_wp], eax |
; mov [edx+STREAM.out_rp], eax |
; mov [edx+STREAM.out_count], 0 |
movzx eax, word [format] |
mov word [edx+STREAM.format], ax |
xor ebx, ebx |
cmp eax, 19 |
jb @f |
mov ebx, 0x80808080 |
@@: |
mov [edx+STREAM.r_silence], ebx |
shl eax, 2 |
lea eax, [eax+eax*2] ;eax*=12 |
mov edi, [resampler_params+eax] |
mov ecx, [resampler_params+eax+4] |
mov ebx, [resampler_params+eax+8] |
mov [edx+STREAM.r_size],edi |
mov [edx+STREAM.r_dt], ecx |
mov [edx+STREAM.resample], ebx |
mov edi, [edx+STREAM.in_base] |
mov ecx, 128/4 |
mov eax, [edx+STREAM.r_silence] |
cld |
rep stosd |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for static buffers only |
; use waveout for streams |
align 4 |
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_OUT |
jnz .fail |
mov esi, [src] |
mov edi, [offs] |
add edi, [edx+STREAM.in_base] |
add edi, 128 |
cmp edi, [edx+STREAM.in_top] |
jae .fail |
mov ecx, [size] |
lea ebx, [ecx+edi] |
sub ebx, [edx+STREAM.in_top] |
jb @F |
sub ecx, ebx |
@@: |
shr ecx, 2 |
cld |
rep movsd |
xor eax,eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for stream buffers only |
align 4 |
proc wave_out stdcall, str:dword,src:dword,size:dword |
locals |
state_saved dd ? |
fpu_state rb 528 |
endl |
mov edx, [str] |
mov eax, [edx+STREAM.format] |
test eax, PCM_OUT |
jz .fail |
cmp ax, PCM_ALL |
je .fail |
mov esi,[src] |
test esi, esi |
jz .fail |
cmp esi, OS_BASE |
jae .fail |
mov [state_saved], 0 |
.main_loop: |
mov edx, [str] |
mov ebx, [size] |
test ebx, ebx |
jz .done |
cmp [edx+STREAM.flags], SND_STOP |
jne .fill |
mov edi, [edx+STREAM.in_base] |
mov ecx, 128/4 |
mov eax, [edx+STREAM.r_silence] |
cld |
rep stosd |
mov ecx, [edx+STREAM.in_size] |
sub ecx, 128 |
mov [edx+STREAM.in_wp], edi |
mov [edx+STREAM.in_rp], edi |
mov [edx+STREAM.in_count], 0 |
mov [edx+STREAM.in_free], ecx |
mov eax,[edx+STREAM.out_base] |
mov [edx+STREAM.out_wp], eax |
mov [edx+STREAM.out_rp], eax |
mov [edx+STREAM.out_count], 0 |
.fill: |
cli |
mov ecx, [edx+STREAM.in_free] |
test ecx, ecx |
jz .wait |
cmp ecx, ebx |
jbe @F |
mov ecx, ebx |
@@: |
sub [size], ecx |
add [edx+STREAM.in_count], ecx |
sub [edx+STREAM.in_free], ecx |
shr ecx, 2 |
mov edi, [edx+STREAM.in_wp] |
mov esi, [src] |
cld |
rep movsd |
mov [src], esi |
cmp edi, [edx+STREAM.in_top] |
jb @F |
sub edi, [edx+STREAM.in_size] |
@@: |
mov [edx+STREAM.in_wp], edi |
cmp [edx+STREAM.out_count], 32768 |
jae .skip |
cmp [state_saved], 0 |
jne @F |
lea eax, [fpu_state+15] |
and eax, -16 |
call FpuSave |
mov [state_saved], 1 |
@@: |
stdcall refill, edx |
.skip: |
sti |
mov edx, [str] |
mov [edx+STREAM.flags], SND_PLAY |
cmp [eng_state], SND_PLAY |
je .main_loop |
stdcall dev_play, [hSound] |
mov [eng_state], SND_PLAY |
jmp .main_loop |
.wait: |
sti |
mov edx, [str] |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call WaitEvent ;eax ebx |
jmp .main_loop |
.done: |
cmp [state_saved], 1 |
jne @F |
lea eax, [fpu_state+15] |
and eax, -16 |
call FpuRestore |
@@: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; both static and stream |
; reset all but not clear buffers |
; flags reserved |
; RESET_INPUT equ 1 ;reserved reset and clear input buffer |
; RESET_OUTPUT equ 2 ;reserved reset and clear output buffer |
; RESET_ALL equ 3 |
align 4 |
proc ResetBuffer stdcall, str:dword, flags:dword |
mov edx, [str] |
mov [edx+STREAM.flags], SND_STOP |
mov edi, [edx+STREAM.in_base] |
mov ecx, 128/4 |
mov eax, [edx+STREAM.r_silence] |
cld |
rep stosd |
mov [edx+STREAM.in_wp], edi |
mov [edx+STREAM.in_rp], edi |
test [edx+STREAM.flags], PCM_STATIC |
jnz .static |
mov [edx+STREAM.in_count], 0 |
jmp @F |
.static: |
mov eax, [edx+STREAM.in_size] |
mov [edx+STREAM.in_count], eax |
@@: |
mov eax, [edx+STREAM.in_size] |
sub eax, 128 |
mov [edx+STREAM.in_free], eax |
xor eax, eax |
mov ebx,[edx+STREAM.out_base] |
mov [edx+STREAM.out_wp], ebx |
mov [edx+STREAM.out_rp], ebx |
mov [edx+STREAM.out_count], eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for static buffers only |
align 4 |
proc SetBufferPos stdcall, str:dword, pos:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_STATIC |
jz .fail |
mov [edx+STREAM.flags], SND_STOP |
mov eax, [pos] |
add eax, [edx+STREAM.in_base] |
mov ebx, [edx+STREAM.in_top] |
add eax, 128 |
cmp eax, ebx |
jae .fail |
mov [edx+STREAM.in_rp], eax |
sub ebx, eax |
mov [edx+STREAM.in_count], ebx |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
align 4 |
proc GetBufferPos stdcall, str:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_STATIC |
jz .fail |
mov ebx, [edx+STREAM.in_rp] |
sub ebx, [edx+STREAM.in_base] |
sub ebx, 128 |
xor eax, eax |
ret |
.fail: |
xor ebx,ebx |
or eax, -1 |
ret |
endp |
; both |
align 4 |
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword |
mov edx, [str] |
stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan] |
ret |
endp |
proc minw stdcall, arg1:dword, arg2:dword |
mov ax, word [arg1] |
cmp ax, word [arg2] |
jle @f |
mov eax, [arg2] |
@@: |
ret |
endp |
proc maxw stdcall, arg1:dword, arg2:dword |
mov ax, word [arg1] |
cmp ax, word [arg2] |
jge @f |
mov eax, [arg2] |
@@: |
ret |
endp |
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword |
locals |
_600 dd ? |
_32767 dd ? |
state rb 108 |
endl |
mov [_600], 0x44160000 ;600.0 |
mov [_32767], 32767 |
lea ebx, [state] |
fnsave [ebx] |
stdcall minw, [l_vol], [vol_max] |
stdcall maxw, eax, [vol_min] |
mov [l_vol], eax |
mov [edx+STREAM.l_vol], eax |
stdcall minw, [r_vol], [vol_max+4] |
stdcall maxw, eax, [vol_min+4] |
mov [r_vol], eax |
mov [edx+STREAM.r_vol], eax |
stdcall minw, [pan], [pan_max] |
stdcall maxw, eax, [vol_min] |
mov [edx+STREAM.pan], eax |
cmp word [edx+STREAM.pan], 0 |
jl @f |
mov ebx, [l_vol] |
sub ebx, eax |
stdcall minw, ebx, [vol_max] |
stdcall maxw, eax, [vol_min] |
mov [l_vol], eax |
jmp .calc_amp |
@@: |
mov ebx, [r_vol] |
add ebx, [pan] |
stdcall minw, ebx, [vol_max+4] |
stdcall maxw, eax, [vol_min+4] |
mov [r_vol], eax |
.calc_amp: |
emms |
fild word [l_vol] |
call .calc |
fistp word [edx+STREAM.l_amp] |
fstp dword [edx+STREAM.l_amp_f] |
fstp st0 |
fild word [r_vol] |
call .calc |
fistp word [edx+STREAM.r_amp] |
fstp dword [edx+STREAM.r_amp_f] |
fstp st0 |
fnclex |
lea ebx, [state] |
frstor [ebx] |
xor eax, eax |
inc eax |
ret |
.calc: |
fdiv dword [_600] |
fld st0 |
frndint |
fxch st1 |
fsub st, st1 |
f2xm1 |
fld1 |
faddp st1, st0 |
fscale |
fld st0 |
fimul dword [_32767] |
ret 0 |
endp |
align 4 |
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword |
mov edx, [str] |
mov eax, [p_lvol] |
movsx ecx, word [edx+STREAM.l_vol] |
mov [eax], ecx |
mov eax, [p_rvol] |
movsx ecx, word [edx+STREAM.r_vol] |
mov [eax], ecx |
xor eax, eax |
ret |
endp |
align 4 |
proc SetBufferPan stdcall, str:dword,pan:dword |
mov edx, [str] |
stdcall set_vol_param,[edx+STREAM.l_vol],\ |
[edx+STREAM.r_vol],[pan] |
ret |
endp |
; for static and ring buffers only |
align 4 |
proc play_buffer stdcall, str:dword, flags:dword |
mov ebx, [str] |
mov eax, [ebx+STREAM.format] |
test eax, PCM_OUT |
jnz .fail |
cmp ax, PCM_ALL |
je .fail |
mov [ebx+STREAM.flags], SND_PLAY |
cmp [eng_state], SND_PLAY |
je .done |
stdcall dev_play, [hSound] |
mov [eng_state], SND_PLAY |
.done: |
test [flags], PLAY_SYNC |
jz @F |
mov edx, [str] |
.wait: |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call WaitEvent ;eax ebx |
mov edx, [str] |
cmp [edx+STREAM.flags], SND_STOP |
jne .wait |
@@: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for static and ring buffers only |
align 4 |
proc stop_buffer stdcall, str:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_STATIC+PCM_RING |
jz .fail |
mov [edx+STREAM.flags], SND_STOP |
; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0 |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call ClearEvent ;eax ebx |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; param |
; eax= mix_list |
align 4 |
do_mix_list: |
xor edx, edx |
mov esi, str.fd-FD_OFFSET |
mov ebx, [esi+STREAM.str_fd] |
@@: |
cmp ebx, esi |
je .done |
cmp [ebx+STREAM.magic], 'WAVE' |
jne .next |
cmp [ebx+STREAM.size], STREAM.sizeof |
jne .next |
cmp [ebx+STREAM.flags], SND_PLAY; |
jne .next |
mov ecx, [ebx+STREAM.out_count] |
test ecx, ecx |
jnz .l1 |
test [ebx+STREAM.format], PCM_RING |
jnz .next |
mov [ebx+STREAM.flags], SND_STOP |
jmp .next |
.l1: |
cmp ecx, 512 |
jae .add_buff |
mov edi, [ebx+STREAM.out_rp] |
add edi, ecx |
sub ecx, 512 |
neg ecx |
push eax |
xor eax, eax |
cld |
rep stosb |
pop eax |
mov [ebx+STREAM.out_count], 512 |
.add_buff: |
mov ecx, [ebx+STREAM.out_rp] |
mov [eax],ecx |
if USE_SSE2_MIXER |
mov edi, dword [ebx+STREAM.l_amp_f] |
mov [eax+4], edi |
mov edi, dword [ebx+STREAM.r_amp_f] |
mov [eax+8], edi |
else |
mov edi, dword [ebx+STREAM.l_amp] |
mov [eax+4], edi |
end if |
add [ebx+STREAM.out_rp], 512 |
sub [ebx+STREAM.out_count], 512 |
add eax, 12 |
inc edx |
.next: |
mov ebx, [ebx+STREAM.str_fd] |
jmp @B |
.done: |
mov eax, edx |
ret |
align 4 |
prepare_playlist: |
xor edx, edx |
mov [play_count], edx |
mov esi, str.fd-FD_OFFSET |
mov edi, [esi+STREAM.str_fd] |
@@: |
cmp edi, esi |
je .done |
cmp [edi+STREAM.magic], 'WAVE' |
jne .next |
cmp [edi+STREAM.size], STREAM.sizeof |
jne .next |
cmp [edi+STREAM.flags], SND_PLAY; |
jne .next |
mov [play_list+edx], edi |
inc [play_count] |
add edx, 4 |
.next: |
mov edi, [edi+STREAM.str_fd] |
jmp @B |
.done: |
ret |
align 4 |
proc set_handler stdcall, hsrv:dword, handler_proc:dword |
locals |
handler dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
val dd ? |
endl |
mov eax, [hsrv] |
lea ecx, [handler_proc] |
xor ebx, ebx |
mov [handler], eax |
mov [io_code], DEV_CALLBACK |
mov [input], ecx |
mov [inp_size], 4 |
mov [output], ebx |
mov [out_size], 0 |
lea eax, [handler] |
stdcall ServiceHandler, eax |
ret |
endp |
align 4 |
proc dev_play stdcall, hsrv:dword |
locals |
handle dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
val dd ? |
endl |
mov eax, [hsrv] |
xor ebx, ebx |
mov [handle], eax |
mov [io_code], DEV_PLAY |
mov [input], ebx |
mov [inp_size], ebx |
mov [output], ebx |
mov [out_size], ebx |
lea eax, [handle] |
stdcall ServiceHandler, eax |
ret |
endp |
if 0 |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
end if |
include 'mixer.asm' |
include 'mix_mmx.inc' |
include 'mix_sse2.inc' |
;if USE_SSE |
; include 'mix_sse.inc' |
;end if |
align 16 |
resampler_params: |
;r_size r_dt resampler_func |
dd 0,0,0 ; 0 PCM_ALL |
dd 16384, 0, copy_stream ; 1 PCM_2_16_48 |
dd 8192, 0, m16_stereo ; 2 PCM_1_16_48 |
dd 16384, 30109, resample_2 ; 3 PCM_2_16_44 |
dd 8192, 30109, resample_1 ; 4 PCM_1_16_44 |
dd 16384, 21846, resample_2 ; 5 PCM_2_16_32 |
dd 8192, 21846, resample_1 ; 6 PCM_1_16_32 |
dd 16384, 16384, resample_2 ; 7 PCM_2_16_24 |
dd 8192, 16384, resample_1 ; 8 PCM_1_16_24 |
dd 8192, 15052, resample_2 ; 9 PCM_2_16_22 |
dd 4096, 15052, resample_1 ;10 PCM_1_16_22 |
dd 8192, 10923, resample_2 ;11 PCM_2_16_16 |
dd 4096, 10923, resample_1 ;12 PCM_1_16_16 |
dd 8192, 8192, resample_2 ;13 PCM_2_16_12 |
dd 4096, 8192, resample_1 ;14 PCM_1_16_12 |
dd 4096, 7527, resample_2 ;15 PCM_2_16_11 |
dd 2048, 7527, resample_1 ;16 PCM_1_16_11 |
dd 4096, 5462, resample_2 ;17 PCM_2_16_8 |
dd 2048, 5462, resample_1 ;18 PCM_1_16_8 |
dd 16384, 0, s8_stereo ;19 PCM_2_8_48 |
dd 8192, 0, m8_stereo ;20 PCM_1_8_48 |
dd 8192, 30109, resample_28 ;21 PCM_2_8_44 |
dd 4096, 30109, resample_18 ;22 PCM_1_8_44 |
dd 8192, 21846, resample_28 ;23 PCM_2_8_32 |
dd 4096, 21846, resample_18 ;24 PCM_1_8_32 |
dd 8192, 16384, resample_28 ;25 PCM_2_8_24 |
dd 4096, 16384, resample_18 ;26 PCM_1_8_24 |
dd 4096, 15052, resample_28 ;27 PCM_2_8_22 |
dd 2048, 15052, resample_18 ;28 PCM_1_8_22 |
dd 4096, 10923, resample_28 ;29 PCM_2_8_16 |
dd 2048, 10923, resample_18 ;30 PCM_1_8_16 |
dd 4096, 8192, resample_28 ;31 PCM_2_8_12 |
dd 2048, 8192, resample_18 ;32 PCM_1_8_12 |
dd 2048, 7527, resample_28 ;33 PCM_2_8_11 |
dd 1024, 7527, resample_18 ;34 PCM_1_8_11 |
dd 2048, 5462, resample_28 ;35 PCM_2_8_8 |
dd 1024, 5462, resample_18 ;36 PCM_1_8_8 |
m7 dw 0x8000,0x8000,0x8000,0x8000 |
mm80 dq 0x8080808080808080 |
mm_mask dq 0xFF00FF00FF00FF00 |
vol_max dd 0x00000000,0x00000000 |
vol_min dd 0x0000D8F0,0x0000D8F0 |
pan_max dd 0x00002710,0x00002710 |
;stream_map dd 0xFFFF ; 16 |
version dd (5 shl 16) or SOUND_VERSION |
szInfinity db 'INFINITY',0 |
szSound db 'SOUND',0 |
if DEBUG |
msgFail db 'Sound service not loaded',13,10,0 |
msgPlay db 'Play buffer',13,10,0 |
msgStop db 'Stop',13,10,0 |
msgUser db 'User callback',13,10,0 |
msgMem db 'Not enough memory',13,10,0 |
msgDestroy db 'Destroy sound buffer', 13,10,0 |
msgWaveout db 'Play waveout', 13,10,0 |
msgSetVolume db 'Set volume',13,10,0 |
end if |
section '.data' data readable writable align 16 |
play_list rd 16 |
mix_input rd 16 |
play_count rd 1 |
hSound rd 1 |
eng_state rd 1 |
mix_buff rd 1 |
mix_buff_map rd 1 |
str.fd rd 1 |
str.bk rd 1 |
mix_2_core rd 1 |
mix_3_core rd 1 |
mix_4_core rd 1 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Serge 2006-2008 |
; email: infinity_sound@mail.ru |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'main.inc' |
include 'imports.inc' |
CURRENT_API equ 0x0101 ;1.01 |
COMPATIBLE_API equ 0x0100 ;1.00 |
API_VERSION equ (COMPATIBLE_API shl 16) or CURRENT_API |
SOUND_VERSION equ CURRENT_API |
FORCE_MMX equ 0 ;set to 1 to force use mmx or |
FORCE_MMX_128 equ 0 ;integer sse2 extensions |
;and reduce driver size |
;USE_SSE equ 0 |
USE_SSE2_MIXER equ 0 ;floating point mixer. Disabled by default |
OS_BASE equ 0x80000000 |
CAPS_SSE2 equ 26 |
PG_SW equ 0x003 |
public START |
public service_proc |
public version |
RT_INP_EMPTY equ 0xFF000001 |
RT_OUT_EMPTY equ 0xFF000002 |
RT_INP_FULL equ 0xFF000003 |
RT_OUT_FULL equ 0xFF000004 |
EVENT_WATCHED equ 0x10000000 |
EVENT_SIGNALED equ 0x20000000 |
MANUAL_RESET equ 0x40000000 |
MANUAL_DESTROY equ 0x80000000 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_GET_POS equ 9 |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
stdcall GetService, szSound |
test eax, eax |
jz .fail |
mov [hSound], eax |
stdcall KernelAlloc, 16*512 |
test eax, eax |
jz .out_of_mem |
mov [mix_buff], eax |
mov eax, str.fd-FD_OFFSET |
mov [str.fd], eax |
mov [str.bk], eax |
if FORCE_MMX |
if FORCE_MMX_128 |
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 |
stop |
end if |
mov [mix_2_core], mmx_mix_2 |
mov [mix_3_core], mmx_mix_3 |
mov [mix_4_core], mmx_mix_4 |
end if |
if FORCE_MMX_128 |
if FORCE_MMX |
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 |
stop |
end if |
mov [mix_2_core], mmx128_mix_2 |
mov [mix_3_core], mmx128_mix_3 |
mov [mix_4_core], mmx128_mix_4 |
end if |
if 0 |
if ~(FORCE_MMX or FORCE_MMX_128) ;autodetect |
mov eax, 1 |
cpuid |
bt edx, CAPS_SSE2 |
jc .mmx128 |
;old 64-bit mmx |
mov [mix_2_core], mmx_mix_2 |
mov [mix_3_core], mmx_mix_3 |
mov [mix_4_core], mmx_mix_4 |
jmp @F |
.mmx128: ;128-bit integer sse2 extensions |
mov [mix_2_core], mmx128_mix_2 |
mov [mix_3_core], mmx128_mix_3 |
mov [mix_4_core], mmx128_mix_4 |
@@: |
end if |
end if |
stdcall set_handler, [hSound], new_mix |
mov [eng_state], SND_STOP |
stdcall RegService, szInfinity, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
.exit: |
xor eax, eax |
ret |
.out_of_mem: |
if DEBUG |
mov esi, msgMem |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
srv_calls dd service_proc.srv_getversion ; 0 |
dd service_proc.snd_create_buff ; 1 |
dd service_proc.snd_destroy_buff ; 2 |
dd service_proc.snd_setformat ; 3 |
dd service_proc.snd_getformat ; 4 |
dd service_proc.snd_reset ; 5 |
dd service_proc.snd_setpos ; 6 |
dd service_proc.snd_getpos ; 7 |
dd service_proc.snd_setbuff ; 8 |
dd service_proc.snd_out ; 9 |
dd service_proc.snd_play ; 10 |
dd service_proc.snd_stop ; 11 |
dd service_proc.snd_setvolume ; 12 |
dd service_proc.snd_getvolume ; 13 |
dd service_proc.snd_setpan ; 14 |
dd service_proc.snd_getpan ; 15 |
dd service_proc.snd_getbuffsize ; 16 |
dd service_proc.snd_getfreespace ; 17 |
dd service_proc.snd_settimebase ; 18 |
dd service_proc.snd_gettimestamp ; 19 |
srv_calls_end: |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, (srv_calls_end-srv_calls)/4 |
ja .fail |
cmp eax, SND_DESTROY_BUFF |
jb @F |
; cmp [edi+inp_size], 4 |
; jb .fali |
mov ebx, [edi+input] |
mov edx, [ebx] |
cmp [edx+STREAM.magic], 'WAVE' |
jne .fail |
cmp [edx+STREAM.size], STREAM.sizeof |
jne .fail |
@@: |
jmp [srv_calls+eax*4] |
.fail: |
mov eax, -1 |
ret |
align 4 |
.srv_getversion: |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov eax, [eax] |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
align 4 |
.snd_create_buff: |
mov ebx, [edi+input] |
stdcall CreateBuffer, [ebx], [ebx+4] |
mov edi, [ioctl] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], ebx |
ret |
align 4 |
.snd_destroy_buff: |
mov eax, edx |
call DestroyBuffer |
ret |
align 4 |
.snd_setformat: |
stdcall SetFormat, edx, [ebx+4] |
ret |
align 4 |
.snd_getformat: |
movzx eax, word [edx+STREAM.format] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], eax |
xor eax, eax |
ret |
align 4 |
.snd_reset: |
stdcall ResetBuffer, edx, [ebx+4] |
ret |
align 4 |
.snd_setpos: |
stdcall SetBufferPos, edx, [ebx+4] |
ret |
align 4 |
.snd_getpos: |
stdcall GetBufferPos, edx |
mov edi, [ioctl] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], ebx |
ret |
align 4 |
.snd_setbuff: |
mov eax, [ebx+4] |
stdcall set_buffer, edx, eax, [ebx+8], [ebx+12] |
ret |
align 4 |
.snd_out: |
mov eax, [ebx+4] |
stdcall wave_out, edx, eax, [ebx+8] |
ret |
align 4 |
.snd_play: |
stdcall play_buffer, edx, [ebx+4] |
ret |
align 4 |
.snd_stop: |
stdcall stop_buffer, edx |
ret |
align 4 |
.snd_setvolume: |
stdcall SetBufferVol, edx, [ebx+4], [ebx+8] |
ret |
align 4 |
.snd_getvolume: |
mov eax, [edi+output] |
mov ecx, [eax] |
mov eax, [eax+4] |
stdcall GetBufferVol, edx, ecx, eax |
ret |
align 4 |
.snd_setpan: |
stdcall SetBufferPan, edx, [ebx+4] |
ret |
align 4 |
.snd_getpan: |
mov eax, [edx+STREAM.pan] |
mov ebx, [edi+output] |
mov ebx, [ebx] |
mov [ebx], eax |
xor eax, eax |
ret |
align 4 |
.snd_getbuffsize: |
mov eax, [edx+STREAM.in_size] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], eax |
xor eax, eax |
ret |
align 4 |
.snd_getfreespace: |
test [edx+STREAM.format], PCM_OUT |
jz .fail |
mov ebx, [edx+STREAM.in_free] |
mov ecx, [edi+output] |
mov [ecx], ebx |
xor eax, eax |
ret |
align 4 |
.snd_settimebase: |
cmp [edi+inp_size], 12 |
jne .fail |
mov eax, [ebx] |
mov ebx, [ebx+4] |
mov dword [edx+STREAM.time_base], eax |
mov dword [edx+STREAM.time_base+4], ebx |
xor eax, eax |
ret |
.snd_gettimestamp: |
cmp [edi+out_size], 8 |
jne .fail |
pushfd |
cli |
xor ebx, ebx |
push 48 |
push ebx ; local storage |
cmp [edx+STREAM.flags], SND_STOP |
je @F |
mov eax, esp |
push edx |
push edi |
push 4 ;.out_size |
push eax ;.output |
push ebx ;.inp_size |
push ebx ;.input |
push DEV_GET_POS ;.code |
push dword [hSound] ;.handle |
mov eax, esp |
stdcall ServiceHandler, eax |
add esp, 6*4 |
pop edi |
pop edx |
test eax, eax |
jz @F |
mov dword [esp], 0 ; clear offset |
@@: |
mov edi, [edi+output] |
emms |
fild qword [edx+STREAM.time_stamp] |
fiadd dword [esp] ; primary buffer offset |
fidiv dword [esp+4] ; total_samples / frequency |
fadd qword [edx+STREAM.time_base] |
fstp qword [edi] |
add esp, 8 |
popfd |
xor eax, eax |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc CreateBuffer stdcall, format:dword, size:dword |
locals |
str dd ? |
ring_size dd ? |
ring_pages dd ? |
endl |
mov eax, [format] |
cmp ax, PCM_1_8_8 |
ja .fail |
test eax, PCM_OUT |
jnz .test_out |
test eax, PCM_RING |
jnz .test_ring |
;staic |
test eax, PCM_STATIC |
jz .test_out ;use PCM_OUT as default format |
jmp .test_ok |
.test_out: |
test eax, PCM_RING+PCM_STATIC |
jnz .fail |
or [format], PCM_OUT ;force set |
jmp .test_ok |
.test_ring: |
test eax, PCM_OUT+PCM_STATIC |
jnz .fail |
.test_ok: |
call GetPid |
mov ebx, eax |
mov eax, STREAM.sizeof |
call CreateObject |
test eax, eax |
jz .fail |
mov [str], eax |
mov ebx, [format] |
mov [eax+STREAM.format], ebx |
xor ecx, ecx |
movzx ebx, bx |
cmp ebx, 19 |
jb @f |
mov ecx, 0x80808080 |
@@: |
mov [eax+STREAM.r_silence], ecx |
shl ebx, 2 |
lea ebx, [ebx+ebx*2] ;ebx*=12 |
mov ecx, [resampler_params+ebx] |
mov edx, [resampler_params+ebx+4] |
mov esi, [resampler_params+ebx+8] |
mov [eax+STREAM.r_size], ecx |
mov [eax+STREAM.r_dt], edx |
mov [eax+STREAM.resample], esi |
xor ecx, ecx |
mov [eax+STREAM.l_vol], ecx |
mov [eax+STREAM.r_vol], ecx |
mov dword [eax+STREAM.l_amp], 0x7FFF7FFF |
mov [eax+STREAM.pan], ecx |
test [format], PCM_STATIC |
jnz .static |
; ring and waveout |
mov ebx, 0x10000 |
test [format], PCM_RING |
jz .waveout |
mov ebx, [eax+STREAM.r_size] |
add ebx, 4095 |
and ebx, -4096 |
add ebx, ebx |
.waveout: |
mov [ring_size], ebx |
mov eax, ebx |
shr ebx, 12 |
mov [ring_pages], ebx |
stdcall CreateRingBuffer, eax, PG_SW |
mov edi, [str] |
mov ecx, [ring_size] |
mov [edi+STREAM.in_base], eax |
mov [edi+STREAM.in_size], ecx |
add eax, 128 |
mov [edi+STREAM.in_wp], eax |
mov [edi+STREAM.in_rp], eax |
mov [edi+STREAM.in_count], 0 |
mov [edi+STREAM.in_free], ecx |
add eax, ecx |
mov [edi+STREAM.in_top], eax |
jmp .out_buff |
.static: |
mov ecx, [size] |
add ecx, 128 ;resampler required |
mov [eax+STREAM.in_size], ecx |
stdcall KernelAlloc, ecx |
mov edi, [str] |
mov [edi+STREAM.in_base], eax |
add eax, 128 |
mov [edi+STREAM.in_wp], eax |
mov [edi+STREAM.in_rp], eax |
mov ebx, [size] |
mov [edi+STREAM.in_count], ebx |
mov [edi+STREAM.in_free], ebx |
add eax, ebx |
mov [edi+STREAM.in_top], eax |
.out_buff: |
stdcall AllocKernelSpace, dword 128*1024 |
mov edi, [str] |
xor ebx, ebx |
mov [edi+STREAM.out_base], eax |
mov [edi+STREAM.out_wp], eax |
mov [edi+STREAM.out_rp], eax |
mov [edi+STREAM.out_count], ebx |
add eax, 64*1024 |
mov [edi+STREAM.out_top], eax |
mov dword [edi+STREAM.time_base], ebx |
mov dword [edi+STREAM.time_base+4], ebx |
mov dword [edi+STREAM.time_stamp], ebx |
mov dword [edi+STREAM.time_stamp+4], ebx |
mov dword [edi+STREAM.last_ts], ebx |
stdcall AllocPages, dword 64/4 |
mov edi, [str] |
mov ebx, [edi+STREAM.out_base] |
mov ecx, 16 |
or eax, PG_SW |
push eax |
push ebx |
call CommitPages ;eax, ebx, ecx |
mov ecx, 16 |
pop ebx |
pop eax |
add ebx, 64*1024 |
call CommitPages ;double mapped |
mov edi, [str] |
mov ecx, [edi+STREAM.in_top] |
mov edi, [edi+STREAM.in_base] |
sub ecx, edi |
xor eax, eax |
shr ecx, 2 |
cld |
rep stosd |
mov edi, [str] |
mov edi, [edi+STREAM.out_base] |
mov ecx, (64*1024)/4 |
rep stosd |
xor esi, esi |
mov ecx, MANUAL_DESTROY |
call CreateEvent |
mov ebx, [str] |
mov [ebx+STREAM.notify_event], eax |
mov [ebx+STREAM.notify_id], edx |
mov [ebx+STREAM.magic], 'WAVE' |
mov [ebx+STREAM.destroy], DestroyBuffer.destroy |
mov [ebx+STREAM.size], STREAM.sizeof |
mov [ebx+STREAM.flags], SND_STOP |
pushf |
cli |
mov eax, str.fd-FD_OFFSET |
mov edx, [eax+STREAM.str_fd] |
mov [ebx+STREAM.str_fd], edx |
mov [ebx+STREAM.str_bk], eax |
mov [eax+STREAM.str_fd], ebx |
mov [edx+STREAM.str_bk], ebx |
popf |
xor eax, eax |
ret |
.fail: |
xor ebx, ebx |
or eax, -1 |
ret |
endp |
;param |
; eax= buffer handle |
align 4 |
DestroyBuffer: |
.handle equ esp ;local |
mov [eax+STREAM.flags], SND_STOP |
.destroy: |
push eax |
pushfd |
cli |
mov ebx, [eax+STREAM.str_fd] |
mov ecx, [eax+STREAM.str_bk] |
mov [ebx+STREAM.str_bk], ecx |
mov [ecx+STREAM.str_fd], ebx |
popf |
stdcall KernelFree, [eax+STREAM.in_base] |
mov eax, [.handle] |
stdcall KernelFree, [eax+STREAM.out_base] |
pop eax ;restore stack |
call DestroyObject ;eax= stream |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
restore .handle |
align 4 |
proc SetFormat stdcall, str:dword, format:dword |
cmp word [format], PCM_1_8_8 |
ja .fail |
mov edx, [str] |
mov [edx+STREAM.flags], SND_STOP |
test [edx+STREAM.format], PCM_RING |
jnz .fail |
; mov eax,[edx+STREAM.out_base] |
; mov [edx+STREAM.out_wp], eax |
; mov [edx+STREAM.out_rp], eax |
; mov [edx+STREAM.out_count], 0 |
movzx eax, word [format] |
mov word [edx+STREAM.format], ax |
xor ebx, ebx |
cmp eax, 19 |
jb @f |
mov ebx, 0x80808080 |
@@: |
mov [edx+STREAM.r_silence], ebx |
shl eax, 2 |
lea eax, [eax+eax*2] ;eax*=12 |
mov edi, [resampler_params+eax] |
mov ecx, [resampler_params+eax+4] |
mov ebx, [resampler_params+eax+8] |
mov [edx+STREAM.r_size], edi |
mov [edx+STREAM.r_dt], ecx |
mov [edx+STREAM.resample], ebx |
mov edi, [edx+STREAM.in_base] |
mov ecx, 128/4 |
mov eax, [edx+STREAM.r_silence] |
cld |
rep stosd |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for static buffers only |
; use waveout for streams |
align 4 |
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_OUT |
jnz .fail |
mov esi, [src] |
mov edi, [offs] |
add edi, [edx+STREAM.in_base] |
add edi, 128 |
cmp edi, [edx+STREAM.in_top] |
jae .fail |
mov ecx, [size] |
lea ebx, [ecx+edi] |
sub ebx, [edx+STREAM.in_top] |
jb @F |
sub ecx, ebx |
@@: |
shr ecx, 2 |
cld |
rep movsd |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for stream buffers only |
align 4 |
proc wave_out stdcall, str:dword,src:dword,size:dword |
locals |
state_saved dd ? |
fpu_state rb 528 |
endl |
mov edx, [str] |
mov eax, [edx+STREAM.format] |
test eax, PCM_OUT |
jz .fail |
cmp ax, PCM_ALL |
je .fail |
mov esi, [src] |
test esi, esi |
jz .fail |
cmp esi, OS_BASE |
jae .fail |
mov [state_saved], 0 |
.main_loop: |
mov edx, [str] |
mov ebx, [size] |
test ebx, ebx |
jz .done |
cmp [edx+STREAM.flags], SND_STOP |
jne .fill |
mov edi, [edx+STREAM.in_base] |
mov ecx, 128/4 |
mov eax, [edx+STREAM.r_silence] |
cld |
rep stosd |
mov ecx, [edx+STREAM.in_size] |
sub ecx, 128 |
mov [edx+STREAM.in_wp], edi |
mov [edx+STREAM.in_rp], edi |
mov [edx+STREAM.in_count], 0 |
mov [edx+STREAM.in_free], ecx |
mov eax, [edx+STREAM.out_base] |
mov [edx+STREAM.out_wp], eax |
mov [edx+STREAM.out_rp], eax |
mov [edx+STREAM.out_count], 0 |
.fill: |
cli |
mov ecx, [edx+STREAM.in_free] |
test ecx, ecx |
jz .wait |
cmp ecx, ebx |
jbe @F |
mov ecx, ebx |
@@: |
sub [size], ecx |
add [edx+STREAM.in_count], ecx |
sub [edx+STREAM.in_free], ecx |
shr ecx, 2 |
mov edi, [edx+STREAM.in_wp] |
mov esi, [src] |
cld |
rep movsd |
mov [src], esi |
cmp edi, [edx+STREAM.in_top] |
jb @F |
sub edi, [edx+STREAM.in_size] |
@@: |
mov [edx+STREAM.in_wp], edi |
cmp [edx+STREAM.out_count], 32768 |
jae .skip |
cmp [state_saved], 0 |
jne @F |
lea eax, [fpu_state+15] |
and eax, -16 |
call FpuSave |
mov [state_saved], 1 |
@@: |
stdcall refill, edx |
.skip: |
sti |
mov edx, [str] |
mov [edx+STREAM.flags], SND_PLAY |
cmp [eng_state], SND_PLAY |
je .main_loop |
stdcall dev_play, [hSound] |
mov [eng_state], SND_PLAY |
jmp .main_loop |
.wait: |
sti |
mov edx, [str] |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call WaitEvent ;eax ebx |
jmp .main_loop |
.done: |
cmp [state_saved], 1 |
jne @F |
lea eax, [fpu_state+15] |
and eax, -16 |
call FpuRestore |
@@: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; both static and stream |
; reset all but not clear buffers |
; flags reserved |
; RESET_INPUT equ 1 ;reserved reset and clear input buffer |
; RESET_OUTPUT equ 2 ;reserved reset and clear output buffer |
; RESET_ALL equ 3 |
align 4 |
proc ResetBuffer stdcall, str:dword, flags:dword |
mov edx, [str] |
mov [edx+STREAM.flags], SND_STOP |
mov edi, [edx+STREAM.in_base] |
mov ecx, 128/4 |
mov eax, [edx+STREAM.r_silence] |
cld |
rep stosd |
mov [edx+STREAM.in_wp], edi |
mov [edx+STREAM.in_rp], edi |
test [edx+STREAM.flags], PCM_STATIC |
jnz .static |
mov [edx+STREAM.in_count], 0 |
jmp @F |
.static: |
mov eax, [edx+STREAM.in_size] |
mov [edx+STREAM.in_count], eax |
@@: |
mov eax, [edx+STREAM.in_size] |
sub eax, 128 |
mov [edx+STREAM.in_free], eax |
xor eax, eax |
mov ebx, [edx+STREAM.out_base] |
mov [edx+STREAM.out_wp], ebx |
mov [edx+STREAM.out_rp], ebx |
mov [edx+STREAM.out_count], eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for static buffers only |
align 4 |
proc SetBufferPos stdcall, str:dword, pos:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_STATIC |
jz .fail |
mov [edx+STREAM.flags], SND_STOP |
mov eax, [pos] |
add eax, [edx+STREAM.in_base] |
mov ebx, [edx+STREAM.in_top] |
add eax, 128 |
cmp eax, ebx |
jae .fail |
mov [edx+STREAM.in_rp], eax |
sub ebx, eax |
mov [edx+STREAM.in_count], ebx |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
align 4 |
proc GetBufferPos stdcall, str:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_STATIC |
jz .fail |
mov ebx, [edx+STREAM.in_rp] |
sub ebx, [edx+STREAM.in_base] |
sub ebx, 128 |
xor eax, eax |
ret |
.fail: |
xor ebx, ebx |
or eax, -1 |
ret |
endp |
; both |
align 4 |
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword |
mov edx, [str] |
stdcall set_vol_param, [l_vol], [r_vol], [edx+STREAM.pan] |
ret |
endp |
proc minw stdcall, arg1:dword, arg2:dword |
mov ax, word [arg1] |
cmp ax, word [arg2] |
jle @f |
mov eax, [arg2] |
@@: |
ret |
endp |
proc maxw stdcall, arg1:dword, arg2:dword |
mov ax, word [arg1] |
cmp ax, word [arg2] |
jge @f |
mov eax, [arg2] |
@@: |
ret |
endp |
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword |
locals |
_600 dd ? |
_32767 dd ? |
state rb 108 |
endl |
mov [_600], 0x44160000 ;600.0 |
mov [_32767], 32767 |
lea ebx, [state] |
fnsave [ebx] |
stdcall minw, [l_vol], [vol_max] |
stdcall maxw, eax, [vol_min] |
mov [l_vol], eax |
mov [edx+STREAM.l_vol], eax |
stdcall minw, [r_vol], [vol_max+4] |
stdcall maxw, eax, [vol_min+4] |
mov [r_vol], eax |
mov [edx+STREAM.r_vol], eax |
stdcall minw, [pan], [pan_max] |
stdcall maxw, eax, [vol_min] |
mov [edx+STREAM.pan], eax |
cmp word [edx+STREAM.pan], 0 |
jl @f |
mov ebx, [l_vol] |
sub ebx, eax |
stdcall minw, ebx, [vol_max] |
stdcall maxw, eax, [vol_min] |
mov [l_vol], eax |
jmp .calc_amp |
@@: |
mov ebx, [r_vol] |
add ebx, [pan] |
stdcall minw, ebx, [vol_max+4] |
stdcall maxw, eax, [vol_min+4] |
mov [r_vol], eax |
.calc_amp: |
emms |
fild word [l_vol] |
call .calc |
fistp word [edx+STREAM.l_amp] |
fstp dword [edx+STREAM.l_amp_f] |
fstp st0 |
fild word [r_vol] |
call .calc |
fistp word [edx+STREAM.r_amp] |
fstp dword [edx+STREAM.r_amp_f] |
fstp st0 |
fnclex |
lea ebx, [state] |
frstor [ebx] |
xor eax, eax |
inc eax |
ret |
.calc: |
fdiv dword [_600] |
fld st0 |
frndint |
fxch st1 |
fsub st, st1 |
f2xm1 |
fld1 |
faddp st1, st0 |
fscale |
fld st0 |
fimul dword [_32767] |
ret 0 |
endp |
align 4 |
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword |
mov edx, [str] |
mov eax, [p_lvol] |
movsx ecx, word [edx+STREAM.l_vol] |
mov [eax], ecx |
mov eax, [p_rvol] |
movsx ecx, word [edx+STREAM.r_vol] |
mov [eax], ecx |
xor eax, eax |
ret |
endp |
align 4 |
proc SetBufferPan stdcall, str:dword,pan:dword |
mov edx, [str] |
stdcall set_vol_param, [edx+STREAM.l_vol], \ |
[edx+STREAM.r_vol],[pan] |
ret |
endp |
; for static and ring buffers only |
align 4 |
proc play_buffer stdcall, str:dword, flags:dword |
mov ebx, [str] |
mov eax, [ebx+STREAM.format] |
test eax, PCM_OUT |
jnz .fail |
cmp ax, PCM_ALL |
je .fail |
mov [ebx+STREAM.flags], SND_PLAY |
cmp [eng_state], SND_PLAY |
je .done |
stdcall dev_play, [hSound] |
mov [eng_state], SND_PLAY |
.done: |
test [flags], PLAY_SYNC |
jz @F |
mov edx, [str] |
.wait: |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call WaitEvent ;eax ebx |
mov edx, [str] |
cmp [edx+STREAM.flags], SND_STOP |
jne .wait |
@@: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for static and ring buffers only |
align 4 |
proc stop_buffer stdcall, str:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_STATIC+PCM_RING |
jz .fail |
mov [edx+STREAM.flags], SND_STOP |
; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0 |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call ClearEvent ;eax ebx |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; param |
; eax= mix_list |
align 4 |
do_mix_list: |
xor edx, edx |
mov esi, str.fd-FD_OFFSET |
mov ebx, [esi+STREAM.str_fd] |
@@: |
cmp ebx, esi |
je .done |
cmp [ebx+STREAM.magic], 'WAVE' |
jne .next |
cmp [ebx+STREAM.size], STREAM.sizeof |
jne .next |
cmp [ebx+STREAM.flags], SND_PLAY; |
jne .next |
mov ecx, [ebx+STREAM.out_count] |
test ecx, ecx |
jnz .l1 |
test [ebx+STREAM.format], PCM_RING |
jnz .next |
mov [ebx+STREAM.flags], SND_STOP |
jmp .next |
.l1: |
cmp ecx, 512 |
jae .add_buff |
mov edi, [ebx+STREAM.out_rp] |
add edi, ecx |
sub ecx, 512 |
neg ecx |
push eax |
xor eax, eax |
cld |
rep stosb |
pop eax |
mov [ebx+STREAM.out_count], 512 |
.add_buff: |
mov ecx, [ebx+STREAM.out_rp] |
mov [eax], ecx |
if USE_SSE2_MIXER |
mov edi, dword [ebx+STREAM.l_amp_f] |
mov [eax+4], edi |
mov edi, dword [ebx+STREAM.r_amp_f] |
mov [eax+8], edi |
else |
mov edi, dword [ebx+STREAM.l_amp] |
mov [eax+4], edi |
end if |
add [ebx+STREAM.out_rp], 512 |
sub [ebx+STREAM.out_count], 512 |
add eax, 12 |
inc edx |
.next: |
mov ebx, [ebx+STREAM.str_fd] |
jmp @B |
.done: |
mov eax, edx |
ret |
align 4 |
prepare_playlist: |
xor edx, edx |
mov [play_count], edx |
mov esi, str.fd-FD_OFFSET |
mov edi, [esi+STREAM.str_fd] |
@@: |
cmp edi, esi |
je .done |
cmp [edi+STREAM.magic], 'WAVE' |
jne .next |
cmp [edi+STREAM.size], STREAM.sizeof |
jne .next |
cmp [edi+STREAM.flags], SND_PLAY; |
jne .next |
mov [play_list+edx], edi |
inc [play_count] |
add edx, 4 |
.next: |
mov edi, [edi+STREAM.str_fd] |
jmp @B |
.done: |
ret |
align 4 |
proc set_handler stdcall, hsrv:dword, handler_proc:dword |
locals |
handler dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
val dd ? |
endl |
mov eax, [hsrv] |
lea ecx, [handler_proc] |
xor ebx, ebx |
mov [handler], eax |
mov [io_code], DEV_CALLBACK |
mov [input], ecx |
mov [inp_size], 4 |
mov [output], ebx |
mov [out_size], 0 |
lea eax, [handler] |
stdcall ServiceHandler, eax |
ret |
endp |
align 4 |
proc dev_play stdcall, hsrv:dword |
locals |
handle dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
val dd ? |
endl |
mov eax, [hsrv] |
xor ebx, ebx |
mov [handle], eax |
mov [io_code], DEV_PLAY |
mov [input], ebx |
mov [inp_size], ebx |
mov [output], ebx |
mov [out_size], ebx |
lea eax, [handle] |
stdcall ServiceHandler, eax |
ret |
endp |
if 0 |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
end if |
include 'mixer.asm' |
include 'mix_mmx.inc' |
include 'mix_sse2.inc' |
;if USE_SSE |
; include 'mix_sse.inc' |
;end if |
align 16 |
resampler_params: |
;r_size r_dt resampler_func |
dd 0,0,0 ; 0 PCM_ALL |
dd 16384, 0, copy_stream ; 1 PCM_2_16_48 |
dd 8192, 0, m16_stereo ; 2 PCM_1_16_48 |
dd 16384, 30109, resample_2 ; 3 PCM_2_16_44 |
dd 8192, 30109, resample_1 ; 4 PCM_1_16_44 |
dd 16384, 21846, resample_2 ; 5 PCM_2_16_32 |
dd 8192, 21846, resample_1 ; 6 PCM_1_16_32 |
dd 16384, 16384, resample_2 ; 7 PCM_2_16_24 |
dd 8192, 16384, resample_1 ; 8 PCM_1_16_24 |
dd 8192, 15052, resample_2 ; 9 PCM_2_16_22 |
dd 4096, 15052, resample_1 ;10 PCM_1_16_22 |
dd 8192, 10923, resample_2 ;11 PCM_2_16_16 |
dd 4096, 10923, resample_1 ;12 PCM_1_16_16 |
dd 8192, 8192, resample_2 ;13 PCM_2_16_12 |
dd 4096, 8192, resample_1 ;14 PCM_1_16_12 |
dd 4096, 7527, resample_2 ;15 PCM_2_16_11 |
dd 2048, 7527, resample_1 ;16 PCM_1_16_11 |
dd 4096, 5462, resample_2 ;17 PCM_2_16_8 |
dd 2048, 5462, resample_1 ;18 PCM_1_16_8 |
dd 16384, 0, s8_stereo ;19 PCM_2_8_48 |
dd 8192, 0, m8_stereo ;20 PCM_1_8_48 |
dd 8192, 30109, resample_28 ;21 PCM_2_8_44 |
dd 4096, 30109, resample_18 ;22 PCM_1_8_44 |
dd 8192, 21846, resample_28 ;23 PCM_2_8_32 |
dd 4096, 21846, resample_18 ;24 PCM_1_8_32 |
dd 8192, 16384, resample_28 ;25 PCM_2_8_24 |
dd 4096, 16384, resample_18 ;26 PCM_1_8_24 |
dd 4096, 15052, resample_28 ;27 PCM_2_8_22 |
dd 2048, 15052, resample_18 ;28 PCM_1_8_22 |
dd 4096, 10923, resample_28 ;29 PCM_2_8_16 |
dd 2048, 10923, resample_18 ;30 PCM_1_8_16 |
dd 4096, 8192, resample_28 ;31 PCM_2_8_12 |
dd 2048, 8192, resample_18 ;32 PCM_1_8_12 |
dd 2048, 7527, resample_28 ;33 PCM_2_8_11 |
dd 1024, 7527, resample_18 ;34 PCM_1_8_11 |
dd 2048, 5462, resample_28 ;35 PCM_2_8_8 |
dd 1024, 5462, resample_18 ;36 PCM_1_8_8 |
m7 dw 0x8000,0x8000,0x8000,0x8000 |
mm80 dq 0x8080808080808080 |
mm_mask dq 0xFF00FF00FF00FF00 |
vol_max dd 0x00000000,0x00000000 |
vol_min dd 0x0000D8F0,0x0000D8F0 |
pan_max dd 0x00002710,0x00002710 |
;stream_map dd 0xFFFF ; 16 |
version dd (5 shl 16) or SOUND_VERSION |
szInfinity db 'INFINITY',0 |
szSound db 'SOUND',0 |
if DEBUG |
msgFail db 'Sound service not loaded',13,10,0 |
msgPlay db 'Play buffer',13,10,0 |
msgStop db 'Stop',13,10,0 |
msgUser db 'User callback',13,10,0 |
msgMem db 'Not enough memory',13,10,0 |
msgDestroy db 'Destroy sound buffer', 13,10,0 |
msgWaveout db 'Play waveout', 13,10,0 |
msgSetVolume db 'Set volume',13,10,0 |
end if |
section '.data' data readable writable align 16 |
play_list rd 16 |
mix_input rd 16 |
play_count rd 1 |
hSound rd 1 |
eng_state rd 1 |
mix_buff rd 1 |
mix_buff_map rd 1 |
str.fd rd 1 |
str.bk rd 1 |
mix_2_core rd 1 |
mix_3_core rd 1 |
mix_4_core rd 1 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/main.inc |
---|
1,173 → 1,173 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Serge 2006-2008 |
; email: infinity_sound@mail.ru |
PLAY_SYNC equ 0x80000000 |
PCM_ALL equ 0 |
PCM_OUT equ 0x08000000 |
PCM_RING equ 0x10000000 |
PCM_STATIC equ 0x20000000 |
PCM_FLOAT equ 0x40000000 ;reserved |
PCM_FILTER equ 0x80000000 ;reserved |
PCM_2_16_48 equ 1 |
PCM_1_16_48 equ 2 |
PCM_2_16_44 equ 3 |
PCM_1_16_44 equ 4 |
PCM_2_16_32 equ 5 |
PCM_1_16_32 equ 6 |
PCM_2_16_24 equ 7 |
PCM_1_16_24 equ 8 |
PCM_2_16_22 equ 9 |
PCM_1_16_22 equ 10 |
PCM_2_16_16 equ 11 |
PCM_1_16_16 equ 12 |
PCM_2_16_12 equ 13 |
PCM_1_16_12 equ 14 |
PCM_2_16_11 equ 15 |
PCM_1_16_11 equ 16 |
PCM_2_16_8 equ 17 |
PCM_1_16_8 equ 18 |
PCM_2_8_48 equ 19 |
PCM_1_8_48 equ 20 |
PCM_2_8_44 equ 21 |
PCM_1_8_44 equ 22 |
PCM_2_8_32 equ 23 |
PCM_1_8_32 equ 24 |
PCM_2_8_24 equ 25 |
PCM_1_8_24 equ 26 |
PCM_2_8_22 equ 27 |
PCM_1_8_22 equ 28 |
PCM_2_8_16 equ 29 |
PCM_1_8_16 equ 30 |
PCM_2_8_12 equ 31 |
PCM_1_8_12 equ 32 |
PCM_2_8_11 equ 33 |
PCM_1_8_11 equ 34 |
PCM_2_8_8 equ 35 |
PCM_1_8_8 equ 36 |
SRV_GETVERSION equ 0 |
SND_CREATE_BUFF equ 1 |
SND_DESTROY_BUFF equ 2 |
SND_SETFORMAT equ 3 |
SND_GETFORMAT equ 4 |
SND_RESET equ 5 |
SND_SETPOS equ 6 |
SND_GETPOS equ 7 |
SND_SETBUFF equ 8 |
SND_OUT equ 9 |
SND_PLAY equ 10 |
SND_STOP equ 11 |
SND_SETVOLUME equ 12 |
SND_GETVOLUME equ 13 |
SND_SETPAN equ 14 |
SND_GETPAN equ 15 |
SND_GETBUFFSIZE equ 16 |
SND_GETFREESPACE equ 17 |
SND_SETTIMEBASE equ 18 |
SND_GETTIMESTAMP equ 19 |
struc STREAM |
{ |
.magic dd ? ;'WAVE' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.size dd ? |
.str_fd dd ? |
.str_bk dd ? |
.device dd ? |
.format dd ? |
.flags dd ? |
.out_base dd ? |
.out_wp dd ? |
.out_rp dd ? |
.out_count dd ? |
.out_top dd ? ;16*4 |
.in_base dd ? |
.in_size dd ? |
.in_wp dd ? |
.in_rp dd ? |
.in_count dd ? |
.in_free dd ? |
.in_top dd ? |
align 8 |
.time_base dq ? |
.time_stamp dq ? |
.last_ts dd ? |
.notify_event dd ? |
.notify_id dd ? |
.r_size dd ? |
.r_dt dd ? |
.r_silence dd ? |
.resample dd ? |
.l_vol dd ? |
.r_vol dd ? |
.l_amp dw ? |
.r_amp dw ? |
.pan dd ? |
.l_amp_f dd ? ;float point left |
.r_amp_f dd ? ;float point right |
.sizeof: |
} |
FD_OFFSET equ 24 |
virtual at 0 |
STREAM STREAM |
end virtual |
struc WAVE_HEADER |
{ .riff_id dd ? |
.riff_size dd ? |
.riff_format dd ? |
.fmt_id dd ? |
.fmt_size dd ? |
.format_tag dw ? |
.channels dw ? |
.freq dd ? |
.bytes_sec dd ? |
.block_align dw ? |
.bits_sample dw ? |
.data_id dd ? |
.data_size dd ? |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Serge 2006-2008 |
; email: infinity_sound@mail.ru |
PLAY_SYNC equ 0x80000000 |
PCM_ALL equ 0 |
PCM_OUT equ 0x08000000 |
PCM_RING equ 0x10000000 |
PCM_STATIC equ 0x20000000 |
PCM_FLOAT equ 0x40000000 ;reserved |
PCM_FILTER equ 0x80000000 ;reserved |
PCM_2_16_48 equ 1 |
PCM_1_16_48 equ 2 |
PCM_2_16_44 equ 3 |
PCM_1_16_44 equ 4 |
PCM_2_16_32 equ 5 |
PCM_1_16_32 equ 6 |
PCM_2_16_24 equ 7 |
PCM_1_16_24 equ 8 |
PCM_2_16_22 equ 9 |
PCM_1_16_22 equ 10 |
PCM_2_16_16 equ 11 |
PCM_1_16_16 equ 12 |
PCM_2_16_12 equ 13 |
PCM_1_16_12 equ 14 |
PCM_2_16_11 equ 15 |
PCM_1_16_11 equ 16 |
PCM_2_16_8 equ 17 |
PCM_1_16_8 equ 18 |
PCM_2_8_48 equ 19 |
PCM_1_8_48 equ 20 |
PCM_2_8_44 equ 21 |
PCM_1_8_44 equ 22 |
PCM_2_8_32 equ 23 |
PCM_1_8_32 equ 24 |
PCM_2_8_24 equ 25 |
PCM_1_8_24 equ 26 |
PCM_2_8_22 equ 27 |
PCM_1_8_22 equ 28 |
PCM_2_8_16 equ 29 |
PCM_1_8_16 equ 30 |
PCM_2_8_12 equ 31 |
PCM_1_8_12 equ 32 |
PCM_2_8_11 equ 33 |
PCM_1_8_11 equ 34 |
PCM_2_8_8 equ 35 |
PCM_1_8_8 equ 36 |
SRV_GETVERSION equ 0 |
SND_CREATE_BUFF equ 1 |
SND_DESTROY_BUFF equ 2 |
SND_SETFORMAT equ 3 |
SND_GETFORMAT equ 4 |
SND_RESET equ 5 |
SND_SETPOS equ 6 |
SND_GETPOS equ 7 |
SND_SETBUFF equ 8 |
SND_OUT equ 9 |
SND_PLAY equ 10 |
SND_STOP equ 11 |
SND_SETVOLUME equ 12 |
SND_GETVOLUME equ 13 |
SND_SETPAN equ 14 |
SND_GETPAN equ 15 |
SND_GETBUFFSIZE equ 16 |
SND_GETFREESPACE equ 17 |
SND_SETTIMEBASE equ 18 |
SND_GETTIMESTAMP equ 19 |
struc STREAM |
{ |
.magic dd ? ;'WAVE' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.size dd ? |
.str_fd dd ? |
.str_bk dd ? |
.device dd ? |
.format dd ? |
.flags dd ? |
.out_base dd ? |
.out_wp dd ? |
.out_rp dd ? |
.out_count dd ? |
.out_top dd ? ;16*4 |
.in_base dd ? |
.in_size dd ? |
.in_wp dd ? |
.in_rp dd ? |
.in_count dd ? |
.in_free dd ? |
.in_top dd ? |
align 8 |
.time_base dq ? |
.time_stamp dq ? |
.last_ts dd ? |
.notify_event dd ? |
.notify_id dd ? |
.r_size dd ? |
.r_dt dd ? |
.r_silence dd ? |
.resample dd ? |
.l_vol dd ? |
.r_vol dd ? |
.l_amp dw ? |
.r_amp dw ? |
.pan dd ? |
.l_amp_f dd ? ;float point left |
.r_amp_f dd ? ;float point right |
.sizeof: |
} |
FD_OFFSET equ 24 |
virtual at 0 |
STREAM STREAM |
end virtual |
struc WAVE_HEADER |
{ .riff_id dd ? |
.riff_size dd ? |
.riff_format dd ? |
.fmt_id dd ? |
.fmt_size dd ? |
.format_tag dw ? |
.channels dw ? |
.freq dd ? |
.bytes_sec dd ? |
.block_align dw ? |
.bits_sample dw ? |
.data_id dd ? |
.data_size dd ? |
} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/mix_mmx.inc |
---|
1,247 → 1,247 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; params |
; edi= output |
; eax= input stream 1 |
; ebx= input stream 2 |
if used mmx_mix_2 |
align 4 |
mmx_mix_2: |
movq mm0, [eax] |
movq mm1, [eax+8] |
movq mm2, [eax+16] |
movq mm3, [eax+24] |
movq mm4, [eax+32] |
movq mm5, [eax+40] |
movq mm6, [eax+48] |
movq mm7, [eax+56] |
paddsw mm0, [ebx] |
movq [edi], mm0 |
paddsw mm1,[ebx+8] |
movq [edi+8], mm1 |
paddsw mm2, [ebx+16] |
movq [edi+16], mm2 |
paddsw mm3, [ebx+24] |
movq [edi+24], mm3 |
paddsw mm4, [ebx+32] |
movq [edi+32], mm4 |
paddsw mm5, [ebx+40] |
movq [edi+40], mm5 |
paddsw mm6, [ebx+48] |
movq [edi+48], mm6 |
paddsw mm7, [ebx+56] |
movq [edi+56], mm7 |
movq mm0, [eax+64] |
movq mm1, [eax+72] |
movq mm2, [eax+80] |
movq mm3, [eax+88] |
movq mm4, [eax+96] |
movq mm5, [eax+104] |
movq mm6, [eax+112] |
movq mm7, [eax+120] |
paddsw mm0, [ebx+64] |
movq [edi+64], mm0 |
paddsw mm1, [ebx+72] |
movq [edi+72], mm1 |
paddsw mm2, [ebx+80] |
movq [edi+80], mm2 |
paddsw mm3, [ebx+88] |
movq [edi+88], mm3 |
paddsw mm4, [ebx+96] |
movq [edi+96], mm4 |
paddsw mm5, [ecx+104] |
movq [edx+104], mm5 |
paddsw mm6, [ebx+112] |
movq [edi+112], mm6 |
paddsw mm7, [ebx+120] |
movq [edi+120], mm7 |
ret |
align 4 |
mmx_mix_3: |
movq mm0, [eax] |
movq mm1, [eax+8] |
movq mm2, [eax+16] |
movq mm3, [eax+24] |
movq mm4, [eax+32] |
movq mm5, [eax+40] |
movq mm6, [eax+48] |
movq mm7, [eax+56] |
paddsw mm0, [ebx] |
paddsw mm1, [ebx+8] |
paddsw mm2, [ebx+16] |
paddsw mm3, [ebx+24] |
paddsw mm4, [ebx+32] |
paddsw mm5, [ebx+40] |
paddsw mm6, [ebx+48] |
paddsw mm7, [ebx+56] |
paddsw mm0, [ecx] |
movq [edi], mm0 |
paddsw mm1,[ecx+8] |
movq [edi+8], mm1 |
paddsw mm2, [ecx+16] |
movq [edi+16], mm2 |
paddsw mm3, [ecx+24] |
movq [edi+24], mm3 |
paddsw mm4, [ecx+32] |
movq [edi+32], mm4 |
paddsw mm5, [ecx+40] |
movq [edi+40], mm5 |
paddsw mm6, [ecx+48] |
movq [edi+48], mm6 |
paddsw mm7, [ecx+56] |
movq [edi+56], mm7 |
movq mm0, [eax+64] |
movq mm1, [eax+72] |
movq mm2, [eax+80] |
movq mm3, [eax+88] |
movq mm4, [eax+96] |
movq mm5, [eax+104] |
movq mm6, [eax+112] |
movq mm7, [eax+120] |
paddsw mm0, [ebx+64] |
paddsw mm1, [ebx+72] |
paddsw mm2, [ebx+80] |
paddsw mm3, [ebx+88] |
paddsw mm4, [ebx+96] |
paddsw mm5, [ebx+104] |
paddsw mm6, [ebx+112] |
paddsw mm7, [ebx+120] |
paddsw mm0, [ecx+64] |
movq [edi+64], mm0 |
paddsw mm1, [ecx+72] |
movq [edi+72], mm1 |
paddsw mm2, [ecx+80] |
movq [edi+80], mm2 |
paddsw mm3, [ecx+88] |
movq [edi+88], mm3 |
paddsw mm4, [ecx+96] |
movq [edi+96], mm4 |
paddsw mm5, [ecx+104] |
movq [edi+104], mm5 |
paddsw mm6, [ecx+112] |
movq [edi+112], mm6 |
paddsw mm7, [ecx+120] |
movq [edi+120], mm7 |
ret |
align 4 |
mmx_mix_4: |
movq mm0, [eax] |
movq mm2, [eax+8] |
movq mm4, [eax+16] |
movq mm6, [eax+24] |
movq mm1, [ebx] |
movq mm3, [ebx+8] |
movq mm5, [ebx+16] |
movq mm7, [ebx+24] |
paddsw mm0, [ecx] |
paddsw mm2, [ecx+8] |
paddsw mm4, [ecx+16] |
paddsw mm6, [ecx+24] |
paddsw mm1, [edx] |
paddsw mm3, [edx+8] |
paddsw mm5, [edx+16] |
paddsw mm7, [edx+24] |
paddsw mm0, mm1 |
movq [edi], mm0 |
paddsw mm2, mm3 |
movq [edi+8], mm2 |
paddsw mm4, mm5 |
movq [edi+16], mm4 |
paddsw mm5, mm6 |
movq [edi+24], mm6 |
movq mm0, [eax+32] |
movq mm2, [eax+40] |
movq mm4, [eax+48] |
movq mm6, [eax+56] |
movq mm1, [ebx+32] |
movq mm3, [ebx+40] |
movq mm5, [ebx+48] |
movq mm7, [ebx+56] |
paddsw mm0, [ecx+32] |
paddsw mm2, [ecx+40] |
paddsw mm4, [ecx+48] |
paddsw mm6, [ecx+56] |
paddsw mm1, [edx+32] |
paddsw mm3, [edx+40] |
paddsw mm5, [edx+48] |
paddsw mm7, [edx+56] |
paddsw mm0, mm1 |
movq [edi+32], mm0 |
paddsw mm2, mm2 |
movq [edi+40], mm2 |
paddsw mm4, mm5 |
movq [edi+48], mm4 |
paddsw mm6, mm7 |
movq [edi+56], mm6 |
movq mm0, [eax+64] |
movq mm2, [eax+72] |
movq mm4, [eax+80] |
movq mm6, [eax+88] |
movq mm1, [ebx+64] |
movq mm3, [ebx+72] |
movq mm5, [ebx+80] |
movq mm7, [ebx+88] |
paddsw mm0, [ecx+64] |
paddsw mm2, [ecx+72] |
paddsw mm4, [ecx+80] |
paddsw mm6, [ecx+88] |
paddsw mm1, [edx+64] |
paddsw mm3, [edx+72] |
paddsw mm5, [edx+80] |
paddsw mm7, [edx+88] |
paddsw mm0, mm1 |
movq [edi+64], mm0 |
paddsw mm2, mm3 |
movq [edi+72], mm2 |
paddsw mm4, mm5 |
movq [edi+80], mm4 |
paddsw mm6, mm5 |
movq [edi+88], mm7 |
movq mm0, [eax+96] |
movq mm2, [eax+104] |
movq mm4, [eax+112] |
movq mm6, [eax+120] |
movq mm1, [ebx+96] |
movq mm3, [ebx+104] |
movq mm5, [ebx+112] |
movq mm7, [ebx+120] |
paddsw mm0, [ecx+96] |
paddsw mm2, [ecx+104] |
paddsw mm4, [ecx+112] |
paddsw mm6, [ecx+120] |
paddsw mm1, [edx+96] |
paddsw mm3, [edx+104] |
paddsw mm5, [edx+112] |
paddsw mm7, [edx+120] |
paddsw mm0, mm1 |
movq [eax+96], mm0 |
paddsw mm2, mm3 |
movq [edi+104], mm2 |
paddsw mm4, mm5 |
movq [edi+112], mm4 |
paddsw mm6, mm7 |
movq [edi+120], mm6 |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; params |
; edi= output |
; eax= input stream 1 |
; ebx= input stream 2 |
if used mmx_mix_2 |
align 4 |
mmx_mix_2: |
movq mm0, [eax] |
movq mm1, [eax+8] |
movq mm2, [eax+16] |
movq mm3, [eax+24] |
movq mm4, [eax+32] |
movq mm5, [eax+40] |
movq mm6, [eax+48] |
movq mm7, [eax+56] |
paddsw mm0, [ebx] |
movq [edi], mm0 |
paddsw mm1, [ebx+8] |
movq [edi+8], mm1 |
paddsw mm2, [ebx+16] |
movq [edi+16], mm2 |
paddsw mm3, [ebx+24] |
movq [edi+24], mm3 |
paddsw mm4, [ebx+32] |
movq [edi+32], mm4 |
paddsw mm5, [ebx+40] |
movq [edi+40], mm5 |
paddsw mm6, [ebx+48] |
movq [edi+48], mm6 |
paddsw mm7, [ebx+56] |
movq [edi+56], mm7 |
movq mm0, [eax+64] |
movq mm1, [eax+72] |
movq mm2, [eax+80] |
movq mm3, [eax+88] |
movq mm4, [eax+96] |
movq mm5, [eax+104] |
movq mm6, [eax+112] |
movq mm7, [eax+120] |
paddsw mm0, [ebx+64] |
movq [edi+64], mm0 |
paddsw mm1, [ebx+72] |
movq [edi+72], mm1 |
paddsw mm2, [ebx+80] |
movq [edi+80], mm2 |
paddsw mm3, [ebx+88] |
movq [edi+88], mm3 |
paddsw mm4, [ebx+96] |
movq [edi+96], mm4 |
paddsw mm5, [ecx+104] |
movq [edx+104], mm5 |
paddsw mm6, [ebx+112] |
movq [edi+112], mm6 |
paddsw mm7, [ebx+120] |
movq [edi+120], mm7 |
ret |
align 4 |
mmx_mix_3: |
movq mm0, [eax] |
movq mm1, [eax+8] |
movq mm2, [eax+16] |
movq mm3, [eax+24] |
movq mm4, [eax+32] |
movq mm5, [eax+40] |
movq mm6, [eax+48] |
movq mm7, [eax+56] |
paddsw mm0, [ebx] |
paddsw mm1, [ebx+8] |
paddsw mm2, [ebx+16] |
paddsw mm3, [ebx+24] |
paddsw mm4, [ebx+32] |
paddsw mm5, [ebx+40] |
paddsw mm6, [ebx+48] |
paddsw mm7, [ebx+56] |
paddsw mm0, [ecx] |
movq [edi], mm0 |
paddsw mm1, [ecx+8] |
movq [edi+8], mm1 |
paddsw mm2, [ecx+16] |
movq [edi+16], mm2 |
paddsw mm3, [ecx+24] |
movq [edi+24], mm3 |
paddsw mm4, [ecx+32] |
movq [edi+32], mm4 |
paddsw mm5, [ecx+40] |
movq [edi+40], mm5 |
paddsw mm6, [ecx+48] |
movq [edi+48], mm6 |
paddsw mm7, [ecx+56] |
movq [edi+56], mm7 |
movq mm0, [eax+64] |
movq mm1, [eax+72] |
movq mm2, [eax+80] |
movq mm3, [eax+88] |
movq mm4, [eax+96] |
movq mm5, [eax+104] |
movq mm6, [eax+112] |
movq mm7, [eax+120] |
paddsw mm0, [ebx+64] |
paddsw mm1, [ebx+72] |
paddsw mm2, [ebx+80] |
paddsw mm3, [ebx+88] |
paddsw mm4, [ebx+96] |
paddsw mm5, [ebx+104] |
paddsw mm6, [ebx+112] |
paddsw mm7, [ebx+120] |
paddsw mm0, [ecx+64] |
movq [edi+64], mm0 |
paddsw mm1, [ecx+72] |
movq [edi+72], mm1 |
paddsw mm2, [ecx+80] |
movq [edi+80], mm2 |
paddsw mm3, [ecx+88] |
movq [edi+88], mm3 |
paddsw mm4, [ecx+96] |
movq [edi+96], mm4 |
paddsw mm5, [ecx+104] |
movq [edi+104], mm5 |
paddsw mm6, [ecx+112] |
movq [edi+112], mm6 |
paddsw mm7, [ecx+120] |
movq [edi+120], mm7 |
ret |
align 4 |
mmx_mix_4: |
movq mm0, [eax] |
movq mm2, [eax+8] |
movq mm4, [eax+16] |
movq mm6, [eax+24] |
movq mm1, [ebx] |
movq mm3, [ebx+8] |
movq mm5, [ebx+16] |
movq mm7, [ebx+24] |
paddsw mm0, [ecx] |
paddsw mm2, [ecx+8] |
paddsw mm4, [ecx+16] |
paddsw mm6, [ecx+24] |
paddsw mm1, [edx] |
paddsw mm3, [edx+8] |
paddsw mm5, [edx+16] |
paddsw mm7, [edx+24] |
paddsw mm0, mm1 |
movq [edi], mm0 |
paddsw mm2, mm3 |
movq [edi+8], mm2 |
paddsw mm4, mm5 |
movq [edi+16], mm4 |
paddsw mm5, mm6 |
movq [edi+24], mm6 |
movq mm0, [eax+32] |
movq mm2, [eax+40] |
movq mm4, [eax+48] |
movq mm6, [eax+56] |
movq mm1, [ebx+32] |
movq mm3, [ebx+40] |
movq mm5, [ebx+48] |
movq mm7, [ebx+56] |
paddsw mm0, [ecx+32] |
paddsw mm2, [ecx+40] |
paddsw mm4, [ecx+48] |
paddsw mm6, [ecx+56] |
paddsw mm1, [edx+32] |
paddsw mm3, [edx+40] |
paddsw mm5, [edx+48] |
paddsw mm7, [edx+56] |
paddsw mm0, mm1 |
movq [edi+32], mm0 |
paddsw mm2, mm2 |
movq [edi+40], mm2 |
paddsw mm4, mm5 |
movq [edi+48], mm4 |
paddsw mm6, mm7 |
movq [edi+56], mm6 |
movq mm0, [eax+64] |
movq mm2, [eax+72] |
movq mm4, [eax+80] |
movq mm6, [eax+88] |
movq mm1, [ebx+64] |
movq mm3, [ebx+72] |
movq mm5, [ebx+80] |
movq mm7, [ebx+88] |
paddsw mm0, [ecx+64] |
paddsw mm2, [ecx+72] |
paddsw mm4, [ecx+80] |
paddsw mm6, [ecx+88] |
paddsw mm1, [edx+64] |
paddsw mm3, [edx+72] |
paddsw mm5, [edx+80] |
paddsw mm7, [edx+88] |
paddsw mm0, mm1 |
movq [edi+64], mm0 |
paddsw mm2, mm3 |
movq [edi+72], mm2 |
paddsw mm4, mm5 |
movq [edi+80], mm4 |
paddsw mm6, mm5 |
movq [edi+88], mm7 |
movq mm0, [eax+96] |
movq mm2, [eax+104] |
movq mm4, [eax+112] |
movq mm6, [eax+120] |
movq mm1, [ebx+96] |
movq mm3, [ebx+104] |
movq mm5, [ebx+112] |
movq mm7, [ebx+120] |
paddsw mm0, [ecx+96] |
paddsw mm2, [ecx+104] |
paddsw mm4, [ecx+112] |
paddsw mm6, [ecx+120] |
paddsw mm1, [edx+96] |
paddsw mm3, [edx+104] |
paddsw mm5, [edx+112] |
paddsw mm7, [edx+120] |
paddsw mm0, mm1 |
movq [eax+96], mm0 |
paddsw mm2, mm3 |
movq [edi+104], mm2 |
paddsw mm4, mm5 |
movq [edi+112], mm4 |
paddsw mm6, mm7 |
movq [edi+120], mm6 |
ret |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/mix_sse2.inc |
---|
1,145 → 1,145 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used mmx128_mix_2 |
align 4 |
mmx128_mix_2: |
prefetcht1 [eax+128] |
prefetcht1 [ebx+128] |
movaps xmm0, [eax] |
movaps xmm1, [eax+16] |
movaps xmm2, [eax+32] |
movaps xmm3, [eax+48] |
movaps xmm4, [eax+64] |
movaps xmm5, [eax+80] |
movaps xmm6, [eax+96] |
movaps xmm7, [eax+112] |
paddsw xmm0, [ebx] |
movaps [edi], xmm0 |
paddsw xmm1,[ebx+16] |
movaps [edi+16], xmm1 |
paddsw xmm2, [ebx+32] |
movaps [edi+32], xmm2 |
paddsw xmm3, [ebx+48] |
movaps [edi+48], xmm3 |
paddsw xmm4, [ebx+64] |
movaps [edi+64], xmm4 |
paddsw xmm5, [ebx+80] |
movaps [edi+80], xmm5 |
paddsw xmm6, [ebx+96] |
movaps [edi+96], xmm6 |
paddsw xmm7, [ebx+112] |
movaps [edi+112], xmm7 |
ret |
align 4 |
mmx128_mix_3: |
prefetcht1 [eax+128] |
prefetcht1 [ebx+128] |
prefetcht1 [ecx+128] |
movaps xmm0, [eax] |
movaps xmm1, [eax+16] |
movaps xmm2, [eax+32] |
movaps xmm3, [eax+48] |
movaps xmm4, [eax+64] |
movaps xmm5, [eax+80] |
movaps xmm6, [eax+96] |
movaps xmm7, [eax+112] |
paddsw xmm0, [ebx] |
paddsw xmm1, [ebx+16] |
paddsw xmm2, [ebx+32] |
paddsw xmm3, [ebx+48] |
paddsw xmm4, [ebx+64] |
paddsw xmm5, [ebx+80] |
paddsw xmm6, [ebx+96] |
paddsw xmm7, [ebx+112] |
paddsw xmm0, [ecx] |
movaps [edi], xmm0 |
paddsw xmm1, [ecx+16] |
movaps [edi+16], xmm1 |
paddsw xmm2, [ecx+32] |
movaps [edi+32], xmm2 |
paddsw xmm3, [ecx+48] |
movaps [edi+48], xmm3 |
paddsw xmm4, [ecx+64] |
movaps [edi+64], xmm4 |
paddsw xmm5, [ecx+80] |
movaps [edi+80], xmm5 |
paddsw xmm6, [ecx+96] |
movaps [edi+96], xmm6 |
paddsw xmm7, [ecx+112] |
movaps [edi+112], xmm7 |
ret |
align 4 |
mmx128_mix_4: |
prefetcht1 [eax+128] |
prefetcht1 [ebx+128] |
prefetcht1 [ecx+128] |
prefetcht1 [edx+128] |
movaps xmm0, [eax] |
movaps xmm2, [eax+16] |
movaps xmm4, [eax+32] |
movaps xmm6, [eax+48] |
movaps xmm1, [ebx] |
movaps xmm3, [ebx+16] |
movaps xmm5, [ebx+32] |
movaps xmm7, [ebx+48] |
paddsw xmm0, [ecx] |
paddsw xmm2, [ecx+16] |
paddsw xmm4, [ecx+32] |
paddsw xmm6, [ecx+48] |
paddsw xmm1, [edx] |
paddsw xmm3, [edx+16] |
paddsw xmm5, [edx+32] |
paddsw xmm7, [edx+48] |
paddsw xmm0, xmm1 |
movaps [edi], xmm0 |
paddsw xmm2, xmm3 |
movaps [edi+16], xmm2 |
paddsw xmm4, xmm5 |
movaps [edi+32], xmm4 |
paddsw xmm6, xmm7 |
movaps [edi+48], xmm6 |
movaps xmm0, [eax+64] |
movaps xmm2, [eax+80] |
movaps xmm4, [eax+96] |
movaps xmm6, [eax+112] |
movaps xmm1, [ebx+64] |
movaps xmm3, [ebx+80] |
movaps xmm5, [ebx+96] |
movaps xmm7, [ebx+112] |
paddsw xmm0, [ecx+64] |
paddsw xmm2, [ecx+80] |
paddsw xmm4, [ecx+96] |
paddsw xmm6, [ecx+112] |
paddsw xmm1, [edx+64] |
paddsw xmm3, [edx+80] |
paddsw xmm5, [edx+96] |
paddsw xmm7, [edx+112] |
paddsw xmm0, xmm1 |
movaps [edi+64], xmm0 |
paddsw xmm2, xmm3 |
movaps [edi+80], xmm2 |
paddsw xmm4, xmm5 |
movaps [edi+96], xmm4 |
paddsw xmm6, xmm7 |
movaps [edi+112], xmm6 |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used mmx128_mix_2 |
align 4 |
mmx128_mix_2: |
prefetcht1 [eax+128] |
prefetcht1 [ebx+128] |
movaps xmm0, [eax] |
movaps xmm1, [eax+16] |
movaps xmm2, [eax+32] |
movaps xmm3, [eax+48] |
movaps xmm4, [eax+64] |
movaps xmm5, [eax+80] |
movaps xmm6, [eax+96] |
movaps xmm7, [eax+112] |
paddsw xmm0, [ebx] |
movaps [edi], xmm0 |
paddsw xmm1, [ebx+16] |
movaps [edi+16], xmm1 |
paddsw xmm2, [ebx+32] |
movaps [edi+32], xmm2 |
paddsw xmm3, [ebx+48] |
movaps [edi+48], xmm3 |
paddsw xmm4, [ebx+64] |
movaps [edi+64], xmm4 |
paddsw xmm5, [ebx+80] |
movaps [edi+80], xmm5 |
paddsw xmm6, [ebx+96] |
movaps [edi+96], xmm6 |
paddsw xmm7, [ebx+112] |
movaps [edi+112], xmm7 |
ret |
align 4 |
mmx128_mix_3: |
prefetcht1 [eax+128] |
prefetcht1 [ebx+128] |
prefetcht1 [ecx+128] |
movaps xmm0, [eax] |
movaps xmm1, [eax+16] |
movaps xmm2, [eax+32] |
movaps xmm3, [eax+48] |
movaps xmm4, [eax+64] |
movaps xmm5, [eax+80] |
movaps xmm6, [eax+96] |
movaps xmm7, [eax+112] |
paddsw xmm0, [ebx] |
paddsw xmm1, [ebx+16] |
paddsw xmm2, [ebx+32] |
paddsw xmm3, [ebx+48] |
paddsw xmm4, [ebx+64] |
paddsw xmm5, [ebx+80] |
paddsw xmm6, [ebx+96] |
paddsw xmm7, [ebx+112] |
paddsw xmm0, [ecx] |
movaps [edi], xmm0 |
paddsw xmm1, [ecx+16] |
movaps [edi+16], xmm1 |
paddsw xmm2, [ecx+32] |
movaps [edi+32], xmm2 |
paddsw xmm3, [ecx+48] |
movaps [edi+48], xmm3 |
paddsw xmm4, [ecx+64] |
movaps [edi+64], xmm4 |
paddsw xmm5, [ecx+80] |
movaps [edi+80], xmm5 |
paddsw xmm6, [ecx+96] |
movaps [edi+96], xmm6 |
paddsw xmm7, [ecx+112] |
movaps [edi+112], xmm7 |
ret |
align 4 |
mmx128_mix_4: |
prefetcht1 [eax+128] |
prefetcht1 [ebx+128] |
prefetcht1 [ecx+128] |
prefetcht1 [edx+128] |
movaps xmm0, [eax] |
movaps xmm2, [eax+16] |
movaps xmm4, [eax+32] |
movaps xmm6, [eax+48] |
movaps xmm1, [ebx] |
movaps xmm3, [ebx+16] |
movaps xmm5, [ebx+32] |
movaps xmm7, [ebx+48] |
paddsw xmm0, [ecx] |
paddsw xmm2, [ecx+16] |
paddsw xmm4, [ecx+32] |
paddsw xmm6, [ecx+48] |
paddsw xmm1, [edx] |
paddsw xmm3, [edx+16] |
paddsw xmm5, [edx+32] |
paddsw xmm7, [edx+48] |
paddsw xmm0, xmm1 |
movaps [edi], xmm0 |
paddsw xmm2, xmm3 |
movaps [edi+16], xmm2 |
paddsw xmm4, xmm5 |
movaps [edi+32], xmm4 |
paddsw xmm6, xmm7 |
movaps [edi+48], xmm6 |
movaps xmm0, [eax+64] |
movaps xmm2, [eax+80] |
movaps xmm4, [eax+96] |
movaps xmm6, [eax+112] |
movaps xmm1, [ebx+64] |
movaps xmm3, [ebx+80] |
movaps xmm5, [ebx+96] |
movaps xmm7, [ebx+112] |
paddsw xmm0, [ecx+64] |
paddsw xmm2, [ecx+80] |
paddsw xmm4, [ecx+96] |
paddsw xmm6, [ecx+112] |
paddsw xmm1, [edx+64] |
paddsw xmm3, [edx+80] |
paddsw xmm5, [edx+96] |
paddsw xmm7, [edx+112] |
paddsw xmm0, xmm1 |
movaps [edi+64], xmm0 |
paddsw xmm2, xmm3 |
movaps [edi+80], xmm2 |
paddsw xmm4, xmm5 |
movaps [edi+96], xmm4 |
paddsw xmm6, xmm7 |
movaps [edi+112], xmm6 |
ret |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/mixer.asm |
---|
1,1266 → 1,1266 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; (C) copyright Serge 2006 |
; email: infinity_sound@mail.ru |
align 4 |
mix_list rd 32*3 |
align 4 |
proc new_mix stdcall, output:dword |
locals |
main_count rd 1 |
fpu_state rb 528 ;512+16 |
endl |
mov [main_count], 32 |
call prepare_playlist |
cmp [play_count], 0 |
je .clear |
lea eax, [fpu_state+16] |
and eax, -16 ;must be 16b aligned |
call FpuSave |
call update_streams |
.mix: |
lea eax, [mix_list] |
call do_mix_list |
test eax, eax |
je .done |
if USE_SSE2_MIXER |
cmp eax, 1 |
ja @F |
;use fast path |
mov edi, [output] |
lea edx, [mix_list] |
call mix_fast |
jmp .next |
@@: |
cmp eax, 2 |
ja @F |
mov edi, [output] |
lea edx, [mix_list] |
call mix_fast_2_stream |
jmp .next |
@@: |
end if |
lea ebx, [mix_list] |
stdcall mix_all, [output], ebx, eax |
.next: |
add [output], 512 |
dec [main_count] |
jnz .mix |
.exit: |
lea eax, [fpu_state+16] |
and eax, -16 |
call FpuRestore |
ret |
.done: |
mov ecx, [main_count] |
shl ecx, 7 ;ecx*= 512/4 |
mov edi, [output] |
xor eax, eax |
cld |
rep stosd |
jmp .exit |
.clear: |
mov edi, [output] |
mov ecx, 4096 |
xor eax, eax |
cld |
rep stosd |
ret |
endp |
align 4 |
proc update_streams |
locals |
stream_index dd ? |
event rd 6 |
endl |
mov [stream_index], 0 |
.l1: |
mov edx, [stream_index] |
mov esi, [play_list+edx*4] |
add dword [esi+STREAM.time_stamp], 4096 |
adc dword [esi+STREAM.time_stamp+4], 0 |
mov dword [esi+STREAM.last_ts], 0 |
mov eax, [esi+STREAM.out_rp] |
cmp eax, [esi+STREAM.out_top] |
jb @f |
sub eax, 64*1024 |
@@: |
mov [esi+STREAM.out_rp], eax |
cmp [esi+STREAM.out_count], 16384 |
ja .skip |
test [esi+STREAM.format], PCM_RING |
jnz .ring |
stdcall refill, esi |
.skip: |
inc [stream_index] |
dec [play_count] |
jnz .l1 |
ret |
.ring: |
stdcall refill_ring, esi |
jmp .skip |
endp |
align 4 |
proc refill stdcall, str:dword |
locals |
r_size rd 1 |
endl |
mov ebx, [str] |
mov edi, [ebx+STREAM.out_wp] |
cmp edi, [ebx+STREAM.out_top] |
jb @F |
sub edi, 0x10000 |
mov [ebx+STREAM.out_wp], edi |
@@: |
mov eax, [ebx+STREAM.in_count] |
test eax, eax |
jz .done |
mov ecx, [ebx+STREAM.r_size] |
cmp eax, ecx |
jle @F |
mov eax, ecx |
@@: |
mov ecx, eax |
cmp word [ebx+STREAM.format], PCM_1_16_8 |
ja @F |
shr eax, 1 ;two channles |
@@: |
test [ebx+STREAM.format], 1 ;even formats mono |
jz @F |
shr eax, 1 ;eax= samples |
@@: |
shl eax, 15 ;eax*=32768 =r_end |
mov [r_size], ecx |
mov esi, [ebx+STREAM.in_rp] |
mov edi, [ebx+STREAM.out_wp] |
stdcall [ebx+STREAM.resample], edi, esi, \ |
[ebx+STREAM.r_dt], ecx, eax |
mov ebx, [str] |
add [ebx+STREAM.out_count], eax; |
add [ebx+STREAM.out_wp], eax; |
mov eax, [ebx+STREAM.in_rp] |
mov ecx, [r_size] |
add eax, ecx |
add [ebx+STREAM.in_free], ecx |
sub [ebx+STREAM.in_count], ecx |
cmp eax, [ebx+STREAM.in_top] |
jb @f |
sub eax, [ebx+STREAM.in_size] |
@@: |
mov [ebx+STREAM.in_rp], eax |
.done: |
mov eax, [ebx+STREAM.notify_event] |
test eax, eax |
jz .exit |
mov ebx, [ebx+STREAM.notify_id] |
mov edx, EVENT_WATCHED |
xor esi, esi |
call RaiseEvent ;eax, ebx, edx, esi |
.exit: |
ret |
endp |
align 4 |
proc refill_ring stdcall, str:dword |
locals |
event rd 6 |
endl |
mov ebx, [str] |
mov edi, [ebx+STREAM.out_wp] |
cmp edi, [ebx+STREAM.out_top] |
jb @F |
sub edi, 0x10000 |
mov [ebx+STREAM.out_wp], edi |
@@: |
mov ecx, [ebx+STREAM.r_size] |
mov eax, ecx |
cmp word [ebx+STREAM.format], PCM_1_16_8 |
ja @F |
shr eax, 1 ;two channles |
@@: |
test [ebx+STREAM.format], 1 ;even formats mono |
jz @F |
shr eax, 1 ;eax= samples |
@@: |
shl eax, 15 ;eax*=32768 =r_end |
mov esi, [ebx+STREAM.in_rp] |
mov edi, [ebx+STREAM.out_wp] |
stdcall [ebx+STREAM.resample], edi, esi, \ |
[ebx+STREAM.r_dt], ecx, eax |
mov ebx, [str] |
add [ebx+STREAM.out_count], eax; |
add [ebx+STREAM.out_wp], eax; |
mov eax, [ebx+STREAM.in_rp] |
mov ecx, [ebx+STREAM.r_size] |
add eax, ecx |
add [ebx+STREAM.in_free], ecx |
sub [ebx+STREAM.in_count], ecx |
cmp eax, [ebx+STREAM.in_top] |
jb @f |
sub eax, [ebx+STREAM.in_size] |
@@: |
mov [ebx+STREAM.in_rp], eax |
sub eax, [ebx+STREAM.in_base] |
sub eax, 128 |
lea esi, [event] |
mov dword [esi], RT_INP_EMPTY |
mov dword [esi+4], 0 |
mov dword [esi+8], ebx |
mov dword [esi+12], eax |
mov eax, [ebx+STREAM.notify_event] |
test eax, eax |
jz .exit |
mov ebx, [ebx+STREAM.notify_id] |
xor edx, edx |
call RaiseEvent ;eax, ebx, edx, esi |
.exit: |
ret |
endp |
if USE_SSE2_MIXER |
align 4 |
proc mix_all stdcall, dest:dword, list:dword, count:dword |
mov edi, [dest] |
mov ebx, 32 |
.mix: |
mov edx, [list] |
mov ecx, [count] |
mov eax, [edx] |
movdqa xmm1, [eax] |
movss xmm2, [edx+4] |
movss xmm3, [edx+8] |
punpcklwd xmm0, xmm1 |
punpckhwd xmm1, xmm1 |
shufps xmm2, xmm3, 0 |
shufps xmm2, xmm2, 0x88 |
psrad xmm0, 16 |
psrad xmm1, 16 |
cvtdq2ps xmm0, xmm0 |
cvtdq2ps xmm1, xmm1 |
mulps xmm0, xmm2 |
mulps xmm1, xmm2 |
.mix_loop: |
add dword [edx], 16 |
add edx, 12 |
dec ecx |
jz @F |
mov eax, [edx] |
movdqa xmm3, [eax] |
movss xmm4, [edx+4] |
movss xmm5, [edx+8] |
punpcklwd xmm2, xmm3 |
punpckhwd xmm3, xmm3 |
shufps xmm4, xmm5, 0 |
shufps xmm4, xmm4, 0x88 |
psrad xmm2, 16 |
psrad xmm3, 16 |
cvtdq2ps xmm2, xmm2 |
cvtdq2ps xmm3, xmm3 |
mulps xmm2, xmm4 |
mulps xmm3, xmm4 |
addps xmm0, xmm2 |
addps xmm1, xmm3 |
jmp .mix_loop |
@@: |
cvtps2dq xmm0, xmm0 |
cvtps2dq xmm1, xmm1 |
packssdw xmm0, xmm0 |
packssdw xmm1, xmm1 |
punpcklqdq xmm0, xmm1 |
movntdq [edi], xmm0 |
add edi, 16 |
dec ebx |
jnz .mix |
ret |
endp |
; param |
; edi = dest |
; edx = mix_list |
align 4 |
mix_fast: |
mov ebx, 32 |
mov eax, [edx] |
movss xmm2, [edx+4] ; vol Lf |
movss xmm3, [edx+8] ; vol Rf |
shufps xmm2, xmm3, 0 ; Rf Rf Lf Lf |
shufps xmm2, xmm2, 0x88 ; volume level Rf Lf Rf Lf |
.mix: |
movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w |
add eax, 16 |
punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w |
punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w |
psrad xmm0, 16 ; R1d L1d R0d L0d |
psrad xmm1, 16 ; R3d L3d R2d L2d |
cvtdq2ps xmm0, xmm0 ; time to use all power |
cvtdq2ps xmm1, xmm1 ; of the dark side |
mulps xmm0, xmm2 ; R1f' L1f' R0f' L0f' |
mulps xmm1, xmm2 ; R3f' L3f' R2f' L2f' |
cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d' |
cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d' |
packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w' |
packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w' |
punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w' |
movntdq [edi], xmm0 |
add edi, 16 |
dec ebx |
jnz .mix |
ret |
align 4 |
mix_fast_2_stream: |
mov ebx, 32 |
mov eax, [edx] |
movss xmm4, [edx+4] ; vol Lf |
movss xmm5, [edx+8] ; vol Rf |
mov ecx, [edx+12] |
movss xmm6, [edx+16] ; vol Lf |
movss xmm7, [edx+20] ; vol Rf |
shufps xmm4, xmm5, 0 ; Rf Rf Lf Lf |
shufps xmm4, xmm4, 0x88 ; volume level Rf Lf Rf Lf |
shufps xmm6, xmm7, 0 ; Rf Rf Lf Lf |
shufps xmm6, xmm6, 0x88 ; volume level Rf Lf Rf Lf |
.mix: |
movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w |
movdqa xmm3, [ecx] ; R3w L3w R2w L2w R1w L1w R0w L0w |
add eax, 16 |
add ecx, 16 |
punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w |
punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w |
psrad xmm0, 16 ; R1d L1d R0d L0d |
psrad xmm1, 16 ; R3d L3d R2d L2d |
cvtdq2ps xmm0, xmm0 ; time to use all power |
cvtdq2ps xmm1, xmm1 ; of the dark side |
mulps xmm0, xmm4 ; R1f' L1f' R0f' L0f' |
mulps xmm1, xmm4 ; R3f' L3f' R2f' L2f' |
punpcklwd xmm2, xmm3 ; R1w R1w L1w L1W R0w R0w L0w L0w |
punpckhwd xmm3, xmm3 ; R3w R3w L3w L3w R2w R2w L2w L2w |
psrad xmm2, 16 ; R1d L1d R0d L0d |
psrad xmm3, 16 ; R3d L3d R2d L2d |
cvtdq2ps xmm2, xmm2 ; time to use all power |
cvtdq2ps xmm3, xmm3 ; of the dark side |
mulps xmm2, xmm6 ; R1f' L1f' R0f' L0f' |
mulps xmm3, xmm6 ; R3f' L3f' R2f' L2f' |
addps xmm0, xmm2 |
addps xmm1, xmm3 |
cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d' |
cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d' |
packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w' |
packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w' |
punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w' |
movntdq [edi], xmm0 |
add edi, 16 |
dec ebx |
jnz .mix |
ret |
else ; fixed point mmx version |
align 4 |
proc mix_all stdcall, dest:dword, list:dword, count:dword |
mov edi, [dest] |
mov ebx, 64 |
.mix: |
mov edx, [list] |
mov ecx, [count] |
mov eax, [edx] |
movq mm0, [eax] |
movd mm1, [edx+4] |
punpckldq mm1,mm1 |
pmulhw mm0, mm1 |
psllw mm0, 1 |
.mix_loop: |
add dword [edx], 8 |
add edx, 12 |
dec ecx |
jz @F |
mov eax, [edx] |
movq mm1, [eax] |
movd mm2, [edx+4] |
punpckldq mm2,mm2 |
pmulhw mm1, mm2 |
psllw mm1, 1 |
paddsw mm0, mm1 |
jmp .mix_loop |
@@: |
movq [edi], mm0 |
add edi, 8 |
dec ebx |
jnz .mix |
ret |
endp |
end if |
align 4 |
proc resample_1 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
; dest equ esp+8 |
; src equ esp+12 |
; r_dt equ esp+16 |
; r_size equ esp+20 |
; r_end equ esp+24 |
mov edi, [dest] |
mov edx, [src] |
sub edx, 32*2 |
mov eax, 16 |
align 4 |
.l1: |
mov ecx, eax |
mov esi, eax |
and ecx, 0x7FFF |
shr esi, 15 |
lea esi, [edx+esi*2] |
movsx ebp, word [esi] |
movsx esi, word [esi+2] |
mov ebx, 32768 |
imul esi, ecx |
sub ebx, ecx |
imul ebx, ebp |
lea ecx, [ebx+esi+16384] |
sar ecx, 15 |
cmp ecx, 32767 ; 00007fffH |
jle @f |
mov ecx, 32767 ; 00007fffH |
jmp .write |
@@: |
cmp ecx, -32768 ; ffff8000H |
jge .write |
mov ecx, -32768 ; ffff8000H |
.write: |
mov ebx, ecx |
shl ebx, 16 |
mov bx, cx |
mov [edi], ebx |
add edi, 4 |
add eax, [esp+16] |
cmp eax, [esp+24] |
jb .l1 |
mov ebp, esp |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
align 4 |
proc resample_18 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov edi, [dest] |
mov edx, [src] |
sub edx, 32 |
mov esi, 16 |
align 4 |
.l1: |
mov ecx, esi |
mov eax, esi |
and ecx, 0x7FFF |
shr eax, 15 |
lea eax, [edx+eax] |
mov bx, word [eax] |
sub bh, 0x80 |
sub bl, 0x80 |
movsx eax, bh |
shl eax,8 |
movsx ebp, bl |
shl ebp,8 |
mov ebx, 32768 |
imul eax, ecx |
sub ebx, ecx |
imul ebx, ebp |
lea ecx, [ebx+eax+16384] |
sar ecx, 15 |
cmp ecx, 32767 ; 00007fffH |
jle @f |
mov ecx, 32767 ; 00007fffH |
jmp .write |
@@: |
cmp ecx, -32768 ; ffff8000H |
jge .write |
mov ecx, -32768 ; ffff8000H |
.write: |
mov ebx, ecx |
shl ebx, 16 |
mov bx, cx |
mov [edi], ebx |
add edi, 4 |
add esi, [esp+16] |
cmp esi, [esp+24] |
jb .l1 |
mov ebp, esp |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
align 4 |
proc copy_stream stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov ecx, [r_size] |
mov eax, ecx |
shr ecx, 2 |
mov esi, [src] |
mov edi, [dest] |
cld |
rep movsd |
ret |
endp |
align 4 |
proc resample_2 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov edx, [src] |
sub edx, 32*4 |
mov edi, [dest] |
mov ebx, [r_dt] |
mov eax, 16 |
emms |
align 4 |
.l1: |
mov ecx, eax |
mov esi, eax |
and ecx, 0x7FFF |
shr esi, 15 |
lea esi, [edx+esi*4] |
movq mm0, [esi] |
movq mm1, mm0 |
movd mm2, ecx |
punpcklwd mm2, mm2 |
movq mm3, qword [m7] ;0x8000 |
psubw mm3, mm2 ; ;0x8000 - iconst |
punpckldq mm3, mm2 |
pmulhw mm0, mm3 |
pmullw mm1, mm3 |
movq mm4, mm1 |
punpcklwd mm1, mm0 |
punpckhwd mm4, mm0 |
paddd mm1, mm4 |
psrad mm1, 15 |
packssdw mm1, mm1 |
movd [edi], mm1 |
add edi, 4 |
add eax, ebx |
cmp eax, [r_end] |
jb .l1 |
emms |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
align 4 |
proc resample_28 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov edx, [src] |
sub edx, 32*2 |
mov edi, [dest] |
mov ebx, [r_dt] |
mov eax, 16 |
emms |
movq mm7,[mm80] |
movq mm6,[mm_mask] |
align 4 |
.l1: |
mov ecx, eax |
mov esi, eax |
and ecx, 0x7FFF |
shr esi, 15 |
lea esi, [edx+esi*2] |
movq mm0, [esi] |
psubb mm0,mm7 |
punpcklbw mm0,mm0 |
pand mm0,mm6 |
movq mm1, mm0 |
movd mm2, ecx |
punpcklwd mm2, mm2 |
movq mm3, qword [m7] ; // 0x8000 |
psubw mm3, mm2 ; // 0x8000 - iconst |
punpckldq mm3, mm2 |
pmulhw mm0, mm3 |
pmullw mm1, mm3 |
movq mm4, mm1 |
punpcklwd mm1, mm0 |
punpckhwd mm4, mm0 |
paddd mm1, mm4 |
psrad mm1, 15 |
packssdw mm1, mm1 |
movd [edi], mm1 |
add edi, 4 |
add eax, ebx |
cmp eax, [r_end] |
jb .l1 |
emms |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
proc m16_stereo stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov esi, [src] |
mov edi, [dest] |
mov ecx, [r_size] |
shr ecx,8 |
@@: |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
dec ecx |
jnz @b |
mov eax, [r_size] |
add eax, eax |
ret |
endp |
align 4 |
proc s8_stereo stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov esi, [src] |
mov edi, [dest] |
mov ecx, [r_size] |
shr ecx, 7 |
movq mm7, [mm80] |
movq mm6, [mm_mask] |
@@: |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
dec ecx |
jnz @b |
mov eax, [r_size] |
add eax, eax |
ret |
endp |
proc m8_stereo stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov esi, [src] |
mov edi, [dest] |
mov ecx, [r_size] |
shr ecx, 6 |
movq mm7, [mm80] |
movq mm6, [mm_mask] |
@@: |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
dec ecx |
jnz @b |
mov eax, [r_size] |
add eax, eax |
add eax, eax |
ret |
endp |
align 4 |
proc alloc_mix_buff |
bsf eax, [mix_buff_map] |
jnz .find |
xor eax, eax |
ret |
.find: |
btr [mix_buff_map], eax |
shl eax, 9 |
add eax, [mix_buff] |
ret |
endp |
align 4 |
proc m16_s_mmx |
movq mm0, [esi] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi], mm0 |
movq [edi+8], mm1 |
movq mm0, [esi+8] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+16], mm0 |
movq [edi+24], mm1 |
movq mm0, [esi+16] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+32], mm0 |
movq [edi+40], mm1 |
movq mm0, [esi+24] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+48], mm0 |
movq [edi+56], mm1 |
movq mm0, [esi+32] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+64], mm0 |
movq [edi+72], mm1 |
movq mm0, [esi+40] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+80], mm0 |
movq [edi+88], mm1 |
movq mm0, [esi+48] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+96], mm0 |
movq [edi+104], mm1 |
movq mm0, [esi+56] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+112], mm0 |
movq [edi+120], mm1 |
ret |
endp |
align 4 |
proc s8_s_mmx |
movq mm0, [esi] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi], mm0 |
movq [edi+8], mm1 |
movq mm0, [esi+8] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi+16], mm0 |
movq [edi+24], mm1 |
movq mm0, [esi+16] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi+32], mm0 |
movq [edi+40], mm1 |
movq mm0, [esi+24] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi+48], mm0 |
movq [edi+56], mm1 |
ret |
endp |
align 4 |
proc m8_s_mmx |
movq mm0, [esi] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq mm2, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm2, mm2 |
movq mm3, mm1 |
punpcklwd mm1, mm1 |
punpckhwd mm3, mm3 |
movq [edi], mm0 |
movq [edi+8], mm2 |
movq [edi+16], mm1 |
movq [edi+24], mm3 |
movq mm0, [esi+8] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq mm2, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm2, mm2 |
movq mm3, mm1 |
punpcklwd mm1, mm1 |
punpckhwd mm3, mm3 |
movq [edi+32], mm0 |
movq [edi+40], mm2 |
movq [edi+48], mm1 |
movq [edi+56], mm3 |
ret |
endp |
align 4 |
proc mix_2_1 stdcall, output:dword, str0:dword, str1:dword |
mov edi, [output] |
mov eax, [str0] |
mov ebx, [str1] |
mov esi, 128 |
call [mix_2_core] ;edi, eax, ebx |
add edi, esi |
add eax, esi |
add ebx, esi |
call [mix_2_core] ;edi, eax, ebx |
add edi, esi |
add eax, esi |
add ebx, esi |
call [mix_2_core] ;edi, eax, ebx |
add edi, esi |
add eax, esi |
add ebx, esi |
call [mix_2_core] ;edi, eax, ebx |
ret |
endp |
align 4 |
proc mix_3_1 stdcall, output:dword, str0:dword, str1:dword, str2:dword |
mov edi, [output] |
mov eax, [str0] |
mov ebx, [str1] |
mov ecx, [str2] |
mov esi, 128 |
call [mix_3_core] |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
call [mix_3_core] |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
call [mix_3_core] |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
call [mix_3_core] |
ret |
endp |
align 4 |
proc mix_4_1 stdcall, str0:dword, str1:dword,\ |
str2:dword, str3:dword |
local output:DWORD |
call alloc_mix_buff |
and eax, eax |
jz .err |
mov [output], eax |
mov edi, eax |
mov eax, [str0] |
mov ebx, [str1] |
mov ecx, [str2] |
mov edx, [str3] |
mov esi, 128 |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
mov eax, [output] |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc final_mix stdcall, output:dword, str0:dword, str1:dword,\ |
str2:dword, str3:dword |
mov edi, [output] |
mov eax, [str0] |
mov ebx, [str1] |
mov ecx, [str2] |
mov edx, [str3] |
mov esi, 128 |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
ret |
endp |
align 4 |
proc copy_mem stdcall, output:dword, input:dword |
mov edi, [output] |
mov esi, [input] |
mov ecx, 0x80 |
.l1: |
mov eax, [esi] |
mov [edi], eax |
add esi, 4 |
add edi, 4 |
loop .l1 |
ret |
endp |
proc memcpy |
@@: |
mov eax, [esi] |
mov [edi], eax |
add esi, 4 |
add edi, 4 |
dec ecx |
jnz @B |
ret |
endp |
if 0 |
align 4 |
proc new_mix stdcall, output:dword |
locals |
mixCounter dd ? |
mixIndex dd ? |
streamIndex dd ? |
inputCount dd ? |
main_count dd ? |
blockCount dd ? |
mix_out dd ? |
endl |
call prepare_playlist |
cmp [play_count], 0 |
je .exit |
call FpuSave |
mov [main_count], 32; |
.l00: |
mov [mix_buff_map], 0x0000FFFF; |
xor eax, eax |
mov [mixCounter], eax |
mov [mixIndex],eax |
mov [streamIndex], eax; |
mov ebx, [play_count] |
mov [inputCount], ebx |
.l0: |
mov ecx, 4 |
.l1: |
mov ebx, [streamIndex] |
mov esi, [play_list+ebx*4] |
mov eax, [esi+STREAM.work_read] |
add [esi+STREAM.work_read], 512 |
mov ebx, [mixIndex] |
mov [mix_input+ebx*4], eax |
inc [mixCounter] |
inc [mixIndex] |
inc [streamIndex] |
dec [inputCount] |
jz .m2 |
dec ecx |
jnz .l1 |
cmp [mixCounter], 4 |
jnz .m2 |
stdcall mix_4_1, [mix_input],[mix_input+4],[mix_input+8],[mix_input+12] |
sub [mixIndex],4 |
mov ebx, [mixIndex] |
mov [mix_input+ebx*4], eax |
inc [mixIndex] |
mov [mixCounter], 0 |
cmp [inputCount], 0 |
jnz .l0 |
.m2: |
cmp [mixIndex], 1 |
jne @f |
stdcall copy_mem, [output], [mix_input] |
jmp .m3 |
@@: |
cmp [mixIndex], 2 |
jne @f |
stdcall mix_2_1, [output], [mix_input], [mix_input+4] |
jmp .m3 |
@@: |
cmp [mixIndex], 3 |
jne @f |
stdcall mix_3_1, [output],[mix_input],[mix_input+4],[mix_input+8] |
jmp .m3 |
@@: |
stdcall final_mix, [output],[mix_input],[mix_input+4],[mix_input+8], [mix_input+12] |
.m3: |
add [output],512 |
dec [main_count] |
jnz .l00 |
call update_stream |
emms |
call FpuRestore |
ret |
.exit: |
mov edi, [output] |
mov ecx, 0x1000 |
xor eax, eax |
cld |
rep stosd |
ret |
endp |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; (C) copyright Serge 2006 |
; email: infinity_sound@mail.ru |
align 4 |
mix_list rd 32*3 |
align 4 |
proc new_mix stdcall, output:dword |
locals |
main_count rd 1 |
fpu_state rb 528 ;512+16 |
endl |
mov [main_count], 32 |
call prepare_playlist |
cmp [play_count], 0 |
je .clear |
lea eax, [fpu_state+16] |
and eax, -16 ;must be 16b aligned |
call FpuSave |
call update_streams |
.mix: |
lea eax, [mix_list] |
call do_mix_list |
test eax, eax |
je .done |
if USE_SSE2_MIXER |
cmp eax, 1 |
ja @F |
;use fast path |
mov edi, [output] |
lea edx, [mix_list] |
call mix_fast |
jmp .next |
@@: |
cmp eax, 2 |
ja @F |
mov edi, [output] |
lea edx, [mix_list] |
call mix_fast_2_stream |
jmp .next |
@@: |
end if |
lea ebx, [mix_list] |
stdcall mix_all, [output], ebx, eax |
.next: |
add [output], 512 |
dec [main_count] |
jnz .mix |
.exit: |
lea eax, [fpu_state+16] |
and eax, -16 |
call FpuRestore |
ret |
.done: |
mov ecx, [main_count] |
shl ecx, 7 ;ecx*= 512/4 |
mov edi, [output] |
xor eax, eax |
cld |
rep stosd |
jmp .exit |
.clear: |
mov edi, [output] |
mov ecx, 4096 |
xor eax, eax |
cld |
rep stosd |
ret |
endp |
align 4 |
proc update_streams |
locals |
stream_index dd ? |
event rd 6 |
endl |
mov [stream_index], 0 |
.l1: |
mov edx, [stream_index] |
mov esi, [play_list+edx*4] |
add dword [esi+STREAM.time_stamp], 4096 |
adc dword [esi+STREAM.time_stamp+4], 0 |
mov dword [esi+STREAM.last_ts], 0 |
mov eax, [esi+STREAM.out_rp] |
cmp eax, [esi+STREAM.out_top] |
jb @f |
sub eax, 64*1024 |
@@: |
mov [esi+STREAM.out_rp], eax |
cmp [esi+STREAM.out_count], 16384 |
ja .skip |
test [esi+STREAM.format], PCM_RING |
jnz .ring |
stdcall refill, esi |
.skip: |
inc [stream_index] |
dec [play_count] |
jnz .l1 |
ret |
.ring: |
stdcall refill_ring, esi |
jmp .skip |
endp |
align 4 |
proc refill stdcall, str:dword |
locals |
r_size rd 1 |
endl |
mov ebx, [str] |
mov edi, [ebx+STREAM.out_wp] |
cmp edi, [ebx+STREAM.out_top] |
jb @F |
sub edi, 0x10000 |
mov [ebx+STREAM.out_wp], edi |
@@: |
mov eax, [ebx+STREAM.in_count] |
test eax, eax |
jz .done |
mov ecx, [ebx+STREAM.r_size] |
cmp eax, ecx |
jle @F |
mov eax, ecx |
@@: |
mov ecx, eax |
cmp word [ebx+STREAM.format], PCM_1_16_8 |
ja @F |
shr eax, 1 ;two channles |
@@: |
test [ebx+STREAM.format], 1 ;even formats mono |
jz @F |
shr eax, 1 ;eax= samples |
@@: |
shl eax, 15 ;eax*=32768 =r_end |
mov [r_size], ecx |
mov esi, [ebx+STREAM.in_rp] |
mov edi, [ebx+STREAM.out_wp] |
stdcall [ebx+STREAM.resample], edi, esi, \ |
[ebx+STREAM.r_dt], ecx, eax |
mov ebx, [str] |
add [ebx+STREAM.out_count], eax; |
add [ebx+STREAM.out_wp], eax; |
mov eax, [ebx+STREAM.in_rp] |
mov ecx, [r_size] |
add eax, ecx |
add [ebx+STREAM.in_free], ecx |
sub [ebx+STREAM.in_count], ecx |
cmp eax, [ebx+STREAM.in_top] |
jb @f |
sub eax, [ebx+STREAM.in_size] |
@@: |
mov [ebx+STREAM.in_rp], eax |
.done: |
mov eax, [ebx+STREAM.notify_event] |
test eax, eax |
jz .exit |
mov ebx, [ebx+STREAM.notify_id] |
mov edx, EVENT_WATCHED |
xor esi, esi |
call RaiseEvent ;eax, ebx, edx, esi |
.exit: |
ret |
endp |
align 4 |
proc refill_ring stdcall, str:dword |
locals |
event rd 6 |
endl |
mov ebx, [str] |
mov edi, [ebx+STREAM.out_wp] |
cmp edi, [ebx+STREAM.out_top] |
jb @F |
sub edi, 0x10000 |
mov [ebx+STREAM.out_wp], edi |
@@: |
mov ecx, [ebx+STREAM.r_size] |
mov eax, ecx |
cmp word [ebx+STREAM.format], PCM_1_16_8 |
ja @F |
shr eax, 1 ;two channles |
@@: |
test [ebx+STREAM.format], 1 ;even formats mono |
jz @F |
shr eax, 1 ;eax= samples |
@@: |
shl eax, 15 ;eax*=32768 =r_end |
mov esi, [ebx+STREAM.in_rp] |
mov edi, [ebx+STREAM.out_wp] |
stdcall [ebx+STREAM.resample], edi, esi, \ |
[ebx+STREAM.r_dt], ecx, eax |
mov ebx, [str] |
add [ebx+STREAM.out_count], eax; |
add [ebx+STREAM.out_wp], eax; |
mov eax, [ebx+STREAM.in_rp] |
mov ecx, [ebx+STREAM.r_size] |
add eax, ecx |
add [ebx+STREAM.in_free], ecx |
sub [ebx+STREAM.in_count], ecx |
cmp eax, [ebx+STREAM.in_top] |
jb @f |
sub eax, [ebx+STREAM.in_size] |
@@: |
mov [ebx+STREAM.in_rp], eax |
sub eax, [ebx+STREAM.in_base] |
sub eax, 128 |
lea esi, [event] |
mov dword [esi], RT_INP_EMPTY |
mov dword [esi+4], 0 |
mov dword [esi+8], ebx |
mov dword [esi+12], eax |
mov eax, [ebx+STREAM.notify_event] |
test eax, eax |
jz .exit |
mov ebx, [ebx+STREAM.notify_id] |
xor edx, edx |
call RaiseEvent ;eax, ebx, edx, esi |
.exit: |
ret |
endp |
if USE_SSE2_MIXER |
align 4 |
proc mix_all stdcall, dest:dword, list:dword, count:dword |
mov edi, [dest] |
mov ebx, 32 |
.mix: |
mov edx, [list] |
mov ecx, [count] |
mov eax, [edx] |
movdqa xmm1, [eax] |
movss xmm2, [edx+4] |
movss xmm3, [edx+8] |
punpcklwd xmm0, xmm1 |
punpckhwd xmm1, xmm1 |
shufps xmm2, xmm3, 0 |
shufps xmm2, xmm2, 0x88 |
psrad xmm0, 16 |
psrad xmm1, 16 |
cvtdq2ps xmm0, xmm0 |
cvtdq2ps xmm1, xmm1 |
mulps xmm0, xmm2 |
mulps xmm1, xmm2 |
.mix_loop: |
add dword [edx], 16 |
add edx, 12 |
dec ecx |
jz @F |
mov eax, [edx] |
movdqa xmm3, [eax] |
movss xmm4, [edx+4] |
movss xmm5, [edx+8] |
punpcklwd xmm2, xmm3 |
punpckhwd xmm3, xmm3 |
shufps xmm4, xmm5, 0 |
shufps xmm4, xmm4, 0x88 |
psrad xmm2, 16 |
psrad xmm3, 16 |
cvtdq2ps xmm2, xmm2 |
cvtdq2ps xmm3, xmm3 |
mulps xmm2, xmm4 |
mulps xmm3, xmm4 |
addps xmm0, xmm2 |
addps xmm1, xmm3 |
jmp .mix_loop |
@@: |
cvtps2dq xmm0, xmm0 |
cvtps2dq xmm1, xmm1 |
packssdw xmm0, xmm0 |
packssdw xmm1, xmm1 |
punpcklqdq xmm0, xmm1 |
movntdq [edi], xmm0 |
add edi, 16 |
dec ebx |
jnz .mix |
ret |
endp |
; param |
; edi = dest |
; edx = mix_list |
align 4 |
mix_fast: |
mov ebx, 32 |
mov eax, [edx] |
movss xmm2, [edx+4] ; vol Lf |
movss xmm3, [edx+8] ; vol Rf |
shufps xmm2, xmm3, 0 ; Rf Rf Lf Lf |
shufps xmm2, xmm2, 0x88 ; volume level Rf Lf Rf Lf |
.mix: |
movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w |
add eax, 16 |
punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w |
punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w |
psrad xmm0, 16 ; R1d L1d R0d L0d |
psrad xmm1, 16 ; R3d L3d R2d L2d |
cvtdq2ps xmm0, xmm0 ; time to use all power |
cvtdq2ps xmm1, xmm1 ; of the dark side |
mulps xmm0, xmm2 ; R1f' L1f' R0f' L0f' |
mulps xmm1, xmm2 ; R3f' L3f' R2f' L2f' |
cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d' |
cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d' |
packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w' |
packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w' |
punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w' |
movntdq [edi], xmm0 |
add edi, 16 |
dec ebx |
jnz .mix |
ret |
align 4 |
mix_fast_2_stream: |
mov ebx, 32 |
mov eax, [edx] |
movss xmm4, [edx+4] ; vol Lf |
movss xmm5, [edx+8] ; vol Rf |
mov ecx, [edx+12] |
movss xmm6, [edx+16] ; vol Lf |
movss xmm7, [edx+20] ; vol Rf |
shufps xmm4, xmm5, 0 ; Rf Rf Lf Lf |
shufps xmm4, xmm4, 0x88 ; volume level Rf Lf Rf Lf |
shufps xmm6, xmm7, 0 ; Rf Rf Lf Lf |
shufps xmm6, xmm6, 0x88 ; volume level Rf Lf Rf Lf |
.mix: |
movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w |
movdqa xmm3, [ecx] ; R3w L3w R2w L2w R1w L1w R0w L0w |
add eax, 16 |
add ecx, 16 |
punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w |
punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w |
psrad xmm0, 16 ; R1d L1d R0d L0d |
psrad xmm1, 16 ; R3d L3d R2d L2d |
cvtdq2ps xmm0, xmm0 ; time to use all power |
cvtdq2ps xmm1, xmm1 ; of the dark side |
mulps xmm0, xmm4 ; R1f' L1f' R0f' L0f' |
mulps xmm1, xmm4 ; R3f' L3f' R2f' L2f' |
punpcklwd xmm2, xmm3 ; R1w R1w L1w L1W R0w R0w L0w L0w |
punpckhwd xmm3, xmm3 ; R3w R3w L3w L3w R2w R2w L2w L2w |
psrad xmm2, 16 ; R1d L1d R0d L0d |
psrad xmm3, 16 ; R3d L3d R2d L2d |
cvtdq2ps xmm2, xmm2 ; time to use all power |
cvtdq2ps xmm3, xmm3 ; of the dark side |
mulps xmm2, xmm6 ; R1f' L1f' R0f' L0f' |
mulps xmm3, xmm6 ; R3f' L3f' R2f' L2f' |
addps xmm0, xmm2 |
addps xmm1, xmm3 |
cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d' |
cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d' |
packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w' |
packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w' |
punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w' |
movntdq [edi], xmm0 |
add edi, 16 |
dec ebx |
jnz .mix |
ret |
else ; fixed point mmx version |
align 4 |
proc mix_all stdcall, dest:dword, list:dword, count:dword |
mov edi, [dest] |
mov ebx, 64 |
.mix: |
mov edx, [list] |
mov ecx, [count] |
mov eax, [edx] |
movq mm0, [eax] |
movd mm1, [edx+4] |
punpckldq mm1, mm1 |
pmulhw mm0, mm1 |
psllw mm0, 1 |
.mix_loop: |
add dword [edx], 8 |
add edx, 12 |
dec ecx |
jz @F |
mov eax, [edx] |
movq mm1, [eax] |
movd mm2, [edx+4] |
punpckldq mm2, mm2 |
pmulhw mm1, mm2 |
psllw mm1, 1 |
paddsw mm0, mm1 |
jmp .mix_loop |
@@: |
movq [edi], mm0 |
add edi, 8 |
dec ebx |
jnz .mix |
ret |
endp |
end if |
align 4 |
proc resample_1 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
; dest equ esp+8 |
; src equ esp+12 |
; r_dt equ esp+16 |
; r_size equ esp+20 |
; r_end equ esp+24 |
mov edi, [dest] |
mov edx, [src] |
sub edx, 32*2 |
mov eax, 16 |
align 4 |
.l1: |
mov ecx, eax |
mov esi, eax |
and ecx, 0x7FFF |
shr esi, 15 |
lea esi, [edx+esi*2] |
movsx ebp, word [esi] |
movsx esi, word [esi+2] |
mov ebx, 32768 |
imul esi, ecx |
sub ebx, ecx |
imul ebx, ebp |
lea ecx, [ebx+esi+16384] |
sar ecx, 15 |
cmp ecx, 32767 ; 00007fffH |
jle @f |
mov ecx, 32767 ; 00007fffH |
jmp .write |
@@: |
cmp ecx, -32768 ; ffff8000H |
jge .write |
mov ecx, -32768 ; ffff8000H |
.write: |
mov ebx, ecx |
shl ebx, 16 |
mov bx, cx |
mov [edi], ebx |
add edi, 4 |
add eax, [esp+16] |
cmp eax, [esp+24] |
jb .l1 |
mov ebp, esp |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
align 4 |
proc resample_18 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov edi, [dest] |
mov edx, [src] |
sub edx, 32 |
mov esi, 16 |
align 4 |
.l1: |
mov ecx, esi |
mov eax, esi |
and ecx, 0x7FFF |
shr eax, 15 |
lea eax, [edx+eax] |
mov bx, word [eax] |
sub bh, 0x80 |
sub bl, 0x80 |
movsx eax, bh |
shl eax, 8 |
movsx ebp, bl |
shl ebp, 8 |
mov ebx, 32768 |
imul eax, ecx |
sub ebx, ecx |
imul ebx, ebp |
lea ecx, [ebx+eax+16384] |
sar ecx, 15 |
cmp ecx, 32767 ; 00007fffH |
jle @f |
mov ecx, 32767 ; 00007fffH |
jmp .write |
@@: |
cmp ecx, -32768 ; ffff8000H |
jge .write |
mov ecx, -32768 ; ffff8000H |
.write: |
mov ebx, ecx |
shl ebx, 16 |
mov bx, cx |
mov [edi], ebx |
add edi, 4 |
add esi, [esp+16] |
cmp esi, [esp+24] |
jb .l1 |
mov ebp, esp |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
align 4 |
proc copy_stream stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov ecx, [r_size] |
mov eax, ecx |
shr ecx, 2 |
mov esi, [src] |
mov edi, [dest] |
cld |
rep movsd |
ret |
endp |
align 4 |
proc resample_2 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov edx, [src] |
sub edx, 32*4 |
mov edi, [dest] |
mov ebx, [r_dt] |
mov eax, 16 |
emms |
align 4 |
.l1: |
mov ecx, eax |
mov esi, eax |
and ecx, 0x7FFF |
shr esi, 15 |
lea esi, [edx+esi*4] |
movq mm0, [esi] |
movq mm1, mm0 |
movd mm2, ecx |
punpcklwd mm2, mm2 |
movq mm3, qword [m7] ;0x8000 |
psubw mm3, mm2 ; ;0x8000 - iconst |
punpckldq mm3, mm2 |
pmulhw mm0, mm3 |
pmullw mm1, mm3 |
movq mm4, mm1 |
punpcklwd mm1, mm0 |
punpckhwd mm4, mm0 |
paddd mm1, mm4 |
psrad mm1, 15 |
packssdw mm1, mm1 |
movd [edi], mm1 |
add edi, 4 |
add eax, ebx |
cmp eax, [r_end] |
jb .l1 |
emms |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
align 4 |
proc resample_28 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov edx, [src] |
sub edx, 32*2 |
mov edi, [dest] |
mov ebx, [r_dt] |
mov eax, 16 |
emms |
movq mm7, [mm80] |
movq mm6, [mm_mask] |
align 4 |
.l1: |
mov ecx, eax |
mov esi, eax |
and ecx, 0x7FFF |
shr esi, 15 |
lea esi, [edx+esi*2] |
movq mm0, [esi] |
psubb mm0, mm7 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
movq mm1, mm0 |
movd mm2, ecx |
punpcklwd mm2, mm2 |
movq mm3, qword [m7] ; // 0x8000 |
psubw mm3, mm2 ; // 0x8000 - iconst |
punpckldq mm3, mm2 |
pmulhw mm0, mm3 |
pmullw mm1, mm3 |
movq mm4, mm1 |
punpcklwd mm1, mm0 |
punpckhwd mm4, mm0 |
paddd mm1, mm4 |
psrad mm1, 15 |
packssdw mm1, mm1 |
movd [edi], mm1 |
add edi, 4 |
add eax, ebx |
cmp eax, [r_end] |
jb .l1 |
emms |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
proc m16_stereo stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov esi, [src] |
mov edi, [dest] |
mov ecx, [r_size] |
shr ecx, 8 |
@@: |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
dec ecx |
jnz @b |
mov eax, [r_size] |
add eax, eax |
ret |
endp |
align 4 |
proc s8_stereo stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov esi, [src] |
mov edi, [dest] |
mov ecx, [r_size] |
shr ecx, 7 |
movq mm7, [mm80] |
movq mm6, [mm_mask] |
@@: |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
dec ecx |
jnz @b |
mov eax, [r_size] |
add eax, eax |
ret |
endp |
proc m8_stereo stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov esi, [src] |
mov edi, [dest] |
mov ecx, [r_size] |
shr ecx, 6 |
movq mm7, [mm80] |
movq mm6, [mm_mask] |
@@: |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
dec ecx |
jnz @b |
mov eax, [r_size] |
add eax, eax |
add eax, eax |
ret |
endp |
align 4 |
proc alloc_mix_buff |
bsf eax, [mix_buff_map] |
jnz .find |
xor eax, eax |
ret |
.find: |
btr [mix_buff_map], eax |
shl eax, 9 |
add eax, [mix_buff] |
ret |
endp |
align 4 |
proc m16_s_mmx |
movq mm0, [esi] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi], mm0 |
movq [edi+8], mm1 |
movq mm0, [esi+8] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+16], mm0 |
movq [edi+24], mm1 |
movq mm0, [esi+16] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+32], mm0 |
movq [edi+40], mm1 |
movq mm0, [esi+24] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+48], mm0 |
movq [edi+56], mm1 |
movq mm0, [esi+32] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+64], mm0 |
movq [edi+72], mm1 |
movq mm0, [esi+40] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+80], mm0 |
movq [edi+88], mm1 |
movq mm0, [esi+48] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+96], mm0 |
movq [edi+104], mm1 |
movq mm0, [esi+56] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+112], mm0 |
movq [edi+120], mm1 |
ret |
endp |
align 4 |
proc s8_s_mmx |
movq mm0, [esi] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi], mm0 |
movq [edi+8], mm1 |
movq mm0, [esi+8] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi+16], mm0 |
movq [edi+24], mm1 |
movq mm0, [esi+16] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi+32], mm0 |
movq [edi+40], mm1 |
movq mm0, [esi+24] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi+48], mm0 |
movq [edi+56], mm1 |
ret |
endp |
align 4 |
proc m8_s_mmx |
movq mm0, [esi] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq mm2, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm2, mm2 |
movq mm3, mm1 |
punpcklwd mm1, mm1 |
punpckhwd mm3, mm3 |
movq [edi], mm0 |
movq [edi+8], mm2 |
movq [edi+16], mm1 |
movq [edi+24], mm3 |
movq mm0, [esi+8] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq mm2, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm2, mm2 |
movq mm3, mm1 |
punpcklwd mm1, mm1 |
punpckhwd mm3, mm3 |
movq [edi+32], mm0 |
movq [edi+40], mm2 |
movq [edi+48], mm1 |
movq [edi+56], mm3 |
ret |
endp |
align 4 |
proc mix_2_1 stdcall, output:dword, str0:dword, str1:dword |
mov edi, [output] |
mov eax, [str0] |
mov ebx, [str1] |
mov esi, 128 |
call [mix_2_core] ;edi, eax, ebx |
add edi, esi |
add eax, esi |
add ebx, esi |
call [mix_2_core] ;edi, eax, ebx |
add edi, esi |
add eax, esi |
add ebx, esi |
call [mix_2_core] ;edi, eax, ebx |
add edi, esi |
add eax, esi |
add ebx, esi |
call [mix_2_core] ;edi, eax, ebx |
ret |
endp |
align 4 |
proc mix_3_1 stdcall, output:dword, str0:dword, str1:dword, str2:dword |
mov edi, [output] |
mov eax, [str0] |
mov ebx, [str1] |
mov ecx, [str2] |
mov esi, 128 |
call [mix_3_core] |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
call [mix_3_core] |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
call [mix_3_core] |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
call [mix_3_core] |
ret |
endp |
align 4 |
proc mix_4_1 stdcall, str0:dword, str1:dword,\ |
str2:dword, str3:dword |
local output:DWORD |
call alloc_mix_buff |
and eax, eax |
jz .err |
mov [output], eax |
mov edi, eax |
mov eax, [str0] |
mov ebx, [str1] |
mov ecx, [str2] |
mov edx, [str3] |
mov esi, 128 |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
mov eax, [output] |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc final_mix stdcall, output:dword, str0:dword, str1:dword,\ |
str2:dword, str3:dword |
mov edi, [output] |
mov eax, [str0] |
mov ebx, [str1] |
mov ecx, [str2] |
mov edx, [str3] |
mov esi, 128 |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
ret |
endp |
align 4 |
proc copy_mem stdcall, output:dword, input:dword |
mov edi, [output] |
mov esi, [input] |
mov ecx, 0x80 |
.l1: |
mov eax, [esi] |
mov [edi], eax |
add esi, 4 |
add edi, 4 |
loop .l1 |
ret |
endp |
proc memcpy |
@@: |
mov eax, [esi] |
mov [edi], eax |
add esi, 4 |
add edi, 4 |
dec ecx |
jnz @B |
ret |
endp |
if 0 |
align 4 |
proc new_mix stdcall, output:dword |
locals |
mixCounter dd ? |
mixIndex dd ? |
streamIndex dd ? |
inputCount dd ? |
main_count dd ? |
blockCount dd ? |
mix_out dd ? |
endl |
call prepare_playlist |
cmp [play_count], 0 |
je .exit |
call FpuSave |
mov [main_count], 32; |
.l00: |
mov [mix_buff_map], 0x0000FFFF; |
xor eax, eax |
mov [mixCounter], eax |
mov [mixIndex], eax |
mov [streamIndex], eax; |
mov ebx, [play_count] |
mov [inputCount], ebx |
.l0: |
mov ecx, 4 |
.l1: |
mov ebx, [streamIndex] |
mov esi, [play_list+ebx*4] |
mov eax, [esi+STREAM.work_read] |
add [esi+STREAM.work_read], 512 |
mov ebx, [mixIndex] |
mov [mix_input+ebx*4], eax |
inc [mixCounter] |
inc [mixIndex] |
inc [streamIndex] |
dec [inputCount] |
jz .m2 |
dec ecx |
jnz .l1 |
cmp [mixCounter], 4 |
jnz .m2 |
stdcall mix_4_1, [mix_input], [mix_input+4], [mix_input+8], [mix_input+12] |
sub [mixIndex], 4 |
mov ebx, [mixIndex] |
mov [mix_input+ebx*4], eax |
inc [mixIndex] |
mov [mixCounter], 0 |
cmp [inputCount], 0 |
jnz .l0 |
.m2: |
cmp [mixIndex], 1 |
jne @f |
stdcall copy_mem, [output], [mix_input] |
jmp .m3 |
@@: |
cmp [mixIndex], 2 |
jne @f |
stdcall mix_2_1, [output], [mix_input], [mix_input+4] |
jmp .m3 |
@@: |
cmp [mixIndex], 3 |
jne @f |
stdcall mix_3_1, [output], [mix_input], [mix_input+4], [mix_input+8] |
jmp .m3 |
@@: |
stdcall final_mix, [output], [mix_input], [mix_input+4], [mix_input+8], [mix_input+12] |
.m3: |
add [output], 512 |
dec [main_count] |
jnz .l00 |
call update_stream |
emms |
call FpuRestore |
ret |
.exit: |
mov edi, [output] |
mov ecx, 0x1000 |
xor eax, eax |
cld |
rep stosd |
ret |
endp |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/proc32.inc |
---|
1,268 → 1,268 |
; Macroinstructions for defining and calling procedures |
macro stdcall proc,[arg] ; directly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call proc } |
macro invoke proc,[arg] ; indirectly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call [proc] } |
macro ccall proc,[arg] ; directly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call proc |
if size@ccall |
add esp,size@ccall |
end if } |
macro cinvoke proc,[arg] ; indirectly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call [proc] |
if size@ccall |
add esp,size@ccall |
end if } |
macro proc [args] ; define procedure |
{ common |
match name params, args> |
\{ define@proc name,<params \} } |
prologue@proc equ prologuedef |
macro prologuedef procname,flag,parmbytes,localbytes,reglist |
{ if parmbytes | localbytes |
push ebp |
mov ebp,esp |
if localbytes |
sub esp,localbytes |
end if |
end if |
irps reg, reglist \{ push reg \} } |
epilogue@proc equ epiloguedef |
macro epiloguedef procname,flag,parmbytes,localbytes,reglist |
{ irps reg, reglist \{ reverse pop reg \} |
if parmbytes | localbytes |
leave |
end if |
if flag and 10000b |
retn |
else |
retn parmbytes |
end if } |
macro define@proc name,statement |
{ local params,flag,regs,parmbytes,localbytes,current |
if used name |
name: |
match =stdcall args, statement \{ params equ args |
flag = 11b \} |
match =stdcall, statement \{ params equ |
flag = 11b \} |
match =c args, statement \{ params equ args |
flag = 10001b \} |
match =c, statement \{ params equ |
flag = 10001b \} |
match =params, params \{ params equ statement |
flag = 0 \} |
virtual at ebp+8 |
match =uses reglist=,args, params \{ regs equ reglist |
params equ args \} |
match =regs =uses reglist, regs params \{ regs equ reglist |
params equ \} |
match =regs, regs \{ regs equ \} |
match =,args, params \{ defargs@proc args \} |
match =args@proc args, args@proc params \{ defargs@proc args \} |
parmbytes = $ - (ebp+8) |
end virtual |
name # % = parmbytes/4 |
all@vars equ |
current = 0 |
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \} |
macro locals |
\{ virtual at ebp-localbytes+current |
macro label . \\{ deflocal@proc .,:, \\} |
struc db [val] \\{ \common deflocal@proc .,db,val \\} |
struc dw [val] \\{ \common deflocal@proc .,dw,val \\} |
struc dp [val] \\{ \common deflocal@proc .,dp,val \\} |
struc dd [val] \\{ \common deflocal@proc .,dd,val \\} |
struc dt [val] \\{ \common deflocal@proc .,dt,val \\} |
struc dq [val] \\{ \common deflocal@proc .,dq,val \\} |
struc rb cnt \\{ deflocal@proc .,rb cnt, \\} |
struc rw cnt \\{ deflocal@proc .,rw cnt, \\} |
struc rp cnt \\{ deflocal@proc .,rp cnt, \\} |
struc rd cnt \\{ deflocal@proc .,rd cnt, \\} |
struc rt cnt \\{ deflocal@proc .,rt cnt, \\} |
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} |
macro endl |
\{ purge label |
restruc db,dw,dp,dd,dt,dq |
restruc rb,rw,rp,rd,rt,rq |
restruc byte,word,dword,pword,tword,qword |
current = $-(ebp-localbytes) |
end virtual \} |
macro ret operand |
\{ match any, operand \\{ retn operand \\} |
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> |
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} |
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 |
end if \} } |
macro defargs@proc [arg] |
{ common |
if ~ arg eq |
forward |
local ..arg,current@arg |
match argname:type, arg |
\{ current@arg equ argname |
label ..arg type |
argname equ ..arg |
if dqword eq type |
dd ?,?,?,? |
else if tbyte eq type |
dd ?,?,? |
else if qword eq type | pword eq type |
dd ?,? |
else |
dd ? |
end if \} |
match =current@arg,current@arg |
\{ current@arg equ arg |
arg equ ..arg |
..arg dd ? \} |
common |
args@proc equ current@arg |
forward |
restore current@arg |
common |
end if } |
macro deflocal@proc name,def,[val] |
{ common |
match vars, all@vars \{ all@vars equ all@vars, \} |
all@vars equ all@vars name |
forward |
local ..var,..tmp |
..var def val |
match =?, val \{ ..tmp equ \} |
match any =dup (=?), val \{ ..tmp equ \} |
match tmp : value, ..tmp : val |
\{ tmp: end virtual |
initlocal@proc ..var,def value |
virtual at tmp\} |
common |
match first rest, ..var, \{ name equ first \} } |
macro initlocal@proc name,def |
{ virtual at name |
def |
size@initlocal = $ - name |
end virtual |
position@initlocal = 0 |
while size@initlocal > position@initlocal |
virtual at name |
def |
if size@initlocal - position@initlocal < 2 |
current@initlocal = 1 |
load byte@initlocal byte from name+position@initlocal |
else if size@initlocal - position@initlocal < 4 |
current@initlocal = 2 |
load word@initlocal word from name+position@initlocal |
else |
current@initlocal = 4 |
load dword@initlocal dword from name+position@initlocal |
end if |
end virtual |
if current@initlocal = 1 |
mov byte [name+position@initlocal],byte@initlocal |
else if current@initlocal = 2 |
mov word [name+position@initlocal],word@initlocal |
else |
mov dword [name+position@initlocal],dword@initlocal |
end if |
position@initlocal = position@initlocal + current@initlocal |
end while } |
macro endp |
{ purge ret,locals,endl |
finish@proc |
purge finish@proc |
restore regs@proc |
match all,args@proc \{ restore all \} |
restore args@proc |
match all,all@vars \{ restore all \} } |
macro local [var] |
{ common |
locals |
forward done@local equ |
match varname[count]:vartype, var |
\{ match =BYTE, vartype \\{ varname rb count |
restore done@local \\} |
match =WORD, vartype \\{ varname rw count |
restore done@local \\} |
match =DWORD, vartype \\{ varname rd count |
restore done@local \\} |
match =PWORD, vartype \\{ varname rp count |
restore done@local \\} |
match =QWORD, vartype \\{ varname rq count |
restore done@local \\} |
match =TBYTE, vartype \\{ varname rt count |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
rq count+count |
restore done@local \\} |
match , done@local \\{ virtual |
varname vartype |
end virtual |
rb count*sizeof.\#vartype |
restore done@local \\} \} |
match :varname:vartype, done@local:var |
\{ match =BYTE, vartype \\{ varname db ? |
restore done@local \\} |
match =WORD, vartype \\{ varname dw ? |
restore done@local \\} |
match =DWORD, vartype \\{ varname dd ? |
restore done@local \\} |
match =PWORD, vartype \\{ varname dp ? |
restore done@local \\} |
match =QWORD, vartype \\{ varname dq ? |
restore done@local \\} |
match =TBYTE, vartype \\{ varname dt ? |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
dq ?,? |
restore done@local \\} |
match , done@local \\{ varname vartype |
restore done@local \\} \} |
match ,done@local |
\{ var |
restore done@local \} |
common |
endl } |
; Macroinstructions for defining and calling procedures |
macro stdcall proc,[arg] ; directly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call proc } |
macro invoke proc,[arg] ; indirectly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call [proc] } |
macro ccall proc,[arg] ; directly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call proc |
if size@ccall |
add esp, size@ccall |
end if } |
macro cinvoke proc,[arg] ; indirectly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call [proc] |
if size@ccall |
add esp, size@ccall |
end if } |
macro proc [args] ; define procedure |
{ common |
match name params, args> |
\{ define@proc name,<params \} } |
prologue@proc equ prologuedef |
macro prologuedef procname,flag,parmbytes,localbytes,reglist |
{ if parmbytes | localbytes |
push ebp |
mov ebp, esp |
if localbytes |
sub esp, localbytes |
end if |
end if |
irps reg, reglist \{ push reg \} } |
epilogue@proc equ epiloguedef |
macro epiloguedef procname,flag,parmbytes,localbytes,reglist |
{ irps reg, reglist \{ reverse pop reg \} |
if parmbytes | localbytes |
leave |
end if |
if flag and 10000b |
retn |
else |
retn parmbytes |
end if } |
macro define@proc name,statement |
{ local params,flag,regs,parmbytes,localbytes,current |
if used name |
name: |
match =stdcall args, statement \{ params equ args |
flag = 11b \} |
match =stdcall, statement \{ params equ |
flag = 11b \} |
match =c args, statement \{ params equ args |
flag = 10001b \} |
match =c, statement \{ params equ |
flag = 10001b \} |
match =params, params \{ params equ statement |
flag = 0 \} |
virtual at ebp+8 |
match =uses reglist=,args, params \{ regs equ reglist |
params equ args \} |
match =regs =uses reglist, regs params \{ regs equ reglist |
params equ \} |
match =regs, regs \{ regs equ \} |
match =,args, params \{ defargs@proc args \} |
match =args@proc args, args@proc params \{ defargs@proc args \} |
parmbytes = $ - (ebp+8) |
end virtual |
name # % = parmbytes/4 |
all@vars equ |
current = 0 |
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \} |
macro locals |
\{ virtual at ebp-localbytes+current |
macro label . \\{ deflocal@proc .,:, \\} |
struc db [val] \\{ \common deflocal@proc .,db,val \\} |
struc dw [val] \\{ \common deflocal@proc .,dw,val \\} |
struc dp [val] \\{ \common deflocal@proc .,dp,val \\} |
struc dd [val] \\{ \common deflocal@proc .,dd,val \\} |
struc dt [val] \\{ \common deflocal@proc .,dt,val \\} |
struc dq [val] \\{ \common deflocal@proc .,dq,val \\} |
struc rb cnt \\{ deflocal@proc .,rb cnt, \\} |
struc rw cnt \\{ deflocal@proc .,rw cnt, \\} |
struc rp cnt \\{ deflocal@proc .,rp cnt, \\} |
struc rd cnt \\{ deflocal@proc .,rd cnt, \\} |
struc rt cnt \\{ deflocal@proc .,rt cnt, \\} |
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} |
macro endl |
\{ purge label |
restruc db,dw,dp,dd,dt,dq |
restruc rb,rw,rp,rd,rt,rq |
restruc byte,word,dword,pword,tword,qword |
current = $-(ebp-localbytes) |
end virtual \} |
macro ret operand |
\{ match any, operand \\{ retn operand \\} |
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> |
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} |
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 |
end if \} } |
macro defargs@proc [arg] |
{ common |
if ~ arg eq |
forward |
local ..arg,current@arg |
match argname:type, arg |
\{ current@arg equ argname |
label ..arg type |
argname equ ..arg |
if dqword eq type |
dd ?,?,?,? |
else if tbyte eq type |
dd ?,?,? |
else if qword eq type | pword eq type |
dd ?,? |
else |
dd ? |
end if \} |
match =current@arg,current@arg |
\{ current@arg equ arg |
arg equ ..arg |
..arg dd ? \} |
common |
args@proc equ current@arg |
forward |
restore current@arg |
common |
end if } |
macro deflocal@proc name,def,[val] |
{ common |
match vars, all@vars \{ all@vars equ all@vars, \} |
all@vars equ all@vars name |
forward |
local ..var,..tmp |
..var def val |
match =?, val \{ ..tmp equ \} |
match any =dup (=?), val \{ ..tmp equ \} |
match tmp : value, ..tmp : val |
\{ tmp: end virtual |
initlocal@proc ..var,def value |
virtual at tmp\} |
common |
match first rest, ..var, \{ name equ first \} } |
macro initlocal@proc name,def |
{ virtual at name |
def |
size@initlocal = $ - name |
end virtual |
position@initlocal = 0 |
while size@initlocal > position@initlocal |
virtual at name |
def |
if size@initlocal - position@initlocal < 2 |
current@initlocal = 1 |
load byte@initlocal byte from name+position@initlocal |
else if size@initlocal - position@initlocal < 4 |
current@initlocal = 2 |
load word@initlocal word from name+position@initlocal |
else |
current@initlocal = 4 |
load dword@initlocal dword from name+position@initlocal |
end if |
end virtual |
if current@initlocal = 1 |
mov byte [name+position@initlocal], byte@initlocal |
else if current@initlocal = 2 |
mov word [name+position@initlocal], word@initlocal |
else |
mov dword [name+position@initlocal], dword@initlocal |
end if |
position@initlocal = position@initlocal + current@initlocal |
end while } |
macro endp |
{ purge ret,locals,endl |
finish@proc |
purge finish@proc |
restore regs@proc |
match all,args@proc \{ restore all \} |
restore args@proc |
match all,all@vars \{ restore all \} } |
macro local [var] |
{ common |
locals |
forward done@local equ |
match varname[count]:vartype, var |
\{ match =BYTE, vartype \\{ varname rb count |
restore done@local \\} |
match =WORD, vartype \\{ varname rw count |
restore done@local \\} |
match =DWORD, vartype \\{ varname rd count |
restore done@local \\} |
match =PWORD, vartype \\{ varname rp count |
restore done@local \\} |
match =QWORD, vartype \\{ varname rq count |
restore done@local \\} |
match =TBYTE, vartype \\{ varname rt count |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
rq count+count |
restore done@local \\} |
match , done@local \\{ virtual |
varname vartype |
end virtual |
rb count*sizeof.\#vartype |
restore done@local \\} \} |
match :varname:vartype, done@local:var |
\{ match =BYTE, vartype \\{ varname db ? |
restore done@local \\} |
match =WORD, vartype \\{ varname dw ? |
restore done@local \\} |
match =DWORD, vartype \\{ varname dd ? |
restore done@local \\} |
match =PWORD, vartype \\{ varname dp ? |
restore done@local \\} |
match =QWORD, vartype \\{ varname dq ? |
restore done@local \\} |
match =TBYTE, vartype \\{ varname dt ? |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
dq ?,? |
restore done@local \\} |
match , done@local \\{ varname vartype |
restore done@local \\} \} |
match ,done@local |
\{ var |
restore done@local \} |
common |
endl } |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/sb16/CONFIG.INC |
---|
1,50 → 1,50 |
;flags------------------------------------------------------------ |
DEBUG equ 1 ;show messages at debug board |
use_cli_sti equ 1 ;driver become more stable (theoretically) |
;constants-------------------------------------------------------- |
API_VERSION equ 0 ;debug |
OS_BASE equ 0x80000000 |
new_app_base equ 0x0 |
PROC_BASE equ (OS_BASE+0x080000) |
SB16Buffer equ (OS_BASE+0x2A0000) |
SB16_Status equ (OS_BASE+0x2B0000) |
DMAPage equ ((SB16Buffer-OS_BASE) shr 16) |
SB16Buffer0 equ SB16Buffer |
SB16Buffer1 equ (SB16Buffer+16384) |
SB16Buffer2 equ (SB16Buffer+(2*16384)) |
SB16Buffer3 equ (SB16Buffer+(3*16384)) |
sb_irq_num equ 5 ;default values for SB16, may be overrided by autodetect |
sb_dma_num equ 5 ;default values for SB16, may be overrided by autodetect |
small_buffer equ 32768 |
full_buffer equ 65536 |
sb_buffer_size equ small_buffer ; FIX ring buffer overlapped events issue; full_buffer |
__supported_buffer_sizes fix <small_buffer, full_buffer> |
if ~(sb_buffer_size in __supported_buffer_sizes) |
display 13,10,'unsupported buffer size was selected, check config.inc',13,10 |
stop |
end if |
sb_out_rate equ 48000 |
;time constant for cards older than SB16 |
sb_tc equ (256-(1000000/(sb_out_rate*2))) |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
;flags------------------------------------------------------------ |
DEBUG equ 1 ;show messages at debug board |
use_cli_sti equ 1 ;driver become more stable (theoretically) |
;constants-------------------------------------------------------- |
API_VERSION equ 0 ;debug |
OS_BASE equ 0x80000000 |
new_app_base equ 0x0 |
PROC_BASE equ (OS_BASE+0x080000) |
SB16Buffer equ (OS_BASE+0x2A0000) |
SB16_Status equ (OS_BASE+0x2B0000) |
DMAPage equ ((SB16Buffer-OS_BASE) shr 16) |
SB16Buffer0 equ SB16Buffer |
SB16Buffer1 equ (SB16Buffer+16384) |
SB16Buffer2 equ (SB16Buffer+(2*16384)) |
SB16Buffer3 equ (SB16Buffer+(3*16384)) |
sb_irq_num equ 5 ;default values for SB16, may be overrided by autodetect |
sb_dma_num equ 5 ;default values for SB16, may be overrided by autodetect |
small_buffer equ 32768 |
full_buffer equ 65536 |
sb_buffer_size equ small_buffer ; FIX ring buffer overlapped events issue; full_buffer |
__supported_buffer_sizes fix <small_buffer, full_buffer> |
if ~(sb_buffer_size in __supported_buffer_sizes) |
display 13,10,'unsupported buffer size was selected, check config.inc',13,10 |
stop |
end if |
sb_out_rate equ 48000 |
;time constant for cards older than SB16 |
sb_tc equ (256-(1000000/(sb_out_rate*2))) |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/sb16/SB16.INC |
---|
1,297 → 1,297 |
;-------------------------------- |
; program dma |
;-------------------------------- |
sb_set_dma: |
mov ebx,[sound_dma] |
lea eax,[ebx+4] ;mask required channel |
cmp bl,4 |
ja .use_second_dma_controller |
jb @f |
.dma_setup_error: |
if DEBUG |
mov esi,msgErrDMAsetup |
call SysMsgBoardStr |
end if |
mov dword[esp],START.stop |
ret |
@@: |
if use_cli_sti |
cli ;here to minimize time with disabled ints |
end if |
out 0xA,al ;mask required channel |
xor eax,eax |
out 0xC,al ;clear byte pointer flip-flop register |
lea eax,[ebx+0x58] ;auto-init mode for channel (ebx) |
out 0xB,al ;DMA channel 0-3 mode register |
movzx edx,byte[ebx+dma_table] ;page register |
mov al,DMAPage |
out dx,al |
lea edx,[ebx*2] ;DMA channel 0-3 base address |
mov al,0 ;LSB is 0 |
out dx,al |
; mov al,0 ;MSB is 0 too |
out dx,al |
inc edx ;DMA channel 0-3 byte count |
mov al,((sb_buffer_size-1) and 0xff) |
out dx,al |
mov al,((sb_buffer_size-1) shr 8) ;it is the same |
out dx,al |
mov eax,ebx ;unmask DMA channel |
out 0xA,al |
if use_cli_sti |
sti |
end if |
ret |
.use_second_dma_controller: |
cmp bl,7 |
ja .dma_setup_error |
sub bl,4 |
sub al,4 |
if use_cli_sti |
cli ;here to minimize time with disabled ints |
end if |
out 0xD4,al ;mask required channel |
xor eax,eax |
out 0xD8,al ;clear byte pointer flip-flop register |
lea eax,[ebx+0x58] ;auto-init mode for channel (ebx+4) |
out 0xD6,al ;DMA channel 4-7 mode register |
movzx edx,byte[ebx+dma_table+4] ;page register |
mov al,DMAPage |
out dx,al |
lea edx,[ebx*4+0xC0] ;DMA channel 4-7 base address |
mov al,0 ;LSB is 0 ;for 16bit DMA this contains |
out dx,al ;A1-A8 lines of address bus, A0 is zero |
; mov al,0 ;MSB is 0 too ;for 16bit DMA this contains |
out dx,al ;A9-A16 lines of address bus |
inc edx |
inc edx ;DMA channel 4-7 16bit word count |
mov al,(((sb_buffer_size/2)-1) and 0xff) |
out dx,al |
mov al,(((sb_buffer_size/2)-1) shr 8) |
out dx,al |
mov eax,ebx ;unmask DMA channel |
out 0xD4,al |
if use_cli_sti |
sti |
end if |
ret |
;------------------------------------------------------------------------------- |
; out byte to SB DSP's write port |
;------------------------------------------------------------------------------- |
macro sb_out data_to_out { |
@@: |
in al,dx |
test al,al ;is DSP busy? |
js @b ;it's busy |
mov al,data_to_out ;it's free |
out dx,al |
} |
;------------------------------------------------------------------------------- |
; stop playing |
;------------------------------------------------------------------------------- |
proc sb_stop |
mov edx,[sb_base_port] |
add dl,0xC |
sb_out 0xD3 ;turn the speaker off |
sb_out 0xDA ;exit 8bit DMA |
sb_out 0xD9 ;exit 16bit DMA |
ret |
endp |
;------------------------------------------------------------------------------- |
; start playing |
;------------------------------------------------------------------------------- |
proc sb_play |
and [int_flip_flop],0 |
mov edx,[sb_base_port] |
add dl,0xC |
sb_out 0xD1 ;turn speaker on |
; sb_out 0x48 ;set DSP transfer size ;for older cards, not supported |
; ;in this version |
; mov ax,32767 ;(64k)/2-1 |
;@@: ;out the low byte... |
; in al,dx |
; test al,al ;is DSP busy? |
; js @b ;it's busy |
; out dx,al |
; mov al,ah ;...then the high byte |
;@@: |
; in al,dx |
; test al,al ;is DSP busy? |
; js @b ;it's busy |
; out dx,al |
; sb_out 0x1C ;auto-init 8bit playback |
; 0xBXh - 16 bit DMA mode |
; |||| |
sb_out 10110110b ;bCommand |
; |||| |
; |||+-reserved |
; ||+--turn FIFO on (0 for off) |
; |+---auto-init mode on (0 for off) |
; +----A/D: 0-output, 1-input |
; +------stereo on |
; |+-----unsigned (1 for signed) |
; || |
sb_out 00110000b ;bMode |
; || |||| |
; ---------reserved |
;wSize is a number of 16bit samples less 1. For auto-init mode each half |
;buffer is (64k)/2 bytes long and, obviously, contains ((64k)/2)/2 samples |
sb_out (((sb_buffer_size/2/2)-1) and 0xFF) ;wSize.LowByte |
sb_out (((sb_buffer_size/2/2)-1) shr 8) ;wSize.HighByte |
ret |
endp |
;------------------------------------------------------------------------------- |
; reset DSP |
;------------------------------------------------------------------------------- |
proc sb_reset |
and [int_flip_flop],0 |
mov edx,[sb_base_port] |
add dl,6 |
mov al,1 ;start DSP reset |
if use_cli_sti |
cli ;here to minimize time with disabled ints |
end if |
out dx,al |
mov ecx,40 ;wait at least 3 microsec. |
@@: |
in al,dx |
loop @b |
xor eax,eax ;stop DSP reset |
if use_cli_sti |
sti |
end if |
out dx,al |
ret |
endp |
;------------------------------------------------------------------------------- |
; set the rate for playing, enable stereo |
;------------------------------------------------------------------------------- |
proc sb_setup |
mov edx,[sb_base_port] |
add dl,0xC |
sb_out 40h ;set time constant, this is for old cards |
sb_out sb_tc |
sb_out 41h ;set sound rate, this can only SB16 |
sb_out (sb_out_rate shr 8) ;first high byte (MSB) |
sb_out (sb_out_rate and 0xff) ;then low byte (LSB) |
; mov al,0xE ;for older cards, not supported in this version |
; sub dl,(0xC-4) ;talk to SB's mixer |
; out dx,al ;select this register of the mixer |
; mov ecx,6 ;wait for the chip |
;@@: |
; in al,dx |
; loop @b |
; inc edx ;now read the data port |
; in al,dx |
; or al,22h ;turn on stereo |
; mov ah,al |
; mov al,0xE |
; dec edx ;talk to SB's mixer |
; out dx,al ;select this register of the mixer |
; mov ecx,6 ;wait for the chip |
;@@: |
; in al,dx |
; loop @b |
; inc edx ;now send data to the data port |
; mov al,ah |
; out dx,al |
; dec edx |
; mov ecx,35 ;wait for the chip |
;@@: |
; in al,dx |
; loop @b |
ret |
endp |
;------------------------------------------------------------------------------- |
; set master volume of SB mixer, note, not only SB16 but SBPro and older |
; this is the first step to more full support for hardware |
;------------------------------------------------------------------------------- |
;in: eax in range [-10000;0] - master volume for _both_ channels |
;note that x*3*17/2000 and x*3/2000*17 are not the same numbers, |
;because we count in integers |
proc sb_set_master_vol |
mov [sb_master_vol],eax |
add eax,10000 ;SB sound level rise from 0 to MAX_LEVEL |
lea eax,[eax+eax*2] ;*3 |
mov ebx,2000 ;divisor |
xor edx,edx |
cmp byte[sb_DSP_version_int],4 |
jae @f ;SBPro's MAX_LEVEL is 15, but we *11 because |
;volume byte looks like that: 0xLR, where L - left |
;channel volume, R - right, 0<=R,L<=15 |
div ebx |
imul eax,17 |
mov edx,[sb_base_port] |
push eax ;here for optimisation |
add dl,4 |
mov al,0x22 ;write mixer register 0x22 |
out dx,al |
in al,dx ;wait for the chip ;6 |
in al,dx ;wait for the chip ;5 |
in al,dx ;wait for the chip ;4 |
in al,dx ;wait for the chip ;3 |
in al,dx ;wait for the chip ;2 |
in al,dx ;wait for the chip ;1 |
pop eax ;go! |
inc edx |
out dx,al |
ret |
@@: ;SB16's MAX_LEVEL is 255 |
imul eax,17 |
div ebx |
mov edx,[sb_base_port] |
push eax ;here for optimisation |
add dl,4 |
mov al,0x30 ;left speaker |
out dx,al |
pop eax ;<--+ |
inc edx ; \/ |
push eax ;here for optimisation |
out dx,al ;write |
dec edx |
mov al,0x31 ;right speaker |
out dx,al |
pop eax |
inc edx |
out dx,al ;write |
ret |
endp |
;------------------------------------------------------------------------------- |
;-------------------------------- |
; program dma |
;-------------------------------- |
sb_set_dma: |
mov ebx, [sound_dma] |
lea eax, [ebx+4];mask required channel |
cmp bl, 4 |
ja .use_second_dma_controller |
jb @f |
.dma_setup_error: |
if DEBUG |
mov esi, msgErrDMAsetup |
call SysMsgBoardStr |
end if |
mov dword[esp], START.stop |
ret |
@@: |
if use_cli_sti |
cli ;here to minimize time with disabled ints |
end if |
out 0xA, al;mask required channel |
xor eax, eax |
out 0xC, al;clear byte pointer flip-flop register |
lea eax, [ebx+0x58];auto-init mode for channel (ebx) |
out 0xB, al;DMA channel 0-3 mode register |
movzx edx, byte[ebx+dma_table];page register |
mov al, DMAPage |
out dx, al |
lea edx, [ebx*2];DMA channel 0-3 base address |
mov al, 0;LSB is 0 |
out dx, al |
; mov al,0 ;MSB is 0 too |
out dx, al |
inc edx ;DMA channel 0-3 byte count |
mov al, ((sb_buffer_size-1) and 0xff) |
out dx, al |
mov al, ((sb_buffer_size-1) shr 8);it is the same |
out dx, al |
mov eax, ebx;unmask DMA channel |
out 0xA, al |
if use_cli_sti |
sti |
end if |
ret |
.use_second_dma_controller: |
cmp bl, 7 |
ja .dma_setup_error |
sub bl, 4 |
sub al, 4 |
if use_cli_sti |
cli ;here to minimize time with disabled ints |
end if |
out 0xD4, al;mask required channel |
xor eax, eax |
out 0xD8, al;clear byte pointer flip-flop register |
lea eax, [ebx+0x58];auto-init mode for channel (ebx+4) |
out 0xD6, al;DMA channel 4-7 mode register |
movzx edx, byte[ebx+dma_table+4];page register |
mov al, DMAPage |
out dx, al |
lea edx, [ebx*4+0xC0];DMA channel 4-7 base address |
mov al, 0;LSB is 0 ;for 16bit DMA this contains |
out dx, al;A1-A8 lines of address bus, A0 is zero |
; mov al,0 ;MSB is 0 too ;for 16bit DMA this contains |
out dx, al;A9-A16 lines of address bus |
inc edx |
inc edx ;DMA channel 4-7 16bit word count |
mov al, (((sb_buffer_size/2)-1) and 0xff) |
out dx, al |
mov al, (((sb_buffer_size/2)-1) shr 8) |
out dx, al |
mov eax, ebx;unmask DMA channel |
out 0xD4, al |
if use_cli_sti |
sti |
end if |
ret |
;------------------------------------------------------------------------------- |
; out byte to SB DSP's write port |
;------------------------------------------------------------------------------- |
macro sb_out data_to_out { |
@@: |
in al, dx |
test al, al;is DSP busy? |
js @b ;it's busy |
mov al, data_to_out;it's free |
out dx, al |
} |
;------------------------------------------------------------------------------- |
; stop playing |
;------------------------------------------------------------------------------- |
proc sb_stop |
mov edx, [sb_base_port] |
add dl, 0xC |
sb_out 0xD3 ;turn the speaker off |
sb_out 0xDA ;exit 8bit DMA |
sb_out 0xD9 ;exit 16bit DMA |
ret |
endp |
;------------------------------------------------------------------------------- |
; start playing |
;------------------------------------------------------------------------------- |
proc sb_play |
and [int_flip_flop], 0 |
mov edx, [sb_base_port] |
add dl, 0xC |
sb_out 0xD1 ;turn speaker on |
; sb_out 0x48 ;set DSP transfer size ;for older cards, not supported |
; ;in this version |
; mov ax,32767 ;(64k)/2-1 |
;@@: ;out the low byte... |
; in al,dx |
; test al,al ;is DSP busy? |
; js @b ;it's busy |
; out dx,al |
; mov al,ah ;...then the high byte |
;@@: |
; in al,dx |
; test al,al ;is DSP busy? |
; js @b ;it's busy |
; out dx,al |
; sb_out 0x1C ;auto-init 8bit playback |
; 0xBXh - 16 bit DMA mode |
; |||| |
sb_out 10110110b ;bCommand |
; |||| |
; |||+-reserved |
; ||+--turn FIFO on (0 for off) |
; |+---auto-init mode on (0 for off) |
; +----A/D: 0-output, 1-input |
; +------stereo on |
; |+-----unsigned (1 for signed) |
; || |
sb_out 00110000b ;bMode |
; || |||| |
; ---------reserved |
;wSize is a number of 16bit samples less 1. For auto-init mode each half |
;buffer is (64k)/2 bytes long and, obviously, contains ((64k)/2)/2 samples |
sb_out (((sb_buffer_size/2/2)-1) and 0xFF) ;wSize.LowByte |
sb_out (((sb_buffer_size/2/2)-1) shr 8) ;wSize.HighByte |
ret |
endp |
;------------------------------------------------------------------------------- |
; reset DSP |
;------------------------------------------------------------------------------- |
proc sb_reset |
and [int_flip_flop], 0 |
mov edx, [sb_base_port] |
add dl, 6 |
mov al, 1;start DSP reset |
if use_cli_sti |
cli ;here to minimize time with disabled ints |
end if |
out dx, al |
mov ecx, 40;wait at least 3 microsec. |
@@: |
in al, dx |
loop @b |
xor eax, eax;stop DSP reset |
if use_cli_sti |
sti |
end if |
out dx, al |
ret |
endp |
;------------------------------------------------------------------------------- |
; set the rate for playing, enable stereo |
;------------------------------------------------------------------------------- |
proc sb_setup |
mov edx, [sb_base_port] |
add dl, 0xC |
sb_out 40h ;set time constant, this is for old cards |
sb_out sb_tc |
sb_out 41h ;set sound rate, this can only SB16 |
sb_out (sb_out_rate shr 8) ;first high byte (MSB) |
sb_out (sb_out_rate and 0xff) ;then low byte (LSB) |
; mov al,0xE ;for older cards, not supported in this version |
; sub dl,(0xC-4) ;talk to SB's mixer |
; out dx,al ;select this register of the mixer |
; mov ecx,6 ;wait for the chip |
;@@: |
; in al,dx |
; loop @b |
; inc edx ;now read the data port |
; in al,dx |
; or al,22h ;turn on stereo |
; mov ah,al |
; mov al,0xE |
; dec edx ;talk to SB's mixer |
; out dx,al ;select this register of the mixer |
; mov ecx,6 ;wait for the chip |
;@@: |
; in al,dx |
; loop @b |
; inc edx ;now send data to the data port |
; mov al,ah |
; out dx,al |
; dec edx |
; mov ecx,35 ;wait for the chip |
;@@: |
; in al,dx |
; loop @b |
ret |
endp |
;------------------------------------------------------------------------------- |
; set master volume of SB mixer, note, not only SB16 but SBPro and older |
; this is the first step to more full support for hardware |
;------------------------------------------------------------------------------- |
;in: eax in range [-10000;0] - master volume for _both_ channels |
;note that x*3*17/2000 and x*3/2000*17 are not the same numbers, |
;because we count in integers |
proc sb_set_master_vol |
mov [sb_master_vol], eax |
add eax, 10000;SB sound level rise from 0 to MAX_LEVEL |
lea eax, [eax+eax*2];*3 |
mov ebx, 2000;divisor |
xor edx, edx |
cmp byte[sb_DSP_version_int], 4 |
jae @f ;SBPro's MAX_LEVEL is 15, but we *11 because |
;volume byte looks like that: 0xLR, where L - left |
;channel volume, R - right, 0<=R,L<=15 |
div ebx |
imul eax, 17 |
mov edx, [sb_base_port] |
push eax ;here for optimisation |
add dl, 4 |
mov al, 0x22;write mixer register 0x22 |
out dx, al |
in al, dx;wait for the chip ;6 |
in al, dx;wait for the chip ;5 |
in al, dx;wait for the chip ;4 |
in al, dx;wait for the chip ;3 |
in al, dx;wait for the chip ;2 |
in al, dx;wait for the chip ;1 |
pop eax ;go! |
inc edx |
out dx, al |
ret |
@@: ;SB16's MAX_LEVEL is 255 |
imul eax, 17 |
div ebx |
mov edx, [sb_base_port] |
push eax ;here for optimisation |
add dl, 4 |
mov al, 0x30;left speaker |
out dx, al |
pop eax ;<--+ |
inc edx ; \/ |
push eax ;here for optimisation |
out dx, al;write |
dec edx |
mov al, 0x31;right speaker |
out dx, al |
pop eax |
inc edx |
out dx, al;write |
ret |
endp |
;------------------------------------------------------------------------------- |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/sb16/sb16.asm |
---|
1,395 → 1,398 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
include 'CONFIG.INC' |
;structs---------------------------------------------------------- |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
;something-------------------------------------------------------- |
public START |
public service_proc |
public version |
include '..\proc32.inc' |
include '..\imports.inc' |
section '.flat' code readable align 16 |
include 'SB16.INC' |
;------------------------------------------------------------------------------- |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect ;returns DSP version or zero if |
test eax,eax ;SB card not found |
jz .exit |
if DEBUG |
movzx eax,al ;major version |
mov esi,sb_DSP_description |
dec eax |
jz .sb_say_about_found_dsp |
mov dword[esi],'2.x ' |
dec eax |
jz .sb_say_about_found_dsp |
mov dword[esi],'Pro ' |
dec eax |
jz .sb_say_about_found_dsp |
mov dword[esi],'16 ' |
.sb_say_about_found_dsp: |
mov esi,msgDSPFound |
call SysMsgBoardStr |
end if |
; xor eax,eax |
; mov ebx,[sb_base_port] |
; lea ecx,[ebx+0xF] |
xor ebx,ebx |
mov ecx,[sb_base_port] |
lea edx,[ebx+0xF] |
call ReservePortArea ;these ports must be my! |
if DEBUG |
dec eax |
jnz @f |
mov esi,msgErrRsrvPorts |
call SysMsgBoardStr |
@@: |
end if |
call sb_setup ;clock it, etc |
stdcall AttachIntHandler, sb_irq_num, sb_irq, 0 |
if DEBUG |
test eax,eax |
jnz @f |
mov esi,msgErrAtchIRQ |
call SysMsgBoardStr |
stdcall GetIntHandler, sb_irq_num |
call SysMsgBoardNum |
jmp .stop |
@@: |
mov esi,msgSucAtchIRQ |
call SysMsgBoardStr |
end if |
stdcall RegService, my_service, service_proc |
ret |
.stop: |
call sb_reset |
.exit: |
if DEBUG |
mov esi,msgExit |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
endp |
;------------------------------------------------------------------------------- |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi,[ioctl] |
mov eax,[edi+io_code] |
cmp eax,SRV_GETVERSION |
jne @F |
mov eax,[edi+output] |
cmp [edi+out_size],4 |
jne .fail |
mov [eax],dword API_VERSION |
xor eax,eax |
ret |
@@: |
cmp eax,DEV_PLAY |
jne @f |
if DEBUG |
mov esi,msgPlay |
call SysMsgBoardStr |
end if |
call sb_stop ;to play smth new we must stop smth old |
call pre_fill_data ;fill first and second half of the buffer |
call pre_fill_data ; |
call sb_set_dma ;is it really needed here? Paranoia. |
call sb_play |
xor eax,eax ;set maximum volume |
call sb_set_master_vol |
xor eax,eax |
ret |
;@@: ;all this commented stuff in service proc |
; cmp eax,DEV_STOP ;is never used. Mixer do this virtually, |
; jne @f ;e.g. instead of stopping driver it |
;if DEBUG ;outputs silence |
; mov esi,msgStop |
; call SysMsgBoardStr |
;end if |
; call sb_stop |
; xor eax,eax |
; ret |
@@: |
cmp eax,DEV_CALLBACK |
jne @f |
if DEBUG |
mov esi,msgCallback |
call SysMsgBoardStr |
end if |
mov edi,[edi+input] |
mov eax,[edi] |
mov [callback],eax |
if DEBUG |
call SysMsgBoardNum |
end if |
xor eax,eax |
ret |
@@: |
cmp eax,DEV_SET_MASTERVOL ;Serge asked me to unlock |
jne @F ;DEV_SET(GET)_MASTERVOL, although mixer doesn't use it. |
;It doesn't use it _in current version_ - but in the future... |
if DEBUG |
mov esi,msgSetVol |
call SysMsgBoardStr |
end if |
mov eax,[edi+input] |
mov eax,[eax] |
call sb_set_master_vol |
xor eax,eax |
ret |
@@: |
cmp eax,DEV_GET_MASTERVOL |
jne @F |
if DEBUG |
mov esi,msgGetVol |
call SysMsgBoardStr |
end if |
mov eax,[edi+output] |
mov edx,[sb_master_vol] |
mov [eax],edx |
xor eax,eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
;------------------------------------------------------------------------------- |
align 4 |
proc sb_irq |
mov edx,[sb_base_port] ;tell the DSP that we have processed IRQ |
add dl,0xF ;0xF for 16 bit sound, 0xE for 8 bit sound |
in al,dx ;for non-stop sound |
pre_fill_data: |
mov eax,int_flip_flop |
not dword[eax] |
mov eax,[eax] |
test eax,eax |
jns .fill_second_half |
if sb_buffer_size eq small_buffer |
stdcall [callback],SB16Buffer0 ;for 32k buffer |
else if sb_buffer_size eq full_buffer |
stdcall [callback],SB16Buffer0 ;for 64k buffer |
stdcall [callback],SB16Buffer1 ;for 64k buffer |
end if |
xor eax, eax |
not eax |
ret |
.fill_second_half: |
if sb_buffer_size eq small_buffer |
stdcall [callback],SB16Buffer1 ;for 32k buffer |
else if sb_buffer_size eq full_buffer |
stdcall [callback],SB16Buffer2 ;for 64k buffer |
stdcall [callback],SB16Buffer3 ;for 64k buffer |
end if |
xor eax, eax |
not eax |
ret |
endp |
;------------------------------------------------------------------------------- |
align 4 |
proc detect |
.sb_detect_next_port: |
if DEBUG |
inc dword[port_second_digit_num] |
end if |
mov edx,sb_base_port |
add byte[edx],10h |
cmp byte[edx],80h |
jbe .sb_try_to_detect_at_specified_port |
;error - no SB card detected |
.sb_not_found_err: |
xor eax, eax |
ret |
.sb_try_to_detect_at_specified_port: |
call sb_reset |
add dl,8 |
mov ecx,100 |
.sb_check_port: |
in al,dx |
test al,al ;is DSP port ready to be read? |
jns .sb_port_not_ready |
sub dl,4 |
in al,dx ;check for AAh response |
add dl,4 |
cmp al,0xAA |
jne .sb_port_not_ready |
.sb_card_found: |
and dl,0xF0 |
add dl,0xC |
sb_out 0xE1 ;get DSP version |
add dl,2 |
@@: |
in al,dx |
test al,al ;is DSP port ready to be read? |
jns @b |
sub dl,4 |
in al,dx ;get major version |
ror eax,16 |
add dl,4 |
@@: |
in al,dx |
test al,al ;is DSP port ready to be read? |
jns @b |
sub dl,4 |
in al,dx ;get minor version |
xor edx,edx |
mov dl,10 |
div dl |
ror eax,16 |
xor ah,ah |
mov [sb_DSP_version_int],eax ;for internal usage |
if DEBUG |
add [sb_DSP_version],eax |
end if |
ret |
.sb_port_not_ready: |
loop .sb_check_port ;100 retries (~100 microsec.) |
jmp .sb_detect_next_port |
endp |
;------------------------------------------------------------------------------- |
if DEBUG |
proc SysMsgBoardNum ;warning: destroys eax,ebx,ecx,esi |
mov ebx,eax |
mov ecx,8 |
mov esi,(number_to_out+1) |
.1: |
mov eax,ebx |
and eax,0xF |
add al,'0' |
cmp al,(10+'0') |
jb @f |
add al,('A'-'0'-10) |
@@: |
mov [esi+ecx],al |
shr ebx,4 |
loop .1 |
dec esi |
call SysMsgBoardStr |
ret |
endp |
end if |
;all initialized data place here |
align 4 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
sb_base_port: dd 200h ;don't ask me why - see the code&docs |
sound_dma dd sb_dma_num |
;note that 4th DMA channel doesn't exist, it is used for cascade |
;plugging the first DMA controler to the second |
dma_table db 0x87,0x83,0x81,0x82,0xFF,0x8B,0x89,0x8A |
my_service db 'SOUND',0 ;max 16 chars include zero |
if DEBUG |
number_to_out db '0x00000000',13,10,0 |
msgInit db 'detecting hardware...',13,10,0 |
msgExit db 'exiting... May be some problems found?',13,10,0 |
msgPlay db 'start play',13,10,0 |
;msgStop db 'stop play',13,10,0 |
msgCallback db 'set_callback received from the mixer!',13,10 |
db 'callback handler is: ',0 |
msgErrAtchIRQ db 'failed to attach IRQ',(sb_irq_num+'0'),13,10 |
db 'owner',39,'s handler: ',0 |
msgSucAtchIRQ db 'succesfully attached IRQ',(sb_irq_num+'0') |
db ' as hardcoded',13,10,0 |
msgErrRsrvPorts db 'failed to reserve needed ports.',13,10 |
db 'Driver may work unstable',13,10,0 |
msgSetVol db 'DEV_SET_MASTERVOL call came',13,10,0 |
msgGetVol db 'DEV_GET_MASTERVOL call came',13,10,0 |
msgErrDMAsetup db 'failed to setup DMA - bad channel',13,10,0 |
;------------------------------------------------------------------------------- |
msgDSPFound db 'DSP found at port 2' |
label port_second_digit_num dword at $ |
db '00h',13,10,'DSP version ' |
sb_DSP_version: db '0.00 - SB' |
sb_DSP_description: db 32,32,32,32,13,10,0 |
;------------------------------------------------------------------------------- |
end if |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
;pTempBuf rd 1 |
callback rd 1 |
int_flip_flop rd 1 |
sb_master_vol rd 1 |
sb_DSP_version_int rd 1 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
include 'CONFIG.INC' |
;structs---------------------------------------------------------- |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
;something-------------------------------------------------------- |
public START |
public service_proc |
public version |
include '..\proc32.inc' |
include '..\imports.inc' |
section '.flat' code readable align 16 |
include 'SB16.INC' |
;------------------------------------------------------------------------------- |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect ;returns DSP version or zero if |
test eax, eax ;SB card not found |
jz .exit |
if DEBUG |
movzx eax, al ;major version |
mov esi, sb_DSP_description |
dec eax |
jz .sb_say_about_found_dsp |
mov dword[esi], '2.x ' |
dec eax |
jz .sb_say_about_found_dsp |
mov dword[esi], 'Pro ' |
dec eax |
jz .sb_say_about_found_dsp |
mov dword[esi], '16 ' |
.sb_say_about_found_dsp: |
mov esi, msgDSPFound |
call SysMsgBoardStr |
end if |
; xor eax,eax |
; mov ebx,[sb_base_port] |
; lea ecx,[ebx+0xF] |
xor ebx, ebx |
mov ecx, [sb_base_port] |
lea edx, [ebx+0xF] |
call ReservePortArea ;these ports must be my! |
if DEBUG |
dec eax |
jnz @f |
mov esi, msgErrRsrvPorts |
call SysMsgBoardStr |
@@: |
end if |
call sb_setup ;clock it, etc |
stdcall AttachIntHandler, sb_irq_num, sb_irq, 0 |
if DEBUG |
test eax, eax |
jnz @f |
mov esi, msgErrAtchIRQ |
call SysMsgBoardStr |
stdcall GetIntHandler, sb_irq_num |
call SysMsgBoardNum |
jmp .stop |
@@: |
mov esi, msgSucAtchIRQ |
call SysMsgBoardStr |
end if |
stdcall RegService, my_service, service_proc |
ret |
.stop: |
call sb_reset |
.exit: |
if DEBUG |
mov esi, msgExit |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
endp |
;------------------------------------------------------------------------------- |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_PLAY |
jne @f |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call sb_stop ;to play smth new we must stop smth old |
call pre_fill_data ;fill first and second half of the buffer |
call pre_fill_data ; |
call sb_set_dma ;is it really needed here? Paranoia. |
call sb_play |
xor eax, eax ;set maximum volume |
call sb_set_master_vol |
xor eax, eax |
ret |
;@@: ;all this commented stuff in service proc |
; cmp eax,DEV_STOP ;is never used. Mixer do this virtually, |
; jne @f ;e.g. instead of stopping driver it |
;if DEBUG ;outputs silence |
; mov esi,msgStop |
; call SysMsgBoardStr |
;end if |
; call sb_stop |
; xor eax,eax |
; ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @f |
if DEBUG |
mov esi, msgCallback |
call SysMsgBoardStr |
end if |
mov edi, [edi+input] |
mov eax, [edi] |
mov [callback], eax |
if DEBUG |
call SysMsgBoardNum |
end if |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL;Serge asked me to unlock |
jne @F ;DEV_SET(GET)_MASTERVOL, although mixer doesn't use it. |
;It doesn't use it _in current version_ - but in the future... |
if DEBUG |
mov esi, msgSetVol |
call SysMsgBoardStr |
end if |
mov eax, [edi+input] |
mov eax, [eax] |
call sb_set_master_vol |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
if DEBUG |
mov esi, msgGetVol |
call SysMsgBoardStr |
end if |
mov eax, [edi+output] |
mov edx, [sb_master_vol] |
mov [eax], edx |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
;------------------------------------------------------------------------------- |
align 4 |
proc sb_irq |
mov edx, [sb_base_port];tell the DSP that we have processed IRQ |
add dl, 0xF ;0xF for 16 bit sound, 0xE for 8 bit sound |
in al, dx ;for non-stop sound |
pre_fill_data: |
mov eax, int_flip_flop |
not dword[eax] |
mov eax, [eax] |
test eax, eax |
jns .fill_second_half |
if sb_buffer_size eq small_buffer |
stdcall [callback], SB16Buffer0 ;for 32k buffer |
else if sb_buffer_size eq full_buffer |
stdcall [callback], SB16Buffer0 ;for 64k buffer |
stdcall [callback], SB16Buffer1 ;for 64k buffer |
end if |
xor eax, eax |
not eax |
ret |
.fill_second_half: |
if sb_buffer_size eq small_buffer |
stdcall [callback], SB16Buffer1 ;for 32k buffer |
else if sb_buffer_size eq full_buffer |
stdcall [callback], SB16Buffer2 ;for 64k buffer |
stdcall [callback], SB16Buffer3 ;for 64k buffer |
end if |
xor eax, eax |
not eax |
ret |
endp |
;------------------------------------------------------------------------------- |
align 4 |
proc detect |
.sb_detect_next_port: |
if DEBUG |
inc dword[port_second_digit_num] |
end if |
mov edx, sb_base_port |
add byte[edx], 10h |
cmp byte[edx], 80h |
jbe .sb_try_to_detect_at_specified_port |
;error - no SB card detected |
.sb_not_found_err: |
xor eax, eax |
ret |
.sb_try_to_detect_at_specified_port: |
call sb_reset |
add dl, 8 |
mov ecx, 100 |
.sb_check_port: |
in al, dx |
test al, al ;is DSP port ready to be read? |
jns .sb_port_not_ready |
sub dl, 4 |
in al, dx ;check for AAh response |
add dl, 4 |
cmp al, 0xAA |
jne .sb_port_not_ready |
.sb_card_found: |
and dl, 0xF0 |
add dl, 0xC |
sb_out 0xE1 ;get DSP version |
add dl, 2 |
@@: |
in al, dx |
test al, al ;is DSP port ready to be read? |
jns @b |
sub dl, 4 |
in al, dx ;get major version |
ror eax, 16 |
add dl, 4 |
@@: |
in al, dx |
test al, al ;is DSP port ready to be read? |
jns @b |
sub dl, 4 |
in al, dx ;get minor version |
xor edx, edx |
mov dl, 10 |
div dl |
ror eax, 16 |
xor ah, ah |
mov [sb_DSP_version_int], eax;for internal usage |
if DEBUG |
add [sb_DSP_version], eax |
end if |
ret |
.sb_port_not_ready: |
loop .sb_check_port ;100 retries (~100 microsec.) |
jmp .sb_detect_next_port |
endp |
;------------------------------------------------------------------------------- |
if DEBUG |
proc SysMsgBoardNum ;warning: destroys eax,ebx,ecx,esi |
mov ebx, eax |
mov ecx, 8 |
mov esi, (number_to_out+1) |
.1: |
mov eax, ebx |
and eax, 0xF |
add al, '0' |
cmp al, (10+'0') |
jb @f |
add al, ('A'-'0'-10) |
@@: |
mov [esi+ecx], al |
shr ebx, 4 |
loop .1 |
dec esi |
call SysMsgBoardStr |
ret |
endp |
end if |
;all initialized data place here |
align 4 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
sb_base_port: |
dd 200h ;don't ask me why - see the code&docs |
sound_dma dd sb_dma_num |
;note that 4th DMA channel doesn't exist, it is used for cascade |
;plugging the first DMA controler to the second |
dma_table db 0x87,0x83,0x81,0x82,0xFF,0x8B,0x89,0x8A |
my_service db 'SOUND',0 ;max 16 chars include zero |
if DEBUG |
number_to_out db '0x00000000',13,10,0 |
msgInit db 'detecting hardware...',13,10,0 |
msgExit db 'exiting... May be some problems found?',13,10,0 |
msgPlay db 'start play',13,10,0 |
;msgStop db 'stop play',13,10,0 |
msgCallback db 'set_callback received from the mixer!',13,10 |
db 'callback handler is: ',0 |
msgErrAtchIRQ db 'failed to attach IRQ',(sb_irq_num+'0'),13,10 |
db 'owner',39,'s handler: ',0 |
msgSucAtchIRQ db 'succesfully attached IRQ',(sb_irq_num+'0') |
db ' as hardcoded',13,10,0 |
msgErrRsrvPorts db 'failed to reserve needed ports.',13,10 |
db 'Driver may work unstable',13,10,0 |
msgSetVol db 'DEV_SET_MASTERVOL call came',13,10,0 |
msgGetVol db 'DEV_GET_MASTERVOL call came',13,10,0 |
msgErrDMAsetup db 'failed to setup DMA - bad channel',13,10,0 |
;------------------------------------------------------------------------------- |
msgDSPFound db 'DSP found at port 2' |
label port_second_digit_num dword at $ |
db '00h',13,10,'DSP version ' |
sb_DSP_version: |
db '0.00 - SB' |
sb_DSP_description: |
db 32,32,32,32,13,10,0 |
;------------------------------------------------------------------------------- |
end if |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
;pTempBuf rd 1 |
callback rd 1 |
int_flip_flop rd 1 |
sb_master_vol rd 1 |
sb_DSP_version_int rd 1 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/sceletone.asm |
---|
1,173 → 1,173 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;driver sceletone |
format MS COFF |
DEBUG equ 1 |
API_VERSION equ 0 ;debug |
include 'proc32.inc' |
include 'imports.inc' |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
public START |
public service_proc |
public version |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
SRV_GETVERSION equ 0 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
stdcall RegService, my_service, service_proc |
ret |
.fail: |
.exit: |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc detect |
locals |
last_bus dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, STRIDE |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
xor eax, eax |
inc eax |
ret |
.err: |
xor eax, eax |
ret |
endp |
DEVICE_ID equ 1234; pci device id |
VENDOR_ID equ 5678; device vendor id |
;all initialized data place here |
align 4 |
devices dd (DEVICE_ID shl 16)+VENDOR_ID |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'MY_SERVICE',0 ;max 16 chars include zero |
msgInit db 'detect hardware...',13,10,0 |
msgPCI db 'PCI accsess not supported',13,10,0 |
msgFail db 'device not found',13,10,0 |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;driver sceletone |
format MS COFF |
DEBUG equ 1 |
API_VERSION equ 0 ;debug |
include 'proc32.inc' |
include 'imports.inc' |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
public START |
public service_proc |
public version |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
SRV_GETVERSION equ 0 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
stdcall RegService, my_service, service_proc |
ret |
.fail: |
.exit: |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc detect |
locals |
last_bus dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, STRIDE |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
xor eax, eax |
inc eax |
ret |
.err: |
xor eax, eax |
ret |
endp |
DEVICE_ID equ 1234; pci device id |
VENDOR_ID equ 5678; device vendor id |
;all initialized data place here |
align 4 |
devices dd (DEVICE_ID shl 16)+VENDOR_ID |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'MY_SERVICE',0 ;max 16 chars include zero |
msgInit db 'detect hardware...',13,10,0 |
msgPCI db 'PCI accsess not supported',13,10,0 |
msgFail db 'device not found',13,10,0 |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/sis.asm |
---|
1,1307 → 1,1307 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0x01000100 |
DEBUG_IRQ equ 0 |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
IRQ_REMAP equ 0 |
IRQ_LINE equ 0 |
;irq 0,1,2,8,12,13 íåäîñòóïíû |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
if USE_COM_IRQ |
ATTCH_IRQ equ 0000111010111000b |
end if |
CPU_FREQ equ 2600d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
BIT2 EQU 0x00000004 |
BIT3 EQU 0x00000008 |
BIT4 EQU 0x00000010 |
BIT5 EQU 0x00000020 |
BIT6 EQU 0x00000040 |
BIT7 EQU 0x00000080 |
BIT8 EQU 0x00000100 |
BIT9 EQU 0x00000200 |
BIT10 EQU 0x00000400 |
BIT11 EQU 0x00000800 |
BIT12 EQU 0x00001000 |
BIT13 EQU 0x00002000 |
BIT14 EQU 0x00004000 |
BIT15 EQU 0x00008000 |
BIT16 EQU 0x00010000 |
BIT17 EQU 0x00020000 |
BIT18 EQU 0x00040000 |
BIT19 EQU 0x00080000 |
BIT20 EQU 0x00100000 |
BIT21 EQU 0x00200000 |
BIT22 EQU 0x00400000 |
BIT23 EQU 0x00800000 |
BIT24 EQU 0x00100000 |
BIT25 EQU 0x02000000 |
BIT26 EQU 0x04000000 |
BIT27 EQU 0x08000000 |
BIT28 EQU 0x10000000 |
BIT29 EQU 0x20000000 |
BIT30 EQU 0x40000000 |
BIT31 EQU 0x80000000 |
VID_SIS equ 0x1039 |
CTRL_SIS equ 0x7012 |
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list |
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register |
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index |
PCM_OUT_SR_REG equ 0x18 ; PCM out Status register |
PCM_OUT_PIV_REG equ 0x1a ; PCM out prefetched index |
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index |
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register |
MC_IN_CR_REG equ 0x2b ; MIC in Control Register |
RR equ BIT1 ; reset registers. Nukes all regs |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate |
GLOB_CTRL equ 0x2C ; Global Control |
CTRL_STAT equ 0x30 ; Global Status |
CTRL_CAS equ 0x34 ; Codec Access Semiphore |
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit |
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready |
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status |
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable |
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off |
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset |
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset |
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable |
CODEC_REG_POWERDOWN equ 0x26 |
CODEC_REG_ST equ 0x26 |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call reset_controller |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call SysMsgBoardStr |
if IRQ_REMAP |
pushf |
cli |
mov ebx, [ctrl.int_line] |
in al, 0xA1 |
mov ah, al |
in al, 0x21 |
test ebx, ebx |
jz .skip |
bts ax, bx ;mask old line |
.skip |
bts ax, IRQ_LINE ;mask new ine |
out 0x21, al |
mov al, ah |
out 0xA1, al |
;remap IRQ |
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE |
mov dx, 0x4d0 ;8259 ELCR1 |
in al, dx |
bts ax, IRQ_LINE |
out dx, al ;set level-triggered mode |
mov [ctrl.int_line], IRQ_LINE |
popf |
mov esi, msgRemap |
call SysMsgBoardStr |
end if |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail_msg |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call SysMsgBoardStr |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
;@@: |
; cmp eax, DEV_GET_INFO |
; jne @F |
; mov ebx, [edi+output] |
; stdcall get_dev_info, ebx |
; ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc ac97_irq |
if DEBUG_IRQ |
mov esi, msgIRQ |
call SysMsgBoardStr |
end if |
mov edx, PCM_OUT_CR_REG |
mov al, 0x10 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
mov edx, PCM_OUT_CIV_REG |
call [ctrl.ctrl_read8] |
and eax, 0x1F |
cmp eax, [civ_val] |
je .skip |
mov [civ_val], eax |
dec eax |
and eax, 0x1F |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 |
call [ctrl.ctrl_write8] |
mov eax, [civ_val] |
add eax, 1 |
and eax, 31 |
mov ebx, dword [buff_list+eax*4] |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
ret |
.skip: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov ebx, 0xC0004000 |
mov ecx, 4 |
mov edi, pcmout_bdl |
@@: |
mov [edi], eax |
mov [edi+4], ebx |
mov [edi+32], eax |
mov [edi+4+32], ebx |
mov [edi+64], eax |
mov [edi+4+64], ebx |
mov [edi+96], eax |
mov [edi+4+96], ebx |
mov [edi+128], eax |
mov [edi+4+128], ebx |
mov [edi+160], eax |
mov [edi+4+160], ebx |
mov [edi+192], eax |
mov [edi+4+192], ebx |
mov [edi+224], eax |
mov [edi+4+224], ebx |
add eax, 0x4000 |
add edi, 8 |
loop @B |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
add eax, 0x4000 |
add edi, 4 |
loop @B |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr ;eax |
and ebx, 0xFFF |
add eax, ebx |
mov edx, PCM_OUT_BDL |
call [ctrl.ctrl_write32] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
and eax, not 0x000000C0 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov [ctrl.vendor_ids], msg_SIS |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_controller |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgMixIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax,0xFFFE |
mov [ctrl.codec_io_base], eax |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
mov esi, msgMixMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 |
mov [ctrl.codec_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C |
mov [ctrl.ctrl_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
.default: |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
@@: |
mov [ctrl.int_line], eax |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41 |
and eax, 0xFF |
mov [ctrl.cfg_reg], eax |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_SIS |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
align 4 |
proc reset_controller |
xor eax, eax |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov eax, RR |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc init_codec |
locals |
counter dd ? |
endl |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
cmp eax, 0xFFFFFFFF |
je .err |
test eax, CTRL_ST_CREADY |
jnz .done ;;;;;.ready |
call reset_codec |
test eax, eax |
jz .err |
.ready: |
xor edx, edx ;ac_reg_0 |
call [ctrl.codec_write16] |
xor eax, eax |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_write16] |
mov [counter], 200 ; total 200*5 ms = 1s |
.wait: |
mov eax, 5000 ; wait 5 ms |
call StallExec |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_read16] |
and eax, 0x0F |
cmp eax, 0x0F |
je .done |
sub [counter] , 1 |
jnz .wait |
.err: |
xor eax, eax ; timeout error |
ret |
.done: |
mov eax, 2 ;force set 16-bit 2-channel PCM |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
mov eax, 5000 ; wait 5 ms |
call StallExec |
call detect_codec |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 0x02 |
jz .cold |
call warm_reset |
jnc .ok |
.cold: |
call cold_reset |
jnc .ok |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc warm_reset |
locals |
counter dd ? |
endl |
mov eax, 0x06 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgWarm |
call SysMsgBoardStr |
end if |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_CREADY |
jnz .ok |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgWRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
clc |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
mov eax, 0x02 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 400000 ; wait 400 ms |
call StallExec |
mov [counter], 16 ; total 20*100 ms = 2s |
.wait: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_CREADY |
jnz .ok |
mov eax, 100000 ; wait 100 ms |
call StallExec |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
endp |
align 4 |
play: |
xor eax, eax |
mov [civ_val], eax |
mov edx, PCM_OUT_CIV_REG |
call [ctrl.ctrl_write8] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x1D |
call [ctrl.ctrl_write8] |
xor eax, eax |
ret |
align 4 |
stop: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x0 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ebx, [ctrl.codec_io_base] |
mov ecx, [ctrl.ctrl_io_base] |
mov edx, [ctrl.codec_mem_base] |
mov edi, [ctrl.ctrl_mem_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.codec_io_base], ebx |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov [CTRL_INFO.codec_mem_base], edx |
mov [CTRL_INFO.ctrl_mem_base], edi |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_cntrl], eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_sta], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
mov edx, [ac_reg] |
mov ebx, edx |
shr ebx, 1 |
bt [codec.shadow_flag], ebx |
jc .use_shadow |
call [ctrl.codec_read16] ;change edx !!! |
mov ecx, eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_RCS |
jz .read_ok |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
xor eax,eax |
not eax ;timeout |
ret |
.read_ok: |
mov edx, [ac_reg] |
mov [codec.regs+edx], cx |
bts [codec.shadow_flag], ebx |
mov eax, ecx |
ret |
.use_shadow: |
movzx eax, word [codec.regs+edx] |
ret |
endp |
align 4 |
proc codec_write stdcall, ac_reg:dword |
push eax |
call check_semafore |
and eax, eax |
jz .err |
pop eax |
mov esi, [ac_reg] |
mov edx, esi |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
shr esi, 1 |
bts [codec.shadow_flag], esi |
ret |
.err: |
pop eax |
ret |
endp |
align 4 |
proc codec_check_ready |
mov edx, CTRL_ST |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .not_ready |
xor eax, wax |
inc eax |
ret |
.not_ready: |
xor eax, eax |
ret |
endp |
align 4 |
proc check_semafore |
local counter:DWORD |
mov [counter], 100 |
.l1: |
mov edx, CTRL_CAS |
call [ctrl.ctrl_read8] |
and eax, CAS_FLAG |
jz .ok |
mov eax, 1 |
call StallExec |
sub [counter], 1 |
jnz .l1 |
xor eax, eax |
ret |
align 4 |
.ok: |
xor eax,eax |
inc eax |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_io_r16 |
add edx, [ctrl.codec_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc codec_io_w16 |
add edx, [ctrl.codec_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
include "codec.inc" |
align 4 |
devices dd (CTRL_SIS shl 16)+VID_SIS,msg_AC, set_SIS |
dd 0 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
msg_AC db '7012 AC97 controller',13,10, 0 |
msg_SIS db 'Silicon Integrated Systems',13,10, 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
msgAttchIRQ db 'IRQ line not supported', 13,10, 0 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
;msgNotify db 'call notify',13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgInitCtrl db 'init controller',13,10,0 |
;msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer ...',0 |
msgDone db 'done',13,10,0 |
msgRemap db 'Remap IRQ',13,10,0 |
;msgReg db 'set service handler',13,10,0 |
msgOk db 'service installed',13,10,0 |
msgCold db 'cold reset',13,10,0 |
msgWarm db 'warm reset',13,10,0 |
msgWRFail db 'warm reset failed',13,10,0 |
msgCRFail db 'cold reset failed',13,10,0 |
msgCFail db 'codec not ready',13,10,0 |
msgResetOk db 'reset complete',13,10,0 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
msgPciCmd db 'PCI command ',0 |
msgPciStat db 'PCI status ',0 |
msgCtrlIsaIo db 'controller io base ',0 |
msgMixIsaIo db 'codec io base ',0 |
msgCtrlMMIo db 'controller mmio base ',0 |
msgMixMMIo db 'codec mmio base ',0 |
msgIrqMap db 'AC97 irq map as ',0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0x01000100 |
DEBUG_IRQ equ 0 |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
IRQ_REMAP equ 0 |
IRQ_LINE equ 0 |
;irq 0,1,2,8,12,13 íåäîñòóïíû |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
if USE_COM_IRQ |
ATTCH_IRQ equ 0000111010111000b |
end if |
CPU_FREQ equ 2600d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
BIT2 EQU 0x00000004 |
BIT3 EQU 0x00000008 |
BIT4 EQU 0x00000010 |
BIT5 EQU 0x00000020 |
BIT6 EQU 0x00000040 |
BIT7 EQU 0x00000080 |
BIT8 EQU 0x00000100 |
BIT9 EQU 0x00000200 |
BIT10 EQU 0x00000400 |
BIT11 EQU 0x00000800 |
BIT12 EQU 0x00001000 |
BIT13 EQU 0x00002000 |
BIT14 EQU 0x00004000 |
BIT15 EQU 0x00008000 |
BIT16 EQU 0x00010000 |
BIT17 EQU 0x00020000 |
BIT18 EQU 0x00040000 |
BIT19 EQU 0x00080000 |
BIT20 EQU 0x00100000 |
BIT21 EQU 0x00200000 |
BIT22 EQU 0x00400000 |
BIT23 EQU 0x00800000 |
BIT24 EQU 0x00100000 |
BIT25 EQU 0x02000000 |
BIT26 EQU 0x04000000 |
BIT27 EQU 0x08000000 |
BIT28 EQU 0x10000000 |
BIT29 EQU 0x20000000 |
BIT30 EQU 0x40000000 |
BIT31 EQU 0x80000000 |
VID_SIS equ 0x1039 |
CTRL_SIS equ 0x7012 |
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list |
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register |
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index |
PCM_OUT_SR_REG equ 0x18 ; PCM out Status register |
PCM_OUT_PIV_REG equ 0x1a ; PCM out prefetched index |
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index |
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register |
MC_IN_CR_REG equ 0x2b ; MIC in Control Register |
RR equ BIT1 ; reset registers. Nukes all regs |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate |
GLOB_CTRL equ 0x2C ; Global Control |
CTRL_STAT equ 0x30 ; Global Status |
CTRL_CAS equ 0x34 ; Codec Access Semiphore |
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit |
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready |
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status |
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable |
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off |
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset |
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset |
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable |
CODEC_REG_POWERDOWN equ 0x26 |
CODEC_REG_ST equ 0x26 |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi, [ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call reset_controller |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call SysMsgBoardStr |
if IRQ_REMAP |
pushf |
cli |
mov ebx, [ctrl.int_line] |
in al, 0xA1 |
mov ah, al |
in al, 0x21 |
test ebx, ebx |
jz .skip |
bts ax, bx ;mask old line |
.skip |
bts ax, IRQ_LINE ;mask new ine |
out 0x21, al |
mov al, ah |
out 0xA1, al |
;remap IRQ |
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE |
mov dx, 0x4d0 ;8259 ELCR1 |
in al, dx |
bts ax, IRQ_LINE |
out dx, al ;set level-triggered mode |
mov [ctrl.int_line], IRQ_LINE |
popf |
mov esi, msgRemap |
call SysMsgBoardStr |
end if |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail_msg |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call SysMsgBoardStr |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
;@@: |
; cmp eax, DEV_GET_INFO |
; jne @F |
; mov ebx, [edi+output] |
; stdcall get_dev_info, ebx |
; ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc ac97_irq |
if DEBUG_IRQ |
mov esi, msgIRQ |
call SysMsgBoardStr |
end if |
mov edx, PCM_OUT_CR_REG |
mov al, 0x10 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
mov edx, PCM_OUT_CIV_REG |
call [ctrl.ctrl_read8] |
and eax, 0x1F |
cmp eax, [civ_val] |
je .skip |
mov [civ_val], eax |
dec eax |
and eax, 0x1F |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 |
call [ctrl.ctrl_write8] |
mov eax, [civ_val] |
add eax, 1 |
and eax, 31 |
mov ebx, dword [buff_list+eax*4] |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
ret |
.skip: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov ebx, 0xC0004000 |
mov ecx, 4 |
mov edi, pcmout_bdl |
@@: |
mov [edi], eax |
mov [edi+4], ebx |
mov [edi+32], eax |
mov [edi+4+32], ebx |
mov [edi+64], eax |
mov [edi+4+64], ebx |
mov [edi+96], eax |
mov [edi+4+96], ebx |
mov [edi+128], eax |
mov [edi+4+128], ebx |
mov [edi+160], eax |
mov [edi+4+160], ebx |
mov [edi+192], eax |
mov [edi+4+192], ebx |
mov [edi+224], eax |
mov [edi+4+224], ebx |
add eax, 0x4000 |
add edi, 8 |
loop @B |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
add eax, 0x4000 |
add edi, 4 |
loop @B |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr ;eax |
and ebx, 0xFFF |
add eax, ebx |
mov edx, PCM_OUT_BDL |
call [ctrl.ctrl_write32] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
and eax, not 0x000000C0 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov [ctrl.vendor_ids], msg_SIS |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_controller |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgMixIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFFE |
mov [ctrl.codec_io_base], eax |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
mov esi, msgMixMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 |
mov [ctrl.codec_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C |
mov [ctrl.ctrl_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
.default: |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
@@: |
mov [ctrl.int_line], eax |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41 |
and eax, 0xFF |
mov [ctrl.cfg_reg], eax |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_SIS |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
align 4 |
proc reset_controller |
xor eax, eax |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov eax, RR |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc init_codec |
locals |
counter dd ? |
endl |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
cmp eax, 0xFFFFFFFF |
je .err |
test eax, CTRL_ST_CREADY |
jnz .done ;;;;;.ready |
call reset_codec |
test eax, eax |
jz .err |
.ready: |
xor edx, edx ;ac_reg_0 |
call [ctrl.codec_write16] |
xor eax, eax |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_write16] |
mov [counter], 200 ; total 200*5 ms = 1s |
.wait: |
mov eax, 5000 ; wait 5 ms |
call StallExec |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_read16] |
and eax, 0x0F |
cmp eax, 0x0F |
je .done |
sub [counter] , 1 |
jnz .wait |
.err: |
xor eax, eax ; timeout error |
ret |
.done: |
mov eax, 2 ;force set 16-bit 2-channel PCM |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
mov eax, 5000 ; wait 5 ms |
call StallExec |
call detect_codec |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 0x02 |
jz .cold |
call warm_reset |
jnc .ok |
.cold: |
call cold_reset |
jnc .ok |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc warm_reset |
locals |
counter dd ? |
endl |
mov eax, 0x06 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgWarm |
call SysMsgBoardStr |
end if |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_CREADY |
jnz .ok |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgWRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
clc |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
mov eax, 0x02 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 400000 ; wait 400 ms |
call StallExec |
mov [counter], 16 ; total 20*100 ms = 2s |
.wait: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_CREADY |
jnz .ok |
mov eax, 100000 ; wait 100 ms |
call StallExec |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
endp |
align 4 |
play: |
xor eax, eax |
mov [civ_val], eax |
mov edx, PCM_OUT_CIV_REG |
call [ctrl.ctrl_write8] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x1D |
call [ctrl.ctrl_write8] |
xor eax, eax |
ret |
align 4 |
stop: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x0 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ebx, [ctrl.codec_io_base] |
mov ecx, [ctrl.ctrl_io_base] |
mov edx, [ctrl.codec_mem_base] |
mov edi, [ctrl.ctrl_mem_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.codec_io_base], ebx |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov [CTRL_INFO.codec_mem_base], edx |
mov [CTRL_INFO.ctrl_mem_base], edi |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_cntrl], eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_sta], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
mov edx, [ac_reg] |
mov ebx, edx |
shr ebx, 1 |
bt [codec.shadow_flag], ebx |
jc .use_shadow |
call [ctrl.codec_read16] ;change edx !!! |
mov ecx, eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_RCS |
jz .read_ok |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
xor eax, eax |
not eax ;timeout |
ret |
.read_ok: |
mov edx, [ac_reg] |
mov [codec.regs+edx], cx |
bts [codec.shadow_flag], ebx |
mov eax, ecx |
ret |
.use_shadow: |
movzx eax, word [codec.regs+edx] |
ret |
endp |
align 4 |
proc codec_write stdcall, ac_reg:dword |
push eax |
call check_semafore |
and eax, eax |
jz .err |
pop eax |
mov esi, [ac_reg] |
mov edx, esi |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
shr esi, 1 |
bts [codec.shadow_flag], esi |
ret |
.err: |
pop eax |
ret |
endp |
align 4 |
proc codec_check_ready |
mov edx, CTRL_ST |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .not_ready |
xor eax, wax |
inc eax |
ret |
.not_ready: |
xor eax, eax |
ret |
endp |
align 4 |
proc check_semafore |
local counter:DWORD |
mov [counter], 100 |
.l1: |
mov edx, CTRL_CAS |
call [ctrl.ctrl_read8] |
and eax, CAS_FLAG |
jz .ok |
mov eax, 1 |
call StallExec |
sub [counter], 1 |
jnz .l1 |
xor eax, eax |
ret |
align 4 |
.ok: |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_io_r16 |
add edx, [ctrl.codec_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc codec_io_w16 |
add edx, [ctrl.codec_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
include "codec.inc" |
align 4 |
devices dd (CTRL_SIS shl 16)+VID_SIS,msg_AC, set_SIS |
dd 0 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
msg_AC db '7012 AC97 controller',13,10, 0 |
msg_SIS db 'Silicon Integrated Systems',13,10, 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
msgAttchIRQ db 'IRQ line not supported', 13,10, 0 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
;msgNotify db 'call notify',13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgInitCtrl db 'init controller',13,10,0 |
;msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer ...',0 |
msgDone db 'done',13,10,0 |
msgRemap db 'Remap IRQ',13,10,0 |
;msgReg db 'set service handler',13,10,0 |
msgOk db 'service installed',13,10,0 |
msgCold db 'cold reset',13,10,0 |
msgWarm db 'warm reset',13,10,0 |
msgWRFail db 'warm reset failed',13,10,0 |
msgCRFail db 'cold reset failed',13,10,0 |
msgCFail db 'codec not ready',13,10,0 |
msgResetOk db 'reset complete',13,10,0 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
msgPciCmd db 'PCI command ',0 |
msgPciStat db 'PCI status ',0 |
msgCtrlIsaIo db 'controller io base ',0 |
msgMixIsaIo db 'codec io base ',0 |
msgCtrlMMIo db 'controller mmio base ',0 |
msgMixMMIo db 'codec mmio base ',0 |
msgIrqMap db 'AC97 irq map as ',0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/sound.asm |
---|
1,1507 → 1,1507 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0x01000100 |
DEBUG_IRQ equ 0 |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
IRQ_REMAP equ 0 |
IRQ_LINE equ 0 |
;irq 0,1,2,8,12,13 íåäîñòóïíû |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
if USE_COM_IRQ |
ATTCH_IRQ equ 0000111010111000b |
end if |
CPU_FREQ equ 2600d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
BIT2 EQU 0x00000004 |
BIT3 EQU 0x00000008 |
BIT4 EQU 0x00000010 |
BIT5 EQU 0x00000020 |
BIT6 EQU 0x00000040 |
BIT7 EQU 0x00000080 |
BIT8 EQU 0x00000100 |
BIT9 EQU 0x00000200 |
BIT10 EQU 0x00000400 |
BIT11 EQU 0x00000800 |
BIT12 EQU 0x00001000 |
BIT13 EQU 0x00002000 |
BIT14 EQU 0x00004000 |
BIT15 EQU 0x00008000 |
BIT16 EQU 0x00010000 |
BIT17 EQU 0x00020000 |
BIT18 EQU 0x00040000 |
BIT19 EQU 0x00080000 |
BIT20 EQU 0x00100000 |
BIT21 EQU 0x00200000 |
BIT22 EQU 0x00400000 |
BIT23 EQU 0x00800000 |
BIT24 EQU 0x00100000 |
BIT25 EQU 0x02000000 |
BIT26 EQU 0x04000000 |
BIT27 EQU 0x08000000 |
BIT28 EQU 0x10000000 |
BIT29 EQU 0x20000000 |
BIT30 EQU 0x40000000 |
BIT31 EQU 0x80000000 |
PCM_4 equ BIT20 |
PCM_6 equ BIT21 |
VID_INTEL equ 0x8086 |
VID_NVIDIA equ 0x10DE |
CTRL_ICH equ 0x2415 |
CTRL_ICH0 equ 0x2425 |
CTRL_ICH2 equ 0x2435 |
CTRL_ICH3 equ 0x2445 |
CTRL_ICH4 equ 0x24C5 |
CTRL_ICH5 equ 0x24D5 |
CTRL_ICH6 equ 0x266E |
CTRL_ICH7 equ 0x27DE |
CTRL_NFORCE equ 0x01B1 |
CTRL_NFORCE2 equ 0x006A |
CTRL_NFORCE3 equ 0x00DA |
CTRL_MCP04 equ 0x003A |
CTRL_CK804 equ 0x0059 |
CTRL_CK8 equ 0x008A |
CTRL_CK8S equ 0x00EA |
CTRL_MCP51 equ 0x026B |
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list |
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register |
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index |
PCM_OUT_SR_REG equ 0x16 ; PCM out Status register |
PCM_OUT_PIV_REG equ 0x1a |
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index |
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register |
MC_IN_CR_REG equ 0x2b ; MIC in Control Register |
RR equ BIT1 ; reset registers. Nukes all regs |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate |
GLOB_CTRL equ 0x2C ; Global Control |
CTRL_STAT equ 0x30 ; Global Status |
CTRL_CAS equ 0x34 ; Codec Access Semiphore |
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit |
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready |
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status |
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable |
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off |
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset |
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset |
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable |
CODEC_REG_POWERDOWN equ 0x26 |
CODEC_REG_ST equ 0x26 |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
DEV_GET_POS equ 9 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call reset_controller |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call SysMsgBoardStr |
if IRQ_REMAP |
pushf |
cli |
mov ebx, [ctrl.int_line] |
in al, 0xA1 |
mov ah, al |
in al, 0x21 |
test ebx, ebx |
jz .skip |
bts ax, bx ;mask old line |
.skip |
bts ax, IRQ_LINE ;mask new ine |
out 0x21, al |
mov al, ah |
out 0xA1, al |
;remap IRQ |
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE |
mov dx, 0x4d0 ;8259 ELCR1 |
in al, dx |
bts ax, IRQ_LINE |
out dx, al ;set level-triggered mode |
mov [ctrl.int_line], IRQ_LINE |
popf |
mov esi, msgRemap |
call SysMsgBoardStr |
end if |
mov ebx, [ctrl.int_line] |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call SysMsgBoardStr |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
@@: |
cmp eax, DEV_GET_POS |
jne @F |
mov ebx, 8192 |
mov edx, 0x18 |
xor eax, eax |
call [ctrl.ctrl_read16] |
sub ebx, eax |
shr ebx, 1 |
mov edx, [edi+output] |
mov [edx], ebx |
xor eax, eax |
ret |
;@@: |
; cmp eax, DEV_GET_INFO |
; jne @F |
; mov ebx, [edi+output] |
; stdcall get_dev_info, ebx |
; ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc ac97_irq |
if DEBUG_IRQ |
mov esi, msgIRQ |
call SysMsgBoardStr |
end if |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
cmp eax, 0xffffffff |
je .exit |
test eax, 0x40 |
jnz .do_intr |
test eax, eax |
jz .exit |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
.exit: |
xor eax, eax |
ret |
.do_intr: |
push eax |
mov edx, PCM_OUT_CR_REG |
mov al, 0x10; 0x10 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
mov edx, PCM_OUT_CIV_REG |
call [ctrl.ctrl_read8] |
and eax, 0x1F |
cmp eax, [civ_val] |
je .skip |
mov [civ_val], eax |
dec eax |
and eax, 0x1F |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 ;0x1D |
call [ctrl.ctrl_write8] |
mov eax, [civ_val] |
add eax, 1 |
and eax, 31 |
mov ebx, dword [buff_list+eax*4] |
cmp [ctrl.user_callback], 0 |
je .done |
stdcall [ctrl.user_callback], ebx |
.done: |
pop eax |
and eax, 0x40 |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
or eax, 1 |
ret |
.skip: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 ;0x1D |
call [ctrl.ctrl_write8] |
jmp .done |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov ebx, 0xC0002000 |
mov ecx, 4 |
mov edi, pcmout_bdl |
@@: |
mov [edi], eax |
mov [edi+4], ebx |
mov [edi+32], eax |
mov [edi+4+32], ebx |
mov [edi+64], eax |
mov [edi+4+64], ebx |
mov [edi+96], eax |
mov [edi+4+96], ebx |
mov [edi+128], eax |
mov [edi+4+128], ebx |
mov [edi+160], eax |
mov [edi+4+160], ebx |
mov [edi+192], eax |
mov [edi+4+192], ebx |
mov [edi+224], eax |
mov [edi+4+224], ebx |
add eax, 0x4000 |
add edi, 8 |
loop @B |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
add eax, 0x4000 |
add edi, 4 |
loop @B |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr ;eax |
and ebx, 0xFFF |
add eax, ebx |
mov edx, PCM_OUT_BDL |
call [ctrl.ctrl_write32] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
cmp edx, VID_INTEL |
jne @F |
mov [ctrl.vendor_ids], msg_Intel |
ret |
@@: |
cmp edx, VID_NVIDIA |
jne @F |
mov [ctrl.vendor_ids], msg_NVidia |
ret |
@@: |
.err: |
xor eax, eax |
mov [ctrl.vendor_ids], eax ;something wrong ? |
ret |
endp |
align 4 |
proc init_controller |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgMixIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax,0xFFFE |
mov [ctrl.codec_io_base], eax |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
mov esi, msgMixMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 |
mov [ctrl.codec_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C |
mov [ctrl.ctrl_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
if 0 |
;;patch for some ugly BIOS ICH-ICH5 compatible |
cmp [ctrl.vendor], VID_INTEL |
jne .default |
mov esi, msgIrqMap |
call SysMsgBoardStr |
stdcall PciRead8, 0, 0xF8, 0x61 |
and eax, 0xFF |
call dword2str |
call SysMsgBoardStr |
btr eax, 7 ;when bit 7 set remap disabled |
jnc @F |
xor eax, eax |
jmp @F |
end if |
.default: |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
@@: |
mov [ctrl.int_line], eax |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41 |
and eax, 0xFF |
mov [ctrl.cfg_reg], eax |
mov [ctrl.user_callback], 0 |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_ICH |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
PG_SW equ 0x003 |
PG_NOCACHE equ 0x018 |
align 4 |
proc set_ICH4 |
stdcall MapIoMem,[ctrl.codec_mem_base],0x1000,PG_SW+PG_NOCACHE |
mov [ctrl.codec_mem_base], eax |
stdcall MapIoMem,[ctrl.ctrl_mem_base],0x1000,PG_SW+PG_NOCACHE |
mov [ctrl.ctrl_mem_base], eax |
mov [ctrl.codec_read16], codec_mem_r16 ;virtual |
mov [ctrl.codec_write16], codec_mem_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_mem_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_mem_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_mem_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_mem_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_mem_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_mem_w32 ;virtual |
ret |
endp |
align 4 |
proc reset_controller |
xor eax, eax |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov eax, RR |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc init_codec |
locals |
counter dd ? |
endl |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
cmp eax, 0xFFFFFFFF |
je .err |
test eax, CTRL_ST_CREADY |
jnz .ready |
call reset_codec |
test eax, eax |
jz .err |
.ready: |
xor edx, edx ;ac_reg_0 |
call [ctrl.codec_write16] |
xor eax, eax |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_write16] |
mov [counter], 200 ; total 200*5 ms = 1s |
.wait: |
mov eax, 5000 ; wait 5 ms |
call StallExec |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_read16] |
and eax, 0x0F |
cmp eax, 0x0F |
jz .done |
sub [counter] , 1 |
jnz .wait |
.err: |
xor eax, eax ; timeout error |
ret |
.done: |
mov eax, 2 ;force set 16-bit 2-channel PCM |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
mov eax, 5000 ; wait 5 ms |
call StallExec |
call detect_codec |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 0x02 |
jz .cold |
call warm_reset |
jnc .ok |
.cold: |
call cold_reset |
jnc .ok |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call SysMsgBoardStr |
end if |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc warm_reset |
locals |
counter dd ? |
endl |
mov eax, 0x06 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgWarm |
call SysMsgBoardStr |
end if |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_CREADY |
jnz .ok |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgWRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
clc |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
mov eax, 0x02 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 400000 ; wait 400 ms |
call StallExec |
mov [counter], 16 ; total 20*100 ms = 2s |
.wait: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_CREADY |
jnz .ok |
mov eax, 100000 ; wait 100 ms |
call StallExec |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
endp |
align 4 |
play: |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x1D |
call [ctrl.ctrl_write8] |
xor eax, eax |
ret |
align 4 |
stop: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x0 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ebx, [ctrl.codec_io_base] |
mov ecx, [ctrl.ctrl_io_base] |
mov edx, [ctrl.codec_mem_base] |
mov edi, [ctrl.ctrl_mem_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.codec_io_base], ebx |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov [CTRL_INFO.codec_mem_base], edx |
mov [CTRL_INFO.ctrl_mem_base], edi |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_cntrl], eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_sta], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
mov edx, [ac_reg] |
mov ebx, edx |
shr ebx, 1 |
bt [codec.shadow_flag], ebx |
jc .use_shadow |
call [ctrl.codec_read16] ;change edx !!! |
mov ecx, eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_RCS |
jz .read_ok |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
xor eax,eax |
not eax ;timeout |
ret |
.read_ok: |
mov edx, [ac_reg] |
mov [codec.regs+edx], cx |
bts [codec.shadow_flag], ebx |
mov eax, ecx |
ret |
.use_shadow: |
movzx eax, word [codec.regs+edx] |
ret |
endp |
align 4 |
proc codec_write stdcall, ac_reg:dword |
push eax |
call check_semafore |
and eax, eax |
jz .err |
pop eax |
mov esi, [ac_reg] |
mov edx, esi |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
shr esi, 1 |
bts [codec.shadow_flag], esi |
ret |
.err: |
pop eax |
ret |
endp |
align 4 |
proc codec_check_ready |
mov edx, CTRL_ST |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .not_ready |
xor eax, wax |
inc eax |
ret |
.not_ready: |
xor eax, eax |
ret |
endp |
align 4 |
proc check_semafore |
local counter:DWORD |
mov [counter], 100 |
.l1: |
mov edx, CTRL_CAS |
call [ctrl.ctrl_read8] |
and eax, CAS_FLAG |
jz .ok |
mov eax, 1 |
call StallExec |
sub [counter], 1 |
jnz .l1 |
xor eax, eax |
ret |
align 4 |
.ok: |
xor eax,eax |
inc eax |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx,edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_io_r16 |
add edx, [ctrl.codec_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc codec_io_w16 |
add edx, [ctrl.codec_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; MEMORY MAPPED IO (os depended) |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_mem_r16 |
add edx, [ctrl.codec_mem_base] |
mov ax, word [edx] |
ret |
endp |
align 4 |
proc codec_mem_w16 |
add edx, [ctrl.codec_mem_base] |
mov word [edx], ax |
ret |
endp |
align 4 |
proc ctrl_mem_r8 |
add edx, [ctrl.ctrl_mem_base] |
mov al, [edx] |
ret |
endp |
align 4 |
proc ctrl_mem_r16 |
add edx, [ctrl.ctrl_mem_base] |
mov ax, [edx] |
ret |
endp |
align 4 |
proc ctrl_mem_r32 |
add edx, [ctrl.ctrl_mem_base] |
mov eax, [edx] |
ret |
endp |
align 4 |
proc ctrl_mem_w8 |
add edx, [ctrl.ctrl_mem_base] |
mov [edx], al |
ret |
endp |
align 4 |
proc ctrl_mem_w16 |
add edx, [ctrl.ctrl_mem_base] |
mov [edx], ax |
ret |
endp |
align 4 |
proc ctrl_mem_w32 |
add edx, [ctrl.ctrl_mem_base] |
mov [edx], eax |
ret |
endp |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
include "codec.inc" |
align 4 |
devices dd (CTRL_ICH shl 16)+VID_INTEL,msg_ICH, set_ICH |
dd (CTRL_ICH0 shl 16)+VID_INTEL,msg_ICH0,set_ICH |
dd (CTRL_ICH2 shl 16)+VID_INTEL,msg_ICH2,set_ICH |
dd (CTRL_ICH3 shl 16)+VID_INTEL,msg_ICH3,set_ICH |
dd (CTRL_ICH4 shl 16)+VID_INTEL,msg_ICH4,set_ICH4 |
dd (CTRL_ICH5 shl 16)+VID_INTEL,msg_ICH5,set_ICH4 |
dd (CTRL_ICH6 shl 16)+VID_INTEL,msg_ICH6,set_ICH4 |
dd (CTRL_ICH7 shl 16)+VID_INTEL,msg_ICH7,set_ICH4 |
dd (CTRL_NFORCE shl 16)+VID_NVIDIA,msg_NForce, set_ICH |
dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA,msg_NForce2,set_ICH |
dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA,msg_NForce3,set_ICH |
dd (CTRL_MCP04 shl 16)+VID_NVIDIA,msg_MCP04,set_ICH |
dd (CTRL_CK804 shl 16)+VID_NVIDIA,msg_CK804,set_ICH |
dd (CTRL_CK8 shl 16)+VID_NVIDIA,msg_CK8,set_ICH |
dd (CTRL_CK8S shl 16)+VID_NVIDIA,msg_CK8S,set_ICH |
dd (CTRL_MCP51 shl 16)+VID_NVIDIA,msg_MCP51,set_ICH |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
msg_ICH db '802801AA (ICH)', 13,10, 0 |
msg_ICH0 db '802801AB (ICH0)', 13,10, 0 |
msg_ICH2 db '802801BA (ICH2)', 13,10, 0 |
msg_ICH3 db '802801CA (ICH3)', 13,10, 0 |
msg_ICH4 db '802801DB (ICH4)', 13,10, 0 |
msg_ICH5 db '802801EB (ICH5)', 13,10, 0 |
msg_ICH6 db '802801FB (ICH6)', 13,10, 0 |
msg_ICH7 db '802801GB (ICH7)', 13,10, 0 |
msg_Intel db 'Intel ', 0 |
msg_NForce db 'NForce', 13,10, 0 |
msg_NForce2 db 'NForce 2', 13,10, 0 |
msg_NForce3 db 'NForce 3', 13,10, 0 |
msg_MCP04 db 'NForce MCP04',13,10, 0 |
msg_CK804 db 'NForce CK804',13,10, 0 |
msg_CK8 db 'NForce CK8', 13,10, 0 |
msg_CK8S db 'NForce CK8S', 13,10, 0 |
msg_MCP51 db 'NForce MCP51',13,10, 0 |
msg_NVidia db 'NVidia', 0 |
szKernel db 'KERNEL', 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
msgAttchIRQ db 'IRQ line not supported', 13,10, 0 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
;msgNotify db 'call notify',13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgInitCtrl db 'init controller',13,10,0 |
;msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer ...',0 |
msgDone db 'done',13,10,0 |
msgRemap db 'Remap IRQ',13,10,0 |
;msgReg db 'set service handler',13,10,0 |
msgOk db 'service installed',13,10,0 |
msgCold db 'cold reset',13,10,0 |
msgWarm db 'warm reset',13,10,0 |
msgWRFail db 'warm reset failed',13,10,0 |
msgCRFail db 'cold reset failed',13,10,0 |
msgCFail db 'codec not ready',13,10,0 |
msgResetOk db 'reset complete',13,10,0 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
msgPciCmd db 'PCI command ',0 |
msgPciStat db 'PCI status ',0 |
msgCtrlIsaIo db 'controller io base ',0 |
msgMixIsaIo db 'codec io base ',0 |
msgCtrlMMIo db 'controller mmio base ',0 |
msgMixMMIo db 'codec mmio base ',0 |
msgIrqMap db 'AC97 irq map as ',0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0x01000100 |
DEBUG_IRQ equ 0 |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
IRQ_REMAP equ 0 |
IRQ_LINE equ 0 |
;irq 0,1,2,8,12,13 íåäîñòóïíû |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
if USE_COM_IRQ |
ATTCH_IRQ equ 0000111010111000b |
end if |
CPU_FREQ equ 2600d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
BIT2 EQU 0x00000004 |
BIT3 EQU 0x00000008 |
BIT4 EQU 0x00000010 |
BIT5 EQU 0x00000020 |
BIT6 EQU 0x00000040 |
BIT7 EQU 0x00000080 |
BIT8 EQU 0x00000100 |
BIT9 EQU 0x00000200 |
BIT10 EQU 0x00000400 |
BIT11 EQU 0x00000800 |
BIT12 EQU 0x00001000 |
BIT13 EQU 0x00002000 |
BIT14 EQU 0x00004000 |
BIT15 EQU 0x00008000 |
BIT16 EQU 0x00010000 |
BIT17 EQU 0x00020000 |
BIT18 EQU 0x00040000 |
BIT19 EQU 0x00080000 |
BIT20 EQU 0x00100000 |
BIT21 EQU 0x00200000 |
BIT22 EQU 0x00400000 |
BIT23 EQU 0x00800000 |
BIT24 EQU 0x00100000 |
BIT25 EQU 0x02000000 |
BIT26 EQU 0x04000000 |
BIT27 EQU 0x08000000 |
BIT28 EQU 0x10000000 |
BIT29 EQU 0x20000000 |
BIT30 EQU 0x40000000 |
BIT31 EQU 0x80000000 |
PCM_4 equ BIT20 |
PCM_6 equ BIT21 |
VID_INTEL equ 0x8086 |
VID_NVIDIA equ 0x10DE |
CTRL_ICH equ 0x2415 |
CTRL_ICH0 equ 0x2425 |
CTRL_ICH2 equ 0x2435 |
CTRL_ICH3 equ 0x2445 |
CTRL_ICH4 equ 0x24C5 |
CTRL_ICH5 equ 0x24D5 |
CTRL_ICH6 equ 0x266E |
CTRL_ICH7 equ 0x27DE |
CTRL_NFORCE equ 0x01B1 |
CTRL_NFORCE2 equ 0x006A |
CTRL_NFORCE3 equ 0x00DA |
CTRL_MCP04 equ 0x003A |
CTRL_CK804 equ 0x0059 |
CTRL_CK8 equ 0x008A |
CTRL_CK8S equ 0x00EA |
CTRL_MCP51 equ 0x026B |
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list |
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register |
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index |
PCM_OUT_SR_REG equ 0x16 ; PCM out Status register |
PCM_OUT_PIV_REG equ 0x1a |
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index |
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register |
MC_IN_CR_REG equ 0x2b ; MIC in Control Register |
RR equ BIT1 ; reset registers. Nukes all regs |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate |
GLOB_CTRL equ 0x2C ; Global Control |
CTRL_STAT equ 0x30 ; Global Status |
CTRL_CAS equ 0x34 ; Codec Access Semiphore |
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit |
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready |
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status |
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable |
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off |
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset |
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset |
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable |
CODEC_REG_POWERDOWN equ 0x26 |
CODEC_REG_ST equ 0x26 |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
DEV_GET_POS equ 9 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi, [ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call reset_controller |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call SysMsgBoardStr |
if IRQ_REMAP |
pushf |
cli |
mov ebx, [ctrl.int_line] |
in al, 0xA1 |
mov ah, al |
in al, 0x21 |
test ebx, ebx |
jz .skip |
bts ax, bx ;mask old line |
.skip |
bts ax, IRQ_LINE ;mask new ine |
out 0x21, al |
mov al, ah |
out 0xA1, al |
;remap IRQ |
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE |
mov dx, 0x4d0 ;8259 ELCR1 |
in al, dx |
bts ax, IRQ_LINE |
out dx, al ;set level-triggered mode |
mov [ctrl.int_line], IRQ_LINE |
popf |
mov esi, msgRemap |
call SysMsgBoardStr |
end if |
mov ebx, [ctrl.int_line] |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call SysMsgBoardStr |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
@@: |
cmp eax, DEV_GET_POS |
jne @F |
mov ebx, 8192 |
mov edx, 0x18 |
xor eax, eax |
call [ctrl.ctrl_read16] |
sub ebx, eax |
shr ebx, 1 |
mov edx, [edi+output] |
mov [edx], ebx |
xor eax, eax |
ret |
;@@: |
; cmp eax, DEV_GET_INFO |
; jne @F |
; mov ebx, [edi+output] |
; stdcall get_dev_info, ebx |
; ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc ac97_irq |
if DEBUG_IRQ |
mov esi, msgIRQ |
call SysMsgBoardStr |
end if |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
cmp eax, 0xffffffff |
je .exit |
test eax, 0x40 |
jnz .do_intr |
test eax, eax |
jz .exit |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
.exit: |
xor eax, eax |
ret |
.do_intr: |
push eax |
mov edx, PCM_OUT_CR_REG |
mov al, 0x10; 0x10 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
mov edx, PCM_OUT_CIV_REG |
call [ctrl.ctrl_read8] |
and eax, 0x1F |
cmp eax, [civ_val] |
je .skip |
mov [civ_val], eax |
dec eax |
and eax, 0x1F |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 ;0x1D |
call [ctrl.ctrl_write8] |
mov eax, [civ_val] |
add eax, 1 |
and eax, 31 |
mov ebx, dword [buff_list+eax*4] |
cmp [ctrl.user_callback], 0 |
je .done |
stdcall [ctrl.user_callback], ebx |
.done: |
pop eax |
and eax, 0x40 |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
or eax, 1 |
ret |
.skip: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 ;0x1D |
call [ctrl.ctrl_write8] |
jmp .done |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov ebx, 0xC0002000 |
mov ecx, 4 |
mov edi, pcmout_bdl |
@@: |
mov [edi], eax |
mov [edi+4], ebx |
mov [edi+32], eax |
mov [edi+4+32], ebx |
mov [edi+64], eax |
mov [edi+4+64], ebx |
mov [edi+96], eax |
mov [edi+4+96], ebx |
mov [edi+128], eax |
mov [edi+4+128], ebx |
mov [edi+160], eax |
mov [edi+4+160], ebx |
mov [edi+192], eax |
mov [edi+4+192], ebx |
mov [edi+224], eax |
mov [edi+4+224], ebx |
add eax, 0x4000 |
add edi, 8 |
loop @B |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
add eax, 0x4000 |
add edi, 4 |
loop @B |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr ;eax |
and ebx, 0xFFF |
add eax, ebx |
mov edx, PCM_OUT_BDL |
call [ctrl.ctrl_write32] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
cmp edx, VID_INTEL |
jne @F |
mov [ctrl.vendor_ids], msg_Intel |
ret |
@@: |
cmp edx, VID_NVIDIA |
jne @F |
mov [ctrl.vendor_ids], msg_NVidia |
ret |
@@: |
.err: |
xor eax, eax |
mov [ctrl.vendor_ids], eax ;something wrong ? |
ret |
endp |
align 4 |
proc init_controller |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgMixIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFFE |
mov [ctrl.codec_io_base], eax |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
mov esi, msgMixMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 |
mov [ctrl.codec_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C |
mov [ctrl.ctrl_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
if 0 |
;;patch for some ugly BIOS ICH-ICH5 compatible |
cmp [ctrl.vendor], VID_INTEL |
jne .default |
mov esi, msgIrqMap |
call SysMsgBoardStr |
stdcall PciRead8, 0, 0xF8, 0x61 |
and eax, 0xFF |
call dword2str |
call SysMsgBoardStr |
btr eax, 7 ;when bit 7 set remap disabled |
jnc @F |
xor eax, eax |
jmp @F |
end if |
.default: |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
@@: |
mov [ctrl.int_line], eax |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41 |
and eax, 0xFF |
mov [ctrl.cfg_reg], eax |
mov [ctrl.user_callback], 0 |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_ICH |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
PG_SW equ 0x003 |
PG_NOCACHE equ 0x018 |
align 4 |
proc set_ICH4 |
stdcall MapIoMem, [ctrl.codec_mem_base], 0x1000, PG_SW+PG_NOCACHE |
mov [ctrl.codec_mem_base], eax |
stdcall MapIoMem, [ctrl.ctrl_mem_base], 0x1000, PG_SW+PG_NOCACHE |
mov [ctrl.ctrl_mem_base], eax |
mov [ctrl.codec_read16], codec_mem_r16 ;virtual |
mov [ctrl.codec_write16], codec_mem_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_mem_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_mem_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_mem_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_mem_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_mem_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_mem_w32 ;virtual |
ret |
endp |
align 4 |
proc reset_controller |
xor eax, eax |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov eax, RR |
mov edx, PCM_IN_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
call [ctrl.ctrl_write8] |
mov edx, MC_IN_CR_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc init_codec |
locals |
counter dd ? |
endl |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
cmp eax, 0xFFFFFFFF |
je .err |
test eax, CTRL_ST_CREADY |
jnz .ready |
call reset_codec |
test eax, eax |
jz .err |
.ready: |
xor edx, edx ;ac_reg_0 |
call [ctrl.codec_write16] |
xor eax, eax |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_write16] |
mov [counter], 200 ; total 200*5 ms = 1s |
.wait: |
mov eax, 5000 ; wait 5 ms |
call StallExec |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_read16] |
and eax, 0x0F |
cmp eax, 0x0F |
jz .done |
sub [counter] , 1 |
jnz .wait |
.err: |
xor eax, eax ; timeout error |
ret |
.done: |
mov eax, 2 ;force set 16-bit 2-channel PCM |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
mov eax, 5000 ; wait 5 ms |
call StallExec |
call detect_codec |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 0x02 |
jz .cold |
call warm_reset |
jnc .ok |
.cold: |
call cold_reset |
jnc .ok |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call SysMsgBoardStr |
end if |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc warm_reset |
locals |
counter dd ? |
endl |
mov eax, 0x06 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgWarm |
call SysMsgBoardStr |
end if |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_CREADY |
jnz .ok |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgWRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
clc |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
mov eax, 0x02 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 400000 ; wait 400 ms |
call StallExec |
mov [counter], 16 ; total 20*100 ms = 2s |
.wait: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_CREADY |
jnz .ok |
mov eax, 100000 ; wait 100 ms |
call StallExec |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
endp |
align 4 |
play: |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x1D |
call [ctrl.ctrl_write8] |
xor eax, eax |
ret |
align 4 |
stop: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x0 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ebx, [ctrl.codec_io_base] |
mov ecx, [ctrl.ctrl_io_base] |
mov edx, [ctrl.codec_mem_base] |
mov edi, [ctrl.ctrl_mem_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.codec_io_base], ebx |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov [CTRL_INFO.codec_mem_base], edx |
mov [CTRL_INFO.ctrl_mem_base], edi |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_cntrl], eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_sta], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
mov edx, [ac_reg] |
mov ebx, edx |
shr ebx, 1 |
bt [codec.shadow_flag], ebx |
jc .use_shadow |
call [ctrl.codec_read16] ;change edx !!! |
mov ecx, eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_RCS |
jz .read_ok |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
xor eax, eax |
not eax ;timeout |
ret |
.read_ok: |
mov edx, [ac_reg] |
mov [codec.regs+edx], cx |
bts [codec.shadow_flag], ebx |
mov eax, ecx |
ret |
.use_shadow: |
movzx eax, word [codec.regs+edx] |
ret |
endp |
align 4 |
proc codec_write stdcall, ac_reg:dword |
push eax |
call check_semafore |
and eax, eax |
jz .err |
pop eax |
mov esi, [ac_reg] |
mov edx, esi |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
shr esi, 1 |
bts [codec.shadow_flag], esi |
ret |
.err: |
pop eax |
ret |
endp |
align 4 |
proc codec_check_ready |
mov edx, CTRL_ST |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .not_ready |
xor eax, wax |
inc eax |
ret |
.not_ready: |
xor eax, eax |
ret |
endp |
align 4 |
proc check_semafore |
local counter:DWORD |
mov [counter], 100 |
.l1: |
mov edx, CTRL_CAS |
call [ctrl.ctrl_read8] |
and eax, CAS_FLAG |
jz .ok |
mov eax, 1 |
call StallExec |
sub [counter], 1 |
jnz .l1 |
xor eax, eax |
ret |
align 4 |
.ok: |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_io_r16 |
add edx, [ctrl.codec_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc codec_io_w16 |
add edx, [ctrl.codec_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; MEMORY MAPPED IO (os depended) |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_mem_r16 |
add edx, [ctrl.codec_mem_base] |
mov ax, word [edx] |
ret |
endp |
align 4 |
proc codec_mem_w16 |
add edx, [ctrl.codec_mem_base] |
mov word [edx], ax |
ret |
endp |
align 4 |
proc ctrl_mem_r8 |
add edx, [ctrl.ctrl_mem_base] |
mov al, [edx] |
ret |
endp |
align 4 |
proc ctrl_mem_r16 |
add edx, [ctrl.ctrl_mem_base] |
mov ax, [edx] |
ret |
endp |
align 4 |
proc ctrl_mem_r32 |
add edx, [ctrl.ctrl_mem_base] |
mov eax, [edx] |
ret |
endp |
align 4 |
proc ctrl_mem_w8 |
add edx, [ctrl.ctrl_mem_base] |
mov [edx], al |
ret |
endp |
align 4 |
proc ctrl_mem_w16 |
add edx, [ctrl.ctrl_mem_base] |
mov [edx], ax |
ret |
endp |
align 4 |
proc ctrl_mem_w32 |
add edx, [ctrl.ctrl_mem_base] |
mov [edx], eax |
ret |
endp |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
include "codec.inc" |
align 4 |
devices dd (CTRL_ICH shl 16)+VID_INTEL,msg_ICH, set_ICH |
dd (CTRL_ICH0 shl 16)+VID_INTEL,msg_ICH0,set_ICH |
dd (CTRL_ICH2 shl 16)+VID_INTEL,msg_ICH2,set_ICH |
dd (CTRL_ICH3 shl 16)+VID_INTEL,msg_ICH3,set_ICH |
dd (CTRL_ICH4 shl 16)+VID_INTEL,msg_ICH4,set_ICH4 |
dd (CTRL_ICH5 shl 16)+VID_INTEL,msg_ICH5,set_ICH4 |
dd (CTRL_ICH6 shl 16)+VID_INTEL,msg_ICH6,set_ICH4 |
dd (CTRL_ICH7 shl 16)+VID_INTEL,msg_ICH7,set_ICH4 |
dd (CTRL_NFORCE shl 16)+VID_NVIDIA,msg_NForce, set_ICH |
dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA,msg_NForce2,set_ICH |
dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA,msg_NForce3,set_ICH |
dd (CTRL_MCP04 shl 16)+VID_NVIDIA,msg_MCP04,set_ICH |
dd (CTRL_CK804 shl 16)+VID_NVIDIA,msg_CK804,set_ICH |
dd (CTRL_CK8 shl 16)+VID_NVIDIA,msg_CK8,set_ICH |
dd (CTRL_CK8S shl 16)+VID_NVIDIA,msg_CK8S,set_ICH |
dd (CTRL_MCP51 shl 16)+VID_NVIDIA,msg_MCP51,set_ICH |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
msg_ICH db '802801AA (ICH)', 13,10, 0 |
msg_ICH0 db '802801AB (ICH0)', 13,10, 0 |
msg_ICH2 db '802801BA (ICH2)', 13,10, 0 |
msg_ICH3 db '802801CA (ICH3)', 13,10, 0 |
msg_ICH4 db '802801DB (ICH4)', 13,10, 0 |
msg_ICH5 db '802801EB (ICH5)', 13,10, 0 |
msg_ICH6 db '802801FB (ICH6)', 13,10, 0 |
msg_ICH7 db '802801GB (ICH7)', 13,10, 0 |
msg_Intel db 'Intel ', 0 |
msg_NForce db 'NForce', 13,10, 0 |
msg_NForce2 db 'NForce 2', 13,10, 0 |
msg_NForce3 db 'NForce 3', 13,10, 0 |
msg_MCP04 db 'NForce MCP04',13,10, 0 |
msg_CK804 db 'NForce CK804',13,10, 0 |
msg_CK8 db 'NForce CK8', 13,10, 0 |
msg_CK8S db 'NForce CK8S', 13,10, 0 |
msg_MCP51 db 'NForce MCP51',13,10, 0 |
msg_NVidia db 'NVidia', 0 |
szKernel db 'KERNEL', 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
msgAttchIRQ db 'IRQ line not supported', 13,10, 0 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
;msgNotify db 'call notify',13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgInitCtrl db 'init controller',13,10,0 |
;msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer ...',0 |
msgDone db 'done',13,10,0 |
msgRemap db 'Remap IRQ',13,10,0 |
;msgReg db 'set service handler',13,10,0 |
msgOk db 'service installed',13,10,0 |
msgCold db 'cold reset',13,10,0 |
msgWarm db 'warm reset',13,10,0 |
msgWRFail db 'warm reset failed',13,10,0 |
msgCRFail db 'cold reset failed',13,10,0 |
msgCFail db 'codec not ready',13,10,0 |
msgResetOk db 'reset complete',13,10,0 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
msgPciCmd db 'PCI command ',0 |
msgPciStat db 'PCI status ',0 |
msgCtrlIsaIo db 'controller io base ',0 |
msgMixIsaIo db 'codec io base ',0 |
msgCtrlMMIo db 'controller mmio base ',0 |
msgMixMMIo db 'codec mmio base ',0 |
msgIrqMap db 'AC97 irq map as ',0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/uart.asm |
---|
1,976 → 1,976 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0 |
UART_VERSION equ API_VERSION |
PG_SW equ 0x003 |
page_tabs equ 0xFDC00000 ;hack |
OS_BASE equ 0x80000000 |
SLOT_BASE equ (OS_BASE+0x0080000) |
TASK_COUNT equ (OS_BASE+0x0003004) |
CURRENT_TASK equ (OS_BASE+0x0003000) |
struc APPOBJ ;common object header |
{ |
.magic dd ? ; |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
}; |
virtual at 0 |
APPOBJ APPOBJ |
end virtual |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
DEBUG equ 1 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
THR_REG equ 0; x3f8 ;transtitter/reciever |
IER_REG equ 1; x3f9 ;interrupt enable |
IIR_REG equ 2; x3fA ;interrupt info |
LCR_REG equ 3; x3FB ;line control |
MCR_REG equ 4; x3FC ;modem control |
LSR_REG equ 5; x3FD ;line status |
MSR_REG equ 6; x3FE ;modem status |
LCR_5BIT equ 0x00 |
LCR_6BIT equ 0x01 |
LCR_7BIT equ 0x02 |
LCR_8BIT equ 0x03 |
LCR_STOP_1 equ 0x00 |
LCR_STOP_2 equ 0x04 |
LCR_PARITY equ 0x08 |
LCR_EVEN equ 0x10 |
LCR_STICK equ 0x20 |
LCR_BREAK equ 0x40 |
LCR_DLAB equ 0x80 |
LSR_DR equ 0x01 ;data ready |
LSR_OE equ 0x02 ;overrun error |
LSR_PE equ 0x04 ;parity error |
LSR_FE equ 0x08 ;framing error |
LSR_BI equ 0x10 ;break interrupt |
LSR_THRE equ 0x20 ;transmitter holding empty |
LSR_TEMT equ 0x40 ;transmitter empty |
LSR_FER equ 0x80 ;FIFO error |
FCR_EFIFO equ 0x01 ;enable FIFO |
FCR_CRB equ 0x02 ;clear reciever FIFO |
FCR_CXMIT equ 0x04 ;clear transmitter FIFO |
FCR_RDY equ 0x08 ;set RXRDY and TXRDY pins |
FCR_FIFO_1 equ 0x00 ;1 byte trigger |
FCR_FIFO_4 equ 0x40 ;4 bytes trigger |
FCR_FIFO_8 equ 0x80 ;8 bytes trigger |
FCR_FIFO_14 equ 0xC0 ;14 bytes trigger |
IIR_INTR equ 0x01 ;1= no interrupts |
IER_RDAI equ 0x01 ;reciever data interrupt |
IER_THRI equ 0x02 ;transmitter empty interrupt |
IER_LSI equ 0x04 ;line status interrupt |
IER_MSI equ 0x08 ;modem status interrupt |
MCR_DTR equ 0x01 ;0-> DTR=1, 1-> DTR=0 |
MCR_RTS equ 0x02 ;0-> RTS=1, 1-> RTS=0 |
MCR_OUT_1 equ 0x04 ;0-> OUT1=1, 1-> OUT1=0 |
MCR_OUT_2 equ 0x08 ;0-> OUT2=1, 1-> OUT2=0; enable intr |
MCR_LOOP equ 0x10 ;lopback mode |
MSR_DCTS equ 0x01 ;delta clear to send |
MSR_DDSR equ 0x02 ;delta data set redy |
MSR_TERI equ 0x04 ;trailinh edge of ring |
MSR_DDCD equ 0x08 ;delta carrier detect |
RATE_50 equ 0 |
RATE_75 equ 1 |
RATE_110 equ 2 |
RATE_134 equ 3 |
RATE_150 equ 4 |
RATE_300 equ 5 |
RATE_600 equ 6 |
RATE_1200 equ 7 |
RATE_1800 equ 8 |
RATE_2000 equ 9 |
RATE_2400 equ 10 |
RATE_3600 equ 11 |
RATE_4800 equ 12 |
RATE_7200 equ 13 |
RATE_9600 equ 14 |
RATE_19200 equ 15 |
RATE_38400 equ 16 |
RATE_57600 equ 17 |
RATE_115200 equ 18 |
COM_1 equ 1 |
COM_2 equ 2 |
COM_3 equ 3 |
COM_4 equ 4 |
COM_MAX equ 2 ;only two port supported |
COM_1_BASE equ 0x3F8 |
COM_2_BASE equ 0x2F8 |
COM_1_IRQ equ 4 |
COM_2_IRQ equ 3 |
UART_CLOSED equ 0 |
UART_TRANSMIT equ 1 |
UART_STOP equ 2 |
struc UART |
{ |
.lock dd ? |
.base dd ? |
.lcr_reg dd ? |
.mcr_reg dd ? |
.rate dd ? |
.mode dd ? |
.state dd ? |
.rcvr_buff dd ? |
.rcvr_rp dd ? |
.rcvr_wp dd ? |
.rcvr_count dd ? |
.rcvr_top dd ? |
.xmit_buff dd ? |
.xmit_rp dd ? |
.xmit_wp dd ? |
.xmit_count dd ? |
.xmit_free dd ? |
.xmit_top dd ? |
} |
virtual at 0 |
UART UART |
end virtual |
UART_SIZE equ 18*4 |
struc CONNECTION |
{ |
.magic dd ? ;'CNCT' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.id dd ? ;reserved |
.uart dd ? ;uart pointer |
} |
virtual at 0 |
CONNECTION CONNECTION |
end virtual |
CONNECTION_SIZE equ 7*4 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
mov eax, UART_SIZE |
call Kmalloc |
test eax, eax |
jz .fail |
mov [com1], eax |
mov edi, eax |
mov ecx, UART_SIZE/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [com1] |
mov [eax+UART.base], COM_1_BASE |
stdcall AllocKernelSpace, 32768 |
mov edi, [com1] |
mov edx, eax |
mov [edi+UART.rcvr_buff], eax |
add eax, 8192 |
mov [edi+UART.rcvr_top], eax |
add eax, 8192 |
mov [edi+UART.xmit_buff], eax |
add eax, 8192 |
mov [edi+UART.xmit_top], eax |
call AllocPage |
test eax, eax |
jz .fail |
shr edx, 12 |
or eax, PG_SW |
mov [page_tabs+edx*4], eax |
mov [page_tabs+edx*4+8], eax |
call AllocPage |
test eax, eax |
jz .fail |
or eax, PG_SW |
mov [page_tabs+edx*4+4], eax |
mov [page_tabs+edx*4+12], eax |
call AllocPage |
test eax, eax |
jz .fail |
or eax, PG_SW |
mov [page_tabs+edx*4+16], eax |
mov [page_tabs+edx*4+24], eax |
call AllocPage |
test eax, eax |
jz .fail |
or eax, PG_SW |
mov [page_tabs+edx*4+20], eax |
mov [page_tabs+edx*4+28], eax |
mov eax, [edi+UART.rcvr_buff] |
invlpg [eax] |
invlpg [eax+0x1000] |
invlpg [eax+0x2000] |
invlpg [eax+0x3000] |
invlpg [eax+0x4000] |
invlpg [eax+0x5000] |
invlpg [eax+0x6000] |
invlpg [eax+0x7000] |
mov eax, edi |
call uart_reset.internal ;eax= uart |
stdcall AttachIntHandler, COM_1_IRQ, com_1_isr, dword 0 |
stdcall RegService, sz_uart_srv, service_proc |
ret |
.fail: |
.stop: |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
SRV_GETVERSION equ 0 |
PORT_OPEN equ 1 |
PORT_CLOSE equ 2 |
PORT_RESET equ 3 |
PORT_SETMODE equ 4 |
PORT_GETMODE equ 5 |
PORT_SETMCR equ 6 |
PORT_GETMCR equ 7 |
PORT_READ equ 8 |
PORT_WRITE equ 9 |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, PORT_WRITE |
ja .fail |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword UART_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, PORT_OPEN |
jne @F |
cmp [ebx+out_size], 4 |
jne .fail |
mov ebx, [ebx+input] |
mov eax, [ebx] |
call uart_open |
mov ebx, [ioctl] |
mov ebx, [ebx+output] |
mov [ebx], ecx |
ret |
@@: |
mov esi, [ebx+input] ;input buffer |
mov edi, [ebx+output] |
call [uart_func+eax*4] |
ret |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
; param |
; esi= input buffer |
; +0 connection |
; |
; retval |
; eax= error code |
align 4 |
uart_reset: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
; set mode 2400 bod 8-bit |
; disable DTR & RTS |
; clear FIFO |
; clear pending interrupts |
; |
; param |
; eax= uart |
align 4 |
.internal: |
mov esi, eax |
mov [eax+UART.state], UART_CLOSED |
mov edx, [eax+UART.base] |
add edx, MCR_REG |
xor eax, eax |
out dx, al ;clear DTR & RTS |
mov eax, esi |
mov ebx, RATE_2400 |
mov ecx, LCR_8BIT+LCR_STOP_1 |
call uart_set_mode.internal |
mov edx, [esi+UART.base] |
add edx, IIR_REG |
mov eax,FCR_EFIFO+FCR_CRB+FCR_CXMIT+FCR_FIFO_14 |
out dx, al |
.clear_RB: |
mov edx, [esi+UART.base] |
add edx, LSR_REG |
in al, dx |
test eax, LSR_DR |
jz @F |
mov edx, [esi+UART.base] |
in al, dx |
jmp .clear_RB |
@@: |
mov edx, [esi+UART.base] |
add edx, IER_REG |
mov eax,IER_RDAI+IER_THRI+IER_LSI |
out dx, al |
.clear_IIR: |
mov edx, [esi+UART.base] |
add edx, IIR_REG |
in al, dx |
test al, IIR_INTR |
jnz .done |
shr eax, 1 |
and eax, 3 |
jnz @F |
mov edx, [esi+UART.base] |
add edx, MSR_REG |
in al, dx |
jmp .clear_IIR |
@@: |
cmp eax, 1 |
je .clear_IIR |
cmp eax, 2 |
jne @F |
mov edx, [esi+UART.base] |
in al, dx |
jmp .clear_IIR |
@@: |
mov edx, [esi+UART.base] |
add edx, LSR_REG |
in al, dx |
jmp .clear_IIR |
.done: |
mov edi, [esi+UART.rcvr_buff] |
mov ecx, 8192/4 |
xor eax, eax |
mov [esi+UART.rcvr_rp], edi |
mov [esi+UART.rcvr_wp], edi |
mov [esi+UART.rcvr_count], eax |
cld |
rep stosd |
mov edi, [esi+UART.xmit_buff] |
mov ecx, 8192/4 |
mov [esi+UART.xmit_rp], edi |
mov [esi+UART.xmit_wp], edi |
mov [esi+UART.xmit_count], eax |
mov [esi+UART.xmit_free], 8192 |
rep stosd |
ret ;eax= 0 |
.fail: |
or eax, -1 |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 rate |
; +8 mode |
; |
; retval |
; eax= error code |
align 4 |
uart_set_mode: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+4] |
mov ecx, [esi+8] |
; param |
; eax= uart |
; ebx= baud rate |
; ecx= mode |
align 4 |
.internal: |
cmp ebx, RATE_115200 |
ja .fail |
cmp ecx, LCR_BREAK |
jae .fail |
mov [eax+UART.rate], ebx |
mov [eax+UART.mode], ecx |
mov esi, eax |
mov bx, [divisor+ebx*2] |
mov edx, [esi+UART.base] |
push edx |
add edx, LCR_REG |
in al, dx |
or al, 0x80 |
out dx, al |
pop edx |
mov al, bl |
out dx, al |
inc dx |
mov al, bh |
out dx, al |
add edx, LCR_REG-1 |
mov eax, ecx |
out dx, al |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 modem control reg valie |
; |
; retval |
; eax= error code |
align 4 |
uart_set_mcr: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+4] |
mov [eax+UART.mcr_reg], ebx |
mov edx, [eax+UART.base] |
add edx, MCR_REG |
mov al, bl |
out dx, al |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; eax= port |
; |
; retval |
; ecx= connection |
; eax= error code |
align 4 |
uart_open: |
dec eax |
cmp eax, COM_MAX |
jae .fail |
mov esi, [com1+eax*4] ;uart |
push esi |
.do_wait: |
cmp dword [esi+UART.lock],0 |
je .get_lock |
; call change_task |
jmp .do_wait |
.get_lock: |
mov eax, 1 |
xchg eax, [esi+UART.lock] |
test eax, eax |
jnz .do_wait |
mov eax, esi ;uart |
call uart_reset.internal |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov ebx, [CURRENT_TASK+ebx+4] |
mov eax, CONNECTION_SIZE |
call CreateObject |
pop esi ;uart |
test eax, eax |
jz .fail |
mov [eax+APPOBJ.magic], 'CNCT' |
mov [eax+APPOBJ.destroy], uart_close.destroy |
mov [eax+CONNECTION.uart], esi |
mov ecx, eax |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
restore .uart |
; param |
; esi= input buffer |
align 4 |
uart_close: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
.destroy: |
push [eax+CONNECTION.uart] |
call DestroyObject ;eax= object |
pop eax ;eax= uart |
test eax, eax |
jz .fail |
mov [eax+UART.state], UART_CLOSED |
mov [eax+UART.lock], 0 ;release port |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; eax= uart |
; ebx= baud rate |
align 4 |
set_rate: |
cmp ebx, RATE_115200 |
ja .fail |
mov [eax+UART.rate], ebx |
mov bx, [divisor+ebx*2] |
mov edx, [eax+UART.base] |
add edx, LCR_REG |
in al, dx |
push eax |
or al, 0x80 |
out dx, al |
sub edx, LCR_REG |
mov al, bl |
out dx, al |
inc edx |
mov al, bh |
out dx, al |
pop eax |
add edx, LCR_REG-1 |
out dx, al |
.fail: |
ret |
; param |
; ebx= uart |
align 4 |
transmit: |
push esi |
push edi |
mov edx, [ebx+UART.base] |
pushfd |
cli |
mov esi, [ebx+UART.xmit_rp] |
mov ecx, [ebx+UART.xmit_count] |
test ecx, ecx |
je .stop |
cmp ecx, 16 |
jbe @F |
mov ecx, 16 |
@@: |
sub [ebx+UART.xmit_count], ecx |
add [ebx+UART.xmit_free], ecx |
cld |
@@: |
lodsb |
out dx, al |
dec ecx |
jnz @B |
cmp esi,[ebx+UART.xmit_top] |
jb @F |
sub esi, 8192 |
@@: |
mov [ebx+UART.xmit_rp], esi |
cmp [ebx+UART.xmit_count], 0 |
je .stop |
mov [ebx+UART.state], UART_TRANSMIT |
jmp @F |
.stop: |
mov [ebx+UART.state], UART_STOP |
@@: |
popfd |
pop edi |
pop esi |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 dst buffer |
; +8 dst size |
; edi= output buffer |
; +0 bytes read |
; retval |
; eax= error code |
align 4 |
uart_read: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+8] ;dst size |
mov ecx, [eax+UART.rcvr_count] |
cmp ecx, ebx |
jbe @F |
mov ecx, ebx |
@@: |
mov [edi], ecx ;bytes read |
test ecx, ecx |
jz .done |
push ecx |
mov edi, [esi+4] ;dst |
mov esi, [eax+UART.rcvr_rp] |
cld |
rep movsb |
pop ecx |
cmp esi, [eax+UART.rcvr_top] |
jb @F |
sub esi, 8192 |
@@: |
mov [eax+UART.rcvr_rp], esi |
sub [eax+UART.rcvr_count], ecx |
.done: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 src buffer |
; +8 src size |
; |
; retval |
; eax= error code |
align 4 |
uart_write: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+4] |
mov edx, [esi+8] |
; param |
; eax= uart |
; ebx= src |
; edx= count |
align 4 |
.internal: |
mov esi, ebx |
mov edi, [eax+UART.xmit_wp] |
.write: |
test edx, edx |
jz .fail |
.wait: |
cmp [eax+UART.xmit_free], 0 |
jne .fill |
cmp [eax+UART.state], UART_TRANSMIT |
je .wait |
mov ebx, eax |
push edx |
call transmit |
pop edx |
mov eax, ebx |
jmp .write |
.fill: |
mov ecx, [eax+UART.xmit_free] |
cmp ecx, edx |
jbe @F |
mov ecx, edx |
@@: |
push ecx |
cld |
rep movsb |
pop ecx |
sub [eax+UART.xmit_free], ecx |
add [eax+UART.xmit_count], ecx |
sub edx, ecx |
jnz .wait |
.done: |
cmp edi, [eax+UART.xmit_top] |
jb @F |
sub edi, 8192 |
@@: |
mov [eax+UART.xmit_wp], edi |
cmp [eax+UART.state], UART_TRANSMIT |
je @F |
mov ebx, eax |
call transmit |
@@: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
align 4 |
com_2_isr: |
mov ebx, [com2] |
jmp com_1_isr.get_info |
align 4 |
com_1_isr: |
mov ebx, [com1] |
.get_info: |
mov edx, [ebx+UART.base] |
add edx, IIR_REG |
in al, dx |
test al, IIR_INTR |
jnz .done |
shr eax, 1 |
and eax, 3 |
call [isr_action+eax*4] |
jmp .get_info |
.done: |
ret |
align 4 |
isr_line: |
mov edx, [ebx+UART.base] |
add edx, LSR_REG |
in al, dx |
ret |
align 4 |
isr_recieve: |
mov esi, [ebx+UART.base] |
add esi, LSR_REG |
mov edi, [ebx+UART.rcvr_wp] |
xor ecx, ecx |
cld |
.read: |
mov edx, esi |
in al, dx |
test eax, LSR_DR |
jz .done |
mov edx, [ebx+UART.base] |
in al, dx |
stosb |
inc ecx |
jmp .read |
.done: |
cmp edi, [ebx+UART.rcvr_top] |
jb @F |
sub edi, 8192 |
@@: |
mov [ebx+UART.rcvr_wp], edi |
add [ebx+UART.rcvr_count], ecx |
ret |
align 4 |
isr_modem: |
mov edx, [ebx+UART.base] |
add edx, MSR_REG |
in al, dx |
ret |
align 4 |
divisor dw 2304, 1536, 1047, 857, 768, 384 |
dw 192, 96, 64, 58, 48, 32 |
dw 24, 16, 12, 6, 3, 2, 1 |
align 4 |
uart_func dd 0 ;SRV_GETVERSION |
dd 0 ;PORT_OPEN |
dd uart_close ;PORT_CLOSE |
dd uart_reset ;PORT_RESET |
dd uart_set_mode ;PORT_SETMODE |
dd 0 ;PORT_GETMODE |
dd uart_set_mcr ;PORT_SETMODEM |
dd 0 ;PORT_GETMODEM |
dd uart_read ;PORT_READ |
dd uart_write ;PORT_WRITE |
isr_action dd isr_modem |
dd transmit |
dd isr_recieve |
dd isr_line |
version dd (5 shl 16) or (UART_VERSION and 0xFFFF) |
sz_uart_srv db 'UART',0 |
align 4 |
com1 rd 1 |
com2 rd 1 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0 |
UART_VERSION equ API_VERSION |
PG_SW equ 0x003 |
page_tabs equ 0xFDC00000 ;hack |
OS_BASE equ 0x80000000 |
SLOT_BASE equ (OS_BASE+0x0080000) |
TASK_COUNT equ (OS_BASE+0x0003004) |
CURRENT_TASK equ (OS_BASE+0x0003000) |
struc APPOBJ ;common object header |
{ |
.magic dd ? ; |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
}; |
virtual at 0 |
APPOBJ APPOBJ |
end virtual |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
DEBUG equ 1 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
THR_REG equ 0; x3f8 ;transtitter/reciever |
IER_REG equ 1; x3f9 ;interrupt enable |
IIR_REG equ 2; x3fA ;interrupt info |
LCR_REG equ 3; x3FB ;line control |
MCR_REG equ 4; x3FC ;modem control |
LSR_REG equ 5; x3FD ;line status |
MSR_REG equ 6; x3FE ;modem status |
LCR_5BIT equ 0x00 |
LCR_6BIT equ 0x01 |
LCR_7BIT equ 0x02 |
LCR_8BIT equ 0x03 |
LCR_STOP_1 equ 0x00 |
LCR_STOP_2 equ 0x04 |
LCR_PARITY equ 0x08 |
LCR_EVEN equ 0x10 |
LCR_STICK equ 0x20 |
LCR_BREAK equ 0x40 |
LCR_DLAB equ 0x80 |
LSR_DR equ 0x01 ;data ready |
LSR_OE equ 0x02 ;overrun error |
LSR_PE equ 0x04 ;parity error |
LSR_FE equ 0x08 ;framing error |
LSR_BI equ 0x10 ;break interrupt |
LSR_THRE equ 0x20 ;transmitter holding empty |
LSR_TEMT equ 0x40 ;transmitter empty |
LSR_FER equ 0x80 ;FIFO error |
FCR_EFIFO equ 0x01 ;enable FIFO |
FCR_CRB equ 0x02 ;clear reciever FIFO |
FCR_CXMIT equ 0x04 ;clear transmitter FIFO |
FCR_RDY equ 0x08 ;set RXRDY and TXRDY pins |
FCR_FIFO_1 equ 0x00 ;1 byte trigger |
FCR_FIFO_4 equ 0x40 ;4 bytes trigger |
FCR_FIFO_8 equ 0x80 ;8 bytes trigger |
FCR_FIFO_14 equ 0xC0 ;14 bytes trigger |
IIR_INTR equ 0x01 ;1= no interrupts |
IER_RDAI equ 0x01 ;reciever data interrupt |
IER_THRI equ 0x02 ;transmitter empty interrupt |
IER_LSI equ 0x04 ;line status interrupt |
IER_MSI equ 0x08 ;modem status interrupt |
MCR_DTR equ 0x01 ;0-> DTR=1, 1-> DTR=0 |
MCR_RTS equ 0x02 ;0-> RTS=1, 1-> RTS=0 |
MCR_OUT_1 equ 0x04 ;0-> OUT1=1, 1-> OUT1=0 |
MCR_OUT_2 equ 0x08 ;0-> OUT2=1, 1-> OUT2=0; enable intr |
MCR_LOOP equ 0x10 ;lopback mode |
MSR_DCTS equ 0x01 ;delta clear to send |
MSR_DDSR equ 0x02 ;delta data set redy |
MSR_TERI equ 0x04 ;trailinh edge of ring |
MSR_DDCD equ 0x08 ;delta carrier detect |
RATE_50 equ 0 |
RATE_75 equ 1 |
RATE_110 equ 2 |
RATE_134 equ 3 |
RATE_150 equ 4 |
RATE_300 equ 5 |
RATE_600 equ 6 |
RATE_1200 equ 7 |
RATE_1800 equ 8 |
RATE_2000 equ 9 |
RATE_2400 equ 10 |
RATE_3600 equ 11 |
RATE_4800 equ 12 |
RATE_7200 equ 13 |
RATE_9600 equ 14 |
RATE_19200 equ 15 |
RATE_38400 equ 16 |
RATE_57600 equ 17 |
RATE_115200 equ 18 |
COM_1 equ 1 |
COM_2 equ 2 |
COM_3 equ 3 |
COM_4 equ 4 |
COM_MAX equ 2 ;only two port supported |
COM_1_BASE equ 0x3F8 |
COM_2_BASE equ 0x2F8 |
COM_1_IRQ equ 4 |
COM_2_IRQ equ 3 |
UART_CLOSED equ 0 |
UART_TRANSMIT equ 1 |
UART_STOP equ 2 |
struc UART |
{ |
.lock dd ? |
.base dd ? |
.lcr_reg dd ? |
.mcr_reg dd ? |
.rate dd ? |
.mode dd ? |
.state dd ? |
.rcvr_buff dd ? |
.rcvr_rp dd ? |
.rcvr_wp dd ? |
.rcvr_count dd ? |
.rcvr_top dd ? |
.xmit_buff dd ? |
.xmit_rp dd ? |
.xmit_wp dd ? |
.xmit_count dd ? |
.xmit_free dd ? |
.xmit_top dd ? |
} |
virtual at 0 |
UART UART |
end virtual |
UART_SIZE equ 18*4 |
struc CONNECTION |
{ |
.magic dd ? ;'CNCT' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.id dd ? ;reserved |
.uart dd ? ;uart pointer |
} |
virtual at 0 |
CONNECTION CONNECTION |
end virtual |
CONNECTION_SIZE equ 7*4 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
mov eax, UART_SIZE |
call Kmalloc |
test eax, eax |
jz .fail |
mov [com1], eax |
mov edi, eax |
mov ecx, UART_SIZE/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [com1] |
mov [eax+UART.base], COM_1_BASE |
stdcall AllocKernelSpace, 32768 |
mov edi, [com1] |
mov edx, eax |
mov [edi+UART.rcvr_buff], eax |
add eax, 8192 |
mov [edi+UART.rcvr_top], eax |
add eax, 8192 |
mov [edi+UART.xmit_buff], eax |
add eax, 8192 |
mov [edi+UART.xmit_top], eax |
call AllocPage |
test eax, eax |
jz .fail |
shr edx, 12 |
or eax, PG_SW |
mov [page_tabs+edx*4], eax |
mov [page_tabs+edx*4+8], eax |
call AllocPage |
test eax, eax |
jz .fail |
or eax, PG_SW |
mov [page_tabs+edx*4+4], eax |
mov [page_tabs+edx*4+12], eax |
call AllocPage |
test eax, eax |
jz .fail |
or eax, PG_SW |
mov [page_tabs+edx*4+16], eax |
mov [page_tabs+edx*4+24], eax |
call AllocPage |
test eax, eax |
jz .fail |
or eax, PG_SW |
mov [page_tabs+edx*4+20], eax |
mov [page_tabs+edx*4+28], eax |
mov eax, [edi+UART.rcvr_buff] |
invlpg [eax] |
invlpg [eax+0x1000] |
invlpg [eax+0x2000] |
invlpg [eax+0x3000] |
invlpg [eax+0x4000] |
invlpg [eax+0x5000] |
invlpg [eax+0x6000] |
invlpg [eax+0x7000] |
mov eax, edi |
call uart_reset.internal ;eax= uart |
stdcall AttachIntHandler, COM_1_IRQ, com_1_isr, dword 0 |
stdcall RegService, sz_uart_srv, service_proc |
ret |
.fail: |
.stop: |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
SRV_GETVERSION equ 0 |
PORT_OPEN equ 1 |
PORT_CLOSE equ 2 |
PORT_RESET equ 3 |
PORT_SETMODE equ 4 |
PORT_GETMODE equ 5 |
PORT_SETMCR equ 6 |
PORT_GETMCR equ 7 |
PORT_READ equ 8 |
PORT_WRITE equ 9 |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, PORT_WRITE |
ja .fail |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword UART_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, PORT_OPEN |
jne @F |
cmp [ebx+out_size], 4 |
jne .fail |
mov ebx, [ebx+input] |
mov eax, [ebx] |
call uart_open |
mov ebx, [ioctl] |
mov ebx, [ebx+output] |
mov [ebx], ecx |
ret |
@@: |
mov esi, [ebx+input] ;input buffer |
mov edi, [ebx+output] |
call [uart_func+eax*4] |
ret |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
; param |
; esi= input buffer |
; +0 connection |
; |
; retval |
; eax= error code |
align 4 |
uart_reset: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
; set mode 2400 bod 8-bit |
; disable DTR & RTS |
; clear FIFO |
; clear pending interrupts |
; |
; param |
; eax= uart |
align 4 |
.internal: |
mov esi, eax |
mov [eax+UART.state], UART_CLOSED |
mov edx, [eax+UART.base] |
add edx, MCR_REG |
xor eax, eax |
out dx, al ;clear DTR & RTS |
mov eax, esi |
mov ebx, RATE_2400 |
mov ecx, LCR_8BIT+LCR_STOP_1 |
call uart_set_mode.internal |
mov edx, [esi+UART.base] |
add edx, IIR_REG |
mov eax, FCR_EFIFO+FCR_CRB+FCR_CXMIT+FCR_FIFO_14 |
out dx, al |
.clear_RB: |
mov edx, [esi+UART.base] |
add edx, LSR_REG |
in al, dx |
test eax, LSR_DR |
jz @F |
mov edx, [esi+UART.base] |
in al, dx |
jmp .clear_RB |
@@: |
mov edx, [esi+UART.base] |
add edx, IER_REG |
mov eax, IER_RDAI+IER_THRI+IER_LSI |
out dx, al |
.clear_IIR: |
mov edx, [esi+UART.base] |
add edx, IIR_REG |
in al, dx |
test al, IIR_INTR |
jnz .done |
shr eax, 1 |
and eax, 3 |
jnz @F |
mov edx, [esi+UART.base] |
add edx, MSR_REG |
in al, dx |
jmp .clear_IIR |
@@: |
cmp eax, 1 |
je .clear_IIR |
cmp eax, 2 |
jne @F |
mov edx, [esi+UART.base] |
in al, dx |
jmp .clear_IIR |
@@: |
mov edx, [esi+UART.base] |
add edx, LSR_REG |
in al, dx |
jmp .clear_IIR |
.done: |
mov edi, [esi+UART.rcvr_buff] |
mov ecx, 8192/4 |
xor eax, eax |
mov [esi+UART.rcvr_rp], edi |
mov [esi+UART.rcvr_wp], edi |
mov [esi+UART.rcvr_count], eax |
cld |
rep stosd |
mov edi, [esi+UART.xmit_buff] |
mov ecx, 8192/4 |
mov [esi+UART.xmit_rp], edi |
mov [esi+UART.xmit_wp], edi |
mov [esi+UART.xmit_count], eax |
mov [esi+UART.xmit_free], 8192 |
rep stosd |
ret ;eax= 0 |
.fail: |
or eax, -1 |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 rate |
; +8 mode |
; |
; retval |
; eax= error code |
align 4 |
uart_set_mode: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+4] |
mov ecx, [esi+8] |
; param |
; eax= uart |
; ebx= baud rate |
; ecx= mode |
align 4 |
.internal: |
cmp ebx, RATE_115200 |
ja .fail |
cmp ecx, LCR_BREAK |
jae .fail |
mov [eax+UART.rate], ebx |
mov [eax+UART.mode], ecx |
mov esi, eax |
mov bx, [divisor+ebx*2] |
mov edx, [esi+UART.base] |
push edx |
add edx, LCR_REG |
in al, dx |
or al, 0x80 |
out dx, al |
pop edx |
mov al, bl |
out dx, al |
inc dx |
mov al, bh |
out dx, al |
add edx, LCR_REG-1 |
mov eax, ecx |
out dx, al |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 modem control reg valie |
; |
; retval |
; eax= error code |
align 4 |
uart_set_mcr: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+4] |
mov [eax+UART.mcr_reg], ebx |
mov edx, [eax+UART.base] |
add edx, MCR_REG |
mov al, bl |
out dx, al |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; eax= port |
; |
; retval |
; ecx= connection |
; eax= error code |
align 4 |
uart_open: |
dec eax |
cmp eax, COM_MAX |
jae .fail |
mov esi, [com1+eax*4] ;uart |
push esi |
.do_wait: |
cmp dword [esi+UART.lock], 0 |
je .get_lock |
; call change_task |
jmp .do_wait |
.get_lock: |
mov eax, 1 |
xchg eax, [esi+UART.lock] |
test eax, eax |
jnz .do_wait |
mov eax, esi ;uart |
call uart_reset.internal |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov ebx, [CURRENT_TASK+ebx+4] |
mov eax, CONNECTION_SIZE |
call CreateObject |
pop esi ;uart |
test eax, eax |
jz .fail |
mov [eax+APPOBJ.magic], 'CNCT' |
mov [eax+APPOBJ.destroy], uart_close.destroy |
mov [eax+CONNECTION.uart], esi |
mov ecx, eax |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
restore .uart |
; param |
; esi= input buffer |
align 4 |
uart_close: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
.destroy: |
push [eax+CONNECTION.uart] |
call DestroyObject ;eax= object |
pop eax ;eax= uart |
test eax, eax |
jz .fail |
mov [eax+UART.state], UART_CLOSED |
mov [eax+UART.lock], 0;release port |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; eax= uart |
; ebx= baud rate |
align 4 |
set_rate: |
cmp ebx, RATE_115200 |
ja .fail |
mov [eax+UART.rate], ebx |
mov bx, [divisor+ebx*2] |
mov edx, [eax+UART.base] |
add edx, LCR_REG |
in al, dx |
push eax |
or al, 0x80 |
out dx, al |
sub edx, LCR_REG |
mov al, bl |
out dx, al |
inc edx |
mov al, bh |
out dx, al |
pop eax |
add edx, LCR_REG-1 |
out dx, al |
.fail: |
ret |
; param |
; ebx= uart |
align 4 |
transmit: |
push esi |
push edi |
mov edx, [ebx+UART.base] |
pushfd |
cli |
mov esi, [ebx+UART.xmit_rp] |
mov ecx, [ebx+UART.xmit_count] |
test ecx, ecx |
je .stop |
cmp ecx, 16 |
jbe @F |
mov ecx, 16 |
@@: |
sub [ebx+UART.xmit_count], ecx |
add [ebx+UART.xmit_free], ecx |
cld |
@@: |
lodsb |
out dx, al |
dec ecx |
jnz @B |
cmp esi, [ebx+UART.xmit_top] |
jb @F |
sub esi, 8192 |
@@: |
mov [ebx+UART.xmit_rp], esi |
cmp [ebx+UART.xmit_count], 0 |
je .stop |
mov [ebx+UART.state], UART_TRANSMIT |
jmp @F |
.stop: |
mov [ebx+UART.state], UART_STOP |
@@: |
popfd |
pop edi |
pop esi |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 dst buffer |
; +8 dst size |
; edi= output buffer |
; +0 bytes read |
; retval |
; eax= error code |
align 4 |
uart_read: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+8] ;dst size |
mov ecx, [eax+UART.rcvr_count] |
cmp ecx, ebx |
jbe @F |
mov ecx, ebx |
@@: |
mov [edi], ecx ;bytes read |
test ecx, ecx |
jz .done |
push ecx |
mov edi, [esi+4] ;dst |
mov esi, [eax+UART.rcvr_rp] |
cld |
rep movsb |
pop ecx |
cmp esi, [eax+UART.rcvr_top] |
jb @F |
sub esi, 8192 |
@@: |
mov [eax+UART.rcvr_rp], esi |
sub [eax+UART.rcvr_count], ecx |
.done: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 src buffer |
; +8 src size |
; |
; retval |
; eax= error code |
align 4 |
uart_write: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+4] |
mov edx, [esi+8] |
; param |
; eax= uart |
; ebx= src |
; edx= count |
align 4 |
.internal: |
mov esi, ebx |
mov edi, [eax+UART.xmit_wp] |
.write: |
test edx, edx |
jz .fail |
.wait: |
cmp [eax+UART.xmit_free], 0 |
jne .fill |
cmp [eax+UART.state], UART_TRANSMIT |
je .wait |
mov ebx, eax |
push edx |
call transmit |
pop edx |
mov eax, ebx |
jmp .write |
.fill: |
mov ecx, [eax+UART.xmit_free] |
cmp ecx, edx |
jbe @F |
mov ecx, edx |
@@: |
push ecx |
cld |
rep movsb |
pop ecx |
sub [eax+UART.xmit_free], ecx |
add [eax+UART.xmit_count], ecx |
sub edx, ecx |
jnz .wait |
.done: |
cmp edi, [eax+UART.xmit_top] |
jb @F |
sub edi, 8192 |
@@: |
mov [eax+UART.xmit_wp], edi |
cmp [eax+UART.state], UART_TRANSMIT |
je @F |
mov ebx, eax |
call transmit |
@@: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
align 4 |
com_2_isr: |
mov ebx, [com2] |
jmp com_1_isr.get_info |
align 4 |
com_1_isr: |
mov ebx, [com1] |
.get_info: |
mov edx, [ebx+UART.base] |
add edx, IIR_REG |
in al, dx |
test al, IIR_INTR |
jnz .done |
shr eax, 1 |
and eax, 3 |
call [isr_action+eax*4] |
jmp .get_info |
.done: |
ret |
align 4 |
isr_line: |
mov edx, [ebx+UART.base] |
add edx, LSR_REG |
in al, dx |
ret |
align 4 |
isr_recieve: |
mov esi, [ebx+UART.base] |
add esi, LSR_REG |
mov edi, [ebx+UART.rcvr_wp] |
xor ecx, ecx |
cld |
.read: |
mov edx, esi |
in al, dx |
test eax, LSR_DR |
jz .done |
mov edx, [ebx+UART.base] |
in al, dx |
stosb |
inc ecx |
jmp .read |
.done: |
cmp edi, [ebx+UART.rcvr_top] |
jb @F |
sub edi, 8192 |
@@: |
mov [ebx+UART.rcvr_wp], edi |
add [ebx+UART.rcvr_count], ecx |
ret |
align 4 |
isr_modem: |
mov edx, [ebx+UART.base] |
add edx, MSR_REG |
in al, dx |
ret |
align 4 |
divisor dw 2304, 1536, 1047, 857, 768, 384 |
dw 192, 96, 64, 58, 48, 32 |
dw 24, 16, 12, 6, 3, 2, 1 |
align 4 |
uart_func dd 0 ;SRV_GETVERSION |
dd 0 ;PORT_OPEN |
dd uart_close ;PORT_CLOSE |
dd uart_reset ;PORT_RESET |
dd uart_set_mode ;PORT_SETMODE |
dd 0 ;PORT_GETMODE |
dd uart_set_mcr ;PORT_SETMODEM |
dd 0 ;PORT_GETMODEM |
dd uart_read ;PORT_READ |
dd uart_write ;PORT_WRITE |
isr_action dd isr_modem |
dd transmit |
dd isr_recieve |
dd isr_line |
version dd (5 shl 16) or (UART_VERSION and 0xFFFF) |
sz_uart_srv db 'UART',0 |
align 4 |
com1 rd 1 |
com2 rd 1 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/usb/urb.inc |
---|
1,115 → 1,115 |
struc URB |
{ |
.fd dd ? |
.bk dd ? |
.dev dd ? ; pointer to associated device |
.pipe dd ? ; pipe information |
.status dd ? ; non-ISO status |
.transfer_flags dd ? ; URB_SHORT_NOT_OK | ... |
.transfer_buffer dd ? ; associated data buffer |
.transfer_dma dd ? ; dma addr for transfer_buffer |
.transfer_buffer_length dd ? ; data buffer length |
.actual_length dd ? ; actual transfer length |
.setup_packet dd ? ; setup packet (control only) |
.setup_dma dd ? ; dma addr for setup_packet |
.start_frame dd ? ; start frame (ISO) |
.number_of_packets dd ? ; number of ISO packets |
.interval dd ? ; transfer interval |
.error_count dd ? ; number of ISO errors |
.context dd ? ; context for completion |
.complete dd ? ; (in) completion routine |
.iso_frame_desc: |
} |
virtual at 0 |
URB URB |
end virtual |
struc REQ ;usb request |
{ |
.request_type db ? |
.request db ? |
.value dw ? |
.index dw ? |
.length dw ? |
} |
virtual at 0 |
REQ REQ |
end virtual |
align 4 |
proc usb_control_msg stdcall, dev:dword, pipe:dword, request:dword,\ |
requesttype:dword, value:dword, index:dword,\ |
data:dword, size:dword, timeout:dword |
locals |
req REQ |
endl |
lea eax, [req] |
mov ecx, [request] |
mov ebx, [requesttupe] |
mov edx, [value] |
mov esi, [index] |
mov edi, [size] |
mov [eax+REQ.request_type], bl |
mov [eax+REQ.request], cl |
mov [eax+REQ.value], dx |
mov [eax+REQ.index], si |
mov [eax+REQ.length], di |
stdcall usb_internal_control_msg, [dev], [pipe],\ |
eax, [data], [size], [timeout] |
ret |
endp |
; returns status (negative) or length (positive) |
static int usb_internal_control_msg(struct usb_device *usb_dev, |
unsigned int pipe, |
struct usb_ctrlrequest *cmd, |
void *data, int len, int timeout) |
{ |
struct urb *urb; |
int retv; |
int length; |
urb = usb_alloc_urb(0, GFP_NOIO); |
if (!urb) |
return -ENOMEM; |
usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, |
len, usb_api_blocking_completion, NULL); |
retv = usb_start_wait_urb(urb, timeout, &length); |
if (retv < 0) |
return retv; |
else |
return length; |
} |
void usb_fill_control_urb (struct urb *urb, |
struct usb_device *dev, |
unsigned int pipe, |
unsigned char *setup_packet, |
void *transfer_buffer, |
int buffer_length, |
usb_complete_t complete_fn, |
void *context) |
{ |
urb->dev = dev; |
urb->pipe = pipe; |
urb->setup_packet = setup_packet; |
urb->transfer_buffer = transfer_buffer; |
urb->transfer_buffer_length = buffer_length; |
urb->complete = complete_fn; |
urb->context = context; |
} |
struc URB |
{ |
.fd dd ? |
.bk dd ? |
.dev dd ? ; pointer to associated device |
.pipe dd ? ; pipe information |
.status dd ? ; non-ISO status |
.transfer_flags dd ? ; URB_SHORT_NOT_OK | ... |
.transfer_buffer dd ? ; associated data buffer |
.transfer_dma dd ? ; dma addr for transfer_buffer |
.transfer_buffer_length dd ? ; data buffer length |
.actual_length dd ? ; actual transfer length |
.setup_packet dd ? ; setup packet (control only) |
.setup_dma dd ? ; dma addr for setup_packet |
.start_frame dd ? ; start frame (ISO) |
.number_of_packets dd ? ; number of ISO packets |
.interval dd ? ; transfer interval |
.error_count dd ? ; number of ISO errors |
.context dd ? ; context for completion |
.complete dd ? ; (in) completion routine |
.iso_frame_desc: |
} |
virtual at 0 |
URB URB |
end virtual |
struc REQ ;usb request |
{ |
.request_type db ? |
.request db ? |
.value dw ? |
.index dw ? |
.length dw ? |
} |
virtual at 0 |
REQ REQ |
end virtual |
align 4 |
proc usb_control_msg stdcall, dev:dword, pipe:dword, request:dword,\ |
requesttype:dword, value:dword, index:dword,\ |
data:dword, size:dword, timeout:dword |
locals |
req REQ |
endl |
lea eax, [req] |
mov ecx, [request] |
mov ebx, [requesttupe] |
mov edx, [value] |
mov esi, [index] |
mov edi, [size] |
mov [eax+REQ.request_type], bl |
mov [eax+REQ.request], cl |
mov [eax+REQ.value], dx |
mov [eax+REQ.index], si |
mov [eax+REQ.length], di |
stdcall usb_internal_control_msg, [dev], [pipe], \ |
eax, [data], [size], [timeout] |
ret |
endp |
; returns status (negative) or length (positive) |
static int usb_internal_control_msg(struct usb_device *usb_dev, |
unsigned int pipe, |
struct usb_ctrlrequest *cmd, |
void *data, int len, int timeout) |
{ |
struct urb *urb; |
int retv; |
int length; |
urb = usb_alloc_urb(0, GFP_NOIO); |
if (!urb) |
return -ENOMEM; |
usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, |
len, usb_api_blocking_completion, NULL); |
retv = usb_start_wait_urb(urb, timeout, &length); |
if (retv < 0) |
return retv; |
else |
return length; |
} |
;void usb_fill_control_urb (struct urb *urb, |
; struct usb_device *dev, |
; unsigned int pipe, |
; unsigned char *setup_packet, |
; void *transfer_buffer, |
; int buffer_length, |
; usb_complete_t complete_fn, |
; void *context) |
;{ |
; |
; urb->dev = dev; |
; urb->pipe = pipe; |
; urb->setup_packet = setup_packet; |
; urb->transfer_buffer = transfer_buffer; |
; urb->transfer_buffer_length = buffer_length; |
; urb->complete = complete_fn; |
; urb->context = context; |
;} |
; |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/usb/usb.asm |
---|
1,435 → 1,435 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;driver sceletone |
format MS COFF |
API_VERSION equ 0 ;debug |
include '../proc32.inc' |
include '../imports.inc' |
include 'urb.inc' |
struc UHCI |
{ |
.bus dd ? |
.devfn dd ? |
.io_base dd ? |
.mm_base dd ? |
.irq dd ? |
.flags dd ? |
.reset dd ? |
.start dd ? |
.stop dd ? |
.port_c_suspend dd ? |
.resuming_ports dd ? |
.rh_state dd ? |
.rh_numports dd ? |
.is_stopped dd ? |
.dead dd ? |
.sizeof: |
} |
virtual at 0 |
UHCI UHCI |
end virtual |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
struc TD ;transfer descriptor |
{ |
.link dd ? |
.status dd ? |
.token dd ? |
.buffer dd ? |
.addr dd ? |
.frame dd ? |
.fd dd ? |
.bk dd ? |
.sizeof: |
} |
virtual at 0 |
TD TD |
end virtual |
public START |
public service_proc |
public version |
DEBUG equ 1 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
SRV_GETVERSION equ 0 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call init |
stdcall RegService, my_service, service_proc |
ret |
.fail: |
.exit: |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc detect |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, STRIDE |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov eax, UHCI.sizeof |
call Kmalloc |
test eax, eax |
jz .mem_fail |
mov ebx, [bus] |
mov [eax+UHCI.bus], ebx |
mov ecx, [devfn] |
mov [eax+UHCI.devfn], ecx |
ret |
.mem_fail: |
if DEBUG |
mov esi, msgMemFail |
call SysMsgBoardStr |
end if |
.err: |
xor eax, eax |
ret |
endp |
PCI_BASE equ 0x20 |
USB_LEGKEY equ 0xC0 |
align 4 |
proc init |
locals |
uhci dd ? |
endl |
call detect |
test eax, eax |
jz .fail |
mov [uhci], eax |
stdcall PciRead32, [eax+UHCI.bus], [eax+UHCI.devfn], PCI_BASE |
and eax, 0xFFC0 |
mov esi, [uhci] |
mov [esi+UHCI.io_base], eax |
stdcall uhci_reset, esi |
stdcall finish_reset, [uhci] |
.fail: |
if DEBUG |
mov esi, msgDevNotFound |
call SysMsgBoardStr |
end if |
ret |
endp |
UHCI_USBINTR equ 4 ; interrupt register |
UHCI_USBLEGSUP_RWC equ 0x8f00 ; the R/WC bits |
UHCI_USBLEGSUP_RO equ 0x5040 ; R/O and reserved bits |
UHCI_USBCMD_RUN equ 0x0001 ; RUN/STOP bit |
UHCI_USBCMD_HCRESET equ 0x0002 ; Host Controller reset |
UHCI_USBCMD_EGSM equ 0x0008 ; Global Suspend Mode |
UHCI_USBCMD_CONFIGURE equ 0x0040 ; Config Flag |
UHCI_USBINTR_RESUME equ 0x0002 ; Resume interrupt enable |
PORTSC0 equ 0x10 |
PORTSC1 equ 0x12 |
UHCI_RH_RESET equ 0 |
UHCI_RH_SUSPENDED equ 1 |
UHCI_RH_AUTO_STOPPED equ 2 |
UHCI_RH_RESUMING equ 3 |
; In this state the HC changes from running to halted |
; so it can legally appear either way. |
UHCI_RH_SUSPENDING equ 4 |
; In the following states it's an error if the HC is halted. |
; These two must come last. |
UHCI_RH_RUNNING equ 5 ; The normal state |
UHCI_RH_RUNNING_NODEVS equ 6 ; Running with no devices |
UHCI_IS_STOPPED equ 9999 |
align 4 |
proc uhci_reset stdcall, uhci:dword |
mov esi, [uhci] |
stdcall PciRead16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY |
test eax, not (UHCI_USBLEGSUP_RO or UHCI_USBLEGSUP_RWC) |
jnz .reset |
mov edx, [esi+UHCI.io_base] |
in ax, dx |
test ax, UHCI_USBCMD_RUN |
jnz .reset |
test ax, UHCI_USBCMD_CONFIGURE |
jz .reset |
test ax, UHCI_USBCMD_EGSM |
jz .reset |
add edx, UHCI_USBINTR |
in ax, dx |
test ax, not UHCI_USBINTR_RESUME |
jnz .reset |
ret |
.reset: |
stdcall PciWrite16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY, UHCI_USBLEGSUP_RWC |
mov edx, [esi+UHCI.io_base] |
mov ax, UHCI_USBCMD_HCRESET |
out dx, ax |
xor eax, eax |
out dx, ax |
add edx, UHCI_USBINTR |
out dx, ax |
ret |
endp |
proc finish_reset stdcall, uhci:dword |
mov esi, [uhci] |
mov edx, [esi+UHCI.io_base] |
add edx, PORTSC0 |
xor eax, eax |
out dx, ax |
add edx, (PORTSC1-PORTSC0) |
out dx, ax |
mov [esi+UHCI.port_c_suspend], eax |
mov [esi+UHCI.resuming_ports], eax |
mov [esi+UHCI.rh_state], UHCI_RH_RESET |
mov [esi+UHCI.rh_numports], 2 |
mov [esi+UHCI.is_stopped], UHCI_IS_STOPPED |
; mov [ uhci_to_hcd(uhci)->state = HC_STATE_HALT; |
; uhci_to_hcd(uhci)->poll_rh = 0; |
mov [esi+UHCI.dead], eax ; Full reset resurrects the controller |
ret |
endp |
proc insert_td stdcall, td:dword, frame:dword |
mov edi, [td] |
mov eax, [frame] |
and eax, -1024 |
mov [edi+TD.frame], eax |
mov ebx, [framelist] |
mov edx, [dma_framelist] |
shl eax, 5 |
mov ecx, [eax+ebx] |
test ecx, ecx |
jz .empty |
mov ecx, [ecx+TD.bk] ;last TD |
mov edx, [ecx+TD.fd] |
mov [edi+TD.fd], edx |
mov [edi+TD.bk], ecx |
mov [ecx+TD.fd], edi |
mov [edx+TD.bk], edi |
mov eax, [ecx+TD.link] |
mov [edi+TD.link], eax |
mov ebx, [edi+TD.addr] |
mov [ecx+TD.link], ebx |
ret |
.empty: |
mov ecx, [eax+edx] |
mov [edi+TD.link], ecx |
mov [ebx+eax], edi |
mov ecx, [edi+TD.addr] |
mov [eax+edx], ecx |
ret |
endp |
align 4 |
proc usb_get_descriptor stdcall, dev:dword, type:dword, index:dword,\ |
buf:dword, size:dword |
locals |
count dd ? |
endl |
mov esi, [buf] |
mov ecx, [size] |
xor eax, eax |
cld |
rep stosb |
mov [count], 3 |
@@: |
mov eax, [type] |
shl eax, 8 |
add eax, [index] |
stdcall usb_control_msg, [dev],pipe,USB_REQ_GET_DESCRIPTOR,\ |
USB_DIR_IN, eax,0,[buf], [size],\ |
USB_CTRL_GET_TIMEOUT |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
jmp. ok |
.next: |
dec [count] |
jnz @B |
mov eax, -1 |
.ok: |
ret |
endp |
DEVICE_ID equ 0x24D2 ; pci device id |
VENDOR_ID equ 0x8086 ; device vendor id |
QEMU_USB equ 0x7020 |
;all initialized data place here |
align 4 |
devices dd (DEVICE_ID shl 16)+VENDOR_ID |
dd (QEMU_USB shl 16)+VENDOR_ID |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'UHCI',0 ;max 16 chars include zero |
msgInit db 'detect hardware...',13,10,0 |
msgPCI db 'PCI accsess not supported',13,10,0 |
msgDevNotFound db 'device not found',13,10,0 |
msgMemFail db 'Kmalloc failed', 10,10,0 |
;msgFail db 'device not found',13,10,0 |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;driver sceletone |
format MS COFF |
API_VERSION equ 0 ;debug |
include '../proc32.inc' |
include '../imports.inc' |
include 'urb.inc' |
struc UHCI |
{ |
.bus dd ? |
.devfn dd ? |
.io_base dd ? |
.mm_base dd ? |
.irq dd ? |
.flags dd ? |
.reset dd ? |
.start dd ? |
.stop dd ? |
.port_c_suspend dd ? |
.resuming_ports dd ? |
.rh_state dd ? |
.rh_numports dd ? |
.is_stopped dd ? |
.dead dd ? |
.sizeof: |
} |
virtual at 0 |
UHCI UHCI |
end virtual |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
struc TD ;transfer descriptor |
{ |
.link dd ? |
.status dd ? |
.token dd ? |
.buffer dd ? |
.addr dd ? |
.frame dd ? |
.fd dd ? |
.bk dd ? |
.sizeof: |
} |
virtual at 0 |
TD TD |
end virtual |
public START |
public service_proc |
public version |
DEBUG equ 1 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
SRV_GETVERSION equ 0 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call init |
stdcall RegService, my_service, service_proc |
ret |
.fail: |
.exit: |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc detect |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, STRIDE |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov eax, UHCI.sizeof |
call Kmalloc |
test eax, eax |
jz .mem_fail |
mov ebx, [bus] |
mov [eax+UHCI.bus], ebx |
mov ecx, [devfn] |
mov [eax+UHCI.devfn], ecx |
ret |
.mem_fail: |
if DEBUG |
mov esi, msgMemFail |
call SysMsgBoardStr |
end if |
.err: |
xor eax, eax |
ret |
endp |
PCI_BASE equ 0x20 |
USB_LEGKEY equ 0xC0 |
align 4 |
proc init |
locals |
uhci dd ? |
endl |
call detect |
test eax, eax |
jz .fail |
mov [uhci], eax |
stdcall PciRead32, [eax+UHCI.bus], [eax+UHCI.devfn], PCI_BASE |
and eax, 0xFFC0 |
mov esi, [uhci] |
mov [esi+UHCI.io_base], eax |
stdcall uhci_reset, esi |
stdcall finish_reset, [uhci] |
.fail: |
if DEBUG |
mov esi, msgDevNotFound |
call SysMsgBoardStr |
end if |
ret |
endp |
UHCI_USBINTR equ 4 ; interrupt register |
UHCI_USBLEGSUP_RWC equ 0x8f00 ; the R/WC bits |
UHCI_USBLEGSUP_RO equ 0x5040 ; R/O and reserved bits |
UHCI_USBCMD_RUN equ 0x0001 ; RUN/STOP bit |
UHCI_USBCMD_HCRESET equ 0x0002 ; Host Controller reset |
UHCI_USBCMD_EGSM equ 0x0008 ; Global Suspend Mode |
UHCI_USBCMD_CONFIGURE equ 0x0040 ; Config Flag |
UHCI_USBINTR_RESUME equ 0x0002 ; Resume interrupt enable |
PORTSC0 equ 0x10 |
PORTSC1 equ 0x12 |
UHCI_RH_RESET equ 0 |
UHCI_RH_SUSPENDED equ 1 |
UHCI_RH_AUTO_STOPPED equ 2 |
UHCI_RH_RESUMING equ 3 |
; In this state the HC changes from running to halted |
; so it can legally appear either way. |
UHCI_RH_SUSPENDING equ 4 |
; In the following states it's an error if the HC is halted. |
; These two must come last. |
UHCI_RH_RUNNING equ 5 ; The normal state |
UHCI_RH_RUNNING_NODEVS equ 6 ; Running with no devices |
UHCI_IS_STOPPED equ 9999 |
align 4 |
proc uhci_reset stdcall, uhci:dword |
mov esi, [uhci] |
stdcall PciRead16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY |
test eax, not (UHCI_USBLEGSUP_RO or UHCI_USBLEGSUP_RWC) |
jnz .reset |
mov edx, [esi+UHCI.io_base] |
in ax, dx |
test ax, UHCI_USBCMD_RUN |
jnz .reset |
test ax, UHCI_USBCMD_CONFIGURE |
jz .reset |
test ax, UHCI_USBCMD_EGSM |
jz .reset |
add edx, UHCI_USBINTR |
in ax, dx |
test ax, not UHCI_USBINTR_RESUME |
jnz .reset |
ret |
.reset: |
stdcall PciWrite16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY, UHCI_USBLEGSUP_RWC |
mov edx, [esi+UHCI.io_base] |
mov ax, UHCI_USBCMD_HCRESET |
out dx, ax |
xor eax, eax |
out dx, ax |
add edx, UHCI_USBINTR |
out dx, ax |
ret |
endp |
proc finish_reset stdcall, uhci:dword |
mov esi, [uhci] |
mov edx, [esi+UHCI.io_base] |
add edx, PORTSC0 |
xor eax, eax |
out dx, ax |
add edx, (PORTSC1-PORTSC0) |
out dx, ax |
mov [esi+UHCI.port_c_suspend], eax |
mov [esi+UHCI.resuming_ports], eax |
mov [esi+UHCI.rh_state], UHCI_RH_RESET |
mov [esi+UHCI.rh_numports], 2 |
mov [esi+UHCI.is_stopped], UHCI_IS_STOPPED |
; mov [ uhci_to_hcd(uhci)->state = HC_STATE_HALT; |
; uhci_to_hcd(uhci)->poll_rh = 0; |
mov [esi+UHCI.dead], eax ; Full reset resurrects the controller |
ret |
endp |
proc insert_td stdcall, td:dword, frame:dword |
mov edi, [td] |
mov eax, [frame] |
and eax, -1024 |
mov [edi+TD.frame], eax |
mov ebx, [framelist] |
mov edx, [dma_framelist] |
shl eax, 5 |
mov ecx, [eax+ebx] |
test ecx, ecx |
jz .empty |
mov ecx, [ecx+TD.bk] ;last TD |
mov edx, [ecx+TD.fd] |
mov [edi+TD.fd], edx |
mov [edi+TD.bk], ecx |
mov [ecx+TD.fd], edi |
mov [edx+TD.bk], edi |
mov eax, [ecx+TD.link] |
mov [edi+TD.link], eax |
mov ebx, [edi+TD.addr] |
mov [ecx+TD.link], ebx |
ret |
.empty: |
mov ecx, [eax+edx] |
mov [edi+TD.link], ecx |
mov [ebx+eax], edi |
mov ecx, [edi+TD.addr] |
mov [eax+edx], ecx |
ret |
endp |
align 4 |
proc usb_get_descriptor stdcall, dev:dword, type:dword, index:dword,\ |
buf:dword, size:dword |
locals |
count dd ? |
endl |
mov esi, [buf] |
mov ecx, [size] |
xor eax, eax |
cld |
rep stosb |
mov [count], 3 |
@@: |
mov eax, [type] |
shl eax, 8 |
add eax, [index] |
stdcall usb_control_msg, [dev], pipe, USB_REQ_GET_DESCRIPTOR, \ |
USB_DIR_IN, eax,0,[buf], [size],\ |
USB_CTRL_GET_TIMEOUT |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
jmp. ok |
.next: |
dec [count] |
jnz @B |
mov eax, -1 |
.ok: |
ret |
endp |
DEVICE_ID equ 0x24D2 ; pci device id |
VENDOR_ID equ 0x8086 ; device vendor id |
QEMU_USB equ 0x7020 |
;all initialized data place here |
align 4 |
devices dd (DEVICE_ID shl 16)+VENDOR_ID |
dd (QEMU_USB shl 16)+VENDOR_ID |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'UHCI',0 ;max 16 chars include zero |
msgInit db 'detect hardware...',13,10,0 |
msgPCI db 'PCI accsess not supported',13,10,0 |
msgDevNotFound db 'device not found',13,10,0 |
msgMemFail db 'Kmalloc failed', 10,10,0 |
;msgFail db 'device not found',13,10,0 |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/vidintel.asm |
---|
1,465 → 1,465 |
; Stub of videodriver for Intel videocards. |
; (c) CleverMouse |
; When the start procedure gots control, |
; it tries to detect preferred resolution, |
; sets the detected resolution assuming 32-bpp VESA mode and exits |
; (without registering a service). |
; Detection can be overloaded with compile-time settings |
; use_predefined_mode/predefined_width/predefined_height. |
; set predefined resolution here |
use_predefined_mode = 0;1 |
predefined_width = 0;1366 |
predefined_height = 0;768 |
; standard driver stuff |
format MS COFF |
DEBUG = 1 |
include 'proc32.inc' |
include 'imports.inc' |
public START |
public version |
section '.flat' code readable align 16 |
; the start procedure (see the description above) |
START: |
; 1. Detect device. Abort if not found. |
push esi |
call DetectDevice |
test esi, esi |
jz .return0 |
; 2. Detect optimal mode unless the mode is given explicitly. Abort if failed. |
if use_predefined_mode = 0 |
call DetectMode |
end if |
cmp [width], 0 |
jz .return0_cleanup |
; 3. Set the detected mode. |
call SetMode |
; 4. Cleanup and return. |
.return0_cleanup: |
stdcall FreeKernelSpace, esi |
.return0: |
pop esi |
xor eax, eax |
ret 4 |
; check that there is Intel videocard |
; if so, map MMIO registers and set internal variables |
; esi points to MMIO block; NULL means no device |
DetectDevice: |
; 1. Sanity check: check that we are dealing with Intel videocard. |
; Integrated video device for Intel is always at PCI:0:2:0. |
xor esi, esi ; initialize return value to NULL |
; 1a. Get PCI VendorID and DeviceID. |
push esi |
push 10h |
push esi |
call PciRead32 |
; 1b. loword(eax) = ax = VendorID, hiword(eax) = DeviceID. |
; Test whether we have Intel chipset. |
cmp ax, 8086h |
jnz .return |
; 1c. Say hi including DeviceID. |
shr eax, 10h |
push edi |
pusha |
mov edi, pciid_text |
call WriteWord |
mov esi, hellomsg |
call SysMsgBoardStr |
popa |
; 1d. Test whether we know this DeviceID. |
; If this is the case, remember the position of the device in line of Intel cards; |
; this knowledge will be useful later. |
; Tested on devices with id: 8086:0046, partially 8086:2A02. |
mov ecx, pciids_num |
mov edi, pciids |
repnz scasw |
pop edi |
jnz .return_unknown_pciid |
sub ecx, pciids_num - 1 |
neg ecx |
mov [deviceType], ecx |
; 1e. Continue saying hi with positive intonation. |
pusha |
mov esi, knownmsg |
call SysMsgBoardStr |
popa |
; 2. Prepare MMIO region to control the card. |
; 2a. Read MMIO physical address from PCI config space. |
push 10h |
cmp ecx, i9xx_start |
jae @f |
mov byte [esp], 14h |
@@: |
push 10h |
push esi |
call PciRead32 |
; 2b. Mask out PCI region type, lower 4 bits. |
and al, not 0xF |
; 2c. Create virtual mapping of the physical memory. |
push 1Bh |
push 100000h |
push eax |
call MapIoMem |
; 3. Return. |
xchg esi, eax |
.return: |
ret |
; 1f. If we do not know DeviceID, continue saying hi with negative intonation. |
.return_unknown_pciid: |
pusha |
mov esi, unknownmsg |
call SysMsgBoardStr |
popa |
ret |
; Convert word in ax to hexadecimal text in edi, advance edi. |
WriteWord: |
; 1. Convert high byte. |
push eax |
mov al, ah |
call WriteByte |
pop eax |
; 2. Convert low byte. |
; Fall through to WriteByte; ret from WriteByte is ret from WriteWord too. |
; Convert byte in al to hexadecimal text in edi, advance edi. |
WriteByte: |
; 1. Convert high nibble. |
push eax |
shr al, 4 |
call WriteNibble |
pop eax |
; 2. Convert low nibble. |
and al, 0xF |
; Fall through to WriteNibble; ret from WriteNibble is ret from WriteByte too. |
; Convert nibble in al to hexadecimal text in edi, advance edi. |
WriteNibble: |
; Obvious, isn't it? |
cmp al, 10 |
sbb al, 69h |
das |
stosb |
ret |
if use_predefined_mode = 0 |
; detect resolution of the flat panel |
DetectMode: |
push esi edi |
; 1. Get the location of block of GMBUS* registers. |
; Starting with Ironlake, GMBUS* registers were moved. |
add esi, 5100h |
cmp [deviceType], ironlake_start |
jb @f |
add esi, 0xC0000 |
@@: |
; 2. Initialize GMBUS engine. |
mov edi, edid |
mov ecx, 0x10000 |
@@: |
test byte [esi+8+1], 80h |
loopnz @b |
jnz .fail |
mov dword [esi], 3 |
test byte [esi+8+1], 4 |
jz .noreset |
call ResetGMBus |
jnz .fail |
.noreset: |
; 3. Send read command. |
and dword [esi+20h], 0 |
mov dword [esi+4], 4E8000A1h |
; 4. Wait for data, writing to the buffer as data arrive. |
.getdata: |
mov ecx, 0x10000 |
@@: |
test byte [esi+8+1], 8 |
loopz @b |
test byte [esi+8+1], 4 |
jz .dataok |
call ResetGMBus |
jmp .fail |
.dataok: |
mov eax, [esi+0Ch] |
stosd |
cmp edi, edid+80h |
jb .getdata |
; 5. Wait for bus idle. |
mov ecx, 0x10000 |
@@: |
test byte [esi+8+1], 2 |
loopnz @b |
; 6. We got EDID; dump it if DEBUG. |
if DEBUG |
pusha |
xor ecx, ecx |
mov esi, edid |
mov edi, edid_text |
.dumploop: |
lodsb |
call WriteByte |
mov al, ' ' |
stosb |
inc cl |
test cl, 15 |
jnz @f |
mov byte [edi-1], 13 |
mov al, 10 |
stosb |
@@: |
test cl, cl |
jns .dumploop |
mov esi, edidmsg |
call SysMsgBoardStr |
popa |
end if |
; 7. Test whether EDID is good. |
; 7a. Signature: 00 FF FF FF FF FF FF 00. |
mov esi, edid |
cmp dword [esi], 0xFFFFFF00 |
jnz .fail |
cmp dword [esi+4], 0x00FFFFFF |
jnz .fail |
; 7b. Checksum must be zero. |
xor edx, edx |
mov ecx, 80h |
@@: |
lodsb |
add dl, al |
loop @b |
jnz .fail |
; 8. Get width and height from EDID. |
xor eax, eax |
mov ah, [esi-80h+3Ah] |
shr ah, 4 |
mov al, [esi-80h+38h] |
mov [width], eax |
mov ah, [esi-80h+3Dh] |
shr ah, 4 |
mov al, [esi-80h+3Bh] |
mov [height], eax |
; 9. Return. |
.fail: |
pop edi esi |
ret |
; reset bus, clear all errors |
ResetGMBus: |
; look into the PRM |
mov dword [esi+4], 80000000h |
mov dword [esi+4], 0 |
mov ecx, 0x10000 |
@@: |
test byte [esi+8+1], 2 |
loopnz @b |
ret |
end if |
; set resolution [width]*[height] |
SetMode: |
; 1. Program the registers of videocard. |
; look into the PRM |
cli |
; or byte [esi+7000Ah], 0Ch ; PIPEACONF: disable Display+Cursor Planes |
; or byte [esi+7100Ah], 0Ch ; PIPEBCONF: disable Display+Cursor Planes |
xor eax, eax |
xor edx, edx |
cmp [deviceType], i965_start |
jb @f |
mov dl, 9Ch - 84h |
@@: |
; or byte [esi+71403h], 80h ; VGACNTRL: VGA Display Disable |
and byte [esi+70080h], not 27h ; CURACNTR: disable cursor A |
mov dword [esi+70084h], eax ; CURABASE: force write to CURA* regs |
and byte [esi+700C0h], not 27h ; CURBCNTR: disable cursor B |
mov dword [esi+700C4h], eax ; CURBBASE: force write to CURB* regs |
and byte [esi+70183h], not 80h ; DSPACNTR: disable Primary A Plane |
mov dword [esi+edx+70184h], eax ; DSPALINOFF/DSPASURF: force write to DSPA* regs |
and byte [esi+71183h], not 80h ; DSPBCNTR: disable Primary B Plane |
mov dword [esi+edx+71184h], eax ; DSPBLINOFF/DSPBSURF: force write to DSPB* regs |
if 1 |
cmp [deviceType], ironlake_start |
jae .disable_pipes |
mov edx, 10000h |
or byte [esi+70024h], 2 ; PIPEASTAT: clear VBLANK status |
or byte [esi+71024h], 2 ; PIPEBSTAT: clear VBLANK status |
.wait_vblank_preironlake1: |
mov ecx, 1000h |
loop $ |
test byte [esi+7000Bh], 80h ; PIPEACONF: pipe A active? |
jz @f |
test byte [esi+70024h], 2 ; PIPEASTAT: got VBLANK? |
jz .wait_vblank_preironlake2 |
@@: |
test byte [esi+7100Bh], 80h ; PIPEBCONF: pipe B active? |
jz .disable_pipes |
test byte [esi+71024h], 2 ; PIPEBSTAT: got VBLANK? |
jnz .disable_pipes |
.wait_vblank_preironlake2: |
dec edx |
jnz .wait_vblank_preironlake1 |
jmp .not_disabled |
.disable_pipes: |
end if |
and byte [esi+7000Bh], not 80h ; PIPEACONF: disable pipe |
and byte [esi+7100Bh], not 80h ; PIPEBCONF: disable pipe |
if 1 |
mov edx, 10000h |
@@: |
mov ecx, 1000h |
loop $ |
test byte [esi+7000Bh], 40h ; PIPEACONF: wait until pipe disabled |
jz @f |
dec edx |
jnz @b |
.not_disabled: |
sti |
jmp .return |
@@: |
test byte [esi+7100Bh], 40h ; PIPEBCONF: wait until pipe disabled |
jz @f |
mov ecx, 1000h |
loop $ |
dec edx |
jnz @b |
jmp .not_disabled |
@@: |
else |
; alternative way of waiting for pipe stop, works too |
mov edx, 1000h |
.dis1: |
push dword [esi+71000h] |
push dword [esi+70000h] |
mov ecx, 10000h |
loop $ |
pop eax |
xor eax, [esi+70000h] |
and eax, 1FFFh |
pop eax |
jnz .notdis1 |
xor eax, [esi+71000h] |
and eax, 1FFFh |
jz .disabled |
.notdis1: |
dec edx |
jnz .dis1 |
.not_disabled: |
sti |
jmp .return |
.disabled: |
end if |
lea eax, [esi+61183h] |
cmp [deviceType], ironlake_start |
jb @f |
add eax, 0xE0000 - 0x60000 |
@@: |
lea edx, [esi+60000h] |
test byte [eax], 40h |
jz @f |
add edx, 1000h |
@@: |
mov eax, [width] |
dec eax |
shl eax, 16 |
mov ax, word [height] |
dec eax |
mov dword [edx+1Ch], eax ; PIPEASRC: set source image size |
ror eax, 16 |
mov dword [edx+10190h], eax ; for old cards |
mov ecx, [width] |
add ecx, 15 |
and ecx, not 15 |
shl ecx, 2 |
mov dword [edx+10188h], ecx ; DSPASTRIDE: set scanline length |
and byte [esi+61233h], not 80h ; PFIT_CONTROL: disable panel fitting |
or byte [edx+1000Bh], 80h ; PIPEACONF: enable pipe |
; and byte [edx+1000Ah], not 0Ch ; PIPEACONF: enable Display+Cursor Planes |
or byte [edx+10183h], 80h ; DSPACNTR: enable Display Plane A |
sti |
; 2. Notify the kernel that resolution has changed. |
call GetDisplay |
mov edx, [width] |
mov dword [eax+8], edx |
mov edx, [height] |
mov dword [eax+0Ch], edx |
mov [eax+18h], ecx |
mov eax, [width] |
dec eax |
dec edx |
call SetScreen |
.return: |
ret |
align 4 |
hellomsg db 'Intel videocard detected, PciId=8086:' |
pciid_text db '0000' |
db ', which is ', 0 |
knownmsg db 'known',13,10,0 |
unknownmsg db 'unknown',13,10,0 |
if DEBUG |
edidmsg db 'EDID successfully read:',13,10 |
edid_text rb 8*(16*3+1) |
db 0 |
end if |
version: |
dd 0x50005 |
width dd predefined_width |
height dd predefined_height |
pciids: |
dw 0x3577 ; i830m |
dw 0x2562 ; 845g |
dw 0x3582 ; i855gm |
i865_start = ($ - pciids) / 2 |
dw 0x2572 ; i865g |
i9xx_start = ($ - pciids) / 2 |
dw 0x2582 ; i915g |
dw 0x258a ; e7221g (i915g) |
dw 0x2592 ; i915gm |
dw 0x2772 ; i945g |
dw 0x27a2 ; i945gm |
dw 0x27ae ; i945gme |
i965_start = ($ - pciids) / 2 |
dw 0x2972 ; i946qz (i965g) |
dw 0x2982 ; g35g (i965g) |
dw 0x2992 ; i965q (i965g) |
dw 0x29a2 ; i965g |
dw 0x29b2 ; q35g |
dw 0x29c2 ; g33g |
dw 0x29d2 ; q33g |
dw 0x2a02 ; i965gm |
dw 0x2a12 ; i965gm |
dw 0x2a42 ; gm45 |
dw 0x2e02 ; g45 |
dw 0x2e12 ; g45 |
dw 0x2e22 ; g45 |
dw 0x2e32 ; g45 |
dw 0x2e42 ; g45 |
dw 0x2e92 ; g45 |
dw 0xa001 ; pineview |
dw 0xa011 ; pineview |
ironlake_start = ($ - pciids) / 2 |
dw 0x0042 ; ironlake_d |
dw 0x0046 ; ironlake_m |
dw 0x0102 ; sandybridge_d |
dw 0x0112 ; sandybridge_d |
dw 0x0122 ; sandybridge_d |
dw 0x0106 ; sandybridge_m |
dw 0x0116 ; sandybridge_m |
dw 0x0126 ; sandybridge_m |
dw 0x010A ; sandybridge_d |
pciids_num = ($ - pciids) / 2 |
align 4 |
deviceType dd ? |
edid rb 0x80 |
; Stub of videodriver for Intel videocards. |
; (c) CleverMouse |
; When the start procedure gots control, |
; it tries to detect preferred resolution, |
; sets the detected resolution assuming 32-bpp VESA mode and exits |
; (without registering a service). |
; Detection can be overloaded with compile-time settings |
; use_predefined_mode/predefined_width/predefined_height. |
; set predefined resolution here |
use_predefined_mode = 0;1 |
predefined_width = 0;1366 |
predefined_height = 0;768 |
; standard driver stuff |
format MS COFF |
DEBUG = 1 |
include 'proc32.inc' |
include 'imports.inc' |
public START |
public version |
section '.flat' code readable align 16 |
; the start procedure (see the description above) |
START: |
; 1. Detect device. Abort if not found. |
push esi |
call DetectDevice |
test esi, esi |
jz .return0 |
; 2. Detect optimal mode unless the mode is given explicitly. Abort if failed. |
if use_predefined_mode = 0 |
call DetectMode |
end if |
cmp [width], 0 |
jz .return0_cleanup |
; 3. Set the detected mode. |
call SetMode |
; 4. Cleanup and return. |
.return0_cleanup: |
stdcall FreeKernelSpace, esi |
.return0: |
pop esi |
xor eax, eax |
ret 4 |
; check that there is Intel videocard |
; if so, map MMIO registers and set internal variables |
; esi points to MMIO block; NULL means no device |
DetectDevice: |
; 1. Sanity check: check that we are dealing with Intel videocard. |
; Integrated video device for Intel is always at PCI:0:2:0. |
xor esi, esi ; initialize return value to NULL |
; 1a. Get PCI VendorID and DeviceID. |
push esi |
push 10h |
push esi |
call PciRead32 |
; 1b. loword(eax) = ax = VendorID, hiword(eax) = DeviceID. |
; Test whether we have Intel chipset. |
cmp ax, 8086h |
jnz .return |
; 1c. Say hi including DeviceID. |
shr eax, 10h |
push edi |
pusha |
mov edi, pciid_text |
call WriteWord |
mov esi, hellomsg |
call SysMsgBoardStr |
popa |
; 1d. Test whether we know this DeviceID. |
; If this is the case, remember the position of the device in line of Intel cards; |
; this knowledge will be useful later. |
; Tested on devices with id: 8086:0046, partially 8086:2A02. |
mov ecx, pciids_num |
mov edi, pciids |
repnz scasw |
pop edi |
jnz .return_unknown_pciid |
sub ecx, pciids_num - 1 |
neg ecx |
mov [deviceType], ecx |
; 1e. Continue saying hi with positive intonation. |
pusha |
mov esi, knownmsg |
call SysMsgBoardStr |
popa |
; 2. Prepare MMIO region to control the card. |
; 2a. Read MMIO physical address from PCI config space. |
push 10h |
cmp ecx, i9xx_start |
jae @f |
mov byte [esp], 14h |
@@: |
push 10h |
push esi |
call PciRead32 |
; 2b. Mask out PCI region type, lower 4 bits. |
and al, not 0xF |
; 2c. Create virtual mapping of the physical memory. |
push 1Bh |
push 100000h |
push eax |
call MapIoMem |
; 3. Return. |
xchg esi, eax |
.return: |
ret |
; 1f. If we do not know DeviceID, continue saying hi with negative intonation. |
.return_unknown_pciid: |
pusha |
mov esi, unknownmsg |
call SysMsgBoardStr |
popa |
ret |
; Convert word in ax to hexadecimal text in edi, advance edi. |
WriteWord: |
; 1. Convert high byte. |
push eax |
mov al, ah |
call WriteByte |
pop eax |
; 2. Convert low byte. |
; Fall through to WriteByte; ret from WriteByte is ret from WriteWord too. |
; Convert byte in al to hexadecimal text in edi, advance edi. |
WriteByte: |
; 1. Convert high nibble. |
push eax |
shr al, 4 |
call WriteNibble |
pop eax |
; 2. Convert low nibble. |
and al, 0xF |
; Fall through to WriteNibble; ret from WriteNibble is ret from WriteByte too. |
; Convert nibble in al to hexadecimal text in edi, advance edi. |
WriteNibble: |
; Obvious, isn't it? |
cmp al, 10 |
sbb al, 69h |
das |
stosb |
ret |
if use_predefined_mode = 0 |
; detect resolution of the flat panel |
DetectMode: |
push esi edi |
; 1. Get the location of block of GMBUS* registers. |
; Starting with Ironlake, GMBUS* registers were moved. |
add esi, 5100h |
cmp [deviceType], ironlake_start |
jb @f |
add esi, 0xC0000 |
@@: |
; 2. Initialize GMBUS engine. |
mov edi, edid |
mov ecx, 0x10000 |
@@: |
test byte [esi+8+1], 80h |
loopnz @b |
jnz .fail |
mov dword [esi], 3 |
test byte [esi+8+1], 4 |
jz .noreset |
call ResetGMBus |
jnz .fail |
.noreset: |
; 3. Send read command. |
and dword [esi+20h], 0 |
mov dword [esi+4], 4E8000A1h |
; 4. Wait for data, writing to the buffer as data arrive. |
.getdata: |
mov ecx, 0x10000 |
@@: |
test byte [esi+8+1], 8 |
loopz @b |
test byte [esi+8+1], 4 |
jz .dataok |
call ResetGMBus |
jmp .fail |
.dataok: |
mov eax, [esi+0Ch] |
stosd |
cmp edi, edid+80h |
jb .getdata |
; 5. Wait for bus idle. |
mov ecx, 0x10000 |
@@: |
test byte [esi+8+1], 2 |
loopnz @b |
; 6. We got EDID; dump it if DEBUG. |
if DEBUG |
pusha |
xor ecx, ecx |
mov esi, edid |
mov edi, edid_text |
.dumploop: |
lodsb |
call WriteByte |
mov al, ' ' |
stosb |
inc cl |
test cl, 15 |
jnz @f |
mov byte [edi-1], 13 |
mov al, 10 |
stosb |
@@: |
test cl, cl |
jns .dumploop |
mov esi, edidmsg |
call SysMsgBoardStr |
popa |
end if |
; 7. Test whether EDID is good. |
; 7a. Signature: 00 FF FF FF FF FF FF 00. |
mov esi, edid |
cmp dword [esi], 0xFFFFFF00 |
jnz .fail |
cmp dword [esi+4], 0x00FFFFFF |
jnz .fail |
; 7b. Checksum must be zero. |
xor edx, edx |
mov ecx, 80h |
@@: |
lodsb |
add dl, al |
loop @b |
jnz .fail |
; 8. Get width and height from EDID. |
xor eax, eax |
mov ah, [esi-80h+3Ah] |
shr ah, 4 |
mov al, [esi-80h+38h] |
mov [width], eax |
mov ah, [esi-80h+3Dh] |
shr ah, 4 |
mov al, [esi-80h+3Bh] |
mov [height], eax |
; 9. Return. |
.fail: |
pop edi esi |
ret |
; reset bus, clear all errors |
ResetGMBus: |
; look into the PRM |
mov dword [esi+4], 80000000h |
mov dword [esi+4], 0 |
mov ecx, 0x10000 |
@@: |
test byte [esi+8+1], 2 |
loopnz @b |
ret |
end if |
; set resolution [width]*[height] |
SetMode: |
; 1. Program the registers of videocard. |
; look into the PRM |
cli |
; or byte [esi+7000Ah], 0Ch ; PIPEACONF: disable Display+Cursor Planes |
; or byte [esi+7100Ah], 0Ch ; PIPEBCONF: disable Display+Cursor Planes |
xor eax, eax |
xor edx, edx |
cmp [deviceType], i965_start |
jb @f |
mov dl, 9Ch - 84h |
@@: |
; or byte [esi+71403h], 80h ; VGACNTRL: VGA Display Disable |
and byte [esi+70080h], not 27h ; CURACNTR: disable cursor A |
mov dword [esi+70084h], eax ; CURABASE: force write to CURA* regs |
and byte [esi+700C0h], not 27h ; CURBCNTR: disable cursor B |
mov dword [esi+700C4h], eax ; CURBBASE: force write to CURB* regs |
and byte [esi+70183h], not 80h ; DSPACNTR: disable Primary A Plane |
mov dword [esi+edx+70184h], eax ; DSPALINOFF/DSPASURF: force write to DSPA* regs |
and byte [esi+71183h], not 80h ; DSPBCNTR: disable Primary B Plane |
mov dword [esi+edx+71184h], eax ; DSPBLINOFF/DSPBSURF: force write to DSPB* regs |
if 1 |
cmp [deviceType], ironlake_start |
jae .disable_pipes |
mov edx, 10000h |
or byte [esi+70024h], 2 ; PIPEASTAT: clear VBLANK status |
or byte [esi+71024h], 2 ; PIPEBSTAT: clear VBLANK status |
.wait_vblank_preironlake1: |
mov ecx, 1000h |
loop $ |
test byte [esi+7000Bh], 80h ; PIPEACONF: pipe A active? |
jz @f |
test byte [esi+70024h], 2 ; PIPEASTAT: got VBLANK? |
jz .wait_vblank_preironlake2 |
@@: |
test byte [esi+7100Bh], 80h ; PIPEBCONF: pipe B active? |
jz .disable_pipes |
test byte [esi+71024h], 2 ; PIPEBSTAT: got VBLANK? |
jnz .disable_pipes |
.wait_vblank_preironlake2: |
dec edx |
jnz .wait_vblank_preironlake1 |
jmp .not_disabled |
.disable_pipes: |
end if |
and byte [esi+7000Bh], not 80h ; PIPEACONF: disable pipe |
and byte [esi+7100Bh], not 80h ; PIPEBCONF: disable pipe |
if 1 |
mov edx, 10000h |
@@: |
mov ecx, 1000h |
loop $ |
test byte [esi+7000Bh], 40h ; PIPEACONF: wait until pipe disabled |
jz @f |
dec edx |
jnz @b |
.not_disabled: |
sti |
jmp .return |
@@: |
test byte [esi+7100Bh], 40h ; PIPEBCONF: wait until pipe disabled |
jz @f |
mov ecx, 1000h |
loop $ |
dec edx |
jnz @b |
jmp .not_disabled |
@@: |
else |
; alternative way of waiting for pipe stop, works too |
mov edx, 1000h |
.dis1: |
push dword [esi+71000h] |
push dword [esi+70000h] |
mov ecx, 10000h |
loop $ |
pop eax |
xor eax, [esi+70000h] |
and eax, 1FFFh |
pop eax |
jnz .notdis1 |
xor eax, [esi+71000h] |
and eax, 1FFFh |
jz .disabled |
.notdis1: |
dec edx |
jnz .dis1 |
.not_disabled: |
sti |
jmp .return |
.disabled: |
end if |
lea eax, [esi+61183h] |
cmp [deviceType], ironlake_start |
jb @f |
add eax, 0xE0000 - 0x60000 |
@@: |
lea edx, [esi+60000h] |
test byte [eax], 40h |
jz @f |
add edx, 1000h |
@@: |
mov eax, [width] |
dec eax |
shl eax, 16 |
mov ax, word [height] |
dec eax |
mov dword [edx+1Ch], eax ; PIPEASRC: set source image size |
ror eax, 16 |
mov dword [edx+10190h], eax ; for old cards |
mov ecx, [width] |
add ecx, 15 |
and ecx, not 15 |
shl ecx, 2 |
mov dword [edx+10188h], ecx ; DSPASTRIDE: set scanline length |
and byte [esi+61233h], not 80h ; PFIT_CONTROL: disable panel fitting |
or byte [edx+1000Bh], 80h ; PIPEACONF: enable pipe |
; and byte [edx+1000Ah], not 0Ch ; PIPEACONF: enable Display+Cursor Planes |
or byte [edx+10183h], 80h ; DSPACNTR: enable Display Plane A |
sti |
; 2. Notify the kernel that resolution has changed. |
call GetDisplay |
mov edx, [width] |
mov dword [eax+8], edx |
mov edx, [height] |
mov dword [eax+0Ch], edx |
mov [eax+18h], ecx |
mov eax, [width] |
dec eax |
dec edx |
call SetScreen |
.return: |
ret |
align 4 |
hellomsg db 'Intel videocard detected, PciId=8086:' |
pciid_text db '0000' |
db ', which is ', 0 |
knownmsg db 'known',13,10,0 |
unknownmsg db 'unknown',13,10,0 |
if DEBUG |
edidmsg db 'EDID successfully read:',13,10 |
edid_text rb 8*(16*3+1) |
db 0 |
end if |
version: |
dd 0x50005 |
width dd predefined_width |
height dd predefined_height |
pciids: |
dw 0x3577 ; i830m |
dw 0x2562 ; 845g |
dw 0x3582 ; i855gm |
i865_start = ($ - pciids) / 2 |
dw 0x2572 ; i865g |
i9xx_start = ($ - pciids) / 2 |
dw 0x2582 ; i915g |
dw 0x258a ; e7221g (i915g) |
dw 0x2592 ; i915gm |
dw 0x2772 ; i945g |
dw 0x27a2 ; i945gm |
dw 0x27ae ; i945gme |
i965_start = ($ - pciids) / 2 |
dw 0x2972 ; i946qz (i965g) |
dw 0x2982 ; g35g (i965g) |
dw 0x2992 ; i965q (i965g) |
dw 0x29a2 ; i965g |
dw 0x29b2 ; q35g |
dw 0x29c2 ; g33g |
dw 0x29d2 ; q33g |
dw 0x2a02 ; i965gm |
dw 0x2a12 ; i965gm |
dw 0x2a42 ; gm45 |
dw 0x2e02 ; g45 |
dw 0x2e12 ; g45 |
dw 0x2e22 ; g45 |
dw 0x2e32 ; g45 |
dw 0x2e42 ; g45 |
dw 0x2e92 ; g45 |
dw 0xa001 ; pineview |
dw 0xa011 ; pineview |
ironlake_start = ($ - pciids) / 2 |
dw 0x0042 ; ironlake_d |
dw 0x0046 ; ironlake_m |
dw 0x0102 ; sandybridge_d |
dw 0x0112 ; sandybridge_d |
dw 0x0122 ; sandybridge_d |
dw 0x0106 ; sandybridge_m |
dw 0x0116 ; sandybridge_m |
dw 0x0126 ; sandybridge_m |
dw 0x010A ; sandybridge_d |
pciids_num = ($ - pciids) / 2 |
align 4 |
deviceType dd ? |
edid rb 0x80 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/drivers/vt823x.asm |
---|
1,1281 → 1,1281 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0x01000100 |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
IRQ_REMAP equ 0 |
IRQ_LINE equ 0 |
;irq 0,1,2,8,12,13 ¥¤®áâã¯ë |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
if USE_COM_IRQ |
ATTCH_IRQ equ 0000111010111000b |
end if |
CPU_FREQ equ 2600d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
BIT5 EQU 0x00000020 |
BIT10 EQU 0x00000400 |
VID_VIA equ 0x1106 |
CTRL_VT82C686 equ 0x3058 |
CTRL_VT8233_5 equ 0x3059 |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate |
;VIA host controller registers set |
;; common offsets |
VIA_REG_OFFSET_STATUS equ 0x00 ;; byte - channel status |
VIA_REG_STAT_ACTIVE equ 0x80 ;; RO |
VIA_REG_STAT_PAUSED equ 0x40 ;; RO |
VIA_REG_STAT_TRIGGER_QUEUED equ 0x08 ;; RO |
VIA_REG_STAT_STOPPED equ 0x04 ;; RWC |
VIA_REG_STAT_EOL equ 0x02 ;; RWC |
VIA_REG_STAT_FLAG equ 0x01 ;; RWC |
VIA_REG_OFFSET_CONTROL equ 0x01 ;; byte - channel control |
VIA_REG_CTRL_START equ 0x80 ;; WO |
VIA_REG_CTRL_TERMINATE equ 0x40 ;; WO |
VIA_REG_CTRL_AUTOSTART equ 0x20 |
VIA_REG_CTRL_PAUSE equ 0x08 ;; RW |
VIA_REG_CTRL_INT_STOP equ 0x04 |
VIA_REG_CTRL_INT_EOL equ 0x02 |
VIA_REG_CTRL_INT_FLAG equ 0x01 |
VIA_REG_CTRL_RESET equ 0x01 ;; RW - probably reset? undocumented |
VIA_REG_CTRL_INT equ (VIA_REG_CTRL_INT_FLAG or \ |
VIA_REG_CTRL_INT_EOL or \ |
VIA_REG_CTRL_AUTOSTART) |
VIA_REG_OFFSET_TYPE equ 0x02 ;; byte - channel type (686 only) |
VIA_REG_TYPE_AUTOSTART equ 0x80 ;; RW - autostart at EOL |
VIA_REG_TYPE_16BIT equ 0x20 ;; RW |
VIA_REG_TYPE_STEREO equ 0x10 ;; RW |
VIA_REG_TYPE_INT_LLINE equ 0x00 |
VIA_REG_TYPE_INT_LSAMPLE equ 0x04 |
VIA_REG_TYPE_INT_LESSONE equ 0x08 |
VIA_REG_TYPE_INT_MASK equ 0x0c |
VIA_REG_TYPE_INT_EOL equ 0x02 |
VIA_REG_TYPE_INT_FLAG equ 0x01 |
VIA_REG_OFFSET_TABLE_PTR equ 0x04 ;; dword - channel table pointer |
VIA_REG_OFFSET_CURR_PTR equ 0x04 ;; dword - channel current pointer |
VIA_REG_OFFSET_STOP_IDX equ 0x08 ;; dword - stop index, channel type, sample rate |
VIA8233_REG_TYPE_16BIT equ 0x00200000 ;; RW |
VIA8233_REG_TYPE_STEREO equ 0x00100000 ;; RW |
VIA_REG_OFFSET_CURR_COUNT equ 0x0c ;; dword - channel current count (24 bit) |
VIA_REG_OFFSET_CURR_INDEX equ 0x0f ;; byte - channel current index (for via8233 only) |
VIADEV_PLAYBACK equ 0x00 |
VIADEV_CAPTURE equ 0x10 |
VIADEV_FM equ 0x20 |
;; AC'97 ;; |
VIA_REG_AC97 equ 0x80 ; dword |
VIA_REG_AC97_CODEC_ID_MASK equ 0xC0000000 ;(3<<30) |
VIA_REG_AC97_CODEC_ID_SHIFT equ 30 |
VIA_REG_AC97_CODEC_ID_PRIMARY equ 0x00 |
VIA_REG_AC97_CODEC_ID_SECONDARY equ 0x01 |
VIA_REG_AC97_SECONDARY_VALID equ 0x08000000 ;(1<<27) |
VIA_REG_AC97_PRIMARY_VALID equ 0x02000000 ;(1<<25) |
VIA_REG_AC97_BUSY equ 0x01000000 ;(1<<24) |
VIA_REG_AC97_READ equ 0x00800000 ;(1<<23) |
VIA_REG_AC97_CMD_SHIFT equ 16 |
VIA_REG_AC97_CMD_MASK equ 0x7E |
VIA_REG_AC97_DATA_SHIFT equ 0 |
VIA_REG_AC97_DATA_MASK equ 0xFFFF |
VIA_REG_SGD_SHADOW equ 0x84 ; dword |
;; via8233-specific registers ;; |
VIA_REG_OFS_PLAYBACK_VOLUME_L equ 0x02 ;; byte |
VIA_REG_OFS_PLAYBACK_VOLUME_R equ 0x03 ;; byte |
VIA_REG_OFS_MULTPLAY_FORMAT equ 0x02 ;; byte - format and channels |
VIA_REG_MULTPLAY_FMT_8BIT equ 0x00 |
VIA_REG_MULTPLAY_FMT_16BIT equ 0x80 |
VIA_REG_MULTPLAY_FMT_CH_MASK equ 0x70 ;; # channels << 4 (valid = 1,2,4,6) |
VIA_REG_OFS_CAPTURE_FIFO equ 0x02 ;; byte - bit 6 = fifo enable |
VIA_REG_CAPTURE_FIFO_ENABLE equ 0x40 |
VIA_DXS_MAX_VOLUME equ 31 ;; max. volume (attenuation) of reg 0x32/33 |
VIA_TBL_BIT_FLAG equ 0x40000000 |
VIA_TBL_BIT_EOL equ 0x80000000 |
;; pci space ;; |
VIA_ACLINK_STAT equ 0x40 |
;... |
VIA_ACLINK_C00_READY equ 0x01 ; primary codec ready |
VIA_ACLINK_CTRL equ 0x41 |
VIA_ACLINK_CTRL_ENABLE equ 0x80 ; 0: disable, 1: enable |
VIA_ACLINK_CTRL_RESET equ 0x40 ; 0: assert, 1: de-assert |
VIA_ACLINK_CTRL_SYNC equ 0x20 ; 0: release SYNC, 1: force SYNC hi |
VIA_ACLINK_CTRL_SDO equ 0x10 ; 0: release SDO, 1: force SDO hi |
VIA_ACLINK_CTRL_VRA equ 0x08 ; 0: disable VRA, 1: enable VRA |
VIA_ACLINK_CTRL_PCM equ 0x04 ; 0: disable PCM, 1: enable PCM |
VIA_ACLINK_CTRL_FM equ 0x02 ; via686 only |
VIA_ACLINK_CTRL_SB equ 0x01 ; via686 only |
VIA_ACLINK_CTRL_INIT equ (VIA_ACLINK_CTRL_ENABLE or \ |
VIA_ACLINK_CTRL_RESET or \ |
VIA_ACLINK_CTRL_PCM or \ |
VIA_ACLINK_CTRL_VRA) |
VIA_FUNC_ENABLE equ 0x42 |
VIA_FUNC_MIDI_PNP equ 0x80 ; FIXME: it's 0x40 in the datasheet! |
VIA_FUNC_MIDI_IRQMASK equ 0x40 ; FIXME: not documented! |
VIA_FUNC_RX2C_WRITE equ 0x20 |
VIA_FUNC_SB_FIFO_EMPTY equ 0x10 |
VIA_FUNC_ENABLE_GAME equ 0x08 |
VIA_FUNC_ENABLE_FM equ 0x04 |
VIA_FUNC_ENABLE_MIDI equ 0x02 |
VIA_FUNC_ENABLE_SB equ 0x01 |
VIA_PNP_CONTROL equ 0x43 |
VIA_FM_NMI_CTRL equ 0x48 |
VIA8233_VOLCHG_CTRL equ 0x48 |
VIA8233_SPDIF_CTRL equ 0x49 |
VIA8233_SPDIF_DX3 equ 0x08 |
VIA8233_SPDIF_SLOT_MASK equ 0x03 |
VIA8233_SPDIF_SLOT_1011 equ 0x00 |
VIA8233_SPDIF_SLOT_34 equ 0x01 |
VIA8233_SPDIF_SLOT_78 equ 0x02 |
VIA8233_SPDIF_SLOT_69 equ 0x03 |
;] Asper |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call SysMsgBoardStr |
if IRQ_REMAP |
pushf |
cli |
mov ebx, [ctrl.int_line] |
in al, 0xA1 |
mov ah, al |
in al, 0x21 |
test ebx, ebx |
jz .skip |
bts ax, bx ;mask old line |
.skip: |
bts ax, IRQ_LINE ;mask new ine |
out 0x21, al |
mov al, ah |
out 0xA1, al |
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ |
mov dx, 0x4d0 ;8259 ELCR1 |
in al, dx |
bts ax, IRQ_LINE |
out dx, al ;set level-triggered mode |
mov [ctrl.int_line], IRQ_LINE |
popf |
mov esi, msgRemap |
call SysMsgBoardStr |
end if |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail_msg |
stdcall AttachIntHandler, ebx, ac97_irq_VIA, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call SysMsgBoardStr |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
@@: |
cmp eax, DEV_GET_INFO |
jne @F |
mov ebx, [edi+output] |
stdcall get_dev_info, ebx |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc ac97_irq_VIA |
locals |
status db 0 |
endl |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS |
call [ctrl.ctrl_read8] |
test al, VIA_REG_STAT_ACTIVE |
jz @f |
and al, VIA_REG_STAT_EOL or VIA_REG_STAT_FLAG or VIA_REG_STAT_STOPPED |
mov byte [status], al |
mov ebx, dword [buff_list] |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
mov al, byte [status] ;; ack ;; |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov edi, pcmout_bdl |
stosd |
mov eax, 0x80004000 |
stosd |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
;add eax, 0x4000 |
add edi, 4 |
loop @B |
stdcall channel_reset, VIADEV_PLAYBACK |
stdcall codec_check_ready |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr |
and ebx, 0xFFF |
add eax, ebx |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR |
call [ctrl.ctrl_write32] |
stdcall codec_check_ready |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_L |
mov eax, 7;31 |
call [ctrl.ctrl_write8] |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_R |
mov eax, 7;31 |
call [ctrl.ctrl_write8] |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX |
mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000 |
mov [ctrl.lvi_reg], 16;0xF;eax |
call [ctrl.ctrl_write32] |
stdcall codec_check_ready |
ret |
endp |
proc channel_reset channel:dword |
mov esi, dword [channel] |
mov edx, esi |
add edx, VIA_REG_OFFSET_CONTROL |
mov eax, VIA_REG_CTRL_PAUSE or VIA_REG_CTRL_TERMINATE or VIA_REG_CTRL_RESET |
call [ctrl.ctrl_write8] |
mov edx, esi |
add edx, VIA_REG_OFFSET_CONTROL |
call [ctrl.ctrl_read8] |
mov eax, 50000 ; wait 50 ms |
call StallExec |
; disable interrupts |
mov edx, esi |
add edx, VIA_REG_OFFSET_CONTROL |
xor eax, eax |
call [ctrl.ctrl_write8] |
; clear interrupts |
mov edx, esi |
add edx, VIA_REG_OFFSET_STATUS |
mov eax, 0x03 |
call [ctrl.ctrl_write8] |
;outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ |
; mov edx, esi ;; for via686 |
; add edx, VIA_REG_OFFSET_TYPE |
; mov eax, 0x03 |
; call [ctrl.ctrl_write8] |
;; outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); |
;mov edx, esi |
;add edx, VIA_REG_OFFSET_CURR_PTR |
;xor eax, eax |
;call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
cmp edx, VID_VIA |
jne @F |
mov [ctrl.vendor_ids], msg_VIA |
ret |
@@: |
.err: |
xor eax, eax |
mov [ctrl.vendor_ids], eax ;something wrong ? |
ret |
endp |
align 4 |
proc init_controller |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
.default: |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
@@: |
mov [ctrl.int_line], eax |
;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE ;0x42 |
;mov byte [old_legacy], al |
;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_PNP_CONTROL ;0x43 |
;mov byte [old_legacy_cfg], al |
;mov al, VIA_FUNC_ENABLE_SB or VIA_FUNC_ENABLE_FM |
;xor al, 0xFF |
;and al, byte [old_legacy] |
;and eax, 0xFF |
;stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE, eax ;0x42 |
;mov byte [old_legacy], al |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_VIA |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
align 4 |
proc init_codec |
locals |
counter dd ? |
endl |
mov esi, msgControl |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL |
and eax, 0xFF |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
and eax, 0xFF |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, VIA_ACLINK_C00_READY |
jz .ready |
call reset_codec |
test eax, eax |
jz .err |
.ready: |
xor edx, edx ; ac_reg_0 |
call [ctrl.codec_write16] |
jmp .done |
.err: |
xor eax, eax ; timeout error |
ret |
.done: |
call detect_codec |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, \ |
VIA_ACLINK_CTRL_ENABLE or VIA_ACLINK_CTRL_RESET or VIA_ACLINK_CTRL_SYNC |
mov eax, 100000 ; wait 100 ms |
call StallExec |
.cold: |
call cold_reset |
jnc .ok |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call SysMsgBoardStr |
end if |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword 0 |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms |
call StallExec |
;; ACLink on, deassert ACLink reset, VSR, SGD data out |
;; note - FM data out has trouble with non VRA codecs !! |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword VIA_ACLINK_CTRL_INIT |
mov [counter], 16 ; total 20*100 ms = 2s |
.wait: |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
test eax, VIA_ACLINK_C00_READY |
jnz .ok |
mov eax, 100000 ; wait 100 ms |
call StallExec |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
and eax, 0xFF |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, VIA_ACLINK_C00_READY ;CTRL_ST_CREADY |
jz .fail |
clc |
ret |
endp |
align 4 |
play: |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX |
mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000 |
mov [ctrl.lvi_reg], 16 |
call [ctrl.ctrl_write32] |
mov eax, VIA_REG_CTRL_INT |
or eax, VIA_REG_CTRL_START |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL |
call [ctrl.ctrl_write8] |
xor eax, eax |
ret |
align 4 |
stop: |
mov eax, VIA_REG_CTRL_INT |
or eax, VIA_REG_CTRL_TERMINATE |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL |
call [ctrl.ctrl_write8] |
stdcall channel_reset, VIADEV_PLAYBACK |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ecx, [ctrl.ctrl_io_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.ctrl_io_base], ecx |
xor eax, eax |
;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR |
;call [ctrl.ctrl_read32] |
mov [CTRL_INFO.codec_io_base], eax |
;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX |
;call [ctrl.ctrl_read32] |
mov [CTRL_INFO.codec_mem_base], eax |
;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CURR_COUNT |
;call [ctrl.ctrl_read32] |
mov [CTRL_INFO.ctrl_mem_base], eax |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL |
call [ctrl.ctrl_read8] |
and eax, 0xFF |
mov [CTRL_INFO.glob_cntrl], eax |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS |
call [ctrl.ctrl_read8] |
and eax, 0xFF |
mov [CTRL_INFO.glob_sta], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_check_ready stdcall |
locals |
counter dd ? |
endl |
mov [counter], 1000 ; total 1000*1 ms = 1s |
.wait: |
call [ctrl.codec_read16] |
test eax, VIA_REG_AC97_BUSY |
jz .ok |
mov eax, 1000 ; wait 1 ms |
call StallExec |
sub [counter] , 1 |
jnz .wait |
.err: |
mov eax, -1 |
ret |
.ok: |
and eax, 0xFFFF |
ret |
endp |
align 4 |
proc codec_valid stdcall |
stdcall codec_check_ready |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
locals |
counter dd ? |
endl |
;Use only primary codec. |
mov eax, [ac_reg] |
and eax, 0x7F |
shl eax, VIA_REG_AC97_CMD_SHIFT |
or eax, VIA_REG_AC97_PRIMARY_VALID or VIA_REG_AC97_READ |
mov [counter], 3 ; total 3*20 ms = 60ms |
.wait: |
push eax |
call [ctrl.codec_write16] |
mov eax, 20000 ; wait 20 ms |
call StallExec |
stdcall codec_valid, |
cmp eax, 0 |
pop eax |
jge .ok |
sub [counter] , 1 |
jnz .wait |
jmp .err |
.ok: |
mov eax, 25000 ; wait 25 ms |
call StallExec |
call [ctrl.codec_read16] ;change edx !!! |
and eax, 0xFFFF |
ret |
.err: |
if DEBUG |
mov esi, msgCInvalid |
call SysMsgBoardStr |
end if |
mov eax, -1 ; invalid codec error |
ret |
endp |
align 4 |
proc codec_write stdcall, ac_reg:dword |
;Use only primary codec. |
mov esi, [ac_reg] |
mov edx, esi |
shl edx, VIA_REG_AC97_CMD_SHIFT |
shl eax, VIA_REG_AC97_DATA_SHIFT |
or edx, eax |
mov eax, VIA_REG_AC97_CODEC_ID_PRIMARY ;not VIA_REG_AC97_CODEC_ID_PRIMARY |
shl eax, VIA_REG_AC97_CODEC_ID_SHIFT |
or edx, eax |
mov eax, edx |
mov edx, esi |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
stdcall codec_check_ready |
cmp eax, 0 |
jl .err |
.ok: |
ret |
.err: |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
;mov eax, -1 ; codec not ready error |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_io_r16 ;r32 |
mov edx, [ctrl.ctrl_io_base] |
add edx, VIA_REG_AC97 |
in eax, dx |
ret |
endp |
align 4 |
proc codec_io_w16 ;w32 |
mov edx, [ctrl.ctrl_io_base] |
add edx, VIA_REG_AC97 |
out dx, eax |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
align 4 |
dword2str: |
push eax ebx ecx |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
pop ecx ebx eax |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
include "codec.inc" |
align 4 |
devices dd (CTRL_VT82C686 shl 16)+VID_VIA,msg_VT82C686,set_VIA |
dd (CTRL_VT8233_5 shl 16)+VID_VIA,msg_VT8233,set_VIA |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
msg_VT82C686 db 'VT82C686', 13,10, 0 |
msg_VT8233 db 'VT8233', 13,10, 0 |
msg_VIA db 'VIA' , 13,10, 0 |
szKernel db 'KERNEL', 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
msgAttchIRQ db 'IRQ line not supported', 13,10, 0 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
;msgIRQ db 'AC97 IRQ', 13,10,0 |
;msgInitCtrl db 'init controller',13,10,0 |
;msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer ...',0 |
msgDone db 'done',13,10,0 |
msgRemap db 'Remap IRQ',13,10,0 |
;msgReg db 'set service handler',13,10,0 |
;msgOk db 'service installed',13,10,0 |
msgCold db 'cold reset',13,10,0 |
;msgWarm db 'warm reset',13,10,0 |
;msgWRFail db 'warm reset failed',13,10,0 |
msgCRFail db 'cold reset failed',13,10,0 |
msgCFail db 'codec not ready',13,10,0 |
msgCInvalid db 'codec is not valid',13,10,0 ;Asper |
msgResetOk db 'reset complete',13,10,0 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
msgPciCmd db 'PCI command ',0 |
msgPciStat db 'PCI status ',0 |
msgCtrlIsaIo db 'controller io base ',0 |
;msgMixIsaIo db 'codec io base ',0 |
;msgCtrlMMIo db 'controller mmio base ',0 |
;msgMixMMIo db 'codec mmio base ',0 |
;msgIrqMap db 'AC97 irq map as ',0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
chip_type rb 1 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0x01000100 |
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices |
IRQ_REMAP equ 0 |
IRQ_LINE equ 0 |
;irq 0,1,2,8,12,13 ¥¤®áâã¯ë |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010100000b |
if USE_COM_IRQ |
ATTCH_IRQ equ 0000111010111000b |
end if |
CPU_FREQ equ 2600d |
BIT0 EQU 0x00000001 |
BIT1 EQU 0x00000002 |
BIT5 EQU 0x00000020 |
BIT10 EQU 0x00000400 |
VID_VIA equ 0x1106 |
CTRL_VT82C686 equ 0x3058 |
CTRL_VT8233_5 equ 0x3059 |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate |
;VIA host controller registers set |
;; common offsets |
VIA_REG_OFFSET_STATUS equ 0x00 ;; byte - channel status |
VIA_REG_STAT_ACTIVE equ 0x80 ;; RO |
VIA_REG_STAT_PAUSED equ 0x40 ;; RO |
VIA_REG_STAT_TRIGGER_QUEUED equ 0x08 ;; RO |
VIA_REG_STAT_STOPPED equ 0x04 ;; RWC |
VIA_REG_STAT_EOL equ 0x02 ;; RWC |
VIA_REG_STAT_FLAG equ 0x01 ;; RWC |
VIA_REG_OFFSET_CONTROL equ 0x01 ;; byte - channel control |
VIA_REG_CTRL_START equ 0x80 ;; WO |
VIA_REG_CTRL_TERMINATE equ 0x40 ;; WO |
VIA_REG_CTRL_AUTOSTART equ 0x20 |
VIA_REG_CTRL_PAUSE equ 0x08 ;; RW |
VIA_REG_CTRL_INT_STOP equ 0x04 |
VIA_REG_CTRL_INT_EOL equ 0x02 |
VIA_REG_CTRL_INT_FLAG equ 0x01 |
VIA_REG_CTRL_RESET equ 0x01 ;; RW - probably reset? undocumented |
VIA_REG_CTRL_INT equ (VIA_REG_CTRL_INT_FLAG or \ |
VIA_REG_CTRL_INT_EOL or \ |
VIA_REG_CTRL_AUTOSTART) |
VIA_REG_OFFSET_TYPE equ 0x02 ;; byte - channel type (686 only) |
VIA_REG_TYPE_AUTOSTART equ 0x80 ;; RW - autostart at EOL |
VIA_REG_TYPE_16BIT equ 0x20 ;; RW |
VIA_REG_TYPE_STEREO equ 0x10 ;; RW |
VIA_REG_TYPE_INT_LLINE equ 0x00 |
VIA_REG_TYPE_INT_LSAMPLE equ 0x04 |
VIA_REG_TYPE_INT_LESSONE equ 0x08 |
VIA_REG_TYPE_INT_MASK equ 0x0c |
VIA_REG_TYPE_INT_EOL equ 0x02 |
VIA_REG_TYPE_INT_FLAG equ 0x01 |
VIA_REG_OFFSET_TABLE_PTR equ 0x04 ;; dword - channel table pointer |
VIA_REG_OFFSET_CURR_PTR equ 0x04 ;; dword - channel current pointer |
VIA_REG_OFFSET_STOP_IDX equ 0x08 ;; dword - stop index, channel type, sample rate |
VIA8233_REG_TYPE_16BIT equ 0x00200000 ;; RW |
VIA8233_REG_TYPE_STEREO equ 0x00100000 ;; RW |
VIA_REG_OFFSET_CURR_COUNT equ 0x0c ;; dword - channel current count (24 bit) |
VIA_REG_OFFSET_CURR_INDEX equ 0x0f ;; byte - channel current index (for via8233 only) |
VIADEV_PLAYBACK equ 0x00 |
VIADEV_CAPTURE equ 0x10 |
VIADEV_FM equ 0x20 |
;; AC'97 ;; |
VIA_REG_AC97 equ 0x80 ; dword |
VIA_REG_AC97_CODEC_ID_MASK equ 0xC0000000 ;(3<<30) |
VIA_REG_AC97_CODEC_ID_SHIFT equ 30 |
VIA_REG_AC97_CODEC_ID_PRIMARY equ 0x00 |
VIA_REG_AC97_CODEC_ID_SECONDARY equ 0x01 |
VIA_REG_AC97_SECONDARY_VALID equ 0x08000000 ;(1<<27) |
VIA_REG_AC97_PRIMARY_VALID equ 0x02000000 ;(1<<25) |
VIA_REG_AC97_BUSY equ 0x01000000 ;(1<<24) |
VIA_REG_AC97_READ equ 0x00800000 ;(1<<23) |
VIA_REG_AC97_CMD_SHIFT equ 16 |
VIA_REG_AC97_CMD_MASK equ 0x7E |
VIA_REG_AC97_DATA_SHIFT equ 0 |
VIA_REG_AC97_DATA_MASK equ 0xFFFF |
VIA_REG_SGD_SHADOW equ 0x84 ; dword |
;; via8233-specific registers ;; |
VIA_REG_OFS_PLAYBACK_VOLUME_L equ 0x02 ;; byte |
VIA_REG_OFS_PLAYBACK_VOLUME_R equ 0x03 ;; byte |
VIA_REG_OFS_MULTPLAY_FORMAT equ 0x02 ;; byte - format and channels |
VIA_REG_MULTPLAY_FMT_8BIT equ 0x00 |
VIA_REG_MULTPLAY_FMT_16BIT equ 0x80 |
VIA_REG_MULTPLAY_FMT_CH_MASK equ 0x70 ;; # channels << 4 (valid = 1,2,4,6) |
VIA_REG_OFS_CAPTURE_FIFO equ 0x02 ;; byte - bit 6 = fifo enable |
VIA_REG_CAPTURE_FIFO_ENABLE equ 0x40 |
VIA_DXS_MAX_VOLUME equ 31 ;; max. volume (attenuation) of reg 0x32/33 |
VIA_TBL_BIT_FLAG equ 0x40000000 |
VIA_TBL_BIT_EOL equ 0x80000000 |
;; pci space ;; |
VIA_ACLINK_STAT equ 0x40 |
;... |
VIA_ACLINK_C00_READY equ 0x01 ; primary codec ready |
VIA_ACLINK_CTRL equ 0x41 |
VIA_ACLINK_CTRL_ENABLE equ 0x80 ; 0: disable, 1: enable |
VIA_ACLINK_CTRL_RESET equ 0x40 ; 0: assert, 1: de-assert |
VIA_ACLINK_CTRL_SYNC equ 0x20 ; 0: release SYNC, 1: force SYNC hi |
VIA_ACLINK_CTRL_SDO equ 0x10 ; 0: release SDO, 1: force SDO hi |
VIA_ACLINK_CTRL_VRA equ 0x08 ; 0: disable VRA, 1: enable VRA |
VIA_ACLINK_CTRL_PCM equ 0x04 ; 0: disable PCM, 1: enable PCM |
VIA_ACLINK_CTRL_FM equ 0x02 ; via686 only |
VIA_ACLINK_CTRL_SB equ 0x01 ; via686 only |
VIA_ACLINK_CTRL_INIT equ (VIA_ACLINK_CTRL_ENABLE or \ |
VIA_ACLINK_CTRL_RESET or \ |
VIA_ACLINK_CTRL_PCM or \ |
VIA_ACLINK_CTRL_VRA) |
VIA_FUNC_ENABLE equ 0x42 |
VIA_FUNC_MIDI_PNP equ 0x80 ; FIXME: it's 0x40 in the datasheet! |
VIA_FUNC_MIDI_IRQMASK equ 0x40 ; FIXME: not documented! |
VIA_FUNC_RX2C_WRITE equ 0x20 |
VIA_FUNC_SB_FIFO_EMPTY equ 0x10 |
VIA_FUNC_ENABLE_GAME equ 0x08 |
VIA_FUNC_ENABLE_FM equ 0x04 |
VIA_FUNC_ENABLE_MIDI equ 0x02 |
VIA_FUNC_ENABLE_SB equ 0x01 |
VIA_PNP_CONTROL equ 0x43 |
VIA_FM_NMI_CTRL equ 0x48 |
VIA8233_VOLCHG_CTRL equ 0x48 |
VIA8233_SPDIF_CTRL equ 0x49 |
VIA8233_SPDIF_DX3 equ 0x08 |
VIA8233_SPDIF_SLOT_MASK equ 0x03 |
VIA8233_SPDIF_SLOT_1011 equ 0x00 |
VIA8233_SPDIF_SLOT_34 equ 0x01 |
VIA8233_SPDIF_SLOT_78 equ 0x02 |
VIA8233_SPDIF_SLOT_69 equ 0x03 |
;] Asper |
SRV_GETVERSION equ 0 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi, [ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
call init_codec |
test eax, eax |
jz .fail |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call SysMsgBoardStr |
if IRQ_REMAP |
pushf |
cli |
mov ebx, [ctrl.int_line] |
in al, 0xA1 |
mov ah, al |
in al, 0x21 |
test ebx, ebx |
jz .skip |
bts ax, bx ;mask old line |
.skip: |
bts ax, IRQ_LINE ;mask new ine |
out 0x21, al |
mov al, ah |
out 0xA1, al |
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ |
mov dx, 0x4d0 ;8259 ELCR1 |
in al, dx |
bts ax, IRQ_LINE |
out dx, al ;set level-triggered mode |
mov [ctrl.int_line], IRQ_LINE |
popf |
mov esi, msgRemap |
call SysMsgBoardStr |
end if |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail_msg |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail_msg |
stdcall AttachIntHandler, ebx, ac97_irq_VIA, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call SysMsgBoardStr |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
stdcall get_master_vol, ebx |
ret |
@@: |
cmp eax, DEV_GET_INFO |
jne @F |
mov ebx, [edi+output] |
stdcall get_dev_info, ebx |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc ac97_irq_VIA |
locals |
status db 0 |
endl |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS |
call [ctrl.ctrl_read8] |
test al, VIA_REG_STAT_ACTIVE |
jz @f |
and al, VIA_REG_STAT_EOL or VIA_REG_STAT_FLAG or VIA_REG_STAT_STOPPED |
mov byte [status], al |
mov ebx, dword [buff_list] |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
mov al, byte [status] ;; ack ;; |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov edi, pcmout_bdl |
stosd |
mov eax, 0x80004000 |
stosd |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
;add eax, 0x4000 |
add edi, 4 |
loop @B |
stdcall channel_reset, VIADEV_PLAYBACK |
stdcall codec_check_ready |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr |
and ebx, 0xFFF |
add eax, ebx |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR |
call [ctrl.ctrl_write32] |
stdcall codec_check_ready |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_L |
mov eax, 7 ;31 |
call [ctrl.ctrl_write8] |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_R |
mov eax, 7 ;31 |
call [ctrl.ctrl_write8] |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX |
mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000 |
mov [ctrl.lvi_reg], 16 ;0xF;eax |
call [ctrl.ctrl_write32] |
stdcall codec_check_ready |
ret |
endp |
proc channel_reset channel:dword |
mov esi, dword [channel] |
mov edx, esi |
add edx, VIA_REG_OFFSET_CONTROL |
mov eax, VIA_REG_CTRL_PAUSE or VIA_REG_CTRL_TERMINATE or VIA_REG_CTRL_RESET |
call [ctrl.ctrl_write8] |
mov edx, esi |
add edx, VIA_REG_OFFSET_CONTROL |
call [ctrl.ctrl_read8] |
mov eax, 50000 ; wait 50 ms |
call StallExec |
; disable interrupts |
mov edx, esi |
add edx, VIA_REG_OFFSET_CONTROL |
xor eax, eax |
call [ctrl.ctrl_write8] |
; clear interrupts |
mov edx, esi |
add edx, VIA_REG_OFFSET_STATUS |
mov eax, 0x03 |
call [ctrl.ctrl_write8] |
;outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ |
; mov edx, esi ;; for via686 |
; add edx, VIA_REG_OFFSET_TYPE |
; mov eax, 0x03 |
; call [ctrl.ctrl_write8] |
;; outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); |
;mov edx, esi |
;add edx, VIA_REG_OFFSET_CURR_PTR |
;xor eax, eax |
;call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
cmp edx, VID_VIA |
jne @F |
mov [ctrl.vendor_ids], msg_VIA |
ret |
@@: |
.err: |
xor eax, eax |
mov [ctrl.vendor_ids], eax ;something wrong ? |
ret |
endp |
align 4 |
proc init_controller |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
mov esi, msgPciCmd |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
.default: |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
@@: |
mov [ctrl.int_line], eax |
;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE ;0x42 |
;mov byte [old_legacy], al |
;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_PNP_CONTROL ;0x43 |
;mov byte [old_legacy_cfg], al |
;mov al, VIA_FUNC_ENABLE_SB or VIA_FUNC_ENABLE_FM |
;xor al, 0xFF |
;and al, byte [old_legacy] |
;and eax, 0xFF |
;stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE, eax ;0x42 |
;mov byte [old_legacy], al |
call [ctrl.ctrl_setup] |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc set_VIA |
mov [ctrl.codec_read16], codec_io_r16 ;virtual |
mov [ctrl.codec_write16], codec_io_w16 ;virtual |
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual |
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual |
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual |
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual |
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual |
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual |
ret |
endp |
align 4 |
proc init_codec |
locals |
counter dd ? |
endl |
mov esi, msgControl |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL |
and eax, 0xFF |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
and eax, 0xFF |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, VIA_ACLINK_C00_READY |
jz .ready |
call reset_codec |
test eax, eax |
jz .err |
.ready: |
xor edx, edx ; ac_reg_0 |
call [ctrl.codec_write16] |
jmp .done |
.err: |
xor eax, eax ; timeout error |
ret |
.done: |
call detect_codec |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, \ |
VIA_ACLINK_CTRL_ENABLE or VIA_ACLINK_CTRL_RESET or VIA_ACLINK_CTRL_SYNC |
mov eax, 100000 ; wait 100 ms |
call StallExec |
.cold: |
call cold_reset |
jnc .ok |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call SysMsgBoardStr |
end if |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword 0 |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms |
call StallExec |
;; ACLink on, deassert ACLink reset, VSR, SGD data out |
;; note - FM data out has trouble with non VRA codecs !! |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword VIA_ACLINK_CTRL_INIT |
mov [counter], 16 ; total 20*100 ms = 2s |
.wait: |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
test eax, VIA_ACLINK_C00_READY |
jnz .ok |
mov eax, 100000 ; wait 100 ms |
call StallExec |
dec [counter] |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
and eax, 0xFF |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, VIA_ACLINK_C00_READY ;CTRL_ST_CREADY |
jz .fail |
clc |
ret |
endp |
align 4 |
play: |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX |
mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000 |
mov [ctrl.lvi_reg], 16 |
call [ctrl.ctrl_write32] |
mov eax, VIA_REG_CTRL_INT |
or eax, VIA_REG_CTRL_START |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL |
call [ctrl.ctrl_write8] |
xor eax, eax |
ret |
align 4 |
stop: |
mov eax, VIA_REG_CTRL_INT |
or eax, VIA_REG_CTRL_TERMINATE |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL |
call [ctrl.ctrl_write8] |
stdcall channel_reset, VIADEV_PLAYBACK |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ecx, [ctrl.ctrl_io_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.ctrl_io_base], ecx |
xor eax, eax |
;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR |
;call [ctrl.ctrl_read32] |
mov [CTRL_INFO.codec_io_base], eax |
;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX |
;call [ctrl.ctrl_read32] |
mov [CTRL_INFO.codec_mem_base], eax |
;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CURR_COUNT |
;call [ctrl.ctrl_read32] |
mov [CTRL_INFO.ctrl_mem_base], eax |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL |
call [ctrl.ctrl_read8] |
and eax, 0xFF |
mov [CTRL_INFO.glob_cntrl], eax |
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS |
call [ctrl.ctrl_read8] |
and eax, 0xFF |
mov [CTRL_INFO.glob_sta], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_check_ready stdcall |
locals |
counter dd ? |
endl |
mov [counter], 1000 ; total 1000*1 ms = 1s |
.wait: |
call [ctrl.codec_read16] |
test eax, VIA_REG_AC97_BUSY |
jz .ok |
mov eax, 1000 ; wait 1 ms |
call StallExec |
sub [counter] , 1 |
jnz .wait |
.err: |
mov eax, -1 |
ret |
.ok: |
and eax, 0xFFFF |
ret |
endp |
align 4 |
proc codec_valid stdcall |
stdcall codec_check_ready |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
locals |
counter dd ? |
endl |
;Use only primary codec. |
mov eax, [ac_reg] |
and eax, 0x7F |
shl eax, VIA_REG_AC97_CMD_SHIFT |
or eax, VIA_REG_AC97_PRIMARY_VALID or VIA_REG_AC97_READ |
mov [counter], 3 ; total 3*20 ms = 60ms |
.wait: |
push eax |
call [ctrl.codec_write16] |
mov eax, 20000 ; wait 20 ms |
call StallExec |
stdcall codec_valid |
cmp eax, 0 |
pop eax |
jge .ok |
sub [counter] , 1 |
jnz .wait |
jmp .err |
.ok: |
mov eax, 25000 ; wait 25 ms |
call StallExec |
call [ctrl.codec_read16] ;change edx !!! |
and eax, 0xFFFF |
ret |
.err: |
if DEBUG |
mov esi, msgCInvalid |
call SysMsgBoardStr |
end if |
mov eax, -1 ; invalid codec error |
ret |
endp |
align 4 |
proc codec_write stdcall, ac_reg:dword |
;Use only primary codec. |
mov esi, [ac_reg] |
mov edx, esi |
shl edx, VIA_REG_AC97_CMD_SHIFT |
shl eax, VIA_REG_AC97_DATA_SHIFT |
or edx, eax |
mov eax, VIA_REG_AC97_CODEC_ID_PRIMARY ;not VIA_REG_AC97_CODEC_ID_PRIMARY |
shl eax, VIA_REG_AC97_CODEC_ID_SHIFT |
or edx, eax |
mov eax, edx |
mov edx, esi |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
stdcall codec_check_ready |
cmp eax, 0 |
jl .err |
.ok: |
ret |
.err: |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
;mov eax, -1 ; codec not ready error |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx, edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_io_r16 ;r32 |
mov edx, [ctrl.ctrl_io_base] |
add edx, VIA_REG_AC97 |
in eax, dx |
ret |
endp |
align 4 |
proc codec_io_w16 ;w32 |
mov edx, [ctrl.ctrl_io_base] |
add edx, VIA_REG_AC97 |
out dx, eax |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
align 4 |
dword2str: |
push eax ebx ecx |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
pop ecx ebx eax |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
include "codec.inc" |
align 4 |
devices dd (CTRL_VT82C686 shl 16)+VID_VIA,msg_VT82C686,set_VIA |
dd (CTRL_VT8233_5 shl 16)+VID_VIA,msg_VT8233,set_VIA |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
msg_VT82C686 db 'VT82C686', 13,10, 0 |
msg_VT8233 db 'VT8233', 13,10, 0 |
msg_VIA db 'VIA' , 13,10, 0 |
szKernel db 'KERNEL', 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
msgAttchIRQ db 'IRQ line not supported', 13,10, 0 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
;msgIRQ db 'AC97 IRQ', 13,10,0 |
;msgInitCtrl db 'init controller',13,10,0 |
;msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer ...',0 |
msgDone db 'done',13,10,0 |
msgRemap db 'Remap IRQ',13,10,0 |
;msgReg db 'set service handler',13,10,0 |
;msgOk db 'service installed',13,10,0 |
msgCold db 'cold reset',13,10,0 |
;msgWarm db 'warm reset',13,10,0 |
;msgWRFail db 'warm reset failed',13,10,0 |
msgCRFail db 'cold reset failed',13,10,0 |
msgCFail db 'codec not ready',13,10,0 |
msgCInvalid db 'codec is not valid',13,10,0 ;Asper |
msgResetOk db 'reset complete',13,10,0 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
msgPciCmd db 'PCI command ',0 |
msgPciStat db 'PCI status ',0 |
msgCtrlIsaIo db 'controller io base ',0 |
;msgMixIsaIo db 'codec io base ',0 |
;msgCtrlMMIo db 'controller mmio base ',0 |
;msgMixMMIo db 'codec mmio base ',0 |
;msgIrqMap db 'AC97 irq map as ',0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
chip_type rb 1 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fdo.inc |
---|
1,437 → 1,444 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
_esp equ esp |
; |
; Formatted Debug Output (FDO) |
; Copyright (c) 2005-2006, mike.dld |
; Created: 2005-01-29, Changed: 2006-11-10 |
; |
; For questions and bug reports, mail to mike.dld@gmail.com |
; |
; Available format specifiers are: %s, %d, %u, %x (with partial width support) |
; |
; to be defined: |
; __DEBUG__ equ 1 |
; __DEBUG_LEVEL__ equ 5 |
macro debug_func name { |
if used name |
name@of@func equ name |
} |
macro debug_beginf { |
align 4 |
name@of@func: |
} |
debug_endf fix end if |
macro DEBUGS _sign,[_str] { |
common |
local tp |
tp equ 0 |
match _arg:_num,_str \{ |
DEBUGS_N _sign,_num,_arg |
tp equ 1 |
\} |
match =0 _arg,tp _str \{ |
DEBUGS_N _sign,,_arg |
\} |
} |
macro DEBUGS_N _sign,_num,[_str] { |
common |
pushf |
pushad |
local ..str,..label,is_str |
is_str = 0 |
forward |
if _str eqtype '' |
is_str = 1 |
end if |
common |
if is_str = 1 |
jmp ..label |
..str db _str,0 |
..label: |
mov edx,..str |
else |
esp equ esp+4*8+4 |
mov edx,_str |
esp equ _esp |
end if |
if ~_num eq |
if _num eqtype eax |
if _num in <eax,ebx,ecx,edx,edi,ebp,esp> |
mov esi,_num |
else if ~_num eq esi |
movzx esi,_num |
end if |
else if _num eqtype 0 |
mov esi,_num |
else |
local tp |
tp equ 0 |
match [_arg],_num \{ |
mov esi,dword[_arg] |
tp equ 1 |
\} |
match =0 =dword[_arg],tp _num \{ |
mov esi,dword[_arg] |
tp equ 1 |
\} |
match =0 =word[_arg],tp _num \{ |
movzx esi,word[_arg] |
tp equ 1 |
\} |
match =0 =byte[_arg],tp _num \{ |
movzx esi,byte[_arg] |
tp equ 1 |
\} |
match =0,tp \{ |
'Error: specified string width is incorrect' |
\} |
end if |
else |
mov esi,0x7FFFFFFF |
end if |
call fdo_debug_outstr |
popad |
popf |
} |
macro DEBUGD _sign,_dec { |
local tp |
tp equ 0 |
match _arg:_num,_dec \{ |
DEBUGD_N _sign,_num,_arg |
tp equ 1 |
\} |
match =0 _arg,tp _dec \{ |
DEBUGD_N _sign,,_arg |
\} |
} |
macro DEBUGD_N _sign,_num,_dec { |
pushf |
pushad |
if (~_num eq) |
if (_dec eqtype eax | _dec eqtype 0) |
'Error: precision allowed only for in-memory variables' |
end if |
if (~_num in <1,2,4>) |
if _sign |
'Error: 1, 2 and 4 are only allowed for precision in %d' |
else |
'Error: 1, 2 and 4 are only allowed for precision in %u' |
end if |
end if |
end if |
if _dec eqtype eax |
if _dec in <ebx,ecx,edx,esi,edi,ebp,esp> |
mov eax,_dec |
else if ~_dec eq eax |
if _sign = 1 |
movsx eax,_dec |
else |
movzx eax,_dec |
end if |
end if |
else if _dec eqtype 0 |
mov eax,_dec |
else |
; add esp,4*8+4 |
esp equ esp+4*8+4 |
if _num eq |
mov eax,dword _dec |
else if _num = 1 |
if _sign = 1 |
movsx eax,byte _dec |
else |
movzx eax,byte _dec |
end if |
else if _num = 2 |
if _sign = 1 |
movsx eax,word _dec |
else |
movzx eax,word _dec |
end if |
else |
mov eax,dword _dec |
end if |
esp equ _esp |
; sub esp,4*8+4 |
end if |
mov cl,_sign |
call fdo_debug_outdec |
popad |
popf |
} |
macro DEBUGH _sign,_hex { |
local tp |
tp equ 0 |
match _arg:_num,_hex \{ |
DEBUGH_N _sign,_num,_arg |
tp equ 1 |
\} |
match =0 _arg,tp _hex \{ |
DEBUGH_N _sign,,_arg |
\} |
} |
macro DEBUGH_N _sign,_num,_hex { |
pushf |
pushad |
if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>) |
'Error: 1..8 are only allowed for precision in %x' |
end if |
if _hex eqtype eax |
if _hex in <eax,ebx,ecx,edx,esi,edi,ebp,esp> |
if ~_hex eq eax |
mov eax,_hex |
end if |
mov edx,8 |
else if _hex in <ax,bx,cx,dx,si,di,bp,sp> |
if ~_hex eq ax |
movzx eax,_hex |
end if |
if (_num eq) |
mov edx,4 |
end if |
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh> |
if ~_hex eq al |
movzx eax,_hex |
end if |
if (_num eq) |
mov edx,2 |
end if |
end if |
else if _hex eqtype 0 |
mov eax,_hex |
else |
; add esp,4*8+4 |
esp equ esp+4*8+4 |
mov eax,dword _hex |
esp equ _esp |
; sub esp,4*8+4 |
end if |
if ~_num eq |
mov edx,_num |
else |
if ~_hex eqtype eax |
mov edx,8 |
end if |
end if |
call fdo_debug_outhex |
popad |
popf |
} |
;----------------------------------------------------------------------------- |
debug_func fdo_debug_outchar |
debug_beginf |
pushad |
movzx ebx,al |
mov eax,1 |
mov ecx,sys_msg_board |
call ecx ; sys_msg_board |
popad |
ret |
debug_endf |
debug_func fdo_debug_outstr |
debug_beginf |
mov eax,1 |
.l1: dec esi |
js .l2 |
movzx ebx,byte[edx] |
or bl,bl |
jz .l2 |
mov ecx,sys_msg_board |
call ecx ; sys_msg_board |
inc edx |
jmp .l1 |
.l2: ret |
debug_endf |
debug_func fdo_debug_outdec |
debug_beginf |
or cl,cl |
jz @f |
or eax,eax |
jns @f |
neg eax |
push eax |
mov al,'-' |
call fdo_debug_outchar |
pop eax |
@@: push 10 |
pop ecx |
push -'0' |
.l1: xor edx,edx |
div ecx |
push edx |
test eax,eax |
jnz .l1 |
.l2: pop eax |
add al,'0' |
jz .l3 |
call fdo_debug_outchar |
jmp .l2 |
.l3: ret |
debug_endf |
debug_func fdo_debug_outhex |
__fdo_hexdigits db '0123456789ABCDEF' |
debug_beginf |
mov cl,dl |
neg cl |
add cl,8 |
shl cl,2 |
rol eax,cl |
.l1: rol eax,4 |
push eax |
and eax,0x0000000F |
mov al,[__fdo_hexdigits+eax] |
call fdo_debug_outchar |
pop eax |
dec edx |
jnz .l1 |
ret |
debug_endf |
;----------------------------------------------------------------------------- |
macro DEBUGF _level,_format,[_arg] { |
common |
if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__ |
local ..f1,f2,a1,a2,c1,c2,c3,..lbl |
_debug_str_ equ __debug_str_ # a1 |
a1 = 0 |
c2 = 0 |
c3 = 0 |
f2 = 0 |
repeat ..lbl-..f1 |
virtual at 0 |
db _format,0,0 |
load c1 word from %-1 |
end virtual |
if c1 = '%s' |
virtual at 0 |
db _format,0,0 |
store word 0 at %-1 |
load c1 from f2-c2 |
end virtual |
if c1 <> 0 |
DEBUGS 0,_debug_str_+f2-c2 |
end if |
c2 = c2 + 1 |
f2 = %+1 |
DEBUGF_HELPER S,a1,0,_arg |
else if c1 = '%x' |
virtual at 0 |
db _format,0,0 |
store word 0 at %-1 |
load c1 from f2-c2 |
end virtual |
if c1 <> 0 |
DEBUGS 0,_debug_str_+f2-c2 |
end if |
c2 = c2 + 1 |
f2 = %+1 |
DEBUGF_HELPER H,a1,0,_arg |
else if c1 = '%d' | c1 = '%u' |
local c4 |
if c1 = '%d' |
c4 = 1 |
else |
c4 = 0 |
end if |
virtual at 0 |
db _format,0,0 |
store word 0 at %-1 |
load c1 from f2-c2 |
end virtual |
if c1 <> 0 |
DEBUGS 0,_debug_str_+f2-c2 |
end if |
c2 = c2 + 1 |
f2 = %+1 |
DEBUGF_HELPER D,a1,c4,_arg |
else if c1 = '\n' |
c3 = c3 + 1 |
end if |
end repeat |
virtual at 0 |
db _format,0,0 |
load c1 from f2-c2 |
end virtual |
if (c1<>0)&(f2<>..lbl-..f1-1) |
DEBUGS 0,_debug_str_+f2-c2 |
end if |
virtual at 0 |
..f1 db _format,0 |
..lbl: |
__debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3 |
end virtual |
end if |
} |
macro __include_debug_strings dummy,[_id,_fmt,_len] { |
common |
local c1,a1,a2 |
forward |
if defined _len & ~_len eq |
_id: |
a1 = 0 |
a2 = 0 |
repeat _len |
virtual at 0 |
db _fmt,0,0 |
load c1 word from %+a2-1 |
end virtual |
if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u') |
db 0 |
a2 = a2 + 1 |
else if (c1='\n') |
dw $0A0D |
a1 = a1 + 1 |
a2 = a2 + 1 |
else |
db c1 and 0x0FF |
end if |
end repeat |
db 0 |
end if |
} |
macro DEBUGF_HELPER _letter,_num,_sign,[_arg] { |
common |
local num |
num = 0 |
forward |
if num = _num |
DEBUG#_letter _sign,_arg |
end if |
num = num+1 |
common |
_num = _num+1 |
} |
macro include_debug_strings { |
if __DEBUG__ = 1 |
match dbg_str,__debug_strings \{ |
__include_debug_strings dbg_str |
\} |
end if |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
_esp equ esp |
; |
; Formatted Debug Output (FDO) |
; Copyright (c) 2005-2006, mike.dld |
; Created: 2005-01-29, Changed: 2006-11-10 |
; |
; For questions and bug reports, mail to mike.dld@gmail.com |
; |
; Available format specifiers are: %s, %d, %u, %x (with partial width support) |
; |
; to be defined: |
; __DEBUG__ equ 1 |
; __DEBUG_LEVEL__ equ 5 |
macro debug_func name { |
if used name |
name@of@func equ name |
} |
macro debug_beginf { |
align 4 |
name@of@func: |
} |
debug_endf fix end if |
macro DEBUGS _sign,[_str] { |
common |
local tp |
tp equ 0 |
match _arg:_num,_str \{ |
DEBUGS_N _sign,_num,_arg |
tp equ 1 |
\} |
match =0 _arg,tp _str \{ |
DEBUGS_N _sign,,_arg |
\} |
} |
macro DEBUGS_N _sign,_num,[_str] { |
common |
pushf |
pushad |
local ..str,..label,is_str |
is_str = 0 |
forward |
if _str eqtype '' |
is_str = 1 |
end if |
common |
if is_str = 1 |
jmp ..label |
..str db _str,0 |
..label: |
mov edx, ..str |
else |
esp equ esp+4*8+4 |
mov edx, _str |
esp equ _esp |
end if |
if ~_num eq |
if _num eqtype eax |
if _num in <eax,ebx,ecx,edx,edi,ebp,esp> |
mov esi, _num |
else if ~_num eq esi |
movzx esi, _num |
end if |
else if _num eqtype 0 |
mov esi, _num |
else |
local tp |
tp equ 0 |
match [_arg],_num \{ |
mov esi, dword[_arg] |
tp equ 1 |
\} |
match =0 =dword[_arg],tp _num \{ |
mov esi, dword[_arg] |
tp equ 1 |
\} |
match =0 =word[_arg],tp _num \{ |
movzx esi, word[_arg] |
tp equ 1 |
\} |
match =0 =byte[_arg],tp _num \{ |
movzx esi, byte[_arg] |
tp equ 1 |
\} |
match =0,tp \{ |
'Error: specified string width is incorrect' |
\} |
end if |
else |
mov esi, 0x7FFFFFFF |
end if |
call fdo_debug_outstr |
popad |
popf |
} |
macro DEBUGD _sign,_dec { |
local tp |
tp equ 0 |
match _arg:_num,_dec \{ |
DEBUGD_N _sign,_num,_arg |
tp equ 1 |
\} |
match =0 _arg,tp _dec \{ |
DEBUGD_N _sign,,_arg |
\} |
} |
macro DEBUGD_N _sign,_num,_dec { |
pushf |
pushad |
if (~_num eq) |
if (_dec eqtype eax | _dec eqtype 0) |
'Error: precision allowed only for in-memory variables' |
end if |
if (~_num in <1,2,4>) |
if _sign |
'Error: 1, 2 and 4 are only allowed for precision in %d' |
else |
'Error: 1, 2 and 4 are only allowed for precision in %u' |
end if |
end if |
end if |
if _dec eqtype eax |
if _dec in <ebx,ecx,edx,esi,edi,ebp,esp> |
mov eax, _dec |
else if ~_dec eq eax |
if _sign = 1 |
movsx eax, _dec |
else |
movzx eax, _dec |
end if |
end if |
else if _dec eqtype 0 |
mov eax, _dec |
else |
; add esp,4*8+4 |
esp equ esp+4*8+4 |
if _num eq |
mov eax, dword _dec |
else if _num = 1 |
if _sign = 1 |
movsx eax, byte _dec |
else |
movzx eax, byte _dec |
end if |
else if _num = 2 |
if _sign = 1 |
movsx eax, word _dec |
else |
movzx eax, word _dec |
end if |
else |
mov eax, dword _dec |
end if |
esp equ _esp |
; sub esp,4*8+4 |
end if |
mov cl, _sign |
call fdo_debug_outdec |
popad |
popf |
} |
macro DEBUGH _sign,_hex { |
local tp |
tp equ 0 |
match _arg:_num,_hex \{ |
DEBUGH_N _sign,_num,_arg |
tp equ 1 |
\} |
match =0 _arg,tp _hex \{ |
DEBUGH_N _sign,,_arg |
\} |
} |
macro DEBUGH_N _sign,_num,_hex { |
pushf |
pushad |
if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>) |
'Error: 1..8 are only allowed for precision in %x' |
end if |
if _hex eqtype eax |
if _hex in <eax,ebx,ecx,edx,esi,edi,ebp,esp> |
if ~_hex eq eax |
mov eax, _hex |
end if |
mov edx, 8 |
else if _hex in <ax,bx,cx,dx,si,di,bp,sp> |
if ~_hex eq ax |
movzx eax, _hex |
end if |
if (_num eq) |
mov edx, 4 |
end if |
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh> |
if ~_hex eq al |
movzx eax, _hex |
end if |
if (_num eq) |
mov edx, 2 |
end if |
end if |
else if _hex eqtype 0 |
mov eax, _hex |
else |
; add esp,4*8+4 |
esp equ esp+4*8+4 |
mov eax, dword _hex |
esp equ _esp |
; sub esp,4*8+4 |
end if |
if ~_num eq |
mov edx, _num |
else |
if ~_hex eqtype eax |
mov edx, 8 |
end if |
end if |
call fdo_debug_outhex |
popad |
popf |
} |
;----------------------------------------------------------------------------- |
debug_func fdo_debug_outchar |
debug_beginf |
pushad |
movzx ebx, al |
mov eax, 1 |
mov ecx, sys_msg_board |
call ecx ; sys_msg_board |
popad |
ret |
debug_endf |
debug_func fdo_debug_outstr |
debug_beginf |
mov eax, 1 |
.l1: |
dec esi |
js .l2 |
movzx ebx, byte[edx] |
or bl, bl |
jz .l2 |
mov ecx, sys_msg_board |
call ecx ; sys_msg_board |
inc edx |
jmp .l1 |
.l2: |
ret |
debug_endf |
debug_func fdo_debug_outdec |
debug_beginf |
or cl, cl |
jz @f |
or eax, eax |
jns @f |
neg eax |
push eax |
mov al, '-' |
call fdo_debug_outchar |
pop eax |
@@: |
push 10 |
pop ecx |
push -'0' |
.l1: |
xor edx, edx |
div ecx |
push edx |
test eax, eax |
jnz .l1 |
.l2: |
pop eax |
add al, '0' |
jz .l3 |
call fdo_debug_outchar |
jmp .l2 |
.l3: |
ret |
debug_endf |
debug_func fdo_debug_outhex |
__fdo_hexdigits db '0123456789ABCDEF' |
debug_beginf |
mov cl, dl |
neg cl |
add cl, 8 |
shl cl, 2 |
rol eax, cl |
.l1: |
rol eax, 4 |
push eax |
and eax, 0x0000000F |
mov al, [__fdo_hexdigits+eax] |
call fdo_debug_outchar |
pop eax |
dec edx |
jnz .l1 |
ret |
debug_endf |
;----------------------------------------------------------------------------- |
macro DEBUGF _level,_format,[_arg] { |
common |
if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__ |
local ..f1,f2,a1,a2,c1,c2,c3,..lbl |
_debug_str_ equ __debug_str_ # a1 |
a1 = 0 |
c2 = 0 |
c3 = 0 |
f2 = 0 |
repeat ..lbl-..f1 |
virtual at 0 |
db _format,0,0 |
load c1 word from %-1 |
end virtual |
if c1 = '%s' |
virtual at 0 |
db _format,0,0 |
store word 0 at %-1 |
load c1 from f2-c2 |
end virtual |
if c1 <> 0 |
DEBUGS 0,_debug_str_+f2-c2 |
end if |
c2 = c2 + 1 |
f2 = %+1 |
DEBUGF_HELPER S,a1,0,_arg |
else if c1 = '%x' |
virtual at 0 |
db _format,0,0 |
store word 0 at %-1 |
load c1 from f2-c2 |
end virtual |
if c1 <> 0 |
DEBUGS 0,_debug_str_+f2-c2 |
end if |
c2 = c2 + 1 |
f2 = %+1 |
DEBUGF_HELPER H,a1,0,_arg |
else if c1 = '%d' | c1 = '%u' |
local c4 |
if c1 = '%d' |
c4 = 1 |
else |
c4 = 0 |
end if |
virtual at 0 |
db _format,0,0 |
store word 0 at %-1 |
load c1 from f2-c2 |
end virtual |
if c1 <> 0 |
DEBUGS 0,_debug_str_+f2-c2 |
end if |
c2 = c2 + 1 |
f2 = %+1 |
DEBUGF_HELPER D,a1,c4,_arg |
else if c1 = '\n' |
c3 = c3 + 1 |
end if |
end repeat |
virtual at 0 |
db _format,0,0 |
load c1 from f2-c2 |
end virtual |
if (c1<>0)&(f2<>..lbl-..f1-1) |
DEBUGS 0,_debug_str_+f2-c2 |
end if |
virtual at 0 |
..f1 db _format,0 |
..lbl: |
__debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3 |
end virtual |
end if |
} |
macro __include_debug_strings dummy,[_id,_fmt,_len] { |
common |
local c1,a1,a2 |
forward |
if defined _len & ~_len eq |
_id: |
a1 = 0 |
a2 = 0 |
repeat _len |
virtual at 0 |
db _fmt,0,0 |
load c1 word from %+a2-1 |
end virtual |
if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u') |
db 0 |
a2 = a2 + 1 |
else if (c1='\n') |
dw $0A0D |
a1 = a1 + 1 |
a2 = a2 + 1 |
else |
db c1 and 0x0FF |
end if |
end repeat |
db 0 |
end if |
} |
macro DEBUGF_HELPER _letter,_num,_sign,[_arg] { |
common |
local num |
num = 0 |
forward |
if num = _num |
DEBUG#_letter _sign,_arg |
end if |
num = num+1 |
common |
_num = _num+1 |
} |
macro include_debug_strings { |
if __DEBUG__ = 1 |
match dbg_str,__debug_strings \{ |
__include_debug_strings dbg_str |
\} |
end if |
} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fs/ext2.inc |
---|
180,9 → 180,9 |
mov esi, ebx |
mov edi, eax |
mov ecx, 512/4 |
rep movsd ; copy sb to reserved mem |
rep movsd ; copy sb to reserved mem |
mov ebx, eax |
mov [ext2_data.sb],eax |
mov [ext2_data.sb], eax |
mov eax, [ebx + EXT2_SB_STRUC.blocks_count] |
sub eax, [ebx + EXT2_SB_STRUC.first_data_block] |
238,7 → 238,7 |
mov eax, EXT2_ROOT_INO |
call ext2_get_inode ; read root inode |
jmp return_from_part_set |
jmp return_from_part_set |
;================================================================== |
;in: eax = i_block |
276,8 → 276,8 |
;.get_triple_indirect_block: |
push eax edx ebx |
mov eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4] |
mov ebx, [ext2_data.ext2_temp_block] |
mov eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4] |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
xor edx, edx |
285,11 → 285,11 |
div [ext2_data.count_pointer_in_block_square] |
;eax - номер в полученном блоке edx - номер дальше |
mov eax, [ebx + eax*4] |
call ext2_get_block |
mov eax, [ebx + eax*4] |
call ext2_get_block |
mov eax, edx |
jmp @F |
mov eax, edx |
jmp @F |
.get_double_indirect_block: |
push eax edx ebx |
303,9 → 303,9 |
xor edx, edx |
div [ext2_data.count_pointer_in_block] |
mov eax, [ebx + eax*4] |
mov eax, [ebx + eax*4] |
call ext2_get_block |
mov ecx, [ebx + edx*4] |
mov ecx, [ebx + edx*4] |
pop ebx edx eax |
ret |
330,11 → 330,11 |
; ebx = address of inode content |
ext2_get_inode: |
pushad |
mov edi, ebx ;сохраним адрес inode |
dec eax |
xor edx, edx |
div [ext2_data.inodes_per_group] |
pushad |
mov edi, ebx ;сохраним адрес inode |
dec eax |
xor edx, edx |
div [ext2_data.inodes_per_group] |
push edx ;locale num in group |
375,7 → 375,7 |
mov esi, edx ;добавим "остаток" |
add esi, ebx ;к адресу |
; mov ecx, [ext2_data.inode_size] |
rep movsb ;копируем inode |
rep movsb ;копируем inode |
popad |
ret |
387,56 → 387,56 |
ext2_test_block_by_name: |
push eax ecx edx edi |
mov edx, ebx |
add edx, [ext2_data.block_size] ;запомним конец блока |
mov edx, ebx |
add edx, [ext2_data.block_size] ;запомним конец блока |
.start_rec: |
cmp [ebx + EXT2_DIR_STRUC.inode], 0 |
jz .next_rec |
cmp [ebx + EXT2_DIR_STRUC.inode], 0 |
jz .next_rec |
push esi |
movzx ecx, [ebx + EXT2_DIR_STRUC.name_len] |
mov edi, EXT2_filename |
lea esi, [ebx + EXT2_DIR_STRUC.name] |
push esi |
movzx ecx, [ebx + EXT2_DIR_STRUC.name_len] |
mov edi, EXT2_filename |
lea esi, [ebx + EXT2_DIR_STRUC.name] |
call utf8toansi_str |
mov ecx, edi |
sub ecx, EXT2_filename ;кол-во байт в получившейся строке |
call utf8toansi_str |
mov ecx, edi |
sub ecx, EXT2_filename ;кол-во байт в получившейся строке |
mov edi, EXT2_filename |
mov esi, [esp] |
mov edi, EXT2_filename |
mov esi, [esp] |
@@: |
jecxz .test_find |
dec ecx |
jecxz .test_find |
dec ecx |
lodsb |
call char_toupper |
lodsb |
call char_toupper |
mov ah, [edi] |
inc edi |
xchg al, ah |
call char_toupper |
cmp al, ah |
je @B |
mov ah, [edi] |
inc edi |
xchg al, ah |
call char_toupper |
cmp al, ah |
je @B |
@@: ;не подошло |
pop esi |
pop esi |
.next_rec: |
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] |
add ebx, eax ;к след. записи |
cmp ebx, edx ;проверим конец ли |
jb .start_rec |
jmp .ret |
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] |
add ebx, eax ;к след. записи |
cmp ebx, edx ;проверим конец ли |
jb .start_rec |
jmp .ret |
.test_find: |
cmp byte [esi], 0 |
je .find ;нашли конец |
cmp byte [esi], '/' |
jne @B |
jne @B |
inc esi |
.find: |
pop eax ;удаляем из стека сохраненое значение |
pop eax ;удаляем из стека сохраненое значение |
.ret: |
pop edi edx ecx eax |
pop edi edx ecx eax |
ret |
;---------------------------------------------------------------- |
480,7 → 480,7 |
xor eax, eax |
mov edi, edx |
mov ecx, 32/4 |
rep stosd ; fill header zero |
rep stosd ; fill header zero |
pop edi ; edi = число блоков для чтения |
push edx ebx |
510,31 → 510,31 |
mov ecx, [ecx] ; ecx = first wanted (flags ommited) |
.find_wanted_start: |
jecxz .find_wanted_end |
jecxz .find_wanted_end |
.find_wanted_cycle: |
cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
jz @F |
inc [EXT2_files_in_folder] |
dec ecx |
cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
jz @F |
inc [EXT2_files_in_folder] |
dec ecx |
@@: |
movzx ebx, [eax+EXT2_DIR_STRUC.rec_len] |
movzx ebx, [eax+EXT2_DIR_STRUC.rec_len] |
cmp ebx, 12 ; минимальная длина записи |
jb .end_error |
test ebx, 0x3 ; длина записи должна делиться на 4 |
jnz .end_error |
cmp ebx, 12 ; минимальная длина записи |
jb .end_error |
test ebx, 0x3 ; длина записи должна делиться на 4 |
jnz .end_error |
add eax, ebx ; к следующей записи |
cmp eax, [EXT2_end_block] ; проверяем "конец" |
jb .find_wanted_start |
add eax, ebx ; к следующей записи |
cmp eax, [EXT2_end_block] ; проверяем "конец" |
jb .find_wanted_start |
push .find_wanted_start |
.end_block: ;вылетили из цикла |
.end_block: ;вылетили из цикла |
mov ebx, [ext2_data.count_block_in_block] |
sub [EXT2_counter_blocks], ebx |
jbe .end_dir |
jbe .end_dir |
inc esi ;получаем новый блок |
inc esi ;получаем новый блок |
push ecx |
mov ecx, esi |
call ext2_get_inode_block |
545,99 → 545,99 |
mov eax, ebx |
add ebx, [ext2_data.block_size] |
mov [EXT2_end_block], ebx |
ret ; опять в цикл |
ret ; опять в цикл |
.wanted_end: |
loop .find_wanted_cycle ; ecx = -1 |
loop .find_wanted_cycle ; ecx = -1 |
.find_wanted_end: |
mov ecx, edi |
.wanted_start: ; ищем first_wanted+count |
jecxz .wanted_end |
cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
jz .empty_rec |
inc [EXT2_files_in_folder] |
inc [EXT2_read_in_folder] |
jecxz .wanted_end |
cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
jz .empty_rec |
inc [EXT2_files_in_folder] |
inc [EXT2_read_in_folder] |
mov edi, edx |
push eax ecx |
xor eax, eax |
mov ecx, 40 / 4 |
rep stosd |
pop ecx eax |
mov edi, edx |
push eax ecx |
xor eax, eax |
mov ecx, 40 / 4 |
rep stosd |
pop ecx eax |
push eax esi edx ;получим inode |
mov eax, [eax + EXT2_DIR_STRUC.inode] |
mov ebx, [ext2_data.ext2_temp_inode] |
call ext2_get_inode |
push eax esi edx ;получим inode |
mov eax, [eax + EXT2_DIR_STRUC.inode] |
mov ebx, [ext2_data.ext2_temp_inode] |
call ext2_get_inode |
lea edi, [edx + 8] |
lea edi, [edx + 8] |
mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] ; переведем время в ntfs формат |
xor edx, edx |
add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] ; переведем время в ntfs формат |
xor edx, edx |
add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
mov eax, [ebx + EXT2_INODE_STRUC.i_atime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
mov eax, [ebx + EXT2_INODE_STRUC.i_atime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
mov eax, [ebx + EXT2_INODE_STRUC.i_mtime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
mov eax, [ebx + EXT2_INODE_STRUC.i_mtime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
pop edx ; пока достаем только буфер |
test [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; для папки размер |
jnz @F ; не возвращаем |
pop edx ; пока достаем только буфер |
test [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; для папки размер |
jnz @F ; не возвращаем |
mov eax, [ebx + EXT2_INODE_STRUC.i_size] ;low size |
stosd |
mov eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ;high size |
stosd |
xor dword [edx], FS_FT_DIR |
mov eax, [ebx + EXT2_INODE_STRUC.i_size] ;low size |
stosd |
mov eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ;high size |
stosd |
xor dword [edx], FS_FT_DIR |
@@: |
xor dword [edx], FS_FT_DIR |
pop esi eax |
xor dword [edx], FS_FT_DIR |
pop esi eax |
or dword [edx+4], FS_FT_ASCII ; symbol type in name |
or dword [edx+4], FS_FT_ASCII ; symbol type in name |
;теперь скопируем имя, сконвертировав из UTF-8 в CP866 |
push eax ecx esi |
movzx ecx, [eax + EXT2_DIR_STRUC.name_len] |
lea edi, [edx + 40] |
lea esi, [eax + EXT2_DIR_STRUC.name] |
call utf8toansi_str |
pop esi ecx eax |
and byte [edi], 0 |
push eax ecx esi |
movzx ecx, [eax + EXT2_DIR_STRUC.name_len] |
lea edi, [edx + 40] |
lea esi, [eax + EXT2_DIR_STRUC.name] |
call utf8toansi_str |
pop esi ecx eax |
and byte [edi], 0 |
cmp byte [edx + 40], '.' |
jne @F |
or dword [edx], FS_FT_HIDDEN |
cmp byte [edx + 40], '.' |
jne @F |
or dword [edx], FS_FT_HIDDEN |
@@: |
add edx, 40 + 264 ; go to next record |
dec ecx ; если запись пустая ecx не надо уменьшать |
add edx, 40 + 264 ; go to next record |
dec ecx ; если запись пустая ecx не надо уменьшать |
.empty_rec: |
movzx ebx, [eax + EXT2_DIR_STRUC.rec_len] |
cmp ebx, 12 ; минимальная длина записи |
jb .end_error |
test ebx, 0x3 ; длина записи должна делиться на 4 |
jnz .end_error |
movzx ebx, [eax + EXT2_DIR_STRUC.rec_len] |
cmp ebx, 12 ; минимальная длина записи |
jb .end_error |
test ebx, 0x3 ; длина записи должна делиться на 4 |
jnz .end_error |
add eax, ebx |
cmp eax, [EXT2_end_block] |
jb .wanted_start |
add eax, ebx |
cmp eax, [EXT2_end_block] |
jb .wanted_start |
push .wanted_start ; дошли до конца очередного блока |
jmp .end_block |
.end_dir: |
pop eax ; мусор (адрес возврата в цикл) |
pop eax ; мусор (адрес возврата в цикл) |
.end_error: |
pop edx |
mov ebx, [EXT2_read_in_folder] |
648,17 → 648,17 |
mov [edx+8], ecx |
lea edi, [edx + 12] |
mov ecx, 20 / 4 |
rep stosd |
rep stosd |
ret |
;====================== end ext2_HdReadFolder |
utf8toansi_str: |
; convert UTF-8 string to ASCII-string (codepage 866) |
; in: ecx=length source, esi->source, edi->buffer |
; convert UTF-8 string to ASCII-string (codepage 866) |
; in: ecx=length source, esi->source, edi->buffer |
; destroys: eax,esi,edi |
jecxz .ret |
.start: |
lodsw |
cmp al, 0x80 |
cmp al, 0x80 |
jb .ascii |
xchg al, ah ; big-endian |
667,10 → 667,10 |
cmp ax, 0xd191 |
jz .yo2 |
cmp ax, 0xd090 |
jb .unk |
cmp ax, 0xd180 |
jb .rus1 |
cmp ax, 0xd190 |
jb .unk |
cmp ax, 0xd180 |
jb .rus1 |
cmp ax, 0xd190 |
jb .rus2 |
.unk: |
mov al, '_' |
700,19 → 700,19 |
.ret: |
ret |
;---------------------------------------------------------------- |
; |
; ext2_HdRead - read hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;---------------------------------------------------------------- |
; |
; ext2_HdRead - read hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ext2_HdRead: |
cmp byte [esi], 0 |
797,7 → 797,7 |
add ebx, edx |
neg edx |
add edx,[ext2_data.block_size] ;block_size - стартовый байт = сколько байт 1-го блока |
add edx, [ext2_data.block_size] ;block_size - стартовый байт = сколько байт 1-го блока |
cmp ecx, edx |
jbe .only_one_block |
806,7 → 806,7 |
mov ecx, edx |
mov esi, ebx |
rep movsb ;кусок 1-го блока |
rep movsb ;кусок 1-го блока |
jmp @F |
.zero_start: |
818,7 → 818,7 |
div [ext2_data.block_size] ;кол-во байт в последнем блоке (остаток) в edx |
mov edi, eax ;кол-во целых блоков в edi |
@@: |
test edi, edi |
test edi, edi |
jz .finish_block |
inc [EXT2_counter_blocks] |
mov ecx, [EXT2_counter_blocks] |
848,7 → 848,7 |
.only_one_block: |
mov esi, ebx |
rep movsb ;кусок last блока |
rep movsb ;кусок last блока |
.end_read: |
pop ebx |
cmp [EXT2_files_in_folder], 0 |
887,7 → 887,7 |
cmp eax, esi ;нашли имя? |
jz .next_block_folder |
cmp byte [esi],0 |
cmp byte [esi], 0 |
jz .get_inode_ret |
cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR |
934,7 → 934,7 |
xor eax, eax |
mov edi, edx |
mov ecx, 40/4 |
rep stosd ; fill zero |
rep stosd ; fill zero |
cmp byte [ebx], '.' |
jnz @F |
942,7 → 942,7 |
@@: |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
jnz @F |
jnz @F |
mov eax, [ebp + EXT2_INODE_STRUC.i_size] ;low size |
mov ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl] ;high size |
mov dword [edx+32], eax |
982,14 → 982,14 |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ext2_HdCreateFolder - create new folder |
; |
; esi points to filename |
; |
; ret eax = 0 ok read or other = errormsg |
; |
;---------------------------------------------------------------- |
; |
; ext2_HdCreateFolder - create new folder |
; |
; esi points to filename |
; |
; ret eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
cmp byte [esi], 0 |
jz .not_found |
1031,7 → 1031,7 |
dec ecx ;выкинули '/' из имени ролителя |
mov esi, ebx |
mov edi, EXT2_parent_name |
rep movsb |
rep movsb |
; esi - pointer to last slash |
mov edx, esi |
1064,7 → 1064,7 |
push ebp |
mov ecx, [ext2_data.sb] |
cmp [ecx + EXT2_SB_STRUC.free_inodes_count],0 ; есть ли место для inode |
cmp [ecx + EXT2_SB_STRUC.free_inodes_count], 0 ; есть ли место для inode |
jz .no_space |
mov eax, [ecx + EXT2_SB_STRUC.free_block_count] |
sub eax, [ecx + EXT2_SB_STRUC.r_block_count] |
1103,7 → 1103,7 |
shr ecx, 5 ;делим на 32 |
mov ebp, ecx ; всего сохраним в ebp |
or eax, -1 ; ищем первый свободный inode (!= -1) |
repne scasd |
repne scasd |
jnz .test_last_dword ;нашли или нет |
mov eax, [esi-4] |
1152,7 → 1152,7 |
mov ecx, [ext2_data.inode_size] |
shr ecx, 2 |
xor eax, eax |
rep stosd |
rep stosd |
mov edi, edx |
mov eax, EXT2_S_IFDIR or EXT2_777_MODE |
1226,8 → 1226,8 |
shr ecx, 5 ;делим на 32 |
mov ebp, ecx ;всего сохраним в ebp |
or eax, -1 ;ищем первый свободный inode (!= -1) |
repe scasd |
jz .test_last_dword ;нашли или нет |
repe scasd |
jz .test_last_dword ;нашли или нет |
mov eax, [edi-4] |
sub ebp, ecx |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fs/fat12.inc |
---|
1,2272 → 1,2272 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; FAT12.INC ;; |
;; (C) 2005 Mario79, License: GPL ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
n_sector dd 0 ; temporary save for sector value |
flp_status dd 0 |
clust_tmp_flp dd 0 ; used by analyze_directory and analyze_directory_to_write |
path_pointer_flp dd 0 |
pointer_file_name_flp dd 0 |
save_root_flag db 0 |
save_flag db 0 |
root_read db 0 ; 0-necessary to load root, 1-not to load root |
flp_fat db 0 ; 0-necessary to load fat, 1-not to load fat |
flp_number db 0 ; 1- Floppy A, 2-Floppy B |
old_track db 0 ; old value track |
flp_label rb 15 ; Label and ID of inserted floppy disk |
reserve_flp: |
cli |
cmp [flp_status],0 |
je reserve_flp_ok |
sti |
call change_task |
jmp reserve_flp |
reserve_flp_ok: |
push eax |
mov eax,[CURRENT_TASK] |
shl eax,5 |
mov eax,[eax+CURRENT_TASK+TASKDATA.pid] |
mov [flp_status],eax |
pop eax |
sti |
ret |
floppy_fileread: |
;---------------------------------------------------------------- |
; |
; fileread - sys floppy |
; |
; eax points to filename 11 chars - for root directory |
; ebx first wanted block ; 1+ ; if 0 then set to 1 |
; ecx number of blocks to read ; 1+ ; if 0 then set to 1 |
; edx mem location to return data |
; esi length of filename 12*X |
; edi pointer to path /fd/1/...... - for all files in nested directories |
; |
; ret ebx = size or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; 10 = access denied |
;-------------------------------------------------------------- |
mov [save_flag],0 |
mov [path_pointer_flp],edi |
test esi,esi ; return ramdisk root |
jnz fr_noroot_1 |
cmp ebx,224/16 |
jbe fr_do_1 |
mov eax,5 |
xor ebx,ebx |
mov [flp_status],ebx |
ret |
fr_do_1: |
push ebx ecx edx |
call read_flp_root |
pop edx ecx ebx |
cmp [FDC_Status],0 |
jne fdc_status_error_1 |
mov edi,edx |
dec ebx |
shl ebx,9 |
mov esi,FLOPPY_BUFF |
add esi,ebx |
shl ecx,9 |
cld |
rep movsb |
xor eax,eax |
xor ebx,ebx |
; mov eax,0 ; ok read |
; mov ebx,0 |
mov [flp_status],eax |
ret |
fdc_status_error_1: |
xor eax,eax |
mov [flp_status],eax |
mov eax,10 |
or ebx,-1 |
ret |
fr_noroot_1: |
sub esp,32 |
call expand_filename |
frfloppy_1: |
test ebx,ebx |
jnz frfl5_1 |
mov ebx,1 |
frfl5_1: |
test ecx,ecx |
jnz frfl6_1 |
mov ecx,1 |
frfl6_1: |
dec ebx |
push eax |
push eax ebx ecx edx esi edi |
call read_flp_fat |
cmp [FDC_Status],0 |
jne fdc_status_error_3_1 |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],1 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
call SeekTrack |
mov dh,14 |
l.20_1: |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne fdc_status_error_3_1 |
mov dl,16 |
mov edi,FDD_BUFF |
inc [FDD_Sector] |
l.21_1: |
mov esi,eax ;Name of file we want |
mov ecx,11 |
cld |
rep cmpsb ;Found the file? |
je fifound_1 ;Yes |
add ecx,21 |
add edi, ecx ;Advance to next entry |
dec dl |
test dl,dl |
jnz l.21_1 |
dec dh |
test dh,dh |
jnz l.20_1 |
fdc_status_error_3: |
mov eax,5 ; file not found ? |
or ebx,-1 |
add esp,32+28 |
mov [flp_status],0 |
ret |
fdc_status_error_3_2: |
cmp [FDC_Status],0 |
je fdc_status_error_3 |
fdc_status_error_3_1: |
add esp,32+28 |
jmp fdc_status_error_1 |
fifound_1: |
mov eax,[path_pointer_flp] |
cmp [eax+36],byte 0 |
je fifound_2 |
add edi,0xf |
mov eax,[edi] |
and eax,65535 |
mov ebx,[path_pointer_flp] |
add ebx,36 |
call get_cluster_of_a_path_flp |
jc fdc_status_error_3_2 |
mov ebx,[ebx-11+28] ;file size |
mov [esp+20],ebx |
mov [esp+24],ebx |
jmp fifound_3 |
fifound_2: |
mov ebx,[edi-11+28] ;file size |
mov [esp+20],ebx |
mov [esp+24],ebx |
add edi,0xf |
mov eax,[edi] |
fifound_3: |
and eax,65535 |
mov [n_sector],eax ;eax=cluster |
frnew_1: |
add eax,31 ;bootsector+2*fat+filenames |
cmp [esp+16],dword 0 ; wanted cluster ? |
jne frfl7_1 |
call read_chs_sector |
cmp [FDC_Status],0 |
jne fdc_status_error_5 |
mov edi,[esp+8] |
call give_back_application_data_1 |
add [esp+8],dword 512 |
dec dword [esp+12] ; last wanted cluster ? |
cmp [esp+12],dword 0 |
je frnoread_1 |
jmp frfl8_1 |
frfl7_1: |
dec dword [esp+16] |
frfl8_1: |
mov edi,[n_sector] |
shl edi,1 ;find next cluster from FAT |
add edi,FLOPPY_FAT |
mov eax,[edi] |
and eax,4095 |
mov edi,eax |
mov [n_sector],edi |
cmp edi,4095 ;eof - cluster |
jz frnoread2_1 |
cmp [esp+24],dword 512 ;eof - size |
jb frnoread_1 |
sub [esp+24],dword 512 |
jmp frnew_1 |
read_chs_sector: |
call calculate_chs |
call ReadSectWithRetr |
ret |
frnoread2_1: |
cmp [esp+16],dword 0 ; eof without read ? |
je frnoread_1 |
mov [fdc_irq_func],fdc_null |
pop edi esi edx ecx |
add esp,4 |
pop ebx ; ebx <- eax : size of file |
add esp,36 |
mov eax,6 ; end of file |
mov [flp_status],0 |
ret |
frnoread_1: |
pop edi esi edx ecx |
add esp,4 |
pop ebx ; ebx <- eax : size of file |
add esp,36 |
xor eax,eax |
mov [flp_status],eax |
ret |
fdc_status_error_5: |
pop edi esi edx ecx |
add esp,4 |
pop ebx ; ebx <- eax : size of file |
add esp,36 |
jmp fdc_status_error_1 |
read_flp_root: |
pusha |
call check_label |
cmp [FDC_Status],0 |
jne unnecessary_root_read |
cmp [root_read],1 |
je unnecessary_root_read |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],1 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
mov edi,FLOPPY_BUFF |
call SeekTrack |
read_flp_root_1: |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_root_read |
push edi |
call give_back_application_data_1 |
pop edi |
add edi,512 |
inc [FDD_Sector] |
cmp [FDD_Sector],16 |
jne read_flp_root_1 |
mov [root_read],1 |
unnecessary_root_read: |
popa |
ret |
read_flp_fat: |
pusha |
call check_label |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat |
cmp [flp_fat],1 |
je unnecessary_flp_fat |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],0 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
mov edi,FLOPPY_BUFF |
call SeekTrack |
read_flp_fat_1: |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat |
push edi |
call give_back_application_data_1 |
pop edi |
add edi,512 |
inc [FDD_Sector] |
cmp [FDD_Sector],19 |
jne read_flp_fat_1 |
mov [FDD_Sector],1 |
mov [FDD_Head],1 |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat |
call give_back_application_data_1 |
call calculatefatchain_flp |
mov [root_read],0 |
mov [flp_fat],1 |
unnecessary_flp_fat: |
popa |
ret |
calculatefatchain_flp: |
pushad |
mov esi,FLOPPY_BUFF |
mov edi,FLOPPY_FAT |
fcnew_1: |
mov eax,dword [esi] |
mov ebx,dword [esi+4] |
mov ecx,dword [esi+8] |
mov edx,ecx |
shr edx,4 ;8 ok |
shr dx,4 ;7 ok |
xor ch,ch |
shld ecx,ebx,20 ;6 ok |
shr cx,4 ;5 ok |
shld ebx,eax,12 |
and ebx,0x0fffffff ;4 ok |
shr bx,4 ;3 ok |
shl eax,4 |
and eax,0x0fffffff ;2 ok |
shr ax,4 ;1 ok |
mov dword [edi],eax |
add edi,4 |
mov dword [edi],ebx |
add edi,4 |
mov dword [edi],ecx |
add edi,4 |
mov dword [edi],edx |
add edi,4 |
add esi,12 |
cmp edi,FLOPPY_FAT+2856*2 ;2849 clusters |
jnz fcnew_1 |
popad |
ret |
check_label: |
pushad |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],0 ; Ñòîðîíà |
mov [FDD_Sector],1 ; Ñåêòîð |
call SetUserInterrupts |
call FDDMotorON |
call RecalibrateFDD |
cmp [FDC_Status],0 |
jne fdc_status_error |
call SeekTrack |
cmp [FDC_Status],0 |
jne fdc_status_error |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne fdc_status_error |
mov esi,flp_label |
mov edi,FDD_BUFF+39 |
mov ecx,15 |
cld |
rep cmpsb |
je same_label |
mov [root_read],0 |
mov [flp_fat],0 |
same_label: |
mov esi,FDD_BUFF+39 |
mov edi,flp_label |
mov ecx,15 |
cld |
rep movsb |
popad |
ret |
fdc_status_error: |
popad |
ret |
save_flp_root: |
pusha |
call check_label |
cmp [FDC_Status],0 |
jne unnecessary_root_save |
cmp [root_read],0 |
je unnecessary_root_save |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],1 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
mov esi,FLOPPY_BUFF |
call SeekTrack |
save_flp_root_1: |
push esi |
call take_data_from_application_1 |
pop esi |
add esi,512 |
call WriteSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_root_save |
inc [FDD_Sector] |
cmp [FDD_Sector],16 |
jne save_flp_root_1 |
unnecessary_root_save: |
mov [fdc_irq_func],fdc_null |
popa |
ret |
save_flp_fat: |
pusha |
call check_label |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat_save |
cmp [flp_fat],0 |
je unnecessary_flp_fat_save |
call restorefatchain_flp |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],0 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
mov esi,FLOPPY_BUFF |
call SeekTrack |
save_flp_fat_1: |
push esi |
call take_data_from_application_1 |
pop esi |
add esi,512 |
call WriteSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat_save |
inc [FDD_Sector] |
cmp [FDD_Sector],19 |
jne save_flp_fat_1 |
mov [FDD_Sector],1 |
mov [FDD_Head],1 |
call take_data_from_application_1 |
call WriteSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat_save |
mov [root_read],0 |
unnecessary_flp_fat_save: |
mov [fdc_irq_func],fdc_null |
popa |
ret |
restorefatchain_flp: ; restore fat chain |
pushad |
mov esi,FLOPPY_FAT |
mov edi,FLOPPY_BUFF |
fcnew2_1: |
mov eax,dword [esi] |
mov ebx,dword [esi+4] |
shl ax,4 |
shl eax,4 |
shl bx,4 |
shr ebx,4 |
shrd eax,ebx,8 |
shr ebx,8 |
mov dword [edi],eax |
add edi,4 |
mov word [edi],bx |
add edi,2 |
add esi,8 |
cmp edi,FLOPPY_BUFF+0x1200 ;4274 bytes - all used FAT |
jb fcnew2_1 |
mov esi,FLOPPY_BUFF ; duplicate fat chain |
mov edi,FLOPPY_BUFF+0x1200 |
mov ecx,0x1200/4 |
cld |
rep movsd |
popad |
ret |
save_chs_sector: |
call calculate_chs |
call WriteSectWithRetr |
ret |
calculate_chs: |
mov bl,[FDD_Track] |
mov [old_track],bl |
mov ebx,18 |
xor edx,edx |
div ebx |
inc edx |
mov [FDD_Sector],dl |
xor edx,edx |
mov ebx,2 |
div ebx |
mov [FDD_Track],al |
mov [FDD_Head],0 |
test edx,edx |
jz no_head_2 |
inc [FDD_Head] |
no_head_2: |
mov dl,[old_track] |
cmp dl,[FDD_Track] |
je no_seek_track_1 |
call SeekTrack |
no_seek_track_1: |
ret |
get_cluster_of_a_path_flp: |
;--------------------------------------------------------- |
; input : EBX = pointer to a path string |
; (example: the path "/files/data/document" become |
; "files......data.......document...0" |
; '.' = space char |
; '0' = char(0) (ASCII=0) !!! ) |
; output : if (CARRY=1) -> ERROR in the PATH |
; if (CARRY=0) -> EAX=cluster |
;--------------------------------------------------------- |
push edx |
mov edx,ebx |
search_end_of_path_flp: |
cmp [save_flag],0 |
jne search_end_of_path_flp_1 |
cmp byte [edx],0 |
je found_end_of_path_flp |
jmp search_end_of_path_flp_2 |
search_end_of_path_flp_1: |
cmp byte [edx+12],0 |
je found_end_of_path_flp |
search_end_of_path_flp_2: |
inc edx ; '/' |
call analyze_directory_flp |
jc directory_not_found_flp |
mov eax,[ebx+20-2] ; read the HIGH 16bit cluster field |
mov ax,[ebx+26] ; read the LOW 16bit cluster field |
and eax,0xfff ;[fatMASK] |
add edx,11 ; 8+3 (name+extension) |
jmp search_end_of_path_flp |
found_end_of_path_flp: |
inc edx |
mov [pointer_file_name_flp],edx |
pop edx |
clc ; no errors |
ret |
directory_not_found_flp: |
pop edx |
stc ; errors occour |
ret |
analyze_directory_flp: |
;-------------------------------- |
; input : EAX = first cluster of the directory |
; EBX = pointer to filename |
; output : IF CARRY=0 EAX = sector where th file is found |
; EBX = pointer in buffer |
; [buffer .. buffer+511] |
; ECX,EDX,EDI,EDI not changed |
; IF CARRY=1 |
;-------------------------------- |
push ebx ;[esp+16] |
push ecx |
push edx |
push esi |
push edi |
adr56_flp: |
mov [clust_tmp_flp],eax |
add eax,31 |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status],0 |
jne not_found_file_analyze_flp |
mov ecx,512/32 |
mov ebx,FDD_BUFF |
adr1_analyze_flp: |
mov esi,edx ;[esp+16] |
mov edi,ebx |
cld |
push ecx |
mov ecx,11 |
rep cmpsb |
pop ecx |
je found_file_analyze_flp |
add ebx,32 |
loop adr1_analyze_flp |
mov eax,[clust_tmp_flp] |
shl eax,1 ;find next cluster from FAT |
add eax,FLOPPY_FAT |
mov eax,[eax] |
and eax,4095 |
cmp eax,0x0ff8 |
jb adr56_flp |
not_found_file_analyze_flp: |
pop edi |
pop esi |
pop edx |
pop ecx |
add esp,4 |
stc ;file not found |
ret |
found_file_analyze_flp: |
pop edi |
pop esi |
pop edx |
pop ecx |
add esp,4 |
clc ;file found |
ret |
; \begin{diamond} |
fat_find_lfn: |
; in: esi->name |
; [esp+4] = next |
; [esp+8] = first |
; [esp+C]... - possibly parameters for first and next |
; out: CF=1 - file not found |
; else CF=0, esi->next name component, edi->direntry |
pusha |
lea eax, [esp+0Ch+20h] |
call dword [eax-4] |
jc .reterr |
sub esp, 262*2 ; reserve place for LFN |
mov ebp, esp |
push 0 ; for fat_get_name: read ASCII name |
.l1: |
call fat_get_name |
jc .l2 |
call fat_compare_name |
jz .found |
.l2: |
lea eax, [esp+0Ch+20h+262*2+4] |
call dword [eax-8] |
jnc .l1 |
add esp, 262*2+4 |
.reterr: |
stc |
popa |
ret |
.found: |
add esp, 262*2+4 |
; if this is LFN entry, advance to true entry |
cmp byte [edi+11], 0xF |
jnz @f |
lea eax, [esp+0Ch+20h] |
call dword [eax-8] |
jc .reterr |
@@: |
add esp, 8 ; CF=0 |
push esi |
push edi |
popa |
ret |
uglobal |
; this is for delete support |
fd_prev_sector dd ? |
fd_prev_prev_sector dd ? |
endg |
flp_root_next: |
cmp edi, OS_BASE+0xD200-0x20 |
jae @f |
add edi, 0x20 |
ret ; CF=0 |
@@: |
; read next sector |
inc dword [eax] |
cmp dword [eax], 14 |
jae flp_root_first.readerr |
push [fd_prev_sector] |
pop [fd_prev_prev_sector] |
push eax |
mov eax, [eax] |
add eax, 19-1 |
mov [fd_prev_sector], eax |
pop eax |
flp_root_first: |
mov eax, [eax] |
pusha |
add eax, 19 |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .readerr |
mov edi, FDD_BUFF |
ret ; CF=0 |
.readerr: |
stc |
ret |
flp_rootmem_first: |
mov edi, FLOPPY_BUFF |
clc |
ret |
flp_rootmem_next: |
add edi, 0x20 |
cmp edi, FLOPPY_BUFF+14*0x200 |
cmc |
flp_rootmem_next_write: |
flp_rootmem_begin_write: |
flp_rootmem_end_write: |
ret |
flp_rootmem_extend_dir: |
stc |
ret |
flp_notroot_next: |
cmp edi, OS_BASE+0xD200-0x20 |
jae flp_notroot_next_sector |
add edi, 0x20 |
ret ; CF=0 |
flp_notroot_next_sector: |
push ecx |
mov ecx, [eax] |
push [fd_prev_sector] |
pop [fd_prev_prev_sector] |
add ecx, 31 |
mov [fd_prev_sector], ecx |
mov ecx, [(ecx-31)*2+FLOPPY_FAT] |
and ecx, 0xFFF |
cmp ecx, 2849 |
jae flp_notroot_first.err2 |
mov [eax], ecx |
pop ecx |
flp_notroot_first: |
mov eax, [eax] |
cmp eax, 2 |
jb .err |
cmp eax, 2849 |
jae .err |
pusha |
add eax, 31 |
call read_chs_sector |
popa |
mov edi, FDD_BUFF |
cmp [FDC_Status], 0 |
jnz .err |
ret ; CF=0 |
.err2: |
pop ecx |
.err: |
stc |
ret |
flp_notroot_begin_write: |
pusha |
mov eax, [eax] |
add eax, 31 |
call read_chs_sector |
popa |
ret |
flp_notroot_end_write: |
pusha |
mov eax, [eax] |
add eax, 31 |
call save_chs_sector |
popa |
ret |
flp_notroot_next_write: |
cmp edi, OS_BASE+0xD200 |
jae @f |
ret |
@@: |
call flp_notroot_end_write |
jmp flp_notroot_next_sector |
flp_notroot_extend_dir: |
; find free cluster in FAT |
pusha |
xor eax, eax |
mov edi, FLOPPY_FAT |
mov ecx, 2849 |
repnz scasw |
jnz .notfound |
mov word [edi-2], 0xFFF ; mark as last cluster |
sub edi, FLOPPY_FAT |
shr edi, 1 |
dec edi |
mov eax, [esp+28] |
mov ecx, [eax] |
mov [FLOPPY_FAT+ecx*2], di |
mov [eax], edi |
xor eax, eax |
mov edi, FDD_BUFF |
mov ecx, 128 |
rep stosd |
popa |
call flp_notroot_end_write |
mov edi, FDD_BUFF |
clc |
ret |
.notfound: |
popa |
stc |
ret |
fd_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and edi->direntry, eax=directory cluster (0 for root) |
push esi edi |
push 0 |
push flp_root_first |
push flp_root_next |
.loop: |
call fat_find_lfn |
jc .notfound |
cmp byte [esi], 0 |
jz .found |
.continue: |
test byte [edi+11], 10h |
jz .notfound |
movzx eax, word [edi+26] ; cluster |
mov [esp+8], eax |
mov dword [esp+4], flp_notroot_first |
mov dword [esp], flp_notroot_next |
jmp .loop |
.notfound: |
add esp, 12 |
pop edi esi |
stc |
ret |
.found: |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .continue |
@@: |
mov eax, [esp+8] |
add eax, 31 |
cmp dword [esp], flp_root_next |
jnz @f |
add eax, -31+19 |
@@: |
add esp, 16 ; CF=0 |
pop esi |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyRead - LFN variant for reading floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppyRead: |
call read_flp_fat |
cmp byte [esi], 0 |
jnz @f |
or ebx, -1 |
mov eax, 10 ; access denied |
ret |
@@: |
push edi |
call fd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, 5 ; file not found |
ret |
.found: |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
xor ebx, ebx |
.reteof: |
mov eax, 6 ; EOF |
pop edi |
ret |
@@: |
mov ebx, [ebx] |
.l1: |
push ecx edx |
push 0 |
mov eax, [edi+28] |
sub eax, ebx |
jb .eof |
cmp eax, ecx |
jae @f |
mov ecx, eax |
mov byte [esp], 6 ; EOF |
@@: |
movzx edi, word [edi+26] |
.new: |
jecxz .done |
test edi, edi |
jz .eof |
cmp edi, 0xFF8 |
jae .eof |
sub ebx, 512 |
jae .skip |
lea eax, [edi+31] |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .err |
lea eax, [FDD_BUFF+ebx+512] |
neg ebx |
push ecx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
mov ebx, edx |
call memmove |
add edx, ecx |
sub [esp], ecx |
pop ecx |
xor ebx, ebx |
.skip: |
movzx edi, word [edi*2+FLOPPY_FAT] |
jmp .new |
.done: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
ret |
.eof: |
mov ebx, edx |
pop eax edx ecx |
jmp .reteof |
.err: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
mov al, 11 |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyReadFolder - LFN variant for reading floppy folders |
; |
; esi points to filename |
; ebx pointer to structure: 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppyReadFolder: |
call read_flp_fat |
push edi |
cmp byte [esi], 0 |
jz .root |
call fd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 ; do not allow read files |
jnz .found_dir |
pop edi |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
movzx eax, word [edi+26] |
add eax, 31 |
push 0 |
jmp .doit |
.root: |
mov eax, 19 |
push 14 |
.doit: |
push ecx ebp |
sub esp, 262*2 ; reserve space for LFN |
mov ebp, esp |
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names |
mov ebx, [ebx] |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
pop ecx eax |
mov byte [edx], 1 ; version |
mov esi, edi ; esi points to BDFE |
.main_loop: |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .error |
mov edi, FDD_BUFF |
push eax |
.l1: |
call fat_get_name |
jc .l2 |
cmp byte [edi+11], 0xF |
jnz .do_bdfe |
add edi, 0x20 |
cmp edi, OS_BASE+0xD200 |
jb .do_bdfe |
pop eax |
inc eax |
dec byte [esp+262*2+12] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+FLOPPY_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+12], 0 |
@@: |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .error |
mov edi, FDD_BUFF |
push eax |
.do_bdfe: |
inc dword [edx+8] ; new file found |
dec ebx |
jns .l2 |
dec ecx |
js .l2 |
inc dword [edx+4] ; new file block copied |
call fat_entry_to_bdfe |
.l2: |
add edi, 0x20 |
cmp edi, OS_BASE+0xD200 |
jb .l1 |
pop eax |
inc eax |
dec byte [esp+262*2+12] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+FLOPPY_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+12], 0 |
@@: |
jmp .main_loop |
.error: |
add esp, 262*2+4 |
pop ebp ecx edi edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.done: |
add esp, 262*2+4 |
pop ebp |
mov ebx, [edx+4] |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
pop ecx edi edi |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyRewrite - LFN variant for writing sys floppy |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
fsfrfe2: |
popad |
fsfrfe: |
mov eax, 11 |
xor ebx, ebx |
ret |
fs_FloppyCreateFolder: |
mov al, 1 |
jmp fs_FloppyRewrite.common |
fs_FloppyRewrite: |
xor eax, eax |
.common: |
cmp byte [esi], 0 |
jz @b |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz fsfrfe |
pushad |
xor edi, edi |
push esi |
test ebp, ebp |
jz @f |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
lea edi, [esi-1] |
jmp @b |
@@: |
pop esi |
test edi, edi |
jnz .noroot |
test ebp, ebp |
jnz .hasebp |
call read_flp_root |
cmp [FDC_Status], 0 |
jnz fsfrfe2 |
push flp_rootmem_extend_dir |
push flp_rootmem_end_write |
push flp_rootmem_next_write |
push flp_rootmem_begin_write |
xor ebp, ebp |
push ebp |
push flp_rootmem_first |
push flp_rootmem_next |
jmp .common1 |
.hasebp: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [ebp], 0 |
jz .ret1 |
push ebp |
xor ebp, ebp |
call fd_find_lfn |
pop esi |
jc .notfound0 |
jmp .common0 |
.noroot: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [edi+1], 0 |
jz .ret1 |
; check existence |
mov byte [edi], 0 |
push edi |
call fd_find_lfn |
pop esi |
mov byte [esi], '/' |
jnc @f |
.notfound0: |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
@@: |
inc esi |
.common0: |
test byte [edi+11], 0x10 ; must be directory |
mov eax, ERROR_ACCESS_DENIED |
jz .ret1 |
movzx ebp, word [edi+26] ; ebp=cluster |
mov eax, ERROR_FAT_TABLE |
cmp ebp, 2 |
jb .ret1 |
cmp ebp, 2849 |
jae .ret1 |
push flp_notroot_extend_dir |
push flp_notroot_end_write |
push flp_notroot_next_write |
push flp_notroot_begin_write |
push ebp |
push flp_notroot_first |
push flp_notroot_next |
.common1: |
call fat_find_lfn |
jc .notfound |
; found |
test byte [edi+11], 10h |
jz .exists_file |
; found directory; if we are creating directory, return OK, |
; if we are creating file, say "access denied" |
add esp, 28 |
popad |
test al, al |
mov eax, ERROR_ACCESS_DENIED |
jz @f |
mov al, 0 |
@@: |
xor ebx, ebx |
ret |
.exists_file: |
; found file; if we are creating directory, return "access denied", |
; if we are creating file, delete existing file and continue |
cmp byte [esp+28+28], 0 |
jz @f |
add esp, 28 |
popad |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
@@: |
; delete FAT chain |
push edi |
xor eax, eax |
mov dword [edi+28], eax ; zero size |
xchg ax, word [edi+26] ; start cluster |
test eax, eax |
jz .done1 |
@@: |
cmp eax, 0xFF8 |
jae .done1 |
lea edi, [FLOPPY_FAT + eax*2] ; position in FAT |
xor eax, eax |
xchg ax, [edi] |
jmp @b |
.done1: |
pop edi |
call get_time_for_file |
mov [edi+22], ax |
call get_date_for_file |
mov [edi+24], ax |
mov [edi+18], ax |
or byte [edi+11], 20h ; set 'archive' attribute |
jmp .doit |
.notfound: |
; file is not found; generate short name |
call fat_name_is_legal |
jc @f |
add esp, 28 |
popad |
mov eax, ERROR_FILE_NOT_FOUND |
xor ebx, ebx |
ret |
@@: |
sub esp, 12 |
mov edi, esp |
call fat_gen_short_name |
.test_short_name_loop: |
push esi edi ecx |
mov esi, edi |
lea eax, [esp+12+12+8] |
mov [eax], ebp |
call dword [eax-4] |
jc .found |
.test_short_name_entry: |
cmp byte [edi+11], 0xF |
jz .test_short_name_cont |
mov ecx, 11 |
push esi edi |
repz cmpsb |
pop edi esi |
jz .short_name_found |
.test_short_name_cont: |
lea eax, [esp+12+12+8] |
call dword [eax-8] |
jnc .test_short_name_entry |
jmp .found |
.short_name_found: |
pop ecx edi esi |
call fat_next_short_name |
jnc .test_short_name_loop |
.disk_full: |
add esp, 12+28 |
popa |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.found: |
pop ecx edi esi |
; now find space in directory |
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' |
mov al, '~' |
push ecx edi |
mov ecx, 8 |
repnz scasb |
push 1 |
pop eax ; 1 entry |
jnz .notilde |
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total |
xor eax, eax |
@@: |
cmp byte [esi], 0 |
jz @f |
inc esi |
inc eax |
jmp @b |
@@: |
sub esi, eax |
add eax, 12+13 |
mov ecx, 13 |
push edx |
cdq |
div ecx |
pop edx |
.notilde: |
push -1 |
push -1 |
; find <eax> successive entries in directory |
xor ecx, ecx |
push eax |
lea eax, [esp+12+8+12+8] |
mov [eax], ebp |
call dword [eax-4] |
pop eax |
jnc .scan_dir |
.fsfrfe3: |
add esp, 8+8+12+28 |
popad |
mov eax, 11 |
xor ebx, ebx |
ret |
.scan_dir: |
cmp byte [edi], 0 |
jz .free |
cmp byte [edi], 0xE5 |
jz .free |
xor ecx, ecx |
.scan_cont: |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax-8] |
pop eax |
jnc .scan_dir |
cmp [FDC_Status], 0 |
jnz .fsfrfe3 |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax+16] ; extend directory |
pop eax |
jnc .scan_dir |
add esp, 8+8+12+28 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.free: |
test ecx, ecx |
jnz @f |
mov [esp], edi |
mov ecx, [esp+8+8+12+8] |
mov [esp+4], ecx |
xor ecx, ecx |
@@: |
inc ecx |
cmp ecx, eax |
jb .scan_cont |
; found! |
; calculate name checksum |
push esi ecx |
mov esi, [esp+8+8] |
mov ecx, 11 |
xor eax, eax |
@@: |
ror al, 1 |
add al, [esi] |
inc esi |
loop @b |
pop ecx esi |
pop edi |
pop dword [esp+8+12+8] |
; edi points to first entry in free chunk |
dec ecx |
jz .nolfn |
push esi |
push eax |
lea eax, [esp+8+8+12+8] |
call dword [eax+4] ; begin write |
mov al, 40h |
.writelfn: |
or al, cl |
mov esi, [esp+4] |
push ecx |
dec ecx |
imul ecx, 13 |
add esi, ecx |
stosb |
mov cl, 5 |
call fs_RamdiskRewrite.read_symbols |
mov ax, 0xF |
stosw |
mov al, [esp+4] |
stosb |
mov cl, 6 |
call fs_RamdiskRewrite.read_symbols |
xor eax, eax |
stosw |
mov cl, 2 |
call fs_RamdiskRewrite.read_symbols |
pop ecx |
lea eax, [esp+8+8+12+8] |
call dword [eax+8] ; next write |
xor eax, eax |
loop .writelfn |
pop eax |
pop esi |
; lea eax, [esp+8+12+8] |
; call dword [eax+12] ; end write |
.nolfn: |
xchg esi, [esp] |
mov ecx, 11 |
rep movsb |
mov word [edi], 20h ; attributes |
sub edi, 11 |
pop esi ecx |
add esp, 12 |
mov byte [edi+13], 0 ; tenths of a second at file creation time |
call get_time_for_file |
mov [edi+14], ax ; creation time |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+16], ax ; creation date |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
and word [edi+20], 0 ; high word of cluster |
and word [edi+26], 0 ; low word of cluster - to be filled |
and dword [edi+28], 0 ; file size - to be filled |
cmp byte [esp+28+28], 0 |
jz .doit |
; create directory |
mov byte [edi+11], 10h ; attributes: folder |
mov ecx, 32*2 |
mov edx, edi |
.doit: |
lea eax, [esp+8] |
call dword [eax+12] ; flush directory |
push ecx |
push edi |
push 0 |
mov esi, edx |
test ecx, ecx |
jz .done |
mov ecx, 2849 |
mov edi, FLOPPY_FAT |
push 0 ; first cluster |
.write_loop: |
; allocate new cluster |
xor eax, eax |
repnz scasw |
mov al, ERROR_DISK_FULL |
jnz .ret |
dec edi |
dec edi |
mov eax, edi |
sub eax, FLOPPY_FAT |
shr eax, 1 ; eax = cluster |
mov word [edi], 0xFFF ; mark as last cluster |
xchg edi, [esp+4] |
cmp dword [esp], 0 |
jz .first |
stosw |
jmp @f |
.first: |
mov [esp], eax |
@@: |
mov edi, [esp+4] |
inc ecx |
; write data |
push ecx edi |
mov ecx, 512 |
cmp dword [esp+20], ecx |
jae @f |
mov ecx, [esp+20] |
@@: |
mov edi, FDD_BUFF |
cmp byte [esp+24+28+28], 0 |
jnz .writedir |
push ecx |
rep movsb |
pop ecx |
.writedircont: |
push ecx |
sub ecx, 512 |
neg ecx |
push eax |
xor eax, eax |
rep stosb |
pop eax |
add eax, 31 |
pusha |
call save_chs_sector |
popa |
pop ecx |
cmp [FDC_Status], 0 |
jnz .diskerr |
sub [esp+20], ecx |
pop edi ecx |
jnz .write_loop |
.done: |
xor eax, eax |
.ret: |
pop ebx edi edi ecx |
mov [esp+28+28], eax |
lea eax, [esp+8] |
call dword [eax+4] |
mov [edi+26], bx |
mov ebx, esi |
sub ebx, edx |
mov [edi+28], ebx |
call dword [eax+12] |
mov [esp+28+16], ebx |
test ebp, ebp |
jnz @f |
call save_flp_root |
@@: |
add esp, 28 |
cmp [FDC_Status], 0 |
jnz .err3 |
call save_flp_fat |
cmp [FDC_Status], 0 |
jnz .err3 |
popa |
ret |
.err3: |
popa |
mov al, 11 |
xor ebx, ebx |
ret |
.diskerr: |
sub esi, ecx |
mov eax, 11 |
pop edi ecx |
jmp .ret |
.writedir: |
push ecx |
mov ecx, 32/4 |
push ecx esi |
rep movsd |
pop esi ecx |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov word [edi-32+26], ax |
push esi |
rep movsd |
pop esi |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov ecx, [esp+28+8] |
mov word [edi-32+26], cx |
pop ecx |
jmp .writedircont |
;---------------------------------------------------------------- |
; |
; fs_FloppyWrite - LFN variant for writing to floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
push ERROR_ACCESS_DENIED |
fs_FloppyWrite.ret0: |
pop eax |
xor ebx, ebx |
ret |
fs_FloppyWrite.ret11: |
push 11 |
jmp fs_FloppyWrite.ret0 |
fs_FloppyWrite: |
cmp byte [esi], 0 |
jz @b |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz .ret11 |
pushad |
call fd_find_lfn |
jnc .found |
popad |
push ERROR_FILE_NOT_FOUND |
jmp .ret0 |
.found: |
; FAT does not support files larger than 4GB |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
.eof: |
popad |
push ERROR_END_OF_FILE |
jmp .ret0 |
@@: |
mov ebx, [ebx] |
.l1: |
; now edi points to direntry, ebx=start byte to write, |
; ecx=number of bytes to write, edx=data pointer |
; extend file if needed |
add ecx, ebx |
jc .eof ; FAT does not support files larger than 4GB |
push eax ; save directory cluster |
push 0 ; return value=0 |
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
push dword [edi+28] ; save current file size |
cmp ecx, [edi+28] |
jbe .length_ok |
cmp ecx, ebx |
jz .length_ok |
call floppy_extend_file |
jnc .length_ok |
mov [esp+4], eax |
; floppy_extend_file can return two error codes: FAT table error or disk full. |
; First case is fatal error, in second case we may write some data |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax |
pop eax |
mov [esp+4+28], eax |
pop eax |
popad |
xor ebx, ebx |
ret |
.disk_full: |
; correct number of bytes to write |
mov ecx, [edi+28] |
cmp ecx, ebx |
ja .length_ok |
.ret: |
pop eax |
pop eax |
mov [esp+4+28], eax ; eax=return value |
pop eax |
sub edx, [esp+20] |
mov [esp+16], edx ; ebx=number of written bytes |
popad |
ret |
.length_ok: |
; save FAT & directory |
; note that directory must be saved first because save_flp_fat uses buffer at 0xD000 |
mov esi, [edi+28] |
movzx edi, word [edi+26] ; starting cluster |
mov eax, [esp+8] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err |
call save_flp_fat |
cmp [FDC_Status], 0 |
jz @f |
.device_err: |
mov byte [esp+4], 11 |
jmp .ret |
@@: |
; now ebx=start pos, ecx=end pos, both lie inside file |
sub ecx, ebx |
jz .ret |
call SetUserInterrupts |
.write_loop: |
; skip unmodified sectors |
cmp dword [esp], 0x200 |
jb .modify |
sub ebx, 0x200 |
jae .skip |
add ebx, 0x200 |
.modify: |
lea eax, [edi+31] ; current sector |
; get length of data in current sector |
push ecx |
sub ebx, 0x200 |
jb .hasdata |
neg ebx |
xor ecx, ecx |
jmp @f |
.hasdata: |
neg ebx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
; load sector if needed |
cmp dword [esp+4], 0 ; we don't need to read uninitialized data |
jz .noread |
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten |
jz .noread |
cmp ecx, esi ; (same for the last sector) |
jz .noread |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jz @f |
.device_err2: |
pop ecx |
jmp .device_err |
@@: |
.noread: |
; zero uninitialized data if file was extended (because floppy_extend_file does not this) |
push eax ecx edi |
xor eax, eax |
mov ecx, 0x200 |
sub ecx, [esp+4+12] |
jbe @f |
mov edi, FDD_BUFF |
add edi, [esp+4+12] |
rep stosb |
@@: |
; zero uninitialized data in the last sector |
mov ecx, 0x200 |
sub ecx, esi |
jbe @f |
mov edi, FDD_BUFF |
add edi, esi |
rep stosb |
@@: |
pop edi ecx eax |
; copy new data |
push eax |
mov eax, edx |
neg ebx |
jecxz @f |
add ebx, FDD_BUFF+0x200 |
call memmove |
xor ebx, ebx |
@@: |
pop eax |
; save sector |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err2 |
add edx, ecx |
sub [esp], ecx |
pop ecx |
jz .done |
.skip: |
.next_cluster: |
movzx edi, word [edi*2+FLOPPY_FAT] |
sub esi, 0x200 |
jae @f |
xor esi, esi |
@@: |
sub dword [esp], 0x200 |
jae .write_loop |
and dword [esp], 0 |
jmp .write_loop |
.done: |
mov [fdc_irq_func], fdc_null |
jmp .ret |
floppy_extend_file.zero_size: |
xor eax, eax |
jmp floppy_extend_file.start_extend |
; extends file on floppy to given size (new data area is undefined) |
; in: edi->direntry, ecx=new size |
; out: CF=0 => OK, eax=0 |
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL) |
floppy_extend_file: |
push ecx |
; find the last cluster of file |
movzx eax, word [edi+26] ; first cluster |
mov ecx, [edi+28] |
jecxz .zero_size |
@@: |
sub ecx, 0x200 |
jbe @f |
mov eax, [eax*2+FLOPPY_FAT] |
and eax, 0xFFF |
jz .fat_err |
cmp eax, 0xFF8 |
jb @b |
.fat_err: |
pop ecx |
push ERROR_FAT_TABLE |
pop eax |
stc |
ret |
@@: |
push eax |
mov eax, [eax*2+FLOPPY_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
pop eax |
jb .fat_err |
; set length to full number of sectors |
sub [edi+28], ecx |
.start_extend: |
pop ecx |
; now do extend |
push edx esi |
mov esi, FLOPPY_FAT+2*2 ; start scan from cluster 2 |
mov edx, 2847 ; number of clusters to scan |
.extend_loop: |
cmp [edi+28], ecx |
jae .extend_done |
; add new sector |
push ecx |
push edi |
.scan: |
mov ecx, edx |
mov edi, esi |
jecxz .disk_full |
push eax |
xor eax, eax |
repnz scasw |
pop eax |
jnz .disk_full |
mov word [edi-2], 0xFFF |
mov esi, edi |
mov edx, ecx |
sub edi, FLOPPY_FAT |
shr edi, 1 |
dec edi ; now edi=new cluster |
test eax, eax |
jz .first_cluster |
mov [FLOPPY_FAT+eax*2], di |
jmp @f |
.first_cluster: |
pop eax ; eax->direntry |
push eax |
mov [eax+26], di |
@@: |
mov eax, edi ; eax=new cluster |
pop edi ; edi->direntry |
pop ecx ; ecx=required size |
add dword [edi+28], 0x200 |
jmp .extend_loop |
.extend_done: |
mov [edi+28], ecx |
pop esi edx |
xor eax, eax ; CF=0 |
ret |
.disk_full: |
pop edi ecx |
pop esi edx |
stc |
push ERROR_DISK_FULL |
pop eax |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppySetFileEnd - set end of file on floppy |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppySetFileEnd: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz ret11 |
cmp byte [esi], 0 |
jnz @f |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .ret |
@@: |
push edi |
call fd_find_lfn |
jnc @f |
pop edi |
push ERROR_FILE_NOT_FOUND |
.ret: |
pop eax |
jmp .doret |
@@: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
pop edi |
jmp .access_denied |
@@: |
; file size must not exceed 4 Gb |
cmp dword [ebx+4], 0 |
jz @f |
pop edi |
push ERROR_END_OF_FILE |
jmp .ret |
@@: |
push eax |
; set file modification date/time to current |
call fat_update_datetime |
mov eax, [ebx] |
cmp eax, [edi+28] |
jb .truncate |
ja .expand |
pop eax |
pushad |
call save_chs_sector |
popad |
pop edi |
xor eax, eax |
cmp [FDC_Status], 0 |
jz @f |
mov al, 11 |
@@: |
.doret: |
mov [fdc_irq_func], fdc_null |
ret |
.expand: |
push ecx |
push dword [edi+28] ; save old size |
mov ecx, eax |
call floppy_extend_file |
push eax ; return code |
jnc .expand_ok |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax ecx ecx edi edi |
jmp .doret |
.device_err: |
pop eax |
.device_err2: |
pop ecx ecx eax edi |
push 11 |
jmp .ret |
.disk_full: |
.expand_ok: |
; save directory & FAT |
mov eax, [edi+28] |
xchg eax, [esp+12] |
movzx edi, word [edi+26] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err |
call save_flp_fat |
cmp [FDC_Status], 0 |
jnz .device_err |
call SetUserInterrupts |
; now zero new data |
; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code |
.zero_loop: |
sub dword [esp+4], 0x200 |
jae .next_cluster |
cmp dword [esp+4], -0x200 |
jz .noread |
lea eax, [edi+31] |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .err_next |
.noread: |
mov ecx, [esp+4] |
neg ecx |
push edi |
mov edi, FDD_BUFF+0x200 |
add edi, [esp+8] |
xor eax, eax |
mov [esp+8], eax |
rep stosb |
pop edi |
lea eax, [edi+31] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jz .next_cluster |
.err_next: |
mov byte [esp], 11 |
.next_cluster: |
sub dword [esp+12], 0x200 |
jbe .expand_done |
movzx edi, word [FLOPPY_FAT+edi*2] |
jmp .zero_loop |
.expand_done: |
pop eax ecx ecx edi edi |
jmp .doret |
.truncate: |
mov [edi+28], eax |
push ecx |
movzx ecx, word [edi+26] |
test eax, eax |
jz .zero_size |
; find new last sector |
@@: |
sub eax, 0x200 |
jbe @f |
movzx ecx, word [FLOPPY_FAT+ecx*2] |
jmp @b |
@@: |
; we will zero data at the end of last sector - remember it |
push ecx |
; terminate FAT chain |
lea ecx, [FLOPPY_FAT+ecx+ecx] |
push dword [ecx] |
mov word [ecx], 0xFFF |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.zero_size: |
and word [edi+26], 0 |
push 0 |
.delete: |
; delete FAT chain starting with ecx |
; mark all clusters as free |
cmp ecx, 0xFF8 |
jae .deleted |
lea ecx, [FLOPPY_FAT+ecx+ecx] |
push dword [ecx] |
and word [ecx], 0 |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.deleted: |
mov edi, [edi+28] |
; save directory & FAT |
mov eax, [esp+8] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err2 |
call save_flp_fat |
cmp [FDC_Status], 0 |
jnz .device_err2 |
; zero last sector, ignore errors |
pop eax |
add eax, 31 |
and edi, 0x1FF |
jz .truncate_done |
call SetUserInterrupts |
pusha |
call read_chs_sector |
popa |
add edi, FDD_BUFF |
mov ecx, FDD_BUFF+0x200 |
sub ecx, edi |
push eax |
xor eax, eax |
rep stosb |
pop eax |
pusha |
call save_chs_sector |
popa |
.truncate_done: |
pop ecx eax edi |
xor eax, eax |
jmp .doret |
fs_FloppyGetFileInfo: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz ret11 |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call fd_find_lfn |
jmp fs_GetFileInfo_finish |
ret11: |
mov eax, 11 |
ret |
fs_FloppySetFileInfo: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz ret11 |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call fd_find_lfn |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
push eax |
call bdfe_to_fat_entry |
pop eax |
pusha |
call save_chs_sector |
popa |
pop edi |
xor eax, eax |
cmp [FDC_Status], al |
jz @f |
mov al, 11 |
@@: |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyDelete - delete file or empty folder from floppy |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppyDelete: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jz @f |
push 11 |
jmp .pop_ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
; cannot delete root! |
.access_denied: |
push ERROR_ACCESS_DENIED |
.pop_ret: |
pop eax |
ret |
@@: |
and [fd_prev_sector], 0 |
and [fd_prev_prev_sector], 0 |
push edi |
call fd_find_lfn |
jnc .found |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .pop_ret |
.found: |
cmp dword [edi], '. ' |
jz .access_denied2 |
cmp dword [edi], '.. ' |
jz .access_denied2 |
test byte [edi+11], 10h |
jz .dodel |
; we can delete only empty folders! |
push eax |
movzx eax, word [edi+26] |
push ebx |
pusha |
add eax, 31 |
call read_chs_sector |
popa |
mov ebx, FDD_BUFF + 2*0x20 |
.checkempty: |
cmp byte [ebx], 0 |
jz .empty |
cmp byte [ebx], 0xE5 |
jnz .notempty |
add ebx, 0x20 |
cmp ebx, FDD_BUFF + 0x200 |
jb .checkempty |
movzx eax, word [FLOPPY_FAT + eax*2] |
pusha |
add eax, 31 |
call read_chs_sector |
popa |
mov ebx, FDD_BUFF |
jmp .checkempty |
.notempty: |
pop ebx |
pop eax |
.access_denied2: |
pop edi |
jmp .access_denied |
.empty: |
pop ebx |
pop eax |
pusha |
call read_chs_sector |
popa |
.dodel: |
push eax |
movzx eax, word [edi+26] |
xchg eax, [esp] |
; delete folder entry |
mov byte [edi], 0xE5 |
; delete LFN (if present) |
.lfndel: |
cmp edi, FDD_BUFF |
ja @f |
cmp [fd_prev_sector], 0 |
jz .lfndone |
push [fd_prev_sector] |
push [fd_prev_prev_sector] |
pop [fd_prev_sector] |
and [fd_prev_prev_sector], 0 |
pusha |
call save_chs_sector |
popa |
pop eax |
pusha |
call read_chs_sector |
popa |
mov edi, FDD_BUFF+0x200 |
@@: |
sub edi, 0x20 |
cmp byte [edi], 0xE5 |
jz .lfndone |
cmp byte [edi+11], 0xF |
jnz .lfndone |
mov byte [edi], 0xE5 |
jmp .lfndel |
.lfndone: |
pusha |
call save_chs_sector |
popa |
; delete FAT chain |
pop eax |
test eax, eax |
jz .done |
@@: |
lea eax, [FLOPPY_FAT + eax*2] |
push dword [eax] |
and word [eax], 0 |
pop eax |
and eax, 0xFFF |
jnz @b |
.done: |
call save_flp_fat |
pop edi |
xor eax, eax |
ret |
; \end{diamond} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; FAT12.INC ;; |
;; (C) 2005 Mario79, License: GPL ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
n_sector dd 0 ; temporary save for sector value |
flp_status dd 0 |
clust_tmp_flp dd 0 ; used by analyze_directory and analyze_directory_to_write |
path_pointer_flp dd 0 |
pointer_file_name_flp dd 0 |
save_root_flag db 0 |
save_flag db 0 |
root_read db 0 ; 0-necessary to load root, 1-not to load root |
flp_fat db 0 ; 0-necessary to load fat, 1-not to load fat |
flp_number db 0 ; 1- Floppy A, 2-Floppy B |
old_track db 0 ; old value track |
flp_label rb 15 ; Label and ID of inserted floppy disk |
reserve_flp: |
cli |
cmp [flp_status], 0 |
je reserve_flp_ok |
sti |
call change_task |
jmp reserve_flp |
reserve_flp_ok: |
push eax |
mov eax, [CURRENT_TASK] |
shl eax, 5 |
mov eax, [eax+CURRENT_TASK+TASKDATA.pid] |
mov [flp_status], eax |
pop eax |
sti |
ret |
floppy_fileread: |
;---------------------------------------------------------------- |
; |
; fileread - sys floppy |
; |
; eax points to filename 11 chars - for root directory |
; ebx first wanted block ; 1+ ; if 0 then set to 1 |
; ecx number of blocks to read ; 1+ ; if 0 then set to 1 |
; edx mem location to return data |
; esi length of filename 12*X |
; edi pointer to path /fd/1/...... - for all files in nested directories |
; |
; ret ebx = size or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; 10 = access denied |
;-------------------------------------------------------------- |
mov [save_flag], 0 |
mov [path_pointer_flp], edi |
test esi, esi ; return ramdisk root |
jnz fr_noroot_1 |
cmp ebx, 224/16 |
jbe fr_do_1 |
mov eax, 5 |
xor ebx, ebx |
mov [flp_status], ebx |
ret |
fr_do_1: |
push ebx ecx edx |
call read_flp_root |
pop edx ecx ebx |
cmp [FDC_Status], 0 |
jne fdc_status_error_1 |
mov edi, edx |
dec ebx |
shl ebx, 9 |
mov esi, FLOPPY_BUFF |
add esi, ebx |
shl ecx, 9 |
cld |
rep movsb |
xor eax, eax |
xor ebx, ebx |
; mov eax,0 ; ok read |
; mov ebx,0 |
mov [flp_status], eax |
ret |
fdc_status_error_1: |
xor eax, eax |
mov [flp_status], eax |
mov eax, 10 |
or ebx, -1 |
ret |
fr_noroot_1: |
sub esp, 32 |
call expand_filename |
frfloppy_1: |
test ebx, ebx |
jnz frfl5_1 |
mov ebx, 1 |
frfl5_1: |
test ecx, ecx |
jnz frfl6_1 |
mov ecx, 1 |
frfl6_1: |
dec ebx |
push eax |
push eax ebx ecx edx esi edi |
call read_flp_fat |
cmp [FDC_Status], 0 |
jne fdc_status_error_3_1 |
mov [FDD_Track], 0; Öèëèíäð |
mov [FDD_Head], 1; Ñòîðîíà |
mov [FDD_Sector], 2; Ñåêòîð |
call SeekTrack |
mov dh, 14 |
l.20_1: |
call ReadSectWithRetr |
cmp [FDC_Status], 0 |
jne fdc_status_error_3_1 |
mov dl, 16 |
mov edi, FDD_BUFF |
inc [FDD_Sector] |
l.21_1: |
mov esi, eax ;Name of file we want |
mov ecx, 11 |
cld |
rep cmpsb ;Found the file? |
je fifound_1 ;Yes |
add ecx, 21 |
add edi, ecx ;Advance to next entry |
dec dl |
test dl, dl |
jnz l.21_1 |
dec dh |
test dh, dh |
jnz l.20_1 |
fdc_status_error_3: |
mov eax, 5 ; file not found ? |
or ebx, -1 |
add esp, 32+28 |
mov [flp_status], 0 |
ret |
fdc_status_error_3_2: |
cmp [FDC_Status], 0 |
je fdc_status_error_3 |
fdc_status_error_3_1: |
add esp, 32+28 |
jmp fdc_status_error_1 |
fifound_1: |
mov eax, [path_pointer_flp] |
cmp [eax+36], byte 0 |
je fifound_2 |
add edi, 0xf |
mov eax, [edi] |
and eax, 65535 |
mov ebx, [path_pointer_flp] |
add ebx, 36 |
call get_cluster_of_a_path_flp |
jc fdc_status_error_3_2 |
mov ebx, [ebx-11+28] ;file size |
mov [esp+20], ebx |
mov [esp+24], ebx |
jmp fifound_3 |
fifound_2: |
mov ebx, [edi-11+28] ;file size |
mov [esp+20], ebx |
mov [esp+24], ebx |
add edi, 0xf |
mov eax, [edi] |
fifound_3: |
and eax, 65535 |
mov [n_sector], eax ;eax=cluster |
frnew_1: |
add eax, 31 ;bootsector+2*fat+filenames |
cmp [esp+16], dword 0; wanted cluster ? |
jne frfl7_1 |
call read_chs_sector |
cmp [FDC_Status], 0 |
jne fdc_status_error_5 |
mov edi, [esp+8] |
call give_back_application_data_1 |
add [esp+8], dword 512 |
dec dword [esp+12] ; last wanted cluster ? |
cmp [esp+12], dword 0 |
je frnoread_1 |
jmp frfl8_1 |
frfl7_1: |
dec dword [esp+16] |
frfl8_1: |
mov edi, [n_sector] |
shl edi, 1 ;find next cluster from FAT |
add edi, FLOPPY_FAT |
mov eax, [edi] |
and eax, 4095 |
mov edi, eax |
mov [n_sector], edi |
cmp edi, 4095 ;eof - cluster |
jz frnoread2_1 |
cmp [esp+24], dword 512;eof - size |
jb frnoread_1 |
sub [esp+24], dword 512 |
jmp frnew_1 |
read_chs_sector: |
call calculate_chs |
call ReadSectWithRetr |
ret |
frnoread2_1: |
cmp [esp+16], dword 0; eof without read ? |
je frnoread_1 |
mov [fdc_irq_func], fdc_null |
pop edi esi edx ecx |
add esp, 4 |
pop ebx; ebx <- eax : size of file |
add esp, 36 |
mov eax, 6; end of file |
mov [flp_status], 0 |
ret |
frnoread_1: |
pop edi esi edx ecx |
add esp, 4 |
pop ebx; ebx <- eax : size of file |
add esp, 36 |
xor eax, eax |
mov [flp_status], eax |
ret |
fdc_status_error_5: |
pop edi esi edx ecx |
add esp, 4 |
pop ebx; ebx <- eax : size of file |
add esp, 36 |
jmp fdc_status_error_1 |
read_flp_root: |
pusha |
call check_label |
cmp [FDC_Status], 0 |
jne unnecessary_root_read |
cmp [root_read], 1 |
je unnecessary_root_read |
mov [FDD_Track], 0; Öèëèíäð |
mov [FDD_Head], 1; Ñòîðîíà |
mov [FDD_Sector], 2; Ñåêòîð |
mov edi, FLOPPY_BUFF |
call SeekTrack |
read_flp_root_1: |
call ReadSectWithRetr |
cmp [FDC_Status], 0 |
jne unnecessary_root_read |
push edi |
call give_back_application_data_1 |
pop edi |
add edi, 512 |
inc [FDD_Sector] |
cmp [FDD_Sector], 16 |
jne read_flp_root_1 |
mov [root_read], 1 |
unnecessary_root_read: |
popa |
ret |
read_flp_fat: |
pusha |
call check_label |
cmp [FDC_Status], 0 |
jne unnecessary_flp_fat |
cmp [flp_fat], 1 |
je unnecessary_flp_fat |
mov [FDD_Track], 0; Öèëèíäð |
mov [FDD_Head], 0; Ñòîðîíà |
mov [FDD_Sector], 2; Ñåêòîð |
mov edi, FLOPPY_BUFF |
call SeekTrack |
read_flp_fat_1: |
call ReadSectWithRetr |
cmp [FDC_Status], 0 |
jne unnecessary_flp_fat |
push edi |
call give_back_application_data_1 |
pop edi |
add edi, 512 |
inc [FDD_Sector] |
cmp [FDD_Sector], 19 |
jne read_flp_fat_1 |
mov [FDD_Sector], 1 |
mov [FDD_Head], 1 |
call ReadSectWithRetr |
cmp [FDC_Status], 0 |
jne unnecessary_flp_fat |
call give_back_application_data_1 |
call calculatefatchain_flp |
mov [root_read], 0 |
mov [flp_fat], 1 |
unnecessary_flp_fat: |
popa |
ret |
calculatefatchain_flp: |
pushad |
mov esi, FLOPPY_BUFF |
mov edi, FLOPPY_FAT |
fcnew_1: |
mov eax, dword [esi] |
mov ebx, dword [esi+4] |
mov ecx, dword [esi+8] |
mov edx, ecx |
shr edx, 4;8 ok |
shr dx, 4;7 ok |
xor ch, ch |
shld ecx, ebx, 20;6 ok |
shr cx, 4;5 ok |
shld ebx, eax, 12 |
and ebx, 0x0fffffff;4 ok |
shr bx, 4;3 ok |
shl eax, 4 |
and eax, 0x0fffffff;2 ok |
shr ax, 4;1 ok |
mov dword [edi], eax |
add edi, 4 |
mov dword [edi], ebx |
add edi, 4 |
mov dword [edi], ecx |
add edi, 4 |
mov dword [edi], edx |
add edi, 4 |
add esi, 12 |
cmp edi, FLOPPY_FAT+2856*2;2849 clusters |
jnz fcnew_1 |
popad |
ret |
check_label: |
pushad |
mov [FDD_Track], 0; Öèëèíäð |
mov [FDD_Head], 0; Ñòîðîíà |
mov [FDD_Sector], 1; Ñåêòîð |
call SetUserInterrupts |
call FDDMotorON |
call RecalibrateFDD |
cmp [FDC_Status], 0 |
jne fdc_status_error |
call SeekTrack |
cmp [FDC_Status], 0 |
jne fdc_status_error |
call ReadSectWithRetr |
cmp [FDC_Status], 0 |
jne fdc_status_error |
mov esi, flp_label |
mov edi, FDD_BUFF+39 |
mov ecx, 15 |
cld |
rep cmpsb |
je same_label |
mov [root_read], 0 |
mov [flp_fat], 0 |
same_label: |
mov esi, FDD_BUFF+39 |
mov edi, flp_label |
mov ecx, 15 |
cld |
rep movsb |
popad |
ret |
fdc_status_error: |
popad |
ret |
save_flp_root: |
pusha |
call check_label |
cmp [FDC_Status], 0 |
jne unnecessary_root_save |
cmp [root_read], 0 |
je unnecessary_root_save |
mov [FDD_Track], 0; Öèëèíäð |
mov [FDD_Head], 1; Ñòîðîíà |
mov [FDD_Sector], 2; Ñåêòîð |
mov esi, FLOPPY_BUFF |
call SeekTrack |
save_flp_root_1: |
push esi |
call take_data_from_application_1 |
pop esi |
add esi, 512 |
call WriteSectWithRetr |
cmp [FDC_Status], 0 |
jne unnecessary_root_save |
inc [FDD_Sector] |
cmp [FDD_Sector], 16 |
jne save_flp_root_1 |
unnecessary_root_save: |
mov [fdc_irq_func], fdc_null |
popa |
ret |
save_flp_fat: |
pusha |
call check_label |
cmp [FDC_Status], 0 |
jne unnecessary_flp_fat_save |
cmp [flp_fat], 0 |
je unnecessary_flp_fat_save |
call restorefatchain_flp |
mov [FDD_Track], 0; Öèëèíäð |
mov [FDD_Head], 0; Ñòîðîíà |
mov [FDD_Sector], 2; Ñåêòîð |
mov esi, FLOPPY_BUFF |
call SeekTrack |
save_flp_fat_1: |
push esi |
call take_data_from_application_1 |
pop esi |
add esi, 512 |
call WriteSectWithRetr |
cmp [FDC_Status], 0 |
jne unnecessary_flp_fat_save |
inc [FDD_Sector] |
cmp [FDD_Sector], 19 |
jne save_flp_fat_1 |
mov [FDD_Sector], 1 |
mov [FDD_Head], 1 |
call take_data_from_application_1 |
call WriteSectWithRetr |
cmp [FDC_Status], 0 |
jne unnecessary_flp_fat_save |
mov [root_read], 0 |
unnecessary_flp_fat_save: |
mov [fdc_irq_func], fdc_null |
popa |
ret |
restorefatchain_flp: ; restore fat chain |
pushad |
mov esi, FLOPPY_FAT |
mov edi, FLOPPY_BUFF |
fcnew2_1: |
mov eax, dword [esi] |
mov ebx, dword [esi+4] |
shl ax, 4 |
shl eax, 4 |
shl bx, 4 |
shr ebx, 4 |
shrd eax, ebx, 8 |
shr ebx, 8 |
mov dword [edi], eax |
add edi, 4 |
mov word [edi], bx |
add edi, 2 |
add esi, 8 |
cmp edi, FLOPPY_BUFF+0x1200;4274 bytes - all used FAT |
jb fcnew2_1 |
mov esi, FLOPPY_BUFF ; duplicate fat chain |
mov edi, FLOPPY_BUFF+0x1200 |
mov ecx, 0x1200/4 |
cld |
rep movsd |
popad |
ret |
save_chs_sector: |
call calculate_chs |
call WriteSectWithRetr |
ret |
calculate_chs: |
mov bl, [FDD_Track] |
mov [old_track], bl |
mov ebx, 18 |
xor edx, edx |
div ebx |
inc edx |
mov [FDD_Sector], dl |
xor edx, edx |
mov ebx, 2 |
div ebx |
mov [FDD_Track], al |
mov [FDD_Head], 0 |
test edx, edx |
jz no_head_2 |
inc [FDD_Head] |
no_head_2: |
mov dl, [old_track] |
cmp dl, [FDD_Track] |
je no_seek_track_1 |
call SeekTrack |
no_seek_track_1: |
ret |
get_cluster_of_a_path_flp: |
;--------------------------------------------------------- |
; input : EBX = pointer to a path string |
; (example: the path "/files/data/document" become |
; "files......data.......document...0" |
; '.' = space char |
; '0' = char(0) (ASCII=0) !!! ) |
; output : if (CARRY=1) -> ERROR in the PATH |
; if (CARRY=0) -> EAX=cluster |
;--------------------------------------------------------- |
push edx |
mov edx, ebx |
search_end_of_path_flp: |
cmp [save_flag], 0 |
jne search_end_of_path_flp_1 |
cmp byte [edx], 0 |
je found_end_of_path_flp |
jmp search_end_of_path_flp_2 |
search_end_of_path_flp_1: |
cmp byte [edx+12], 0 |
je found_end_of_path_flp |
search_end_of_path_flp_2: |
inc edx; '/' |
call analyze_directory_flp |
jc directory_not_found_flp |
mov eax, [ebx+20-2] ; read the HIGH 16bit cluster field |
mov ax, [ebx+26] ; read the LOW 16bit cluster field |
and eax, 0xfff ;[fatMASK] |
add edx, 11 ; 8+3 (name+extension) |
jmp search_end_of_path_flp |
found_end_of_path_flp: |
inc edx |
mov [pointer_file_name_flp], edx |
pop edx |
clc ; no errors |
ret |
directory_not_found_flp: |
pop edx |
stc ; errors occour |
ret |
analyze_directory_flp: |
;-------------------------------- |
; input : EAX = first cluster of the directory |
; EBX = pointer to filename |
; output : IF CARRY=0 EAX = sector where th file is found |
; EBX = pointer in buffer |
; [buffer .. buffer+511] |
; ECX,EDX,EDI,EDI not changed |
; IF CARRY=1 |
;-------------------------------- |
push ebx;[esp+16] |
push ecx |
push edx |
push esi |
push edi |
adr56_flp: |
mov [clust_tmp_flp], eax |
add eax, 31 |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jne not_found_file_analyze_flp |
mov ecx, 512/32 |
mov ebx, FDD_BUFF |
adr1_analyze_flp: |
mov esi, edx;[esp+16] |
mov edi, ebx |
cld |
push ecx |
mov ecx, 11 |
rep cmpsb |
pop ecx |
je found_file_analyze_flp |
add ebx, 32 |
loop adr1_analyze_flp |
mov eax, [clust_tmp_flp] |
shl eax, 1 ;find next cluster from FAT |
add eax, FLOPPY_FAT |
mov eax, [eax] |
and eax, 4095 |
cmp eax, 0x0ff8 |
jb adr56_flp |
not_found_file_analyze_flp: |
pop edi |
pop esi |
pop edx |
pop ecx |
add esp, 4 |
stc ;file not found |
ret |
found_file_analyze_flp: |
pop edi |
pop esi |
pop edx |
pop ecx |
add esp, 4 |
clc ;file found |
ret |
; \begin{diamond} |
fat_find_lfn: |
; in: esi->name |
; [esp+4] = next |
; [esp+8] = first |
; [esp+C]... - possibly parameters for first and next |
; out: CF=1 - file not found |
; else CF=0, esi->next name component, edi->direntry |
pusha |
lea eax, [esp+0Ch+20h] |
call dword [eax-4] |
jc .reterr |
sub esp, 262*2 ; reserve place for LFN |
mov ebp, esp |
push 0 ; for fat_get_name: read ASCII name |
.l1: |
call fat_get_name |
jc .l2 |
call fat_compare_name |
jz .found |
.l2: |
lea eax, [esp+0Ch+20h+262*2+4] |
call dword [eax-8] |
jnc .l1 |
add esp, 262*2+4 |
.reterr: |
stc |
popa |
ret |
.found: |
add esp, 262*2+4 |
; if this is LFN entry, advance to true entry |
cmp byte [edi+11], 0xF |
jnz @f |
lea eax, [esp+0Ch+20h] |
call dword [eax-8] |
jc .reterr |
@@: |
add esp, 8 ; CF=0 |
push esi |
push edi |
popa |
ret |
uglobal |
; this is for delete support |
fd_prev_sector dd ? |
fd_prev_prev_sector dd ? |
endg |
flp_root_next: |
cmp edi, OS_BASE+0xD200-0x20 |
jae @f |
add edi, 0x20 |
ret ; CF=0 |
@@: |
; read next sector |
inc dword [eax] |
cmp dword [eax], 14 |
jae flp_root_first.readerr |
push [fd_prev_sector] |
pop [fd_prev_prev_sector] |
push eax |
mov eax, [eax] |
add eax, 19-1 |
mov [fd_prev_sector], eax |
pop eax |
flp_root_first: |
mov eax, [eax] |
pusha |
add eax, 19 |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .readerr |
mov edi, FDD_BUFF |
ret ; CF=0 |
.readerr: |
stc |
ret |
flp_rootmem_first: |
mov edi, FLOPPY_BUFF |
clc |
ret |
flp_rootmem_next: |
add edi, 0x20 |
cmp edi, FLOPPY_BUFF+14*0x200 |
cmc |
flp_rootmem_next_write: |
flp_rootmem_begin_write: |
flp_rootmem_end_write: |
ret |
flp_rootmem_extend_dir: |
stc |
ret |
flp_notroot_next: |
cmp edi, OS_BASE+0xD200-0x20 |
jae flp_notroot_next_sector |
add edi, 0x20 |
ret ; CF=0 |
flp_notroot_next_sector: |
push ecx |
mov ecx, [eax] |
push [fd_prev_sector] |
pop [fd_prev_prev_sector] |
add ecx, 31 |
mov [fd_prev_sector], ecx |
mov ecx, [(ecx-31)*2+FLOPPY_FAT] |
and ecx, 0xFFF |
cmp ecx, 2849 |
jae flp_notroot_first.err2 |
mov [eax], ecx |
pop ecx |
flp_notroot_first: |
mov eax, [eax] |
cmp eax, 2 |
jb .err |
cmp eax, 2849 |
jae .err |
pusha |
add eax, 31 |
call read_chs_sector |
popa |
mov edi, FDD_BUFF |
cmp [FDC_Status], 0 |
jnz .err |
ret ; CF=0 |
.err2: |
pop ecx |
.err: |
stc |
ret |
flp_notroot_begin_write: |
pusha |
mov eax, [eax] |
add eax, 31 |
call read_chs_sector |
popa |
ret |
flp_notroot_end_write: |
pusha |
mov eax, [eax] |
add eax, 31 |
call save_chs_sector |
popa |
ret |
flp_notroot_next_write: |
cmp edi, OS_BASE+0xD200 |
jae @f |
ret |
@@: |
call flp_notroot_end_write |
jmp flp_notroot_next_sector |
flp_notroot_extend_dir: |
; find free cluster in FAT |
pusha |
xor eax, eax |
mov edi, FLOPPY_FAT |
mov ecx, 2849 |
repnz scasw |
jnz .notfound |
mov word [edi-2], 0xFFF ; mark as last cluster |
sub edi, FLOPPY_FAT |
shr edi, 1 |
dec edi |
mov eax, [esp+28] |
mov ecx, [eax] |
mov [FLOPPY_FAT+ecx*2], di |
mov [eax], edi |
xor eax, eax |
mov edi, FDD_BUFF |
mov ecx, 128 |
rep stosd |
popa |
call flp_notroot_end_write |
mov edi, FDD_BUFF |
clc |
ret |
.notfound: |
popa |
stc |
ret |
fd_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and edi->direntry, eax=directory cluster (0 for root) |
push esi edi |
push 0 |
push flp_root_first |
push flp_root_next |
.loop: |
call fat_find_lfn |
jc .notfound |
cmp byte [esi], 0 |
jz .found |
.continue: |
test byte [edi+11], 10h |
jz .notfound |
movzx eax, word [edi+26] ; cluster |
mov [esp+8], eax |
mov dword [esp+4], flp_notroot_first |
mov dword [esp], flp_notroot_next |
jmp .loop |
.notfound: |
add esp, 12 |
pop edi esi |
stc |
ret |
.found: |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .continue |
@@: |
mov eax, [esp+8] |
add eax, 31 |
cmp dword [esp], flp_root_next |
jnz @f |
add eax, -31+19 |
@@: |
add esp, 16 ; CF=0 |
pop esi |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyRead - LFN variant for reading floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppyRead: |
call read_flp_fat |
cmp byte [esi], 0 |
jnz @f |
or ebx, -1 |
mov eax, 10 ; access denied |
ret |
@@: |
push edi |
call fd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, 5 ; file not found |
ret |
.found: |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
xor ebx, ebx |
.reteof: |
mov eax, 6 ; EOF |
pop edi |
ret |
@@: |
mov ebx, [ebx] |
.l1: |
push ecx edx |
push 0 |
mov eax, [edi+28] |
sub eax, ebx |
jb .eof |
cmp eax, ecx |
jae @f |
mov ecx, eax |
mov byte [esp], 6 ; EOF |
@@: |
movzx edi, word [edi+26] |
.new: |
jecxz .done |
test edi, edi |
jz .eof |
cmp edi, 0xFF8 |
jae .eof |
sub ebx, 512 |
jae .skip |
lea eax, [edi+31] |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .err |
lea eax, [FDD_BUFF+ebx+512] |
neg ebx |
push ecx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
mov ebx, edx |
call memmove |
add edx, ecx |
sub [esp], ecx |
pop ecx |
xor ebx, ebx |
.skip: |
movzx edi, word [edi*2+FLOPPY_FAT] |
jmp .new |
.done: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
ret |
.eof: |
mov ebx, edx |
pop eax edx ecx |
jmp .reteof |
.err: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
mov al, 11 |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyReadFolder - LFN variant for reading floppy folders |
; |
; esi points to filename |
; ebx pointer to structure: 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppyReadFolder: |
call read_flp_fat |
push edi |
cmp byte [esi], 0 |
jz .root |
call fd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 ; do not allow read files |
jnz .found_dir |
pop edi |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
movzx eax, word [edi+26] |
add eax, 31 |
push 0 |
jmp .doit |
.root: |
mov eax, 19 |
push 14 |
.doit: |
push ecx ebp |
sub esp, 262*2 ; reserve space for LFN |
mov ebp, esp |
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names |
mov ebx, [ebx] |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
pop ecx eax |
mov byte [edx], 1 ; version |
mov esi, edi ; esi points to BDFE |
.main_loop: |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .error |
mov edi, FDD_BUFF |
push eax |
.l1: |
call fat_get_name |
jc .l2 |
cmp byte [edi+11], 0xF |
jnz .do_bdfe |
add edi, 0x20 |
cmp edi, OS_BASE+0xD200 |
jb .do_bdfe |
pop eax |
inc eax |
dec byte [esp+262*2+12] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+FLOPPY_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+12], 0 |
@@: |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .error |
mov edi, FDD_BUFF |
push eax |
.do_bdfe: |
inc dword [edx+8] ; new file found |
dec ebx |
jns .l2 |
dec ecx |
js .l2 |
inc dword [edx+4] ; new file block copied |
call fat_entry_to_bdfe |
.l2: |
add edi, 0x20 |
cmp edi, OS_BASE+0xD200 |
jb .l1 |
pop eax |
inc eax |
dec byte [esp+262*2+12] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+FLOPPY_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+12], 0 |
@@: |
jmp .main_loop |
.error: |
add esp, 262*2+4 |
pop ebp ecx edi edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.done: |
add esp, 262*2+4 |
pop ebp |
mov ebx, [edx+4] |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
pop ecx edi edi |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyRewrite - LFN variant for writing sys floppy |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
fsfrfe2: |
popad |
fsfrfe: |
mov eax, 11 |
xor ebx, ebx |
ret |
fs_FloppyCreateFolder: |
mov al, 1 |
jmp fs_FloppyRewrite.common |
fs_FloppyRewrite: |
xor eax, eax |
.common: |
cmp byte [esi], 0 |
jz @b |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz fsfrfe |
pushad |
xor edi, edi |
push esi |
test ebp, ebp |
jz @f |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
lea edi, [esi-1] |
jmp @b |
@@: |
pop esi |
test edi, edi |
jnz .noroot |
test ebp, ebp |
jnz .hasebp |
call read_flp_root |
cmp [FDC_Status], 0 |
jnz fsfrfe2 |
push flp_rootmem_extend_dir |
push flp_rootmem_end_write |
push flp_rootmem_next_write |
push flp_rootmem_begin_write |
xor ebp, ebp |
push ebp |
push flp_rootmem_first |
push flp_rootmem_next |
jmp .common1 |
.hasebp: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [ebp], 0 |
jz .ret1 |
push ebp |
xor ebp, ebp |
call fd_find_lfn |
pop esi |
jc .notfound0 |
jmp .common0 |
.noroot: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [edi+1], 0 |
jz .ret1 |
; check existence |
mov byte [edi], 0 |
push edi |
call fd_find_lfn |
pop esi |
mov byte [esi], '/' |
jnc @f |
.notfound0: |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
@@: |
inc esi |
.common0: |
test byte [edi+11], 0x10 ; must be directory |
mov eax, ERROR_ACCESS_DENIED |
jz .ret1 |
movzx ebp, word [edi+26] ; ebp=cluster |
mov eax, ERROR_FAT_TABLE |
cmp ebp, 2 |
jb .ret1 |
cmp ebp, 2849 |
jae .ret1 |
push flp_notroot_extend_dir |
push flp_notroot_end_write |
push flp_notroot_next_write |
push flp_notroot_begin_write |
push ebp |
push flp_notroot_first |
push flp_notroot_next |
.common1: |
call fat_find_lfn |
jc .notfound |
; found |
test byte [edi+11], 10h |
jz .exists_file |
; found directory; if we are creating directory, return OK, |
; if we are creating file, say "access denied" |
add esp, 28 |
popad |
test al, al |
mov eax, ERROR_ACCESS_DENIED |
jz @f |
mov al, 0 |
@@: |
xor ebx, ebx |
ret |
.exists_file: |
; found file; if we are creating directory, return "access denied", |
; if we are creating file, delete existing file and continue |
cmp byte [esp+28+28], 0 |
jz @f |
add esp, 28 |
popad |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
@@: |
; delete FAT chain |
push edi |
xor eax, eax |
mov dword [edi+28], eax ; zero size |
xchg ax, word [edi+26] ; start cluster |
test eax, eax |
jz .done1 |
@@: |
cmp eax, 0xFF8 |
jae .done1 |
lea edi, [FLOPPY_FAT + eax*2] ; position in FAT |
xor eax, eax |
xchg ax, [edi] |
jmp @b |
.done1: |
pop edi |
call get_time_for_file |
mov [edi+22], ax |
call get_date_for_file |
mov [edi+24], ax |
mov [edi+18], ax |
or byte [edi+11], 20h ; set 'archive' attribute |
jmp .doit |
.notfound: |
; file is not found; generate short name |
call fat_name_is_legal |
jc @f |
add esp, 28 |
popad |
mov eax, ERROR_FILE_NOT_FOUND |
xor ebx, ebx |
ret |
@@: |
sub esp, 12 |
mov edi, esp |
call fat_gen_short_name |
.test_short_name_loop: |
push esi edi ecx |
mov esi, edi |
lea eax, [esp+12+12+8] |
mov [eax], ebp |
call dword [eax-4] |
jc .found |
.test_short_name_entry: |
cmp byte [edi+11], 0xF |
jz .test_short_name_cont |
mov ecx, 11 |
push esi edi |
repz cmpsb |
pop edi esi |
jz .short_name_found |
.test_short_name_cont: |
lea eax, [esp+12+12+8] |
call dword [eax-8] |
jnc .test_short_name_entry |
jmp .found |
.short_name_found: |
pop ecx edi esi |
call fat_next_short_name |
jnc .test_short_name_loop |
.disk_full: |
add esp, 12+28 |
popa |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.found: |
pop ecx edi esi |
; now find space in directory |
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' |
mov al, '~' |
push ecx edi |
mov ecx, 8 |
repnz scasb |
push 1 |
pop eax ; 1 entry |
jnz .notilde |
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total |
xor eax, eax |
@@: |
cmp byte [esi], 0 |
jz @f |
inc esi |
inc eax |
jmp @b |
@@: |
sub esi, eax |
add eax, 12+13 |
mov ecx, 13 |
push edx |
cdq |
div ecx |
pop edx |
.notilde: |
push -1 |
push -1 |
; find <eax> successive entries in directory |
xor ecx, ecx |
push eax |
lea eax, [esp+12+8+12+8] |
mov [eax], ebp |
call dword [eax-4] |
pop eax |
jnc .scan_dir |
.fsfrfe3: |
add esp, 8+8+12+28 |
popad |
mov eax, 11 |
xor ebx, ebx |
ret |
.scan_dir: |
cmp byte [edi], 0 |
jz .free |
cmp byte [edi], 0xE5 |
jz .free |
xor ecx, ecx |
.scan_cont: |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax-8] |
pop eax |
jnc .scan_dir |
cmp [FDC_Status], 0 |
jnz .fsfrfe3 |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax+16] ; extend directory |
pop eax |
jnc .scan_dir |
add esp, 8+8+12+28 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.free: |
test ecx, ecx |
jnz @f |
mov [esp], edi |
mov ecx, [esp+8+8+12+8] |
mov [esp+4], ecx |
xor ecx, ecx |
@@: |
inc ecx |
cmp ecx, eax |
jb .scan_cont |
; found! |
; calculate name checksum |
push esi ecx |
mov esi, [esp+8+8] |
mov ecx, 11 |
xor eax, eax |
@@: |
ror al, 1 |
add al, [esi] |
inc esi |
loop @b |
pop ecx esi |
pop edi |
pop dword [esp+8+12+8] |
; edi points to first entry in free chunk |
dec ecx |
jz .nolfn |
push esi |
push eax |
lea eax, [esp+8+8+12+8] |
call dword [eax+4] ; begin write |
mov al, 40h |
.writelfn: |
or al, cl |
mov esi, [esp+4] |
push ecx |
dec ecx |
imul ecx, 13 |
add esi, ecx |
stosb |
mov cl, 5 |
call fs_RamdiskRewrite.read_symbols |
mov ax, 0xF |
stosw |
mov al, [esp+4] |
stosb |
mov cl, 6 |
call fs_RamdiskRewrite.read_symbols |
xor eax, eax |
stosw |
mov cl, 2 |
call fs_RamdiskRewrite.read_symbols |
pop ecx |
lea eax, [esp+8+8+12+8] |
call dword [eax+8] ; next write |
xor eax, eax |
loop .writelfn |
pop eax |
pop esi |
; lea eax, [esp+8+12+8] |
; call dword [eax+12] ; end write |
.nolfn: |
xchg esi, [esp] |
mov ecx, 11 |
rep movsb |
mov word [edi], 20h ; attributes |
sub edi, 11 |
pop esi ecx |
add esp, 12 |
mov byte [edi+13], 0 ; tenths of a second at file creation time |
call get_time_for_file |
mov [edi+14], ax ; creation time |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+16], ax ; creation date |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
and word [edi+20], 0 ; high word of cluster |
and word [edi+26], 0 ; low word of cluster - to be filled |
and dword [edi+28], 0 ; file size - to be filled |
cmp byte [esp+28+28], 0 |
jz .doit |
; create directory |
mov byte [edi+11], 10h ; attributes: folder |
mov ecx, 32*2 |
mov edx, edi |
.doit: |
lea eax, [esp+8] |
call dword [eax+12] ; flush directory |
push ecx |
push edi |
push 0 |
mov esi, edx |
test ecx, ecx |
jz .done |
mov ecx, 2849 |
mov edi, FLOPPY_FAT |
push 0 ; first cluster |
.write_loop: |
; allocate new cluster |
xor eax, eax |
repnz scasw |
mov al, ERROR_DISK_FULL |
jnz .ret |
dec edi |
dec edi |
mov eax, edi |
sub eax, FLOPPY_FAT |
shr eax, 1 ; eax = cluster |
mov word [edi], 0xFFF ; mark as last cluster |
xchg edi, [esp+4] |
cmp dword [esp], 0 |
jz .first |
stosw |
jmp @f |
.first: |
mov [esp], eax |
@@: |
mov edi, [esp+4] |
inc ecx |
; write data |
push ecx edi |
mov ecx, 512 |
cmp dword [esp+20], ecx |
jae @f |
mov ecx, [esp+20] |
@@: |
mov edi, FDD_BUFF |
cmp byte [esp+24+28+28], 0 |
jnz .writedir |
push ecx |
rep movsb |
pop ecx |
.writedircont: |
push ecx |
sub ecx, 512 |
neg ecx |
push eax |
xor eax, eax |
rep stosb |
pop eax |
add eax, 31 |
pusha |
call save_chs_sector |
popa |
pop ecx |
cmp [FDC_Status], 0 |
jnz .diskerr |
sub [esp+20], ecx |
pop edi ecx |
jnz .write_loop |
.done: |
xor eax, eax |
.ret: |
pop ebx edi edi ecx |
mov [esp+28+28], eax |
lea eax, [esp+8] |
call dword [eax+4] |
mov [edi+26], bx |
mov ebx, esi |
sub ebx, edx |
mov [edi+28], ebx |
call dword [eax+12] |
mov [esp+28+16], ebx |
test ebp, ebp |
jnz @f |
call save_flp_root |
@@: |
add esp, 28 |
cmp [FDC_Status], 0 |
jnz .err3 |
call save_flp_fat |
cmp [FDC_Status], 0 |
jnz .err3 |
popa |
ret |
.err3: |
popa |
mov al, 11 |
xor ebx, ebx |
ret |
.diskerr: |
sub esi, ecx |
mov eax, 11 |
pop edi ecx |
jmp .ret |
.writedir: |
push ecx |
mov ecx, 32/4 |
push ecx esi |
rep movsd |
pop esi ecx |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov word [edi-32+26], ax |
push esi |
rep movsd |
pop esi |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov ecx, [esp+28+8] |
mov word [edi-32+26], cx |
pop ecx |
jmp .writedircont |
;---------------------------------------------------------------- |
; |
; fs_FloppyWrite - LFN variant for writing to floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
push ERROR_ACCESS_DENIED |
fs_FloppyWrite.ret0: |
pop eax |
xor ebx, ebx |
ret |
fs_FloppyWrite.ret11: |
push 11 |
jmp fs_FloppyWrite.ret0 |
fs_FloppyWrite: |
cmp byte [esi], 0 |
jz @b |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz .ret11 |
pushad |
call fd_find_lfn |
jnc .found |
popad |
push ERROR_FILE_NOT_FOUND |
jmp .ret0 |
.found: |
; FAT does not support files larger than 4GB |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
.eof: |
popad |
push ERROR_END_OF_FILE |
jmp .ret0 |
@@: |
mov ebx, [ebx] |
.l1: |
; now edi points to direntry, ebx=start byte to write, |
; ecx=number of bytes to write, edx=data pointer |
; extend file if needed |
add ecx, ebx |
jc .eof ; FAT does not support files larger than 4GB |
push eax ; save directory cluster |
push 0 ; return value=0 |
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
push dword [edi+28] ; save current file size |
cmp ecx, [edi+28] |
jbe .length_ok |
cmp ecx, ebx |
jz .length_ok |
call floppy_extend_file |
jnc .length_ok |
mov [esp+4], eax |
; floppy_extend_file can return two error codes: FAT table error or disk full. |
; First case is fatal error, in second case we may write some data |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax |
pop eax |
mov [esp+4+28], eax |
pop eax |
popad |
xor ebx, ebx |
ret |
.disk_full: |
; correct number of bytes to write |
mov ecx, [edi+28] |
cmp ecx, ebx |
ja .length_ok |
.ret: |
pop eax |
pop eax |
mov [esp+4+28], eax ; eax=return value |
pop eax |
sub edx, [esp+20] |
mov [esp+16], edx ; ebx=number of written bytes |
popad |
ret |
.length_ok: |
; save FAT & directory |
; note that directory must be saved first because save_flp_fat uses buffer at 0xD000 |
mov esi, [edi+28] |
movzx edi, word [edi+26] ; starting cluster |
mov eax, [esp+8] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err |
call save_flp_fat |
cmp [FDC_Status], 0 |
jz @f |
.device_err: |
mov byte [esp+4], 11 |
jmp .ret |
@@: |
; now ebx=start pos, ecx=end pos, both lie inside file |
sub ecx, ebx |
jz .ret |
call SetUserInterrupts |
.write_loop: |
; skip unmodified sectors |
cmp dword [esp], 0x200 |
jb .modify |
sub ebx, 0x200 |
jae .skip |
add ebx, 0x200 |
.modify: |
lea eax, [edi+31] ; current sector |
; get length of data in current sector |
push ecx |
sub ebx, 0x200 |
jb .hasdata |
neg ebx |
xor ecx, ecx |
jmp @f |
.hasdata: |
neg ebx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
; load sector if needed |
cmp dword [esp+4], 0 ; we don't need to read uninitialized data |
jz .noread |
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten |
jz .noread |
cmp ecx, esi ; (same for the last sector) |
jz .noread |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jz @f |
.device_err2: |
pop ecx |
jmp .device_err |
@@: |
.noread: |
; zero uninitialized data if file was extended (because floppy_extend_file does not this) |
push eax ecx edi |
xor eax, eax |
mov ecx, 0x200 |
sub ecx, [esp+4+12] |
jbe @f |
mov edi, FDD_BUFF |
add edi, [esp+4+12] |
rep stosb |
@@: |
; zero uninitialized data in the last sector |
mov ecx, 0x200 |
sub ecx, esi |
jbe @f |
mov edi, FDD_BUFF |
add edi, esi |
rep stosb |
@@: |
pop edi ecx eax |
; copy new data |
push eax |
mov eax, edx |
neg ebx |
jecxz @f |
add ebx, FDD_BUFF+0x200 |
call memmove |
xor ebx, ebx |
@@: |
pop eax |
; save sector |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err2 |
add edx, ecx |
sub [esp], ecx |
pop ecx |
jz .done |
.skip: |
.next_cluster: |
movzx edi, word [edi*2+FLOPPY_FAT] |
sub esi, 0x200 |
jae @f |
xor esi, esi |
@@: |
sub dword [esp], 0x200 |
jae .write_loop |
and dword [esp], 0 |
jmp .write_loop |
.done: |
mov [fdc_irq_func], fdc_null |
jmp .ret |
floppy_extend_file.zero_size: |
xor eax, eax |
jmp floppy_extend_file.start_extend |
; extends file on floppy to given size (new data area is undefined) |
; in: edi->direntry, ecx=new size |
; out: CF=0 => OK, eax=0 |
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL) |
floppy_extend_file: |
push ecx |
; find the last cluster of file |
movzx eax, word [edi+26] ; first cluster |
mov ecx, [edi+28] |
jecxz .zero_size |
@@: |
sub ecx, 0x200 |
jbe @f |
mov eax, [eax*2+FLOPPY_FAT] |
and eax, 0xFFF |
jz .fat_err |
cmp eax, 0xFF8 |
jb @b |
.fat_err: |
pop ecx |
push ERROR_FAT_TABLE |
pop eax |
stc |
ret |
@@: |
push eax |
mov eax, [eax*2+FLOPPY_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
pop eax |
jb .fat_err |
; set length to full number of sectors |
sub [edi+28], ecx |
.start_extend: |
pop ecx |
; now do extend |
push edx esi |
mov esi, FLOPPY_FAT+2*2 ; start scan from cluster 2 |
mov edx, 2847 ; number of clusters to scan |
.extend_loop: |
cmp [edi+28], ecx |
jae .extend_done |
; add new sector |
push ecx |
push edi |
.scan: |
mov ecx, edx |
mov edi, esi |
jecxz .disk_full |
push eax |
xor eax, eax |
repnz scasw |
pop eax |
jnz .disk_full |
mov word [edi-2], 0xFFF |
mov esi, edi |
mov edx, ecx |
sub edi, FLOPPY_FAT |
shr edi, 1 |
dec edi ; now edi=new cluster |
test eax, eax |
jz .first_cluster |
mov [FLOPPY_FAT+eax*2], di |
jmp @f |
.first_cluster: |
pop eax ; eax->direntry |
push eax |
mov [eax+26], di |
@@: |
mov eax, edi ; eax=new cluster |
pop edi ; edi->direntry |
pop ecx ; ecx=required size |
add dword [edi+28], 0x200 |
jmp .extend_loop |
.extend_done: |
mov [edi+28], ecx |
pop esi edx |
xor eax, eax ; CF=0 |
ret |
.disk_full: |
pop edi ecx |
pop esi edx |
stc |
push ERROR_DISK_FULL |
pop eax |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppySetFileEnd - set end of file on floppy |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppySetFileEnd: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz ret11 |
cmp byte [esi], 0 |
jnz @f |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .ret |
@@: |
push edi |
call fd_find_lfn |
jnc @f |
pop edi |
push ERROR_FILE_NOT_FOUND |
.ret: |
pop eax |
jmp .doret |
@@: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
pop edi |
jmp .access_denied |
@@: |
; file size must not exceed 4 Gb |
cmp dword [ebx+4], 0 |
jz @f |
pop edi |
push ERROR_END_OF_FILE |
jmp .ret |
@@: |
push eax |
; set file modification date/time to current |
call fat_update_datetime |
mov eax, [ebx] |
cmp eax, [edi+28] |
jb .truncate |
ja .expand |
pop eax |
pushad |
call save_chs_sector |
popad |
pop edi |
xor eax, eax |
cmp [FDC_Status], 0 |
jz @f |
mov al, 11 |
@@: |
.doret: |
mov [fdc_irq_func], fdc_null |
ret |
.expand: |
push ecx |
push dword [edi+28] ; save old size |
mov ecx, eax |
call floppy_extend_file |
push eax ; return code |
jnc .expand_ok |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax ecx ecx edi edi |
jmp .doret |
.device_err: |
pop eax |
.device_err2: |
pop ecx ecx eax edi |
push 11 |
jmp .ret |
.disk_full: |
.expand_ok: |
; save directory & FAT |
mov eax, [edi+28] |
xchg eax, [esp+12] |
movzx edi, word [edi+26] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err |
call save_flp_fat |
cmp [FDC_Status], 0 |
jnz .device_err |
call SetUserInterrupts |
; now zero new data |
; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code |
.zero_loop: |
sub dword [esp+4], 0x200 |
jae .next_cluster |
cmp dword [esp+4], -0x200 |
jz .noread |
lea eax, [edi+31] |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .err_next |
.noread: |
mov ecx, [esp+4] |
neg ecx |
push edi |
mov edi, FDD_BUFF+0x200 |
add edi, [esp+8] |
xor eax, eax |
mov [esp+8], eax |
rep stosb |
pop edi |
lea eax, [edi+31] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jz .next_cluster |
.err_next: |
mov byte [esp], 11 |
.next_cluster: |
sub dword [esp+12], 0x200 |
jbe .expand_done |
movzx edi, word [FLOPPY_FAT+edi*2] |
jmp .zero_loop |
.expand_done: |
pop eax ecx ecx edi edi |
jmp .doret |
.truncate: |
mov [edi+28], eax |
push ecx |
movzx ecx, word [edi+26] |
test eax, eax |
jz .zero_size |
; find new last sector |
@@: |
sub eax, 0x200 |
jbe @f |
movzx ecx, word [FLOPPY_FAT+ecx*2] |
jmp @b |
@@: |
; we will zero data at the end of last sector - remember it |
push ecx |
; terminate FAT chain |
lea ecx, [FLOPPY_FAT+ecx+ecx] |
push dword [ecx] |
mov word [ecx], 0xFFF |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.zero_size: |
and word [edi+26], 0 |
push 0 |
.delete: |
; delete FAT chain starting with ecx |
; mark all clusters as free |
cmp ecx, 0xFF8 |
jae .deleted |
lea ecx, [FLOPPY_FAT+ecx+ecx] |
push dword [ecx] |
and word [ecx], 0 |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.deleted: |
mov edi, [edi+28] |
; save directory & FAT |
mov eax, [esp+8] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err2 |
call save_flp_fat |
cmp [FDC_Status], 0 |
jnz .device_err2 |
; zero last sector, ignore errors |
pop eax |
add eax, 31 |
and edi, 0x1FF |
jz .truncate_done |
call SetUserInterrupts |
pusha |
call read_chs_sector |
popa |
add edi, FDD_BUFF |
mov ecx, FDD_BUFF+0x200 |
sub ecx, edi |
push eax |
xor eax, eax |
rep stosb |
pop eax |
pusha |
call save_chs_sector |
popa |
.truncate_done: |
pop ecx eax edi |
xor eax, eax |
jmp .doret |
fs_FloppyGetFileInfo: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz ret11 |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call fd_find_lfn |
jmp fs_GetFileInfo_finish |
ret11: |
mov eax, 11 |
ret |
fs_FloppySetFileInfo: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz ret11 |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call fd_find_lfn |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
push eax |
call bdfe_to_fat_entry |
pop eax |
pusha |
call save_chs_sector |
popa |
pop edi |
xor eax, eax |
cmp [FDC_Status], al |
jz @f |
mov al, 11 |
@@: |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyDelete - delete file or empty folder from floppy |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppyDelete: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jz @f |
push 11 |
jmp .pop_ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
; cannot delete root! |
.access_denied: |
push ERROR_ACCESS_DENIED |
.pop_ret: |
pop eax |
ret |
@@: |
and [fd_prev_sector], 0 |
and [fd_prev_prev_sector], 0 |
push edi |
call fd_find_lfn |
jnc .found |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .pop_ret |
.found: |
cmp dword [edi], '. ' |
jz .access_denied2 |
cmp dword [edi], '.. ' |
jz .access_denied2 |
test byte [edi+11], 10h |
jz .dodel |
; we can delete only empty folders! |
push eax |
movzx eax, word [edi+26] |
push ebx |
pusha |
add eax, 31 |
call read_chs_sector |
popa |
mov ebx, FDD_BUFF + 2*0x20 |
.checkempty: |
cmp byte [ebx], 0 |
jz .empty |
cmp byte [ebx], 0xE5 |
jnz .notempty |
add ebx, 0x20 |
cmp ebx, FDD_BUFF + 0x200 |
jb .checkempty |
movzx eax, word [FLOPPY_FAT + eax*2] |
pusha |
add eax, 31 |
call read_chs_sector |
popa |
mov ebx, FDD_BUFF |
jmp .checkempty |
.notempty: |
pop ebx |
pop eax |
.access_denied2: |
pop edi |
jmp .access_denied |
.empty: |
pop ebx |
pop eax |
pusha |
call read_chs_sector |
popa |
.dodel: |
push eax |
movzx eax, word [edi+26] |
xchg eax, [esp] |
; delete folder entry |
mov byte [edi], 0xE5 |
; delete LFN (if present) |
.lfndel: |
cmp edi, FDD_BUFF |
ja @f |
cmp [fd_prev_sector], 0 |
jz .lfndone |
push [fd_prev_sector] |
push [fd_prev_prev_sector] |
pop [fd_prev_sector] |
and [fd_prev_prev_sector], 0 |
pusha |
call save_chs_sector |
popa |
pop eax |
pusha |
call read_chs_sector |
popa |
mov edi, FDD_BUFF+0x200 |
@@: |
sub edi, 0x20 |
cmp byte [edi], 0xE5 |
jz .lfndone |
cmp byte [edi+11], 0xF |
jnz .lfndone |
mov byte [edi], 0xE5 |
jmp .lfndel |
.lfndone: |
pusha |
call save_chs_sector |
popa |
; delete FAT chain |
pop eax |
test eax, eax |
jz .done |
@@: |
lea eax, [FLOPPY_FAT + eax*2] |
push dword [eax] |
and word [eax], 0 |
pop eax |
and eax, 0xFFF |
jnz @b |
.done: |
call save_flp_fat |
pop edi |
xor eax, eax |
ret |
; \end{diamond} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fs/fat32.inc |
---|
1,2935 → 1,2940 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; FAT32.INC ;; |
;; ;; |
;; FAT16/32 functions for KolibriOS ;; |
;; ;; |
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; |
;; ;; |
;; See file COPYING for details ;; |
;; 04.02.2007 LFN create folder - diamond ;; |
;; 08.10.2006 LFN delete file/folder - diamond ;; |
;; 20.08.2006 LFN set file size (truncate/extend) - diamond ;; |
;; 17.08.2006 LFN write/append to file - diamond ;; |
;; 23.06.2006 LFN start application - diamond ;; |
;; 15.06.2006 LFN get/set file/folder info - diamond ;; |
;; 27.05.2006 LFN create/rewrite file - diamond ;; |
;; 04.05.2006 LFN read folder - diamond ;; |
;; 29.04.2006 Elimination of hangup after the ;; |
;; expiration hd_wait_timeout - Mario79 ;; |
;; 23.04.2006 LFN read file - diamond ;; |
;; 28.01.2006 find all Fat16/32 partition in all input point ;; |
;; to MBR, see file part_set.inc - Mario79 ;; |
;; 15.01.2005 get file size/attr/date, file_append - ATV ;; |
;; 04.12.2004 skip volume label, file delete bug fixed - ATV ;; |
;; 29.11.2004 get_free_FAT changed, append dir bug fixed - ATV ;; |
;; 23.11.2004 don't allow overwrite dir with file - ATV ;; |
;; 18.11.2004 get_disk_info and more error codes - ATV ;; |
;; 17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV ;; |
;; 10.11.2004 removedir clear whole directory structure - ATV ;; |
;; 08.11.2004 rename - ATV ;; |
;; 30.10.2004 file_read return also dirsize in bytes - ATV ;; |
;; 20.10.2004 Makedir/Removedir - ATV ;; |
;; 14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx) ;; |
;; 06.9.2004 Fix free space by Mario79 added - MH ;; |
;; 24.5.2004 Write back buffer for File_write -VT ;; |
;; 20.5.2004 File_read function to work with syscall 58 - VT ;; |
;; 30.3.2004 Error parameters at function return - VT ;; |
;; 01.5.2002 Bugfix in device write - VT ;; |
;; 20.5.2002 Hd status check - VT ;; |
;; 29.6.2002 Improved fat32 verification - VT ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
cache_max equ 1919 ; max. is 1919*512+0x610000=0x6ffe00 |
ERROR_SUCCESS = 0 |
ERROR_DISK_BASE = 1 |
ERROR_UNSUPPORTED_FS = 2 |
ERROR_UNKNOWN_FS = 3 |
ERROR_PARTITION = 4 |
ERROR_FILE_NOT_FOUND = 5 |
ERROR_END_OF_FILE = 6 |
ERROR_MEMORY_POINTER = 7 |
ERROR_DISK_FULL = 8 |
ERROR_FAT_TABLE = 9 |
ERROR_ACCESS_DENIED = 10 |
ERROR_DEVICE = 11 |
PUSHAD_EAX equ [esp+28] |
PUSHAD_ECX equ [esp+24] |
PUSHAD_EDX equ [esp+20] |
PUSHAD_EBX equ [esp+16] |
PUSHAD_EBP equ [esp+8] |
PUSHAD_ESI equ [esp+4] |
PUSHAD_EDI equ [esp+0] |
uglobal |
align 4 |
partition_count dd 0 ; partitions found by set_FAT32_variables |
longname_sec1 dd 0 ; used by analyze_directory to save 2 previous |
longname_sec2 dd 0 ; directory sectors for delete long filename |
hd_error dd 0 ; set by wait_for_sector_buffer |
hd_setup dd 0 |
hd_wait_timeout dd 0 |
cluster_tmp dd 0 ; used by analyze_directory |
; and analyze_directory_to_write |
file_size dd 0 ; used by file_read |
cache_search_start dd 0 ; used by find_empty_slot |
endg |
iglobal |
fat_in_cache dd -1 |
endg |
uglobal |
align 4 |
fat_cache: times 512 db 0 |
Sector512: ; label for dev_hdcd.inc |
buffer: times 512 db 0 |
fsinfo_buffer: times 512 db 0 |
endg |
uglobal |
fat16_root db 0 ; flag for fat16 rootdir |
fat_change db 0 ; 1=fat has changed |
endg |
reserve_hd1: |
cli |
cmp [hd1_status],0 |
je reserve_ok1 |
sti |
call change_task |
jmp reserve_hd1 |
reserve_ok1: |
push eax |
mov eax,[CURRENT_TASK] |
shl eax,5 |
mov eax,[eax+CURRENT_TASK+TASKDATA.pid] |
mov [hd1_status],eax |
pop eax |
sti |
ret |
;******************************************** |
uglobal |
hd_in_cache db ? |
endg |
reserve_hd_channel: |
; BIOS disk accesses are protected with common mutex hd1_status |
; This must be modified when hd1_status will not be valid! |
cmp [hdpos], 0x80 |
jae .ret |
cmp [hdbase], 0x1F0 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
cli |
cmp [IDE_Channel_1],0 |
je .reserve_ok_1 |
sti |
call change_task |
jmp .IDE_Channel_1 |
.IDE_Channel_2: |
cli |
cmp [IDE_Channel_2],0 |
je .reserve_ok_2 |
sti |
call change_task |
jmp .IDE_Channel_2 |
.reserve_ok_1: |
mov [IDE_Channel_1], 1 |
push eax |
mov al, 1 |
jmp @f |
.reserve_ok_2: |
mov [IDE_Channel_2], 1 |
push eax |
mov al, 3 |
@@: |
cmp [hdid], 1 |
sbb al, -1 |
cmp al, [hd_in_cache] |
jz @f |
mov [hd_in_cache], al |
call clear_hd_cache |
@@: |
pop eax |
sti |
.ret: |
ret |
free_hd_channel: |
; see comment at reserve_hd_channel |
cmp [hdpos], 0x80 |
jae .ret |
cmp [hdbase], 0x1F0 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
mov [IDE_Channel_1],0 |
.ret: |
ret |
.IDE_Channel_2: |
mov [IDE_Channel_2],0 |
ret |
;******************************************** |
problem_partition db 0 ; used for partitions search |
include 'part_set.inc' |
set_FAT: |
;-------------------------------- |
; input : EAX = cluster |
; EDX = value to save |
; output : EDX = old value |
;-------------------------------- |
push eax ebx esi |
cmp eax,2 |
jb sfc_error |
cmp eax,[LAST_CLUSTER] |
ja sfc_error |
cmp [fs_type],16 |
je sfc_1 |
add eax,eax |
sfc_1: |
add eax,eax |
mov esi,511 |
and esi,eax ; esi = position in fat sector |
shr eax,9 ; eax = fat sector |
add eax,[FAT_START] |
mov ebx,fat_cache |
cmp eax,[fat_in_cache] ; is fat sector already in memory? |
je sfc_in_cache ; yes |
cmp [fat_change],0 ; is fat changed? |
je sfc_no_change ; no |
call write_fat_sector ; yes. write it into disk |
cmp [hd_error],0 |
jne sfc_error |
sfc_no_change: |
mov [fat_in_cache],eax ; save fat sector |
call hd_read |
cmp [hd_error],0 |
jne sfc_error |
sfc_in_cache: |
cmp [fs_type],16 |
jne sfc_test32 |
sfc_set16: |
xchg [ebx+esi],dx ; save new value and get old value |
jmp sfc_write |
sfc_test32: |
mov eax,[fatMASK] |
sfc_set32: |
and edx,eax |
xor eax,-1 ; mask for high bits |
and eax,[ebx+esi] ; get high 4 bits |
or eax,edx |
mov edx,[ebx+esi] ; get old value |
mov [ebx+esi],eax ; save new value |
sfc_write: |
mov [fat_change],1 ; fat has changed |
sfc_nonzero: |
and edx,[fatMASK] |
sfc_error: |
pop esi ebx eax |
ret |
get_FAT: |
;-------------------------------- |
; input : EAX = cluster |
; output : EAX = next cluster |
;-------------------------------- |
push ebx esi |
cmp [fs_type],16 |
je gfc_1 |
add eax,eax |
gfc_1: |
add eax,eax |
mov esi,511 |
and esi,eax ; esi = position in fat sector |
shr eax,9 ; eax = fat sector |
add eax,[FAT_START] |
mov ebx,fat_cache |
cmp eax,[fat_in_cache] ; is fat sector already in memory? |
je gfc_in_cache |
cmp [fat_change],0 ; is fat changed? |
je gfc_no_change ; no |
call write_fat_sector ; yes. write it into disk |
cmp [hd_error],0 |
jne hd_error_01 |
gfc_no_change: |
mov [fat_in_cache],eax |
call hd_read |
cmp [hd_error],0 |
jne hd_error_01 |
gfc_in_cache: |
mov eax,[ebx+esi] |
and eax,[fatMASK] |
hd_error_01: |
pop esi ebx |
ret |
get_free_FAT: |
;----------------------------------------------------------- |
; output : if CARRY=0 EAX = # first cluster found free |
; if CARRY=1 disk full |
; Note : for more speed need to use fat_cache directly |
;----------------------------------------------------------- |
push ecx |
mov ecx,[LAST_CLUSTER] ; counter for full disk |
sub ecx,2 |
mov eax,[fatStartScan] |
cmp eax,2 |
jb gff_reset |
gff_test: |
cmp eax,[LAST_CLUSTER] ; if above last cluster start at cluster 2 |
jbe gff_in_range |
gff_reset: |
mov eax,2 |
gff_in_range: |
push eax |
call get_FAT ; get cluster state |
cmp [hd_error],0 |
jne gff_not_found_1 |
test eax,eax ; is it free? |
pop eax |
je gff_found ; yes |
inc eax ; next cluster |
dec ecx ; is all checked? |
jns gff_test ; no |
gff_not_found_1: |
add esp,4 |
gff_not_found: |
pop ecx ; yes. disk is full |
stc |
ret |
gff_found: |
lea ecx,[eax+1] |
mov [fatStartScan],ecx |
pop ecx |
clc |
ret |
write_fat_sector: |
;----------------------------------------------------------- |
; write changed fat to disk |
;----------------------------------------------------------- |
push eax ebx ecx |
mov [fat_change],0 |
mov eax,[fat_in_cache] |
cmp eax,-1 |
jz write_fat_not_used |
mov ebx,fat_cache |
mov ecx,[NUMBER_OF_FATS] |
write_next_fat: |
call hd_write |
cmp [hd_error],0 |
jne write_fat_not_used |
add eax,[SECTORS_PER_FAT] |
dec ecx |
jnz write_next_fat |
write_fat_not_used: |
pop ecx ebx eax |
ret |
analyze_directory: |
;----------------------------------------------------------- |
; input : EAX = first cluster of the directory |
; EBX = pointer to filename |
; output : IF CARRY=0 EAX = sector where th file is found |
; EBX = pointer in buffer |
; [buffer .. buffer+511] |
; ECX,EDX,ESI,EDI not changed |
; IF CARRY=1 filename not found |
; Note : if cluster=0 it's changed to read rootdir |
; save 2 previous directory sectors in longname_sec |
;----------------------------------------------------------- |
push ecx edx esi edi ebx ; ebx = [esp+0] |
mov [longname_sec1],0 |
mov [longname_sec2],0 |
adr_new_cluster: |
mov [cluster_tmp],eax |
mov [fat16_root],0 |
cmp eax,[LAST_CLUSTER] |
ja adr_not_found ; too big cluster number, something is wrong |
cmp eax,2 |
jnb adr_data_cluster |
mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir |
cmp [fs_type],16 |
jne adr_data_cluster |
mov eax,[ROOT_START] |
mov edx,[ROOT_SECTORS] |
mov [fat16_root],1 ; flag for fat16 rootdir |
jmp adr_new_sector |
adr_data_cluster: |
sub eax,2 |
mov edx,[SECTORS_PER_CLUSTER] |
imul eax,edx |
add eax,[DATA_START] |
adr_new_sector: |
mov ebx,buffer |
call hd_read |
cmp [hd_error],0 |
jne adr_not_found |
mov ecx,512/32 ; count of dir entrys per sector = 16 |
adr_analyze: |
mov edi,[ebx+11] ; file attribute |
and edi,0xf |
cmp edi,0xf |
je adr_long_filename |
test edi,0x8 ; skip over volume label |
jne adr_long_filename ; Note: label can be same name as file/dir |
mov esi,[esp+0] ; filename need to be uppercase |
mov edi,ebx |
push ecx |
mov ecx,11 |
cld |
rep cmpsb ; compare 8+3 filename |
pop ecx |
je adr_found |
adr_long_filename: |
add ebx,32 ; position of next dir entry |
dec ecx |
jnz adr_analyze |
mov ecx,[longname_sec1] ; save 2 previous directory sectors |
mov [longname_sec1],eax ; for delete long filename |
mov [longname_sec2],ecx |
inc eax ; next sector |
dec edx |
jne adr_new_sector |
cmp [fat16_root],1 ; end of fat16 rootdir |
je adr_not_found |
adr_next_cluster: |
mov eax,[cluster_tmp] |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne adr_not_found |
cmp eax,2 ; incorrect fat chain? |
jb adr_not_found ; yes |
cmp eax,[fatRESERVED] ; is it end of directory? |
jb adr_new_cluster ; no. analyse it |
adr_not_found: |
pop edi edi esi edx ecx ; first edi will remove ebx |
stc ; file not found |
ret |
adr_found: |
pop edi edi esi edx ecx ; first edi will remove ebx |
clc ; file found |
ret |
get_data_cluster: |
;----------------------------------------------------------- |
; input : EAX = cluster |
; EBX = pointer to buffer |
; EDX = # blocks to read in buffer |
; ESI = # blocks to skip over |
; output : if CARRY=0 ok EBX/EDX/ESI updated |
; if CARRY=1 cluster out of range |
; Note : if cluster=0 it's changed to read rootdir |
;----------------------------------------------------------- |
push eax ecx |
mov [fat16_root],0 |
cmp eax,[LAST_CLUSTER] |
ja gdc_error ; too big cluster number, something is wrong |
cmp eax,2 |
jnb gdc_cluster |
mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir |
cmp [fs_type],16 |
jne gdc_cluster |
mov eax,[ROOT_START] |
mov ecx,[ROOT_SECTORS] ; Note: not cluster size |
mov [fat16_root],1 ; flag for fat16 rootdir |
jmp gdc_read |
gdc_cluster: |
sub eax,2 |
mov ecx,[SECTORS_PER_CLUSTER] |
imul eax,ecx |
add eax,[DATA_START] |
gdc_read: |
test esi,esi ; first wanted block |
je gdcl1 ; yes, skip count is 0 |
dec esi |
jmp gdcl2 |
gdcl1: |
call hd_read |
cmp [hd_error],0 |
jne gdc_error |
add ebx,512 ; update pointer |
dec edx |
gdcl2: |
test edx,edx ; is all read? |
je out_of_read |
inc eax ; next sector |
dec ecx |
jnz gdc_read |
out_of_read: |
pop ecx eax |
clc |
ret |
gdc_error: |
pop ecx eax |
stc |
ret |
get_cluster_of_a_path: |
;--------------------------------------------------------- |
; input : EBX = pointer to a path string |
; (example: the path "/files/data/document" become |
; "files......data.......document...0" |
; '.' = space char |
; '0' = char(0) (ASCII=0) !!! ) |
; output : if (CARRY=1) -> ERROR in the PATH |
; if (CARRY=0) -> EAX=cluster |
;--------------------------------------------------------- |
push ebx edx |
mov eax,[ROOT_CLUSTER] |
mov edx,ebx |
search_end_of_path: |
cmp byte [edx],0 |
je found_end_of_path |
inc edx ; '/' |
mov ebx,edx |
call analyze_directory |
jc directory_not_found |
mov eax,[ebx+20-2] ; read the HIGH 16bit cluster field |
mov ax,[ebx+26] ; read the LOW 16bit cluster field |
and eax,[fatMASK] |
add edx,11 ; 8+3 (name+extension) |
jmp search_end_of_path |
found_end_of_path: |
pop edx ebx |
clc ; no errors |
ret |
directory_not_found: |
pop edx ebx |
stc ; errors occour |
ret |
bcd2bin: |
;---------------------------------- |
; input : AL=BCD number (eg. 0x11) |
; output : AH=0 |
; AL=decimal number (eg. 11) |
;---------------------------------- |
xor ah,ah |
shl ax,4 |
shr al,4 |
aad |
ret |
get_date_for_file: |
;----------------------------------------------------- |
; Get date from CMOS and pack day,month,year in AX |
; DATE bits 0..4 : day of month 0..31 |
; 5..8 : month of year 1..12 |
; 9..15 : count of years from 1980 |
;----------------------------------------------------- |
mov al,0x7 ;day |
out 0x70,al |
in al,0x71 |
call bcd2bin |
ror eax,5 |
mov al,0x8 ;month |
out 0x70,al |
in al,0x71 |
call bcd2bin |
ror eax,4 |
mov al,0x9 ;year |
out 0x70,al |
in al,0x71 |
call bcd2bin |
add ax,20 ;because CMOS return only the two last |
;digit (eg. 2000 -> 00 , 2001 -> 01) and we |
rol eax,9 ;need the difference with 1980 (eg. 2001-1980) |
ret |
get_time_for_file: |
;----------------------------------------------------- |
; Get time from CMOS and pack hour,minute,second in AX |
; TIME bits 0..4 : second (the low bit is lost) |
; 5..10 : minute 0..59 |
; 11..15 : hour 0..23 |
;----------------------------------------------------- |
mov al,0x0 ;second |
out 0x70,al |
in al,0x71 |
call bcd2bin |
ror eax,6 |
mov al,0x2 ;minute |
out 0x70,al |
in al,0x71 |
call bcd2bin |
ror eax,6 |
mov al,0x4 ;hour |
out 0x70,al |
in al,0x71 |
call bcd2bin |
rol eax,11 |
ret |
set_current_time_for_entry: |
;----------------------------------------------------- |
; Set current time/date for file entry |
; input : ebx = file entry pointer |
;----------------------------------------------------- |
push eax |
call get_time_for_file ; update files date/time |
mov [ebx+22],ax |
call get_date_for_file |
mov [ebx+24],ax |
pop eax |
ret |
add_disk_free_space: |
;----------------------------------------------------- |
; input : ecx = cluster count |
; Note : negative = remove clusters from free space |
; positive = add clusters to free space |
;----------------------------------------------------- |
test ecx,ecx ; no change |
je add_dfs_no |
cmp [fs_type],32 ; free disk space only used by fat32 |
jne add_dfs_no |
push eax ebx |
mov eax,[ADR_FSINFO] |
mov ebx,fsinfo_buffer |
call hd_read |
cmp [hd_error],0 |
jne add_not_fs |
cmp dword [ebx+0x1fc],0xaa550000 ; check sector id |
jne add_not_fs |
add [ebx+0x1e8],ecx |
push [fatStartScan] |
pop dword [ebx+0x1ec] |
call hd_write |
; cmp [hd_error],0 |
; jne add_not_fs |
add_not_fs: |
pop ebx eax |
add_dfs_no: |
ret |
file_read: |
;-------------------------------------------------------------------------- |
; INPUT : user-register register-in-this meaning symbol-in-this |
; |
; EAX EDI system call to write / |
; EBX EAX (PAR0) pointer to file-name PAR0 |
; EDX ECX (PAR1) pointer to buffer PAR1 |
; ECX EBX (PAR2) vt file blocks to read PAR2 |
; ESI EDX (PAR3) pointer to path PAR3 |
; EDI ESI vt first 512 block to read |
; EDI if 0 - read root |
; |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 6 - end of file |
; 9 - fat table corrupted |
; 10 - access denied |
; ebx = size of file/directory |
;-------------------------------------------------------------------------- |
cmp [fs_type], 16 |
jz fat_ok_for_reading |
cmp [fs_type], 32 |
jz fat_ok_for_reading |
xor ebx,ebx |
mov eax,ERROR_UNKNOWN_FS |
mov [hd1_status], ebx |
ret |
fat_ok_for_reading: |
; call reserve_hd1 |
pushad |
mov ebx,edx |
call get_cluster_of_a_path |
jc file_to_read_not_found |
test edi,edi ; read rootdir |
jne no_read_root |
xor eax,eax |
call get_dir_size ; return rootdir size |
cmp [hd_error],0 |
jne file_access_denied |
mov [file_size],eax |
mov eax,[ROOT_CLUSTER] |
jmp file_read_start |
no_read_root: |
mov ebx,PUSHAD_EAX ; file name |
call analyze_directory |
jc file_to_read_not_found |
mov eax,[ebx+28] ; file size |
test byte [ebx+11],0x10 ; is it directory? |
jz read_set_size ; no |
mov eax,[ebx+20-2] ; FAT entry |
mov ax,[ebx+26] |
and eax,[fatMASK] |
call get_dir_size |
cmp [hd_error],0 |
jne file_access_denied |
read_set_size: |
mov [file_size],eax |
mov eax,[ebx+20-2] ; FAT entry |
mov ax,[ebx+26] |
and eax,[fatMASK] |
file_read_start: |
mov ebx,PUSHAD_ECX ; pointer to buffer |
mov edx,PUSHAD_EBX ; file blocks to read |
mov esi,PUSHAD_ESI ; first 512 block to read |
file_read_new_cluster: |
call get_data_cluster |
jc file_read_eof ; end of file or cluster out of range |
test edx,edx ; is all read? |
je file_read_OK ; yes |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne file_access_denied |
cmp eax,[fatRESERVED] ; end of file |
jnb file_read_eof |
cmp eax,2 ; incorrect fat chain |
jnb file_read_new_cluster |
popad |
mov [hd1_status],0 |
mov ebx,[file_size] |
mov eax,ERROR_FAT_TABLE |
ret |
file_read_eof: |
cmp [hd_error],0 |
jne file_access_denied |
popad |
mov [hd1_status],0 |
mov ebx,[file_size] |
mov eax,ERROR_END_OF_FILE |
ret |
file_read_OK: |
popad |
mov [hd1_status],0 |
mov ebx,[file_size] |
xor eax,eax |
ret |
file_to_read_not_found: |
cmp [hd_error],0 |
jne file_access_denied |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
file_access_denied: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_ACCESS_DENIED |
ret |
get_dir_size: |
;----------------------------------------------------- |
; input : eax = first cluster (0=rootdir) |
; output : eax = directory size in bytes |
;----------------------------------------------------- |
push edx |
xor edx,edx ; count of directory clusters |
test eax,eax |
jnz dir_size_next |
mov eax,[ROOT_SECTORS] |
shl eax,9 ; fat16 rootdir size in bytes |
cmp [fs_type],16 |
je dir_size_ret |
mov eax,[ROOT_CLUSTER] |
dir_size_next: |
cmp eax,2 ; incorrect fat chain |
jb dir_size_end |
cmp eax,[fatRESERVED] ; end of directory |
ja dir_size_end |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne dir_size_ret |
inc edx |
jmp dir_size_next |
dir_size_end: |
imul eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes |
imul eax,edx |
dir_size_ret: |
pop edx |
ret |
clear_cluster_chain: |
;----------------------------------------------------- |
; input : eax = first cluster |
;----------------------------------------------------- |
push eax ecx edx |
xor ecx,ecx ; cluster count |
clean_new_chain: |
cmp eax,[LAST_CLUSTER] ; end of file |
ja delete_OK |
cmp eax,2 ; unfinished fat chain or zero length file |
jb delete_OK |
cmp eax,[ROOT_CLUSTER] ; don't remove root cluster |
jz delete_OK |
xor edx,edx |
call set_FAT ; clear fat entry |
cmp [hd_error],0 |
jne access_denied_01 |
inc ecx ; update cluster count |
mov eax,edx ; old cluster |
jmp clean_new_chain |
delete_OK: |
call add_disk_free_space ; add clusters to free disk space |
access_denied_01: |
pop edx ecx eax |
ret |
get_hd_info: |
;----------------------------------------------------------- |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 10 - access denied |
; edx = cluster size in bytes |
; ebx = total clusters on disk |
; ecx = free clusters on disk |
;----------------------------------------------------------- |
cmp [fs_type], 16 |
jz info_fat_ok |
cmp [fs_type], 32 |
jz info_fat_ok |
xor edx,edx |
xor ebx,ebx |
xor ecx,ecx |
mov eax,ERROR_UNKNOWN_FS |
ret |
info_fat_ok: |
; call reserve_hd1 |
xor ecx,ecx ; count of free clusters |
mov eax,2 |
mov ebx,[LAST_CLUSTER] |
info_cluster: |
push eax |
call get_FAT ; get cluster info |
cmp [hd_error],0 |
jne info_access_denied |
test eax,eax ; is it free? |
jnz info_used ; no |
inc ecx |
info_used: |
pop eax |
inc eax |
cmp eax,ebx ; is above last cluster? |
jbe info_cluster ; no. test next cluster |
dec ebx ; cluster count |
imul edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes |
mov [hd1_status],0 |
xor eax,eax |
ret |
info_access_denied: |
add esp,4 |
xor edx,edx |
xor ebx,ebx |
xor ecx,ecx |
mov eax,ERROR_ACCESS_DENIED |
ret |
update_disk: |
;----------------------------------------------------------- |
; write changed fat and cache to disk |
;----------------------------------------------------------- |
cmp [fat_change],0 ; is fat changed? |
je upd_no_change |
call write_fat_sector |
cmp [hd_error],0 |
jne update_disk_acces_denied |
upd_no_change: |
call write_cache |
update_disk_acces_denied: |
ret |
; \begin{diamond} |
hd_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and edi->direntry, eax=sector |
; destroys eax |
push esi edi |
push 0 |
push 0 |
push fat16_root_first |
push fat16_root_next |
mov eax, [ROOT_CLUSTER] |
cmp [fs_type], 32 |
jz .fat32 |
.loop: |
call fat_find_lfn |
jc .notfound |
cmp byte [esi], 0 |
jz .found |
.continue: |
test byte [edi+11], 10h |
jz .notfound |
and dword [esp+12], 0 |
mov eax, [edi+20-2] |
mov ax, [edi+26] ; cluster |
.fat32: |
mov [esp+8], eax |
mov dword [esp+4], fat_notroot_first |
mov dword [esp], fat_notroot_next |
jmp .loop |
.notfound: |
add esp, 16 |
pop edi esi |
stc |
ret |
.found: |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .continue |
@@: |
lea eax, [esp+8] |
cmp dword [eax], 0 |
jz .root |
call fat_get_sector |
jmp .cmn |
.root: |
mov eax, [eax+4] |
add eax, [ROOT_START] |
.cmn: |
add esp, 20 ; CF=0 |
pop esi |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdRead - LFN variant for reading hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdRead: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdRead |
cmp [fs_type], 2 |
jz ext2_HdRead |
or ebx, -1 |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
push edi |
cmp byte [esi], 0 |
jnz @f |
.noaccess: |
pop edi |
.noaccess_2: |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
@@: |
call hd_find_lfn |
jnc .found |
pop edi |
cmp [hd_error],0 |
jne .noaccess_2 |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 ; 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 |
pop edi |
ret |
@@: |
mov ebx, [ebx] |
.l1: |
push ecx edx |
push 0 |
mov eax, [edi+28] |
sub eax, ebx |
jb .eof |
cmp eax, ecx |
jae @f |
mov ecx, eax |
mov byte [esp], 6 |
@@: |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data |
.new_cluster: |
jecxz .new_sector |
test eax, eax |
jz .eof |
cmp eax, [fatRESERVED] |
jae .eof |
mov [cluster_tmp], eax |
dec eax |
dec eax |
mov edi, [SECTORS_PER_CLUSTER] |
imul eax, edi |
add eax, [DATA_START] |
.new_sector: |
test ecx, ecx |
jz .done |
sub ebx, 512 |
jae .skip |
add ebx, 512 |
jnz .force_buf |
cmp ecx, 512 |
jb .force_buf |
; we may read directly to given buffer |
push ebx |
mov ebx, edx |
call hd_read |
pop ebx |
cmp [hd_error],0 |
jne .noaccess_1 |
add edx, 512 |
sub ecx, 512 |
jmp .skip |
.force_buf: |
; we must read sector to temporary buffer and then copy it to destination |
push eax ebx |
mov ebx, buffer |
call hd_read |
mov eax, ebx |
pop ebx |
cmp [hd_error],0 |
jne .noaccess_3 |
add eax, ebx |
push ecx |
add ecx, ebx |
cmp ecx, 512 |
jbe @f |
mov ecx, 512 |
@@: |
sub ecx, ebx |
mov ebx, edx |
call memmove |
add edx, ecx |
sub [esp], ecx |
pop ecx |
pop eax |
xor ebx, ebx |
.skip: |
inc eax |
dec edi |
jnz .new_sector |
mov eax, [cluster_tmp] |
call get_FAT |
cmp [hd_error],0 |
jne .noaccess_1 |
jmp .new_cluster |
.noaccess_3: |
pop eax |
.noaccess_1: |
pop eax |
push 11 |
.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_HdReadFolder - LFN variant for reading hard disk folder |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdReadFolder: |
cmp [fs_type], 1 |
jz ntfs_HdReadFolder |
cmp [fs_type], 2 |
jz ext2_HdReadFolder |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNSUPPORTED_FS |
pop eax |
or ebx, -1 |
ret |
@@: |
mov eax, [ROOT_CLUSTER] |
push edi |
cmp byte [esi], 0 |
jz .doit |
call hd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 ; do not allow read files |
jnz .found_dir |
pop edi |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
mov eax, [edi+20-2] |
mov ax, [edi+26] ; eax=cluster |
.doit: |
push esi ecx |
push ebp |
sub esp, 262*2 ; reserve space for LFN |
mov ebp, esp |
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE name |
mov ebx, [ebx] |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
pop ecx eax |
mov byte [edx], 1 ; version |
mov esi, edi ; esi points to BDFE |
.new_cluster: |
mov [cluster_tmp], eax |
test eax, eax |
jnz @f |
cmp [fs_type], 32 |
jz .notfound |
mov eax, [ROOT_START] |
push [ROOT_SECTORS] |
push ebx |
jmp .new_sector |
@@: |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
push [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
push ebx |
.new_sector: |
mov ebx, buffer |
mov edi, ebx |
call hd_read |
cmp [hd_error], 0 |
jnz .notfound2 |
add ebx, 512 |
push eax |
.l1: |
call fat_get_name |
jc .l2 |
cmp byte [edi+11], 0xF |
jnz .do_bdfe |
add edi, 0x20 |
cmp edi, ebx |
jb .do_bdfe |
pop eax |
inc eax |
dec dword [esp+4] |
jnz @f |
mov eax, [cluster_tmp] |
test eax, eax |
jz .done |
call get_FAT |
cmp [hd_error], 0 |
jnz .notfound2 |
cmp eax, 2 |
jb .done |
cmp eax, [fatRESERVED] |
jae .done |
push eax |
mov eax, [SECTORS_PER_CLUSTER] |
mov [esp+8], eax |
pop eax |
mov [cluster_tmp], eax |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
@@: |
mov ebx, buffer |
mov edi, ebx |
call hd_read |
cmp [hd_error], 0 |
jnz .notfound2 |
add ebx, 512 |
push eax |
.do_bdfe: |
inc dword [edx+8] ; new file found |
dec dword [esp+4] |
jns .l2 |
dec ecx |
js .l2 |
inc dword [edx+4] ; new file block copied |
call fat_entry_to_bdfe |
.l2: |
add edi, 0x20 |
cmp edi, ebx |
jb .l1 |
pop eax |
inc eax |
dec dword [esp+4] |
jnz .new_sector |
mov eax, [cluster_tmp] |
test eax, eax |
jz .done |
call get_FAT |
cmp [hd_error], 0 |
jnz .notfound2 |
cmp eax, 2 |
jb .done |
cmp eax, [fatRESERVED] |
jae .done |
push eax |
mov eax, [SECTORS_PER_CLUSTER] |
mov [esp+8], eax |
pop eax |
pop ebx |
add esp, 4 |
jmp .new_cluster |
.notfound2: |
add esp, 8 |
.notfound: |
add esp, 262*2+4 |
pop ebp ecx esi edi |
mov eax, ERROR_FILE_NOT_FOUND |
or ebx, -1 |
ret |
.done: |
add esp, 262*2+4+8 |
pop ebp |
mov ebx, [edx+4] |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
pop ecx esi edi |
ret |
fat16_root_next: |
cmp edi, buffer+0x200-0x20 |
jae fat16_root_next_sector |
add edi, 0x20 |
ret ; CF=0 |
fat16_root_next_sector: |
; read next sector |
push [longname_sec2] |
pop [longname_sec1] |
push ecx |
mov ecx, [eax+4] |
push ecx |
add ecx, [ROOT_START] |
mov [longname_sec2], ecx |
pop ecx |
inc ecx |
mov [eax+4], ecx |
cmp ecx, [ROOT_SECTORS] |
pop ecx |
jae fat16_root_first.readerr |
fat16_root_first: |
mov eax, [eax+4] |
add eax, [ROOT_START] |
push ebx |
mov edi, buffer |
mov ebx, edi |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jnz .readerr |
ret ; CF=0 |
.readerr: |
stc |
ret |
fat16_root_begin_write: |
push edi eax |
call fat16_root_first |
pop eax edi |
ret |
fat16_root_end_write: |
pusha |
mov eax, [eax+4] |
add eax, [ROOT_START] |
mov ebx, buffer |
call hd_write |
popa |
ret |
fat16_root_next_write: |
cmp edi, buffer+0x200 |
jae @f |
ret |
@@: |
call fat16_root_end_write |
jmp fat16_root_next_sector |
fat16_root_extend_dir: |
stc |
ret |
fat_notroot_next: |
cmp edi, buffer+0x200-0x20 |
jae fat_notroot_next_sector |
add edi, 0x20 |
ret ; CF=0 |
fat_notroot_next_sector: |
push [longname_sec2] |
pop [longname_sec1] |
push eax |
call fat_get_sector |
mov [longname_sec2], eax |
pop eax |
push ecx |
mov ecx, [eax+4] |
inc ecx |
cmp ecx, [SECTORS_PER_CLUSTER] |
jae fat_notroot_next_cluster |
mov [eax+4], ecx |
jmp @f |
fat_notroot_next_cluster: |
push eax |
mov eax, [eax] |
call get_FAT |
mov ecx, eax |
pop eax |
cmp [hd_error], 0 |
jnz fat_notroot_next_err |
cmp ecx, [fatRESERVED] |
jae fat_notroot_next_err |
mov [eax], ecx |
and dword [eax+4], 0 |
@@: |
pop ecx |
fat_notroot_first: |
call fat_get_sector |
push ebx |
mov edi, buffer |
mov ebx, edi |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jnz @f |
ret ; CF=0 |
fat_notroot_next_err: |
pop ecx |
@@: |
stc |
ret |
fat_notroot_begin_write: |
push eax edi |
call fat_notroot_first |
pop edi eax |
ret |
fat_notroot_end_write: |
call fat_get_sector |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
ret |
fat_notroot_next_write: |
cmp edi, buffer+0x200 |
jae @f |
ret |
@@: |
push eax |
call fat_notroot_end_write |
pop eax |
jmp fat_notroot_next_sector |
fat_notroot_extend_dir: |
push eax |
call get_free_FAT |
jnc .found |
pop eax |
ret ; CF=1 |
.found: |
push edx |
mov edx, [fatEND] |
call set_FAT |
mov edx, eax |
mov eax, [esp+4] |
mov eax, [eax] |
push edx |
call set_FAT |
pop edx |
cmp [hd_error], 0 |
jz @f |
pop edx |
pop eax |
stc |
ret |
@@: |
push ecx |
or ecx, -1 |
call add_disk_free_space |
; zero new cluster |
mov ecx, 512/4 |
mov edi, buffer |
push edi |
xor eax, eax |
rep stosd |
pop edi |
pop ecx |
mov eax, [esp+4] |
mov [eax], edx |
and dword [eax+4], 0 |
pop edx |
mov eax, [eax] |
dec eax |
dec eax |
push ebx ecx |
mov ecx, [SECTORS_PER_CLUSTER] |
imul eax, ecx |
add eax, [DATA_START] |
mov ebx, edi |
@@: |
call hd_write |
inc eax |
loop @b |
pop ecx ebx eax |
clc |
ret |
fat_get_sector: |
push ecx |
mov ecx, [eax] |
dec ecx |
dec ecx |
imul ecx, [SECTORS_PER_CLUSTER] |
add ecx, [DATA_START] |
add ecx, [eax+4] |
mov eax, ecx |
pop ecx |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdRewrite - LFN variant for writing hard disk |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fshrad: |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
fshrfs: |
mov eax, ERROR_UNKNOWN_FS |
xor ebx, ebx |
ret |
fs_HdCreateFolder: |
mov al, 1 |
jmp fs_HdRewrite.common |
fs_HdRewrite: |
xor eax, eax |
.common: |
cmp [fs_type], 1 |
jz ntfs_HdRewrite |
cmp [fs_type], 2 |
jz ext2_HdRewrite |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jnz fshrfs |
@@: |
cmp byte [esi], 0 |
jz fshrad |
pushad |
xor edi, edi |
push esi |
test ebp, ebp |
jz @f |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
lea edi, [esi-1] |
jmp @b |
@@: |
pop esi |
test edi, edi |
jnz .noroot |
test ebp, ebp |
jnz .hasebp |
mov ebp, [ROOT_CLUSTER] |
cmp [fs_type], 32 |
jz .pushnotroot |
push fat16_root_extend_dir |
push fat16_root_end_write |
push fat16_root_next_write |
push fat16_root_begin_write |
xor ebp, ebp |
push ebp |
push ebp |
push fat16_root_first |
push fat16_root_next |
jmp .common1 |
.hasebp: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [ebp], 0 |
jz .ret1 |
push ebp |
xor ebp, ebp |
call hd_find_lfn |
pop esi |
jc .notfound0 |
jmp .common0 |
.noroot: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [edi+1], 0 |
jz .ret1 |
; check existence |
mov byte [edi], 0 |
push edi |
call hd_find_lfn |
pop esi |
mov byte [esi], '/' |
jnc @f |
.notfound0: |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
@@: |
inc esi |
.common0: |
test byte [edi+11], 0x10 ; must be directory |
mov eax, ERROR_ACCESS_DENIED |
jz .ret1 |
mov ebp, [edi+20-2] |
mov bp, [edi+26] ; ebp=cluster |
mov eax, ERROR_FAT_TABLE |
cmp ebp, 2 |
jb .ret1 |
.pushnotroot: |
push fat_notroot_extend_dir |
push fat_notroot_end_write |
push fat_notroot_next_write |
push fat_notroot_begin_write |
push 0 |
push ebp |
push fat_notroot_first |
push fat_notroot_next |
.common1: |
call fat_find_lfn |
jc .notfound |
; found |
test byte [edi+11], 10h |
jz .exists_file |
; found directory; if we are creating directory, return OK, |
; if we are creating file, say "access denied" |
add esp, 32 |
popad |
test al, al |
mov eax, ERROR_ACCESS_DENIED |
jz @f |
mov al, 0 |
@@: |
xor ebx, ebx |
ret |
.exists_file: |
; found file; if we are creating directory, return "access denied", |
; if we are creating file, delete existing file and continue |
cmp byte [esp+32+28], 0 |
jz @f |
add esp, 32 |
popad |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
@@: |
; delete FAT chain |
push edi |
xor eax, eax |
mov dword [edi+28], eax ; zero size |
xor ecx, ecx |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov word [edi+20], cx |
mov word [edi+26], cx |
test eax, eax |
jz .done1 |
@@: |
cmp eax, [fatRESERVED] |
jae .done1 |
push edx |
xor edx, edx |
call set_FAT |
mov eax, edx |
pop edx |
inc ecx |
jmp @b |
.done1: |
pop edi |
call get_time_for_file |
mov [edi+22], ax |
call get_date_for_file |
mov [edi+24], ax |
mov [edi+18], ax |
or byte [edi+11], 20h ; set 'archive' attribute |
jmp .doit |
.notfound: |
; file is not found; generate short name |
call fat_name_is_legal |
jc @f |
add esp, 32 |
popad |
mov eax, ERROR_FILE_NOT_FOUND |
xor ebx, ebx |
ret |
@@: |
sub esp, 12 |
mov edi, esp |
call fat_gen_short_name |
.test_short_name_loop: |
push esi edi ecx |
mov esi, edi |
lea eax, [esp+12+12+8] |
mov [eax], ebp |
and dword [eax+4], 0 |
call dword [eax-4] |
jc .found |
.test_short_name_entry: |
cmp byte [edi+11], 0xF |
jz .test_short_name_cont |
mov ecx, 11 |
push esi edi |
repz cmpsb |
pop edi esi |
jz .short_name_found |
.test_short_name_cont: |
lea eax, [esp+12+12+8] |
call dword [eax-8] |
jnc .test_short_name_entry |
jmp .found |
.short_name_found: |
pop ecx edi esi |
call fat_next_short_name |
jnc .test_short_name_loop |
.disk_full: |
add esp, 12+32 |
popa |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.found: |
pop ecx edi esi |
; now find space in directory |
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' |
mov al, '~' |
push ecx edi |
mov ecx, 8 |
repnz scasb |
push 1 |
pop eax ; 1 entry |
jnz .notilde |
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total |
xor eax, eax |
@@: |
cmp byte [esi], 0 |
jz @f |
inc esi |
inc eax |
jmp @b |
@@: |
sub esi, eax |
add eax, 12+13 |
mov ecx, 13 |
push edx |
cdq |
div ecx |
pop edx |
.notilde: |
push -1 |
push -1 |
push -1 |
; find <eax> successive entries in directory |
xor ecx, ecx |
push eax |
lea eax, [esp+16+8+12+8] |
mov [eax], ebp |
and dword [eax+4], 0 |
call dword [eax-4] |
pop eax |
jnc .scan_dir |
.fsfrfe3: |
add esp, 12+8+12+32 |
popad |
mov eax, 11 |
xor ebx, ebx |
ret |
.scan_dir: |
cmp byte [edi], 0 |
jz .free |
cmp byte [edi], 0xE5 |
jz .free |
xor ecx, ecx |
.scan_cont: |
push eax |
lea eax, [esp+16+8+12+8] |
call dword [eax-8] |
pop eax |
jnc .scan_dir |
cmp [hd_error], 0 |
jnz .fsfrfe3 |
push eax |
lea eax, [esp+16+8+12+8] |
call dword [eax+20] ; extend directory |
pop eax |
jnc .scan_dir |
add esp, 12+8+12+32 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.free: |
test ecx, ecx |
jnz @f |
mov [esp], edi |
mov ecx, [esp+12+8+12+8] |
mov [esp+4], ecx |
mov ecx, [esp+12+8+12+12] |
mov [esp+8], ecx |
xor ecx, ecx |
@@: |
inc ecx |
cmp ecx, eax |
jb .scan_cont |
; found! |
; calculate name checksum |
push esi ecx |
mov esi, [esp+8+12] |
mov ecx, 11 |
xor eax, eax |
@@: |
ror al, 1 |
add al, [esi] |
inc esi |
loop @b |
pop ecx esi |
pop edi |
pop dword [esp+8+12+12] |
pop dword [esp+8+12+12] |
; edi points to first entry in free chunk |
dec ecx |
jz .nolfn |
push esi |
push eax |
lea eax, [esp+8+8+12+8] |
call dword [eax+8] ; begin write |
mov al, 40h |
.writelfn: |
or al, cl |
mov esi, [esp+4] |
push ecx |
dec ecx |
imul ecx, 13 |
add esi, ecx |
stosb |
mov cl, 5 |
call fs_RamdiskRewrite.read_symbols |
mov ax, 0xF |
stosw |
mov al, [esp+4] |
stosb |
mov cl, 6 |
call fs_RamdiskRewrite.read_symbols |
xor eax, eax |
stosw |
mov cl, 2 |
call fs_RamdiskRewrite.read_symbols |
pop ecx |
lea eax, [esp+8+8+12+8] |
call dword [eax+12] ; next write |
xor eax, eax |
loop .writelfn |
pop eax |
pop esi |
; lea eax, [esp+8+12+8] |
; call dword [eax+16] ; end write |
.nolfn: |
xchg esi, [esp] |
mov ecx, 11 |
rep movsb |
mov word [edi], 20h ; attributes |
sub edi, 11 |
pop esi ecx |
add esp, 12 |
mov byte [edi+13], 0 ; tenths of a second at file creation time |
call get_time_for_file |
mov [edi+14], ax ; creation time |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+16], ax ; creation date |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
xor ecx, ecx |
mov word [edi+20], cx ; high word of cluster |
mov word [edi+26], cx ; low word of cluster - to be filled |
mov dword [edi+28], ecx ; file size - to be filled |
cmp byte [esp+32+28], cl |
jz .doit |
; create directory |
mov byte [edi+11], 10h ; attributes: folder |
mov edx, edi |
lea eax, [esp+8] |
call dword [eax+16] ; flush directory |
push ecx |
mov ecx, [SECTORS_PER_CLUSTER] |
shl ecx, 9 |
jmp .doit2 |
.doit: |
lea eax, [esp+8] |
call dword [eax+16] ; flush directory |
push ecx |
mov ecx, [esp+4+32+24] |
.doit2: |
push ecx |
push edi |
mov esi, edx |
test ecx, ecx |
jz .done |
call get_free_FAT |
jc .diskfull |
push eax |
mov [edi+26], ax |
shr eax, 16 |
mov [edi+20], ax |
lea eax, [esp+16+8] |
call dword [eax+16] ; flush directory |
pop eax |
push edx |
mov edx, [fatEND] |
call set_FAT |
pop edx |
.write_cluster: |
push eax |
dec eax |
dec eax |
mov ebp, [SECTORS_PER_CLUSTER] |
imul eax, ebp |
add eax, [DATA_START] |
; write data |
.write_sector: |
cmp byte [esp+16+32+28], 0 |
jnz .writedir |
mov ecx, 512 |
cmp dword [esp+8], ecx |
jb .writeshort |
; we can write directly from given buffer |
mov ebx, esi |
add esi, ecx |
jmp .writecommon |
.writeshort: |
mov ecx, [esp+8] |
push ecx |
mov edi, buffer |
mov ebx, edi |
rep movsb |
.writedircont: |
mov ecx, buffer+0x200 |
sub ecx, edi |
push eax |
xor eax, eax |
rep stosb |
pop eax |
pop ecx |
.writecommon: |
call hd_write |
cmp [hd_error], 0 |
jnz .writeerr |
inc eax |
sub dword [esp+8], ecx |
jz .writedone |
dec ebp |
jnz .write_sector |
; allocate new cluster |
pop eax |
mov ecx, eax |
call get_free_FAT |
jc .diskfull |
push edx |
mov edx, [fatEND] |
call set_FAT |
xchg eax, ecx |
mov edx, ecx |
call set_FAT |
pop edx |
xchg eax, ecx |
jmp .write_cluster |
.diskfull: |
mov eax, ERROR_DISK_FULL |
jmp .ret |
.writeerr: |
pop eax |
sub esi, ecx |
mov eax, 11 |
jmp .ret |
.writedone: |
pop eax |
.done: |
xor eax, eax |
.ret: |
pop edi ecx |
mov ebx, esi |
sub ebx, edx |
pop ebp |
mov [esp+32+28], eax |
lea eax, [esp+8] |
call dword [eax+8] |
mov [edi+28], ebx |
call dword [eax+16] |
mov [esp+32+16], ebx |
lea eax, [ebx+511] |
shr eax, 9 |
mov ecx, [SECTORS_PER_CLUSTER] |
lea eax, [eax+ecx-1] |
xor edx, edx |
div ecx |
mov ecx, ebp |
sub ecx, eax |
call add_disk_free_space |
add esp, 32 |
call update_disk |
popad |
ret |
.writedir: |
push 512 |
mov edi, buffer |
mov ebx, edi |
mov ecx, [SECTORS_PER_CLUSTER] |
shl ecx, 9 |
cmp ecx, [esp+12] |
jnz .writedircont |
dec dword [esp+16] |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov ecx, [esp+20+8] |
cmp ecx, [ROOT_CLUSTER] |
jnz @f |
xor ecx, ecx |
@@: |
mov word [edi-32+26], cx |
shr ecx, 16 |
mov [edi-32+20], cx |
jmp .writedircont |
;---------------------------------------------------------------- |
; |
; fs_HdWrite - LFN variant for writing to hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdWrite.access_denied: |
push ERROR_ACCESS_DENIED |
fs_HdWrite.ret0: |
pop eax |
xor ebx, ebx |
ret |
fs_HdWrite.ret11: |
push 11 |
jmp fs_HdWrite.ret0 |
fs_HdWrite: |
cmp [fs_type], 1 |
jz ntfs_HdWrite |
cmp [fs_type], 2 |
jz ext2_HdWrite |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNKNOWN_FS |
jmp .ret0 |
@@: |
cmp byte [esi], 0 |
jz .access_denied |
pushad |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
popad |
push 11 |
jmp .ret0 |
@@: |
popfd |
jnc .found |
popad |
push ERROR_FILE_NOT_FOUND |
jmp .ret0 |
.found: |
; FAT does not support files larger than 4GB |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
.eof: |
popad |
push ERROR_END_OF_FILE |
jmp .ret0 |
@@: |
mov ebx, [ebx] |
.l1: |
; now edi points to direntry, ebx=start byte to write, |
; ecx=number of bytes to write, edx=data pointer |
; extend file if needed |
add ecx, ebx |
jc .eof ; FAT does not support files larger than 4GB |
push eax ; save directory sector |
push 0 ; return value=0 |
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
push dword [edi+28] ; save current file size |
cmp ecx, [edi+28] |
jbe .length_ok |
cmp ecx, ebx |
jz .length_ok |
call hd_extend_file |
jnc .length_ok |
mov [esp+4], eax |
; hd_extend_file can return three error codes: FAT table error, device error or disk full. |
; First two cases are fatal errors, in third case we may write some data |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax |
pop eax |
mov [esp+4+28], eax |
pop eax |
popad |
xor ebx, ebx |
ret |
.disk_full: |
; correct number of bytes to write |
mov ecx, [edi+28] |
cmp ecx, ebx |
ja .length_ok |
.ret: |
call update_disk |
cmp [hd_error], 0 |
jz @f |
mov byte [esp+4], 11 |
@@: |
pop eax |
pop eax |
mov [esp+4+28], eax ; eax=return value |
pop eax |
sub edx, [esp+20] |
mov [esp+16], edx ; ebx=number of written bytes |
popad |
ret |
.length_ok: |
mov esi, [edi+28] |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov edi, eax ; edi=current cluster |
xor ebp, ebp ; ebp=current sector in cluster |
; save directory |
mov eax, [esp+8] |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jz @f |
.device_err: |
mov byte [esp+4], 11 |
jmp .ret |
@@: |
; now ebx=start pos, ecx=end pos, both lie inside file |
sub ecx, ebx |
jz .ret |
.write_loop: |
; skip unmodified sectors |
cmp dword [esp], 0x200 |
jb .modify |
sub ebx, 0x200 |
jae .skip |
add ebx, 0x200 |
.modify: |
; get length of data in current sector |
push ecx |
sub ebx, 0x200 |
jb .hasdata |
neg ebx |
xor ecx, ecx |
jmp @f |
.hasdata: |
neg ebx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
; get current sector number |
mov eax, edi |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ebp |
; load sector if needed |
cmp dword [esp+4], 0 ; we don't need to read uninitialized data |
jz .noread |
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten |
jz .noread |
cmp ecx, esi ; (same for the last sector) |
jz .noread |
push ebx |
mov ebx, buffer |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jz @f |
.device_err2: |
pop ecx |
jmp .device_err |
@@: |
.noread: |
; zero uninitialized data if file was extended (because hd_extend_file does not this) |
push eax ecx edi |
xor eax, eax |
mov ecx, 0x200 |
sub ecx, [esp+4+12] |
jbe @f |
mov edi, buffer |
add edi, [esp+4+12] |
rep stosb |
@@: |
; zero uninitialized data in the last sector |
mov ecx, 0x200 |
sub ecx, esi |
jbe @f |
mov edi, buffer |
add edi, esi |
rep stosb |
@@: |
pop edi ecx |
; copy new data |
mov eax, edx |
neg ebx |
jecxz @f |
add ebx, buffer+0x200 |
call memmove |
xor ebx, ebx |
@@: |
pop eax |
; save sector |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jnz .device_err2 |
add edx, ecx |
sub [esp], ecx |
pop ecx |
jz .ret |
.skip: |
; next sector |
inc ebp |
cmp ebp, [SECTORS_PER_CLUSTER] |
jb @f |
xor ebp, ebp |
mov eax, edi |
call get_FAT |
mov edi, eax |
cmp [hd_error], 0 |
jnz .device_err |
@@: |
sub esi, 0x200 |
jae @f |
xor esi, esi |
@@: |
sub dword [esp], 0x200 |
jae @f |
and dword [esp], 0 |
@@: jmp .write_loop |
hd_extend_file.zero_size: |
xor eax, eax |
jmp hd_extend_file.start_extend |
; extends file on hd to given size (new data area is undefined) |
; in: edi->direntry, ecx=new size |
; out: CF=0 => OK, eax=0 |
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or 11) |
hd_extend_file: |
push ebp |
mov ebp, [SECTORS_PER_CLUSTER] |
imul ebp, [BYTES_PER_SECTOR] |
push ecx |
; find the last cluster of file |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov ecx, [edi+28] |
jecxz .zero_size |
.last_loop: |
sub ecx, ebp |
jbe .last_found |
call get_FAT |
cmp [hd_error], 0 |
jz @f |
.device_err: |
pop ecx |
.device_err2: |
pop ebp |
push 11 |
.ret_err: |
pop eax |
stc |
ret |
@@: |
cmp eax, 2 |
jb .fat_err |
cmp eax, [fatRESERVED] |
jb .last_loop |
.fat_err: |
pop ecx ebp |
push ERROR_FAT_TABLE |
jmp .ret_err |
.last_found: |
push eax |
call get_FAT |
cmp [hd_error], 0 |
jz @f |
pop eax |
jmp .device_err |
@@: |
cmp eax, [fatRESERVED] |
pop eax |
jb .fat_err |
; set length to full number of clusters |
sub [edi+28], ecx |
.start_extend: |
pop ecx |
; now do extend |
push edx |
mov edx, 2 ; start scan from cluster 2 |
.extend_loop: |
cmp [edi+28], ecx |
jae .extend_done |
; add new cluster |
push eax |
call get_free_FAT |
jc .disk_full |
mov edx, [fatEND] |
call set_FAT |
mov edx, eax |
pop eax |
test eax, eax |
jz .first_cluster |
push edx |
call set_FAT |
pop edx |
jmp @f |
.first_cluster: |
ror edx, 16 |
mov [edi+20], dx |
ror edx, 16 |
mov [edi+26], dx |
@@: |
push ecx |
mov ecx, -1 |
call add_disk_free_space |
pop ecx |
mov eax, edx |
cmp [hd_error], 0 |
jnz .device_err3 |
add [edi+28], ebp |
jmp .extend_loop |
.extend_done: |
mov [edi+28], ecx |
pop edx ebp |
xor eax, eax ; CF=0 |
ret |
.device_err3: |
pop edx |
jmp .device_err2 |
.disk_full: |
pop eax edx ebp |
push ERROR_DISK_FULL |
pop eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: stc |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdSetFileEnd - set end of file on hard disk |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdSetFileEnd: |
cmp [fs_type], 1 |
jz ntfs_HdSetFileEnd |
cmp [fs_type], 2 |
jz ext2_HdSetFileEnd |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNKNOWN_FS |
.ret: |
pop eax |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .ret |
@@: |
push edi |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
push 11 |
jmp .ret |
@@: |
popfd |
jnc @f |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .ret |
@@: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
pop edi |
jmp .access_denied |
@@: |
; file size must not exceed 4 Gb |
cmp dword [ebx+4], 0 |
jz @f |
pop edi |
push ERROR_END_OF_FILE |
jmp .ret |
@@: |
push eax ; save directory sector |
; set file modification date/time to current |
call fat_update_datetime |
mov eax, [ebx] |
cmp eax, [edi+28] |
jb .truncate |
ja .expand |
pop eax |
mov ebx, buffer |
call hd_write |
pop edi |
xor eax, eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
.expand: |
push ebx ebp ecx |
push dword [edi+28] ; save old size |
mov ecx, eax |
call hd_extend_file |
push eax ; return code |
jnc .expand_ok |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
.pop_ret: |
call update_disk |
pop eax ecx ebp ebx ecx edi edi |
ret |
.expand_ok: |
.disk_full: |
; save directory |
mov eax, [edi+28] |
xchg eax, [esp+20] |
mov ebx, buffer |
call hd_write |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov edi, eax |
cmp [hd_error], 0 |
jz @f |
.pop_ret11: |
mov byte [esp], 11 |
jmp .pop_ret |
@@: |
; now zero new data |
xor ebp, ebp |
; edi=current cluster, ebp=sector in cluster |
; [esp+20]=new size, [esp+4]=old size, [esp]=return code |
.zero_loop: |
sub dword [esp+4], 0x200 |
jae .next_cluster |
lea eax, [edi-2] |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ebp |
cmp dword [esp+4], -0x200 |
jz .noread |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jnz .err_next |
.noread: |
mov ecx, [esp+4] |
neg ecx |
push edi |
mov edi, buffer+0x200 |
add edi, [esp+8] |
push eax |
xor eax, eax |
mov [esp+12], eax |
rep stosb |
pop eax |
pop edi |
call hd_write |
cmp [hd_error], 0 |
jz .next_cluster |
.err_next: |
mov byte [esp], 11 |
.next_cluster: |
sub dword [esp+20], 0x200 |
jbe .pop_ret |
inc ebp |
cmp ebp, [SECTORS_PER_CLUSTER] |
jb .zero_loop |
xor ebp, ebp |
mov eax, edi |
call get_FAT |
mov edi, eax |
cmp [hd_error], 0 |
jnz .pop_ret11 |
jmp .zero_loop |
.truncate: |
mov [edi+28], eax |
push ecx |
mov ecx, [edi+20-2] |
mov cx, [edi+26] |
push eax |
test eax, eax |
jz .zero_size |
; find new last cluster |
@@: |
mov eax, [SECTORS_PER_CLUSTER] |
shl eax, 9 |
sub [esp], eax |
jbe @f |
mov eax, ecx |
call get_FAT |
mov ecx, eax |
cmp [hd_error], 0 |
jz @b |
.device_err3: |
pop eax ecx eax edi |
push 11 |
pop eax |
ret |
@@: |
; we will zero data at the end of last sector - remember it |
push ecx |
; terminate FAT chain |
push edx |
mov eax, ecx |
mov edx, [fatEND] |
call set_FAT |
mov eax, edx |
pop edx |
cmp [hd_error], 0 |
jz @f |
.device_err4: |
pop ecx |
jmp .device_err3 |
.zero_size: |
and word [edi+20], 0 |
and word [edi+26], 0 |
push 0 |
mov eax, ecx |
@@: |
; delete FAT chain |
call clear_cluster_chain |
cmp [hd_error], 0 |
jnz .device_err4 |
; save directory |
mov eax, [esp+12] |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jnz .device_err4 |
; zero last sector, ignore errors |
pop ecx |
pop eax |
dec ecx |
imul ecx, [SECTORS_PER_CLUSTER] |
add ecx, [DATA_START] |
push eax |
sar eax, 9 |
add ecx, eax |
pop eax |
and eax, 0x1FF |
jz .truncate_done |
push ebx eax |
mov eax, ecx |
mov ebx, buffer |
call hd_read |
pop eax |
lea edi, [buffer+eax] |
push ecx |
mov ecx, 0x200 |
sub ecx, eax |
xor eax, eax |
rep stosb |
pop eax |
call hd_write |
pop ebx |
.truncate_done: |
pop ecx eax edi |
call update_disk |
xor eax, eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
fs_HdGetFileInfo: |
cmp [fs_type], 1 |
jz ntfs_HdGetFileInfo |
cmp [fs_type], 2 |
jz ext2_HdGetFileInfo |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 |
ret |
@@: |
push edi |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
pop edi |
mov eax, 11 |
ret |
@@: |
popfd |
jmp fs_GetFileInfo_finish |
fs_HdSetFileInfo: |
cmp [fs_type], 1 |
jz ntfs_HdSetFileInfo |
cmp [fs_type], 2 |
jz ext2_HdSetFileInfo |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 |
ret |
@@: |
push edi |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
pop edi |
mov eax, 11 |
ret |
@@: |
popfd |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
push eax |
call bdfe_to_fat_entry |
pop eax |
mov ebx, buffer |
call hd_write |
call update_disk |
pop edi |
xor eax, eax |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdDelete - delete file or empty folder from hard disk |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdDelete: |
cmp [fs_type], 1 |
jz ntfs_HdDelete |
cmp [fs_type], 2 |
jz ext2_HdDelete |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNKNOWN_FS |
.pop_ret: |
pop eax |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
; cannot delete root! |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .pop_ret |
@@: |
and [longname_sec1], 0 |
and [longname_sec2], 0 |
push edi |
call hd_find_lfn |
jnc .found |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .pop_ret |
.found: |
cmp dword [edi], '. ' |
jz .access_denied2 |
cmp dword [edi], '.. ' |
jz .access_denied2 |
test byte [edi+11], 10h |
jz .dodel |
; we can delete only empty folders! |
pushad |
mov ebp, [edi+20-2] |
mov bp, [edi+26] |
xor ecx, ecx |
lea eax, [ebp-2] |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jnz .err1 |
add ebx, 2*0x20 |
.checkempty: |
cmp byte [ebx], 0 |
jz .empty |
cmp byte [ebx], 0xE5 |
jnz .notempty |
add ebx, 0x20 |
cmp ebx, buffer+0x200 |
jb .checkempty |
inc ecx |
cmp ecx, [SECTORS_PER_CLUSTER] |
jb @f |
mov eax, ebp |
call get_FAT |
cmp [hd_error], 0 |
jnz .err1 |
mov ebp, eax |
xor ecx, ecx |
@@: |
lea eax, [ebp-2] |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ecx |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jz .checkempty |
.err1: |
popad |
.err2: |
pop edi |
push 11 |
pop eax |
ret |
.notempty: |
popad |
.access_denied2: |
pop edi |
push ERROR_ACCESS_DENIED |
pop eax |
ret |
.empty: |
popad |
push ebx |
mov ebx, buffer |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jnz .err2 |
.dodel: |
push eax |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
xchg eax, [esp] |
; delete folder entry |
mov byte [edi], 0xE5 |
; delete LFN (if present) |
.lfndel: |
cmp edi, buffer |
ja @f |
cmp [longname_sec2], 0 |
jz .lfndone |
push [longname_sec2] |
push [longname_sec1] |
pop [longname_sec2] |
and [longname_sec1], 0 |
push ebx |
mov ebx, buffer |
call hd_write |
mov eax, [esp+4] |
call hd_read |
pop ebx |
pop eax |
mov edi, buffer+0x200 |
@@: |
sub edi, 0x20 |
cmp byte [edi], 0xE5 |
jz .lfndone |
cmp byte [edi+11], 0xF |
jnz .lfndone |
mov byte [edi], 0xE5 |
jmp .lfndel |
.lfndone: |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
; delete FAT chain |
pop eax |
call clear_cluster_chain |
call update_disk |
pop edi |
xor eax, eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
; \end{diamond} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; FAT32.INC ;; |
;; ;; |
;; FAT16/32 functions for KolibriOS ;; |
;; ;; |
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; |
;; ;; |
;; See file COPYING for details ;; |
;; 04.02.2007 LFN create folder - diamond ;; |
;; 08.10.2006 LFN delete file/folder - diamond ;; |
;; 20.08.2006 LFN set file size (truncate/extend) - diamond ;; |
;; 17.08.2006 LFN write/append to file - diamond ;; |
;; 23.06.2006 LFN start application - diamond ;; |
;; 15.06.2006 LFN get/set file/folder info - diamond ;; |
;; 27.05.2006 LFN create/rewrite file - diamond ;; |
;; 04.05.2006 LFN read folder - diamond ;; |
;; 29.04.2006 Elimination of hangup after the ;; |
;; expiration hd_wait_timeout - Mario79 ;; |
;; 23.04.2006 LFN read file - diamond ;; |
;; 28.01.2006 find all Fat16/32 partition in all input point ;; |
;; to MBR, see file part_set.inc - Mario79 ;; |
;; 15.01.2005 get file size/attr/date, file_append - ATV ;; |
;; 04.12.2004 skip volume label, file delete bug fixed - ATV ;; |
;; 29.11.2004 get_free_FAT changed, append dir bug fixed - ATV ;; |
;; 23.11.2004 don't allow overwrite dir with file - ATV ;; |
;; 18.11.2004 get_disk_info and more error codes - ATV ;; |
;; 17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV ;; |
;; 10.11.2004 removedir clear whole directory structure - ATV ;; |
;; 08.11.2004 rename - ATV ;; |
;; 30.10.2004 file_read return also dirsize in bytes - ATV ;; |
;; 20.10.2004 Makedir/Removedir - ATV ;; |
;; 14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx) ;; |
;; 06.9.2004 Fix free space by Mario79 added - MH ;; |
;; 24.5.2004 Write back buffer for File_write -VT ;; |
;; 20.5.2004 File_read function to work with syscall 58 - VT ;; |
;; 30.3.2004 Error parameters at function return - VT ;; |
;; 01.5.2002 Bugfix in device write - VT ;; |
;; 20.5.2002 Hd status check - VT ;; |
;; 29.6.2002 Improved fat32 verification - VT ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
cache_max equ 1919 ; max. is 1919*512+0x610000=0x6ffe00 |
ERROR_SUCCESS = 0 |
ERROR_DISK_BASE = 1 |
ERROR_UNSUPPORTED_FS = 2 |
ERROR_UNKNOWN_FS = 3 |
ERROR_PARTITION = 4 |
ERROR_FILE_NOT_FOUND = 5 |
ERROR_END_OF_FILE = 6 |
ERROR_MEMORY_POINTER = 7 |
ERROR_DISK_FULL = 8 |
ERROR_FAT_TABLE = 9 |
ERROR_ACCESS_DENIED = 10 |
ERROR_DEVICE = 11 |
PUSHAD_EAX equ [esp+28] |
PUSHAD_ECX equ [esp+24] |
PUSHAD_EDX equ [esp+20] |
PUSHAD_EBX equ [esp+16] |
PUSHAD_EBP equ [esp+8] |
PUSHAD_ESI equ [esp+4] |
PUSHAD_EDI equ [esp+0] |
uglobal |
align 4 |
partition_count dd 0 ; partitions found by set_FAT32_variables |
longname_sec1 dd 0 ; used by analyze_directory to save 2 previous |
longname_sec2 dd 0 ; directory sectors for delete long filename |
hd_error dd 0 ; set by wait_for_sector_buffer |
hd_setup dd 0 |
hd_wait_timeout dd 0 |
cluster_tmp dd 0 ; used by analyze_directory |
; and analyze_directory_to_write |
file_size dd 0 ; used by file_read |
cache_search_start dd 0 ; used by find_empty_slot |
endg |
iglobal |
fat_in_cache dd -1 |
endg |
uglobal |
align 4 |
fat_cache: |
times 512 db 0 |
Sector512: ; label for dev_hdcd.inc |
buffer: |
times 512 db 0 |
fsinfo_buffer: |
times 512 db 0 |
endg |
uglobal |
fat16_root db 0 ; flag for fat16 rootdir |
fat_change db 0 ; 1=fat has changed |
endg |
reserve_hd1: |
cli |
cmp [hd1_status], 0 |
je reserve_ok1 |
sti |
call change_task |
jmp reserve_hd1 |
reserve_ok1: |
push eax |
mov eax, [CURRENT_TASK] |
shl eax, 5 |
mov eax, [eax+CURRENT_TASK+TASKDATA.pid] |
mov [hd1_status], eax |
pop eax |
sti |
ret |
;******************************************** |
uglobal |
hd_in_cache db ? |
endg |
reserve_hd_channel: |
; BIOS disk accesses are protected with common mutex hd1_status |
; This must be modified when hd1_status will not be valid! |
cmp [hdpos], 0x80 |
jae .ret |
cmp [hdbase], 0x1F0 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
cli |
cmp [IDE_Channel_1], 0 |
je .reserve_ok_1 |
sti |
call change_task |
jmp .IDE_Channel_1 |
.IDE_Channel_2: |
cli |
cmp [IDE_Channel_2], 0 |
je .reserve_ok_2 |
sti |
call change_task |
jmp .IDE_Channel_2 |
.reserve_ok_1: |
mov [IDE_Channel_1], 1 |
push eax |
mov al, 1 |
jmp @f |
.reserve_ok_2: |
mov [IDE_Channel_2], 1 |
push eax |
mov al, 3 |
@@: |
cmp [hdid], 1 |
sbb al, -1 |
cmp al, [hd_in_cache] |
jz @f |
mov [hd_in_cache], al |
call clear_hd_cache |
@@: |
pop eax |
sti |
.ret: |
ret |
free_hd_channel: |
; see comment at reserve_hd_channel |
cmp [hdpos], 0x80 |
jae .ret |
cmp [hdbase], 0x1F0 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
mov [IDE_Channel_1], 0 |
.ret: |
ret |
.IDE_Channel_2: |
mov [IDE_Channel_2], 0 |
ret |
;******************************************** |
problem_partition db 0 ; used for partitions search |
include 'part_set.inc' |
set_FAT: |
;-------------------------------- |
; input : EAX = cluster |
; EDX = value to save |
; output : EDX = old value |
;-------------------------------- |
push eax ebx esi |
cmp eax, 2 |
jb sfc_error |
cmp eax, [LAST_CLUSTER] |
ja sfc_error |
cmp [fs_type], 16 |
je sfc_1 |
add eax, eax |
sfc_1: |
add eax, eax |
mov esi, 511 |
and esi, eax ; esi = position in fat sector |
shr eax, 9 ; eax = fat sector |
add eax, [FAT_START] |
mov ebx, fat_cache |
cmp eax, [fat_in_cache]; is fat sector already in memory? |
je sfc_in_cache ; yes |
cmp [fat_change], 0 ; is fat changed? |
je sfc_no_change ; no |
call write_fat_sector; yes. write it into disk |
cmp [hd_error], 0 |
jne sfc_error |
sfc_no_change: |
mov [fat_in_cache], eax; save fat sector |
call hd_read |
cmp [hd_error], 0 |
jne sfc_error |
sfc_in_cache: |
cmp [fs_type], 16 |
jne sfc_test32 |
sfc_set16: |
xchg [ebx+esi], dx ; save new value and get old value |
jmp sfc_write |
sfc_test32: |
mov eax, [fatMASK] |
sfc_set32: |
and edx, eax |
xor eax, -1 ; mask for high bits |
and eax, [ebx+esi] ; get high 4 bits |
or eax, edx |
mov edx, [ebx+esi] ; get old value |
mov [ebx+esi], eax ; save new value |
sfc_write: |
mov [fat_change], 1 ; fat has changed |
sfc_nonzero: |
and edx, [fatMASK] |
sfc_error: |
pop esi ebx eax |
ret |
get_FAT: |
;-------------------------------- |
; input : EAX = cluster |
; output : EAX = next cluster |
;-------------------------------- |
push ebx esi |
cmp [fs_type], 16 |
je gfc_1 |
add eax, eax |
gfc_1: |
add eax, eax |
mov esi, 511 |
and esi, eax ; esi = position in fat sector |
shr eax, 9 ; eax = fat sector |
add eax, [FAT_START] |
mov ebx, fat_cache |
cmp eax, [fat_in_cache]; is fat sector already in memory? |
je gfc_in_cache |
cmp [fat_change], 0 ; is fat changed? |
je gfc_no_change ; no |
call write_fat_sector; yes. write it into disk |
cmp [hd_error], 0 |
jne hd_error_01 |
gfc_no_change: |
mov [fat_in_cache], eax |
call hd_read |
cmp [hd_error], 0 |
jne hd_error_01 |
gfc_in_cache: |
mov eax, [ebx+esi] |
and eax, [fatMASK] |
hd_error_01: |
pop esi ebx |
ret |
get_free_FAT: |
;----------------------------------------------------------- |
; output : if CARRY=0 EAX = # first cluster found free |
; if CARRY=1 disk full |
; Note : for more speed need to use fat_cache directly |
;----------------------------------------------------------- |
push ecx |
mov ecx, [LAST_CLUSTER]; counter for full disk |
sub ecx, 2 |
mov eax, [fatStartScan] |
cmp eax, 2 |
jb gff_reset |
gff_test: |
cmp eax, [LAST_CLUSTER]; if above last cluster start at cluster 2 |
jbe gff_in_range |
gff_reset: |
mov eax, 2 |
gff_in_range: |
push eax |
call get_FAT ; get cluster state |
cmp [hd_error], 0 |
jne gff_not_found_1 |
test eax, eax ; is it free? |
pop eax |
je gff_found ; yes |
inc eax ; next cluster |
dec ecx ; is all checked? |
jns gff_test ; no |
gff_not_found_1: |
add esp, 4 |
gff_not_found: |
pop ecx ; yes. disk is full |
stc |
ret |
gff_found: |
lea ecx, [eax+1] |
mov [fatStartScan], ecx |
pop ecx |
clc |
ret |
write_fat_sector: |
;----------------------------------------------------------- |
; write changed fat to disk |
;----------------------------------------------------------- |
push eax ebx ecx |
mov [fat_change], 0 |
mov eax, [fat_in_cache] |
cmp eax, -1 |
jz write_fat_not_used |
mov ebx, fat_cache |
mov ecx, [NUMBER_OF_FATS] |
write_next_fat: |
call hd_write |
cmp [hd_error], 0 |
jne write_fat_not_used |
add eax, [SECTORS_PER_FAT] |
dec ecx |
jnz write_next_fat |
write_fat_not_used: |
pop ecx ebx eax |
ret |
analyze_directory: |
;----------------------------------------------------------- |
; input : EAX = first cluster of the directory |
; EBX = pointer to filename |
; output : IF CARRY=0 EAX = sector where th file is found |
; EBX = pointer in buffer |
; [buffer .. buffer+511] |
; ECX,EDX,ESI,EDI not changed |
; IF CARRY=1 filename not found |
; Note : if cluster=0 it's changed to read rootdir |
; save 2 previous directory sectors in longname_sec |
;----------------------------------------------------------- |
push ecx edx esi edi ebx; ebx = [esp+0] |
mov [longname_sec1], 0 |
mov [longname_sec2], 0 |
adr_new_cluster: |
mov [cluster_tmp], eax |
mov [fat16_root], 0 |
cmp eax, [LAST_CLUSTER] |
ja adr_not_found ; too big cluster number, something is wrong |
cmp eax, 2 |
jnb adr_data_cluster |
mov eax, [ROOT_CLUSTER]; if cluster < 2 then read rootdir |
cmp [fs_type], 16 |
jne adr_data_cluster |
mov eax, [ROOT_START] |
mov edx, [ROOT_SECTORS] |
mov [fat16_root], 1 ; flag for fat16 rootdir |
jmp adr_new_sector |
adr_data_cluster: |
sub eax, 2 |
mov edx, [SECTORS_PER_CLUSTER] |
imul eax, edx |
add eax, [DATA_START] |
adr_new_sector: |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jne adr_not_found |
mov ecx, 512/32 ; count of dir entrys per sector = 16 |
adr_analyze: |
mov edi, [ebx+11] ; file attribute |
and edi, 0xf |
cmp edi, 0xf |
je adr_long_filename |
test edi, 0x8 ; skip over volume label |
jne adr_long_filename; Note: label can be same name as file/dir |
mov esi, [esp+0] ; filename need to be uppercase |
mov edi, ebx |
push ecx |
mov ecx, 11 |
cld |
rep cmpsb ; compare 8+3 filename |
pop ecx |
je adr_found |
adr_long_filename: |
add ebx, 32 ; position of next dir entry |
dec ecx |
jnz adr_analyze |
mov ecx, [longname_sec1]; save 2 previous directory sectors |
mov [longname_sec1], eax; for delete long filename |
mov [longname_sec2], ecx |
inc eax ; next sector |
dec edx |
jne adr_new_sector |
cmp [fat16_root], 1 ; end of fat16 rootdir |
je adr_not_found |
adr_next_cluster: |
mov eax, [cluster_tmp] |
call get_FAT ; get next cluster |
cmp [hd_error], 0 |
jne adr_not_found |
cmp eax, 2 ; incorrect fat chain? |
jb adr_not_found ; yes |
cmp eax, [fatRESERVED]; is it end of directory? |
jb adr_new_cluster ; no. analyse it |
adr_not_found: |
pop edi edi esi edx ecx; first edi will remove ebx |
stc ; file not found |
ret |
adr_found: |
pop edi edi esi edx ecx; first edi will remove ebx |
clc ; file found |
ret |
get_data_cluster: |
;----------------------------------------------------------- |
; input : EAX = cluster |
; EBX = pointer to buffer |
; EDX = # blocks to read in buffer |
; ESI = # blocks to skip over |
; output : if CARRY=0 ok EBX/EDX/ESI updated |
; if CARRY=1 cluster out of range |
; Note : if cluster=0 it's changed to read rootdir |
;----------------------------------------------------------- |
push eax ecx |
mov [fat16_root], 0 |
cmp eax, [LAST_CLUSTER] |
ja gdc_error ; too big cluster number, something is wrong |
cmp eax, 2 |
jnb gdc_cluster |
mov eax, [ROOT_CLUSTER]; if cluster < 2 then read rootdir |
cmp [fs_type], 16 |
jne gdc_cluster |
mov eax, [ROOT_START] |
mov ecx, [ROOT_SECTORS]; Note: not cluster size |
mov [fat16_root], 1 ; flag for fat16 rootdir |
jmp gdc_read |
gdc_cluster: |
sub eax, 2 |
mov ecx, [SECTORS_PER_CLUSTER] |
imul eax, ecx |
add eax, [DATA_START] |
gdc_read: |
test esi, esi ; first wanted block |
je gdcl1 ; yes, skip count is 0 |
dec esi |
jmp gdcl2 |
gdcl1: |
call hd_read |
cmp [hd_error], 0 |
jne gdc_error |
add ebx, 512 ; update pointer |
dec edx |
gdcl2: |
test edx, edx ; is all read? |
je out_of_read |
inc eax ; next sector |
dec ecx |
jnz gdc_read |
out_of_read: |
pop ecx eax |
clc |
ret |
gdc_error: |
pop ecx eax |
stc |
ret |
get_cluster_of_a_path: |
;--------------------------------------------------------- |
; input : EBX = pointer to a path string |
; (example: the path "/files/data/document" become |
; "files......data.......document...0" |
; '.' = space char |
; '0' = char(0) (ASCII=0) !!! ) |
; output : if (CARRY=1) -> ERROR in the PATH |
; if (CARRY=0) -> EAX=cluster |
;--------------------------------------------------------- |
push ebx edx |
mov eax, [ROOT_CLUSTER] |
mov edx, ebx |
search_end_of_path: |
cmp byte [edx], 0 |
je found_end_of_path |
inc edx; '/' |
mov ebx, edx |
call analyze_directory |
jc directory_not_found |
mov eax, [ebx+20-2] ; read the HIGH 16bit cluster field |
mov ax, [ebx+26] ; read the LOW 16bit cluster field |
and eax, [fatMASK] |
add edx, 11 ; 8+3 (name+extension) |
jmp search_end_of_path |
found_end_of_path: |
pop edx ebx |
clc ; no errors |
ret |
directory_not_found: |
pop edx ebx |
stc ; errors occour |
ret |
bcd2bin: |
;---------------------------------- |
; input : AL=BCD number (eg. 0x11) |
; output : AH=0 |
; AL=decimal number (eg. 11) |
;---------------------------------- |
xor ah, ah |
shl ax, 4 |
shr al, 4 |
aad |
ret |
get_date_for_file: |
;----------------------------------------------------- |
; Get date from CMOS and pack day,month,year in AX |
; DATE bits 0..4 : day of month 0..31 |
; 5..8 : month of year 1..12 |
; 9..15 : count of years from 1980 |
;----------------------------------------------------- |
mov al, 0x7 ;day |
out 0x70, al |
in al, 0x71 |
call bcd2bin |
ror eax, 5 |
mov al, 0x8 ;month |
out 0x70, al |
in al, 0x71 |
call bcd2bin |
ror eax, 4 |
mov al, 0x9 ;year |
out 0x70, al |
in al, 0x71 |
call bcd2bin |
add ax, 20 ;because CMOS return only the two last |
;digit (eg. 2000 -> 00 , 2001 -> 01) and we |
rol eax, 9 ;need the difference with 1980 (eg. 2001-1980) |
ret |
get_time_for_file: |
;----------------------------------------------------- |
; Get time from CMOS and pack hour,minute,second in AX |
; TIME bits 0..4 : second (the low bit is lost) |
; 5..10 : minute 0..59 |
; 11..15 : hour 0..23 |
;----------------------------------------------------- |
mov al, 0x0 ;second |
out 0x70, al |
in al, 0x71 |
call bcd2bin |
ror eax, 6 |
mov al, 0x2 ;minute |
out 0x70, al |
in al, 0x71 |
call bcd2bin |
ror eax, 6 |
mov al, 0x4 ;hour |
out 0x70, al |
in al, 0x71 |
call bcd2bin |
rol eax, 11 |
ret |
set_current_time_for_entry: |
;----------------------------------------------------- |
; Set current time/date for file entry |
; input : ebx = file entry pointer |
;----------------------------------------------------- |
push eax |
call get_time_for_file; update files date/time |
mov [ebx+22], ax |
call get_date_for_file |
mov [ebx+24], ax |
pop eax |
ret |
add_disk_free_space: |
;----------------------------------------------------- |
; input : ecx = cluster count |
; Note : negative = remove clusters from free space |
; positive = add clusters to free space |
;----------------------------------------------------- |
test ecx, ecx ; no change |
je add_dfs_no |
cmp [fs_type], 32 ; free disk space only used by fat32 |
jne add_dfs_no |
push eax ebx |
mov eax, [ADR_FSINFO] |
mov ebx, fsinfo_buffer |
call hd_read |
cmp [hd_error], 0 |
jne add_not_fs |
cmp dword [ebx+0x1fc], 0xaa550000; check sector id |
jne add_not_fs |
add [ebx+0x1e8], ecx |
push [fatStartScan] |
pop dword [ebx+0x1ec] |
call hd_write |
; cmp [hd_error],0 |
; jne add_not_fs |
add_not_fs: |
pop ebx eax |
add_dfs_no: |
ret |
file_read: |
;-------------------------------------------------------------------------- |
; INPUT : user-register register-in-this meaning symbol-in-this |
; |
; EAX EDI system call to write / |
; EBX EAX (PAR0) pointer to file-name PAR0 |
; EDX ECX (PAR1) pointer to buffer PAR1 |
; ECX EBX (PAR2) vt file blocks to read PAR2 |
; ESI EDX (PAR3) pointer to path PAR3 |
; EDI ESI vt first 512 block to read |
; EDI if 0 - read root |
; |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 6 - end of file |
; 9 - fat table corrupted |
; 10 - access denied |
; ebx = size of file/directory |
;-------------------------------------------------------------------------- |
cmp [fs_type], 16 |
jz fat_ok_for_reading |
cmp [fs_type], 32 |
jz fat_ok_for_reading |
xor ebx, ebx |
mov eax, ERROR_UNKNOWN_FS |
mov [hd1_status], ebx |
ret |
fat_ok_for_reading: |
; call reserve_hd1 |
pushad |
mov ebx, edx |
call get_cluster_of_a_path |
jc file_to_read_not_found |
test edi, edi ; read rootdir |
jne no_read_root |
xor eax, eax |
call get_dir_size ; return rootdir size |
cmp [hd_error], 0 |
jne file_access_denied |
mov [file_size], eax |
mov eax, [ROOT_CLUSTER] |
jmp file_read_start |
no_read_root: |
mov ebx, PUSHAD_EAX ; file name |
call analyze_directory |
jc file_to_read_not_found |
mov eax, [ebx+28] ; file size |
test byte [ebx+11], 0x10; is it directory? |
jz read_set_size ; no |
mov eax, [ebx+20-2] ; FAT entry |
mov ax, [ebx+26] |
and eax, [fatMASK] |
call get_dir_size |
cmp [hd_error], 0 |
jne file_access_denied |
read_set_size: |
mov [file_size], eax |
mov eax, [ebx+20-2] ; FAT entry |
mov ax, [ebx+26] |
and eax, [fatMASK] |
file_read_start: |
mov ebx, PUSHAD_ECX ; pointer to buffer |
mov edx, PUSHAD_EBX ; file blocks to read |
mov esi, PUSHAD_ESI ; first 512 block to read |
file_read_new_cluster: |
call get_data_cluster |
jc file_read_eof ; end of file or cluster out of range |
test edx, edx ; is all read? |
je file_read_OK ; yes |
call get_FAT ; get next cluster |
cmp [hd_error], 0 |
jne file_access_denied |
cmp eax, [fatRESERVED]; end of file |
jnb file_read_eof |
cmp eax, 2 ; incorrect fat chain |
jnb file_read_new_cluster |
popad |
mov [hd1_status], 0 |
mov ebx, [file_size] |
mov eax, ERROR_FAT_TABLE |
ret |
file_read_eof: |
cmp [hd_error], 0 |
jne file_access_denied |
popad |
mov [hd1_status], 0 |
mov ebx, [file_size] |
mov eax, ERROR_END_OF_FILE |
ret |
file_read_OK: |
popad |
mov [hd1_status], 0 |
mov ebx, [file_size] |
xor eax, eax |
ret |
file_to_read_not_found: |
cmp [hd_error], 0 |
jne file_access_denied |
popad |
mov [hd1_status], 0 |
xor ebx, ebx |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
file_access_denied: |
popad |
mov [hd1_status], 0 |
xor ebx, ebx |
mov eax, ERROR_ACCESS_DENIED |
ret |
get_dir_size: |
;----------------------------------------------------- |
; input : eax = first cluster (0=rootdir) |
; output : eax = directory size in bytes |
;----------------------------------------------------- |
push edx |
xor edx, edx ; count of directory clusters |
test eax, eax |
jnz dir_size_next |
mov eax, [ROOT_SECTORS] |
shl eax, 9 ; fat16 rootdir size in bytes |
cmp [fs_type], 16 |
je dir_size_ret |
mov eax, [ROOT_CLUSTER] |
dir_size_next: |
cmp eax, 2 ; incorrect fat chain |
jb dir_size_end |
cmp eax, [fatRESERVED]; end of directory |
ja dir_size_end |
call get_FAT ; get next cluster |
cmp [hd_error], 0 |
jne dir_size_ret |
inc edx |
jmp dir_size_next |
dir_size_end: |
imul eax, [SECTORS_PER_CLUSTER], 512; cluster size in bytes |
imul eax, edx |
dir_size_ret: |
pop edx |
ret |
clear_cluster_chain: |
;----------------------------------------------------- |
; input : eax = first cluster |
;----------------------------------------------------- |
push eax ecx edx |
xor ecx, ecx ; cluster count |
clean_new_chain: |
cmp eax, [LAST_CLUSTER]; end of file |
ja delete_OK |
cmp eax, 2 ; unfinished fat chain or zero length file |
jb delete_OK |
cmp eax, [ROOT_CLUSTER]; don't remove root cluster |
jz delete_OK |
xor edx, edx |
call set_FAT ; clear fat entry |
cmp [hd_error], 0 |
jne access_denied_01 |
inc ecx ; update cluster count |
mov eax, edx ; old cluster |
jmp clean_new_chain |
delete_OK: |
call add_disk_free_space; add clusters to free disk space |
access_denied_01: |
pop edx ecx eax |
ret |
get_hd_info: |
;----------------------------------------------------------- |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 10 - access denied |
; edx = cluster size in bytes |
; ebx = total clusters on disk |
; ecx = free clusters on disk |
;----------------------------------------------------------- |
cmp [fs_type], 16 |
jz info_fat_ok |
cmp [fs_type], 32 |
jz info_fat_ok |
xor edx, edx |
xor ebx, ebx |
xor ecx, ecx |
mov eax, ERROR_UNKNOWN_FS |
ret |
info_fat_ok: |
; call reserve_hd1 |
xor ecx, ecx ; count of free clusters |
mov eax, 2 |
mov ebx, [LAST_CLUSTER] |
info_cluster: |
push eax |
call get_FAT ; get cluster info |
cmp [hd_error], 0 |
jne info_access_denied |
test eax, eax ; is it free? |
jnz info_used ; no |
inc ecx |
info_used: |
pop eax |
inc eax |
cmp eax, ebx ; is above last cluster? |
jbe info_cluster ; no. test next cluster |
dec ebx ; cluster count |
imul edx, [SECTORS_PER_CLUSTER], 512; cluster size in bytes |
mov [hd1_status], 0 |
xor eax, eax |
ret |
info_access_denied: |
add esp, 4 |
xor edx, edx |
xor ebx, ebx |
xor ecx, ecx |
mov eax, ERROR_ACCESS_DENIED |
ret |
update_disk: |
;----------------------------------------------------------- |
; write changed fat and cache to disk |
;----------------------------------------------------------- |
cmp [fat_change], 0 ; is fat changed? |
je upd_no_change |
call write_fat_sector |
cmp [hd_error], 0 |
jne update_disk_acces_denied |
upd_no_change: |
call write_cache |
update_disk_acces_denied: |
ret |
; \begin{diamond} |
hd_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and edi->direntry, eax=sector |
; destroys eax |
push esi edi |
push 0 |
push 0 |
push fat16_root_first |
push fat16_root_next |
mov eax, [ROOT_CLUSTER] |
cmp [fs_type], 32 |
jz .fat32 |
.loop: |
call fat_find_lfn |
jc .notfound |
cmp byte [esi], 0 |
jz .found |
.continue: |
test byte [edi+11], 10h |
jz .notfound |
and dword [esp+12], 0 |
mov eax, [edi+20-2] |
mov ax, [edi+26] ; cluster |
.fat32: |
mov [esp+8], eax |
mov dword [esp+4], fat_notroot_first |
mov dword [esp], fat_notroot_next |
jmp .loop |
.notfound: |
add esp, 16 |
pop edi esi |
stc |
ret |
.found: |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .continue |
@@: |
lea eax, [esp+8] |
cmp dword [eax], 0 |
jz .root |
call fat_get_sector |
jmp .cmn |
.root: |
mov eax, [eax+4] |
add eax, [ROOT_START] |
.cmn: |
add esp, 20 ; CF=0 |
pop esi |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdRead - LFN variant for reading hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdRead: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdRead |
cmp [fs_type], 2 |
jz ext2_HdRead |
or ebx, -1 |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
push edi |
cmp byte [esi], 0 |
jnz @f |
.noaccess: |
pop edi |
.noaccess_2: |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
@@: |
call hd_find_lfn |
jnc .found |
pop edi |
cmp [hd_error], 0 |
jne .noaccess_2 |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10; 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 |
pop edi |
ret |
@@: |
mov ebx, [ebx] |
.l1: |
push ecx edx |
push 0 |
mov eax, [edi+28] |
sub eax, ebx |
jb .eof |
cmp eax, ecx |
jae @f |
mov ecx, eax |
mov byte [esp], 6 |
@@: |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data |
.new_cluster: |
jecxz .new_sector |
test eax, eax |
jz .eof |
cmp eax, [fatRESERVED] |
jae .eof |
mov [cluster_tmp], eax |
dec eax |
dec eax |
mov edi, [SECTORS_PER_CLUSTER] |
imul eax, edi |
add eax, [DATA_START] |
.new_sector: |
test ecx, ecx |
jz .done |
sub ebx, 512 |
jae .skip |
add ebx, 512 |
jnz .force_buf |
cmp ecx, 512 |
jb .force_buf |
; we may read directly to given buffer |
push ebx |
mov ebx, edx |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jne .noaccess_1 |
add edx, 512 |
sub ecx, 512 |
jmp .skip |
.force_buf: |
; we must read sector to temporary buffer and then copy it to destination |
push eax ebx |
mov ebx, buffer |
call hd_read |
mov eax, ebx |
pop ebx |
cmp [hd_error], 0 |
jne .noaccess_3 |
add eax, ebx |
push ecx |
add ecx, ebx |
cmp ecx, 512 |
jbe @f |
mov ecx, 512 |
@@: |
sub ecx, ebx |
mov ebx, edx |
call memmove |
add edx, ecx |
sub [esp], ecx |
pop ecx |
pop eax |
xor ebx, ebx |
.skip: |
inc eax |
dec edi |
jnz .new_sector |
mov eax, [cluster_tmp] |
call get_FAT |
cmp [hd_error], 0 |
jne .noaccess_1 |
jmp .new_cluster |
.noaccess_3: |
pop eax |
.noaccess_1: |
pop eax |
push 11 |
.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_HdReadFolder - LFN variant for reading hard disk folder |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdReadFolder: |
cmp [fs_type], 1 |
jz ntfs_HdReadFolder |
cmp [fs_type], 2 |
jz ext2_HdReadFolder |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNSUPPORTED_FS |
pop eax |
or ebx, -1 |
ret |
@@: |
mov eax, [ROOT_CLUSTER] |
push edi |
cmp byte [esi], 0 |
jz .doit |
call hd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 ; do not allow read files |
jnz .found_dir |
pop edi |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
mov eax, [edi+20-2] |
mov ax, [edi+26] ; eax=cluster |
.doit: |
push esi ecx |
push ebp |
sub esp, 262*2 ; reserve space for LFN |
mov ebp, esp |
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE name |
mov ebx, [ebx] |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
pop ecx eax |
mov byte [edx], 1 ; version |
mov esi, edi ; esi points to BDFE |
.new_cluster: |
mov [cluster_tmp], eax |
test eax, eax |
jnz @f |
cmp [fs_type], 32 |
jz .notfound |
mov eax, [ROOT_START] |
push [ROOT_SECTORS] |
push ebx |
jmp .new_sector |
@@: |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
push [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
push ebx |
.new_sector: |
mov ebx, buffer |
mov edi, ebx |
call hd_read |
cmp [hd_error], 0 |
jnz .notfound2 |
add ebx, 512 |
push eax |
.l1: |
call fat_get_name |
jc .l2 |
cmp byte [edi+11], 0xF |
jnz .do_bdfe |
add edi, 0x20 |
cmp edi, ebx |
jb .do_bdfe |
pop eax |
inc eax |
dec dword [esp+4] |
jnz @f |
mov eax, [cluster_tmp] |
test eax, eax |
jz .done |
call get_FAT |
cmp [hd_error], 0 |
jnz .notfound2 |
cmp eax, 2 |
jb .done |
cmp eax, [fatRESERVED] |
jae .done |
push eax |
mov eax, [SECTORS_PER_CLUSTER] |
mov [esp+8], eax |
pop eax |
mov [cluster_tmp], eax |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
@@: |
mov ebx, buffer |
mov edi, ebx |
call hd_read |
cmp [hd_error], 0 |
jnz .notfound2 |
add ebx, 512 |
push eax |
.do_bdfe: |
inc dword [edx+8] ; new file found |
dec dword [esp+4] |
jns .l2 |
dec ecx |
js .l2 |
inc dword [edx+4] ; new file block copied |
call fat_entry_to_bdfe |
.l2: |
add edi, 0x20 |
cmp edi, ebx |
jb .l1 |
pop eax |
inc eax |
dec dword [esp+4] |
jnz .new_sector |
mov eax, [cluster_tmp] |
test eax, eax |
jz .done |
call get_FAT |
cmp [hd_error], 0 |
jnz .notfound2 |
cmp eax, 2 |
jb .done |
cmp eax, [fatRESERVED] |
jae .done |
push eax |
mov eax, [SECTORS_PER_CLUSTER] |
mov [esp+8], eax |
pop eax |
pop ebx |
add esp, 4 |
jmp .new_cluster |
.notfound2: |
add esp, 8 |
.notfound: |
add esp, 262*2+4 |
pop ebp ecx esi edi |
mov eax, ERROR_FILE_NOT_FOUND |
or ebx, -1 |
ret |
.done: |
add esp, 262*2+4+8 |
pop ebp |
mov ebx, [edx+4] |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
pop ecx esi edi |
ret |
fat16_root_next: |
cmp edi, buffer+0x200-0x20 |
jae fat16_root_next_sector |
add edi, 0x20 |
ret ; CF=0 |
fat16_root_next_sector: |
; read next sector |
push [longname_sec2] |
pop [longname_sec1] |
push ecx |
mov ecx, [eax+4] |
push ecx |
add ecx, [ROOT_START] |
mov [longname_sec2], ecx |
pop ecx |
inc ecx |
mov [eax+4], ecx |
cmp ecx, [ROOT_SECTORS] |
pop ecx |
jae fat16_root_first.readerr |
fat16_root_first: |
mov eax, [eax+4] |
add eax, [ROOT_START] |
push ebx |
mov edi, buffer |
mov ebx, edi |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jnz .readerr |
ret ; CF=0 |
.readerr: |
stc |
ret |
fat16_root_begin_write: |
push edi eax |
call fat16_root_first |
pop eax edi |
ret |
fat16_root_end_write: |
pusha |
mov eax, [eax+4] |
add eax, [ROOT_START] |
mov ebx, buffer |
call hd_write |
popa |
ret |
fat16_root_next_write: |
cmp edi, buffer+0x200 |
jae @f |
ret |
@@: |
call fat16_root_end_write |
jmp fat16_root_next_sector |
fat16_root_extend_dir: |
stc |
ret |
fat_notroot_next: |
cmp edi, buffer+0x200-0x20 |
jae fat_notroot_next_sector |
add edi, 0x20 |
ret ; CF=0 |
fat_notroot_next_sector: |
push [longname_sec2] |
pop [longname_sec1] |
push eax |
call fat_get_sector |
mov [longname_sec2], eax |
pop eax |
push ecx |
mov ecx, [eax+4] |
inc ecx |
cmp ecx, [SECTORS_PER_CLUSTER] |
jae fat_notroot_next_cluster |
mov [eax+4], ecx |
jmp @f |
fat_notroot_next_cluster: |
push eax |
mov eax, [eax] |
call get_FAT |
mov ecx, eax |
pop eax |
cmp [hd_error], 0 |
jnz fat_notroot_next_err |
cmp ecx, [fatRESERVED] |
jae fat_notroot_next_err |
mov [eax], ecx |
and dword [eax+4], 0 |
@@: |
pop ecx |
fat_notroot_first: |
call fat_get_sector |
push ebx |
mov edi, buffer |
mov ebx, edi |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jnz @f |
ret ; CF=0 |
fat_notroot_next_err: |
pop ecx |
@@: |
stc |
ret |
fat_notroot_begin_write: |
push eax edi |
call fat_notroot_first |
pop edi eax |
ret |
fat_notroot_end_write: |
call fat_get_sector |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
ret |
fat_notroot_next_write: |
cmp edi, buffer+0x200 |
jae @f |
ret |
@@: |
push eax |
call fat_notroot_end_write |
pop eax |
jmp fat_notroot_next_sector |
fat_notroot_extend_dir: |
push eax |
call get_free_FAT |
jnc .found |
pop eax |
ret ; CF=1 |
.found: |
push edx |
mov edx, [fatEND] |
call set_FAT |
mov edx, eax |
mov eax, [esp+4] |
mov eax, [eax] |
push edx |
call set_FAT |
pop edx |
cmp [hd_error], 0 |
jz @f |
pop edx |
pop eax |
stc |
ret |
@@: |
push ecx |
or ecx, -1 |
call add_disk_free_space |
; zero new cluster |
mov ecx, 512/4 |
mov edi, buffer |
push edi |
xor eax, eax |
rep stosd |
pop edi |
pop ecx |
mov eax, [esp+4] |
mov [eax], edx |
and dword [eax+4], 0 |
pop edx |
mov eax, [eax] |
dec eax |
dec eax |
push ebx ecx |
mov ecx, [SECTORS_PER_CLUSTER] |
imul eax, ecx |
add eax, [DATA_START] |
mov ebx, edi |
@@: |
call hd_write |
inc eax |
loop @b |
pop ecx ebx eax |
clc |
ret |
fat_get_sector: |
push ecx |
mov ecx, [eax] |
dec ecx |
dec ecx |
imul ecx, [SECTORS_PER_CLUSTER] |
add ecx, [DATA_START] |
add ecx, [eax+4] |
mov eax, ecx |
pop ecx |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdRewrite - LFN variant for writing hard disk |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fshrad: |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
fshrfs: |
mov eax, ERROR_UNKNOWN_FS |
xor ebx, ebx |
ret |
fs_HdCreateFolder: |
mov al, 1 |
jmp fs_HdRewrite.common |
fs_HdRewrite: |
xor eax, eax |
.common: |
cmp [fs_type], 1 |
jz ntfs_HdRewrite |
cmp [fs_type], 2 |
jz ext2_HdRewrite |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jnz fshrfs |
@@: |
cmp byte [esi], 0 |
jz fshrad |
pushad |
xor edi, edi |
push esi |
test ebp, ebp |
jz @f |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
lea edi, [esi-1] |
jmp @b |
@@: |
pop esi |
test edi, edi |
jnz .noroot |
test ebp, ebp |
jnz .hasebp |
mov ebp, [ROOT_CLUSTER] |
cmp [fs_type], 32 |
jz .pushnotroot |
push fat16_root_extend_dir |
push fat16_root_end_write |
push fat16_root_next_write |
push fat16_root_begin_write |
xor ebp, ebp |
push ebp |
push ebp |
push fat16_root_first |
push fat16_root_next |
jmp .common1 |
.hasebp: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [ebp], 0 |
jz .ret1 |
push ebp |
xor ebp, ebp |
call hd_find_lfn |
pop esi |
jc .notfound0 |
jmp .common0 |
.noroot: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [edi+1], 0 |
jz .ret1 |
; check existence |
mov byte [edi], 0 |
push edi |
call hd_find_lfn |
pop esi |
mov byte [esi], '/' |
jnc @f |
.notfound0: |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
@@: |
inc esi |
.common0: |
test byte [edi+11], 0x10 ; must be directory |
mov eax, ERROR_ACCESS_DENIED |
jz .ret1 |
mov ebp, [edi+20-2] |
mov bp, [edi+26] ; ebp=cluster |
mov eax, ERROR_FAT_TABLE |
cmp ebp, 2 |
jb .ret1 |
.pushnotroot: |
push fat_notroot_extend_dir |
push fat_notroot_end_write |
push fat_notroot_next_write |
push fat_notroot_begin_write |
push 0 |
push ebp |
push fat_notroot_first |
push fat_notroot_next |
.common1: |
call fat_find_lfn |
jc .notfound |
; found |
test byte [edi+11], 10h |
jz .exists_file |
; found directory; if we are creating directory, return OK, |
; if we are creating file, say "access denied" |
add esp, 32 |
popad |
test al, al |
mov eax, ERROR_ACCESS_DENIED |
jz @f |
mov al, 0 |
@@: |
xor ebx, ebx |
ret |
.exists_file: |
; found file; if we are creating directory, return "access denied", |
; if we are creating file, delete existing file and continue |
cmp byte [esp+32+28], 0 |
jz @f |
add esp, 32 |
popad |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
@@: |
; delete FAT chain |
push edi |
xor eax, eax |
mov dword [edi+28], eax ; zero size |
xor ecx, ecx |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov word [edi+20], cx |
mov word [edi+26], cx |
test eax, eax |
jz .done1 |
@@: |
cmp eax, [fatRESERVED] |
jae .done1 |
push edx |
xor edx, edx |
call set_FAT |
mov eax, edx |
pop edx |
inc ecx |
jmp @b |
.done1: |
pop edi |
call get_time_for_file |
mov [edi+22], ax |
call get_date_for_file |
mov [edi+24], ax |
mov [edi+18], ax |
or byte [edi+11], 20h ; set 'archive' attribute |
jmp .doit |
.notfound: |
; file is not found; generate short name |
call fat_name_is_legal |
jc @f |
add esp, 32 |
popad |
mov eax, ERROR_FILE_NOT_FOUND |
xor ebx, ebx |
ret |
@@: |
sub esp, 12 |
mov edi, esp |
call fat_gen_short_name |
.test_short_name_loop: |
push esi edi ecx |
mov esi, edi |
lea eax, [esp+12+12+8] |
mov [eax], ebp |
and dword [eax+4], 0 |
call dword [eax-4] |
jc .found |
.test_short_name_entry: |
cmp byte [edi+11], 0xF |
jz .test_short_name_cont |
mov ecx, 11 |
push esi edi |
repz cmpsb |
pop edi esi |
jz .short_name_found |
.test_short_name_cont: |
lea eax, [esp+12+12+8] |
call dword [eax-8] |
jnc .test_short_name_entry |
jmp .found |
.short_name_found: |
pop ecx edi esi |
call fat_next_short_name |
jnc .test_short_name_loop |
.disk_full: |
add esp, 12+32 |
popa |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.found: |
pop ecx edi esi |
; now find space in directory |
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' |
mov al, '~' |
push ecx edi |
mov ecx, 8 |
repnz scasb |
push 1 |
pop eax ; 1 entry |
jnz .notilde |
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total |
xor eax, eax |
@@: |
cmp byte [esi], 0 |
jz @f |
inc esi |
inc eax |
jmp @b |
@@: |
sub esi, eax |
add eax, 12+13 |
mov ecx, 13 |
push edx |
cdq |
div ecx |
pop edx |
.notilde: |
push -1 |
push -1 |
push -1 |
; find <eax> successive entries in directory |
xor ecx, ecx |
push eax |
lea eax, [esp+16+8+12+8] |
mov [eax], ebp |
and dword [eax+4], 0 |
call dword [eax-4] |
pop eax |
jnc .scan_dir |
.fsfrfe3: |
add esp, 12+8+12+32 |
popad |
mov eax, 11 |
xor ebx, ebx |
ret |
.scan_dir: |
cmp byte [edi], 0 |
jz .free |
cmp byte [edi], 0xE5 |
jz .free |
xor ecx, ecx |
.scan_cont: |
push eax |
lea eax, [esp+16+8+12+8] |
call dword [eax-8] |
pop eax |
jnc .scan_dir |
cmp [hd_error], 0 |
jnz .fsfrfe3 |
push eax |
lea eax, [esp+16+8+12+8] |
call dword [eax+20] ; extend directory |
pop eax |
jnc .scan_dir |
add esp, 12+8+12+32 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.free: |
test ecx, ecx |
jnz @f |
mov [esp], edi |
mov ecx, [esp+12+8+12+8] |
mov [esp+4], ecx |
mov ecx, [esp+12+8+12+12] |
mov [esp+8], ecx |
xor ecx, ecx |
@@: |
inc ecx |
cmp ecx, eax |
jb .scan_cont |
; found! |
; calculate name checksum |
push esi ecx |
mov esi, [esp+8+12] |
mov ecx, 11 |
xor eax, eax |
@@: |
ror al, 1 |
add al, [esi] |
inc esi |
loop @b |
pop ecx esi |
pop edi |
pop dword [esp+8+12+12] |
pop dword [esp+8+12+12] |
; edi points to first entry in free chunk |
dec ecx |
jz .nolfn |
push esi |
push eax |
lea eax, [esp+8+8+12+8] |
call dword [eax+8] ; begin write |
mov al, 40h |
.writelfn: |
or al, cl |
mov esi, [esp+4] |
push ecx |
dec ecx |
imul ecx, 13 |
add esi, ecx |
stosb |
mov cl, 5 |
call fs_RamdiskRewrite.read_symbols |
mov ax, 0xF |
stosw |
mov al, [esp+4] |
stosb |
mov cl, 6 |
call fs_RamdiskRewrite.read_symbols |
xor eax, eax |
stosw |
mov cl, 2 |
call fs_RamdiskRewrite.read_symbols |
pop ecx |
lea eax, [esp+8+8+12+8] |
call dword [eax+12] ; next write |
xor eax, eax |
loop .writelfn |
pop eax |
pop esi |
; lea eax, [esp+8+12+8] |
; call dword [eax+16] ; end write |
.nolfn: |
xchg esi, [esp] |
mov ecx, 11 |
rep movsb |
mov word [edi], 20h ; attributes |
sub edi, 11 |
pop esi ecx |
add esp, 12 |
mov byte [edi+13], 0 ; tenths of a second at file creation time |
call get_time_for_file |
mov [edi+14], ax ; creation time |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+16], ax ; creation date |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
xor ecx, ecx |
mov word [edi+20], cx ; high word of cluster |
mov word [edi+26], cx ; low word of cluster - to be filled |
mov dword [edi+28], ecx ; file size - to be filled |
cmp byte [esp+32+28], cl |
jz .doit |
; create directory |
mov byte [edi+11], 10h ; attributes: folder |
mov edx, edi |
lea eax, [esp+8] |
call dword [eax+16] ; flush directory |
push ecx |
mov ecx, [SECTORS_PER_CLUSTER] |
shl ecx, 9 |
jmp .doit2 |
.doit: |
lea eax, [esp+8] |
call dword [eax+16] ; flush directory |
push ecx |
mov ecx, [esp+4+32+24] |
.doit2: |
push ecx |
push edi |
mov esi, edx |
test ecx, ecx |
jz .done |
call get_free_FAT |
jc .diskfull |
push eax |
mov [edi+26], ax |
shr eax, 16 |
mov [edi+20], ax |
lea eax, [esp+16+8] |
call dword [eax+16] ; flush directory |
pop eax |
push edx |
mov edx, [fatEND] |
call set_FAT |
pop edx |
.write_cluster: |
push eax |
dec eax |
dec eax |
mov ebp, [SECTORS_PER_CLUSTER] |
imul eax, ebp |
add eax, [DATA_START] |
; write data |
.write_sector: |
cmp byte [esp+16+32+28], 0 |
jnz .writedir |
mov ecx, 512 |
cmp dword [esp+8], ecx |
jb .writeshort |
; we can write directly from given buffer |
mov ebx, esi |
add esi, ecx |
jmp .writecommon |
.writeshort: |
mov ecx, [esp+8] |
push ecx |
mov edi, buffer |
mov ebx, edi |
rep movsb |
.writedircont: |
mov ecx, buffer+0x200 |
sub ecx, edi |
push eax |
xor eax, eax |
rep stosb |
pop eax |
pop ecx |
.writecommon: |
call hd_write |
cmp [hd_error], 0 |
jnz .writeerr |
inc eax |
sub dword [esp+8], ecx |
jz .writedone |
dec ebp |
jnz .write_sector |
; allocate new cluster |
pop eax |
mov ecx, eax |
call get_free_FAT |
jc .diskfull |
push edx |
mov edx, [fatEND] |
call set_FAT |
xchg eax, ecx |
mov edx, ecx |
call set_FAT |
pop edx |
xchg eax, ecx |
jmp .write_cluster |
.diskfull: |
mov eax, ERROR_DISK_FULL |
jmp .ret |
.writeerr: |
pop eax |
sub esi, ecx |
mov eax, 11 |
jmp .ret |
.writedone: |
pop eax |
.done: |
xor eax, eax |
.ret: |
pop edi ecx |
mov ebx, esi |
sub ebx, edx |
pop ebp |
mov [esp+32+28], eax |
lea eax, [esp+8] |
call dword [eax+8] |
mov [edi+28], ebx |
call dword [eax+16] |
mov [esp+32+16], ebx |
lea eax, [ebx+511] |
shr eax, 9 |
mov ecx, [SECTORS_PER_CLUSTER] |
lea eax, [eax+ecx-1] |
xor edx, edx |
div ecx |
mov ecx, ebp |
sub ecx, eax |
call add_disk_free_space |
add esp, 32 |
call update_disk |
popad |
ret |
.writedir: |
push 512 |
mov edi, buffer |
mov ebx, edi |
mov ecx, [SECTORS_PER_CLUSTER] |
shl ecx, 9 |
cmp ecx, [esp+12] |
jnz .writedircont |
dec dword [esp+16] |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov ecx, [esp+20+8] |
cmp ecx, [ROOT_CLUSTER] |
jnz @f |
xor ecx, ecx |
@@: |
mov word [edi-32+26], cx |
shr ecx, 16 |
mov [edi-32+20], cx |
jmp .writedircont |
;---------------------------------------------------------------- |
; |
; fs_HdWrite - LFN variant for writing to hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdWrite.access_denied: |
push ERROR_ACCESS_DENIED |
fs_HdWrite.ret0: |
pop eax |
xor ebx, ebx |
ret |
fs_HdWrite.ret11: |
push 11 |
jmp fs_HdWrite.ret0 |
fs_HdWrite: |
cmp [fs_type], 1 |
jz ntfs_HdWrite |
cmp [fs_type], 2 |
jz ext2_HdWrite |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNKNOWN_FS |
jmp .ret0 |
@@: |
cmp byte [esi], 0 |
jz .access_denied |
pushad |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
popad |
push 11 |
jmp .ret0 |
@@: |
popfd |
jnc .found |
popad |
push ERROR_FILE_NOT_FOUND |
jmp .ret0 |
.found: |
; FAT does not support files larger than 4GB |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
.eof: |
popad |
push ERROR_END_OF_FILE |
jmp .ret0 |
@@: |
mov ebx, [ebx] |
.l1: |
; now edi points to direntry, ebx=start byte to write, |
; ecx=number of bytes to write, edx=data pointer |
; extend file if needed |
add ecx, ebx |
jc .eof ; FAT does not support files larger than 4GB |
push eax ; save directory sector |
push 0 ; return value=0 |
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
push dword [edi+28] ; save current file size |
cmp ecx, [edi+28] |
jbe .length_ok |
cmp ecx, ebx |
jz .length_ok |
call hd_extend_file |
jnc .length_ok |
mov [esp+4], eax |
; hd_extend_file can return three error codes: FAT table error, device error or disk full. |
; First two cases are fatal errors, in third case we may write some data |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax |
pop eax |
mov [esp+4+28], eax |
pop eax |
popad |
xor ebx, ebx |
ret |
.disk_full: |
; correct number of bytes to write |
mov ecx, [edi+28] |
cmp ecx, ebx |
ja .length_ok |
.ret: |
call update_disk |
cmp [hd_error], 0 |
jz @f |
mov byte [esp+4], 11 |
@@: |
pop eax |
pop eax |
mov [esp+4+28], eax ; eax=return value |
pop eax |
sub edx, [esp+20] |
mov [esp+16], edx ; ebx=number of written bytes |
popad |
ret |
.length_ok: |
mov esi, [edi+28] |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov edi, eax ; edi=current cluster |
xor ebp, ebp ; ebp=current sector in cluster |
; save directory |
mov eax, [esp+8] |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jz @f |
.device_err: |
mov byte [esp+4], 11 |
jmp .ret |
@@: |
; now ebx=start pos, ecx=end pos, both lie inside file |
sub ecx, ebx |
jz .ret |
.write_loop: |
; skip unmodified sectors |
cmp dword [esp], 0x200 |
jb .modify |
sub ebx, 0x200 |
jae .skip |
add ebx, 0x200 |
.modify: |
; get length of data in current sector |
push ecx |
sub ebx, 0x200 |
jb .hasdata |
neg ebx |
xor ecx, ecx |
jmp @f |
.hasdata: |
neg ebx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
; get current sector number |
mov eax, edi |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ebp |
; load sector if needed |
cmp dword [esp+4], 0 ; we don't need to read uninitialized data |
jz .noread |
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten |
jz .noread |
cmp ecx, esi ; (same for the last sector) |
jz .noread |
push ebx |
mov ebx, buffer |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jz @f |
.device_err2: |
pop ecx |
jmp .device_err |
@@: |
.noread: |
; zero uninitialized data if file was extended (because hd_extend_file does not this) |
push eax ecx edi |
xor eax, eax |
mov ecx, 0x200 |
sub ecx, [esp+4+12] |
jbe @f |
mov edi, buffer |
add edi, [esp+4+12] |
rep stosb |
@@: |
; zero uninitialized data in the last sector |
mov ecx, 0x200 |
sub ecx, esi |
jbe @f |
mov edi, buffer |
add edi, esi |
rep stosb |
@@: |
pop edi ecx |
; copy new data |
mov eax, edx |
neg ebx |
jecxz @f |
add ebx, buffer+0x200 |
call memmove |
xor ebx, ebx |
@@: |
pop eax |
; save sector |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jnz .device_err2 |
add edx, ecx |
sub [esp], ecx |
pop ecx |
jz .ret |
.skip: |
; next sector |
inc ebp |
cmp ebp, [SECTORS_PER_CLUSTER] |
jb @f |
xor ebp, ebp |
mov eax, edi |
call get_FAT |
mov edi, eax |
cmp [hd_error], 0 |
jnz .device_err |
@@: |
sub esi, 0x200 |
jae @f |
xor esi, esi |
@@: |
sub dword [esp], 0x200 |
jae @f |
and dword [esp], 0 |
@@: |
jmp .write_loop |
hd_extend_file.zero_size: |
xor eax, eax |
jmp hd_extend_file.start_extend |
; extends file on hd to given size (new data area is undefined) |
; in: edi->direntry, ecx=new size |
; out: CF=0 => OK, eax=0 |
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or 11) |
hd_extend_file: |
push ebp |
mov ebp, [SECTORS_PER_CLUSTER] |
imul ebp, [BYTES_PER_SECTOR] |
push ecx |
; find the last cluster of file |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov ecx, [edi+28] |
jecxz .zero_size |
.last_loop: |
sub ecx, ebp |
jbe .last_found |
call get_FAT |
cmp [hd_error], 0 |
jz @f |
.device_err: |
pop ecx |
.device_err2: |
pop ebp |
push 11 |
.ret_err: |
pop eax |
stc |
ret |
@@: |
cmp eax, 2 |
jb .fat_err |
cmp eax, [fatRESERVED] |
jb .last_loop |
.fat_err: |
pop ecx ebp |
push ERROR_FAT_TABLE |
jmp .ret_err |
.last_found: |
push eax |
call get_FAT |
cmp [hd_error], 0 |
jz @f |
pop eax |
jmp .device_err |
@@: |
cmp eax, [fatRESERVED] |
pop eax |
jb .fat_err |
; set length to full number of clusters |
sub [edi+28], ecx |
.start_extend: |
pop ecx |
; now do extend |
push edx |
mov edx, 2 ; start scan from cluster 2 |
.extend_loop: |
cmp [edi+28], ecx |
jae .extend_done |
; add new cluster |
push eax |
call get_free_FAT |
jc .disk_full |
mov edx, [fatEND] |
call set_FAT |
mov edx, eax |
pop eax |
test eax, eax |
jz .first_cluster |
push edx |
call set_FAT |
pop edx |
jmp @f |
.first_cluster: |
ror edx, 16 |
mov [edi+20], dx |
ror edx, 16 |
mov [edi+26], dx |
@@: |
push ecx |
mov ecx, -1 |
call add_disk_free_space |
pop ecx |
mov eax, edx |
cmp [hd_error], 0 |
jnz .device_err3 |
add [edi+28], ebp |
jmp .extend_loop |
.extend_done: |
mov [edi+28], ecx |
pop edx ebp |
xor eax, eax ; CF=0 |
ret |
.device_err3: |
pop edx |
jmp .device_err2 |
.disk_full: |
pop eax edx ebp |
push ERROR_DISK_FULL |
pop eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
stc |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdSetFileEnd - set end of file on hard disk |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdSetFileEnd: |
cmp [fs_type], 1 |
jz ntfs_HdSetFileEnd |
cmp [fs_type], 2 |
jz ext2_HdSetFileEnd |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNKNOWN_FS |
.ret: |
pop eax |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .ret |
@@: |
push edi |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
push 11 |
jmp .ret |
@@: |
popfd |
jnc @f |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .ret |
@@: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
pop edi |
jmp .access_denied |
@@: |
; file size must not exceed 4 Gb |
cmp dword [ebx+4], 0 |
jz @f |
pop edi |
push ERROR_END_OF_FILE |
jmp .ret |
@@: |
push eax ; save directory sector |
; set file modification date/time to current |
call fat_update_datetime |
mov eax, [ebx] |
cmp eax, [edi+28] |
jb .truncate |
ja .expand |
pop eax |
mov ebx, buffer |
call hd_write |
pop edi |
xor eax, eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
.expand: |
push ebx ebp ecx |
push dword [edi+28] ; save old size |
mov ecx, eax |
call hd_extend_file |
push eax ; return code |
jnc .expand_ok |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
.pop_ret: |
call update_disk |
pop eax ecx ebp ebx ecx edi edi |
ret |
.expand_ok: |
.disk_full: |
; save directory |
mov eax, [edi+28] |
xchg eax, [esp+20] |
mov ebx, buffer |
call hd_write |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov edi, eax |
cmp [hd_error], 0 |
jz @f |
.pop_ret11: |
mov byte [esp], 11 |
jmp .pop_ret |
@@: |
; now zero new data |
xor ebp, ebp |
; edi=current cluster, ebp=sector in cluster |
; [esp+20]=new size, [esp+4]=old size, [esp]=return code |
.zero_loop: |
sub dword [esp+4], 0x200 |
jae .next_cluster |
lea eax, [edi-2] |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ebp |
cmp dword [esp+4], -0x200 |
jz .noread |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jnz .err_next |
.noread: |
mov ecx, [esp+4] |
neg ecx |
push edi |
mov edi, buffer+0x200 |
add edi, [esp+8] |
push eax |
xor eax, eax |
mov [esp+12], eax |
rep stosb |
pop eax |
pop edi |
call hd_write |
cmp [hd_error], 0 |
jz .next_cluster |
.err_next: |
mov byte [esp], 11 |
.next_cluster: |
sub dword [esp+20], 0x200 |
jbe .pop_ret |
inc ebp |
cmp ebp, [SECTORS_PER_CLUSTER] |
jb .zero_loop |
xor ebp, ebp |
mov eax, edi |
call get_FAT |
mov edi, eax |
cmp [hd_error], 0 |
jnz .pop_ret11 |
jmp .zero_loop |
.truncate: |
mov [edi+28], eax |
push ecx |
mov ecx, [edi+20-2] |
mov cx, [edi+26] |
push eax |
test eax, eax |
jz .zero_size |
; find new last cluster |
@@: |
mov eax, [SECTORS_PER_CLUSTER] |
shl eax, 9 |
sub [esp], eax |
jbe @f |
mov eax, ecx |
call get_FAT |
mov ecx, eax |
cmp [hd_error], 0 |
jz @b |
.device_err3: |
pop eax ecx eax edi |
push 11 |
pop eax |
ret |
@@: |
; we will zero data at the end of last sector - remember it |
push ecx |
; terminate FAT chain |
push edx |
mov eax, ecx |
mov edx, [fatEND] |
call set_FAT |
mov eax, edx |
pop edx |
cmp [hd_error], 0 |
jz @f |
.device_err4: |
pop ecx |
jmp .device_err3 |
.zero_size: |
and word [edi+20], 0 |
and word [edi+26], 0 |
push 0 |
mov eax, ecx |
@@: |
; delete FAT chain |
call clear_cluster_chain |
cmp [hd_error], 0 |
jnz .device_err4 |
; save directory |
mov eax, [esp+12] |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jnz .device_err4 |
; zero last sector, ignore errors |
pop ecx |
pop eax |
dec ecx |
imul ecx, [SECTORS_PER_CLUSTER] |
add ecx, [DATA_START] |
push eax |
sar eax, 9 |
add ecx, eax |
pop eax |
and eax, 0x1FF |
jz .truncate_done |
push ebx eax |
mov eax, ecx |
mov ebx, buffer |
call hd_read |
pop eax |
lea edi, [buffer+eax] |
push ecx |
mov ecx, 0x200 |
sub ecx, eax |
xor eax, eax |
rep stosb |
pop eax |
call hd_write |
pop ebx |
.truncate_done: |
pop ecx eax edi |
call update_disk |
xor eax, eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
fs_HdGetFileInfo: |
cmp [fs_type], 1 |
jz ntfs_HdGetFileInfo |
cmp [fs_type], 2 |
jz ext2_HdGetFileInfo |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 |
ret |
@@: |
push edi |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
pop edi |
mov eax, 11 |
ret |
@@: |
popfd |
jmp fs_GetFileInfo_finish |
fs_HdSetFileInfo: |
cmp [fs_type], 1 |
jz ntfs_HdSetFileInfo |
cmp [fs_type], 2 |
jz ext2_HdSetFileInfo |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 |
ret |
@@: |
push edi |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
pop edi |
mov eax, 11 |
ret |
@@: |
popfd |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
push eax |
call bdfe_to_fat_entry |
pop eax |
mov ebx, buffer |
call hd_write |
call update_disk |
pop edi |
xor eax, eax |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdDelete - delete file or empty folder from hard disk |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdDelete: |
cmp [fs_type], 1 |
jz ntfs_HdDelete |
cmp [fs_type], 2 |
jz ext2_HdDelete |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNKNOWN_FS |
.pop_ret: |
pop eax |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
; cannot delete root! |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .pop_ret |
@@: |
and [longname_sec1], 0 |
and [longname_sec2], 0 |
push edi |
call hd_find_lfn |
jnc .found |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .pop_ret |
.found: |
cmp dword [edi], '. ' |
jz .access_denied2 |
cmp dword [edi], '.. ' |
jz .access_denied2 |
test byte [edi+11], 10h |
jz .dodel |
; we can delete only empty folders! |
pushad |
mov ebp, [edi+20-2] |
mov bp, [edi+26] |
xor ecx, ecx |
lea eax, [ebp-2] |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jnz .err1 |
add ebx, 2*0x20 |
.checkempty: |
cmp byte [ebx], 0 |
jz .empty |
cmp byte [ebx], 0xE5 |
jnz .notempty |
add ebx, 0x20 |
cmp ebx, buffer+0x200 |
jb .checkempty |
inc ecx |
cmp ecx, [SECTORS_PER_CLUSTER] |
jb @f |
mov eax, ebp |
call get_FAT |
cmp [hd_error], 0 |
jnz .err1 |
mov ebp, eax |
xor ecx, ecx |
@@: |
lea eax, [ebp-2] |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ecx |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jz .checkempty |
.err1: |
popad |
.err2: |
pop edi |
push 11 |
pop eax |
ret |
.notempty: |
popad |
.access_denied2: |
pop edi |
push ERROR_ACCESS_DENIED |
pop eax |
ret |
.empty: |
popad |
push ebx |
mov ebx, buffer |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jnz .err2 |
.dodel: |
push eax |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
xchg eax, [esp] |
; delete folder entry |
mov byte [edi], 0xE5 |
; delete LFN (if present) |
.lfndel: |
cmp edi, buffer |
ja @f |
cmp [longname_sec2], 0 |
jz .lfndone |
push [longname_sec2] |
push [longname_sec1] |
pop [longname_sec2] |
and [longname_sec1], 0 |
push ebx |
mov ebx, buffer |
call hd_write |
mov eax, [esp+4] |
call hd_read |
pop ebx |
pop eax |
mov edi, buffer+0x200 |
@@: |
sub edi, 0x20 |
cmp byte [edi], 0xE5 |
jz .lfndone |
cmp byte [edi+11], 0xF |
jnz .lfndone |
mov byte [edi], 0xE5 |
jmp .lfndel |
.lfndone: |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
; delete FAT chain |
pop eax |
call clear_cluster_chain |
call update_disk |
pop edi |
xor eax, eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
; \end{diamond} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fs/fs.inc |
---|
1,797 → 1,801 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; System service for filesystem call ;; |
;; (C) 2004 Ville Turjanmaa, License: GPL ;; |
;; 29.04.2006 Elimination of hangup after the ;; |
;; expiration hd_wait_timeout (for LBA) - Mario79 ;; |
;; 15.01.2005 get file size/attr/date, ;; |
;; file_append (only for hd) - ATV ;; |
;; 23.11.2004 test if hd/partition is set - ATV ;; |
;; 18.11.2004 get_disk_info and more error codes - ATV ;; |
;; 08.11.2004 expand_pathz and rename (only for hd) - ATV ;; |
;; 20.10.2004 Makedir/Removedir (only for hd) - ATV ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
dir0: db 'HARDDISK ' |
db 'RAMDISK ' |
db 'FLOPPYDISK ' |
db 0 |
dir1: db 'FIRST ' |
db 'SECOND ' |
db 'THIRD ' |
db 'FOURTH ' |
db 0 |
not_select_IDE db 0 |
hd_address_table: dd 0x1f0,0x00,0x1f0,0x10 |
dd 0x170,0x00,0x170,0x10 |
endg |
file_system: |
; IN: |
; |
; eax = 0 ; read file /RamDisk/First 6 |
; eax = 8 ; lba read |
; eax = 15 ; get_disk_info |
; |
; OUT: |
; |
; eax = 0 : read ok |
; eax = 1 : no hd base and/or partition defined |
; eax = 2 : function is unsupported for this FS |
; eax = 3 : unknown FS |
; eax = 4 : partition not defined at hd |
; eax = 5 : file not found |
; eax = 6 : end of file |
; eax = 7 : memory pointer not in application area |
; eax = 8 : disk full |
; eax = 9 : fat table corrupted |
; eax = 10 : access denied |
; eax = 11 : disk error |
; |
; ebx = size |
; \begin{diamond}[18.03.2006] |
; for subfunction 16 (start application) error codes must be negative |
; because positive values are valid PIDs |
; so possible return values are: |
; eax > 0 : process created, eax=PID |
; -0x10 <= eax < 0 : -eax is filesystem error code: |
; eax = -1 = 0xFFFFFFFF : no hd base and/or partition defined |
; eax = -3 = 0xFFFFFFFD : unknown FS |
; eax = -5 = 0xFFFFFFFB : file not found |
; eax = -6 = 0xFFFFFFFA : unexpected end of file (probably not executable file) |
; eax = -9 = 0xFFFFFFF7 : fat table corrupted |
; eax = -10 = 0xFFFFFFF6 : access denied |
; -0x20 <= eax < -0x10: eax is process creation error code: |
; eax = -0x20 = 0xFFFFFFE0 : too many processes |
; eax = -0x1F = 0xFFFFFFE1 : not Menuet/Kolibri executable |
; eax = -0x1E = 0xFFFFFFE2 : no memory |
; ebx is not changed |
; \end{diamond}[18.03.2006] |
; Extract parameters |
; add eax, std_application_base_address ; abs start of info block |
cmp dword [eax+0],15 ; GET_DISK_INFO |
je fs_info |
cmp dword [CURRENT_TASK],1 ; no memory checks for kernel requests |
jz no_checks_for_kernel |
mov edx,eax |
cmp dword [eax+0],1 |
jnz .usual_check |
mov ebx,[eax+12] |
; add ebx,std_application_base_address |
mov ecx,[eax+8] |
call check_region |
test eax,eax |
jnz area_in_app_mem |
.error_output: |
mov esi,buffer_failed |
call sys_msg_board_str |
; mov eax,7 |
mov dword [esp+36],7 |
ret |
iglobal |
buffer_failed db 'K : Buffer check failed',13,10,0 |
endg |
.usual_check: |
cmp dword [eax+0],0 |
mov ecx,512 |
jnz .small_size |
mov ecx,[eax+8] |
shl ecx,9 |
.small_size: |
mov ebx,[eax+12] |
; add ebx,std_application_base_address |
call check_region |
test eax,eax |
jz .error_output |
area_in_app_mem: |
mov eax,edx |
no_checks_for_kernel: |
fs_read: |
mov ebx,[eax+20] ; program wants root directory ? |
test bl,bl |
je fs_getroot |
test bh,bh |
jne fs_noroot |
fs_getroot: |
; \begin{diamond}[18.03.2006] |
; root - only read is allowed |
; other operations return "access denied", eax=10 |
; (execute operation returns eax=-10) |
cmp dword [eax], 0 |
jz .read_root |
mov dword [esp+36], 10 |
ret |
.read_root: |
; \end{diamond}[18.03.2006] |
mov esi,dir0 |
mov edi,[eax+12] |
; add edi,std_application_base_address |
mov ecx,11 |
push ecx |
; cld ; already is |
rep movsb |
mov al,0x10 |
stosb |
add edi,32-11-1 |
pop ecx |
rep movsb |
stosb |
and dword [esp+36],0 ; ok read |
mov dword [esp+24],32*2 ; size of root |
ret |
fs_info: ;start of code - Mihasik |
push eax |
cmp [eax+21],byte 'h' |
je fs_info_h |
cmp [eax+21],byte 'H' |
je fs_info_h |
cmp [eax+21],byte 'r' |
je fs_info_r |
cmp [eax+21],byte 'R' |
je fs_info_r |
mov eax,3 ;if unknown disk |
xor ebx,ebx |
xor ecx,ecx |
xor edx,edx |
jmp fs_info1 |
fs_info_r: |
call ramdisk_free_space ;if ramdisk |
mov ecx,edi ;free space in ecx |
shr ecx,9 ;free clusters |
mov ebx,2847 ;total clusters |
mov edx,512 ;cluster size |
xor eax,eax ;always 0 |
jmp fs_info1 |
fs_info_h: ;if harddisk |
call get_hd_info |
fs_info1: |
pop edi |
mov [esp+36],eax |
mov [esp+24],ebx ; total clusters on disk |
mov [esp+32],ecx ; free clusters on disk |
mov [edi],edx ; cluster size in bytes |
ret ;end of code - Mihasik |
fs_noroot: |
push dword [eax+0] ; read/write/delete/.../makedir/rename/lba/run |
push dword [eax+4] ; 512 block number to read |
push dword [eax+8] ; bytes to write/append or 512 blocks to read |
mov ebx,[eax+12] |
; add ebx,std_application_base_address |
push ebx ; abs start of return/save area |
lea esi,[eax+20] ; abs start of dir + filename |
mov edi,[eax+16] |
; add edi,std_application_base_address ; abs start of work area |
call expand_pathz |
push edi ; dir start |
push ebx ; name of file start |
mov eax,[edi+1] |
cmp eax,'RD ' |
je fs_yesramdisk |
cmp eax,'RAMD' |
jne fs_noramdisk |
fs_yesramdisk: |
cmp byte [edi+1+11],0 |
je fs_give_dir1 |
mov eax,[edi+1+12] |
cmp eax,'1 ' |
je fs_yesramdisk_first |
cmp eax,'FIRS' |
jne fs_noramdisk |
fs_yesramdisk_first: |
cmp dword [esp+20],8 ; LBA read ramdisk |
jne fs_no_LBA_read_ramdisk |
mov eax,[esp+16] ; LBA block to read |
mov ecx,[esp+8] ; abs pointer to return area |
call LBA_read_ramdisk |
jmp file_system_return |
fs_no_LBA_read_ramdisk: |
cmp dword [esp+20],0 ; READ |
jne fs_noramdisk_read |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
mov ebx,[esp+16] ; block start |
inc ebx |
mov ecx,[esp+12] ; block count |
mov edx,[esp+8] ; return |
mov esi,[esp+0] |
sub esi,eax |
add esi,12+1 ; file name length |
call fileread |
jmp file_system_return |
fs_noramdisk_read: |
fs_noramdisk: |
;******************************************************************** |
mov eax,[edi+1] |
cmp eax,'FD ' |
je fs_yesflpdisk |
cmp eax,'FLOP' |
jne fs_noflpdisk |
fs_yesflpdisk: |
call reserve_flp |
cmp byte [edi+1+11],0 |
je fs_give_dir1 |
mov eax,[edi+1+12] |
cmp eax,'1 ' |
je fs_yesflpdisk_first |
cmp eax,'FIRS' |
je fs_yesflpdisk_first |
cmp eax,'2 ' |
je fs_yesflpdisk_second |
cmp eax,'SECO' |
jne fs_noflpdisk |
jmp fs_yesflpdisk_second |
fs_yesflpdisk_first: |
mov [flp_number],1 |
jmp fs_yesflpdisk_start |
fs_yesflpdisk_second: |
mov [flp_number],2 |
fs_yesflpdisk_start: |
cmp dword [esp+20],0 ; READ |
jne fs_noflpdisk_read |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
mov ebx,[esp+16] ; block start |
inc ebx |
mov ecx,[esp+12] ; block count |
mov edx,[esp+8] ; return |
mov esi,[esp+0] |
sub esi,eax |
add esi,12+1 ; file name length |
call floppy_fileread |
jmp file_system_return |
fs_noflpdisk_read: |
fs_noflpdisk: |
;***************************************************************** |
mov eax,[edi+1] |
cmp eax,'HD0 ' |
je fs_yesharddisk_IDE0 |
cmp eax,'HD1 ' |
je fs_yesharddisk_IDE1 |
cmp eax,'HD2 ' |
je fs_yesharddisk_IDE2 |
cmp eax,'HD3 ' |
je fs_yesharddisk_IDE3 |
jmp old_path_harddisk |
fs_yesharddisk_IDE0: |
call reserve_hd1 |
mov [hdbase],0x1f0 |
mov [hdid],0x0 |
mov [hdpos],1 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE1: |
call reserve_hd1 |
mov [hdbase],0x1f0 |
mov [hdid],0x10 |
mov [hdpos],2 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE2: |
call reserve_hd1 |
mov [hdbase],0x170 |
mov [hdid],0x0 |
mov [hdpos],3 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE3: |
call reserve_hd1 |
mov [hdbase],0x170 |
mov [hdid],0x10 |
mov [hdpos],4 |
fs_yesharddisk_partition: |
call reserve_hd_channel |
; call choice_necessity_partition |
; jmp fs_yesharddisk_all |
jmp fs_for_new_semantic |
choice_necessity_partition: |
mov eax,[edi+1+12] |
call StringToNumber |
mov [fat32part],eax |
choice_necessity_partition_1: |
mov ecx,[hdpos] |
xor eax,eax |
mov [hd_entries], eax ; entries in hd cache |
mov edx,DRIVE_DATA+2 |
cmp ecx,0x80 |
jb search_partition_array |
mov ecx,4 |
search_partition_array: |
mov bl,[edx] |
movzx ebx,bl |
add eax,ebx |
inc edx |
loop search_partition_array |
mov ecx,[hdpos] |
mov edx,BiosDiskPartitions |
sub ecx,0x80 |
jb .s |
je .f |
@@: |
mov ebx,[edx] |
add edx,4 |
add eax,ebx |
loop @b |
jmp .f |
.s: |
sub eax,ebx |
.f: |
add eax, [known_part] ; add eax,[fat32part] |
dec eax |
xor edx,edx |
imul eax,100 |
add eax,DRIVE_DATA+0xa |
mov [transfer_adress],eax |
call partition_data_transfer_1 |
ret |
old_path_harddisk: |
mov eax,[edi+1] |
cmp eax,'HD ' |
je fs_yesharddisk |
cmp eax,'HARD' |
jne fs_noharddisk |
fs_yesharddisk: |
cmp dword [esp+20],8 ; LBA read |
jne fs_no_LBA_read |
mov eax,[esp+16] ; LBA block to read |
lea ebx,[edi+1+12] ; pointer to FIRST/SECOND/THIRD/FOURTH |
mov ecx,[esp+8] ; abs pointer to return area |
call LBA_read |
jmp file_system_return |
fs_no_LBA_read: |
cmp byte [edi+1+11],0 ; directory read |
je fs_give_dir1 |
call reserve_hd1 |
fs_for_new_semantic: |
call choice_necessity_partition |
fs_yesharddisk_all: |
mov eax,1 |
mov ebx, [esp+24+24] |
cmp [hdpos],0 ; is hd base set? |
jz hd_err_return |
cmp [fat32part],0 ; is partition set? |
jnz @f |
hd_err_return: |
call free_hd_channel |
and [hd1_status], 0 |
jmp file_system_return |
@@: |
cmp dword [esp+20],0 ; READ |
jne fs_noharddisk_read |
mov eax,[esp+0] ; /fname |
lea edi,[eax+12] |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov ebx,[esp+12] ; count to read |
mov ecx,[esp+8] ; buffer |
mov edx,[esp+4] |
add edx,12*2 ; dir start |
sub edi,edx ; path length |
mov esi,[esp+16] ; blocks to read |
call file_read |
mov edi,[esp+0] |
mov byte [edi],'/' |
call free_hd_channel |
and [hd1_status], 0 |
jmp file_system_return |
fs_noharddisk_read: |
call free_hd_channel |
and [hd1_status], 0 |
fs_noharddisk: |
; \begin{diamond}[18.03.2006] |
mov eax, 5 ; file not found |
; à ìîæåò áûòü, âîçâðàùàòü äðóãîé êîä îøèáêè? |
mov ebx, [esp+24+24] ; do not change ebx in application |
; \end{diamond}[18.03.2006] |
file_system_return: |
add esp,24 |
mov [esp+36],eax |
mov [esp+24],ebx |
ret |
fs_give_dir1: |
; \begin{diamond}[18.03.2006] |
; /RD,/FD,/HD - only read is allowed |
; other operations return "access denied", eax=10 |
; (execute operation returns eax=-10) |
cmp dword [esp+20], 0 |
jz .read |
add esp, 20 |
pop ecx |
mov dword [esp+36], 10 |
ret |
.read: |
; \end{diamond}[18.03.2006] |
mov al,0x10 |
mov ebx,1 |
mov edi,[esp+8] |
mov esi,dir1 |
fs_d1_new: |
mov ecx,11 |
; cld |
rep movsb |
stosb |
add edi,32-11-1 |
dec ebx |
jne fs_d1_new |
add esp,24 |
and dword [esp+36],0 ; ok read |
mov dword [esp+24],32*1 ; dir/data size |
ret |
LBA_read_ramdisk: |
cmp [lba_read_enabled],1 |
je lbarrl1 |
xor ebx,ebx |
mov eax,2 |
ret |
lbarrl1: |
cmp eax,18*2*80 |
jb lbarrl2 |
xor ebx,ebx |
mov eax,3 |
ret |
lbarrl2: |
pushad |
call restorefatchain |
mov edi,ecx |
mov esi,eax |
shl esi,9 |
add esi,RAMDISK |
mov ecx,512/4 |
; cld |
rep movsd |
popad |
xor ebx,ebx |
xor eax,eax |
ret |
LBA_read: |
; IN: |
; |
; eax = LBA block to read |
; ebx = pointer to FIRST/SECOND/THIRD/FOURTH |
; ecx = abs pointer to return area |
cmp [lba_read_enabled],1 |
je lbarl1 |
mov eax,2 |
ret |
lbarl1: |
call reserve_hd1 |
push eax |
push ecx |
mov edi,hd_address_table |
mov esi,dir1 |
mov eax,[ebx] |
mov edx,'1 ' |
mov ecx,4 |
blar0: |
cmp eax,[esi] |
je blar2 |
cmp eax,edx |
je blar2 |
inc edx |
add edi,8 |
add esi,11 |
dec ecx |
jnz blar0 |
mov eax,1 |
mov ebx,1 |
jmp LBA_read_ret |
blar2: |
mov eax,[edi+0] |
mov ebx,[edi+4] |
mov [hdbase],eax |
mov [hdid],ebx |
call wait_for_hd_idle |
cmp [hd_error],0 |
jne hd_lba_error |
; eax = hd port |
; ebx = set for primary (0x00) or slave (0x10) |
cli |
mov edx,eax |
inc edx |
xor eax,eax |
out dx,al |
inc edx |
inc eax |
out dx,al |
inc edx |
mov eax,[esp+4] |
out dx,al |
shr eax,8 |
inc edx |
out dx,al |
shr eax,8 |
inc edx |
out dx,al |
shr eax,8 |
inc edx |
and al,1+2+4+8 |
add al,bl |
add al,128+64+32 |
out dx,al |
inc edx |
mov al,20h |
out dx,al |
sti |
call wait_for_sector_buffer |
cmp [hd_error],0 |
jne hd_lba_error |
cli |
mov edi,[esp+0] |
mov ecx,256 |
sub edx,7 |
cld |
rep insw |
sti |
xor eax,eax |
xor ebx,ebx |
LBA_read_ret: |
mov [hd_error],0 |
mov [hd1_status],0 |
add esp,2*4 |
ret |
expand_pathz: |
; IN: |
; esi = asciiz path & file |
; edi = buffer for path & file name |
; OUT: |
; edi = directory & file : / 11 + / 11 + / 11 - zero terminated |
; ebx = /file name - zero terminated |
; esi = pointer after source |
push eax |
push ecx |
push edi ;[esp+0] |
pathz_start: |
mov byte [edi],'/' |
inc edi |
mov al,32 |
mov ecx,11 |
cld |
rep stosb ; clear filename area |
sub edi,11 |
mov ebx,edi ; start of dir/file name |
pathz_new_char: |
mov al,[esi] |
inc esi |
cmp al,0 |
je pathz_end |
cmp al,'/' |
jne pathz_not_path |
cmp edi,ebx ; skip first '/' |
jz pathz_new_char |
lea edi,[ebx+11] ; start of next directory |
jmp pathz_start |
pathz_not_path: |
cmp al,'.' |
jne pathz_not_ext |
lea edi,[ebx+8] ; start of extension |
jmp pathz_new_char |
pathz_not_ext: |
cmp al,'a' |
jb pathz_not_low |
cmp al,'z' |
ja pathz_not_low |
sub al,0x20 ; char to uppercase |
pathz_not_low: |
mov [edi],al |
inc edi |
mov eax,[esp+0] ; start_of_dest_path |
add eax,512 ; keep maximum path under 512 bytes |
cmp edi,eax |
jb pathz_new_char |
pathz_end: |
cmp ebx,edi ; if path end with '/' |
jnz pathz_put_zero ; go back 1 level |
sub ebx,12 |
pathz_put_zero: |
mov byte [ebx+11],0 |
dec ebx ; include '/' char into file name |
pop edi |
pop ecx |
pop eax |
ret |
;******************************************* |
;* string to number |
;* input eax - 4 byte string |
;* output eax - number |
;******************************************* |
StringToNumber: |
; ÏÅÐÅÂÎÄ ÑÒÐÎÊÎÂÎÃÎ ×ÈÑËÀ  ×ÈÑËÎÂÎÉ ÂÈÄ |
; Âõîä: |
; EDI - àäðåñ ñòðîêè ñ ÷èñëîì. Êîíåö ÷èñëà îòìå÷åí êîäîì 0Dh |
; Âûõîä: |
; CF - èíäèêàòîð îøèáîê: |
; 0 - îøèáîê íåò; |
; 1 - îøèáêà |
; Åñëè CF=0, òî AX - ÷èñëî. |
push bx |
push cx |
push dx |
push edi |
mov [partition_string],eax |
mov edi,partition_string |
xor cx,cx |
i1: |
mov al,[edi] |
cmp al,32 ;13 |
je i_exit |
; cmp al,'0' |
; jb err |
; cmp al,'9' |
; ja err |
sub al,48 |
shl cx,1 |
jc error |
mov bx,cx |
shl cx,1 |
jc error |
shl cx,1 |
jc error |
add cx,bx |
jc error |
cbw |
add cx,ax |
jc error |
i3: |
inc edi |
jmp i1 |
i_exit: |
mov ax,cx |
clc |
i4: |
movzx eax,ax |
pop edi |
pop dx |
pop cx |
pop bx |
ret |
error: |
stc |
jmp i4 |
partition_string: dd 0 |
db 32 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; System service for filesystem call ;; |
;; (C) 2004 Ville Turjanmaa, License: GPL ;; |
;; 29.04.2006 Elimination of hangup after the ;; |
;; expiration hd_wait_timeout (for LBA) - Mario79 ;; |
;; 15.01.2005 get file size/attr/date, ;; |
;; file_append (only for hd) - ATV ;; |
;; 23.11.2004 test if hd/partition is set - ATV ;; |
;; 18.11.2004 get_disk_info and more error codes - ATV ;; |
;; 08.11.2004 expand_pathz and rename (only for hd) - ATV ;; |
;; 20.10.2004 Makedir/Removedir (only for hd) - ATV ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
dir0: |
db 'HARDDISK ' |
db 'RAMDISK ' |
db 'FLOPPYDISK ' |
db 0 |
dir1: |
db 'FIRST ' |
db 'SECOND ' |
db 'THIRD ' |
db 'FOURTH ' |
db 0 |
not_select_IDE db 0 |
hd_address_table: |
dd 0x1f0,0x00,0x1f0,0x10 |
dd 0x170,0x00,0x170,0x10 |
endg |
file_system: |
; IN: |
; |
; eax = 0 ; read file /RamDisk/First 6 |
; eax = 8 ; lba read |
; eax = 15 ; get_disk_info |
; |
; OUT: |
; |
; eax = 0 : read ok |
; eax = 1 : no hd base and/or partition defined |
; eax = 2 : function is unsupported for this FS |
; eax = 3 : unknown FS |
; eax = 4 : partition not defined at hd |
; eax = 5 : file not found |
; eax = 6 : end of file |
; eax = 7 : memory pointer not in application area |
; eax = 8 : disk full |
; eax = 9 : fat table corrupted |
; eax = 10 : access denied |
; eax = 11 : disk error |
; |
; ebx = size |
; \begin{diamond}[18.03.2006] |
; for subfunction 16 (start application) error codes must be negative |
; because positive values are valid PIDs |
; so possible return values are: |
; eax > 0 : process created, eax=PID |
; -0x10 <= eax < 0 : -eax is filesystem error code: |
; eax = -1 = 0xFFFFFFFF : no hd base and/or partition defined |
; eax = -3 = 0xFFFFFFFD : unknown FS |
; eax = -5 = 0xFFFFFFFB : file not found |
; eax = -6 = 0xFFFFFFFA : unexpected end of file (probably not executable file) |
; eax = -9 = 0xFFFFFFF7 : fat table corrupted |
; eax = -10 = 0xFFFFFFF6 : access denied |
; -0x20 <= eax < -0x10: eax is process creation error code: |
; eax = -0x20 = 0xFFFFFFE0 : too many processes |
; eax = -0x1F = 0xFFFFFFE1 : not Menuet/Kolibri executable |
; eax = -0x1E = 0xFFFFFFE2 : no memory |
; ebx is not changed |
; \end{diamond}[18.03.2006] |
; Extract parameters |
; add eax, std_application_base_address ; abs start of info block |
cmp dword [eax+0], 15; GET_DISK_INFO |
je fs_info |
cmp dword [CURRENT_TASK], 1; no memory checks for kernel requests |
jz no_checks_for_kernel |
mov edx, eax |
cmp dword [eax+0], 1 |
jnz .usual_check |
mov ebx, [eax+12] |
; add ebx,std_application_base_address |
mov ecx, [eax+8] |
call check_region |
test eax, eax |
jnz area_in_app_mem |
.error_output: |
mov esi, buffer_failed |
call sys_msg_board_str |
; mov eax,7 |
mov dword [esp+36], 7 |
ret |
iglobal |
buffer_failed db 'K : Buffer check failed',13,10,0 |
endg |
.usual_check: |
cmp dword [eax+0], 0 |
mov ecx, 512 |
jnz .small_size |
mov ecx, [eax+8] |
shl ecx, 9 |
.small_size: |
mov ebx, [eax+12] |
; add ebx,std_application_base_address |
call check_region |
test eax, eax |
jz .error_output |
area_in_app_mem: |
mov eax, edx |
no_checks_for_kernel: |
fs_read: |
mov ebx, [eax+20] ; program wants root directory ? |
test bl, bl |
je fs_getroot |
test bh, bh |
jne fs_noroot |
fs_getroot: |
; \begin{diamond}[18.03.2006] |
; root - only read is allowed |
; other operations return "access denied", eax=10 |
; (execute operation returns eax=-10) |
cmp dword [eax], 0 |
jz .read_root |
mov dword [esp+36], 10 |
ret |
.read_root: |
; \end{diamond}[18.03.2006] |
mov esi, dir0 |
mov edi, [eax+12] |
; add edi,std_application_base_address |
mov ecx, 11 |
push ecx |
; cld ; already is |
rep movsb |
mov al, 0x10 |
stosb |
add edi, 32-11-1 |
pop ecx |
rep movsb |
stosb |
and dword [esp+36], 0; ok read |
mov dword [esp+24], 32*2; size of root |
ret |
fs_info: ;start of code - Mihasik |
push eax |
cmp [eax+21], byte 'h' |
je fs_info_h |
cmp [eax+21], byte 'H' |
je fs_info_h |
cmp [eax+21], byte 'r' |
je fs_info_r |
cmp [eax+21], byte 'R' |
je fs_info_r |
mov eax, 3 ;if unknown disk |
xor ebx, ebx |
xor ecx, ecx |
xor edx, edx |
jmp fs_info1 |
fs_info_r: |
call ramdisk_free_space;if ramdisk |
mov ecx, edi ;free space in ecx |
shr ecx, 9 ;free clusters |
mov ebx, 2847 ;total clusters |
mov edx, 512 ;cluster size |
xor eax, eax ;always 0 |
jmp fs_info1 |
fs_info_h: ;if harddisk |
call get_hd_info |
fs_info1: |
pop edi |
mov [esp+36], eax |
mov [esp+24], ebx ; total clusters on disk |
mov [esp+32], ecx ; free clusters on disk |
mov [edi], edx ; cluster size in bytes |
ret ;end of code - Mihasik |
fs_noroot: |
push dword [eax+0] ; read/write/delete/.../makedir/rename/lba/run |
push dword [eax+4] ; 512 block number to read |
push dword [eax+8] ; bytes to write/append or 512 blocks to read |
mov ebx, [eax+12] |
; add ebx,std_application_base_address |
push ebx ; abs start of return/save area |
lea esi, [eax+20] ; abs start of dir + filename |
mov edi, [eax+16] |
; add edi,std_application_base_address ; abs start of work area |
call expand_pathz |
push edi ; dir start |
push ebx ; name of file start |
mov eax, [edi+1] |
cmp eax, 'RD ' |
je fs_yesramdisk |
cmp eax, 'RAMD' |
jne fs_noramdisk |
fs_yesramdisk: |
cmp byte [edi+1+11], 0 |
je fs_give_dir1 |
mov eax, [edi+1+12] |
cmp eax, '1 ' |
je fs_yesramdisk_first |
cmp eax, 'FIRS' |
jne fs_noramdisk |
fs_yesramdisk_first: |
cmp dword [esp+20], 8; LBA read ramdisk |
jne fs_no_LBA_read_ramdisk |
mov eax, [esp+16] ; LBA block to read |
mov ecx, [esp+8] ; abs pointer to return area |
call LBA_read_ramdisk |
jmp file_system_return |
fs_no_LBA_read_ramdisk: |
cmp dword [esp+20], 0; READ |
jne fs_noramdisk_read |
mov eax, [esp+4] ; fname |
add eax, 2*12+1 |
mov ebx, [esp+16] ; block start |
inc ebx |
mov ecx, [esp+12] ; block count |
mov edx, [esp+8] ; return |
mov esi, [esp+0] |
sub esi, eax |
add esi, 12+1 ; file name length |
call fileread |
jmp file_system_return |
fs_noramdisk_read: |
fs_noramdisk: |
;******************************************************************** |
mov eax, [edi+1] |
cmp eax, 'FD ' |
je fs_yesflpdisk |
cmp eax, 'FLOP' |
jne fs_noflpdisk |
fs_yesflpdisk: |
call reserve_flp |
cmp byte [edi+1+11], 0 |
je fs_give_dir1 |
mov eax, [edi+1+12] |
cmp eax, '1 ' |
je fs_yesflpdisk_first |
cmp eax, 'FIRS' |
je fs_yesflpdisk_first |
cmp eax, '2 ' |
je fs_yesflpdisk_second |
cmp eax, 'SECO' |
jne fs_noflpdisk |
jmp fs_yesflpdisk_second |
fs_yesflpdisk_first: |
mov [flp_number], 1 |
jmp fs_yesflpdisk_start |
fs_yesflpdisk_second: |
mov [flp_number], 2 |
fs_yesflpdisk_start: |
cmp dword [esp+20], 0; READ |
jne fs_noflpdisk_read |
mov eax, [esp+4] ; fname |
add eax, 2*12+1 |
mov ebx, [esp+16] ; block start |
inc ebx |
mov ecx, [esp+12] ; block count |
mov edx, [esp+8] ; return |
mov esi, [esp+0] |
sub esi, eax |
add esi, 12+1 ; file name length |
call floppy_fileread |
jmp file_system_return |
fs_noflpdisk_read: |
fs_noflpdisk: |
;***************************************************************** |
mov eax, [edi+1] |
cmp eax, 'HD0 ' |
je fs_yesharddisk_IDE0 |
cmp eax, 'HD1 ' |
je fs_yesharddisk_IDE1 |
cmp eax, 'HD2 ' |
je fs_yesharddisk_IDE2 |
cmp eax, 'HD3 ' |
je fs_yesharddisk_IDE3 |
jmp old_path_harddisk |
fs_yesharddisk_IDE0: |
call reserve_hd1 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x0 |
mov [hdpos], 1 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE1: |
call reserve_hd1 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x10 |
mov [hdpos], 2 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE2: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0x0 |
mov [hdpos], 3 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE3: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0x10 |
mov [hdpos], 4 |
fs_yesharddisk_partition: |
call reserve_hd_channel |
; call choice_necessity_partition |
; jmp fs_yesharddisk_all |
jmp fs_for_new_semantic |
choice_necessity_partition: |
mov eax, [edi+1+12] |
call StringToNumber |
mov [fat32part], eax |
choice_necessity_partition_1: |
mov ecx, [hdpos] |
xor eax, eax |
mov [hd_entries], eax; entries in hd cache |
mov edx, DRIVE_DATA+2 |
cmp ecx, 0x80 |
jb search_partition_array |
mov ecx, 4 |
search_partition_array: |
mov bl, [edx] |
movzx ebx, bl |
add eax, ebx |
inc edx |
loop search_partition_array |
mov ecx, [hdpos] |
mov edx, BiosDiskPartitions |
sub ecx, 0x80 |
jb .s |
je .f |
@@: |
mov ebx, [edx] |
add edx, 4 |
add eax, ebx |
loop @b |
jmp .f |
.s: |
sub eax, ebx |
.f: |
add eax, [known_part]; add eax,[fat32part] |
dec eax |
xor edx, edx |
imul eax, 100 |
add eax, DRIVE_DATA+0xa |
mov [transfer_adress], eax |
call partition_data_transfer_1 |
ret |
old_path_harddisk: |
mov eax, [edi+1] |
cmp eax, 'HD ' |
je fs_yesharddisk |
cmp eax, 'HARD' |
jne fs_noharddisk |
fs_yesharddisk: |
cmp dword [esp+20], 8; LBA read |
jne fs_no_LBA_read |
mov eax, [esp+16] ; LBA block to read |
lea ebx, [edi+1+12] ; pointer to FIRST/SECOND/THIRD/FOURTH |
mov ecx, [esp+8] ; abs pointer to return area |
call LBA_read |
jmp file_system_return |
fs_no_LBA_read: |
cmp byte [edi+1+11], 0; directory read |
je fs_give_dir1 |
call reserve_hd1 |
fs_for_new_semantic: |
call choice_necessity_partition |
fs_yesharddisk_all: |
mov eax, 1 |
mov ebx, [esp+24+24] |
cmp [hdpos], 0 ; is hd base set? |
jz hd_err_return |
cmp [fat32part], 0 ; is partition set? |
jnz @f |
hd_err_return: |
call free_hd_channel |
and [hd1_status], 0 |
jmp file_system_return |
@@: |
cmp dword [esp+20], 0; READ |
jne fs_noharddisk_read |
mov eax, [esp+0] ; /fname |
lea edi, [eax+12] |
mov byte [eax], 0 ; path to asciiz |
inc eax ; filename start |
mov ebx, [esp+12] ; count to read |
mov ecx, [esp+8] ; buffer |
mov edx, [esp+4] |
add edx, 12*2 ; dir start |
sub edi, edx ; path length |
mov esi, [esp+16] ; blocks to read |
call file_read |
mov edi, [esp+0] |
mov byte [edi], '/' |
call free_hd_channel |
and [hd1_status], 0 |
jmp file_system_return |
fs_noharddisk_read: |
call free_hd_channel |
and [hd1_status], 0 |
fs_noharddisk: |
; \begin{diamond}[18.03.2006] |
mov eax, 5 ; file not found |
; à ìîæåò áûòü, âîçâðàùàòü äðóãîé êîä îøèáêè? |
mov ebx, [esp+24+24]; do not change ebx in application |
; \end{diamond}[18.03.2006] |
file_system_return: |
add esp, 24 |
mov [esp+36], eax |
mov [esp+24], ebx |
ret |
fs_give_dir1: |
; \begin{diamond}[18.03.2006] |
; /RD,/FD,/HD - only read is allowed |
; other operations return "access denied", eax=10 |
; (execute operation returns eax=-10) |
cmp dword [esp+20], 0 |
jz .read |
add esp, 20 |
pop ecx |
mov dword [esp+36], 10 |
ret |
.read: |
; \end{diamond}[18.03.2006] |
mov al, 0x10 |
mov ebx, 1 |
mov edi, [esp+8] |
mov esi, dir1 |
fs_d1_new: |
mov ecx, 11 |
; cld |
rep movsb |
stosb |
add edi, 32-11-1 |
dec ebx |
jne fs_d1_new |
add esp, 24 |
and dword [esp+36], 0; ok read |
mov dword [esp+24], 32*1; dir/data size |
ret |
LBA_read_ramdisk: |
cmp [lba_read_enabled], 1 |
je lbarrl1 |
xor ebx, ebx |
mov eax, 2 |
ret |
lbarrl1: |
cmp eax, 18*2*80 |
jb lbarrl2 |
xor ebx, ebx |
mov eax, 3 |
ret |
lbarrl2: |
pushad |
call restorefatchain |
mov edi, ecx |
mov esi, eax |
shl esi, 9 |
add esi, RAMDISK |
mov ecx, 512/4 |
; cld |
rep movsd |
popad |
xor ebx, ebx |
xor eax, eax |
ret |
LBA_read: |
; IN: |
; |
; eax = LBA block to read |
; ebx = pointer to FIRST/SECOND/THIRD/FOURTH |
; ecx = abs pointer to return area |
cmp [lba_read_enabled], 1 |
je lbarl1 |
mov eax, 2 |
ret |
lbarl1: |
call reserve_hd1 |
push eax |
push ecx |
mov edi, hd_address_table |
mov esi, dir1 |
mov eax, [ebx] |
mov edx, '1 ' |
mov ecx, 4 |
blar0: |
cmp eax, [esi] |
je blar2 |
cmp eax, edx |
je blar2 |
inc edx |
add edi, 8 |
add esi, 11 |
dec ecx |
jnz blar0 |
mov eax, 1 |
mov ebx, 1 |
jmp LBA_read_ret |
blar2: |
mov eax, [edi+0] |
mov ebx, [edi+4] |
mov [hdbase], eax |
mov [hdid], ebx |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jne hd_lba_error |
; eax = hd port |
; ebx = set for primary (0x00) or slave (0x10) |
cli |
mov edx, eax |
inc edx |
xor eax, eax |
out dx, al |
inc edx |
inc eax |
out dx, al |
inc edx |
mov eax, [esp+4] |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
out dx, al |
shr eax, 8 |
inc edx |
and al, 1+2+4+8 |
add al, bl |
add al, 128+64+32 |
out dx, al |
inc edx |
mov al, 20h |
out dx, al |
sti |
call wait_for_sector_buffer |
cmp [hd_error], 0 |
jne hd_lba_error |
cli |
mov edi, [esp+0] |
mov ecx, 256 |
sub edx, 7 |
cld |
rep insw |
sti |
xor eax, eax |
xor ebx, ebx |
LBA_read_ret: |
mov [hd_error], 0 |
mov [hd1_status], 0 |
add esp, 2*4 |
ret |
expand_pathz: |
; IN: |
; esi = asciiz path & file |
; edi = buffer for path & file name |
; OUT: |
; edi = directory & file : / 11 + / 11 + / 11 - zero terminated |
; ebx = /file name - zero terminated |
; esi = pointer after source |
push eax |
push ecx |
push edi;[esp+0] |
pathz_start: |
mov byte [edi], '/' |
inc edi |
mov al, 32 |
mov ecx, 11 |
cld |
rep stosb ; clear filename area |
sub edi, 11 |
mov ebx, edi ; start of dir/file name |
pathz_new_char: |
mov al, [esi] |
inc esi |
cmp al, 0 |
je pathz_end |
cmp al, '/' |
jne pathz_not_path |
cmp edi, ebx ; skip first '/' |
jz pathz_new_char |
lea edi, [ebx+11] ; start of next directory |
jmp pathz_start |
pathz_not_path: |
cmp al, '.' |
jne pathz_not_ext |
lea edi, [ebx+8] ; start of extension |
jmp pathz_new_char |
pathz_not_ext: |
cmp al, 'a' |
jb pathz_not_low |
cmp al, 'z' |
ja pathz_not_low |
sub al, 0x20 ; char to uppercase |
pathz_not_low: |
mov [edi], al |
inc edi |
mov eax, [esp+0] ; start_of_dest_path |
add eax, 512 ; keep maximum path under 512 bytes |
cmp edi, eax |
jb pathz_new_char |
pathz_end: |
cmp ebx, edi ; if path end with '/' |
jnz pathz_put_zero ; go back 1 level |
sub ebx, 12 |
pathz_put_zero: |
mov byte [ebx+11], 0 |
dec ebx ; include '/' char into file name |
pop edi |
pop ecx |
pop eax |
ret |
;******************************************* |
;* string to number |
;* input eax - 4 byte string |
;* output eax - number |
;******************************************* |
StringToNumber: |
; ÏÅÐÅÂÎÄ ÑÒÐÎÊÎÂÎÃÎ ×ÈÑËÀ  ×ÈÑËÎÂÎÉ ÂÈÄ |
; Âõîä: |
; EDI - àäðåñ ñòðîêè ñ ÷èñëîì. Êîíåö ÷èñëà îòìå÷åí êîäîì 0Dh |
; Âûõîä: |
; CF - èíäèêàòîð îøèáîê: |
; 0 - îøèáîê íåò; |
; 1 - îøèáêà |
; Åñëè CF=0, òî AX - ÷èñëî. |
push bx |
push cx |
push dx |
push edi |
mov [partition_string], eax |
mov edi, partition_string |
xor cx, cx |
i1: |
mov al, [edi] |
cmp al, 32;13 |
je i_exit |
; cmp al,'0' |
; jb err |
; cmp al,'9' |
; ja err |
sub al, 48 |
shl cx, 1 |
jc error |
mov bx, cx |
shl cx, 1 |
jc error |
shl cx, 1 |
jc error |
add cx, bx |
jc error |
cbw |
add cx, ax |
jc error |
i3: |
inc edi |
jmp i1 |
i_exit: |
mov ax, cx |
clc |
i4: |
movzx eax, ax |
pop edi |
pop dx |
pop cx |
pop bx |
ret |
error: |
stc |
jmp i4 |
partition_string: |
dd 0 |
db 32 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fs/fs_lfn.inc |
---|
1,1148 → 1,1150 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
image_of_eax EQU esp+32 |
image_of_ebx EQU esp+20 |
; System function 70 - files with long names (LFN) |
; diamond, 2006 |
iglobal |
; in this table names must be in lowercase |
rootdirs: |
db 2,'rd' |
dd fs_OnRamdisk |
dd fs_NextRamdisk |
db 7,'ramdisk' |
dd fs_OnRamdisk |
dd fs_NextRamdisk |
db 2,'fd' |
dd fs_OnFloppy |
dd fs_NextFloppy |
db 10,'floppydisk' |
dd fs_OnFloppy |
dd fs_NextFloppy |
db 3,'hd0' |
dd fs_OnHd0 |
dd fs_NextHd0 |
db 3,'hd1' |
dd fs_OnHd1 |
dd fs_NextHd1 |
db 3,'hd2' |
dd fs_OnHd2 |
dd fs_NextHd2 |
db 3,'hd3' |
dd fs_OnHd3 |
dd fs_NextHd3 |
;********************************************** |
db 3,'cd0' |
dd fs_OnCd0 |
dd fs_NextCd |
db 3,'cd1' |
dd fs_OnCd1 |
dd fs_NextCd |
db 3,'cd2' |
dd fs_OnCd2 |
dd fs_NextCd |
db 3,'cd3' |
dd fs_OnCd3 |
dd fs_NextCd |
;*********************************************** |
db 0 |
virtual_root_query: |
dd fs_HasRamdisk |
db 'rd',0 |
dd fs_HasFloppy |
db 'fd',0 |
dd fs_HasHd0 |
db 'hd0',0 |
dd fs_HasHd1 |
db 'hd1',0 |
dd fs_HasHd2 |
db 'hd2',0 |
dd fs_HasHd3 |
db 'hd3',0 |
;********************************************** |
dd fs_HasCd0 |
db 'cd0',0 |
dd fs_HasCd1 |
db 'cd1',0 |
dd fs_HasCd2 |
db 'cd2',0 |
dd fs_HasCd3 |
db 'cd3',0 |
;********************************************** |
dd 0 |
fs_additional_handlers: |
dd biosdisk_handler, biosdisk_enum_root |
dd dyndisk_handler, dyndisk_enum_root |
; add new handlers here |
dd 0 |
endg |
file_system_lfn: |
; in: ebx->fileinfo block |
; operation codes: |
; 0 : read file |
; 1 : read folder |
; 2 : create/rewrite file |
; 3 : write/append to file |
; 4 : set end of file |
; 5 : get file/directory attributes structure |
; 6 : set file/directory attributes structure |
; 7 : start application |
; 8 : delete file |
; 9 : create directory |
; parse file name |
lea esi, [ebx+20] |
lodsb |
test al, al |
jnz @f |
mov esi, [esi] |
lodsb |
@@: |
cmp al, '/' |
jz .notcurdir |
dec esi |
mov ebp, esi |
test al, al |
jnz @f |
xor ebp, ebp |
@@: |
mov esi, [current_slot] |
mov esi, [esi+APPDATA.cur_dir] |
jmp .parse_normal |
.notcurdir: |
cmp byte [esi], 0 |
jz .rootdir |
call process_replace_file_name |
.parse_normal: |
cmp dword [ebx], 7 |
jne @F |
mov edx, [ebx+4] |
mov ebx, [ebx+8] |
call fs_execute ; esi+ebp, ebx, edx |
mov [image_of_eax], eax |
ret |
@@: |
mov edi, rootdirs-8 |
xor ecx, ecx |
push esi |
.scan1: |
pop esi |
add edi, ecx |
scasd |
scasd |
mov cl, byte [edi] |
test cl, cl |
jz .notfound_try |
inc edi |
push esi |
@@: |
lodsb |
or al, 20h |
scasb |
loopz @b |
jnz .scan1 |
lodsb |
cmp al, '/' |
jz .found1 |
test al, al |
jnz .scan1 |
pop eax |
; directory /xxx |
.maindir: |
mov esi, [edi+4] |
.maindir_noesi: |
cmp dword [ebx], 1 |
jnz .access_denied |
xor eax, eax |
mov ebp, [ebx+12] ;количество блоков для считывания |
mov edx, [ebx+16] ;куда записывать рузельтат |
; add edx, std_application_base_address |
push dword [ebx+4] ; first block |
mov ebx, [ebx+8] ; flags |
; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler |
mov edi, edx |
push ecx |
mov ecx, 32/4 |
rep stosd |
pop ecx |
mov byte [edx], 1 ; version |
.maindir_loop: |
call esi |
jc .maindir_done |
inc dword [edx+8] |
dec dword [esp] |
jns .maindir_loop |
dec ebp |
js .maindir_loop |
inc dword [edx+4] |
mov dword [edi], 0x10 ; attributes: folder |
mov dword [edi+4], 1 ; name type: UNICODE |
push eax |
xor eax, eax |
add edi, 8 |
push ecx |
mov ecx, 40/4-2 |
rep stosd |
pop ecx |
pop eax |
push eax edx |
; convert number in eax to decimal UNICODE string |
push edi |
push ecx |
push -'0' |
mov ecx, 10 |
@@: |
xor edx, edx |
div ecx |
push edx |
test eax, eax |
jnz @b |
@@: |
pop eax |
add al, '0' |
stosb |
test bl, 1 ; UNICODE name? |
jz .ansi2 |
mov byte [edi], 0 |
inc edi |
.ansi2: |
test al, al |
jnz @b |
mov byte [edi-1], 0 |
pop ecx |
pop edi |
; UNICODE name length is 520 bytes, ANSI - 264 |
add edi, 520 |
test bl, 1 |
jnz @f |
sub edi, 520-264 |
@@: |
pop edx eax |
jmp .maindir_loop |
.maindir_done: |
pop eax |
mov ebx, [edx+4] |
xor eax, eax |
dec ebp |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
; directory / |
.rootdir: |
cmp dword [ebx], 1 ; read folder? |
jz .readroot |
.access_denied: |
mov dword [image_of_eax], 10 ; access denied |
ret |
.readroot: |
; virtual root folder - special handler |
mov esi, virtual_root_query |
mov ebp, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
push dword [ebx+4] ; first block |
mov ebx, [ebx+8] ; flags |
xor eax, eax |
; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area |
mov edi, edx |
mov ecx, 32/4 |
rep stosd |
mov byte [edx], 1 ; version |
.readroot_loop: |
cmp dword [esi], eax |
jz .readroot_done_static |
call dword [esi] |
add esi, 4 |
test eax, eax |
jnz @f |
.readroot_next: |
or ecx, -1 |
xchg esi, edi |
repnz scasb |
xchg esi, edi |
jmp .readroot_loop |
@@: |
xor eax, eax |
inc dword [edx+8] |
dec dword [esp] |
jns .readroot_next |
dec ebp |
js .readroot_next |
inc dword [edx+4] |
mov dword [edi], 0x10 ; attributes: folder |
mov dword [edi+4], ebx ; name type: UNICODE |
add edi, 8 |
mov ecx, 40/4-2 |
rep stosd |
push edi |
@@: |
lodsb |
stosb |
test bl, 1 |
jz .ansi |
mov byte [edi], 0 |
inc edi |
.ansi: |
test eax, eax |
jnz @b |
pop edi |
add edi, 520 |
test bl, 1 |
jnz .readroot_loop |
sub edi, 520-264 |
jmp .readroot_loop |
.readroot_done_static: |
mov esi, fs_additional_handlers-8 |
sub esp, 16 |
.readroot_ah_loop: |
add esi, 8 |
cmp dword [esi], 0 |
jz .readroot_done |
xor eax, eax |
.readroot_ah_loop2: |
push edi |
lea edi, [esp+4] |
call dword [esi+4] |
pop edi |
test eax, eax |
jz .readroot_ah_loop |
inc dword [edx+8] |
dec dword [esp+16] |
jns .readroot_ah_loop2 |
dec ebp |
js .readroot_ah_loop2 |
push eax |
xor eax, eax |
inc dword [edx+4] |
mov dword [edi], 0x10 ; attributes: folder |
mov dword [edi+4], ebx |
add edi, 8 |
mov ecx, 40/4-2 |
rep stosd |
push esi edi |
lea esi, [esp+12] |
@@: |
lodsb |
stosb |
test bl, 1 |
jz .ansi3 |
mov byte [edi], 0 |
inc edi |
.ansi3: |
test al, al |
jnz @b |
pop edi esi eax |
add edi, 520 |
test bl, 1 |
jnz .readroot_ah_loop2 |
sub edi, 520-264 |
jmp .readroot_ah_loop2 |
.readroot_done: |
add esp, 16 |
pop eax |
mov ebx, [edx+4] |
xor eax, eax |
dec ebp |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.notfound_try: |
mov edi, fs_additional_handlers |
@@: |
cmp dword [edi], 0 |
jz .notfound |
call dword [edi] |
scasd |
scasd |
jmp @b |
.notfound: |
mov dword [image_of_eax], ERROR_FILE_NOT_FOUND |
and dword [image_of_ebx], 0 |
ret |
.notfounda: |
cmp edi, esp |
jnz .notfound |
call dword [edi+4] |
add esp, 16 |
jmp .notfound |
.found1: |
pop eax |
cmp byte [esi], 0 |
jz .maindir |
.found2: |
; read partition number |
xor ecx, ecx |
xor eax, eax |
@@: |
lodsb |
cmp al, '/' |
jz .done1 |
test al, al |
jz .done1 |
sub al, '0' |
cmp al, 9 |
ja .notfounda |
lea ecx, [ecx*5] |
lea ecx, [ecx*2+eax] |
jmp @b |
.done1: |
jecxz .notfounda |
test al, al |
jnz @f |
dec esi |
@@: |
cmp byte [esi], 0 |
jnz @f |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
@@: |
; now [edi] contains handler address, ecx - partition number, |
; esi points to ASCIIZ string - rest of name |
jmp dword [edi] |
; handlers for devices |
; in: ecx = 0 => query virtual directory /xxx |
; in: ecx = partition number |
; esi -> relative (for device) name |
; ebx -> fileinfo |
; ebp = 0 or pointer to rest of name from folder addressed by esi |
; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx |
fs_OnRamdisk: |
cmp ecx, 1 |
jnz file_system_lfn.notfound |
mov eax, [ebx] |
cmp eax, fs_NumRamdiskServices |
jae .not_impl |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
add ebx, 4 |
call dword [fs_RamdiskServices + eax*4] |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_NotImplemented: |
mov eax, 2 |
ret |
fs_RamdiskServices: |
dd fs_RamdiskRead |
dd fs_RamdiskReadFolder |
dd fs_RamdiskRewrite |
dd fs_RamdiskWrite |
dd fs_RamdiskSetFileEnd |
dd fs_RamdiskGetFileInfo |
dd fs_RamdiskSetFileInfo |
dd 0 |
dd fs_RamdiskDelete |
dd fs_RamdiskCreateFolder |
fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4 |
fs_OnFloppy: |
cmp ecx, 2 |
ja file_system_lfn.notfound |
mov eax, [ebx] |
cmp eax, fs_NumFloppyServices |
jae fs_OnRamdisk.not_impl |
call reserve_flp |
mov [flp_number], cl |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
add ebx, 4 |
call dword [fs_FloppyServices + eax*4] |
and [flp_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
fs_FloppyServices: |
dd fs_FloppyRead |
dd fs_FloppyReadFolder |
dd fs_FloppyRewrite |
dd fs_FloppyWrite |
dd fs_FloppySetFileEnd |
dd fs_FloppyGetFileInfo |
dd fs_FloppySetFileInfo |
dd 0 |
dd fs_FloppyDelete |
dd fs_FloppyCreateFolder |
fs_NumFloppyServices = ($ - fs_FloppyServices)/4 |
fs_OnHd0: |
call reserve_hd1 |
mov [hdbase], 0x1F0 |
mov [hdid], 0 |
push 1 |
jmp fs_OnHd |
fs_OnHd1: |
call reserve_hd1 |
mov [hdbase], 0x1F0 |
mov [hdid], 0x10 |
push 2 |
jmp fs_OnHd |
fs_OnHd2: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0 |
push 3 |
jmp fs_OnHd |
fs_OnHd3: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0x10 |
push 4 |
fs_OnHd: |
call reserve_hd_channel |
pop eax |
mov [hdpos], eax |
cmp ecx, 0x100 |
jae fs_OnHdAndBd.nf |
cmp cl, [DRIVE_DATA+1+eax] |
fs_OnHdAndBd: |
jbe @f |
.nf: |
call free_hd_channel |
and [hd1_status], 0 |
mov dword [image_of_eax], 5 ; not found |
ret |
@@: |
mov [known_part], ecx ; mov [fat32part], ecx |
push ebx esi |
call choice_necessity_partition_1 |
pop esi ebx |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
mov eax, [ebx] |
cmp eax, fs_NumHdServices |
jae .not_impl |
add ebx, 4 |
call dword [fs_HdServices + eax*4] |
call free_hd_channel |
and [hd1_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
call free_hd_channel |
and [hd1_status], 0 |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_HdServices: |
dd fs_HdRead |
dd fs_HdReadFolder |
dd fs_HdRewrite |
dd fs_HdWrite |
dd fs_HdSetFileEnd |
dd fs_HdGetFileInfo |
dd fs_HdSetFileInfo |
dd 0 |
dd fs_HdDelete |
dd fs_HdCreateFolder |
fs_NumHdServices = ($ - fs_HdServices)/4 |
;******************************************************* |
fs_OnCd0: |
call reserve_cd |
mov [ChannelNumber],1 |
mov [DiskNumber],0 |
push 6 |
push 1 |
jmp fs_OnCd |
fs_OnCd1: |
call reserve_cd |
mov [ChannelNumber],1 |
mov [DiskNumber],1 |
push 4 |
push 2 |
jmp fs_OnCd |
fs_OnCd2: |
call reserve_cd |
mov [ChannelNumber],2 |
mov [DiskNumber],0 |
push 2 |
push 3 |
jmp fs_OnCd |
fs_OnCd3: |
call reserve_cd |
mov [ChannelNumber],2 |
mov [DiskNumber],1 |
push 0 |
push 4 |
fs_OnCd: |
call reserve_cd_channel |
pop eax |
mov [cdpos], eax |
pop eax |
cmp ecx, 0x100 |
jae .nf |
push ecx ebx |
mov cl,al |
mov bl,[DRIVE_DATA+1] |
shr bl,cl |
test bl,2 |
pop ebx ecx |
jnz @f |
.nf: |
call free_cd_channel |
and [cd_status], 0 |
mov dword [image_of_eax], 5 ; not found |
ret |
@@: |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
mov eax, [ebx] |
cmp eax,fs_NumCdServices |
jae .not_impl |
add ebx, 4 |
call dword [fs_CdServices + eax*4] |
call free_cd_channel |
and [cd_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
call free_cd_channel |
and [cd_status], 0 |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_CdServices: |
dd fs_CdRead |
dd fs_CdReadFolder |
dd fs_NotImplemented |
dd fs_NotImplemented |
dd fs_NotImplemented |
dd fs_CdGetFileInfo |
dd fs_NotImplemented |
dd 0 |
dd fs_NotImplemented |
dd fs_NotImplemented |
fs_NumCdServices = ($ - fs_CdServices)/4 |
;******************************************************* |
fs_HasRamdisk: |
mov al, 1 ; we always have ramdisk |
ret |
fs_HasFloppy: |
cmp byte [DRIVE_DATA], 0 |
setnz al |
ret |
fs_HasHd0: |
mov al, [DRIVE_DATA+1] |
and al, 11000000b |
cmp al, 01000000b |
setz al |
ret |
fs_HasHd1: |
mov al, [DRIVE_DATA+1] |
and al, 00110000b |
cmp al, 00010000b |
setz al |
ret |
fs_HasHd2: |
mov al, [DRIVE_DATA+1] |
and al, 00001100b |
cmp al, 00000100b |
setz al |
ret |
fs_HasHd3: |
mov al, [DRIVE_DATA+1] |
and al, 00000011b |
cmp al, 00000001b |
setz al |
ret |
;******************************************************* |
fs_HasCd0: |
mov al, [DRIVE_DATA+1] |
and al, 11000000b |
cmp al, 10000000b |
setz al |
ret |
fs_HasCd1: |
mov al, [DRIVE_DATA+1] |
and al, 00110000b |
cmp al, 00100000b |
setz al |
ret |
fs_HasCd2: |
mov al, [DRIVE_DATA+1] |
and al, 00001100b |
cmp al, 00001000b |
setz al |
ret |
fs_HasCd3: |
mov al, [DRIVE_DATA+1] |
and al, 00000011b |
cmp al, 00000010b |
setz 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_NextRamdisk: |
; we always have /rd/1 |
test eax, eax |
stc |
jnz @f |
mov al, 1 |
clc |
@@: |
ret |
fs_NextFloppy: |
; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0) |
test byte [DRIVE_DATA], 0xF0 |
jz .no1 |
test eax, eax |
jnz .no1 |
inc eax |
ret ; CF cleared |
.no1: |
test byte [DRIVE_DATA], 0x0F |
jz .no2 |
cmp al, 2 |
jae .no2 |
mov al, 2 |
clc |
ret |
.no2: |
stc |
ret |
; on hdx, we have partitions from 1 to [0x40002+x] |
fs_NextHd0: |
push 0 |
jmp fs_NextHd |
fs_NextHd1: |
push 1 |
jmp fs_NextHd |
fs_NextHd2: |
push 2 |
jmp fs_NextHd |
fs_NextHd3: |
push 3 |
fs_NextHd: |
pop ecx |
movzx ecx, byte [DRIVE_DATA+2+ecx] |
cmp eax, ecx |
jae fs_NextFloppy.no2 |
inc eax |
clc |
ret |
;******************************************************* |
fs_NextCd: |
; we always have /cdX/1 |
test eax, eax |
stc |
jnz @f |
mov al, 1 |
clc |
@@: |
ret |
;******************************************************* |
; Additional FS handlers. |
; This handler gets the control each time when fn 70 is called |
; with unknown item of root subdirectory. |
; in: esi -> name |
; ebp = 0 or rest of name relative to esi |
; out: if the handler processes path, he must not return in file_system_lfn, |
; but instead pop return address and return directly to the caller |
; otherwise simply return |
; here we test for /bd<N>/... - BIOS disks |
biosdisk_handler: |
cmp [NumBiosDisks], 0 |
jz .ret |
mov al, [esi] |
or al, 20h |
cmp al, 'b' |
jnz .ret |
mov al, [esi+1] |
or al, 20h |
cmp al, 'd' |
jnz .ret |
push esi |
inc esi |
inc esi |
cmp byte [esi], '0' |
jb .ret2 |
cmp byte [esi], '9' |
ja .ret2 |
xor edx, edx |
@@: |
lodsb |
test al, al |
jz .ok |
cmp al, '/' |
jz .ok |
sub al, '0' |
cmp al, 9 |
ja .ret2 |
lea edx, [edx*5] |
lea edx, [edx*2+eax] |
jmp @b |
.ret2: |
pop esi |
.ret: |
ret |
.ok: |
cmp al, '/' |
jz @f |
dec esi |
@@: |
add dl, 80h |
xor ecx, ecx |
@@: |
cmp dl, [BiosDisksData+ecx*4] |
jz .ok2 |
inc ecx |
cmp ecx, [NumBiosDisks] |
jb @b |
jmp .ret2 |
.ok2: |
add esp, 8 |
test al, al |
jnz @f |
mov esi, fs_BdNext |
jmp file_system_lfn.maindir_noesi |
@@: |
push ecx |
push ecx |
push biosdisk_cleanup |
push fs_OnBd |
mov edi, esp |
jmp file_system_lfn.found2 |
fs_BdNext: |
cmp eax, [BiosDiskPartitions+ecx*4] |
inc eax |
cmc |
biosdisk_cleanup: |
ret |
fs_OnBd: |
pop edx edx edx edx |
; edx = disk number, ecx = partition number |
; esi+ebp = name |
call reserve_hd1 |
add edx, 0x80 |
mov [hdpos], edx |
cmp ecx, [BiosDiskPartitions+(edx-0x80)*4] |
jmp fs_OnHdAndBd |
; This handler is called when virtual root is enumerated |
; and must return all items which can be handled by this. |
; It is called several times, first time with eax=0 |
; in: eax = 0 for first call, previously returned value for subsequent calls |
; out: eax = 0 => no more items |
; eax != 0 => buffer pointed to by edi contains name of item |
; here we enumerate existing BIOS disks /bd<N> |
biosdisk_enum_root: |
cmp eax, [NumBiosDisks] |
jae .end |
push eax |
movzx eax, byte [BiosDisksData+eax*4] |
sub al, 80h |
push eax |
mov al, 'b' |
stosb |
mov al, 'd' |
stosb |
pop eax |
cmp al, 10 |
jae .big |
add al, '0' |
stosb |
mov byte [edi], 0 |
pop eax |
inc eax |
ret |
.end: |
xor eax, eax |
ret |
.big: |
push ecx edx |
push -'0' |
mov ecx, 10 |
@@: |
xor edx, edx |
div ecx |
push edx |
test eax, eax |
jnz @b |
xchg eax, edx |
@@: |
pop eax |
add al, '0' |
stosb |
jnz @b |
pop edx ecx |
pop eax |
inc eax |
ret |
process_replace_file_name: |
mov ebp, [full_file_name_table] |
mov edi, [full_file_name_table.size] |
dec edi |
shl edi, 7 |
add edi, ebp |
.loop: |
cmp edi, ebp |
jb .notfound |
push esi edi |
@@: |
cmp byte [edi], 0 |
jz .dest_done |
lodsb |
test al, al |
jz .cont |
or al, 20h |
scasb |
jz @b |
jmp .cont |
.dest_done: |
cmp byte [esi], 0 |
jz .found |
cmp byte [esi], '/' |
jnz .cont |
inc esi |
jmp .found |
.cont: |
pop edi esi |
sub edi, 128 |
jmp .loop |
.found: |
pop edi eax |
mov ebp, esi |
cmp byte [esi], 0 |
lea esi, [edi+64] |
jnz .ret |
.notfound: |
xor ebp, ebp |
.ret: |
ret |
sys_current_directory: |
; mov esi, [current_slot] |
; mov esi, [esi+APPDATA.cur_dir] |
; mov edx, esi |
;get length string of appdata.cur_dir |
mov eax, [current_slot] |
mov edi, [eax+APPDATA.cur_dir] |
dec ebx |
jz .set |
dec ebx |
jz .get |
ret |
.get: |
; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len |
; for our code: ebx->buffer,ecx=len |
max_cur_dir equ 0x1000 |
mov ebx,edi |
push ecx |
push edi |
xor eax,eax |
mov ecx,max_cur_dir |
repne scasb ;find zerro at and string |
jnz .error ; no zero in cur_dir: internal error, should not happen |
sub edi,ebx ;lenght for copy |
inc edi |
mov [esp+32+8],edi ;return in eax |
cmp edx, edi |
jbe @f |
mov edx, edi |
@@: |
;source string |
pop esi |
;destination string |
pop edi |
cmp edx, 1 |
jbe .ret |
mov al,'/' ;start string with '/' |
stosb |
mov ecx,edx |
rep movsb ;copy string |
.ret: ret |
.error: add esp,8 |
or dword [esp+32],-1 ;error not found zerro at string ->[eax+APPDATA.cur_dir] |
ret |
.set: |
; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string |
; for our code: ebx->string to set |
; use generic resolver with APPDATA.cur_dir as destination |
push max_cur_dir ;0x1000 |
push edi ;destination |
mov ebx,ecx |
call get_full_file_name |
ret |
; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination |
; destroys all registers except ebp,esp |
get_full_file_name: |
push ebp |
mov esi, [current_slot] |
mov esi, [esi+APPDATA.cur_dir] |
mov edx, esi |
@@: |
inc esi |
cmp byte [esi-1], 0 |
jnz @b |
dec esi |
cmp byte [ebx], '/' |
jz .set_absolute |
; string gives relative path |
mov edi, [esp+8] ; destination |
.relative: |
cmp byte [ebx], 0 |
jz .set_ok |
cmp word [ebx], '.' |
jz .set_ok |
cmp word [ebx], './' |
jnz @f |
add ebx, 2 |
jmp .relative |
@@: |
cmp word [ebx], '..' |
jnz .doset_relative |
cmp byte [ebx+2], 0 |
jz @f |
cmp byte [ebx+2], '/' |
jnz .doset_relative |
@@: |
dec esi |
cmp byte [esi], '/' |
jnz @b |
add ebx, 3 |
jmp .relative |
.set_ok: |
cmp edx, edi ; is destination equal to APPDATA.cur_dir? |
jz .set_ok.cur_dir |
sub esi, edx |
cmp esi, [esp+12] |
jb .set_ok.copy |
.fail: |
mov byte [edi], 0 |
xor eax, eax ; fail |
pop ebp |
ret 8 |
.set_ok.copy: |
mov ecx, esi |
mov esi, edx |
rep movsb |
mov byte [edi], 0 |
.ret.ok: |
mov al, 1 ; ok |
pop ebp |
ret 8 |
.set_ok.cur_dir: |
mov byte [esi], 0 |
jmp .ret.ok |
.doset_relative: |
cmp edx, edi |
jz .doset_relative.cur_dir |
sub esi, edx |
cmp esi, [esp+12] |
jae .fail |
mov ecx, esi |
mov esi, edx |
mov edx, edi |
rep movsb |
jmp .doset_relative.copy |
.doset_relative.cur_dir: |
mov edi, esi |
.doset_relative.copy: |
add edx, [esp+12] |
mov byte [edi], '/' |
inc edi |
cmp edi, edx |
jae .overflow |
@@: |
mov al, [ebx] |
inc ebx |
stosb |
test al, al |
jz .ret.ok |
cmp edi, edx |
jb @b |
.overflow: |
dec edi |
jmp .fail |
.set_absolute: |
lea esi, [ebx+1] |
call process_replace_file_name |
mov edi, [esp+8] |
mov edx, [esp+12] |
add edx, edi |
.set_copy: |
lodsb |
stosb |
test al, al |
jz .set_part2 |
.set_copy_cont: |
cmp edi, edx |
jb .set_copy |
jmp .overflow |
.set_part2: |
mov esi, ebp |
xor ebp, ebp |
test esi, esi |
jz .ret.ok |
mov byte [edi-1], '/' |
jmp .set_copy_cont |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
image_of_eax EQU esp+32 |
image_of_ebx EQU esp+20 |
; System function 70 - files with long names (LFN) |
; diamond, 2006 |
iglobal |
; in this table names must be in lowercase |
rootdirs: |
db 2,'rd' |
dd fs_OnRamdisk |
dd fs_NextRamdisk |
db 7,'ramdisk' |
dd fs_OnRamdisk |
dd fs_NextRamdisk |
db 2,'fd' |
dd fs_OnFloppy |
dd fs_NextFloppy |
db 10,'floppydisk' |
dd fs_OnFloppy |
dd fs_NextFloppy |
db 3,'hd0' |
dd fs_OnHd0 |
dd fs_NextHd0 |
db 3,'hd1' |
dd fs_OnHd1 |
dd fs_NextHd1 |
db 3,'hd2' |
dd fs_OnHd2 |
dd fs_NextHd2 |
db 3,'hd3' |
dd fs_OnHd3 |
dd fs_NextHd3 |
;********************************************** |
db 3,'cd0' |
dd fs_OnCd0 |
dd fs_NextCd |
db 3,'cd1' |
dd fs_OnCd1 |
dd fs_NextCd |
db 3,'cd2' |
dd fs_OnCd2 |
dd fs_NextCd |
db 3,'cd3' |
dd fs_OnCd3 |
dd fs_NextCd |
;*********************************************** |
db 0 |
virtual_root_query: |
dd fs_HasRamdisk |
db 'rd',0 |
dd fs_HasFloppy |
db 'fd',0 |
dd fs_HasHd0 |
db 'hd0',0 |
dd fs_HasHd1 |
db 'hd1',0 |
dd fs_HasHd2 |
db 'hd2',0 |
dd fs_HasHd3 |
db 'hd3',0 |
;********************************************** |
dd fs_HasCd0 |
db 'cd0',0 |
dd fs_HasCd1 |
db 'cd1',0 |
dd fs_HasCd2 |
db 'cd2',0 |
dd fs_HasCd3 |
db 'cd3',0 |
;********************************************** |
dd 0 |
fs_additional_handlers: |
dd biosdisk_handler, biosdisk_enum_root |
dd dyndisk_handler, dyndisk_enum_root |
; add new handlers here |
dd 0 |
endg |
file_system_lfn: |
; in: ebx->fileinfo block |
; operation codes: |
; 0 : read file |
; 1 : read folder |
; 2 : create/rewrite file |
; 3 : write/append to file |
; 4 : set end of file |
; 5 : get file/directory attributes structure |
; 6 : set file/directory attributes structure |
; 7 : start application |
; 8 : delete file |
; 9 : create directory |
; parse file name |
lea esi, [ebx+20] |
lodsb |
test al, al |
jnz @f |
mov esi, [esi] |
lodsb |
@@: |
cmp al, '/' |
jz .notcurdir |
dec esi |
mov ebp, esi |
test al, al |
jnz @f |
xor ebp, ebp |
@@: |
mov esi, [current_slot] |
mov esi, [esi+APPDATA.cur_dir] |
jmp .parse_normal |
.notcurdir: |
cmp byte [esi], 0 |
jz .rootdir |
call process_replace_file_name |
.parse_normal: |
cmp dword [ebx], 7 |
jne @F |
mov edx, [ebx+4] |
mov ebx, [ebx+8] |
call fs_execute; esi+ebp, ebx, edx |
mov [image_of_eax], eax |
ret |
@@: |
mov edi, rootdirs-8 |
xor ecx, ecx |
push esi |
.scan1: |
pop esi |
add edi, ecx |
scasd |
scasd |
mov cl, byte [edi] |
test cl, cl |
jz .notfound_try |
inc edi |
push esi |
@@: |
lodsb |
or al, 20h |
scasb |
loopz @b |
jnz .scan1 |
lodsb |
cmp al, '/' |
jz .found1 |
test al, al |
jnz .scan1 |
pop eax |
; directory /xxx |
.maindir: |
mov esi, [edi+4] |
.maindir_noesi: |
cmp dword [ebx], 1 |
jnz .access_denied |
xor eax, eax |
mov ebp, [ebx+12] ;количество блоков для считывания |
mov edx, [ebx+16] ;куда записывать рузельтат |
; add edx, std_application_base_address |
push dword [ebx+4] ; first block |
mov ebx, [ebx+8] ; flags |
; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler |
mov edi, edx |
push ecx |
mov ecx, 32/4 |
rep stosd |
pop ecx |
mov byte [edx], 1 ; version |
.maindir_loop: |
call esi |
jc .maindir_done |
inc dword [edx+8] |
dec dword [esp] |
jns .maindir_loop |
dec ebp |
js .maindir_loop |
inc dword [edx+4] |
mov dword [edi], 0x10 ; attributes: folder |
mov dword [edi+4], 1 ; name type: UNICODE |
push eax |
xor eax, eax |
add edi, 8 |
push ecx |
mov ecx, 40/4-2 |
rep stosd |
pop ecx |
pop eax |
push eax edx |
; convert number in eax to decimal UNICODE string |
push edi |
push ecx |
push -'0' |
mov ecx, 10 |
@@: |
xor edx, edx |
div ecx |
push edx |
test eax, eax |
jnz @b |
@@: |
pop eax |
add al, '0' |
stosb |
test bl, 1 ; UNICODE name? |
jz .ansi2 |
mov byte [edi], 0 |
inc edi |
.ansi2: |
test al, al |
jnz @b |
mov byte [edi-1], 0 |
pop ecx |
pop edi |
; UNICODE name length is 520 bytes, ANSI - 264 |
add edi, 520 |
test bl, 1 |
jnz @f |
sub edi, 520-264 |
@@: |
pop edx eax |
jmp .maindir_loop |
.maindir_done: |
pop eax |
mov ebx, [edx+4] |
xor eax, eax |
dec ebp |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
; directory / |
.rootdir: |
cmp dword [ebx], 1 ; read folder? |
jz .readroot |
.access_denied: |
mov dword [image_of_eax], 10 ; access denied |
ret |
.readroot: |
; virtual root folder - special handler |
mov esi, virtual_root_query |
mov ebp, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
push dword [ebx+4] ; first block |
mov ebx, [ebx+8] ; flags |
xor eax, eax |
; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area |
mov edi, edx |
mov ecx, 32/4 |
rep stosd |
mov byte [edx], 1 ; version |
.readroot_loop: |
cmp dword [esi], eax |
jz .readroot_done_static |
call dword [esi] |
add esi, 4 |
test eax, eax |
jnz @f |
.readroot_next: |
or ecx, -1 |
xchg esi, edi |
repnz scasb |
xchg esi, edi |
jmp .readroot_loop |
@@: |
xor eax, eax |
inc dword [edx+8] |
dec dword [esp] |
jns .readroot_next |
dec ebp |
js .readroot_next |
inc dword [edx+4] |
mov dword [edi], 0x10 ; attributes: folder |
mov dword [edi+4], ebx ; name type: UNICODE |
add edi, 8 |
mov ecx, 40/4-2 |
rep stosd |
push edi |
@@: |
lodsb |
stosb |
test bl, 1 |
jz .ansi |
mov byte [edi], 0 |
inc edi |
.ansi: |
test eax, eax |
jnz @b |
pop edi |
add edi, 520 |
test bl, 1 |
jnz .readroot_loop |
sub edi, 520-264 |
jmp .readroot_loop |
.readroot_done_static: |
mov esi, fs_additional_handlers-8 |
sub esp, 16 |
.readroot_ah_loop: |
add esi, 8 |
cmp dword [esi], 0 |
jz .readroot_done |
xor eax, eax |
.readroot_ah_loop2: |
push edi |
lea edi, [esp+4] |
call dword [esi+4] |
pop edi |
test eax, eax |
jz .readroot_ah_loop |
inc dword [edx+8] |
dec dword [esp+16] |
jns .readroot_ah_loop2 |
dec ebp |
js .readroot_ah_loop2 |
push eax |
xor eax, eax |
inc dword [edx+4] |
mov dword [edi], 0x10 ; attributes: folder |
mov dword [edi+4], ebx |
add edi, 8 |
mov ecx, 40/4-2 |
rep stosd |
push esi edi |
lea esi, [esp+12] |
@@: |
lodsb |
stosb |
test bl, 1 |
jz .ansi3 |
mov byte [edi], 0 |
inc edi |
.ansi3: |
test al, al |
jnz @b |
pop edi esi eax |
add edi, 520 |
test bl, 1 |
jnz .readroot_ah_loop2 |
sub edi, 520-264 |
jmp .readroot_ah_loop2 |
.readroot_done: |
add esp, 16 |
pop eax |
mov ebx, [edx+4] |
xor eax, eax |
dec ebp |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.notfound_try: |
mov edi, fs_additional_handlers |
@@: |
cmp dword [edi], 0 |
jz .notfound |
call dword [edi] |
scasd |
scasd |
jmp @b |
.notfound: |
mov dword [image_of_eax], ERROR_FILE_NOT_FOUND |
and dword [image_of_ebx], 0 |
ret |
.notfounda: |
cmp edi, esp |
jnz .notfound |
call dword [edi+4] |
add esp, 16 |
jmp .notfound |
.found1: |
pop eax |
cmp byte [esi], 0 |
jz .maindir |
.found2: |
; read partition number |
xor ecx, ecx |
xor eax, eax |
@@: |
lodsb |
cmp al, '/' |
jz .done1 |
test al, al |
jz .done1 |
sub al, '0' |
cmp al, 9 |
ja .notfounda |
lea ecx, [ecx*5] |
lea ecx, [ecx*2+eax] |
jmp @b |
.done1: |
jecxz .notfounda |
test al, al |
jnz @f |
dec esi |
@@: |
cmp byte [esi], 0 |
jnz @f |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
@@: |
; now [edi] contains handler address, ecx - partition number, |
; esi points to ASCIIZ string - rest of name |
jmp dword [edi] |
; handlers for devices |
; in: ecx = 0 => query virtual directory /xxx |
; in: ecx = partition number |
; esi -> relative (for device) name |
; ebx -> fileinfo |
; ebp = 0 or pointer to rest of name from folder addressed by esi |
; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx |
fs_OnRamdisk: |
cmp ecx, 1 |
jnz file_system_lfn.notfound |
mov eax, [ebx] |
cmp eax, fs_NumRamdiskServices |
jae .not_impl |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
add ebx, 4 |
call dword [fs_RamdiskServices + eax*4] |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_NotImplemented: |
mov eax, 2 |
ret |
fs_RamdiskServices: |
dd fs_RamdiskRead |
dd fs_RamdiskReadFolder |
dd fs_RamdiskRewrite |
dd fs_RamdiskWrite |
dd fs_RamdiskSetFileEnd |
dd fs_RamdiskGetFileInfo |
dd fs_RamdiskSetFileInfo |
dd 0 |
dd fs_RamdiskDelete |
dd fs_RamdiskCreateFolder |
fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4 |
fs_OnFloppy: |
cmp ecx, 2 |
ja file_system_lfn.notfound |
mov eax, [ebx] |
cmp eax, fs_NumFloppyServices |
jae fs_OnRamdisk.not_impl |
call reserve_flp |
mov [flp_number], cl |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
add ebx, 4 |
call dword [fs_FloppyServices + eax*4] |
and [flp_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
fs_FloppyServices: |
dd fs_FloppyRead |
dd fs_FloppyReadFolder |
dd fs_FloppyRewrite |
dd fs_FloppyWrite |
dd fs_FloppySetFileEnd |
dd fs_FloppyGetFileInfo |
dd fs_FloppySetFileInfo |
dd 0 |
dd fs_FloppyDelete |
dd fs_FloppyCreateFolder |
fs_NumFloppyServices = ($ - fs_FloppyServices)/4 |
fs_OnHd0: |
call reserve_hd1 |
mov [hdbase], 0x1F0 |
mov [hdid], 0 |
push 1 |
jmp fs_OnHd |
fs_OnHd1: |
call reserve_hd1 |
mov [hdbase], 0x1F0 |
mov [hdid], 0x10 |
push 2 |
jmp fs_OnHd |
fs_OnHd2: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0 |
push 3 |
jmp fs_OnHd |
fs_OnHd3: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0x10 |
push 4 |
fs_OnHd: |
call reserve_hd_channel |
pop eax |
mov [hdpos], eax |
cmp ecx, 0x100 |
jae fs_OnHdAndBd.nf |
cmp cl, [DRIVE_DATA+1+eax] |
fs_OnHdAndBd: |
jbe @f |
.nf: |
call free_hd_channel |
and [hd1_status], 0 |
mov dword [image_of_eax], 5 ; not found |
ret |
@@: |
mov [known_part], ecx ; mov [fat32part], ecx |
push ebx esi |
call choice_necessity_partition_1 |
pop esi ebx |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
mov eax, [ebx] |
cmp eax, fs_NumHdServices |
jae .not_impl |
add ebx, 4 |
call dword [fs_HdServices + eax*4] |
call free_hd_channel |
and [hd1_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
call free_hd_channel |
and [hd1_status], 0 |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_HdServices: |
dd fs_HdRead |
dd fs_HdReadFolder |
dd fs_HdRewrite |
dd fs_HdWrite |
dd fs_HdSetFileEnd |
dd fs_HdGetFileInfo |
dd fs_HdSetFileInfo |
dd 0 |
dd fs_HdDelete |
dd fs_HdCreateFolder |
fs_NumHdServices = ($ - fs_HdServices)/4 |
;******************************************************* |
fs_OnCd0: |
call reserve_cd |
mov [ChannelNumber], 1 |
mov [DiskNumber], 0 |
push 6 |
push 1 |
jmp fs_OnCd |
fs_OnCd1: |
call reserve_cd |
mov [ChannelNumber], 1 |
mov [DiskNumber], 1 |
push 4 |
push 2 |
jmp fs_OnCd |
fs_OnCd2: |
call reserve_cd |
mov [ChannelNumber], 2 |
mov [DiskNumber], 0 |
push 2 |
push 3 |
jmp fs_OnCd |
fs_OnCd3: |
call reserve_cd |
mov [ChannelNumber], 2 |
mov [DiskNumber], 1 |
push 0 |
push 4 |
fs_OnCd: |
call reserve_cd_channel |
pop eax |
mov [cdpos], eax |
pop eax |
cmp ecx, 0x100 |
jae .nf |
push ecx ebx |
mov cl, al |
mov bl, [DRIVE_DATA+1] |
shr bl, cl |
test bl, 2 |
pop ebx ecx |
jnz @f |
.nf: |
call free_cd_channel |
and [cd_status], 0 |
mov dword [image_of_eax], 5 ; not found |
ret |
@@: |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
mov eax, [ebx] |
cmp eax, fs_NumCdServices |
jae .not_impl |
add ebx, 4 |
call dword [fs_CdServices + eax*4] |
call free_cd_channel |
and [cd_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
call free_cd_channel |
and [cd_status], 0 |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_CdServices: |
dd fs_CdRead |
dd fs_CdReadFolder |
dd fs_NotImplemented |
dd fs_NotImplemented |
dd fs_NotImplemented |
dd fs_CdGetFileInfo |
dd fs_NotImplemented |
dd 0 |
dd fs_NotImplemented |
dd fs_NotImplemented |
fs_NumCdServices = ($ - fs_CdServices)/4 |
;******************************************************* |
fs_HasRamdisk: |
mov al, 1 ; we always have ramdisk |
ret |
fs_HasFloppy: |
cmp byte [DRIVE_DATA], 0 |
setnz al |
ret |
fs_HasHd0: |
mov al, [DRIVE_DATA+1] |
and al, 11000000b |
cmp al, 01000000b |
setz al |
ret |
fs_HasHd1: |
mov al, [DRIVE_DATA+1] |
and al, 00110000b |
cmp al, 00010000b |
setz al |
ret |
fs_HasHd2: |
mov al, [DRIVE_DATA+1] |
and al, 00001100b |
cmp al, 00000100b |
setz al |
ret |
fs_HasHd3: |
mov al, [DRIVE_DATA+1] |
and al, 00000011b |
cmp al, 00000001b |
setz al |
ret |
;******************************************************* |
fs_HasCd0: |
mov al, [DRIVE_DATA+1] |
and al, 11000000b |
cmp al, 10000000b |
setz al |
ret |
fs_HasCd1: |
mov al, [DRIVE_DATA+1] |
and al, 00110000b |
cmp al, 00100000b |
setz al |
ret |
fs_HasCd2: |
mov al, [DRIVE_DATA+1] |
and al, 00001100b |
cmp al, 00001000b |
setz al |
ret |
fs_HasCd3: |
mov al, [DRIVE_DATA+1] |
and al, 00000011b |
cmp al, 00000010b |
setz 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_NextRamdisk: |
; we always have /rd/1 |
test eax, eax |
stc |
jnz @f |
mov al, 1 |
clc |
@@: |
ret |
fs_NextFloppy: |
; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0) |
test byte [DRIVE_DATA], 0xF0 |
jz .no1 |
test eax, eax |
jnz .no1 |
inc eax |
ret ; CF cleared |
.no1: |
test byte [DRIVE_DATA], 0x0F |
jz .no2 |
cmp al, 2 |
jae .no2 |
mov al, 2 |
clc |
ret |
.no2: |
stc |
ret |
; on hdx, we have partitions from 1 to [0x40002+x] |
fs_NextHd0: |
push 0 |
jmp fs_NextHd |
fs_NextHd1: |
push 1 |
jmp fs_NextHd |
fs_NextHd2: |
push 2 |
jmp fs_NextHd |
fs_NextHd3: |
push 3 |
fs_NextHd: |
pop ecx |
movzx ecx, byte [DRIVE_DATA+2+ecx] |
cmp eax, ecx |
jae fs_NextFloppy.no2 |
inc eax |
clc |
ret |
;******************************************************* |
fs_NextCd: |
; we always have /cdX/1 |
test eax, eax |
stc |
jnz @f |
mov al, 1 |
clc |
@@: |
ret |
;******************************************************* |
; Additional FS handlers. |
; This handler gets the control each time when fn 70 is called |
; with unknown item of root subdirectory. |
; in: esi -> name |
; ebp = 0 or rest of name relative to esi |
; out: if the handler processes path, he must not return in file_system_lfn, |
; but instead pop return address and return directly to the caller |
; otherwise simply return |
; here we test for /bd<N>/... - BIOS disks |
biosdisk_handler: |
cmp [NumBiosDisks], 0 |
jz .ret |
mov al, [esi] |
or al, 20h |
cmp al, 'b' |
jnz .ret |
mov al, [esi+1] |
or al, 20h |
cmp al, 'd' |
jnz .ret |
push esi |
inc esi |
inc esi |
cmp byte [esi], '0' |
jb .ret2 |
cmp byte [esi], '9' |
ja .ret2 |
xor edx, edx |
@@: |
lodsb |
test al, al |
jz .ok |
cmp al, '/' |
jz .ok |
sub al, '0' |
cmp al, 9 |
ja .ret2 |
lea edx, [edx*5] |
lea edx, [edx*2+eax] |
jmp @b |
.ret2: |
pop esi |
.ret: |
ret |
.ok: |
cmp al, '/' |
jz @f |
dec esi |
@@: |
add dl, 80h |
xor ecx, ecx |
@@: |
cmp dl, [BiosDisksData+ecx*4] |
jz .ok2 |
inc ecx |
cmp ecx, [NumBiosDisks] |
jb @b |
jmp .ret2 |
.ok2: |
add esp, 8 |
test al, al |
jnz @f |
mov esi, fs_BdNext |
jmp file_system_lfn.maindir_noesi |
@@: |
push ecx |
push ecx |
push biosdisk_cleanup |
push fs_OnBd |
mov edi, esp |
jmp file_system_lfn.found2 |
fs_BdNext: |
cmp eax, [BiosDiskPartitions+ecx*4] |
inc eax |
cmc |
biosdisk_cleanup: |
ret |
fs_OnBd: |
pop edx edx edx edx |
; edx = disk number, ecx = partition number |
; esi+ebp = name |
call reserve_hd1 |
add edx, 0x80 |
mov [hdpos], edx |
cmp ecx, [BiosDiskPartitions+(edx-0x80)*4] |
jmp fs_OnHdAndBd |
; This handler is called when virtual root is enumerated |
; and must return all items which can be handled by this. |
; It is called several times, first time with eax=0 |
; in: eax = 0 for first call, previously returned value for subsequent calls |
; out: eax = 0 => no more items |
; eax != 0 => buffer pointed to by edi contains name of item |
; here we enumerate existing BIOS disks /bd<N> |
biosdisk_enum_root: |
cmp eax, [NumBiosDisks] |
jae .end |
push eax |
movzx eax, byte [BiosDisksData+eax*4] |
sub al, 80h |
push eax |
mov al, 'b' |
stosb |
mov al, 'd' |
stosb |
pop eax |
cmp al, 10 |
jae .big |
add al, '0' |
stosb |
mov byte [edi], 0 |
pop eax |
inc eax |
ret |
.end: |
xor eax, eax |
ret |
.big: |
push ecx edx |
push -'0' |
mov ecx, 10 |
@@: |
xor edx, edx |
div ecx |
push edx |
test eax, eax |
jnz @b |
xchg eax, edx |
@@: |
pop eax |
add al, '0' |
stosb |
jnz @b |
pop edx ecx |
pop eax |
inc eax |
ret |
process_replace_file_name: |
mov ebp, [full_file_name_table] |
mov edi, [full_file_name_table.size] |
dec edi |
shl edi, 7 |
add edi, ebp |
.loop: |
cmp edi, ebp |
jb .notfound |
push esi edi |
@@: |
cmp byte [edi], 0 |
jz .dest_done |
lodsb |
test al, al |
jz .cont |
or al, 20h |
scasb |
jz @b |
jmp .cont |
.dest_done: |
cmp byte [esi], 0 |
jz .found |
cmp byte [esi], '/' |
jnz .cont |
inc esi |
jmp .found |
.cont: |
pop edi esi |
sub edi, 128 |
jmp .loop |
.found: |
pop edi eax |
mov ebp, esi |
cmp byte [esi], 0 |
lea esi, [edi+64] |
jnz .ret |
.notfound: |
xor ebp, ebp |
.ret: |
ret |
sys_current_directory: |
; mov esi, [current_slot] |
; mov esi, [esi+APPDATA.cur_dir] |
; mov edx, esi |
;get length string of appdata.cur_dir |
mov eax, [current_slot] |
mov edi, [eax+APPDATA.cur_dir] |
dec ebx |
jz .set |
dec ebx |
jz .get |
ret |
.get: |
; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len |
; for our code: ebx->buffer,ecx=len |
max_cur_dir equ 0x1000 |
mov ebx, edi |
push ecx |
push edi |
xor eax, eax |
mov ecx, max_cur_dir |
repne scasb ;find zerro at and string |
jnz .error ; no zero in cur_dir: internal error, should not happen |
sub edi, ebx ;lenght for copy |
inc edi |
mov [esp+32+8], edi ;return in eax |
cmp edx, edi |
jbe @f |
mov edx, edi |
@@: |
;source string |
pop esi |
;destination string |
pop edi |
cmp edx, 1 |
jbe .ret |
mov al, '/' ;start string with '/' |
stosb |
mov ecx, edx |
rep movsb ;copy string |
.ret: |
ret |
.error: |
add esp, 8 |
or dword [esp+32], -1 ;error not found zerro at string ->[eax+APPDATA.cur_dir] |
ret |
.set: |
; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string |
; for our code: ebx->string to set |
; use generic resolver with APPDATA.cur_dir as destination |
push max_cur_dir ;0x1000 |
push edi ;destination |
mov ebx, ecx |
call get_full_file_name |
ret |
; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination |
; destroys all registers except ebp,esp |
get_full_file_name: |
push ebp |
mov esi, [current_slot] |
mov esi, [esi+APPDATA.cur_dir] |
mov edx, esi |
@@: |
inc esi |
cmp byte [esi-1], 0 |
jnz @b |
dec esi |
cmp byte [ebx], '/' |
jz .set_absolute |
; string gives relative path |
mov edi, [esp+8] ; destination |
.relative: |
cmp byte [ebx], 0 |
jz .set_ok |
cmp word [ebx], '.' |
jz .set_ok |
cmp word [ebx], './' |
jnz @f |
add ebx, 2 |
jmp .relative |
@@: |
cmp word [ebx], '..' |
jnz .doset_relative |
cmp byte [ebx+2], 0 |
jz @f |
cmp byte [ebx+2], '/' |
jnz .doset_relative |
@@: |
dec esi |
cmp byte [esi], '/' |
jnz @b |
add ebx, 3 |
jmp .relative |
.set_ok: |
cmp edx, edi ; is destination equal to APPDATA.cur_dir? |
jz .set_ok.cur_dir |
sub esi, edx |
cmp esi, [esp+12] |
jb .set_ok.copy |
.fail: |
mov byte [edi], 0 |
xor eax, eax ; fail |
pop ebp |
ret 8 |
.set_ok.copy: |
mov ecx, esi |
mov esi, edx |
rep movsb |
mov byte [edi], 0 |
.ret.ok: |
mov al, 1 ; ok |
pop ebp |
ret 8 |
.set_ok.cur_dir: |
mov byte [esi], 0 |
jmp .ret.ok |
.doset_relative: |
cmp edx, edi |
jz .doset_relative.cur_dir |
sub esi, edx |
cmp esi, [esp+12] |
jae .fail |
mov ecx, esi |
mov esi, edx |
mov edx, edi |
rep movsb |
jmp .doset_relative.copy |
.doset_relative.cur_dir: |
mov edi, esi |
.doset_relative.copy: |
add edx, [esp+12] |
mov byte [edi], '/' |
inc edi |
cmp edi, edx |
jae .overflow |
@@: |
mov al, [ebx] |
inc ebx |
stosb |
test al, al |
jz .ret.ok |
cmp edi, edx |
jb @b |
.overflow: |
dec edi |
jmp .fail |
.set_absolute: |
lea esi, [ebx+1] |
call process_replace_file_name |
mov edi, [esp+8] |
mov edx, [esp+12] |
add edx, edi |
.set_copy: |
lodsb |
stosb |
test al, al |
jz .set_part2 |
.set_copy_cont: |
cmp edi, edx |
jb .set_copy |
jmp .overflow |
.set_part2: |
mov esi, ebp |
xor ebp, ebp |
test esi, esi |
jz .ret.ok |
mov byte [edi-1], '/' |
jmp .set_copy_cont |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fs/iso9660.inc |
---|
1,761 → 1,761 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$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 |
sti |
call change_task |
jmp reserve_cd |
reserve_ok2: |
push eax |
mov eax,[CURRENT_TASK] |
shl eax,5 |
mov eax,[eax+CURRENT_TASK+TASKDATA.pid] |
mov [cd_status],eax |
pop eax |
sti |
ret |
reserve_cd_channel: |
cmp [ChannelNumber],1 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
cli |
cmp [IDE_Channel_1],0 |
je .reserve_ok_1 |
sti |
call change_task |
jmp .IDE_Channel_1 |
.IDE_Channel_2: |
cli |
cmp [IDE_Channel_2],0 |
je .reserve_ok_2 |
sti |
call change_task |
jmp .IDE_Channel_2 |
.reserve_ok_1: |
mov [IDE_Channel_1],1 |
sti |
ret |
.reserve_ok_2: |
mov [IDE_Channel_2],1 |
sti |
ret |
free_cd_channel: |
cmp [ChannelNumber],1 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
mov [IDE_Channel_1],0 |
sti |
ret |
.IDE_Channel_2: |
mov [IDE_Channel_2],0 |
sti |
ret |
uglobal |
cd_status dd 0 |
endg |
;---------------------------------------------------------------- |
; |
; fs_CdRead - LFN variant for reading CD disk |
; |
; esi points to filename /dir1/dir2/.../dirn/file,0 |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; 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] ; ðåàëüíûé ðàçìåð ôàéëîâîé ñåêöèè |
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 ; ÷èòàåì ñåêòîð ôàéëà |
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 ; ÷èòàåì ñåêòîð ôàéëà |
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 |
mov edi,edx |
lea esi, [CDDataBuf + ebx] |
cld |
rep movsb |
pop ecx esi edi |
add edx, ecx |
sub [esp], ecx |
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 |
; |
; esi points to filename /dir1/dir2/.../dirn/file,0 |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; 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] ; ðàçìåð äèðåêòðîðèè |
.doit: |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
pop ecx eax |
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 ; ÷èòàåì ñåêòîð äèðåêòîðèè |
cmp [DevErrorCode], 0 |
jne .noaccess_1 |
call .get_names_from_buffer |
sub eax,2048 |
; äèðåêòîðèÿ çàêîí÷èëàñü? |
ja .read_to_buffer |
mov edi, [cd_counter_block] |
mov [edx+8], edi |
mov edi, [ebx] |
sub [edx+4], edi |
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 |
mov esi,ebp |
mov edi,[cd_mem_location] |
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 |
call uni2ansi_char |
cld |
stosb |
; ïðîâåðêà êîíöà ôàéëà |
mov ax,[esi] |
cmp ax,word 3B00h ; ñåïàðàòîð êîíöà ôàéëà ';' |
je .cd_get_parameters_of_file_1 |
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì |
movzx eax,byte [ebp-33] |
add eax,ebp |
sub eax,34 |
cmp esi,eax |
je .cd_get_parameters_of_file_1 |
; ïðîâåðêà êîíöà ïàïêè |
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 |
; ïðîâåðêà êîíöà ôàéëà |
mov ax,[esi] |
cmp ax,word 3B00h ; ñåïàðàòîð êîíöà ôàéëà ';' |
je .cd_get_parameters_of_file_2 |
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì |
movzx eax,byte [ebp-33] |
add eax,ebp |
sub eax,34 |
cmp esi,eax |
je .cd_get_parameters_of_file_2 |
; ïðîâåðêà êîíöà ïàïêè |
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: |
; ïîëó÷àåì àòðèáóòû ôàéëà |
xor eax,eax |
; ôàéë íå àðõèâèðîâàëñÿ |
inc eax |
shl eax,1 |
; ýòî êàòàëîã? |
test [ebp-8],byte 2 |
jz .file |
inc eax |
.file: |
; ìåòêà òîìà íå êàê â FAT, â ýòîì âèäå îòñóòñâóåò |
; ôàéë íå ÿâëÿåòñÿ ñèñòåìíûì |
shl eax,3 |
; ôàéë ÿâëÿåòñÿ ñêðûòûì? (àòðèáóò ñóùåñòâîâàíèå) |
test [ebp-8],byte 1 |
jz .hidden |
inc eax |
.hidden: |
shl eax,1 |
; ôàéë âñåãäà òîëüêî äëÿ ÷òåíèÿ, òàê êàê ýòî CD |
inc eax |
mov [edi],eax |
; ïîëó÷àåì âðåìÿ äëÿ ôàéëà |
;÷àñ |
movzx eax,byte [ebp-12] |
shl eax,8 |
;ìèíóòà |
mov al,[ebp-11] |
shl eax,8 |
;ñåêóíäà |
mov al,[ebp-10] |
;âðåìÿ ñîçäàíèÿ ôàéëà |
mov [edi+8],eax |
;âðåìÿ ïîñëåäíåãî äîñòóïà |
mov [edi+16],eax |
;âðåìÿ ïîñëåäíåé çàïèñè |
mov [edi+24],eax |
; ïîëó÷àåì äàòó äëÿ ôàéëà |
;ãîä |
movzx eax,byte [ebp-15] |
add eax,1900 |
shl eax,8 |
;ìåñÿö |
mov al,[ebp-14] |
shl eax,8 |
;äåíü |
mov al,[ebp-13] |
;äàòà ñîçäàíèÿ ôàéëà |
mov [edi+12],eax |
;âðåìÿ ïîñëåäíåãî äîñòóïà |
mov [edi+20],eax |
;âðåìÿ ïîñëåäíåé çàïèñè |
mov [edi+28],eax |
; ïîëó÷àåì òèï äàííûõ èìåíè |
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 |
@@: |
; ïîëó÷àåì ðàçìåð ôàéëà â áàéòàõ |
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 |
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 |
push ebp |
mov ebp, [cd_current_pointer_of_input] |
add ebp, 33 |
call cd_get_parameters_of_file_1 |
pop ebp |
and dword [edi+4], 0 |
pop edi |
xor eax, eax |
ret |
;---------------------------------------------------------------- |
cd_find_lfn: |
mov [cd_appl_data],0 |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and [cd_current_pointer_of_input] direntry |
push eax esi |
; 16 ñåêòîð íà÷àëî íàáîðà äåñêðèïòîðîâ òîìîâ |
call WaitUnitReady |
cmp [DevErrorCode],0 |
jne .access_denied |
call prevent_medium_removal |
; òåñòîâîå ÷òåíèå |
mov [CDSectorAddress],dword 16 |
mov [CDDataBuf_pointer],CDDataBuf |
call ReadCDWRetr ;_1 |
cmp [DevErrorCode],0 |
jne .access_denied |
; âû÷èñëåíèå ïîñëåäíåé ñåññèè |
call WaitUnitReady |
cmp [DevErrorCode],0 |
jne .access_denied |
call Read_TOC |
mov ah,[CDDataBuf+4+4] |
mov al,[CDDataBuf+4+5] |
shl eax,16 |
mov ah,[CDDataBuf+4+6] |
mov al,[CDDataBuf+4+7] |
add eax,15 |
mov [CDSectorAddress],eax |
; mov [CDSectorAddress],dword 15 |
mov [CDDataBuf_pointer],CDDataBuf |
.start: |
inc dword [CDSectorAddress] |
call ReadCDWRetr ;_1 |
cmp [DevErrorCode],0 |
jne .access_denied |
.start_check: |
; ïðîâåðêà íà âøèâîñòü |
cmp [CDDataBuf+1],dword 'CD00' |
jne .access_denied |
cmp [CDDataBuf+5],byte '1' |
jne .access_denied |
; ñåêòîð ÿâëÿåòñÿ òåðìèíàòîðîì íàáîð äåñêðèïòîðîâ òîìîâ? |
cmp [CDDataBuf],byte 0xff |
je .access_denied |
; ñåêòîð ÿâëÿåòñÿ äîïîëíèòåëüíûì è óëó÷øåííûì äåñêðèïòîðîì òîìà? |
cmp [CDDataBuf],byte 0x2 |
jne .start |
; ñåêòîð ÿâëÿåòñÿ äîïîëíèòåëüíûì äåñêðèïòîðîì òîìà? |
cmp [CDDataBuf+6],byte 0x1 |
jne .start |
; ïàðàìåòðû root äèðåêòðîðèè |
mov eax,[CDDataBuf+0x9c+2] ; íà÷àëî root äèðåêòðîðèè |
mov [CDSectorAddress],eax |
mov eax,[CDDataBuf+0x9c+10] ; ðàçìåð root äèðåêòðîðèè |
cmp byte [esi], 0 |
jnz @f |
mov [cd_current_pointer_of_input],CDDataBuf+0x9c |
jmp .done |
@@: |
; íà÷èíàåì ïîèñê |
.mainloop: |
dec dword [CDSectorAddress] |
.read_to_buffer: |
inc dword [CDSectorAddress] |
mov [CDDataBuf_pointer],CDDataBuf |
call ReadCDWRetr ; ÷èòàåì ñåêòîð äèðåêòîðèè |
cmp [DevErrorCode],0 |
jne .access_denied |
push ebp |
call cd_find_name_in_buffer |
pop ebp |
jnc .found |
sub eax,2048 |
; äèðåêòîðèÿ çàêîí÷èëàñü? |
cmp eax,0 |
ja .read_to_buffer |
; íåò èñêîìîãî ýëåìåíòà öåïî÷êè |
.access_denied: |
pop esi eax |
mov [cd_appl_data],1 |
stc |
ret |
; èñêîìûé ýëåìåíò öåïî÷êè íàéäåí |
.found: |
; êîíåö ïóòè ôàéëà |
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] ; ðàçìåð äèðåêòîðèè |
jmp .mainloop |
; óêàçàòåëü ôàéëà íàéäåí |
.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 ; âõîäû çàêîí÷èëèñü? |
jz .next_sector |
cmp ebp,CDDataBuf+2048 ; áóôåð çàêîí÷èëñÿ? |
jae .next_sector |
movzx eax, byte [ebp] |
add [cd_current_pointer_of_input_2],eax ; ñëåäóþùèé âõîä êàòàëîãà |
add ebp,33 ; óêàçàòåëü óñòàíîâëåí íà íà÷àëî èìåíè |
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 |
; out: if names match: ZF=1 and esi->next component of name |
; else: ZF=0, esi is not changed |
; destroys eax |
push esi eax edi |
mov edi,ebp |
.loop: |
cld |
lodsb |
push eax |
call char_todown |
call ansi2uni_char |
xchg ah,al |
scasw |
pop eax |
je .coincides |
call char_toupper |
call ansi2uni_char |
xchg ah,al |
sub edi,2 |
scasw |
jne .name_not_coincide |
.coincides: |
cmp [esi],byte '/' ; ðàçäåëèòåëü ïóòè, êîíåö èìåíè òåêóùåãî ýëåìåíòà |
je .done |
cmp [esi],byte 0 ; ðàçäåëèòåëü ïóòè, êîíåö èìåíè òåêóùåãî ýëåìåíòà |
je .done |
jmp .loop |
.name_not_coincide: |
pop edi eax esi |
stc |
ret |
.done: |
; ïðîâåðêà êîíöà ôàéëà |
cmp [edi],word 3B00h ; ñåïàðàòîð êîíöà ôàéëà ';' |
je .done_1 |
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì |
movzx eax,byte [ebp-33] |
add eax,ebp |
sub eax,34 |
cmp edi,eax |
je .done_1 |
; ïðîâåðêà êîíöà ïàïêè |
movzx eax,byte [ebp-1] |
add eax,ebp |
cmp edi,eax |
jne .name_not_coincide |
.done_1: |
pop edi eax |
add esp,4 |
inc esi |
clc |
ret |
char_todown: |
; convert character to uppercase, using cp866 encoding |
; in: al=symbol |
; out: al=converted symbol |
cmp al, 'A' |
jb .ret |
cmp al, 'Z' |
jbe .az |
cmp al, '' |
jb .ret |
cmp al, '' |
jb .rus1 |
cmp al, '' |
ja .ret |
; 0x90-0x9F -> 0xE0-0xEF |
add al, 'à'-'' |
.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 |
; 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, 'ð' |
jmp .doit |
.yo2: |
mov al, 'ñ' |
jmp .doit |
.rus1: |
; 0x410-0x43F -> 0x80-0xAF |
add al, 0x70 |
jmp .doit |
.rus2: |
; 0x440-0x44F -> 0xE0-0xEF |
add al, 0xA0 |
.ascii: |
.doit: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$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 |
sti |
call change_task |
jmp reserve_cd |
reserve_ok2: |
push eax |
mov eax, [CURRENT_TASK] |
shl eax, 5 |
mov eax, [eax+CURRENT_TASK+TASKDATA.pid] |
mov [cd_status], eax |
pop eax |
sti |
ret |
reserve_cd_channel: |
cmp [ChannelNumber], 1 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
cli |
cmp [IDE_Channel_1], 0 |
je .reserve_ok_1 |
sti |
call change_task |
jmp .IDE_Channel_1 |
.IDE_Channel_2: |
cli |
cmp [IDE_Channel_2], 0 |
je .reserve_ok_2 |
sti |
call change_task |
jmp .IDE_Channel_2 |
.reserve_ok_1: |
mov [IDE_Channel_1], 1 |
sti |
ret |
.reserve_ok_2: |
mov [IDE_Channel_2], 1 |
sti |
ret |
free_cd_channel: |
cmp [ChannelNumber], 1 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
mov [IDE_Channel_1], 0 |
sti |
ret |
.IDE_Channel_2: |
mov [IDE_Channel_2], 0 |
sti |
ret |
uglobal |
cd_status dd 0 |
endg |
;---------------------------------------------------------------- |
; |
; fs_CdRead - LFN variant for reading CD disk |
; |
; esi points to filename /dir1/dir2/.../dirn/file,0 |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; 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] ; ðåàëüíûé ðàçìåð ôàéëîâîé ñåêöèè |
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; ÷èòàåì ñåêòîð ôàéëà |
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; ÷èòàåì ñåêòîð ôàéëà |
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 |
mov edi, edx |
lea esi, [CDDataBuf + ebx] |
cld |
rep movsb |
pop ecx esi edi |
add edx, ecx |
sub [esp], ecx |
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 |
; |
; esi points to filename /dir1/dir2/.../dirn/file,0 |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; 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] ; ðàçìåð äèðåêòðîðèè |
.doit: |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
pop ecx eax |
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 ; ÷èòàåì ñåêòîð äèðåêòîðèè |
cmp [DevErrorCode], 0 |
jne .noaccess_1 |
call .get_names_from_buffer |
sub eax, 2048 |
; äèðåêòîðèÿ çàêîí÷èëàñü? |
ja .read_to_buffer |
mov edi, [cd_counter_block] |
mov [edx+8], edi |
mov edi, [ebx] |
sub [edx+4], edi |
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 |
mov esi, ebp |
mov edi, [cd_mem_location] |
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 |
call uni2ansi_char |
cld |
stosb |
; ïðîâåðêà êîíöà ôàéëà |
mov ax, [esi] |
cmp ax, word 3B00h; ñåïàðàòîð êîíöà ôàéëà ';' |
je .cd_get_parameters_of_file_1 |
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì |
movzx eax, byte [ebp-33] |
add eax, ebp |
sub eax, 34 |
cmp esi, eax |
je .cd_get_parameters_of_file_1 |
; ïðîâåðêà êîíöà ïàïêè |
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 |
; ïðîâåðêà êîíöà ôàéëà |
mov ax, [esi] |
cmp ax, word 3B00h; ñåïàðàòîð êîíöà ôàéëà ';' |
je .cd_get_parameters_of_file_2 |
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì |
movzx eax, byte [ebp-33] |
add eax, ebp |
sub eax, 34 |
cmp esi, eax |
je .cd_get_parameters_of_file_2 |
; ïðîâåðêà êîíöà ïàïêè |
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: |
; ïîëó÷àåì àòðèáóòû ôàéëà |
xor eax, eax |
; ôàéë íå àðõèâèðîâàëñÿ |
inc eax |
shl eax, 1 |
; ýòî êàòàëîã? |
test [ebp-8], byte 2 |
jz .file |
inc eax |
.file: |
; ìåòêà òîìà íå êàê â FAT, â ýòîì âèäå îòñóòñâóåò |
; ôàéë íå ÿâëÿåòñÿ ñèñòåìíûì |
shl eax, 3 |
; ôàéë ÿâëÿåòñÿ ñêðûòûì? (àòðèáóò ñóùåñòâîâàíèå) |
test [ebp-8], byte 1 |
jz .hidden |
inc eax |
.hidden: |
shl eax, 1 |
; ôàéë âñåãäà òîëüêî äëÿ ÷òåíèÿ, òàê êàê ýòî CD |
inc eax |
mov [edi], eax |
; ïîëó÷àåì âðåìÿ äëÿ ôàéëà |
;÷àñ |
movzx eax, byte [ebp-12] |
shl eax, 8 |
;ìèíóòà |
mov al, [ebp-11] |
shl eax, 8 |
;ñåêóíäà |
mov al, [ebp-10] |
;âðåìÿ ñîçäàíèÿ ôàéëà |
mov [edi+8], eax |
;âðåìÿ ïîñëåäíåãî äîñòóïà |
mov [edi+16], eax |
;âðåìÿ ïîñëåäíåé çàïèñè |
mov [edi+24], eax |
; ïîëó÷àåì äàòó äëÿ ôàéëà |
;ãîä |
movzx eax, byte [ebp-15] |
add eax, 1900 |
shl eax, 8 |
;ìåñÿö |
mov al, [ebp-14] |
shl eax, 8 |
;äåíü |
mov al, [ebp-13] |
;äàòà ñîçäàíèÿ ôàéëà |
mov [edi+12], eax |
;âðåìÿ ïîñëåäíåãî äîñòóïà |
mov [edi+20], eax |
;âðåìÿ ïîñëåäíåé çàïèñè |
mov [edi+28], eax |
; ïîëó÷àåì òèï äàííûõ èìåíè |
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 |
@@: |
; ïîëó÷àåì ðàçìåð ôàéëà â áàéòàõ |
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 |
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 |
push ebp |
mov ebp, [cd_current_pointer_of_input] |
add ebp, 33 |
call cd_get_parameters_of_file_1 |
pop ebp |
and dword [edi+4], 0 |
pop edi |
xor eax, eax |
ret |
;---------------------------------------------------------------- |
cd_find_lfn: |
mov [cd_appl_data], 0 |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and [cd_current_pointer_of_input] direntry |
push eax esi |
; 16 ñåêòîð íà÷àëî íàáîðà äåñêðèïòîðîâ òîìîâ |
call WaitUnitReady |
cmp [DevErrorCode], 0 |
jne .access_denied |
call prevent_medium_removal |
; òåñòîâîå ÷òåíèå |
mov [CDSectorAddress], dword 16 |
mov [CDDataBuf_pointer], CDDataBuf |
call ReadCDWRetr;_1 |
cmp [DevErrorCode], 0 |
jne .access_denied |
; âû÷èñëåíèå ïîñëåäíåé ñåññèè |
call WaitUnitReady |
cmp [DevErrorCode], 0 |
jne .access_denied |
call Read_TOC |
mov ah, [CDDataBuf+4+4] |
mov al, [CDDataBuf+4+5] |
shl eax, 16 |
mov ah, [CDDataBuf+4+6] |
mov al, [CDDataBuf+4+7] |
add eax, 15 |
mov [CDSectorAddress], eax |
; mov [CDSectorAddress],dword 15 |
mov [CDDataBuf_pointer], CDDataBuf |
.start: |
inc dword [CDSectorAddress] |
call ReadCDWRetr;_1 |
cmp [DevErrorCode], 0 |
jne .access_denied |
.start_check: |
; ïðîâåðêà íà âøèâîñòü |
cmp [CDDataBuf+1], dword 'CD00' |
jne .access_denied |
cmp [CDDataBuf+5], byte '1' |
jne .access_denied |
; ñåêòîð ÿâëÿåòñÿ òåðìèíàòîðîì íàáîð äåñêðèïòîðîâ òîìîâ? |
cmp [CDDataBuf], byte 0xff |
je .access_denied |
; ñåêòîð ÿâëÿåòñÿ äîïîëíèòåëüíûì è óëó÷øåííûì äåñêðèïòîðîì òîìà? |
cmp [CDDataBuf], byte 0x2 |
jne .start |
; ñåêòîð ÿâëÿåòñÿ äîïîëíèòåëüíûì äåñêðèïòîðîì òîìà? |
cmp [CDDataBuf+6], byte 0x1 |
jne .start |
; ïàðàìåòðû root äèðåêòðîðèè |
mov eax, [CDDataBuf+0x9c+2]; íà÷àëî root äèðåêòðîðèè |
mov [CDSectorAddress], eax |
mov eax, [CDDataBuf+0x9c+10]; ðàçìåð root äèðåêòðîðèè |
cmp byte [esi], 0 |
jnz @f |
mov [cd_current_pointer_of_input], CDDataBuf+0x9c |
jmp .done |
@@: |
; íà÷èíàåì ïîèñê |
.mainloop: |
dec dword [CDSectorAddress] |
.read_to_buffer: |
inc dword [CDSectorAddress] |
mov [CDDataBuf_pointer], CDDataBuf |
call ReadCDWRetr ; ÷èòàåì ñåêòîð äèðåêòîðèè |
cmp [DevErrorCode], 0 |
jne .access_denied |
push ebp |
call cd_find_name_in_buffer |
pop ebp |
jnc .found |
sub eax, 2048 |
; äèðåêòîðèÿ çàêîí÷èëàñü? |
cmp eax, 0 |
ja .read_to_buffer |
; íåò èñêîìîãî ýëåìåíòà öåïî÷êè |
.access_denied: |
pop esi eax |
mov [cd_appl_data], 1 |
stc |
ret |
; èñêîìûé ýëåìåíò öåïî÷êè íàéäåí |
.found: |
; êîíåö ïóòè ôàéëà |
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]; ðàçìåð äèðåêòîðèè |
jmp .mainloop |
; óêàçàòåëü ôàéëà íàéäåí |
.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 ; âõîäû çàêîí÷èëèñü? |
jz .next_sector |
cmp ebp, CDDataBuf+2048 ; áóôåð çàêîí÷èëñÿ? |
jae .next_sector |
movzx eax, byte [ebp] |
add [cd_current_pointer_of_input_2], eax; ñëåäóþùèé âõîä êàòàëîãà |
add ebp, 33; óêàçàòåëü óñòàíîâëåí íà íà÷àëî èìåíè |
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 |
; out: if names match: ZF=1 and esi->next component of name |
; else: ZF=0, esi is not changed |
; destroys eax |
push esi eax edi |
mov edi, ebp |
.loop: |
cld |
lodsb |
push eax |
call char_todown |
call ansi2uni_char |
xchg ah, al |
scasw |
pop eax |
je .coincides |
call char_toupper |
call ansi2uni_char |
xchg ah, al |
sub edi, 2 |
scasw |
jne .name_not_coincide |
.coincides: |
cmp [esi], byte '/'; ðàçäåëèòåëü ïóòè, êîíåö èìåíè òåêóùåãî ýëåìåíòà |
je .done |
cmp [esi], byte 0; ðàçäåëèòåëü ïóòè, êîíåö èìåíè òåêóùåãî ýëåìåíòà |
je .done |
jmp .loop |
.name_not_coincide: |
pop edi eax esi |
stc |
ret |
.done: |
; ïðîâåðêà êîíöà ôàéëà |
cmp [edi], word 3B00h; ñåïàðàòîð êîíöà ôàéëà ';' |
je .done_1 |
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì |
movzx eax, byte [ebp-33] |
add eax, ebp |
sub eax, 34 |
cmp edi, eax |
je .done_1 |
; ïðîâåðêà êîíöà ïàïêè |
movzx eax, byte [ebp-1] |
add eax, ebp |
cmp edi, eax |
jne .name_not_coincide |
.done_1: |
pop edi eax |
add esp, 4 |
inc esi |
clc |
ret |
char_todown: |
; convert character to uppercase, using cp866 encoding |
; in: al=symbol |
; out: al=converted symbol |
cmp al, 'A' |
jb .ret |
cmp al, 'Z' |
jbe .az |
cmp al, '' |
jb .ret |
cmp al, '' |
jb .rus1 |
cmp al, '' |
ja .ret |
; 0x90-0x9F -> 0xE0-0xEF |
add al, 'à'-'' |
.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 |
; 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, 'ð' |
jmp .doit |
.yo2: |
mov al, 'ñ' |
jmp .doit |
.rus1: |
; 0x410-0x43F -> 0x80-0xAF |
add al, 0x70 |
jmp .doit |
.rus2: |
; 0x440-0x44F -> 0xE0-0xEF |
add al, 0xA0 |
.ascii: |
.doit: |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fs/ntfs.inc |
---|
1,1829 → 1,1829 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
ntfs_test_bootsec: |
; in: ebx->buffer, edx=size of partition |
; out: CF set <=> invalid |
; 1. Name=='NTFS ' |
cmp dword [ebx+3], 'NTFS' |
jnz .no |
cmp dword [ebx+7], ' ' |
jnz .no |
; 2. Number of bytes per sector is the same as for physical device |
; (that is, 0x200 for hard disk) |
cmp word [ebx+11], 0x200 |
jnz .no |
; 3. Number of sectors per cluster must be power of 2 |
movzx eax, byte [ebx+13] |
dec eax |
js .no |
test al, [ebx+13] |
jnz .no |
; 4. FAT parameters must be zero |
cmp word [ebx+14], 0 |
jnz .no |
cmp dword [ebx+16], 0 |
jnz .no |
cmp byte [ebx+20], 0 |
jnz .no |
cmp word [ebx+22], 0 |
jnz .no |
cmp dword [ebx+32], 0 |
jnz .no |
; 5. Number of sectors <= partition size |
cmp dword [ebx+0x2C], 0 |
ja .no |
cmp [ebx+0x28], edx |
ja .no |
; 6. $MFT and $MFTMirr clusters must be within partition |
cmp dword [ebx+0x34], 0 |
ja .no |
push edx |
movzx eax, byte [ebx+13] |
mul dword [ebx+0x30] |
test edx, edx |
pop edx |
jnz .no |
cmp eax, edx |
ja .no |
cmp dword [ebx+0x3C], 0 |
ja .no |
push edx |
movzx eax, byte [ebx+13] |
mul dword [ebx+0x38] |
test edx, edx |
pop edx |
jnz .no |
cmp eax, edx |
ja .no |
; 7. Clusters per FRS must be either negative and in [-31,-9] or positive and power of 2 |
movsx eax, byte [ebx+0x40] |
cmp al, -31 |
jl .no |
cmp al, -9 |
jle @f |
dec eax |
js .no |
test [ebx+0x40], al |
jnz .no |
@@: |
; 8. Same for clusters per IndexAllocationBuffer |
movsx eax, byte [ebx+0x44] |
cmp al, -31 |
jl .no |
cmp al, -9 |
jle @f |
dec eax |
js .no |
test [ebx+0x44], al |
jnz .no |
@@: |
; OK, this is correct NTFS bootsector |
clc |
ret |
.no: |
; No, this bootsector isn't NTFS |
stc |
ret |
ntfs_setup: ; CODE XREF: part_set.inc |
; By given bootsector, initialize some NTFS variables |
; call ntfs_test_bootsec ; checking boot sector was already |
; jc problem_fat_dec_count |
movzx eax, byte [ebx+13] |
mov [ntfs_data.sectors_per_cluster], eax |
mov eax, [ebx+0x28] |
add eax, [PARTITION_START] |
dec eax |
mov [PARTITION_END], eax |
mov [fs_type], 1 |
mov eax, [ebx+0x30] |
mov [ntfs_data.mft_cluster], eax |
mov eax, [ebx+0x38] |
mov [ntfs_data.mftmirr_cluster], eax |
movsx eax, byte [ebx+0x40] |
test eax, eax |
js .1 |
mul [ntfs_data.sectors_per_cluster] |
shl eax, 9 |
jmp .2 |
.1: |
neg eax |
mov ecx, eax |
mov eax, 1 |
shl eax, cl |
.2: |
mov [ntfs_data.frs_size], eax |
movsx eax, byte [ebx+0x44] |
test eax, eax |
js .3 |
mul [ntfs_data.sectors_per_cluster] |
shl eax, 9 |
jmp .4 |
.3: |
neg eax |
mov ecx, eax |
mov eax, 1 |
shl eax, cl |
.4: |
mov [ntfs_data.iab_size], eax |
; allocate space for buffers |
add eax, [ntfs_data.frs_size] |
push eax |
call kernel_alloc |
test eax, eax |
jz problem_fat_dec_count |
mov [ntfs_data.frs_buffer], eax |
add eax, [ntfs_data.frs_size] |
mov [ntfs_data.iab_buffer], eax |
; read $MFT disposition |
mov eax, [ntfs_data.mft_cluster] |
mul [ntfs_data.sectors_per_cluster] |
call ntfs_read_frs_sector |
cmp [hd_error], 0 |
jnz .usemirr |
cmp dword [ebx], 'FILE' |
jnz .usemirr |
call ntfs_restore_usa_frs |
jnc .mftok |
.usemirr: |
and [hd_error], 0 |
mov eax, [ntfs_data.mftmirr_cluster] |
mul [ntfs_data.sectors_per_cluster] |
call ntfs_read_frs_sector |
cmp [hd_error], 0 |
jnz @f |
cmp dword [ebx], 'FILE' |
jnz @f |
call ntfs_restore_usa_frs |
jnc .mftok |
@@: |
; $MFT and $MFTMirr invalid! |
.fail_free_frs: |
push [ntfs_data.frs_buffer] |
call kernel_free |
jmp problem_fat_dec_count |
.fail_free_mft: |
push [ntfs_data.mft_retrieval] |
call kernel_free |
jmp .fail_free_frs |
.mftok: |
; read $MFT table retrieval information |
; start with one page, increase if not enough (when MFT too fragmented) |
push ebx |
push 0x1000 |
call kernel_alloc |
pop ebx |
test eax, eax |
jz .fail_free_frs |
mov [ntfs_data.mft_retrieval], eax |
and [ntfs_data.mft_retrieval_size], 0 |
mov [ntfs_data.mft_retrieval_alloc], 0x1000/8 |
; $MFT base record must contain unnamed non-resident $DATA attribute |
movzx eax, word [ebx+14h] |
add eax, ebx |
.scandata: |
cmp dword [eax], -1 |
jz .fail_free_mft |
cmp dword [eax], 0x80 |
jnz @f |
cmp byte [eax+9], 0 |
jz .founddata |
@@: |
add eax, [eax+4] |
jmp .scandata |
.founddata: |
cmp byte [eax+8], 0 |
jz .fail_free_mft |
; load first portion of $DATA attribute retrieval information |
mov edx, [eax+0x18] |
mov [ntfs_data.mft_retrieval_end], edx |
mov esi, eax |
movzx eax, word [eax+0x20] |
add esi, eax |
sub esp, 10h |
.scanmcb: |
call ntfs_decode_mcb_entry |
jnc .scanmcbend |
call .get_mft_retrieval_ptr |
mov edx, [esp] ; block length |
mov [eax], edx |
mov edx, [esp+8] ; block addr (relative) |
mov [eax+4], edx |
inc [ntfs_data.mft_retrieval_size] |
jmp .scanmcb |
.scanmcbend: |
add esp, 10h |
; there may be other portions of $DATA attribute in auxiliary records; |
; if they will be needed, they will be loaded later |
mov [ntfs_data.cur_index_size], 0x1000/0x200 |
push 0x1000 |
call kernel_alloc |
test eax, eax |
jz .fail_free_mft |
mov [ntfs_data.cur_index_buf], eax |
popad |
call free_hd_channel |
and [hd1_status], 0 |
ret |
.get_mft_retrieval_ptr: |
pushad |
mov eax, [ntfs_data.mft_retrieval_size] |
cmp eax, [ntfs_data.mft_retrieval_alloc] |
jnz .ok |
add eax, 0x1000/8 |
mov [ntfs_data.mft_retrieval_alloc], eax |
shl eax, 3 |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
popad |
add esp, 14h |
jmp .fail_free_mft |
@@: |
mov esi, [ntfs_data.mft_retrieval] |
mov edi, eax |
mov ecx, [ntfs_data.mft_retrieval_size] |
add ecx, ecx |
rep movsd |
push [ntfs_data.mft_retrieval] |
mov [ntfs_data.mft_retrieval], eax |
call kernel_free |
mov eax, [ntfs_data.mft_retrieval_size] |
.ok: |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
mov [esp+28], eax |
popad |
ret |
ntfs_read_frs_sector: |
push eax ecx |
add eax, [PARTITION_START] |
mov ecx, [ntfs_data.frs_size] |
shr ecx, 9 |
mov ebx, [ntfs_data.frs_buffer] |
push ebx |
@@: |
call hd_read |
cmp [hd_error], 0 |
jnz .fail |
add ebx, 0x200 |
inc eax |
loop @b |
.fail: |
pop ebx |
pop ecx eax |
ret |
uglobal |
align 4 |
ntfs_cur_attr dd ? |
ntfs_cur_iRecord dd ? |
ntfs_cur_offs dd ? ; in sectors |
ntfs_cur_size dd ? ; in sectors |
ntfs_cur_buf dd ? |
ntfs_cur_read dd ? ; [output] |
ntfs_bCanContinue db ? |
rb 3 |
ntfs_attrlist_buf rb 0x400 |
ntfs_attrlist_mft_buf rb 0x400 |
ntfs_bitmap_buf rb 0x400 |
ntfs_attr_iRecord dd ? |
ntfs_attr_iBaseRecord dd ? |
ntfs_attr_offs dd ? |
ntfs_attr_list dd ? |
ntfs_attr_size dq ? |
ntfs_cur_tail dd ? |
endg |
ntfs_read_attr: |
; in: global variables |
; out: [ntfs_cur_read] |
pushad |
and [ntfs_cur_read], 0 |
cmp [ntfs_cur_iRecord], 0 |
jnz .nomft |
cmp [ntfs_cur_attr], 0x80 |
jnz .nomft |
mov eax, [ntfs_data.mft_retrieval_end] |
inc eax |
mul [ntfs_data.sectors_per_cluster] |
cmp eax, [ntfs_cur_offs] |
jbe .nomft |
; precalculated part of $Mft $DATA |
mov esi, [ntfs_data.mft_retrieval] |
mov eax, [ntfs_cur_offs] |
xor edx, edx |
div [ntfs_data.sectors_per_cluster] |
; eax = VCN, edx = offset in sectors from beginning of cluster |
xor ecx, ecx ; ecx will contain LCN |
.mftscan: |
add ecx, [esi+4] |
sub eax, [esi] |
jb @f |
add esi, 8 |
push eax |
mov eax, [ntfs_data.mft_retrieval_end] |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
cmp eax, esi |
pop eax |
jnz .mftscan |
jmp .nomft |
@@: |
push ecx |
add ecx, eax |
add ecx, [esi] |
push eax |
push edx |
mov eax, [ntfs_data.sectors_per_cluster] |
mul ecx |
; eax = sector on partition |
add eax, [PARTITION_START] |
pop edx |
add eax, edx |
mov ebx, [ntfs_cur_buf] |
pop ecx |
neg ecx |
imul ecx, [ntfs_data.sectors_per_cluster] |
sub ecx, edx |
cmp ecx, [ntfs_cur_size] |
jb @f |
mov ecx, [ntfs_cur_size] |
@@: |
; ecx = number of sequential sectors to read |
call hd_read |
cmp [hd_error], 0 |
jnz .errread |
add [ntfs_cur_read], 0x200 |
dec [ntfs_cur_size] |
inc [ntfs_cur_offs] |
add ebx, 0x200 |
mov [ntfs_cur_buf], ebx |
inc eax |
loop @b |
pop ecx |
xor eax, eax |
xor edx, edx |
cmp [ntfs_cur_size], eax |
jz @f |
add esi, 8 |
push eax |
mov eax, [ntfs_data.mft_retrieval_end] |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
cmp eax, esi |
pop eax |
jz .nomft |
jmp .mftscan |
@@: |
popad |
ret |
.errread: |
pop ecx |
.errret: |
stc |
popad |
ret |
.nomft: |
; 1. Read file record. |
; N.B. This will do recursive call of read_attr for $MFT::$Data. |
mov eax, [ntfs_cur_iRecord] |
mov [ntfs_attr_iRecord], eax |
and [ntfs_attr_list], 0 |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
or [ntfs_attr_iBaseRecord], -1 |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
; 2. Find required attribute. |
mov eax, [ntfs_data.frs_buffer] |
; a) For auxiliary records, read base record |
; N.B. If base record is present, |
; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero |
cmp dword [eax+24h], 0 |
jz @f |
mov eax, [eax+20h] |
; test eax, eax |
; jz @f |
.beginfindattr: |
mov [ntfs_attr_iRecord], eax |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
@@: |
; b) Scan for required attribute and for $ATTR_LIST |
mov eax, [ntfs_data.frs_buffer] |
movzx ecx, word [eax+14h] |
add eax, ecx |
mov ecx, [ntfs_cur_attr] |
and [ntfs_attr_offs], 0 |
.scanattr: |
cmp dword [eax], -1 |
jz .scandone |
cmp dword [eax], ecx |
jz .okattr |
cmp [ntfs_attr_iBaseRecord], -1 |
jnz .scancont |
cmp dword [eax], 0x20 ; $ATTR_LIST |
jnz .scancont |
mov [ntfs_attr_list], eax |
jmp .scancont |
.okattr: |
; ignore named $DATA attributes (aka NTFS streams) |
cmp ecx, 0x80 |
jnz @f |
cmp byte [eax+9], 0 |
jnz .scancont |
@@: |
mov [ntfs_attr_offs], eax |
.scancont: |
add eax, [eax+4] |
jmp .scanattr |
.continue: |
pushad |
and [ntfs_cur_read], 0 |
.scandone: |
; c) Check for required offset and length |
mov ecx, [ntfs_attr_offs] |
jecxz .noattr |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
call .doreadattr |
pop edx |
pop eax |
jc @f |
cmp [ntfs_bCanContinue], 0 |
jz @f |
sub edx, [ntfs_cur_read] |
neg edx |
shr edx, 9 |
sub eax, edx |
mov [ntfs_cur_size], eax |
jnz .not_in_cur |
@@: |
popad |
ret |
.noattr: |
.not_in_cur: |
cmp [ntfs_cur_attr], 0x20 |
jz @f |
mov ecx, [ntfs_attr_list] |
test ecx, ecx |
jnz .lookattr |
.ret_is_attr: |
cmp [ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0 |
popad |
ret |
.lookattr: |
; required attribute or required offset was not found in base record; |
; it may be present in auxiliary records; |
; scan $ATTR_LIST |
mov eax, [ntfs_attr_iBaseRecord] |
cmp eax, -1 |
jz @f |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
or [ntfs_attr_iBaseRecord], -1 |
@@: |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
push [ntfs_cur_buf] |
push dword [ntfs_attr_size] |
push dword [ntfs_attr_size+4] |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 2 |
and [ntfs_cur_read], 0 |
mov eax, ntfs_attrlist_buf |
cmp [ntfs_cur_iRecord], 0 |
jnz @f |
mov eax, ntfs_attrlist_mft_buf |
@@: |
mov [ntfs_cur_buf], eax |
push eax |
call .doreadattr |
pop esi |
mov edx, 1 |
pop dword [ntfs_attr_size+4] |
pop dword [ntfs_attr_size] |
mov ebp, [ntfs_cur_read] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_read] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
jc .errret |
or edi, -1 |
lea ebp, [ebp+esi-1Ah] |
.scanliststart: |
mov eax, [ntfs_cur_attr] |
.scanlist: |
cmp esi, ebp |
jae .scanlistdone |
cmp eax, [esi] |
jz @f |
.scanlistcont: |
movzx ecx, word [esi+4] |
add esi, ecx |
jmp .scanlist |
@@: |
; ignore named $DATA attributes (aka NTFS streams) |
cmp eax, 0x80 |
jnz @f |
cmp byte [esi+6], 0 |
jnz .scanlistcont |
@@: |
push eax |
mov eax, [esi+8] |
test eax, eax |
jnz .testf |
mov eax, dword [ntfs_attr_size] |
and eax, dword [ntfs_attr_size+4] |
cmp eax, -1 |
jnz .testfz |
; if attribute is in auxiliary records, its size is defined only in first |
mov eax, [esi+10h] |
call ntfs_read_file_record |
test eax, eax |
jnz @f |
.errret_pop: |
pop eax |
jmp .errret |
@@: |
mov eax, [ntfs_data.frs_buffer] |
movzx ecx, word [eax+14h] |
add eax, ecx |
mov ecx, [ntfs_cur_attr] |
@@: |
cmp dword [eax], -1 |
jz .errret_pop |
cmp dword [eax], ecx |
jz @f |
.l1: |
add eax, [eax+4] |
jmp @b |
@@: |
cmp eax, 0x80 |
jnz @f |
cmp byte [eax+9], 0 |
jnz .l1 |
@@: |
cmp byte [eax+8], 0 |
jnz .sdnores |
mov eax, [eax+10h] |
mov dword [ntfs_attr_size], eax |
and dword [ntfs_attr_size+4], 0 |
jmp .testfz |
.sdnores: |
mov ecx, [eax+30h] |
mov dword [ntfs_attr_size], ecx |
mov ecx, [eax+34h] |
mov dword [ntfs_attr_size+4], ecx |
.testfz: |
xor eax, eax |
.testf: |
imul eax, [ntfs_data.sectors_per_cluster] |
cmp eax, [ntfs_cur_offs] |
pop eax |
ja @f |
mov edi, [esi+10h] ; keep previous iRecord |
jmp .scanlistcont |
@@: |
.scanlistfound: |
cmp edi, -1 |
jnz @f |
popad |
ret |
@@: |
mov eax, [ntfs_cur_iRecord] |
mov [ntfs_attr_iBaseRecord], eax |
mov eax, edi |
jmp .beginfindattr |
.sde: |
popad |
stc |
ret |
.scanlistdone: |
sub ebp, ntfs_attrlist_buf-1Ah |
cmp [ntfs_cur_iRecord], 0 |
jnz @f |
sub ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf |
@@: |
cmp ebp, 0x400 |
jnz .scanlistfound |
inc edx |
push esi edi |
mov esi, ntfs_attrlist_buf+0x200 |
mov edi, ntfs_attrlist_buf |
cmp [ntfs_cur_iRecord], 0 |
jnz @f |
mov esi, ntfs_attrlist_mft_buf+0x200 |
mov edi, ntfs_attrlist_mft_buf |
@@: |
mov ecx, 0x200/4 |
rep movsd |
mov eax, edi |
pop edi esi |
sub esi, 0x200 |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
push [ntfs_cur_buf] |
push dword [ntfs_attr_size] |
push dword [ntfs_attr_size+4] |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
mov [ntfs_cur_offs], edx |
mov [ntfs_cur_size], 1 |
and [ntfs_cur_read], 0 |
mov [ntfs_cur_buf], eax |
mov ecx, [ntfs_attr_list] |
push esi edx |
call .doreadattr |
pop edx esi |
mov ebp, [ntfs_cur_read] |
pop dword [ntfs_attr_size+4] |
pop dword [ntfs_attr_size] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_read] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
jc .errret |
add ebp, ntfs_attrlist_buf+0x200-0x1A |
cmp [ntfs_cur_iRecord], 0 |
jnz .scanliststart |
add ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf |
jmp .scanliststart |
.doreadattr: |
mov [ntfs_bCanContinue], 0 |
cmp byte [ecx+8], 0 |
jnz .nonresident |
mov eax, [ecx+10h] ; length |
mov esi, eax |
mov edx, [ntfs_cur_offs] |
shr eax, 9 |
cmp eax, edx |
jb .okret |
shl edx, 9 |
sub esi, edx |
movzx eax, word [ecx+14h] |
add edx, eax |
add edx, ecx ; edx -> data |
mov eax, [ntfs_cur_size] |
cmp eax, (0xFFFFFFFF shr 9)+1 |
jbe @f |
mov eax, (0xFFFFFFFF shr 9)+1 |
@@: |
shl eax, 9 |
cmp eax, esi |
jbe @f |
mov eax, esi |
@@: |
; eax = length, edx -> data |
mov [ntfs_cur_read], eax |
mov ecx, eax |
mov eax, edx |
mov ebx, [ntfs_cur_buf] |
call memmove |
and [ntfs_cur_size], 0 ; CF=0 |
ret |
.nonresident: |
; Not all auxiliary records contain correct FileSize info |
mov eax, dword [ntfs_attr_size] |
mov edx, dword [ntfs_attr_size+4] |
push eax |
and eax, edx |
cmp eax, -1 |
pop eax |
jnz @f |
mov eax, [ecx+30h] ; FileSize |
mov edx, [ecx+34h] |
mov dword [ntfs_attr_size], eax |
mov dword [ntfs_attr_size+4], edx |
@@: |
add eax, 0x1FF |
adc edx, 0 |
shrd eax, edx, 9 |
sub eax, [ntfs_cur_offs] |
ja @f |
; return with nothing read |
and [ntfs_cur_size], 0 |
.okret: |
clc |
ret |
@@: |
; reduce read length |
and [ntfs_cur_tail], 0 |
cmp [ntfs_cur_size], eax |
jb @f |
mov [ntfs_cur_size], eax |
mov eax, dword [ntfs_attr_size] |
and eax, 0x1FF |
mov [ntfs_cur_tail], eax |
@@: |
cmp [ntfs_cur_size], 0 |
jz .okret |
mov eax, [ntfs_cur_offs] |
xor edx, edx |
div [ntfs_data.sectors_per_cluster] |
sub eax, [ecx+10h] ; first_vbo |
jb .okret |
; eax = cluster, edx = starting sector |
sub esp, 10h |
movzx esi, word [ecx+20h] ; mcb_info_ofs |
add esi, ecx |
xor ebp, ebp |
.readloop: |
call ntfs_decode_mcb_entry |
jnc .break |
add ebp, [esp+8] |
sub eax, [esp] |
jae .readloop |
push ecx |
push eax |
add eax, [esp+8] |
add eax, ebp |
imul eax, [ntfs_data.sectors_per_cluster] |
add eax, edx |
add eax, [PARTITION_START] |
pop ecx |
neg ecx |
imul ecx, [ntfs_data.sectors_per_cluster] |
sub ecx, edx |
cmp ecx, [ntfs_cur_size] |
jb @f |
mov ecx, [ntfs_cur_size] |
@@: |
mov ebx, [ntfs_cur_buf] |
@@: |
call hd_read |
cmp [hd_error], 0 |
jnz .errread2 |
add ebx, 0x200 |
mov [ntfs_cur_buf], ebx |
inc eax |
add [ntfs_cur_read], 0x200 |
dec [ntfs_cur_size] |
inc [ntfs_cur_offs] |
loop @b |
pop ecx |
xor eax, eax |
xor edx, edx |
cmp [ntfs_cur_size], 0 |
jnz .readloop |
add esp, 10h |
mov eax, [ntfs_cur_tail] |
test eax, eax |
jz @f |
sub eax, 0x200 |
add [ntfs_cur_read], eax |
@@: |
clc |
ret |
.errread2: |
pop ecx |
add esp, 10h |
stc |
ret |
.break: |
add esp, 10h ; CF=0 |
mov [ntfs_bCanContinue], 1 |
ret |
ntfs_read_file_record: |
; in: eax=iRecord |
; out: [ntfs_data.frs_buffer] contains information |
; eax=0 - failed, eax=1 - success |
; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size] |
push ecx edx |
mov ecx, [ntfs_data.frs_size] |
mul ecx |
shrd eax, edx, 9 |
shr edx, 9 |
jnz .err |
push [ntfs_attr_iRecord] |
push [ntfs_attr_iBaseRecord] |
push [ntfs_attr_offs] |
push [ntfs_attr_list] |
push dword [ntfs_attr_size+4] |
push dword [ntfs_attr_size] |
push [ntfs_cur_iRecord] |
push [ntfs_cur_attr] |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_buf] |
push [ntfs_cur_read] |
mov [ntfs_cur_attr], 0x80 ; $DATA |
and [ntfs_cur_iRecord], 0 ; $Mft |
mov [ntfs_cur_offs], eax |
shr ecx, 9 |
mov [ntfs_cur_size], ecx |
mov eax, [ntfs_data.frs_buffer] |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
mov eax, [ntfs_cur_read] |
pop [ntfs_cur_read] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
pop [ntfs_cur_attr] |
pop [ntfs_cur_iRecord] |
pop dword [ntfs_attr_size] |
pop dword [ntfs_attr_size+4] |
pop [ntfs_attr_list] |
pop [ntfs_attr_offs] |
pop [ntfs_attr_iBaseRecord] |
pop [ntfs_attr_iRecord] |
pop edx ecx |
jc .errret |
cmp eax, [ntfs_data.frs_size] |
jnz .errret |
mov eax, [ntfs_data.frs_buffer] |
cmp dword [eax], 'FILE' |
jnz .errret |
push ebx |
mov ebx, eax |
call ntfs_restore_usa_frs |
pop ebx |
setnc al |
movzx eax, al |
.ret: |
ret |
.err: |
pop edx ecx |
.errret: |
xor eax, eax |
ret |
ntfs_restore_usa_frs: |
mov eax, [ntfs_data.frs_size] |
ntfs_restore_usa: |
pushad |
shr eax, 9 |
mov ecx, eax |
inc eax |
cmp [ebx+6], ax |
jnz .err |
movzx eax, word [ebx+4] |
lea esi, [eax+ebx] |
lodsw |
mov edx, eax |
lea edi, [ebx+0x1FE] |
@@: |
cmp [edi], dx |
jnz .err |
lodsw |
stosw |
add edi, 0x1FE |
loop @b |
popad |
clc |
ret |
.err: |
popad |
stc |
ret |
ntfs_decode_mcb_entry: |
push eax ecx edi |
lea edi, [esp+16] |
xor eax, eax |
lodsb |
test al, al |
jz .end |
mov ecx, eax |
and ecx, 0xF |
cmp ecx, 8 |
ja .end |
push ecx |
rep movsb |
pop ecx |
sub ecx, 8 |
neg ecx |
cmp byte [esi-1], 80h |
jae .end |
push eax |
xor eax, eax |
rep stosb |
pop ecx |
shr ecx, 4 |
cmp ecx, 8 |
ja .end |
push ecx |
rep movsb |
pop ecx |
sub ecx, 8 |
neg ecx |
cmp byte [esi-1], 80h |
cmc |
sbb eax, eax |
rep stosb |
stc |
.end: |
pop edi ecx eax |
ret |
unichar_toupper: |
push eax |
call uni2ansi_char |
cmp al, '_' |
jz .unk |
add esp, 4 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
ntfs_test_bootsec: |
; in: ebx->buffer, edx=size of partition |
; out: CF set <=> invalid |
; 1. Name=='NTFS ' |
cmp dword [ebx+3], 'NTFS' |
jnz .no |
cmp dword [ebx+7], ' ' |
jnz .no |
; 2. Number of bytes per sector is the same as for physical device |
; (that is, 0x200 for hard disk) |
cmp word [ebx+11], 0x200 |
jnz .no |
; 3. Number of sectors per cluster must be power of 2 |
movzx eax, byte [ebx+13] |
dec eax |
js .no |
test al, [ebx+13] |
jnz .no |
; 4. FAT parameters must be zero |
cmp word [ebx+14], 0 |
jnz .no |
cmp dword [ebx+16], 0 |
jnz .no |
cmp byte [ebx+20], 0 |
jnz .no |
cmp word [ebx+22], 0 |
jnz .no |
cmp dword [ebx+32], 0 |
jnz .no |
; 5. Number of sectors <= partition size |
cmp dword [ebx+0x2C], 0 |
ja .no |
cmp [ebx+0x28], edx |
ja .no |
; 6. $MFT and $MFTMirr clusters must be within partition |
cmp dword [ebx+0x34], 0 |
ja .no |
push edx |
movzx eax, byte [ebx+13] |
mul dword [ebx+0x30] |
test edx, edx |
pop edx |
jnz .no |
cmp eax, edx |
ja .no |
cmp dword [ebx+0x3C], 0 |
ja .no |
push edx |
movzx eax, byte [ebx+13] |
mul dword [ebx+0x38] |
test edx, edx |
pop edx |
jnz .no |
cmp eax, edx |
ja .no |
; 7. Clusters per FRS must be either negative and in [-31,-9] or positive and power of 2 |
movsx eax, byte [ebx+0x40] |
cmp al, -31 |
jl .no |
cmp al, -9 |
jle @f |
dec eax |
js .no |
test [ebx+0x40], al |
jnz .no |
@@: |
; 8. Same for clusters per IndexAllocationBuffer |
movsx eax, byte [ebx+0x44] |
cmp al, -31 |
jl .no |
cmp al, -9 |
jle @f |
dec eax |
js .no |
test [ebx+0x44], al |
jnz .no |
@@: |
; OK, this is correct NTFS bootsector |
clc |
ret |
.no: |
; No, this bootsector isn't NTFS |
stc |
ret |
ntfs_setup: ; CODE XREF: part_set.inc |
; By given bootsector, initialize some NTFS variables |
; call ntfs_test_bootsec ; checking boot sector was already |
; jc problem_fat_dec_count |
movzx eax, byte [ebx+13] |
mov [ntfs_data.sectors_per_cluster], eax |
mov eax, [ebx+0x28] |
add eax, [PARTITION_START] |
dec eax |
mov [PARTITION_END], eax |
mov [fs_type], 1 |
mov eax, [ebx+0x30] |
mov [ntfs_data.mft_cluster], eax |
mov eax, [ebx+0x38] |
mov [ntfs_data.mftmirr_cluster], eax |
movsx eax, byte [ebx+0x40] |
test eax, eax |
js .1 |
mul [ntfs_data.sectors_per_cluster] |
shl eax, 9 |
jmp .2 |
.1: |
neg eax |
mov ecx, eax |
mov eax, 1 |
shl eax, cl |
.2: |
mov [ntfs_data.frs_size], eax |
movsx eax, byte [ebx+0x44] |
test eax, eax |
js .3 |
mul [ntfs_data.sectors_per_cluster] |
shl eax, 9 |
jmp .4 |
.3: |
neg eax |
mov ecx, eax |
mov eax, 1 |
shl eax, cl |
.4: |
mov [ntfs_data.iab_size], eax |
; allocate space for buffers |
add eax, [ntfs_data.frs_size] |
push eax |
call kernel_alloc |
test eax, eax |
jz problem_fat_dec_count |
mov [ntfs_data.frs_buffer], eax |
add eax, [ntfs_data.frs_size] |
mov [ntfs_data.iab_buffer], eax |
; read $MFT disposition |
mov eax, [ntfs_data.mft_cluster] |
mul [ntfs_data.sectors_per_cluster] |
call ntfs_read_frs_sector |
cmp [hd_error], 0 |
jnz .usemirr |
cmp dword [ebx], 'FILE' |
jnz .usemirr |
call ntfs_restore_usa_frs |
jnc .mftok |
.usemirr: |
and [hd_error], 0 |
mov eax, [ntfs_data.mftmirr_cluster] |
mul [ntfs_data.sectors_per_cluster] |
call ntfs_read_frs_sector |
cmp [hd_error], 0 |
jnz @f |
cmp dword [ebx], 'FILE' |
jnz @f |
call ntfs_restore_usa_frs |
jnc .mftok |
@@: |
; $MFT and $MFTMirr invalid! |
.fail_free_frs: |
push [ntfs_data.frs_buffer] |
call kernel_free |
jmp problem_fat_dec_count |
.fail_free_mft: |
push [ntfs_data.mft_retrieval] |
call kernel_free |
jmp .fail_free_frs |
.mftok: |
; read $MFT table retrieval information |
; start with one page, increase if not enough (when MFT too fragmented) |
push ebx |
push 0x1000 |
call kernel_alloc |
pop ebx |
test eax, eax |
jz .fail_free_frs |
mov [ntfs_data.mft_retrieval], eax |
and [ntfs_data.mft_retrieval_size], 0 |
mov [ntfs_data.mft_retrieval_alloc], 0x1000/8 |
; $MFT base record must contain unnamed non-resident $DATA attribute |
movzx eax, word [ebx+14h] |
add eax, ebx |
.scandata: |
cmp dword [eax], -1 |
jz .fail_free_mft |
cmp dword [eax], 0x80 |
jnz @f |
cmp byte [eax+9], 0 |
jz .founddata |
@@: |
add eax, [eax+4] |
jmp .scandata |
.founddata: |
cmp byte [eax+8], 0 |
jz .fail_free_mft |
; load first portion of $DATA attribute retrieval information |
mov edx, [eax+0x18] |
mov [ntfs_data.mft_retrieval_end], edx |
mov esi, eax |
movzx eax, word [eax+0x20] |
add esi, eax |
sub esp, 10h |
.scanmcb: |
call ntfs_decode_mcb_entry |
jnc .scanmcbend |
call .get_mft_retrieval_ptr |
mov edx, [esp] ; block length |
mov [eax], edx |
mov edx, [esp+8] ; block addr (relative) |
mov [eax+4], edx |
inc [ntfs_data.mft_retrieval_size] |
jmp .scanmcb |
.scanmcbend: |
add esp, 10h |
; there may be other portions of $DATA attribute in auxiliary records; |
; if they will be needed, they will be loaded later |
mov [ntfs_data.cur_index_size], 0x1000/0x200 |
push 0x1000 |
call kernel_alloc |
test eax, eax |
jz .fail_free_mft |
mov [ntfs_data.cur_index_buf], eax |
popad |
call free_hd_channel |
and [hd1_status], 0 |
ret |
.get_mft_retrieval_ptr: |
pushad |
mov eax, [ntfs_data.mft_retrieval_size] |
cmp eax, [ntfs_data.mft_retrieval_alloc] |
jnz .ok |
add eax, 0x1000/8 |
mov [ntfs_data.mft_retrieval_alloc], eax |
shl eax, 3 |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
popad |
add esp, 14h |
jmp .fail_free_mft |
@@: |
mov esi, [ntfs_data.mft_retrieval] |
mov edi, eax |
mov ecx, [ntfs_data.mft_retrieval_size] |
add ecx, ecx |
rep movsd |
push [ntfs_data.mft_retrieval] |
mov [ntfs_data.mft_retrieval], eax |
call kernel_free |
mov eax, [ntfs_data.mft_retrieval_size] |
.ok: |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
mov [esp+28], eax |
popad |
ret |
ntfs_read_frs_sector: |
push eax ecx |
add eax, [PARTITION_START] |
mov ecx, [ntfs_data.frs_size] |
shr ecx, 9 |
mov ebx, [ntfs_data.frs_buffer] |
push ebx |
@@: |
call hd_read |
cmp [hd_error], 0 |
jnz .fail |
add ebx, 0x200 |
inc eax |
loop @b |
.fail: |
pop ebx |
pop ecx eax |
ret |
uglobal |
align 4 |
ntfs_cur_attr dd ? |
ntfs_cur_iRecord dd ? |
ntfs_cur_offs dd ? ; in sectors |
ntfs_cur_size dd ? ; in sectors |
ntfs_cur_buf dd ? |
ntfs_cur_read dd ? ; [output] |
ntfs_bCanContinue db ? |
rb 3 |
ntfs_attrlist_buf rb 0x400 |
ntfs_attrlist_mft_buf rb 0x400 |
ntfs_bitmap_buf rb 0x400 |
ntfs_attr_iRecord dd ? |
ntfs_attr_iBaseRecord dd ? |
ntfs_attr_offs dd ? |
ntfs_attr_list dd ? |
ntfs_attr_size dq ? |
ntfs_cur_tail dd ? |
endg |
ntfs_read_attr: |
; in: global variables |
; out: [ntfs_cur_read] |
pushad |
and [ntfs_cur_read], 0 |
cmp [ntfs_cur_iRecord], 0 |
jnz .nomft |
cmp [ntfs_cur_attr], 0x80 |
jnz .nomft |
mov eax, [ntfs_data.mft_retrieval_end] |
inc eax |
mul [ntfs_data.sectors_per_cluster] |
cmp eax, [ntfs_cur_offs] |
jbe .nomft |
; precalculated part of $Mft $DATA |
mov esi, [ntfs_data.mft_retrieval] |
mov eax, [ntfs_cur_offs] |
xor edx, edx |
div [ntfs_data.sectors_per_cluster] |
; eax = VCN, edx = offset in sectors from beginning of cluster |
xor ecx, ecx ; ecx will contain LCN |
.mftscan: |
add ecx, [esi+4] |
sub eax, [esi] |
jb @f |
add esi, 8 |
push eax |
mov eax, [ntfs_data.mft_retrieval_end] |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
cmp eax, esi |
pop eax |
jnz .mftscan |
jmp .nomft |
@@: |
push ecx |
add ecx, eax |
add ecx, [esi] |
push eax |
push edx |
mov eax, [ntfs_data.sectors_per_cluster] |
mul ecx |
; eax = sector on partition |
add eax, [PARTITION_START] |
pop edx |
add eax, edx |
mov ebx, [ntfs_cur_buf] |
pop ecx |
neg ecx |
imul ecx, [ntfs_data.sectors_per_cluster] |
sub ecx, edx |
cmp ecx, [ntfs_cur_size] |
jb @f |
mov ecx, [ntfs_cur_size] |
@@: |
; ecx = number of sequential sectors to read |
call hd_read |
cmp [hd_error], 0 |
jnz .errread |
add [ntfs_cur_read], 0x200 |
dec [ntfs_cur_size] |
inc [ntfs_cur_offs] |
add ebx, 0x200 |
mov [ntfs_cur_buf], ebx |
inc eax |
loop @b |
pop ecx |
xor eax, eax |
xor edx, edx |
cmp [ntfs_cur_size], eax |
jz @f |
add esi, 8 |
push eax |
mov eax, [ntfs_data.mft_retrieval_end] |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
cmp eax, esi |
pop eax |
jz .nomft |
jmp .mftscan |
@@: |
popad |
ret |
.errread: |
pop ecx |
.errret: |
stc |
popad |
ret |
.nomft: |
; 1. Read file record. |
; N.B. This will do recursive call of read_attr for $MFT::$Data. |
mov eax, [ntfs_cur_iRecord] |
mov [ntfs_attr_iRecord], eax |
and [ntfs_attr_list], 0 |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
or [ntfs_attr_iBaseRecord], -1 |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
; 2. Find required attribute. |
mov eax, [ntfs_data.frs_buffer] |
; a) For auxiliary records, read base record |
; N.B. If base record is present, |
; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero |
cmp dword [eax+24h], 0 |
jz @f |
mov eax, [eax+20h] |
; test eax, eax |
; jz @f |
.beginfindattr: |
mov [ntfs_attr_iRecord], eax |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
@@: |
; b) Scan for required attribute and for $ATTR_LIST |
mov eax, [ntfs_data.frs_buffer] |
movzx ecx, word [eax+14h] |
add eax, ecx |
mov ecx, [ntfs_cur_attr] |
and [ntfs_attr_offs], 0 |
.scanattr: |
cmp dword [eax], -1 |
jz .scandone |
cmp dword [eax], ecx |
jz .okattr |
cmp [ntfs_attr_iBaseRecord], -1 |
jnz .scancont |
cmp dword [eax], 0x20 ; $ATTR_LIST |
jnz .scancont |
mov [ntfs_attr_list], eax |
jmp .scancont |
.okattr: |
; ignore named $DATA attributes (aka NTFS streams) |
cmp ecx, 0x80 |
jnz @f |
cmp byte [eax+9], 0 |
jnz .scancont |
@@: |
mov [ntfs_attr_offs], eax |
.scancont: |
add eax, [eax+4] |
jmp .scanattr |
.continue: |
pushad |
and [ntfs_cur_read], 0 |
.scandone: |
; c) Check for required offset and length |
mov ecx, [ntfs_attr_offs] |
jecxz .noattr |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
call .doreadattr |
pop edx |
pop eax |
jc @f |
cmp [ntfs_bCanContinue], 0 |
jz @f |
sub edx, [ntfs_cur_read] |
neg edx |
shr edx, 9 |
sub eax, edx |
mov [ntfs_cur_size], eax |
jnz .not_in_cur |
@@: |
popad |
ret |
.noattr: |
.not_in_cur: |
cmp [ntfs_cur_attr], 0x20 |
jz @f |
mov ecx, [ntfs_attr_list] |
test ecx, ecx |
jnz .lookattr |
.ret_is_attr: |
cmp [ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0 |
popad |
ret |
.lookattr: |
; required attribute or required offset was not found in base record; |
; it may be present in auxiliary records; |
; scan $ATTR_LIST |
mov eax, [ntfs_attr_iBaseRecord] |
cmp eax, -1 |
jz @f |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
or [ntfs_attr_iBaseRecord], -1 |
@@: |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
push [ntfs_cur_buf] |
push dword [ntfs_attr_size] |
push dword [ntfs_attr_size+4] |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 2 |
and [ntfs_cur_read], 0 |
mov eax, ntfs_attrlist_buf |
cmp [ntfs_cur_iRecord], 0 |
jnz @f |
mov eax, ntfs_attrlist_mft_buf |
@@: |
mov [ntfs_cur_buf], eax |
push eax |
call .doreadattr |
pop esi |
mov edx, 1 |
pop dword [ntfs_attr_size+4] |
pop dword [ntfs_attr_size] |
mov ebp, [ntfs_cur_read] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_read] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
jc .errret |
or edi, -1 |
lea ebp, [ebp+esi-1Ah] |
.scanliststart: |
mov eax, [ntfs_cur_attr] |
.scanlist: |
cmp esi, ebp |
jae .scanlistdone |
cmp eax, [esi] |
jz @f |
.scanlistcont: |
movzx ecx, word [esi+4] |
add esi, ecx |
jmp .scanlist |
@@: |
; ignore named $DATA attributes (aka NTFS streams) |
cmp eax, 0x80 |
jnz @f |
cmp byte [esi+6], 0 |
jnz .scanlistcont |
@@: |
push eax |
mov eax, [esi+8] |
test eax, eax |
jnz .testf |
mov eax, dword [ntfs_attr_size] |
and eax, dword [ntfs_attr_size+4] |
cmp eax, -1 |
jnz .testfz |
; if attribute is in auxiliary records, its size is defined only in first |
mov eax, [esi+10h] |
call ntfs_read_file_record |
test eax, eax |
jnz @f |
.errret_pop: |
pop eax |
jmp .errret |
@@: |
mov eax, [ntfs_data.frs_buffer] |
movzx ecx, word [eax+14h] |
add eax, ecx |
mov ecx, [ntfs_cur_attr] |
@@: |
cmp dword [eax], -1 |
jz .errret_pop |
cmp dword [eax], ecx |
jz @f |
.l1: |
add eax, [eax+4] |
jmp @b |
@@: |
cmp eax, 0x80 |
jnz @f |
cmp byte [eax+9], 0 |
jnz .l1 |
@@: |
cmp byte [eax+8], 0 |
jnz .sdnores |
mov eax, [eax+10h] |
mov dword [ntfs_attr_size], eax |
and dword [ntfs_attr_size+4], 0 |
jmp .testfz |
.sdnores: |
mov ecx, [eax+30h] |
mov dword [ntfs_attr_size], ecx |
mov ecx, [eax+34h] |
mov dword [ntfs_attr_size+4], ecx |
.testfz: |
xor eax, eax |
.testf: |
imul eax, [ntfs_data.sectors_per_cluster] |
cmp eax, [ntfs_cur_offs] |
pop eax |
ja @f |
mov edi, [esi+10h] ; keep previous iRecord |
jmp .scanlistcont |
@@: |
.scanlistfound: |
cmp edi, -1 |
jnz @f |
popad |
ret |
@@: |
mov eax, [ntfs_cur_iRecord] |
mov [ntfs_attr_iBaseRecord], eax |
mov eax, edi |
jmp .beginfindattr |
.sde: |
popad |
stc |
ret |
.scanlistdone: |
sub ebp, ntfs_attrlist_buf-1Ah |
cmp [ntfs_cur_iRecord], 0 |
jnz @f |
sub ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf |
@@: |
cmp ebp, 0x400 |
jnz .scanlistfound |
inc edx |
push esi edi |
mov esi, ntfs_attrlist_buf+0x200 |
mov edi, ntfs_attrlist_buf |
cmp [ntfs_cur_iRecord], 0 |
jnz @f |
mov esi, ntfs_attrlist_mft_buf+0x200 |
mov edi, ntfs_attrlist_mft_buf |
@@: |
mov ecx, 0x200/4 |
rep movsd |
mov eax, edi |
pop edi esi |
sub esi, 0x200 |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
push [ntfs_cur_buf] |
push dword [ntfs_attr_size] |
push dword [ntfs_attr_size+4] |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
mov [ntfs_cur_offs], edx |
mov [ntfs_cur_size], 1 |
and [ntfs_cur_read], 0 |
mov [ntfs_cur_buf], eax |
mov ecx, [ntfs_attr_list] |
push esi edx |
call .doreadattr |
pop edx esi |
mov ebp, [ntfs_cur_read] |
pop dword [ntfs_attr_size+4] |
pop dword [ntfs_attr_size] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_read] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
jc .errret |
add ebp, ntfs_attrlist_buf+0x200-0x1A |
cmp [ntfs_cur_iRecord], 0 |
jnz .scanliststart |
add ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf |
jmp .scanliststart |
.doreadattr: |
mov [ntfs_bCanContinue], 0 |
cmp byte [ecx+8], 0 |
jnz .nonresident |
mov eax, [ecx+10h] ; length |
mov esi, eax |
mov edx, [ntfs_cur_offs] |
shr eax, 9 |
cmp eax, edx |
jb .okret |
shl edx, 9 |
sub esi, edx |
movzx eax, word [ecx+14h] |
add edx, eax |
add edx, ecx ; edx -> data |
mov eax, [ntfs_cur_size] |
cmp eax, (0xFFFFFFFF shr 9)+1 |
jbe @f |
mov eax, (0xFFFFFFFF shr 9)+1 |
@@: |
shl eax, 9 |
cmp eax, esi |
jbe @f |
mov eax, esi |
@@: |
; eax = length, edx -> data |
mov [ntfs_cur_read], eax |
mov ecx, eax |
mov eax, edx |
mov ebx, [ntfs_cur_buf] |
call memmove |
and [ntfs_cur_size], 0 ; CF=0 |
ret |
.nonresident: |
; Not all auxiliary records contain correct FileSize info |
mov eax, dword [ntfs_attr_size] |
mov edx, dword [ntfs_attr_size+4] |
push eax |
and eax, edx |
cmp eax, -1 |
pop eax |
jnz @f |
mov eax, [ecx+30h] ; FileSize |
mov edx, [ecx+34h] |
mov dword [ntfs_attr_size], eax |
mov dword [ntfs_attr_size+4], edx |
@@: |
add eax, 0x1FF |
adc edx, 0 |
shrd eax, edx, 9 |
sub eax, [ntfs_cur_offs] |
ja @f |
; return with nothing read |
and [ntfs_cur_size], 0 |
.okret: |
clc |
ret |
@@: |
; reduce read length |
and [ntfs_cur_tail], 0 |
cmp [ntfs_cur_size], eax |
jb @f |
mov [ntfs_cur_size], eax |
mov eax, dword [ntfs_attr_size] |
and eax, 0x1FF |
mov [ntfs_cur_tail], eax |
@@: |
cmp [ntfs_cur_size], 0 |
jz .okret |
mov eax, [ntfs_cur_offs] |
xor edx, edx |
div [ntfs_data.sectors_per_cluster] |
sub eax, [ecx+10h] ; first_vbo |
jb .okret |
; eax = cluster, edx = starting sector |
sub esp, 10h |
movzx esi, word [ecx+20h] ; mcb_info_ofs |
add esi, ecx |
xor ebp, ebp |
.readloop: |
call ntfs_decode_mcb_entry |
jnc .break |
add ebp, [esp+8] |
sub eax, [esp] |
jae .readloop |
push ecx |
push eax |
add eax, [esp+8] |
add eax, ebp |
imul eax, [ntfs_data.sectors_per_cluster] |
add eax, edx |
add eax, [PARTITION_START] |
pop ecx |
neg ecx |
imul ecx, [ntfs_data.sectors_per_cluster] |
sub ecx, edx |
cmp ecx, [ntfs_cur_size] |
jb @f |
mov ecx, [ntfs_cur_size] |
@@: |
mov ebx, [ntfs_cur_buf] |
@@: |
call hd_read |
cmp [hd_error], 0 |
jnz .errread2 |
add ebx, 0x200 |
mov [ntfs_cur_buf], ebx |
inc eax |
add [ntfs_cur_read], 0x200 |
dec [ntfs_cur_size] |
inc [ntfs_cur_offs] |
loop @b |
pop ecx |
xor eax, eax |
xor edx, edx |
cmp [ntfs_cur_size], 0 |
jnz .readloop |
add esp, 10h |
mov eax, [ntfs_cur_tail] |
test eax, eax |
jz @f |
sub eax, 0x200 |
add [ntfs_cur_read], eax |
@@: |
clc |
ret |
.errread2: |
pop ecx |
add esp, 10h |
stc |
ret |
.break: |
add esp, 10h ; CF=0 |
mov [ntfs_bCanContinue], 1 |
ret |
ntfs_read_file_record: |
; in: eax=iRecord |
; out: [ntfs_data.frs_buffer] contains information |
; eax=0 - failed, eax=1 - success |
; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size] |
push ecx edx |
mov ecx, [ntfs_data.frs_size] |
mul ecx |
shrd eax, edx, 9 |
shr edx, 9 |
jnz .err |
push [ntfs_attr_iRecord] |
push [ntfs_attr_iBaseRecord] |
push [ntfs_attr_offs] |
push [ntfs_attr_list] |
push dword [ntfs_attr_size+4] |
push dword [ntfs_attr_size] |
push [ntfs_cur_iRecord] |
push [ntfs_cur_attr] |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_buf] |
push [ntfs_cur_read] |
mov [ntfs_cur_attr], 0x80 ; $DATA |
and [ntfs_cur_iRecord], 0 ; $Mft |
mov [ntfs_cur_offs], eax |
shr ecx, 9 |
mov [ntfs_cur_size], ecx |
mov eax, [ntfs_data.frs_buffer] |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
mov eax, [ntfs_cur_read] |
pop [ntfs_cur_read] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
pop [ntfs_cur_attr] |
pop [ntfs_cur_iRecord] |
pop dword [ntfs_attr_size] |
pop dword [ntfs_attr_size+4] |
pop [ntfs_attr_list] |
pop [ntfs_attr_offs] |
pop [ntfs_attr_iBaseRecord] |
pop [ntfs_attr_iRecord] |
pop edx ecx |
jc .errret |
cmp eax, [ntfs_data.frs_size] |
jnz .errret |
mov eax, [ntfs_data.frs_buffer] |
cmp dword [eax], 'FILE' |
jnz .errret |
push ebx |
mov ebx, eax |
call ntfs_restore_usa_frs |
pop ebx |
setnc al |
movzx eax, al |
.ret: |
ret |
.err: |
pop edx ecx |
.errret: |
xor eax, eax |
ret |
ntfs_restore_usa_frs: |
mov eax, [ntfs_data.frs_size] |
ntfs_restore_usa: |
pushad |
shr eax, 9 |
mov ecx, eax |
inc eax |
cmp [ebx+6], ax |
jnz .err |
movzx eax, word [ebx+4] |
lea esi, [eax+ebx] |
lodsw |
mov edx, eax |
lea edi, [ebx+0x1FE] |
@@: |
cmp [edi], dx |
jnz .err |
lodsw |
stosw |
add edi, 0x1FE |
loop @b |
popad |
clc |
ret |
.err: |
popad |
stc |
ret |
ntfs_decode_mcb_entry: |
push eax ecx edi |
lea edi, [esp+16] |
xor eax, eax |
lodsb |
test al, al |
jz .end |
mov ecx, eax |
and ecx, 0xF |
cmp ecx, 8 |
ja .end |
push ecx |
rep movsb |
pop ecx |
sub ecx, 8 |
neg ecx |
cmp byte [esi-1], 80h |
jae .end |
push eax |
xor eax, eax |
rep stosb |
pop ecx |
shr ecx, 4 |
cmp ecx, 8 |
ja .end |
push ecx |
rep movsb |
pop ecx |
sub ecx, 8 |
neg ecx |
cmp byte [esi-1], 80h |
cmc |
sbb eax, eax |
rep stosb |
stc |
.end: |
pop edi ecx eax |
ret |
unichar_toupper: |
push eax |
call uni2ansi_char |
cmp al, '_' |
jz .unk |
add esp, 4 |
call char_toupper |
jmp ansi2uni_char |
.unk: |
pop eax |
ret |
ntfs_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0, [ntfs_cur_iRecord] valid, eax->record in parent directory |
mov [ntfs_cur_iRecord], 5 ; start parse from root cluster |
.doit2: |
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ntfs_cur_offs], 0 |
mov eax, [ntfs_data.cur_index_size] |
mov [ntfs_cur_size], eax |
mov eax, [ntfs_data.cur_index_buf] |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
jnc @f |
.ret: |
ret |
@@: |
cmp [ntfs_cur_read], 0x20 |
jc .ret |
pushad |
mov esi, [ntfs_data.cur_index_buf] |
mov eax, [esi+14h] |
add eax, 10h |
cmp [ntfs_cur_read], eax |
jae .readok1 |
add eax, 1FFh |
shr eax, 9 |
cmp eax, [ntfs_data.cur_index_size] |
ja @f |
.stc_ret: |
popad |
stc |
ret |
@@: |
; reallocate |
push eax |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop eax |
mov [ntfs_data.cur_index_size], eax |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
and [ntfs_data.cur_index_size], 0 |
and [ntfs_data.cur_index_buf], 0 |
jmp .stc_ret |
@@: |
mov [ntfs_data.cur_index_buf], eax |
popad |
jmp .doit2 |
.readok1: |
mov ebp, [esi+8] ; subnode_size |
shr ebp, 9 |
cmp ebp, [ntfs_data.cur_index_size] |
jbe .ok2 |
push esi ebp |
push ebp |
call kernel_alloc |
pop ebp esi |
test eax, eax |
jz .stc_ret |
mov edi, eax |
mov ecx, [ntfs_data.cur_index_size] |
shl ecx, 9-2 |
rep movsd |
mov esi, eax |
mov [ntfs_data.cur_index_size], ebp |
push esi ebp |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop ebp esi |
mov [ntfs_data.cur_index_buf], esi |
.ok2: |
add esi, 10h |
mov edi, [esp+4] |
; edi -> name, esi -> current index data, ebp = subnode size |
.scanloop: |
add esi, [esi] |
.scanloopint: |
test byte [esi+0Ch], 2 |
jnz .subnode |
push esi |
add esi, 0x52 |
movzx ecx, byte [esi-2] |
push edi |
@@: |
lodsw |
call unichar_toupper |
push eax |
mov al, [edi] |
inc edi |
cmp al, '/' |
jz .slash |
call char_toupper |
call ansi2uni_char |
cmp ax, [esp] |
pop eax |
loopz @b |
jz .found |
pop edi |
pop esi |
jb .subnode |
.scanloopcont: |
movzx eax, word [esi+8] |
add esi, eax |
jmp .scanloopint |
.slash: |
pop eax |
pop edi |
pop esi |
.subnode: |
test byte [esi+0Ch], 1 |
jz .notfound |
movzx eax, word [esi+8] |
mov eax, [esi+eax-8] |
mul [ntfs_data.sectors_per_cluster] |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION |
mov [ntfs_cur_size], ebp |
mov eax, [ntfs_data.cur_index_buf] |
mov esi, eax |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
mov eax, ebp |
shl eax, 9 |
cmp [ntfs_cur_read], eax |
jnz .notfound |
cmp dword [esi], 'INDX' |
jnz .notfound |
mov ebx, esi |
call ntfs_restore_usa |
jc .notfound |
add esi, 0x18 |
jmp .scanloop |
.notfound: |
popad |
stc |
ret |
.found: |
cmp byte [edi], 0 |
jz .done |
cmp byte [edi], '/' |
jz .next |
pop edi |
pop esi |
jmp .scanloopcont |
.done: |
.next: |
pop esi |
pop esi |
mov eax, [esi] |
mov [ntfs_cur_iRecord], eax |
mov [esp+1Ch], esi |
mov [esp+4], edi |
popad |
inc esi |
cmp byte [esi-1], 0 |
jnz .doit2 |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .doit2 |
@@: |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdRead - read NTFS hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdRead: |
cmp byte [esi], 0 |
jnz @f |
or ebx, -1 |
push ERROR_ACCESS_DENIED |
pop eax |
ret |
@@: |
call ntfs_find_lfn |
jnc .found |
or ebx, -1 |
push ERROR_FILE_NOT_FOUND |
pop eax |
ret |
.found: |
mov [ntfs_cur_attr], 0x80 ; $DATA |
and [ntfs_cur_offs], 0 |
and [ntfs_cur_size], 0 |
call ntfs_read_attr |
jnc @f |
or ebx, -1 |
push ERROR_ACCESS_DENIED |
pop eax |
ret |
@@: |
pushad |
and dword [esp+10h], 0 |
xor eax, eax |
test ebx, ebx |
jz .zero1 |
cmp dword [ebx+4], 0x200 |
jb @f |
.eof0: |
popad |
xor ebx, ebx |
.eof: |
push ERROR_END_OF_FILE |
pop eax |
ret |
@@: |
mov eax, [ebx] |
test eax, 0x1FF |
jz .alignedstart |
push edx |
mov edx, [ebx+4] |
shrd eax, edx, 9 |
pop edx |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
call ntfs_read_attr.continue |
mov eax, [ebx] |
and eax, 0x1FF |
lea esi, [ntfs_bitmap_buf+eax] |
sub eax, [ntfs_cur_read] |
jae .eof0 |
neg eax |
push ecx |
cmp ecx, eax |
jb @f |
mov ecx, eax |
@@: |
mov [esp+10h+4], ecx |
mov edi, edx |
rep movsb |
mov edx, edi |
pop ecx |
sub ecx, [esp+10h] |
jnz @f |
.retok: |
popad |
xor eax, eax |
ret |
@@: |
cmp [ntfs_cur_read], 0x200 |
jz .alignedstart |
.eof_ebx: |
popad |
jmp .eof |
.alignedstart: |
mov eax, [ebx] |
push edx |
mov edx, [ebx+4] |
add eax, 511 |
adc edx, 0 |
shrd eax, edx, 9 |
pop edx |
.zero1: |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_buf], edx |
mov eax, ecx |
shr eax, 9 |
mov [ntfs_cur_size], eax |
add eax, [ntfs_cur_offs] |
push eax |
call ntfs_read_attr.continue |
pop [ntfs_cur_offs] |
mov eax, [ntfs_cur_read] |
add [esp+10h], eax |
mov eax, ecx |
and eax, not 0x1FF |
cmp [ntfs_cur_read], eax |
jnz .eof_ebx |
and ecx, 0x1FF |
jz .retok |
add edx, [ntfs_cur_read] |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
call ntfs_read_attr.continue |
cmp [ntfs_cur_read], ecx |
jb @f |
mov [ntfs_cur_read], ecx |
@@: |
xchg ecx, [ntfs_cur_read] |
push ecx |
mov edi, edx |
mov esi, ntfs_bitmap_buf |
add [esp+10h+4], ecx |
rep movsb |
pop ecx |
xor eax, eax |
cmp ecx, [ntfs_cur_read] |
jz @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [esp+1Ch], eax |
popad |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdReadFolder - read NTFS hard disk folder |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdReadFolder: |
mov eax, 5 ; root cluster |
cmp byte [esi], 0 |
jz .doit |
call ntfs_find_lfn |
jnc .doit2 |
.notfound: |
or ebx, -1 |
push ERROR_FILE_NOT_FOUND |
.pop_ret: |
pop eax |
ret |
.doit: |
mov [ntfs_cur_iRecord], eax |
.doit2: |
mov [ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
call ntfs_read_attr |
jc .notfound |
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ntfs_cur_offs], 0 |
mov eax, [ntfs_data.cur_index_size] |
mov [ntfs_cur_size], eax |
mov eax, [ntfs_data.cur_index_buf] |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
jnc .ok |
cmp [hd_error], 0 |
jz .notfound |
or ebx, -1 |
push 11 |
jmp .pop_ret |
.ok: |
cmp [ntfs_cur_read], 0x20 |
jae @f |
or ebx, -1 |
.fserr: |
push ERROR_FAT_TABLE |
jmp .pop_ret |
@@: |
pushad |
mov esi, [ntfs_data.cur_index_buf] |
mov eax, [esi+14h] |
add eax, 10h |
cmp [ntfs_cur_read], eax |
jae .readok1 |
add eax, 1FFh |
shr eax, 9 |
cmp eax, [ntfs_data.cur_index_size] |
ja @f |
popad |
jmp .fserr |
@@: |
; reallocate |
push eax |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop eax |
mov [ntfs_data.cur_index_size], eax |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
and [ntfs_data.cur_index_size], 0 |
and [ntfs_data.cur_index_buf], 0 |
.nomem: |
popad |
or ebx, -1 |
push 12 |
pop eax |
ret |
@@: |
mov [ntfs_data.cur_index_buf], eax |
popad |
jmp .doit2 |
.readok1: |
mov ebp, [esi+8] ; subnode_size |
shr ebp, 9 |
cmp ebp, [ntfs_data.cur_index_size] |
jbe .ok2 |
push esi ebp |
push ebp |
call kernel_alloc |
pop ebp esi |
test eax, eax |
jz .nomem |
mov edi, eax |
mov ecx, [ntfs_data.cur_index_size] |
shl ecx, 9-2 |
rep movsd |
mov esi, eax |
mov [ntfs_data.cur_index_size], ebp |
push esi ebp |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop ebp esi |
mov [ntfs_data.cur_index_buf], esi |
.ok2: |
add esi, 10h |
mov ebx, [esp+10h] |
mov edx, [esp+14h] |
push dword [ebx+4] ; read ANSI/UNICODE name |
mov ebx, [ebx] |
; init header |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
mov byte [edx], 1 ; version |
mov ecx, [esp+4+18h] |
push edx |
mov edx, esp |
; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block, |
; ecx = number of blocks to read |
; edx -> parameters block: dd <output>, dd <flags> |
cmp [ntfs_cur_iRecord], 5 |
jz .skip_specials |
; dot and dotdot entries |
push esi |
xor esi, esi |
call .add_special_entry |
inc esi |
call .add_special_entry |
pop esi |
.skip_specials: |
; at first, dump index root |
add esi, [esi] |
.dump_root: |
test byte [esi+0Ch], 2 |
jnz .dump_root_done |
call .add_entry |
movzx eax, word [esi+8] |
add esi, eax |
jmp .dump_root |
.dump_root_done: |
; now dump all subnodes |
push ecx edi |
mov edi, ntfs_bitmap_buf |
mov [ntfs_cur_buf], edi |
mov ecx, 0x400/4 |
xor eax, eax |
rep stosd |
mov [ntfs_cur_attr], 0xB0 ; $BITMAP |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 2 |
call ntfs_read_attr |
pop edi ecx |
push 0 ; save offset in $BITMAP attribute |
and [ntfs_cur_offs], 0 |
.dumploop: |
mov [ntfs_cur_attr], 0xA0 |
mov [ntfs_cur_size], ebp |
mov eax, [ntfs_data.cur_index_buf] |
mov esi, eax |
mov [ntfs_cur_buf], eax |
push [ntfs_cur_offs] |
mov eax, [ntfs_cur_offs] |
imul eax, ebp |
mov [ntfs_cur_offs], eax |
call ntfs_read_attr |
pop [ntfs_cur_offs] |
mov eax, ebp |
shl eax, 9 |
cmp [ntfs_cur_read], eax |
jnz .done |
push eax |
mov eax, [ntfs_cur_offs] |
and eax, 0x400*8-1 |
bt dword [ntfs_bitmap_buf], eax |
pop eax |
jnc .dump_subnode_done |
cmp dword [esi], 'INDX' |
jnz .dump_subnode_done |
push ebx |
mov ebx, esi |
call ntfs_restore_usa |
pop ebx |
jc .dump_subnode_done |
add esi, 0x18 |
add esi, [esi] |
.dump_subnode: |
test byte [esi+0Ch], 2 |
jnz .dump_subnode_done |
call .add_entry |
movzx eax, word [esi+8] |
add esi, eax |
jmp .dump_subnode |
.dump_subnode_done: |
inc [ntfs_cur_offs] |
test [ntfs_cur_offs], 0x400*8-1 |
jnz .dumploop |
mov [ntfs_cur_attr], 0xB0 |
push ecx edi |
mov edi, ntfs_bitmap_buf |
mov [ntfs_cur_buf], edi |
mov ecx, 0x400/4 |
xor eax, eax |
rep stosd |
pop edi ecx |
pop eax |
push [ntfs_cur_offs] |
inc eax |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_size], 2 |
push eax |
call ntfs_read_attr |
pop eax |
pop [ntfs_cur_offs] |
push eax |
jmp .dumploop |
.done: |
pop eax |
pop edx |
mov ebx, [edx+4] |
pop edx |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [esp+1Ch], eax |
mov [esp+10h], ebx |
popad |
ret |
.add_special_entry: |
mov eax, [edx] |
inc dword [eax+8] ; new file found |
dec ebx |
jns .ret |
dec ecx |
js .ret |
inc dword [eax+4] ; new file block copied |
mov eax, [edx+4] |
mov [edi+4], eax |
; mov eax, dword [ntfs_bitmap_buf+0x20] |
; or al, 0x10 |
mov eax, 0x10 |
stosd |
scasd |
push edx |
mov eax, dword [ntfs_bitmap_buf] |
mov edx, dword [ntfs_bitmap_buf+4] |
call ntfs_datetime_to_bdfe |
mov eax, dword [ntfs_bitmap_buf+0x18] |
mov edx, dword [ntfs_bitmap_buf+0x1C] |
call ntfs_datetime_to_bdfe |
mov eax, dword [ntfs_bitmap_buf+8] |
mov edx, dword [ntfs_bitmap_buf+0xC] |
call ntfs_datetime_to_bdfe |
pop edx |
xor eax, eax |
stosd |
stosd |
mov al, '.' |
push edi ecx |
lea ecx, [esi+1] |
test byte [edi-0x24], 1 |
jz @f |
rep stosw |
pop ecx |
xor eax, eax |
stosw |
pop edi |
add edi, 520 |
ret |
@@: |
rep stosb |
pop ecx |
xor eax, eax |
stosb |
pop edi |
add edi, 264 |
.ret: |
ret |
.add_entry: |
; do not return DOS 8.3 names |
cmp byte [esi+0x51], 2 |
jz .ret |
; do not return system files |
; ... note that there will be no bad effects if system files also were reported ... |
cmp dword [esi], 0x10 |
jb .ret |
mov eax, [edx] |
inc dword [eax+8] ; new file found |
dec ebx |
jns .ret |
dec ecx |
js .ret |
inc dword [eax+4] ; new file block copied |
mov eax, [edx+4] ; flags |
call ntfs_direntry_to_bdfe |
push ecx esi edi |
movzx ecx, byte [esi+0x50] |
add esi, 0x52 |
test byte [edi-0x24], 1 |
jz .ansi |
shr ecx, 1 |
rep movsd |
adc ecx, ecx |
rep movsw |
and word [edi], 0 |
pop edi |
add edi, 520 |
pop esi ecx |
ret |
.ansi: |
jecxz .skip |
@@: |
lodsw |
call uni2ansi_char |
stosb |
loop @b |
.skip: |
xor al, al |
stosb |
pop edi |
add edi, 264 |
pop esi ecx |
ret |
ntfs_direntry_to_bdfe: |
mov [edi+4], eax ; ANSI/UNICODE name |
mov eax, [esi+48h] |
test eax, 0x10000000 |
jz @f |
and eax, not 0x10000000 |
or al, 0x10 |
@@: |
stosd |
scasd |
push edx |
mov eax, [esi+0x18] |
mov edx, [esi+0x1C] |
call ntfs_datetime_to_bdfe |
mov eax, [esi+0x30] |
mov edx, [esi+0x34] |
call ntfs_datetime_to_bdfe |
mov eax, [esi+0x20] |
mov edx, [esi+0x24] |
call ntfs_datetime_to_bdfe |
pop edx |
mov eax, [esi+0x40] |
stosd |
mov eax, [esi+0x44] |
stosd |
ret |
iglobal |
_24 dd 24 |
_60 dd 60 |
_10000000 dd 10000000 |
days400year dd 365*400+100-4+1 |
days100year dd 365*100+25-1 |
days4year dd 365*4+1 |
days1year dd 365 |
months dd 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 |
months2 dd 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 |
_400 dd 400 |
_100 dd 100 |
endg |
ntfs_datetime_to_bdfe: |
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC |
push eax |
mov eax, edx |
xor edx, edx |
div [_10000000] |
xchg eax, [esp] |
div [_10000000] |
ntfs_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0, [ntfs_cur_iRecord] valid, eax->record in parent directory |
mov [ntfs_cur_iRecord], 5 ; start parse from root cluster |
.doit2: |
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ntfs_cur_offs], 0 |
mov eax, [ntfs_data.cur_index_size] |
mov [ntfs_cur_size], eax |
mov eax, [ntfs_data.cur_index_buf] |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
jnc @f |
.ret: |
ret |
@@: |
cmp [ntfs_cur_read], 0x20 |
jc .ret |
pushad |
mov esi, [ntfs_data.cur_index_buf] |
mov eax, [esi+14h] |
add eax, 10h |
cmp [ntfs_cur_read], eax |
jae .readok1 |
add eax, 1FFh |
shr eax, 9 |
cmp eax, [ntfs_data.cur_index_size] |
ja @f |
.stc_ret: |
popad |
stc |
ret |
@@: |
; reallocate |
push eax |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop eax |
mov [ntfs_data.cur_index_size], eax |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
and [ntfs_data.cur_index_size], 0 |
and [ntfs_data.cur_index_buf], 0 |
jmp .stc_ret |
@@: |
mov [ntfs_data.cur_index_buf], eax |
popad |
jmp .doit2 |
.readok1: |
mov ebp, [esi+8] ; subnode_size |
shr ebp, 9 |
cmp ebp, [ntfs_data.cur_index_size] |
jbe .ok2 |
push esi ebp |
push ebp |
call kernel_alloc |
pop ebp esi |
test eax, eax |
jz .stc_ret |
mov edi, eax |
mov ecx, [ntfs_data.cur_index_size] |
shl ecx, 9-2 |
rep movsd |
mov esi, eax |
mov [ntfs_data.cur_index_size], ebp |
push esi ebp |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop ebp esi |
mov [ntfs_data.cur_index_buf], esi |
.ok2: |
add esi, 10h |
mov edi, [esp+4] |
; edi -> name, esi -> current index data, ebp = subnode size |
.scanloop: |
add esi, [esi] |
.scanloopint: |
test byte [esi+0Ch], 2 |
jnz .subnode |
push esi |
add esi, 0x52 |
movzx ecx, byte [esi-2] |
push edi |
@@: |
lodsw |
call unichar_toupper |
push eax |
mov al, [edi] |
inc edi |
cmp al, '/' |
jz .slash |
call char_toupper |
call ansi2uni_char |
cmp ax, [esp] |
pop eax |
loopz @b |
jz .found |
pop edi |
pop esi |
jb .subnode |
.scanloopcont: |
movzx eax, word [esi+8] |
add esi, eax |
jmp .scanloopint |
.slash: |
pop eax |
pop edi |
pop esi |
.subnode: |
test byte [esi+0Ch], 1 |
jz .notfound |
movzx eax, word [esi+8] |
mov eax, [esi+eax-8] |
mul [ntfs_data.sectors_per_cluster] |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION |
mov [ntfs_cur_size], ebp |
mov eax, [ntfs_data.cur_index_buf] |
mov esi, eax |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
mov eax, ebp |
shl eax, 9 |
cmp [ntfs_cur_read], eax |
jnz .notfound |
cmp dword [esi], 'INDX' |
jnz .notfound |
mov ebx, esi |
call ntfs_restore_usa |
jc .notfound |
add esi, 0x18 |
jmp .scanloop |
.notfound: |
popad |
stc |
ret |
.found: |
cmp byte [edi], 0 |
jz .done |
cmp byte [edi], '/' |
jz .next |
pop edi |
pop esi |
jmp .scanloopcont |
.done: |
.next: |
pop esi |
pop esi |
mov eax, [esi] |
mov [ntfs_cur_iRecord], eax |
mov [esp+1Ch], esi |
mov [esp+4], edi |
popad |
inc esi |
cmp byte [esi-1], 0 |
jnz .doit2 |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .doit2 |
@@: |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdRead - read NTFS hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdRead: |
cmp byte [esi], 0 |
jnz @f |
or ebx, -1 |
push ERROR_ACCESS_DENIED |
pop eax |
ret |
@@: |
call ntfs_find_lfn |
jnc .found |
or ebx, -1 |
push ERROR_FILE_NOT_FOUND |
pop eax |
ret |
.found: |
mov [ntfs_cur_attr], 0x80 ; $DATA |
and [ntfs_cur_offs], 0 |
and [ntfs_cur_size], 0 |
call ntfs_read_attr |
jnc @f |
or ebx, -1 |
push ERROR_ACCESS_DENIED |
pop eax |
ret |
@@: |
pushad |
and dword [esp+10h], 0 |
xor eax, eax |
test ebx, ebx |
jz .zero1 |
cmp dword [ebx+4], 0x200 |
jb @f |
.eof0: |
popad |
xor ebx, ebx |
.eof: |
push ERROR_END_OF_FILE |
pop eax |
ret |
@@: |
mov eax, [ebx] |
test eax, 0x1FF |
jz .alignedstart |
push edx |
mov edx, [ebx+4] |
shrd eax, edx, 9 |
pop edx |
.sec: |
; edx:eax = number of seconds since January 1, 1601 |
push eax |
mov eax, edx |
xor edx, edx |
div [_60] |
xchg eax, [esp] |
div [_60] |
mov [edi], dl |
pop edx |
; edx:eax = number of minutes |
div [_60] |
mov [edi+1], dl |
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32) |
xor edx, edx |
div [_24] |
mov [edi+2], dl |
mov [edi+3], byte 0 |
; eax = number of days since January 1, 1601 |
xor edx, edx |
div [days400year] |
imul eax, 400 |
add eax, 1601 |
mov [edi+6], ax |
mov eax, edx |
xor edx, edx |
div [days100year] |
cmp al, 4 |
jnz @f |
dec eax |
add edx, [days100year] |
@@: |
imul eax, 100 |
add [edi+6], ax |
mov eax, edx |
xor edx, edx |
div [days4year] |
shl eax, 2 |
add [edi+6], ax |
mov eax, edx |
xor edx, edx |
div [days1year] |
cmp al, 4 |
jnz @f |
dec eax |
add edx, [days1year] |
@@: |
add [edi+6], ax |
push esi edx |
mov esi, months |
movzx eax, word [edi+6] |
test al, 3 |
jnz .noleap |
xor edx, edx |
push eax |
div [_400] |
pop eax |
test edx, edx |
jz .leap |
xor edx, edx |
div [_100] |
test edx, edx |
jz .noleap |
.leap: |
mov esi, months2 |
.noleap: |
pop edx |
xor eax, eax |
inc eax |
@@: |
sub edx, [esi] |
jb @f |
add esi, 4 |
inc eax |
jmp @b |
@@: |
add edx, [esi] |
pop esi |
inc edx |
mov [edi+4], dl |
mov [edi+5], al |
add edi, 8 |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdRewrite - write to NTFS hard disk |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdRewrite: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdWrite - write to NTFS hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdWrite: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdSetFileEnd - set end of file on NTFS hard disk |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdSetFileEnd: |
ntfs_HdSetFileInfo: |
;---------------------------------------------------------------- |
; |
; ntfs_HdDelete - delete file or empty folder from NTFS hard disk |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdDelete: |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
ntfs_HdGetFileInfo: |
cmp byte [esi], 0 |
jnz @f |
push 2 |
pop eax |
ret |
@@: |
call ntfs_find_lfn |
jnc .doit |
push ERROR_FILE_NOT_FOUND |
pop eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
.doit: |
push esi edi |
mov esi, eax |
mov edi, edx |
xor eax, eax |
call ntfs_direntry_to_bdfe |
pop edi esi |
xor eax, eax |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
call ntfs_read_attr.continue |
mov eax, [ebx] |
and eax, 0x1FF |
lea esi, [ntfs_bitmap_buf+eax] |
sub eax, [ntfs_cur_read] |
jae .eof0 |
neg eax |
push ecx |
cmp ecx, eax |
jb @f |
mov ecx, eax |
@@: |
mov [esp+10h+4], ecx |
mov edi, edx |
rep movsb |
mov edx, edi |
pop ecx |
sub ecx, [esp+10h] |
jnz @f |
.retok: |
popad |
xor eax, eax |
ret |
@@: |
cmp [ntfs_cur_read], 0x200 |
jz .alignedstart |
.eof_ebx: |
popad |
jmp .eof |
.alignedstart: |
mov eax, [ebx] |
push edx |
mov edx, [ebx+4] |
add eax, 511 |
adc edx, 0 |
shrd eax, edx, 9 |
pop edx |
.zero1: |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_buf], edx |
mov eax, ecx |
shr eax, 9 |
mov [ntfs_cur_size], eax |
add eax, [ntfs_cur_offs] |
push eax |
call ntfs_read_attr.continue |
pop [ntfs_cur_offs] |
mov eax, [ntfs_cur_read] |
add [esp+10h], eax |
mov eax, ecx |
and eax, not 0x1FF |
cmp [ntfs_cur_read], eax |
jnz .eof_ebx |
and ecx, 0x1FF |
jz .retok |
add edx, [ntfs_cur_read] |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
call ntfs_read_attr.continue |
cmp [ntfs_cur_read], ecx |
jb @f |
mov [ntfs_cur_read], ecx |
@@: |
xchg ecx, [ntfs_cur_read] |
push ecx |
mov edi, edx |
mov esi, ntfs_bitmap_buf |
add [esp+10h+4], ecx |
rep movsb |
pop ecx |
xor eax, eax |
cmp ecx, [ntfs_cur_read] |
jz @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [esp+1Ch], eax |
popad |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdReadFolder - read NTFS hard disk folder |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdReadFolder: |
mov eax, 5 ; root cluster |
cmp byte [esi], 0 |
jz .doit |
call ntfs_find_lfn |
jnc .doit2 |
.notfound: |
or ebx, -1 |
push ERROR_FILE_NOT_FOUND |
.pop_ret: |
pop eax |
ret |
.doit: |
mov [ntfs_cur_iRecord], eax |
.doit2: |
mov [ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
call ntfs_read_attr |
jc .notfound |
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ntfs_cur_offs], 0 |
mov eax, [ntfs_data.cur_index_size] |
mov [ntfs_cur_size], eax |
mov eax, [ntfs_data.cur_index_buf] |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
jnc .ok |
cmp [hd_error], 0 |
jz .notfound |
or ebx, -1 |
push 11 |
jmp .pop_ret |
.ok: |
cmp [ntfs_cur_read], 0x20 |
jae @f |
or ebx, -1 |
.fserr: |
push ERROR_FAT_TABLE |
jmp .pop_ret |
@@: |
pushad |
mov esi, [ntfs_data.cur_index_buf] |
mov eax, [esi+14h] |
add eax, 10h |
cmp [ntfs_cur_read], eax |
jae .readok1 |
add eax, 1FFh |
shr eax, 9 |
cmp eax, [ntfs_data.cur_index_size] |
ja @f |
popad |
jmp .fserr |
@@: |
; reallocate |
push eax |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop eax |
mov [ntfs_data.cur_index_size], eax |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
and [ntfs_data.cur_index_size], 0 |
and [ntfs_data.cur_index_buf], 0 |
.nomem: |
popad |
or ebx, -1 |
push 12 |
pop eax |
ret |
@@: |
mov [ntfs_data.cur_index_buf], eax |
popad |
jmp .doit2 |
.readok1: |
mov ebp, [esi+8] ; subnode_size |
shr ebp, 9 |
cmp ebp, [ntfs_data.cur_index_size] |
jbe .ok2 |
push esi ebp |
push ebp |
call kernel_alloc |
pop ebp esi |
test eax, eax |
jz .nomem |
mov edi, eax |
mov ecx, [ntfs_data.cur_index_size] |
shl ecx, 9-2 |
rep movsd |
mov esi, eax |
mov [ntfs_data.cur_index_size], ebp |
push esi ebp |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop ebp esi |
mov [ntfs_data.cur_index_buf], esi |
.ok2: |
add esi, 10h |
mov ebx, [esp+10h] |
mov edx, [esp+14h] |
push dword [ebx+4] ; read ANSI/UNICODE name |
mov ebx, [ebx] |
; init header |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
mov byte [edx], 1 ; version |
mov ecx, [esp+4+18h] |
push edx |
mov edx, esp |
; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block, |
; ecx = number of blocks to read |
; edx -> parameters block: dd <output>, dd <flags> |
cmp [ntfs_cur_iRecord], 5 |
jz .skip_specials |
; dot and dotdot entries |
push esi |
xor esi, esi |
call .add_special_entry |
inc esi |
call .add_special_entry |
pop esi |
.skip_specials: |
; at first, dump index root |
add esi, [esi] |
.dump_root: |
test byte [esi+0Ch], 2 |
jnz .dump_root_done |
call .add_entry |
movzx eax, word [esi+8] |
add esi, eax |
jmp .dump_root |
.dump_root_done: |
; now dump all subnodes |
push ecx edi |
mov edi, ntfs_bitmap_buf |
mov [ntfs_cur_buf], edi |
mov ecx, 0x400/4 |
xor eax, eax |
rep stosd |
mov [ntfs_cur_attr], 0xB0 ; $BITMAP |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 2 |
call ntfs_read_attr |
pop edi ecx |
push 0 ; save offset in $BITMAP attribute |
and [ntfs_cur_offs], 0 |
.dumploop: |
mov [ntfs_cur_attr], 0xA0 |
mov [ntfs_cur_size], ebp |
mov eax, [ntfs_data.cur_index_buf] |
mov esi, eax |
mov [ntfs_cur_buf], eax |
push [ntfs_cur_offs] |
mov eax, [ntfs_cur_offs] |
imul eax, ebp |
mov [ntfs_cur_offs], eax |
call ntfs_read_attr |
pop [ntfs_cur_offs] |
mov eax, ebp |
shl eax, 9 |
cmp [ntfs_cur_read], eax |
jnz .done |
push eax |
mov eax, [ntfs_cur_offs] |
and eax, 0x400*8-1 |
bt dword [ntfs_bitmap_buf], eax |
pop eax |
jnc .dump_subnode_done |
cmp dword [esi], 'INDX' |
jnz .dump_subnode_done |
push ebx |
mov ebx, esi |
call ntfs_restore_usa |
pop ebx |
jc .dump_subnode_done |
add esi, 0x18 |
add esi, [esi] |
.dump_subnode: |
test byte [esi+0Ch], 2 |
jnz .dump_subnode_done |
call .add_entry |
movzx eax, word [esi+8] |
add esi, eax |
jmp .dump_subnode |
.dump_subnode_done: |
inc [ntfs_cur_offs] |
test [ntfs_cur_offs], 0x400*8-1 |
jnz .dumploop |
mov [ntfs_cur_attr], 0xB0 |
push ecx edi |
mov edi, ntfs_bitmap_buf |
mov [ntfs_cur_buf], edi |
mov ecx, 0x400/4 |
xor eax, eax |
rep stosd |
pop edi ecx |
pop eax |
push [ntfs_cur_offs] |
inc eax |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_size], 2 |
push eax |
call ntfs_read_attr |
pop eax |
pop [ntfs_cur_offs] |
push eax |
jmp .dumploop |
.done: |
pop eax |
pop edx |
mov ebx, [edx+4] |
pop edx |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [esp+1Ch], eax |
mov [esp+10h], ebx |
popad |
ret |
.add_special_entry: |
mov eax, [edx] |
inc dword [eax+8] ; new file found |
dec ebx |
jns .ret |
dec ecx |
js .ret |
inc dword [eax+4] ; new file block copied |
mov eax, [edx+4] |
mov [edi+4], eax |
; mov eax, dword [ntfs_bitmap_buf+0x20] |
; or al, 0x10 |
mov eax, 0x10 |
stosd |
scasd |
push edx |
mov eax, dword [ntfs_bitmap_buf] |
mov edx, dword [ntfs_bitmap_buf+4] |
call ntfs_datetime_to_bdfe |
mov eax, dword [ntfs_bitmap_buf+0x18] |
mov edx, dword [ntfs_bitmap_buf+0x1C] |
call ntfs_datetime_to_bdfe |
mov eax, dword [ntfs_bitmap_buf+8] |
mov edx, dword [ntfs_bitmap_buf+0xC] |
call ntfs_datetime_to_bdfe |
pop edx |
xor eax, eax |
stosd |
stosd |
mov al, '.' |
push edi ecx |
lea ecx, [esi+1] |
test byte [edi-0x24], 1 |
jz @f |
rep stosw |
pop ecx |
xor eax, eax |
stosw |
pop edi |
add edi, 520 |
ret |
@@: |
rep stosb |
pop ecx |
xor eax, eax |
stosb |
pop edi |
add edi, 264 |
.ret: |
ret |
.add_entry: |
; do not return DOS 8.3 names |
cmp byte [esi+0x51], 2 |
jz .ret |
; do not return system files |
; ... note that there will be no bad effects if system files also were reported ... |
cmp dword [esi], 0x10 |
jb .ret |
mov eax, [edx] |
inc dword [eax+8] ; new file found |
dec ebx |
jns .ret |
dec ecx |
js .ret |
inc dword [eax+4] ; new file block copied |
mov eax, [edx+4] ; flags |
call ntfs_direntry_to_bdfe |
push ecx esi edi |
movzx ecx, byte [esi+0x50] |
add esi, 0x52 |
test byte [edi-0x24], 1 |
jz .ansi |
shr ecx, 1 |
rep movsd |
adc ecx, ecx |
rep movsw |
and word [edi], 0 |
pop edi |
add edi, 520 |
pop esi ecx |
ret |
.ansi: |
jecxz .skip |
@@: |
lodsw |
call uni2ansi_char |
stosb |
loop @b |
.skip: |
xor al, al |
stosb |
pop edi |
add edi, 264 |
pop esi ecx |
ret |
ntfs_direntry_to_bdfe: |
mov [edi+4], eax ; ANSI/UNICODE name |
mov eax, [esi+48h] |
test eax, 0x10000000 |
jz @f |
and eax, not 0x10000000 |
or al, 0x10 |
@@: |
stosd |
scasd |
push edx |
mov eax, [esi+0x18] |
mov edx, [esi+0x1C] |
call ntfs_datetime_to_bdfe |
mov eax, [esi+0x30] |
mov edx, [esi+0x34] |
call ntfs_datetime_to_bdfe |
mov eax, [esi+0x20] |
mov edx, [esi+0x24] |
call ntfs_datetime_to_bdfe |
pop edx |
mov eax, [esi+0x40] |
stosd |
mov eax, [esi+0x44] |
stosd |
ret |
iglobal |
_24 dd 24 |
_60 dd 60 |
_10000000 dd 10000000 |
days400year dd 365*400+100-4+1 |
days100year dd 365*100+25-1 |
days4year dd 365*4+1 |
days1year dd 365 |
months dd 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 |
months2 dd 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 |
_400 dd 400 |
_100 dd 100 |
endg |
ntfs_datetime_to_bdfe: |
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC |
push eax |
mov eax, edx |
xor edx, edx |
div [_10000000] |
xchg eax, [esp] |
div [_10000000] |
pop edx |
.sec: |
; edx:eax = number of seconds since January 1, 1601 |
push eax |
mov eax, edx |
xor edx, edx |
div [_60] |
xchg eax, [esp] |
div [_60] |
mov [edi], dl |
pop edx |
; edx:eax = number of minutes |
div [_60] |
mov [edi+1], dl |
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32) |
xor edx, edx |
div [_24] |
mov [edi+2], dl |
mov [edi+3], byte 0 |
; eax = number of days since January 1, 1601 |
xor edx, edx |
div [days400year] |
imul eax, 400 |
add eax, 1601 |
mov [edi+6], ax |
mov eax, edx |
xor edx, edx |
div [days100year] |
cmp al, 4 |
jnz @f |
dec eax |
add edx, [days100year] |
@@: |
imul eax, 100 |
add [edi+6], ax |
mov eax, edx |
xor edx, edx |
div [days4year] |
shl eax, 2 |
add [edi+6], ax |
mov eax, edx |
xor edx, edx |
div [days1year] |
cmp al, 4 |
jnz @f |
dec eax |
add edx, [days1year] |
@@: |
add [edi+6], ax |
push esi edx |
mov esi, months |
movzx eax, word [edi+6] |
test al, 3 |
jnz .noleap |
xor edx, edx |
push eax |
div [_400] |
pop eax |
test edx, edx |
jz .leap |
xor edx, edx |
div [_100] |
test edx, edx |
jz .noleap |
.leap: |
mov esi, months2 |
.noleap: |
pop edx |
xor eax, eax |
inc eax |
@@: |
sub edx, [esi] |
jb @f |
add esi, 4 |
inc eax |
jmp @b |
@@: |
add edx, [esi] |
pop esi |
inc edx |
mov [edi+4], dl |
mov [edi+5], al |
add edi, 8 |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdRewrite - write to NTFS hard disk |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdRewrite: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdWrite - write to NTFS hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdWrite: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdSetFileEnd - set end of file on NTFS hard disk |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdSetFileEnd: |
ntfs_HdSetFileInfo: |
;---------------------------------------------------------------- |
; |
; ntfs_HdDelete - delete file or empty folder from NTFS hard disk |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdDelete: |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
ntfs_HdGetFileInfo: |
cmp byte [esi], 0 |
jnz @f |
push 2 |
pop eax |
ret |
@@: |
call ntfs_find_lfn |
jnc .doit |
push ERROR_FILE_NOT_FOUND |
pop eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
.doit: |
push esi edi |
mov esi, eax |
mov edi, edx |
xor eax, eax |
call ntfs_direntry_to_bdfe |
pop edi esi |
xor eax, eax |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fs/parse_fn.inc |
---|
1,236 → 1,236 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;------------------------------------------------------------------------- |
; |
; File path partial substitution (according to configuration) |
; |
; |
; SPraid |
; |
;------------------------------------------------------------------------- |
$Revision$ |
iglobal |
; pointer to memory for path replace table, |
; size of one record is 128 bytes: 64 bytes for search pattern + 64 bytes for replace string |
; start with one entry: sys -> <sysdir> |
full_file_name_table dd sysdir_name |
.size dd 1 |
tmp_file_name_size dd 1 |
endg |
uglobal |
; Parser_params will initialize: sysdir_name = "sys", sysdir_path = <sysdir> |
sysdir_name rb 64 |
sysdir_path rb 64 |
tmp_file_name_table dd ? |
endg |
; use bx_from_load and init system directory /sys |
proc Parser_params |
locals |
buff db 4 dup(?) ; for test cd |
endl |
mov eax,[OS_BASE+0x10000+bx_from_load] |
mov ecx,sysdir_path |
mov [ecx-64],dword 'sys' |
cmp al,'r' ; if ram disk |
jnz @f |
mov [ecx],dword 'RD/?' |
mov [ecx+3],byte ah |
mov [ecx+4],byte 0 |
ret |
@@: |
cmp al,'m' ; if ram disk |
jnz @f |
mov [ecx],dword 'CD?/' ; if cd disk {m} |
mov [ecx+4],byte '1' |
mov [ecx+5],dword '/KOL' |
mov [ecx+9],dword 'IBRI' |
mov [ecx+13],byte 0 |
.next_cd: |
mov [ecx+2],byte ah |
inc ah |
cmp ah,'5' |
je .not_found_cd |
lea edx,[buff] |
pushad |
stdcall read_file,read_firstapp,edx,0,4 |
popad |
cmp [edx],dword 'MENU' |
jne .next_cd |
jmp .ok |
@@: |
sub al,49 |
mov [ecx],dword 'HD?/' ; if hard disk |
mov [ecx+2],byte al |
mov [ecx+4],byte ah |
mov [ecx+5],dword '/KOL' |
mov [ecx+9],dword 'IBRI' |
mov [ecx+13],byte 0 |
.ok: |
.not_found_cd: |
ret |
endp |
proc load_file_parse_table |
stdcall kernel_alloc,0x1000 |
mov [tmp_file_name_table],eax |
mov edi,eax |
mov esi,sysdir_name |
mov ecx,128/4 |
rep movsd |
invoke ini.enum_keys,conf_fname,conf_path_sect,get_every_key |
mov eax,[tmp_file_name_table] |
mov [full_file_name_table],eax |
mov eax,[tmp_file_name_size] |
mov [full_file_name_table.size],eax |
ret |
endp |
uglobal |
def_val_1 db 0 |
endg |
proc get_every_key stdcall, f_name, sec_name, key_name |
mov esi, [key_name] |
mov ecx, esi |
cmp byte [esi], '/' |
jnz @f |
inc esi |
@@: |
mov edi, [tmp_file_name_size] |
shl edi, 7 |
cmp edi, 0x1000 |
jae .stop_parse |
add edi, [tmp_file_name_table] |
lea ebx, [edi+64] |
@@: |
cmp edi, ebx |
jae .skip_this_key |
lodsb |
test al, al |
jz @f |
or al, 20h |
stosb |
jmp @b |
@@: |
stosb |
invoke ini.get_str, [f_name],[sec_name],ecx,ebx,64,def_val_1 |
cmp byte [ebx], '/' |
jnz @f |
lea esi, [ebx+1] |
mov edi, ebx |
mov ecx, 63 |
rep movsb |
@@: |
push ebp |
mov ebp, [tmp_file_name_table] |
mov ecx, [tmp_file_name_size] |
jecxz .noreplace |
mov eax, ecx |
dec eax |
shl eax, 7 |
add ebp, eax |
.replace_loop: |
mov edi, ebx |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz .doreplace |
mov dl, [edi] |
inc edi |
test dl, dl |
jz .replace_loop_cont |
or dl, 20h |
cmp al, dl |
jz @b |
jmp .replace_loop_cont |
.doreplace: |
cmp byte [edi], 0 |
jz @f |
cmp byte [edi], '/' |
jnz .replace_loop_cont |
@@: |
lea esi, [ebp+64] |
call .replace |
jc .skip_this_key2 |
.replace_loop_cont: |
sub ebp, 128 |
loop .replace_loop |
.noreplace: |
pop ebp |
inc [tmp_file_name_size] |
.skip_this_key: |
xor eax, eax |
inc eax |
ret |
.skip_this_key2: |
pop ebp |
jmp .skip_this_key |
.stop_parse: |
xor eax, eax |
ret |
endp |
proc get_every_key.replace |
; in: ebx->destination, esi->first part of name, edi->second part of name |
; maximum length is 64 bytes |
; out: CF=1 <=> overflow |
; 1) allocate temporary buffer in stack |
sub esp, 64 |
; 2) save second part of name to temporary buffer |
push esi |
lea esi, [esp+4] ; esi->tmp buffer |
xchg esi, edi ; edi->tmp buffer, esi->source |
@@: |
lodsb |
stosb |
test al, al |
jnz @b |
; 3) copy first part of name to destination |
pop esi |
mov edi, ebx |
@@: |
lodsb |
test al, al |
jz @f |
stosb |
jmp @b |
@@: |
; 4) restore second part of name from temporary buffer to destination |
; (may cause overflow) |
lea edx, [ebx+64] ; limit of destination |
mov esi, esp |
@@: |
cmp edi, edx |
jae .overflow |
lodsb |
stosb |
test al, al |
jnz @b |
; all is OK |
add esp, 64 ; CF is cleared |
ret |
.overflow: |
; name is too long |
add esp, 64 |
stc |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;------------------------------------------------------------------------- |
; |
; File path partial substitution (according to configuration) |
; |
; |
; SPraid |
; |
;------------------------------------------------------------------------- |
$Revision$ |
iglobal |
; pointer to memory for path replace table, |
; size of one record is 128 bytes: 64 bytes for search pattern + 64 bytes for replace string |
; start with one entry: sys -> <sysdir> |
full_file_name_table dd sysdir_name |
.size dd 1 |
tmp_file_name_size dd 1 |
endg |
uglobal |
; Parser_params will initialize: sysdir_name = "sys", sysdir_path = <sysdir> |
sysdir_name rb 64 |
sysdir_path rb 64 |
tmp_file_name_table dd ? |
endg |
; use bx_from_load and init system directory /sys |
proc Parser_params |
locals |
buff db 4 dup(?) ; for test cd |
endl |
mov eax, [OS_BASE+0x10000+bx_from_load] |
mov ecx, sysdir_path |
mov [ecx-64], dword 'sys' |
cmp al, 'r'; if ram disk |
jnz @f |
mov [ecx], dword 'RD/?' |
mov [ecx+3], byte ah |
mov [ecx+4], byte 0 |
ret |
@@: |
cmp al, 'm'; if ram disk |
jnz @f |
mov [ecx], dword 'CD?/'; if cd disk {m} |
mov [ecx+4], byte '1' |
mov [ecx+5], dword '/KOL' |
mov [ecx+9], dword 'IBRI' |
mov [ecx+13], byte 0 |
.next_cd: |
mov [ecx+2], byte ah |
inc ah |
cmp ah, '5' |
je .not_found_cd |
lea edx, [buff] |
pushad |
stdcall read_file, read_firstapp, edx, 0, 4 |
popad |
cmp [edx], dword 'MENU' |
jne .next_cd |
jmp .ok |
@@: |
sub al, 49 |
mov [ecx], dword 'HD?/'; if hard disk |
mov [ecx+2], byte al |
mov [ecx+4], byte ah |
mov [ecx+5], dword '/KOL' |
mov [ecx+9], dword 'IBRI' |
mov [ecx+13], byte 0 |
.ok: |
.not_found_cd: |
ret |
endp |
proc load_file_parse_table |
stdcall kernel_alloc, 0x1000 |
mov [tmp_file_name_table], eax |
mov edi, eax |
mov esi, sysdir_name |
mov ecx, 128/4 |
rep movsd |
invoke ini.enum_keys, conf_fname, conf_path_sect, get_every_key |
mov eax, [tmp_file_name_table] |
mov [full_file_name_table], eax |
mov eax, [tmp_file_name_size] |
mov [full_file_name_table.size], eax |
ret |
endp |
uglobal |
def_val_1 db 0 |
endg |
proc get_every_key stdcall, f_name, sec_name, key_name |
mov esi, [key_name] |
mov ecx, esi |
cmp byte [esi], '/' |
jnz @f |
inc esi |
@@: |
mov edi, [tmp_file_name_size] |
shl edi, 7 |
cmp edi, 0x1000 |
jae .stop_parse |
add edi, [tmp_file_name_table] |
lea ebx, [edi+64] |
@@: |
cmp edi, ebx |
jae .skip_this_key |
lodsb |
test al, al |
jz @f |
or al, 20h |
stosb |
jmp @b |
@@: |
stosb |
invoke ini.get_str, [f_name], [sec_name], ecx, ebx, 64, def_val_1 |
cmp byte [ebx], '/' |
jnz @f |
lea esi, [ebx+1] |
mov edi, ebx |
mov ecx, 63 |
rep movsb |
@@: |
push ebp |
mov ebp, [tmp_file_name_table] |
mov ecx, [tmp_file_name_size] |
jecxz .noreplace |
mov eax, ecx |
dec eax |
shl eax, 7 |
add ebp, eax |
.replace_loop: |
mov edi, ebx |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz .doreplace |
mov dl, [edi] |
inc edi |
test dl, dl |
jz .replace_loop_cont |
or dl, 20h |
cmp al, dl |
jz @b |
jmp .replace_loop_cont |
.doreplace: |
cmp byte [edi], 0 |
jz @f |
cmp byte [edi], '/' |
jnz .replace_loop_cont |
@@: |
lea esi, [ebp+64] |
call .replace |
jc .skip_this_key2 |
.replace_loop_cont: |
sub ebp, 128 |
loop .replace_loop |
.noreplace: |
pop ebp |
inc [tmp_file_name_size] |
.skip_this_key: |
xor eax, eax |
inc eax |
ret |
.skip_this_key2: |
pop ebp |
jmp .skip_this_key |
.stop_parse: |
xor eax, eax |
ret |
endp |
proc get_every_key.replace |
; in: ebx->destination, esi->first part of name, edi->second part of name |
; maximum length is 64 bytes |
; out: CF=1 <=> overflow |
; 1) allocate temporary buffer in stack |
sub esp, 64 |
; 2) save second part of name to temporary buffer |
push esi |
lea esi, [esp+4] ; esi->tmp buffer |
xchg esi, edi ; edi->tmp buffer, esi->source |
@@: |
lodsb |
stosb |
test al, al |
jnz @b |
; 3) copy first part of name to destination |
pop esi |
mov edi, ebx |
@@: |
lodsb |
test al, al |
jz @f |
stosb |
jmp @b |
@@: |
; 4) restore second part of name from temporary buffer to destination |
; (may cause overflow) |
lea edx, [ebx+64] ; limit of destination |
mov esi, esp |
@@: |
cmp edi, edx |
jae .overflow |
lodsb |
stosb |
test al, al |
jnz @b |
; all is OK |
add esp, 64 ; CF is cleared |
ret |
.overflow: |
; name is too long |
add esp, 64 |
stc |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/fs/part_set.inc |
---|
1,531 → 1,534 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;************************************************************* |
;* 13.02.2010 Find all partition and check supported FS |
;* 12.07.2007 Check all 4 entry of MBR and EMBR |
;* 29.04.2006 Elimination of hangup after the |
;* expiration hd_wait_timeout - Mario79 |
;* 28.01.2006 find all Fat16/32 partition in all input point |
;* to MBR - Mario79 |
;************************************************************* |
uglobal |
align 4 |
;****************************************************** |
; Please do not change this place - variables in text |
; Mario79 |
; START place |
;****************************************************** |
PARTITION_START dd 0x3f |
PARTITION_END dd 0 |
fs_type db 0 ; 1=NTFS, 2=EXT2/3, 16=FAT16, 32=FAT32 |
align 4 |
fs_dependent_data_start: |
; FATxx data |
SECTORS_PER_FAT dd 0x1f3a |
NUMBER_OF_FATS dd 0x2 |
SECTORS_PER_CLUSTER dd 0x8 |
BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes |
ROOT_CLUSTER dd 2 ; first rootdir cluster |
FAT_START dd 0 ; start of fat table |
ROOT_START dd 0 ; start of rootdir (only fat16) |
ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16) |
DATA_START dd 0 ; start of data area (=first cluster 2) |
LAST_CLUSTER dd 0 ; last availabe cluster |
ADR_FSINFO dd 0 ; used only by fat32 |
fatRESERVED dd 0x0FFFFFF6 |
fatBAD dd 0x0FFFFFF7 |
fatEND dd 0x0FFFFFF8 |
fatMASK dd 0x0FFFFFFF |
fatStartScan dd 2 |
fs_dependent_data_end: |
file_system_data_size = $ - PARTITION_START |
if file_system_data_size > 96 |
ERROR: sizeof(file system data) too big! |
end if |
virtual at fs_dependent_data_start |
; NTFS data |
ntfs_data: |
.sectors_per_cluster dd ? |
.mft_cluster dd ? |
.mftmirr_cluster dd ? |
.frs_size dd ? ; FRS size in bytes |
.iab_size dd ? ; IndexAllocationBuffer size in bytes |
.frs_buffer dd ? |
.iab_buffer dd ? |
.mft_retrieval dd ? |
.mft_retrieval_size dd ? |
.mft_retrieval_alloc dd ? |
.mft_retrieval_end dd ? |
.cur_index_size dd ? |
.cur_index_buf dd ? |
if $ > fs_dependent_data_end |
ERROR: increase sizeof(fs_dependent_data)! |
end if |
end virtual |
virtual at fs_dependent_data_start |
; EXT2 data |
ext2_data: |
.log_block_size dd ? |
.block_size dd ? |
.count_block_in_block dd ? |
.blocks_per_group dd ? |
.inodes_per_group dd ? |
.global_desc_table dd ? |
.root_inode dd ? ; pointer to root inode in memory |
.inode_size dd ? |
.count_pointer_in_block dd ? ; block_size / 4 |
.count_pointer_in_block_square dd ? ; (block_size / 4)**2 |
.ext2_save_block dd ? ; ¡«®ª £«®¡ «ìãî 1 ¯à®æ¥¤ãàã |
.ext2_temp_block dd ? ; ¡«®ª ¤«ï ¬¥«ª¨å ¯à®æ¥¤ãà |
.ext2_save_inode dd ? ; inode £«®¡ «ìãî ¯à®æ¥¤ãàã |
;* 13.02.2010 Find all partition and check supported FS |
;* 12.07.2007 Check all 4 entry of MBR and EMBR |
;* 29.04.2006 Elimination of hangup after the |
;* expiration hd_wait_timeout - Mario79 |
;* 28.01.2006 find all Fat16/32 partition in all input point |
;* to MBR - Mario79 |
;************************************************************* |
uglobal |
align 4 |
;****************************************************** |
; Please do not change this place - variables in text |
; Mario79 |
; START place |
;****************************************************** |
PARTITION_START dd 0x3f |
PARTITION_END dd 0 |
fs_type db 0 ; 1=NTFS, 2=EXT2/3, 16=FAT16, 32=FAT32 |
align 4 |
fs_dependent_data_start: |
; FATxx data |
SECTORS_PER_FAT dd 0x1f3a |
NUMBER_OF_FATS dd 0x2 |
SECTORS_PER_CLUSTER dd 0x8 |
BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes |
ROOT_CLUSTER dd 2 ; first rootdir cluster |
FAT_START dd 0 ; start of fat table |
ROOT_START dd 0 ; start of rootdir (only fat16) |
ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16) |
DATA_START dd 0 ; start of data area (=first cluster 2) |
LAST_CLUSTER dd 0 ; last availabe cluster |
ADR_FSINFO dd 0 ; used only by fat32 |
fatRESERVED dd 0x0FFFFFF6 |
fatBAD dd 0x0FFFFFF7 |
fatEND dd 0x0FFFFFF8 |
fatMASK dd 0x0FFFFFFF |
fatStartScan dd 2 |
fs_dependent_data_end: |
file_system_data_size = $ - PARTITION_START |
if file_system_data_size > 96 |
ERROR: |
sizeof(file system data) too big! |
end if |
virtual at fs_dependent_data_start |
; NTFS data |
ntfs_data: |
.sectors_per_cluster dd ? |
.mft_cluster dd ? |
.mftmirr_cluster dd ? |
.frs_size dd ? ; FRS size in bytes |
.iab_size dd ? ; IndexAllocationBuffer size in bytes |
.frs_buffer dd ? |
.iab_buffer dd ? |
.mft_retrieval dd ? |
.mft_retrieval_size dd ? |
.mft_retrieval_alloc dd ? |
.mft_retrieval_end dd ? |
.cur_index_size dd ? |
.cur_index_buf dd ? |
if $ > fs_dependent_data_end |
ERROR: |
increase sizeof(fs_dependent_data)! |
end if |
end virtual |
virtual at fs_dependent_data_start |
; EXT2 data |
ext2_data: |
.log_block_size dd ? |
.block_size dd ? |
.count_block_in_block dd ? |
.blocks_per_group dd ? |
.inodes_per_group dd ? |
.global_desc_table dd ? |
.root_inode dd ? ; pointer to root inode in memory |
.inode_size dd ? |
.count_pointer_in_block dd ? ; block_size / 4 |
.count_pointer_in_block_square dd ? ; (block_size / 4)**2 |
.ext2_save_block dd ? ; ¡«®ª £«®¡ «ìãî 1 ¯à®æ¥¤ãàã |
.ext2_temp_block dd ? ; ¡«®ª ¤«ï ¬¥«ª¨å ¯à®æ¥¤ãà |
.ext2_save_inode dd ? ; inode £«®¡ «ìãî ¯à®æ¥¤ãàã |
.ext2_temp_inode dd ? ; inode ¤«ï ¬¥«ª¨å ¯à®æ¥¤ãà |
.sb dd ? ; superblock |
.groups_count dd ? |
if $ > fs_dependent_data_end |
ERROR: increase sizeof(fs_dependent_data)! |
end if |
end virtual |
;*************************************************************************** |
; End place |
; Mario79 |
;*************************************************************************** |
endg |
iglobal |
partition_types: ; list of fat16/32 partitions |
db 0x04 ; DOS: fat16 <32M |
db 0x06 ; DOS: fat16 >32M |
db 0x0b ; WIN95: fat32 |
db 0x0c ; WIN95: fat32, LBA-mapped |
db 0x0e ; WIN95: fat16, LBA-mapped |
db 0x14 ; Hidden DOS: fat16 <32M |
db 0x16 ; Hidden DOS: fat16 >32M |
db 0x1b ; Hidden WIN95: fat32 |
db 0x1c ; Hidden WIN95: fat32, LBA-mapped |
db 0x1e ; Hidden WIN95: fat16, LBA-mapped |
db 0xc4 ; DRDOS/secured: fat16 <32M |
db 0xc6 ; DRDOS/secured: fat16 >32M |
db 0xcb ; DRDOS/secured: fat32 |
db 0xcc ; DRDOS/secured: fat32, LBA-mapped |
db 0xce ; DRDOS/secured: fat16, LBA-mapped |
db 0xd4 ; Old Multiuser DOS secured: fat16 <32M |
db 0xd6 ; Old Multiuser DOS secured: fat16 >32M |
db 0x07 ; NTFS |
db 0x27 ; NTFS, hidden |
db 0x83 ; Linux native file system (ext2fs) |
partition_types_end: |
extended_types: ; list of extended partitions |
db 0x05 ; DOS: extended partition |
db 0x0f ; WIN95: extended partition, LBA-mapped |
db 0xc5 ; DRDOS/secured: extended partition |
db 0xd5 ; Old Multiuser DOS secured: extended partition |
extended_types_end: |
endg |
; Partition chain used: |
; MBR <--------------------- |
; | | |
; |-> PARTITION1 | |
; |-> EXTENDED PARTITION - ;not need be second partition |
; |-> PARTITION3 |
; |-> PARTITION4 |
set_PARTITION_variables: |
set_FAT32_variables: ;deprecated |
and [problem_partition], 0 |
call reserve_hd1 |
call reserve_hd_channel |
pushad |
cmp dword [hdpos],0 |
je problem_hd |
xor ecx,ecx ; partition count |
;or edx,-1 ; flag for partition |
xor eax,eax ; address MBR |
xor ebp,ebp ; extended partition start |
new_mbr: |
test ebp,ebp ; is there extended partition? (MBR or EMBR) |
jnz extended_already_set ; yes |
xchg ebp,eax ; no. set it now |
extended_already_set: |
add eax,ebp ; mbr=mbr+0, ext_part=ext_start+relat_start |
mov ebx,buffer |
call hd_read |
cmp [hd_error],0 |
jne problem_hd |
cmp word [ebx+0x1fe],0xaa55 ; is it valid boot sector? |
jnz end_partition_chain |
push eax ; push only one time |
cmp dword [ebx+0x1be+0xc],0 ; skip over empty partition |
jnz test_primary_partition_0 |
cmp dword [ebx+0x1be+0xc+16],0 |
jnz test_primary_partition_1 |
cmp dword [ebx+0x1be+0xc+16+16],0 |
jnz test_primary_partition_2 |
cmp dword [ebx+0x1be+0xc+16+16+16],0 |
jnz test_primary_partition_3 |
pop eax |
jmp end_partition_chain |
test_primary_partition_0: |
mov al,[ebx+0x1be+4] ; get primary partition type |
call scan_partition_types |
jnz test_primary_partition_1 ; no. skip over |
inc ecx |
cmp ecx,[known_part] ; is it wanted partition? |
jnz test_primary_partition_1 ; no |
.groups_count dd ? |
if $ > fs_dependent_data_end |
ERROR: |
increase sizeof(fs_dependent_data)! |
end if |
end virtual |
pop eax |
;mov edx, eax ; start sector |
;*************************************************************************** |
; End place |
; Mario79 |
;*************************************************************************** |
endg |
iglobal |
partition_types: ; list of fat16/32 partitions |
db 0x04 ; DOS: fat16 <32M |
db 0x06 ; DOS: fat16 >32M |
db 0x0b ; WIN95: fat32 |
db 0x0c ; WIN95: fat32, LBA-mapped |
db 0x0e ; WIN95: fat16, LBA-mapped |
db 0x14 ; Hidden DOS: fat16 <32M |
db 0x16 ; Hidden DOS: fat16 >32M |
db 0x1b ; Hidden WIN95: fat32 |
db 0x1c ; Hidden WIN95: fat32, LBA-mapped |
db 0x1e ; Hidden WIN95: fat16, LBA-mapped |
db 0xc4 ; DRDOS/secured: fat16 <32M |
db 0xc6 ; DRDOS/secured: fat16 >32M |
db 0xcb ; DRDOS/secured: fat32 |
db 0xcc ; DRDOS/secured: fat32, LBA-mapped |
db 0xce ; DRDOS/secured: fat16, LBA-mapped |
db 0xd4 ; Old Multiuser DOS secured: fat16 <32M |
db 0xd6 ; Old Multiuser DOS secured: fat16 >32M |
db 0x07 ; NTFS |
db 0x27 ; NTFS, hidden |
db 0x83 ; Linux native file system (ext2fs) |
partition_types_end: |
extended_types: ; list of extended partitions |
db 0x05 ; DOS: extended partition |
db 0x0f ; WIN95: extended partition, LBA-mapped |
db 0xc5 ; DRDOS/secured: extended partition |
db 0xd5 ; Old Multiuser DOS secured: extended partition |
extended_types_end: |
endg |
; Partition chain used: |
; MBR <--------------------- |
; | | |
; |-> PARTITION1 | |
; |-> EXTENDED PARTITION - ;not need be second partition |
; |-> PARTITION3 |
; |-> PARTITION4 |
set_PARTITION_variables: |
set_FAT32_variables: ;deprecated |
and [problem_partition], 0 |
call reserve_hd1 |
call reserve_hd_channel |
pushad |
cmp dword [hdpos], 0 |
je problem_hd |
xor ecx, ecx ; partition count |
;or edx,-1 ; flag for partition |
xor eax, eax ; address MBR |
xor ebp, ebp ; extended partition start |
new_mbr: |
test ebp, ebp ; is there extended partition? (MBR or EMBR) |
jnz extended_already_set; yes |
xchg ebp, eax ; no. set it now |
extended_already_set: |
add eax, ebp ; mbr=mbr+0, ext_part=ext_start+relat_start |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jne problem_hd |
cmp word [ebx+0x1fe], 0xaa55; is it valid boot sector? |
jnz end_partition_chain |
push eax ; push only one time |
cmp dword [ebx+0x1be+0xc], 0; skip over empty partition |
jnz test_primary_partition_0 |
cmp dword [ebx+0x1be+0xc+16], 0 |
jnz test_primary_partition_1 |
cmp dword [ebx+0x1be+0xc+16+16], 0 |
jnz test_primary_partition_2 |
cmp dword [ebx+0x1be+0xc+16+16+16], 0 |
jnz test_primary_partition_3 |
pop eax |
jmp end_partition_chain |
test_primary_partition_0: |
mov al, [ebx+0x1be+4]; get primary partition type |
call scan_partition_types |
jnz test_primary_partition_1; no. skip over |
inc ecx |
cmp ecx, [known_part]; is it wanted partition? |
jnz test_primary_partition_1; no |
pop eax |
;mov edx, eax ; start sector |
add eax, [ebx+0x1be+8] ; add relative start |
;mov [PARTITON_START],edx |
;mov [PARTITON_START],edx |
;push edx |
mov edx, [ebx+0x1be+12] ; length |
;add edx, eax ; add length |
;dec edx ; PARTITION_END is inclusive |
;mov [PARTITION_END], edx ; note that this can be changed |
; when file system data will be available |
mov cl, [ebx+0x1be+4] ; fs_type |
;mov [fs_type], dl ; save for FS recognizer (separate FAT vs NTFS) |
mov edx, [ebx+0x1be+12] ; length |
;add edx, eax ; add length |
;dec edx ; PARTITION_END is inclusive |
;mov [PARTITION_END], edx ; note that this can be changed |
; when file system data will be available |
mov cl, [ebx+0x1be+4] ; fs_type |
;mov [fs_type], dl ; save for FS recognizer (separate FAT vs NTFS) |
;pop edx |
jmp hd_and_partition_ok |
test_primary_partition_1: |
mov al,[ebx+0x1be+4+16] ; get primary partition type |
call scan_partition_types |
jnz test_primary_partition_2 ; no. skip over |
inc ecx |
cmp ecx,[known_part] ; is it wanted partition? |
jnz test_primary_partition_2 ; no |
jmp hd_and_partition_ok |
test_primary_partition_1: |
mov al, [ebx+0x1be+4+16]; get primary partition type |
call scan_partition_types |
jnz test_primary_partition_2 ; no. skip over |
inc ecx |
cmp ecx, [known_part]; is it wanted partition? |
jnz test_primary_partition_2 ; no |
pop eax |
add eax, [ebx+0x1be+8+16] |
mov edx, [ebx+0x1be+12+16] |
mov cl, [ebx+0x1be+4+16] |
jmp hd_and_partition_ok |
;mov edx, eax |
;add edx, [ebx+0x1be+8+16] |
;push edx |
;add edx, [ebx+0x1be+12+16] |
;dec edx |
;mov [PARTITION_END], edx |
;mov al, [ebx+0x1be+4+16] |
;mov [fs_type], dl |
;pop edx |
test_primary_partition_2: |
mov al,[ebx+0x1be+4+16+16] ; get primary partition type |
call scan_partition_types |
jnz test_primary_partition_3 ; no. skip over |
inc ecx |
cmp ecx,[known_part] ; is it wanted partition? |
jnz test_primary_partition_3 ; no |
;mov edx, eax |
;add edx, [ebx+0x1be+8+16] |
;push edx |
;add edx, [ebx+0x1be+12+16] |
;dec edx |
;mov [PARTITION_END], edx |
;mov al, [ebx+0x1be+4+16] |
;mov [fs_type], dl |
;pop edx |
test_primary_partition_2: |
mov al, [ebx+0x1be+4+16+16]; get primary partition type |
call scan_partition_types |
jnz test_primary_partition_3 ; no. skip over |
inc ecx |
cmp ecx, [known_part]; is it wanted partition? |
jnz test_primary_partition_3 ; no |
pop eax |
add eax, [ebx+0x1be+8+16+16] |
mov edx, [ebx+0x1be+12+16+16] |
mov cl, [ebx+0x1be+4+16+16] |
jmp hd_and_partition_ok |
;mov edx, eax |
;add edx, [ebx+0x1be+8+16+16] |
;push edx |
;add edx, [ebx+0x1be+12+16+16] |
;dec edx |
;mov [PARTITION_END], edx |
;mov al, [ebx+0x1be+4+16+16] |
;mov [fs_type], dl |
;pop edx |
test_primary_partition_3: |
mov al,[ebx+0x1be+4+16+16+16] ; get primary partition type |
call scan_partition_types |
jnz test_ext_partition_0 ; no. skip over |
inc ecx |
cmp ecx,[known_part] ; is it wanted partition? |
jnz test_ext_partition_0 ; no |
jmp hd_and_partition_ok |
;mov edx, eax |
;add edx, [ebx+0x1be+8+16+16] |
;push edx |
;add edx, [ebx+0x1be+12+16+16] |
;dec edx |
;mov [PARTITION_END], edx |
;mov al, [ebx+0x1be+4+16+16] |
;mov [fs_type], dl |
;pop edx |
test_primary_partition_3: |
mov al, [ebx+0x1be+4+16+16+16]; get primary partition type |
call scan_partition_types |
jnz test_ext_partition_0 ; no. skip over |
inc ecx |
cmp ecx, [known_part]; is it wanted partition? |
jnz test_ext_partition_0; no |
pop eax |
add eax, [ebx+0x1be+8+16+16+16] |
mov edx, [ebx+0x1be+12+16+16+16] |
mov cl, [ebx+0x1be+4+16+16+16] |
jmp hd_and_partition_ok |
;mov edx, eax |
;add edx, [ebx+0x1be+8+16+16+16] |
;push edx |
;add edx, [ebx+0x1be+12+16+16+16] |
;dec edx |
;mov [PARTITION_END], edx |
;mov al, [ebx+0x1be+4+16+16+16] |
;mov [fs_type], dl |
;pop edx |
;mov edx, eax |
;add edx, [ebx+0x1be+8+16+16+16] |
;push edx |
;add edx, [ebx+0x1be+12+16+16+16] |
;dec edx |
;mov [PARTITION_END], edx |
;mov al, [ebx+0x1be+4+16+16+16] |
;mov [fs_type], dl |
;pop edx |
test_ext_partition_0: |
pop eax ; ¯à®áâ® ¢ëª¨¤ë¢ ¥¬ ¨§ á⥪ |
mov al,[ebx+0x1be+4] ; get extended partition type |
call scan_extended_types |
jnz test_ext_partition_1 |
mov eax,[ebx+0x1be+8] ; add relative start |
test eax,eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
test_ext_partition_1: |
mov al,[ebx+0x1be+4+16] ; get extended partition type |
call scan_extended_types |
jnz test_ext_partition_2 |
mov eax,[ebx+0x1be+8+16] ; add relative start |
test eax,eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
test_ext_partition_2: |
mov al,[ebx+0x1be+4+16+16] ; get extended partition type |
call scan_extended_types |
jnz test_ext_partition_3 |
mov eax,[ebx+0x1be+8+16+16] ; add relative start |
test eax,eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
test_ext_partition_3: |
mov al,[ebx+0x1be+4+16+16+16] ; get extended partition type |
call scan_extended_types |
jnz end_partition_chain ; no. end chain |
mov eax,[ebx+0x1be+8+16+16+16] ; get start of extended partition |
test eax,eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
end_partition_chain: |
;mov [partition_count],ecx |
;cmp edx,-1 ; found wanted partition? |
;jnz hd_and_partition_ok ; yes. install it |
pop eax ; ¯à®áâ® ¢ëª¨¤ë¢ ¥¬ ¨§ á⥪ |
mov al, [ebx+0x1be+4]; get extended partition type |
call scan_extended_types |
jnz test_ext_partition_1 |
mov eax, [ebx+0x1be+8]; add relative start |
test eax, eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
test_ext_partition_1: |
mov al, [ebx+0x1be+4+16]; get extended partition type |
call scan_extended_types |
jnz test_ext_partition_2 |
mov eax, [ebx+0x1be+8+16]; add relative start |
test eax, eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
test_ext_partition_2: |
mov al, [ebx+0x1be+4+16+16]; get extended partition type |
call scan_extended_types |
jnz test_ext_partition_3 |
mov eax, [ebx+0x1be+8+16+16]; add relative start |
test eax, eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
test_ext_partition_3: |
mov al, [ebx+0x1be+4+16+16+16]; get extended partition type |
call scan_extended_types |
jnz end_partition_chain; no. end chain |
mov eax, [ebx+0x1be+8+16+16+16]; get start of extended partition |
test eax, eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
end_partition_chain: |
;mov [partition_count],ecx |
;cmp edx,-1 ; found wanted partition? |
;jnz hd_and_partition_ok ; yes. install it |
;jmp problem_partition_or_fat |
problem_hd: |
or [problem_partition], 2 |
jmp return_from_part_set |
scan_partition_types: |
push ecx |
mov edi,partition_types |
mov ecx,partition_types_end-partition_types |
cld |
repne scasb ; is partition type ok? |
pop ecx |
ret |
scan_extended_types: |
push ecx |
mov edi,extended_types |
mov ecx,extended_types_end-extended_types |
cld |
repne scasb ; is it extended partition? |
pop ecx |
ret |
problem_fat_dec_count: ; bootsector is missing or another problem |
; dec [partition_count] ; remove it from partition_count |
problem_partition_or_fat: |
or [problem_partition],1 |
or [problem_partition], 2 |
jmp return_from_part_set |
return_from_part_set: |
popad |
;mov [fs_type],0 |
call free_hd_channel |
mov [hd1_status],0 ; free |
ret |
scan_partition_types: |
push ecx |
mov edi, partition_types |
mov ecx, partition_types_end-partition_types |
cld |
repne scasb ; is partition type ok? |
pop ecx |
ret |
scan_extended_types: |
push ecx |
mov edi, extended_types |
mov ecx, extended_types_end-extended_types |
cld |
repne scasb ; is it extended partition? |
pop ecx |
ret |
problem_fat_dec_count: ; bootsector is missing or another problem |
; dec [partition_count] ; remove it from partition_count |
problem_partition_or_fat: |
or [problem_partition], 1 |
return_from_part_set: |
popad |
;mov [fs_type],0 |
call free_hd_channel |
mov [hd1_status], 0 ; free |
ret |
hd_and_partition_ok: |
;eax = PARTITION_START edx=PARTITION_LENGTH cl=fs_type |
mov [fs_type], cl |
;mov eax,edx |
mov [PARTITION_START],eax |
add edx, eax |
dec edx |
mov [PARTITION_END], edx |
; mov edx, [PARTITION_END] |
; sub edx, eax |
; inc edx ; edx = length of partition § 祬 ®® ¬?? |
; mov [hd_setup],1 |
mov ebx,buffer |
call hd_read ; read boot sector of partition |
cmp [hd_error], 0 |
jz boot_read_ok |
cmp [fs_type], 7 |
jnz problem_fat_dec_count |
; NTFS duplicates bootsector: |
; NT4/2k/XP+ saves bootsector copy in the end of disk |
; NT 3.51 saves bootsector copy in the middle of disk |
and [hd_error], 0 |
mov eax, [PARTITION_END] |
call hd_read |
cmp [hd_error], 0 |
jnz @f |
call ntfs_test_bootsec |
jnc boot_read_ok |
@@: |
and [hd_error], 0 |
mov eax, edx |
shr eax, 1 |
add eax, [PARTITION_START] |
call hd_read |
cmp [hd_error], 0 |
jnz problem_fat_dec_count ; no chance... |
boot_read_ok: |
; if we are running on NTFS, check bootsector |
call ntfs_test_bootsec ; test ntfs |
jnc ntfs_setup |
call ext2_test_superblock ; test ext2fs |
jnc ext2_setup |
mov eax, [PARTITION_START] ;ext2 test changes [buffer] |
call hd_read |
cmp [hd_error], 0 |
jnz problem_fat_dec_count |
cmp word [ebx+0x1fe],0xaa55 ; is it valid boot sector? |
jnz problem_fat_dec_count |
movzx eax,word [ebx+0xe] ; sectors reserved |
add eax,[PARTITION_START] |
mov [FAT_START],eax ; fat_start = partition_start + reserved |
movzx eax,byte [ebx+0xd] ; sectors per cluster |
test eax,eax |
jz problem_fat_dec_count |
mov [SECTORS_PER_CLUSTER],eax |
movzx ecx,word [ebx+0xb] ; bytes per sector |
cmp ecx,0x200 |
jnz problem_fat_dec_count |
mov [BYTES_PER_SECTOR],ecx |
movzx eax,word [ebx+0x11] ; count of rootdir entries (=0 fat32) |
mov edx,32 |
mul edx |
dec ecx |
add eax,ecx ; round up if not equal count |
inc ecx ; bytes per sector |
div ecx |
mov [ROOT_SECTORS],eax ; count of rootdir sectors |
movzx eax,word [ebx+0x16] ; sectors per fat <65536 |
test eax,eax |
jnz fat16_fatsize |
mov eax,[ebx+0x24] ; sectors per fat |
fat16_fatsize: |
mov [SECTORS_PER_FAT],eax |
movzx eax,byte [ebx+0x10] ; number of fats |
test eax,eax ; if 0 it's not fat partition |
jz problem_fat_dec_count |
mov [NUMBER_OF_FATS],eax |
imul eax,[SECTORS_PER_FAT] |
add eax,[FAT_START] |
mov [ROOT_START],eax ; rootdir = fat_start + fat_size * fat_count |
add eax,[ROOT_SECTORS] ; rootdir sectors should be 0 on fat32 |
mov [DATA_START],eax ; data area = rootdir + rootdir_size |
movzx eax,word [ebx+0x13] ; total sector count <65536 |
test eax,eax |
jnz fat16_total |
mov eax,[ebx+0x20] ; total sector count |
fat16_total: |
add eax,[PARTITION_START] |
dec eax |
mov [PARTITION_END],eax |
inc eax |
sub eax,[DATA_START] ; eax = count of data sectors |
xor edx,edx |
div dword [SECTORS_PER_CLUSTER] |
inc eax |
mov [LAST_CLUSTER],eax |
dec eax ; cluster count |
mov [fatStartScan],2 |
; limits by Microsoft Hardware White Paper v1.03 |
cmp eax,4085 ; 0xff5 |
jb problem_fat_dec_count ; fat12 not supported |
cmp eax,65525 ; 0xfff5 |
jb fat16_partition |
fat32_partition: |
mov eax,[ebx+0x2c] ; rootdir cluster |
mov [ROOT_CLUSTER],eax |
movzx eax,word [ebx+0x30] ; fs info sector |
add eax,[PARTITION_START] |
mov [ADR_FSINFO],eax |
call hd_read |
mov eax,[ebx+0x1ec] |
cmp eax,-1 |
jz @f |
mov [fatStartScan],eax |
@@: |
popad |
mov [fatRESERVED],0x0FFFFFF6 |
mov [fatBAD],0x0FFFFFF7 |
mov [fatEND],0x0FFFFFF8 |
mov [fatMASK],0x0FFFFFFF |
mov [fs_type],32 ; Fat32 |
call free_hd_channel |
mov [hd1_status],0 ; free |
ret |
fat16_partition: |
xor eax,eax |
mov [ROOT_CLUSTER],eax |
popad |
mov [fatRESERVED],0x0000FFF6 |
mov [fatBAD],0x0000FFF7 |
mov [fatEND],0x0000FFF8 |
mov [fatMASK],0x0000FFFF |
mov [fs_type],16 ; Fat16 |
call free_hd_channel |
mov [hd1_status],0 ; free |
ret |
mov [fs_type], cl |
;mov eax,edx |
mov [PARTITION_START], eax |
add edx, eax |
dec edx |
mov [PARTITION_END], edx |
; mov edx, [PARTITION_END] |
; sub edx, eax |
; inc edx ; edx = length of partition § 祬 ®® ¬?? |
; mov [hd_setup],1 |
mov ebx, buffer |
call hd_read ; read boot sector of partition |
cmp [hd_error], 0 |
jz boot_read_ok |
cmp [fs_type], 7 |
jnz problem_fat_dec_count |
; NTFS duplicates bootsector: |
; NT4/2k/XP+ saves bootsector copy in the end of disk |
; NT 3.51 saves bootsector copy in the middle of disk |
and [hd_error], 0 |
mov eax, [PARTITION_END] |
call hd_read |
cmp [hd_error], 0 |
jnz @f |
call ntfs_test_bootsec |
jnc boot_read_ok |
@@: |
and [hd_error], 0 |
mov eax, edx |
shr eax, 1 |
add eax, [PARTITION_START] |
call hd_read |
cmp [hd_error], 0 |
jnz problem_fat_dec_count ; no chance... |
boot_read_ok: |
; if we are running on NTFS, check bootsector |
call ntfs_test_bootsec ; test ntfs |
jnc ntfs_setup |
call ext2_test_superblock ; test ext2fs |
jnc ext2_setup |
mov eax, [PARTITION_START] ;ext2 test changes [buffer] |
call hd_read |
cmp [hd_error], 0 |
jnz problem_fat_dec_count |
cmp word [ebx+0x1fe], 0xaa55; is it valid boot sector? |
jnz problem_fat_dec_count |
movzx eax, word [ebx+0xe]; sectors reserved |
add eax, [PARTITION_START] |
mov [FAT_START], eax; fat_start = partition_start + reserved |
movzx eax, byte [ebx+0xd]; sectors per cluster |
test eax, eax |
jz problem_fat_dec_count |
mov [SECTORS_PER_CLUSTER], eax |
movzx ecx, word [ebx+0xb]; bytes per sector |
cmp ecx, 0x200 |
jnz problem_fat_dec_count |
mov [BYTES_PER_SECTOR], ecx |
movzx eax, word [ebx+0x11]; count of rootdir entries (=0 fat32) |
mov edx, 32 |
mul edx |
dec ecx |
add eax, ecx ; round up if not equal count |
inc ecx ; bytes per sector |
div ecx |
mov [ROOT_SECTORS], eax; count of rootdir sectors |
movzx eax, word [ebx+0x16]; sectors per fat <65536 |
test eax, eax |
jnz fat16_fatsize |
mov eax, [ebx+0x24] ; sectors per fat |
fat16_fatsize: |
mov [SECTORS_PER_FAT], eax |
movzx eax, byte [ebx+0x10]; number of fats |
test eax, eax ; if 0 it's not fat partition |
jz problem_fat_dec_count |
mov [NUMBER_OF_FATS], eax |
imul eax, [SECTORS_PER_FAT] |
add eax, [FAT_START] |
mov [ROOT_START], eax; rootdir = fat_start + fat_size * fat_count |
add eax, [ROOT_SECTORS]; rootdir sectors should be 0 on fat32 |
mov [DATA_START], eax; data area = rootdir + rootdir_size |
movzx eax, word [ebx+0x13]; total sector count <65536 |
test eax, eax |
jnz fat16_total |
mov eax, [ebx+0x20] ; total sector count |
fat16_total: |
add eax, [PARTITION_START] |
dec eax |
mov [PARTITION_END], eax |
inc eax |
sub eax, [DATA_START]; eax = count of data sectors |
xor edx, edx |
div dword [SECTORS_PER_CLUSTER] |
inc eax |
mov [LAST_CLUSTER], eax |
dec eax ; cluster count |
mov [fatStartScan], 2 |
; limits by Microsoft Hardware White Paper v1.03 |
cmp eax, 4085 ; 0xff5 |
jb problem_fat_dec_count; fat12 not supported |
cmp eax, 65525 ; 0xfff5 |
jb fat16_partition |
fat32_partition: |
mov eax, [ebx+0x2c] ; rootdir cluster |
mov [ROOT_CLUSTER], eax |
movzx eax, word [ebx+0x30]; fs info sector |
add eax, [PARTITION_START] |
mov [ADR_FSINFO], eax |
call hd_read |
mov eax, [ebx+0x1ec] |
cmp eax, -1 |
jz @f |
mov [fatStartScan], eax |
@@: |
popad |
mov [fatRESERVED], 0x0FFFFFF6 |
mov [fatBAD], 0x0FFFFFF7 |
mov [fatEND], 0x0FFFFFF8 |
mov [fatMASK], 0x0FFFFFFF |
mov [fs_type], 32 ; Fat32 |
call free_hd_channel |
mov [hd1_status], 0 ; free |
ret |
fat16_partition: |
xor eax, eax |
mov [ROOT_CLUSTER], eax |
popad |
mov [fatRESERVED], 0x0000FFF6 |
mov [fatBAD], 0x0000FFF7 |
mov [fatEND], 0x0000FFF8 |
mov [fatMASK], 0x0000FFFF |
mov [fs_type], 16 ; Fat16 |
call free_hd_channel |
mov [hd1_status], 0 ; free |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/gui/button.inc |
---|
131,7 → 131,8 |
call button._.incecx2 |
; set button height counter |
@@: mov edx, edi |
@@: |
mov edx, edi |
.next_line: |
call button._.button_dececx |
380,14 → 381,17 |
sub cl, 0x20 |
jnc @f |
xor cl, cl |
@@: sub ch, 0x20 |
@@: |
sub ch, 0x20 |
jnc @f |
xor ch, ch |
@@: rol ecx, 16 |
@@: |
rol ecx, 16 |
sub cl, 0x20 |
jnc @f |
xor cl, cl |
@@: rol ecx, 16 |
@@: |
rol ecx, 16 |
ret |
;------------------------------------------------------------------------------ |
398,14 → 402,17 |
add cl, 0x20 |
jnc @f |
or cl, -1 |
@@: add ch, 0x20 |
@@: |
add ch, 0x20 |
jnc @f |
or ch, -1 |
@@: rol ecx, 16 |
@@: |
rol ecx, 16 |
add cl, 0x20 |
jnc @f |
or cl, -1 |
@@: rol ecx, 16 |
@@: |
rol ecx, 16 |
ret |
;------------------------------------------------------------------------------ |
416,14 → 423,17 |
add cl, 0x14 |
jnc @f |
or cl, -1 |
@@: add ch, 0x14 |
@@: |
add ch, 0x14 |
jnc @f |
or ch, -1 |
@@: rol ecx, 16 |
@@: |
rol ecx, 16 |
add cl, 0x14 |
jnc @f |
or cl, -1 |
@@: rol ecx, 16 |
@@: |
rol ecx, 16 |
ret |
;------------------------------------------------------------------------------ |
440,17 → 450,21 |
jg @f |
mov al, 2 |
@@: sub cl, al |
@@: |
sub cl, al |
jnc @f |
xor cl, cl |
@@: sub ch, al |
@@: |
sub ch, al |
jnc @f |
xor ch, ch |
@@: rol ecx, 16 |
@@: |
rol ecx, 16 |
sub cl, al |
jnc @f |
xor cl, cl |
@@: rol ecx, 16 |
@@: |
rol ecx, 16 |
pop eax |
/kernel/trunk/gui/event.inc |
---|
1,497 → 1,510 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
WINDOW_MOVE_AND_RESIZE_FLAGS = \ |
mouse.WINDOW_RESIZE_N_FLAG + \ |
mouse.WINDOW_RESIZE_W_FLAG + \ |
mouse.WINDOW_RESIZE_S_FLAG + \ |
mouse.WINDOW_RESIZE_E_FLAG + \ |
mouse.WINDOW_MOVE_FLAG |
uglobal |
align 4 |
event_start dd ? |
event_end dd ? |
event_uid dd 0 |
endg |
EV_SPACE = 512 |
FreeEvents = event_start-EVENT.fd ; "âèðòóàëüíûé" event, èñïîëüçóþòñÿ òîëüêî ïîëÿ: |
; FreeEvents.fd=event_start è FreeEvents.bk=event_end |
align 4 |
init_events: ;; used from kernel.asm |
stdcall kernel_alloc,EV_SPACE*EVENT.size |
or eax,eax |
jz .fail |
; eax - current event, ebx - previos event below |
mov ecx,EV_SPACE ; current - in allocated space |
mov ebx,FreeEvents ; previos - íà÷àëî ñïèñêà |
push ebx ; îíî æå è êîíåö ïîòîì áóäåò |
@@: mov [ebx+EVENT.fd],eax |
mov [eax+EVENT.bk],ebx |
mov ebx,eax ; previos <- current |
add eax,EVENT.size ; new current |
loop @b |
pop eax ; âîò îíî êîíöîì è ñòàëî |
mov [ebx+EVENT.fd],eax |
mov [eax+EVENT.bk],ebx |
.fail: ret |
EVENT_WATCHED equ 0x10000000 ;áèò 28 |
EVENT_SIGNALED equ 0x20000000 ;áèò 29 |
MANUAL_RESET equ 0x40000000 ;áèò 30 |
MANUAL_DESTROY equ 0x80000000 ;áèò 31 |
align 4 |
create_event: ;; EXPORT use |
;info: |
; Ïåðåíîñèì EVENT èç ñïèñêà FreeEvents â ñïèñîê ObjList òåêóùåãî ñëîòà |
; EVENT.state óñòàíàâëèâàåì èç ecx, EVENT.code êîñâåííî èç esi (åñëè esi<>0) |
;param: |
; esi - event data |
; ecx - flags |
;retval: |
; eax - event (=0 => fail) |
; edx - uid |
;scratched: ebx,ecx,esi,edi |
mov ebx,[current_slot] |
add ebx,APP_OBJ_OFFSET |
mov edx,[TASK_BASE] |
mov edx,[edx+TASKDATA.pid] |
pushfd |
cli |
set_event: ;; INTERNAL use !!! don't use for Call |
;info: |
; Áåðåì íîâûé event èç FreeEvents, çàïîëíÿåì åãî ïîëÿ, êàê óêàçàíî â ecx,edx,esi |
; è óñòàíàâëèâàåì â ñïèñîê, óêàçàííûé â ebx. |
; Âîçâðàùàåì ñàì event (â eax), è åãî uid (â edx) |
;param: |
; ebx - start-chain "virtual" event for entry new event Right of him |
; ecx - flags (copied to EVENT.state) |
; edx - pid (copied to EVENT.pid) |
; esi - event data (copied to EVENT.code indirect, =0 => skip) |
;retval: |
; eax - event (=0 => fail) |
; edx - uid |
;scratched: ebx,ecx,esi,edi |
mov eax,FreeEvents |
cmp eax,[eax+EVENT.fd] |
jne @f ; not empty ??? |
pushad |
call init_events |
popad |
jz RemoveEventTo.break ; POPF+RET |
@@: mov eax,[eax+EVENT.fd] |
mov [eax+EVENT.magic],'EVNT' |
mov [eax+EVENT.destroy],destroy_event.internal |
mov [eax+EVENT.state],ecx |
mov [eax+EVENT.pid],edx |
inc [event_uid] |
Mov [eax+EVENT.id],edx,[event_uid] |
or esi,esi |
jz RemoveEventTo |
lea edi,[eax+EVENT.code] |
mov ecx,EVENT.codesize/4 |
cld |
rep movsd |
RemoveEventTo: ;; INTERNAL use !!! don't use for Call |
;param: |
; eax - óêàçàòåëü íà event, ÊÎÒÎÐÛÉ âñòàâëÿåì |
; ebx - óêàçàòåëü íà event, ÏÎÑËÅ êîòîðîãî âñòàâëÿåì |
;scratched: ebx,ecx |
mov ecx,eax ; ecx=eax=Self, ebx=NewLeft |
xchg ecx,[ebx+EVENT.fd] ; NewLeft.fd=Self, ecx=NewRight |
cmp eax,ecx ; ñòîï, ñåáå äóìàþ... |
je .break ; - à íå äóðàê ëè ÿ? |
mov [ecx+EVENT.bk],eax ; NewRight.bk=Self |
xchg ebx,[eax+EVENT.bk] ; Self.bk=NewLeft, ebx=OldLeft |
xchg ecx,[eax+EVENT.fd] ; Self.fd=NewRight, ecx=OldRight |
mov [ebx+EVENT.fd],ecx ; OldLeft.fd=OldRight |
mov [ecx+EVENT.bk],ebx ; OldRight.bk=OldLeft |
.break: popfd |
ret |
align 4 |
NotDummyTest: ;; INTERNAL use (not returned for fail !!!) |
pop edi |
call DummyTest ; not returned for fail !!! |
mov ebx,eax |
mov eax,[ebx+EVENT.pid] |
push edi |
.small: ; êðèâî êàê-òî... |
pop edi |
pushfd |
cli |
call pid_to_slot ; saved all registers (eax - retval) |
shl eax,8 |
jz RemoveEventTo.break ; POPF+RET |
jmp edi ; øòàòíûé âîçâðàò |
align 4 |
raise_event: ;; EXPORT use |
;info: |
; Óñòàíàâëèâàåì äàííûå EVENT.code |
; Åñëè òàì ôëàã EVENT_SIGNALED óæå àêòèâåí - áîëüøå íè÷åãî |
; Èíà÷å: ýòîò ôëàã âçâîäèòñÿ, çà èñêëþ÷åíèåì ñëó÷àÿ íàëè÷èÿ ôëàãà EVENT_WATCHED â edx |
;  ýòîì ñëó÷àå EVENT_SIGNALED âçâîäèòñÿ ëèøü ïðè íàëè÷èå EVENT_WATCHED â ñàìîì ñîáûòèè |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
; edx - flags |
; esi - event data (=0 => skip) |
;scratched: ebx,ecx,esi,edi |
call NotDummyTest ; not returned for fail !!! |
or esi,esi |
jz @f |
lea edi,[ebx+EVENT.code] |
mov ecx,EVENT.codesize/4 |
cld |
rep movsd |
@@: |
test byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24 |
jnz RemoveEventTo.break ; POPF+RET |
bt edx, 28 ;EVENT_WATCHED |
jnc @f |
test byte[ebx+EVENT.state+3], EVENT_WATCHED shr 24 |
jz RemoveEventTo.break ; POPF+RET |
@@: |
or byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24 |
add eax,SLOT_BASE+APP_EV_OFFSET |
xchg eax,ebx |
jmp RemoveEventTo |
align 4 |
clear_event: ;; EXPORT use |
;info: |
; |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
;scratched: ebx,ecx |
call NotDummyTest ; not returned for fail !!! |
add eax,SLOT_BASE+APP_OBJ_OFFSET |
and byte[ebx+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24) |
xchg eax,ebx |
jmp RemoveEventTo |
align 4 |
send_event: ;; EXPORT use |
;info: |
; Ñîçäàåò íîâûé EVENT (âûòàñêèâàåò èç ñïèñêà FreeEvents) â ñïèñêå EventList |
; öåëåâîãî ñëîòà (eax=pid), ñ äàííûìè èç esi êîñâåííî, è state=EVENT_SIGNALED |
;param: |
; eax - slots pid, to sending new event |
; esi - pointer to sending data (in code field of new event) |
;retval: |
; eax - event (=0 => fail) |
; edx - uid |
;warning: |
; may be used as CDECL with such prefix... |
; mov esi,[esp+8] |
; mov eax,[esp+4] |
; but not as STDCALL :( |
;scratched: ebx,ecx,esi,edi |
mov edx,eax |
call NotDummyTest.small ; not returned for fail !!! |
lea ebx,[eax+SLOT_BASE+APP_EV_OFFSET] |
mov ecx,EVENT_SIGNALED |
jmp set_event |
align 4 |
DummyTest: ;; INTERNAL use (not returned for fail !!!) |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
cmp [eax+EVENT.magic],'EVNT' |
jne @f |
cmp [eax+EVENT.id],ebx |
je .ret |
@@: pop eax |
xor eax,eax |
.ret: ret |
align 4 |
Wait_events: |
or ebx,-1 ; infinite timeout |
Wait_events_ex: |
;info: |
; Îæèäàíèå "àáñòðàêòíîãî" ñîáûòèÿ ÷åðåç ïåðåâîä ñëîòà â 5-þ ïîçèöèþ. |
; Àáñòðàêòíîñòü çàêëþ÷åíà â òîì, ÷òî ôàêò ñîáûòèÿ îïðåäåëÿåòñÿ ôóíêöèåé APPDATA.wait_test, |
; êîòîðàÿ çàäàåòñÿ êëèåíòîì è ìîæåò áûòü ôàêòè÷åñêè ëþáîé. |
; Ýòî ïîçâîëÿåò shed-ó íàäåæíî îïðåäåëèòü ôàêò ñîáûòèÿ, è íå ñîâåðøàòü "õîëîñòûõ" ïåðåêëþ÷åíèé, |
; ïðåäíàçíà÷åííûõ äëÿ ðàçáîðîê òèïà "ñâîé/÷óæîé" âíóòðè çàäà÷è. |
;param: |
; edx - wait_test, êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ (àäðåñ êîäà) |
; ecx - wait_param, äîïîëíèòåëüíûé ïàðàìåòð, âîçìîæíî íåîáõîäèìûé äëÿ [wait_test] |
; ebx - wait_timeout |
;retval: |
; eax - ðåçóëüòàò âûçîâà [wait_test] (=0 => timeout) |
;scratched: esi |
mov esi,[current_slot] |
mov [esi+APPDATA.wait_param],ecx |
pushad |
mov ebx,esi;ïîêà ýòî âîïðîñ, ÷åãî êóäû ñóâàòü.......... |
pushfd ; ýòî ñëåäñòâèå îáùåé êîíöåïöèè: ïóñòü ô-ÿ òåñòèðîâàíèÿ èìååò |
cli ; ïðàâî ðàññ÷èòûâàòü íà çàêðûòûå ïðåðûâàíèÿ, êàê ïðè âûçîâå èç shed |
call edx |
popfd |
mov [esp+28],eax |
popad |
or eax,eax |
jnz @f ;RET |
mov [esi+APPDATA.wait_test],edx |
mov [esi+APPDATA.wait_timeout],ebx |
Mov [esi+APPDATA.wait_begin],eax,[timer_ticks] |
mov eax,[TASK_BASE] |
mov [eax+TASKDATA.state], 5 |
call change_task |
mov eax,[esi+APPDATA.wait_param] |
@@: ret |
align 4 |
wait_event: ;; EXPORT use |
;info: |
; Îæèäàíèå ôëàãà EVENT_SIGNALED â ñîâåðøåííî êîíêðåòíîì Event |
; (óñòàíàâëèâàåìîãî, íàäî ïîëàãàòü, ÷åðåç raise_event) |
; Ïðè àêòèâíîì ôëàãå MANUAL_RESET - áîëüøå íè÷åãî |
; Èíà÷å: ôëàãè EVENT_SIGNALED è EVENT_WATCHED ó ïîëó÷åííîãî ñîáûòèÿ ñáðàñûâàþòñÿ, |
; è, ïðè àêòèâíîì MANUAL_DESTROY - ïåðåìåùàåòñÿ â ñïèñîê ObjList òåêóùåãî ñëîòà, |
; à ïðè íå àêòèâíîì - óíè÷òîæàåòñÿ øòàòíî (destroy_event.internal) |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
;scratched: ecx,edx,esi |
call DummyTest |
mov ecx,eax ; wait_param |
mov edx, get_event_alone ; wait_test |
call Wait_events ; timeout ignored |
jmp wait_finish |
align 4 |
get_event_ex: ;; f68:14 |
;info: |
; Îæèäàíèå ëþáîãî ñîáûòèÿ â î÷åðåäè EventList òåêóùåãî ñëîòà |
; Äàííûå ñîáûòèÿ code - êîïèðóþòñÿ â ïàìÿòü ïðèëîæåíèÿ (êîñâåííî ïî edi) |
; Ïðè àêòèâíîì ôëàãå MANUAL_RESET - áîëüøå íè÷åãî |
; Èíà÷å: ôëàãè EVENT_SIGNALED è EVENT_WATCHED ó ïîëó÷åííîãî ñîáûòèÿ ñáðàñûâàþòñÿ, |
; è, ïðè àêòèâíîì MANUAL_DESTROY - ïåðåìåùàåòñÿ â ñïèñîê ObjList òåêóùåãî ñëîòà, |
; à ïðè íå àêòèâíîì - óíè÷òîæàåòñÿ øòàòíî (destroy_event.internal) |
;param: |
; edi - àäðåñ â êîäå ïðèëîæåíèÿ äëÿ êîïèðîâàíèÿ äàííûõ èç EVENT.code |
;retval: |
; eax - ñîáñòâåííî EVENT (áóäåì íàçûâàòü ýòî åãî õýíäëîì) |
;scratched: ebx,ecx,edx,esi,edi |
mov edx, get_event_queue ; wait_test |
call Wait_events ; timeout ignored |
lea esi,[eax+EVENT.code] |
mov ecx,EVENT.codesize/4 |
cld |
rep movsd |
mov [edi-EVENT.codesize+2],cl ;clear priority field |
wait_finish: |
test byte[eax+EVENT.state+3], MANUAL_RESET shr 24 |
jnz get_event_queue.ret ; RET |
and byte[eax+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24) |
test byte[eax+EVENT.state+3], MANUAL_DESTROY shr 24 |
jz destroy_event.internal |
mov ebx,[current_slot] |
add ebx,APP_OBJ_OFFSET |
pushfd |
cli |
jmp RemoveEventTo |
align 4 |
destroy_event: ;; EXPORT use |
;info: |
; Ïåðåíîñèì EVENT â ñïèñîê FreeEvents, ÷èñòèì ïîëÿ magic,destroy,pid,id |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
;retval: |
; eax - àäðåñ îáúåêòà EVENT (=0 => fail) |
;scratched: ebx,ecx |
call DummyTest ; not returned for fail !!! |
.internal: |
xor ecx,ecx ; clear common header |
pushfd |
cli |
mov [eax+EVENT.magic],ecx |
mov [eax+EVENT.destroy],ecx |
mov [eax+EVENT.pid],ecx |
mov [eax+EVENT.id],ecx |
mov ebx,FreeEvents |
jmp RemoveEventTo |
align 4 |
get_event_queue: |
;info: |
; êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ äëÿ get_event_ex |
;warning: |
; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot |
; -may be assumed, that interrupt are disabled |
; -it is not restriction for scratched registers |
;param: |
; ebx - àäðåñ APPDATA ñëîòà òåñòèðîâàíèÿ |
;retval: |
; eax - àäðåñ îáúåêòà EVENT (=0 => fail) |
add ebx,APP_EV_OFFSET |
mov eax,[ebx+APPOBJ.bk] ; âûáèðàåì ñ êîíöà, ïî ïðèíöèïó FIFO |
cmp eax,ebx ; empty ??? |
je get_event_alone.ret0 |
.ret: ret |
align 4 |
get_event_alone: |
;info: |
; êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ äëÿ wait_event |
;warning: |
; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot |
; -may be assumed, that interrupt are disabled |
; -it is not restriction for scratched registers |
;param: |
; ebx - àäðåñ APPDATA ñëîòà òåñòèðîâàíèÿ |
;retval: |
; eax - àäðåñ îáúåêòà EVENT (=0 => fail) |
mov eax,[ebx+APPDATA.wait_param] |
test byte[eax+EVENT.state+3], EVENT_SIGNALED shr 24 |
jnz .ret |
or byte[eax+EVENT.state+3], EVENT_WATCHED shr 24 |
.ret0: xor eax,eax ; NO event!!! |
.ret: ret |
align 4 |
sys_sendwindowmsg: ;; f72 |
dec ebx |
jnz .ret ;subfunction==1 ? |
;pushfd ;à íàôèãà? |
cli |
sub ecx,2 |
je .sendkey |
dec ecx |
jnz .retf |
.sendbtn: |
cmp byte[BTN_COUNT],1 |
jae .result ;overflow |
inc byte[BTN_COUNT] |
shl edx, 8 |
mov [BTN_BUFF],edx |
jmp .result |
.sendkey: |
movzx eax,byte[KEY_COUNT] |
cmp al,120 |
jae .result ;overflow |
inc byte[KEY_COUNT] |
mov [KEY_COUNT+1+eax],dl |
.result: |
setae byte[esp+32] ;ñ÷èòàåì, ÷òî èñõîäíî: dword[esp+32]==72 |
.retf: ;popfd |
.ret: ret |
align 4 |
sys_getevent: ;; f11 |
mov ebx,[current_slot] ;ïîêà ýòî âîïðîñ, ÷åãî êóäû ñóâàòü.......... |
pushfd ; ýòî ñëåäñòâèå îáùåé êîíöåïöèè: ïóñòü ô-ÿ òåñòèðîâàíèÿ èìååò |
cli ; ïðàâî ðàññ÷èòûâàòü íà çàêðûòûå ïðåðûâàíèÿ, êàê ïðè âûçîâå èç shed |
call get_event_for_app |
popfd |
mov [esp+32],eax |
ret |
align 4 |
sys_waitforevent: ;; f10 |
or ebx,-1 ; infinite timeout |
sys_wait_event_timeout: ;; f23 |
mov edx,get_event_for_app ; wait_test |
call Wait_events_ex ; ebx - timeout |
mov [esp+32],eax |
ret |
align 4 |
get_event_for_app: ;; used from f10,f11,f23 |
;info: |
; êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ äëÿ ïðèëîæåíèé (f10,f23) |
;warning: |
; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot |
; -may be assumed, that interrupt are disabled |
; -it is not restriction for scratched registers |
;param: |
; ebx - àäðåñ APPDATA ñëîòà òåñòèðîâàíèÿ |
;retval: |
; eax - íîìåð ñîáûòèÿ (=0 => no events) |
movzx edi,bh ; bh is assumed as [CURRENT_TASK] |
shl edi,5 |
add edi,CURRENT_TASK ; edi is assumed as [TASK_BASE] |
mov ecx,[edi+TASKDATA.event_mask] |
.loop: ; ïîêà íå èñ÷åðïàåì âñå áèòû ìàñêè |
bsr eax,ecx ; íàõîäèì íåíóëåâîé áèò ìàñêè (31 -> 0) |
jz .no_events ; èñ÷åðïàëè âñå áèòû ìàñêè, íî íè÷åãî íå íàøëè ??? |
btr ecx,eax ; ñáðàñûâàåì ïðîâåðÿåìûé áèò ìàñêè |
; ïåðåõîäèì íà îáðàáîò÷èê ýòîãî (eax) áèòà |
cmp eax,9 |
jae .loop ; eax=[9..31], ignored |
cmp eax,3 |
je .loop ; eax=3, ignored |
ja .FlagAutoReset ; eax=[4..8], retvals=eax+1 |
cmp eax,1 |
jae .BtKy ; eax=[1,2], retvals=eax+1 |
.WndRedraw: ; eax=0, retval WndRedraw=1 |
cmp [edi-twdw+WDATA.fl_redraw],al ;al==0 |
jne .result |
jmp .loop |
.no_events: |
xor eax,eax |
ret |
.FlagAutoReset: ; retvals: BgrRedraw=5, Mouse=6, IPC=7, Stack=8, Debug=9 |
cmp eax,5 ; Mouse 5+1=6 |
jne @f |
push eax |
; If the window is captured and moved by the user, then no mouse events!!! |
mov al,[mouse.active_sys_window.action] |
and al,WINDOW_MOVE_AND_RESIZE_FLAGS |
test al,al |
pop eax |
jnz .loop |
@@: |
btr [ebx+APPDATA.event_mask],eax |
jnc .loop |
.result: ; retval = eax+1 |
inc eax |
ret |
.BtKy: |
movzx edx,bh |
movzx edx, word[WIN_STACK+edx*2] |
je .Keys ; eax=1, retval Keys=2 |
.Buttons: ; eax=2, retval Buttons=3 |
cmp byte[BTN_COUNT],0 |
je .loop ; empty ??? |
cmp edx,[TASK_COUNT] |
jne .loop ; not Top ??? |
mov edx, [BTN_BUFF] |
shr edx, 8 |
cmp edx, 0xFFFF ;-ID for Minimize-Button of Form |
jne .result |
mov [window_minimize],1 |
dec byte[BTN_COUNT] |
jmp .loop |
.Keys: ; eax==1 |
cmp edx,[TASK_COUNT] |
jne @f ; not Top ??? |
cmp [KEY_COUNT],al ; al==1 |
jae .result ; not empty ??? |
@@: mov edx, hotkey_buffer |
@@: cmp [edx],bh ; bh - slot for testing |
je .result |
add edx,8 |
cmp edx, hotkey_buffer+120*8 |
jb @b |
jmp .loop |
;end. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
WINDOW_MOVE_AND_RESIZE_FLAGS = \ |
mouse.WINDOW_RESIZE_N_FLAG + \ |
mouse.WINDOW_RESIZE_W_FLAG + \ |
mouse.WINDOW_RESIZE_S_FLAG + \ |
mouse.WINDOW_RESIZE_E_FLAG + \ |
mouse.WINDOW_MOVE_FLAG |
uglobal |
align 4 |
event_start dd ? |
event_end dd ? |
event_uid dd 0 |
endg |
EV_SPACE = 512 |
FreeEvents = event_start-EVENT.fd ; "âèðòóàëüíûé" event, èñïîëüçóþòñÿ òîëüêî ïîëÿ: |
; FreeEvents.fd=event_start è FreeEvents.bk=event_end |
align 4 |
init_events: ;; used from kernel.asm |
stdcall kernel_alloc, EV_SPACE*EVENT.size |
or eax, eax |
jz .fail |
; eax - current event, ebx - previos event below |
mov ecx, EV_SPACE ; current - in allocated space |
mov ebx, FreeEvents ; previos - íà÷àëî ñïèñêà |
push ebx ; îíî æå è êîíåö ïîòîì áóäåò |
@@: |
mov [ebx+EVENT.fd], eax |
mov [eax+EVENT.bk], ebx |
mov ebx, eax ; previos <- current |
add eax, EVENT.size ; new current |
loop @b |
pop eax ; âîò îíî êîíöîì è ñòàëî |
mov [ebx+EVENT.fd], eax |
mov [eax+EVENT.bk], ebx |
.fail: |
ret |
EVENT_WATCHED equ 0x10000000 ;áèò 28 |
EVENT_SIGNALED equ 0x20000000 ;áèò 29 |
MANUAL_RESET equ 0x40000000 ;áèò 30 |
MANUAL_DESTROY equ 0x80000000 ;áèò 31 |
align 4 |
create_event: ;; EXPORT use |
;info: |
; Ïåðåíîñèì EVENT èç ñïèñêà FreeEvents â ñïèñîê ObjList òåêóùåãî ñëîòà |
; EVENT.state óñòàíàâëèâàåì èç ecx, EVENT.code êîñâåííî èç esi (åñëè esi<>0) |
;param: |
; esi - event data |
; ecx - flags |
;retval: |
; eax - event (=0 => fail) |
; edx - uid |
;scratched: ebx,ecx,esi,edi |
mov ebx, [current_slot] |
add ebx, APP_OBJ_OFFSET |
mov edx, [TASK_BASE] |
mov edx, [edx+TASKDATA.pid] |
pushfd |
cli |
set_event: ;; INTERNAL use !!! don't use for Call |
;info: |
; Áåðåì íîâûé event èç FreeEvents, çàïîëíÿåì åãî ïîëÿ, êàê óêàçàíî â ecx,edx,esi |
; è óñòàíàâëèâàåì â ñïèñîê, óêàçàííûé â ebx. |
; Âîçâðàùàåì ñàì event (â eax), è åãî uid (â edx) |
;param: |
; ebx - start-chain "virtual" event for entry new event Right of him |
; ecx - flags (copied to EVENT.state) |
; edx - pid (copied to EVENT.pid) |
; esi - event data (copied to EVENT.code indirect, =0 => skip) |
;retval: |
; eax - event (=0 => fail) |
; edx - uid |
;scratched: ebx,ecx,esi,edi |
mov eax, FreeEvents |
cmp eax, [eax+EVENT.fd] |
jne @f ; not empty ??? |
pushad |
call init_events |
popad |
jz RemoveEventTo.break ; POPF+RET |
@@: |
mov eax, [eax+EVENT.fd] |
mov [eax+EVENT.magic], 'EVNT' |
mov [eax+EVENT.destroy], destroy_event.internal |
mov [eax+EVENT.state], ecx |
mov [eax+EVENT.pid], edx |
inc [event_uid] |
Mov [eax+EVENT.id],edx,[event_uid] |
or esi, esi |
jz RemoveEventTo |
lea edi, [eax+EVENT.code] |
mov ecx, EVENT.codesize/4 |
cld |
rep movsd |
RemoveEventTo: ;; INTERNAL use !!! don't use for Call |
;param: |
; eax - óêàçàòåëü íà event, ÊÎÒÎÐÛÉ âñòàâëÿåì |
; ebx - óêàçàòåëü íà event, ÏÎÑËÅ êîòîðîãî âñòàâëÿåì |
;scratched: ebx,ecx |
mov ecx, eax ; ecx=eax=Self, ebx=NewLeft |
xchg ecx, [ebx+EVENT.fd] ; NewLeft.fd=Self, ecx=NewRight |
cmp eax, ecx ; ñòîï, ñåáå äóìàþ... |
je .break ; - à íå äóðàê ëè ÿ? |
mov [ecx+EVENT.bk], eax ; NewRight.bk=Self |
xchg ebx, [eax+EVENT.bk] ; Self.bk=NewLeft, ebx=OldLeft |
xchg ecx, [eax+EVENT.fd] ; Self.fd=NewRight, ecx=OldRight |
mov [ebx+EVENT.fd], ecx ; OldLeft.fd=OldRight |
mov [ecx+EVENT.bk], ebx ; OldRight.bk=OldLeft |
.break: |
popfd |
ret |
align 4 |
NotDummyTest: ;; INTERNAL use (not returned for fail !!!) |
pop edi |
call DummyTest ; not returned for fail !!! |
mov ebx, eax |
mov eax, [ebx+EVENT.pid] |
push edi |
.small: ; êðèâî êàê-òî... |
pop edi |
pushfd |
cli |
call pid_to_slot ; saved all registers (eax - retval) |
shl eax, 8 |
jz RemoveEventTo.break ; POPF+RET |
jmp edi ; øòàòíûé âîçâðàò |
align 4 |
raise_event: ;; EXPORT use |
;info: |
; Óñòàíàâëèâàåì äàííûå EVENT.code |
; Åñëè òàì ôëàã EVENT_SIGNALED óæå àêòèâåí - áîëüøå íè÷åãî |
; Èíà÷å: ýòîò ôëàã âçâîäèòñÿ, çà èñêëþ÷åíèåì ñëó÷àÿ íàëè÷èÿ ôëàãà EVENT_WATCHED â edx |
;  ýòîì ñëó÷àå EVENT_SIGNALED âçâîäèòñÿ ëèøü ïðè íàëè÷èå EVENT_WATCHED â ñàìîì ñîáûòèè |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
; edx - flags |
; esi - event data (=0 => skip) |
;scratched: ebx,ecx,esi,edi |
call NotDummyTest ; not returned for fail !!! |
or esi, esi |
jz @f |
lea edi, [ebx+EVENT.code] |
mov ecx, EVENT.codesize/4 |
cld |
rep movsd |
@@: |
test byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24 |
jnz RemoveEventTo.break ; POPF+RET |
bt edx, 28 ;EVENT_WATCHED |
jnc @f |
test byte[ebx+EVENT.state+3], EVENT_WATCHED shr 24 |
jz RemoveEventTo.break ; POPF+RET |
@@: |
or byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24 |
add eax, SLOT_BASE+APP_EV_OFFSET |
xchg eax, ebx |
jmp RemoveEventTo |
align 4 |
clear_event: ;; EXPORT use |
;info: |
; |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
;scratched: ebx,ecx |
call NotDummyTest ; not returned for fail !!! |
add eax, SLOT_BASE+APP_OBJ_OFFSET |
and byte[ebx+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24) |
xchg eax, ebx |
jmp RemoveEventTo |
align 4 |
send_event: ;; EXPORT use |
;info: |
; Ñîçäàåò íîâûé EVENT (âûòàñêèâàåò èç ñïèñêà FreeEvents) â ñïèñêå EventList |
; öåëåâîãî ñëîòà (eax=pid), ñ äàííûìè èç esi êîñâåííî, è state=EVENT_SIGNALED |
;param: |
; eax - slots pid, to sending new event |
; esi - pointer to sending data (in code field of new event) |
;retval: |
; eax - event (=0 => fail) |
; edx - uid |
;warning: |
; may be used as CDECL with such prefix... |
; mov esi,[esp+8] |
; mov eax,[esp+4] |
; but not as STDCALL :( |
;scratched: ebx,ecx,esi,edi |
mov edx, eax |
call NotDummyTest.small ; not returned for fail !!! |
lea ebx, [eax+SLOT_BASE+APP_EV_OFFSET] |
mov ecx, EVENT_SIGNALED |
jmp set_event |
align 4 |
DummyTest: ;; INTERNAL use (not returned for fail !!!) |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
cmp [eax+EVENT.magic], 'EVNT' |
jne @f |
cmp [eax+EVENT.id], ebx |
je .ret |
@@: |
pop eax |
xor eax, eax |
.ret: |
ret |
align 4 |
Wait_events: |
or ebx, -1; infinite timeout |
Wait_events_ex: |
;info: |
; Îæèäàíèå "àáñòðàêòíîãî" ñîáûòèÿ ÷åðåç ïåðåâîä ñëîòà â 5-þ ïîçèöèþ. |
; Àáñòðàêòíîñòü çàêëþ÷åíà â òîì, ÷òî ôàêò ñîáûòèÿ îïðåäåëÿåòñÿ ôóíêöèåé APPDATA.wait_test, |
; êîòîðàÿ çàäàåòñÿ êëèåíòîì è ìîæåò áûòü ôàêòè÷åñêè ëþáîé. |
; Ýòî ïîçâîëÿåò shed-ó íàäåæíî îïðåäåëèòü ôàêò ñîáûòèÿ, è íå ñîâåðøàòü "õîëîñòûõ" ïåðåêëþ÷åíèé, |
; ïðåäíàçíà÷åííûõ äëÿ ðàçáîðîê òèïà "ñâîé/÷óæîé" âíóòðè çàäà÷è. |
;param: |
; edx - wait_test, êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ (àäðåñ êîäà) |
; ecx - wait_param, äîïîëíèòåëüíûé ïàðàìåòð, âîçìîæíî íåîáõîäèìûé äëÿ [wait_test] |
; ebx - wait_timeout |
;retval: |
; eax - ðåçóëüòàò âûçîâà [wait_test] (=0 => timeout) |
;scratched: esi |
mov esi, [current_slot] |
mov [esi+APPDATA.wait_param], ecx |
pushad |
mov ebx, esi;ïîêà ýòî âîïðîñ, ÷åãî êóäû ñóâàòü.......... |
pushfd ; ýòî ñëåäñòâèå îáùåé êîíöåïöèè: ïóñòü ô-ÿ òåñòèðîâàíèÿ èìååò |
cli ; ïðàâî ðàññ÷èòûâàòü íà çàêðûòûå ïðåðûâàíèÿ, êàê ïðè âûçîâå èç shed |
call edx |
popfd |
mov [esp+28], eax |
popad |
or eax, eax |
jnz @f ;RET |
mov [esi+APPDATA.wait_test], edx |
mov [esi+APPDATA.wait_timeout], ebx |
Mov [esi+APPDATA.wait_begin],eax,[timer_ticks] |
mov eax, [TASK_BASE] |
mov [eax+TASKDATA.state], 5 |
call change_task |
mov eax, [esi+APPDATA.wait_param] |
@@: |
ret |
align 4 |
wait_event: ;; EXPORT use |
;info: |
; Îæèäàíèå ôëàãà EVENT_SIGNALED â ñîâåðøåííî êîíêðåòíîì Event |
; (óñòàíàâëèâàåìîãî, íàäî ïîëàãàòü, ÷åðåç raise_event) |
; Ïðè àêòèâíîì ôëàãå MANUAL_RESET - áîëüøå íè÷åãî |
; Èíà÷å: ôëàãè EVENT_SIGNALED è EVENT_WATCHED ó ïîëó÷åííîãî ñîáûòèÿ ñáðàñûâàþòñÿ, |
; è, ïðè àêòèâíîì MANUAL_DESTROY - ïåðåìåùàåòñÿ â ñïèñîê ObjList òåêóùåãî ñëîòà, |
; à ïðè íå àêòèâíîì - óíè÷òîæàåòñÿ øòàòíî (destroy_event.internal) |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
;scratched: ecx,edx,esi |
call DummyTest |
mov ecx, eax ; wait_param |
mov edx, get_event_alone ; wait_test |
call Wait_events ; timeout ignored |
jmp wait_finish |
align 4 |
get_event_ex: ;; f68:14 |
;info: |
; Îæèäàíèå ëþáîãî ñîáûòèÿ â î÷åðåäè EventList òåêóùåãî ñëîòà |
; Äàííûå ñîáûòèÿ code - êîïèðóþòñÿ â ïàìÿòü ïðèëîæåíèÿ (êîñâåííî ïî edi) |
; Ïðè àêòèâíîì ôëàãå MANUAL_RESET - áîëüøå íè÷åãî |
; Èíà÷å: ôëàãè EVENT_SIGNALED è EVENT_WATCHED ó ïîëó÷åííîãî ñîáûòèÿ ñáðàñûâàþòñÿ, |
; è, ïðè àêòèâíîì MANUAL_DESTROY - ïåðåìåùàåòñÿ â ñïèñîê ObjList òåêóùåãî ñëîòà, |
; à ïðè íå àêòèâíîì - óíè÷òîæàåòñÿ øòàòíî (destroy_event.internal) |
;param: |
; edi - àäðåñ â êîäå ïðèëîæåíèÿ äëÿ êîïèðîâàíèÿ äàííûõ èç EVENT.code |
;retval: |
; eax - ñîáñòâåííî EVENT (áóäåì íàçûâàòü ýòî åãî õýíäëîì) |
;scratched: ebx,ecx,edx,esi,edi |
mov edx, get_event_queue ; wait_test |
call Wait_events ; timeout ignored |
lea esi, [eax+EVENT.code] |
mov ecx, EVENT.codesize/4 |
cld |
rep movsd |
mov [edi-EVENT.codesize+2], cl;clear priority field |
wait_finish: |
test byte[eax+EVENT.state+3], MANUAL_RESET shr 24 |
jnz get_event_queue.ret ; RET |
and byte[eax+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24) |
test byte[eax+EVENT.state+3], MANUAL_DESTROY shr 24 |
jz destroy_event.internal |
mov ebx, [current_slot] |
add ebx, APP_OBJ_OFFSET |
pushfd |
cli |
jmp RemoveEventTo |
align 4 |
destroy_event: ;; EXPORT use |
;info: |
; Ïåðåíîñèì EVENT â ñïèñîê FreeEvents, ÷èñòèì ïîëÿ magic,destroy,pid,id |
;param: |
; eax - event |
; ebx - uid (for Dummy testing) |
;retval: |
; eax - àäðåñ îáúåêòà EVENT (=0 => fail) |
;scratched: ebx,ecx |
call DummyTest ; not returned for fail !!! |
.internal: |
xor ecx, ecx ; clear common header |
pushfd |
cli |
mov [eax+EVENT.magic], ecx |
mov [eax+EVENT.destroy], ecx |
mov [eax+EVENT.pid], ecx |
mov [eax+EVENT.id], ecx |
mov ebx, FreeEvents |
jmp RemoveEventTo |
align 4 |
get_event_queue: |
;info: |
; êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ äëÿ get_event_ex |
;warning: |
; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot |
; -may be assumed, that interrupt are disabled |
; -it is not restriction for scratched registers |
;param: |
; ebx - àäðåñ APPDATA ñëîòà òåñòèðîâàíèÿ |
;retval: |
; eax - àäðåñ îáúåêòà EVENT (=0 => fail) |
add ebx, APP_EV_OFFSET |
mov eax, [ebx+APPOBJ.bk] ; âûáèðàåì ñ êîíöà, ïî ïðèíöèïó FIFO |
cmp eax, ebx ; empty ??? |
je get_event_alone.ret0 |
.ret: |
ret |
align 4 |
get_event_alone: |
;info: |
; êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ äëÿ wait_event |
;warning: |
; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot |
; -may be assumed, that interrupt are disabled |
; -it is not restriction for scratched registers |
;param: |
; ebx - àäðåñ APPDATA ñëîòà òåñòèðîâàíèÿ |
;retval: |
; eax - àäðåñ îáúåêòà EVENT (=0 => fail) |
mov eax, [ebx+APPDATA.wait_param] |
test byte[eax+EVENT.state+3], EVENT_SIGNALED shr 24 |
jnz .ret |
or byte[eax+EVENT.state+3], EVENT_WATCHED shr 24 |
.ret0: |
xor eax, eax; NO event!!! |
.ret: |
ret |
align 4 |
sys_sendwindowmsg: ;; f72 |
dec ebx |
jnz .ret ;subfunction==1 ? |
;pushfd ;à íàôèãà? |
cli |
sub ecx, 2 |
je .sendkey |
dec ecx |
jnz .retf |
.sendbtn: |
cmp byte[BTN_COUNT], 1 |
jae .result ;overflow |
inc byte[BTN_COUNT] |
shl edx, 8 |
mov [BTN_BUFF], edx |
jmp .result |
.sendkey: |
movzx eax, byte[KEY_COUNT] |
cmp al, 120 |
jae .result ;overflow |
inc byte[KEY_COUNT] |
mov [KEY_COUNT+1+eax], dl |
.result: |
setae byte[esp+32] ;ñ÷èòàåì, ÷òî èñõîäíî: dword[esp+32]==72 |
.retf: ;popfd |
.ret: |
ret |
align 4 |
sys_getevent: ;; f11 |
mov ebx, [current_slot];ïîêà ýòî âîïðîñ, ÷åãî êóäû ñóâàòü.......... |
pushfd ; ýòî ñëåäñòâèå îáùåé êîíöåïöèè: ïóñòü ô-ÿ òåñòèðîâàíèÿ èìååò |
cli ; ïðàâî ðàññ÷èòûâàòü íà çàêðûòûå ïðåðûâàíèÿ, êàê ïðè âûçîâå èç shed |
call get_event_for_app |
popfd |
mov [esp+32], eax |
ret |
align 4 |
sys_waitforevent: ;; f10 |
or ebx, -1; infinite timeout |
sys_wait_event_timeout: ;; f23 |
mov edx, get_event_for_app; wait_test |
call Wait_events_ex ; ebx - timeout |
mov [esp+32], eax |
ret |
align 4 |
get_event_for_app: ;; used from f10,f11,f23 |
;info: |
; êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ äëÿ ïðèëîæåíèé (f10,f23) |
;warning: |
; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot |
; -may be assumed, that interrupt are disabled |
; -it is not restriction for scratched registers |
;param: |
; ebx - àäðåñ APPDATA ñëîòà òåñòèðîâàíèÿ |
;retval: |
; eax - íîìåð ñîáûòèÿ (=0 => no events) |
movzx edi, bh ; bh is assumed as [CURRENT_TASK] |
shl edi, 5 |
add edi, CURRENT_TASK ; edi is assumed as [TASK_BASE] |
mov ecx, [edi+TASKDATA.event_mask] |
.loop: ; ïîêà íå èñ÷åðïàåì âñå áèòû ìàñêè |
bsr eax, ecx ; íàõîäèì íåíóëåâîé áèò ìàñêè (31 -> 0) |
jz .no_events ; èñ÷åðïàëè âñå áèòû ìàñêè, íî íè÷åãî íå íàøëè ??? |
btr ecx, eax ; ñáðàñûâàåì ïðîâåðÿåìûé áèò ìàñêè |
; ïåðåõîäèì íà îáðàáîò÷èê ýòîãî (eax) áèòà |
cmp eax, 9 |
jae .loop ; eax=[9..31], ignored |
cmp eax, 3 |
je .loop ; eax=3, ignored |
ja .FlagAutoReset ; eax=[4..8], retvals=eax+1 |
cmp eax, 1 |
jae .BtKy ; eax=[1,2], retvals=eax+1 |
.WndRedraw: ; eax=0, retval WndRedraw=1 |
cmp [edi-twdw+WDATA.fl_redraw], al;al==0 |
jne .result |
jmp .loop |
.no_events: |
xor eax, eax |
ret |
.FlagAutoReset: ; retvals: BgrRedraw=5, Mouse=6, IPC=7, Stack=8, Debug=9 |
cmp eax, 5; Mouse 5+1=6 |
jne @f |
push eax |
; If the window is captured and moved by the user, then no mouse events!!! |
mov al, [mouse.active_sys_window.action] |
and al, WINDOW_MOVE_AND_RESIZE_FLAGS |
test al, al |
pop eax |
jnz .loop |
@@: |
btr [ebx+APPDATA.event_mask], eax |
jnc .loop |
.result: ; retval = eax+1 |
inc eax |
ret |
.BtKy: |
movzx edx, bh |
movzx edx, word[WIN_STACK+edx*2] |
je .Keys ; eax=1, retval Keys=2 |
.Buttons: ; eax=2, retval Buttons=3 |
cmp byte[BTN_COUNT], 0 |
je .loop ; empty ??? |
cmp edx, [TASK_COUNT] |
jne .loop ; not Top ??? |
mov edx, [BTN_BUFF] |
shr edx, 8 |
cmp edx, 0xFFFF ;-ID for Minimize-Button of Form |
jne .result |
mov [window_minimize], 1 |
dec byte[BTN_COUNT] |
jmp .loop |
.Keys: ; eax==1 |
cmp edx, [TASK_COUNT] |
jne @f ; not Top ??? |
cmp [KEY_COUNT], al; al==1 |
jae .result ; not empty ??? |
@@: |
mov edx, hotkey_buffer |
@@: |
cmp [edx], bh ; bh - slot for testing |
je .result |
add edx, 8 |
cmp edx, hotkey_buffer+120*8 |
jb @b |
jmp .loop |
;end. |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/gui/font.inc |
---|
1,132 → 1,132 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; // Alver 22.06.2008 // { |
align 4 |
dtext_asciiz_esi: ; for skins title out |
push eax |
xor eax, eax |
inc eax |
jmp dtext.1 |
; } \\ Alver \\ |
align 4 |
dtext: ; Text String Output (rw by Johnny_B[john@kolibrios.org]) |
; ebx x & y |
; ecx style ( 0xX0000000 ) & color ( 0x00RRGGBB ) |
; X = ABnnb: |
; nn = font |
; A = 0 <=> output esi characters; otherwise output ASCIIZ string |
; B = 1 <=> fill background with color eax |
; edx start of text |
; edi 1 force |
; // Alver 22.06.2008 // { |
push eax |
xor eax, eax |
.1: |
; } \\ Alver \\ |
pushad |
call [_display.disable_mouse] |
movsx eax, bx ; eax=y |
sar ebx, 16 ; ebx=x |
xchg eax, ebx ; eax=x, ebx=y |
cmp esi, 255 |
jb .loop |
mov esi, 255 |
.loop: |
test ecx, ecx |
js .test_asciiz |
dec esi |
js .end |
jmp @f |
.test_asciiz: |
cmp byte [edx], 0 |
jz .end |
; // Alver 22.06.2008 // { |
cmp byte [esp+28], 1 |
jne @f |
dec esi |
js .end |
; } \\ Alver \\ |
@@: |
inc edx |
pushad |
movzx edx, byte [edx-1] |
test ecx, 0x10000000 |
jnz .font2 |
mov esi, 9 |
lea ebp, [FONT_I+8*edx+edx] |
.symloop1: |
mov dl, byte [ebp] |
or dl, 1 shl 6 |
.pixloop1: |
shr dl, 1 |
jz .pixloop1end |
jnc .nopix |
call [putpixel] |
jmp .pixloop1cont |
.nopix: |
test ecx, 0x40000000 |
jz .pixloop1cont |
push ecx |
mov ecx, [esp+4+20h+20h] |
call [putpixel] |
pop ecx |
.pixloop1cont: |
inc eax |
jmp .pixloop1 |
.pixloop1end: |
sub eax, 6 |
inc ebx |
inc ebp |
dec esi |
jnz .symloop1 |
popad |
add eax, 6 |
jmp .loop |
.font2: |
add edx, edx |
lea ebp, [FONT_II+4*edx+edx+1] |
push 9 |
movzx esi, byte [ebp-1] |
.symloop2: |
mov dl, byte [ebp] |
push esi |
.pixloop2: |
shr dl, 1 |
jnc .nopix2 |
call [putpixel] |
jmp .pixloop2cont |
.nopix2: |
test ecx, 0x40000000 |
jz .pixloop2cont |
push ecx |
mov ecx, [esp+12+20h+20h] |
call [putpixel] |
pop ecx |
.pixloop2cont: |
inc eax |
dec esi |
jnz .pixloop2 |
pop esi |
sub eax, esi |
inc ebx |
inc ebp |
dec dword [esp] |
jnz .symloop2 |
pop eax |
add dword [esp+28], esi |
popad |
jmp .loop |
.end: |
popad |
pop eax ; << // Alver 22.06.2008 // << |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; // Alver 22.06.2008 // { |
align 4 |
dtext_asciiz_esi: ; for skins title out |
push eax |
xor eax, eax |
inc eax |
jmp dtext.1 |
; } \\ Alver \\ |
align 4 |
dtext: ; Text String Output (rw by Johnny_B[john@kolibrios.org]) |
; ebx x & y |
; ecx style ( 0xX0000000 ) & color ( 0x00RRGGBB ) |
; X = ABnnb: |
; nn = font |
; A = 0 <=> output esi characters; otherwise output ASCIIZ string |
; B = 1 <=> fill background with color eax |
; edx start of text |
; edi 1 force |
; // Alver 22.06.2008 // { |
push eax |
xor eax, eax |
.1: |
; } \\ Alver \\ |
pushad |
call [_display.disable_mouse] |
movsx eax, bx ; eax=y |
sar ebx, 16 ; ebx=x |
xchg eax, ebx ; eax=x, ebx=y |
cmp esi, 255 |
jb .loop |
mov esi, 255 |
.loop: |
test ecx, ecx |
js .test_asciiz |
dec esi |
js .end |
jmp @f |
.test_asciiz: |
cmp byte [edx], 0 |
jz .end |
; // Alver 22.06.2008 // { |
cmp byte [esp+28], 1 |
jne @f |
dec esi |
js .end |
; } \\ Alver \\ |
@@: |
inc edx |
pushad |
movzx edx, byte [edx-1] |
test ecx, 0x10000000 |
jnz .font2 |
mov esi, 9 |
lea ebp, [FONT_I+8*edx+edx] |
.symloop1: |
mov dl, byte [ebp] |
or dl, 1 shl 6 |
.pixloop1: |
shr dl, 1 |
jz .pixloop1end |
jnc .nopix |
call [putpixel] |
jmp .pixloop1cont |
.nopix: |
test ecx, 0x40000000 |
jz .pixloop1cont |
push ecx |
mov ecx, [esp+4+20h+20h] |
call [putpixel] |
pop ecx |
.pixloop1cont: |
inc eax |
jmp .pixloop1 |
.pixloop1end: |
sub eax, 6 |
inc ebx |
inc ebp |
dec esi |
jnz .symloop1 |
popad |
add eax, 6 |
jmp .loop |
.font2: |
add edx, edx |
lea ebp, [FONT_II+4*edx+edx+1] |
push 9 |
movzx esi, byte [ebp-1] |
.symloop2: |
mov dl, byte [ebp] |
push esi |
.pixloop2: |
shr dl, 1 |
jnc .nopix2 |
call [putpixel] |
jmp .pixloop2cont |
.nopix2: |
test ecx, 0x40000000 |
jz .pixloop2cont |
push ecx |
mov ecx, [esp+12+20h+20h] |
call [putpixel] |
pop ecx |
.pixloop2cont: |
inc eax |
dec esi |
jnz .pixloop2 |
pop esi |
sub eax, esi |
inc ebx |
inc ebp |
dec dword [esp] |
jnz .symloop2 |
pop eax |
add dword [esp+28], esi |
popad |
jmp .loop |
.end: |
popad |
pop eax ; << // Alver 22.06.2008 // << |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/gui/mouse.inc |
---|
72,7 → 72,8 |
jmp .exit |
; is there any system button under cursor? |
@@: call mouse._.find_sys_button_under_cursor |
@@: |
call mouse._.find_sys_button_under_cursor |
or eax, eax |
jz .check_buttons_released |
119,12 → 120,14 |
mov eax, [esp + 4] |
call .call_left_button_handler |
@@: test byte[esp], mouse.RIGHT_BUTTON_FLAG |
@@: |
test byte[esp], mouse.RIGHT_BUTTON_FLAG |
jz @f |
mov eax, [esp + 4] |
call .call_right_button_handler |
@@: test byte[esp], mouse.MIDDLE_BUTTON_FLAG |
@@: |
test byte[esp], mouse.MIDDLE_BUTTON_FLAG |
jz .check_position |
mov eax, [esp + 4] |
call .call_middle_button_handler |
222,7 → 225,8 |
call sys_window_maximize_handler |
jmp .exit |
@@: test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED |
@@: |
test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED |
jnz .exit |
mov [mouse.active_sys_window.pslot], esi |
lea eax, [edi + WDATA.box] |
238,15 → 242,18 |
call .calculate_w_delta |
jmp .call_window_handler |
@@: test dl, mouse.WINDOW_RESIZE_W_FLAG |
@@: |
test dl, mouse.WINDOW_RESIZE_W_FLAG |
jz @f |
call .calculate_w_delta |
@@: test dl, mouse.WINDOW_RESIZE_S_FLAG |
@@: |
test dl, mouse.WINDOW_RESIZE_S_FLAG |
jz @f |
call .calculate_s_delta |
@@: test dl, mouse.WINDOW_RESIZE_E_FLAG |
@@: |
test dl, mouse.WINDOW_RESIZE_E_FLAG |
jz .call_window_handler |
call .calculate_e_delta |
389,17 → 396,20 |
jge @f |
xor eax, eax |
mov [mouse.active_sys_window.new_box.left], eax |
@@: add eax, [mouse.active_sys_window.new_box.width] |
@@: |
add eax, [mouse.active_sys_window.new_box.width] |
cmp eax, [Screen_Max_X] |
jl @f |
sub eax, [Screen_Max_X] |
sub [mouse.active_sys_window.new_box.left], eax |
@@: mov eax, [mouse.active_sys_window.new_box.top] |
@@: |
mov eax, [mouse.active_sys_window.new_box.top] |
or eax, eax |
jge @f |
xor eax, eax |
mov [mouse.active_sys_window.new_box.top], eax |
@@: add eax, [mouse.active_sys_window.new_box.height] |
@@: |
add eax, [mouse.active_sys_window.new_box.height] |
cmp eax, [Screen_Max_Y] |
jle .call_window_handler |
sub eax, [Screen_Max_Y] |
421,7 → 431,8 |
jge @f |
add [mouse.active_sys_window.new_box.left], eax |
mov [mouse.active_sys_window.new_box.width], 127 |
@@: mov eax, [mouse.active_sys_window.new_box.left] |
@@: |
mov eax, [mouse.active_sys_window.new_box.left] |
or eax, eax |
jge .check_resize_s |
add [mouse.active_sys_window.new_box.width], eax |
449,7 → 460,8 |
jge @f |
mov eax, ecx |
mov [mouse.active_sys_window.new_box.height], eax |
@@: add eax, [mouse.active_sys_window.new_box.top] |
@@: |
add eax, [mouse.active_sys_window.new_box.top] |
cmp eax, [Screen_Max_Y] |
jle .check_resize_e |
sub eax, [Screen_Max_Y] |
474,7 → 486,8 |
jge @f |
mov eax, 127 |
mov [mouse.active_sys_window.new_box.width], eax |
@@: add eax, [mouse.active_sys_window.new_box.left] |
@@: |
add eax, [mouse.active_sys_window.new_box.left] |
cmp eax, [Screen_Max_X] |
jle .call_window_handler |
sub eax, [Screen_Max_X] |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/gui/mousepointer.inc |
---|
1,250 → 1,250 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
align 4 |
mousepointer: |
db 0x00,0x00,0x00,0x74,0x74,0x74,0x6e,0x6e,0x6e,0x6f |
db 0x6f,0x6f,0x71,0x71,0x71,0x75,0x75,0x75,0x79,0x79 |
db 0x79,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63 |
db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 |
db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0 |
db 0xc0,0xc0,0x00,0x00,0x00,0x54,0x54,0x54,0x57,0x57 |
db 0x57,0x5f,0x5f,0x5f,0x68,0x68,0x68,0x71,0x71,0x71 |
db 0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x47,0x47,0x47,0x50 |
db 0x50,0x50,0x5b,0x5b,0x5b,0x67,0x67,0x67,0x70,0x70 |
db 0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3f,0x3f,0x3f |
db 0x4b,0x4b,0x4b,0x59,0x59,0x59,0x66,0x66,0x66,0x70 |
db 0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e |
db 0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3a,0x3a |
db 0x3a,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66,0x66 |
db 0x70,0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e |
db 0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x39 |
db 0x39,0x39,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66 |
db 0x66,0x71,0x71,0x71,0x78,0x78,0x78,0x7c,0x7c,0x7c |
db 0x7e,0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00 |
db 0x39,0x39,0x39,0x4a,0x4a,0x4a,0x5a,0x5a,0x5a,0x68 |
db 0x68,0x68,0x72,0x72,0x72,0x79,0x79,0x79,0x7d,0x7d |
db 0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00 |
db 0x00,0x3c,0x3c,0x3c,0x4e,0x4e,0x4e,0x5e,0x5e,0x5e |
db 0x6b,0x6b,0x6b,0x75,0x75,0x75,0x7a,0x7a,0x7a,0x7e |
db 0x7e,0x7e,0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00 |
db 0x00,0x00,0x43,0x43,0x43,0x55,0x55,0x55,0x64,0x64 |
db 0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d |
db 0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0 |
db 0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x4e,0x4e,0x4e,0x5f,0x5f,0x5f,0x6d |
db 0x6d,0x6d,0x76,0x76,0x76,0x7c,0x7c,0x7c,0x80,0x80 |
db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 |
db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x14 |
db 0x14,0x14,0x1b,0x1b,0x1b,0x29,0x29,0x29,0x3a,0x3a |
db 0x3a,0x4c,0x4c,0x4c,0x5d,0x5d,0x5d,0x6c,0x6c,0x6c |
db 0x75,0x75,0x75,0x7b,0x7b,0x7b,0x80,0x80,0x80,0xc0 |
db 0xc0,0xc0,0x00,0x00,0x00,0x2f,0x2f,0x2f,0x80,0x80 |
db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 |
db 0x21,0x21,0x21,0x2e,0x2e,0x2e,0x40,0x40,0x40,0x52 |
db 0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f,0x77,0x77 |
db 0x77,0x7c,0x7c,0x7c,0x80,0x80,0x80,0x00,0x00,0x00 |
db 0x47,0x47,0x47,0x3b,0x3b,0x3b,0x80,0x80,0x80,0xff |
db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x25,0x25 |
db 0x25,0x30,0x30,0x30,0x42,0x42,0x42,0x54,0x54,0x54 |
db 0x64,0x64,0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d |
db 0x7d,0x7d,0x00,0x00,0x00,0x62,0x62,0x62,0x52,0x52 |
db 0x52,0x4a,0x4a,0x4a,0x43,0x43,0x43,0x80,0x80,0x80 |
db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x33 |
db 0x33,0x33,0x42,0x42,0x42,0x54,0x54,0x54,0x64,0x64 |
db 0x64,0x71,0x71,0x71,0x79,0x79,0x79,0x7d,0x7d,0x7d |
db 0x72,0x72,0x72,0x6b,0x6b,0x6b,0x5f,0x5f,0x5f,0x5a |
db 0x5a,0x5a,0x54,0x54,0x54,0x80,0x80,0x80,0xff,0xff |
db 0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x35,0x35,0x35 |
db 0x41,0x41,0x41,0x53,0x53,0x53,0x63,0x63,0x63,0x70 |
db 0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d,0x77,0x77 |
db 0x77,0x73,0x73,0x73,0x6c,0x6c,0x6c,0x68,0x68,0x68 |
db 0x62,0x62,0x62,0x5a,0x5a,0x5a,0x80,0x80,0x80,0xff |
db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x41,0x41 |
db 0x41,0x52,0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f |
db 0x78,0x78,0x78,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x79 |
db 0x79,0x79,0x74,0x74,0x74,0x72,0x72,0x72,0x6e,0x6e |
db 0x6e,0x66,0x66,0x66,0x80,0x80,0x80,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x44,0x44,0x44,0x52 |
db 0x52,0x52,0x62,0x62,0x62,0x6e,0x6e,0x6e,0x77,0x77 |
db 0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7c,0x7c,0x7c |
db 0x7a,0x7a,0x7a,0x79,0x79,0x79,0x75,0x75,0x75,0x6f |
db 0x6f,0x6f,0x65,0x65,0x65,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x48,0x48,0x48,0x4b,0x4b,0x4b,0x56,0x56,0x56 |
db 0x65,0x65,0x65,0x70,0x70,0x70,0x78,0x78,0x78,0x7d |
db 0x7d,0x7d,0x80,0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e |
db 0x7e,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76,0x76 |
db 0x6f,0x6f,0x6f,0x65,0x65,0x65,0x5c,0x5c,0x5c,0x56 |
db 0x56,0x56,0x58,0x58,0x58,0x60,0x60,0x60,0x6b,0x6b |
db 0x6b,0x73,0x73,0x73,0x7a,0x7a,0x7a,0x7d,0x7d,0x7d |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7f |
db 0x7f,0x7f,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76 |
db 0x76,0x70,0x70,0x70,0x6a,0x6a,0x6a,0x66,0x66,0x66 |
db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 |
db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x77 |
db 0x77,0x77,0x73,0x73,0x73,0x71,0x71,0x71,0x71,0x71 |
db 0x71,0x74,0x74,0x74,0x78,0x78,0x78,0x7b,0x7b,0x7b |
db 0x7d,0x7d,0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7c,0x7c,0x7c |
db 0x7a,0x7a,0x7a,0x78,0x78,0x78,0x78,0x78,0x78,0x7a |
db 0x7a,0x7a,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7f,0x7f |
db 0x7f,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e,0x7e,0x7e,0x7e |
db 0x7e,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e |
db 0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 |
db 0x80,0x80 |
mousepointer1: |
db 0xff,0xff,0xff,0x06,0x06,0x06,0x0a,0x0a |
db 0x0a,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x19,0x16 |
db 0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2e,0x2e,0x2e |
db 0x23,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f |
db 0x3f,0x29,0x29,0x29,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x47 |
db 0x47,0x47,0x2c,0x2c,0x2c,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0x47,0x47,0x47,0x29,0x29,0x29 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0x40,0x40,0x40,0x23,0x23 |
db 0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xaa,0xaa,0xaa,0x9f,0x9f,0x9f,0x8c,0x8c,0x8c |
db 0x70,0x70,0x70,0x4f,0x4f,0x4f,0x30,0x30,0x30,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8f,0x8f,0x8f |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0x9c,0x9c,0x9c,0x87,0x87,0x87,0x6c,0x6c |
db 0x6c,0x4f,0x4f,0x4f,0x32,0x32,0x32,0x19,0x19,0x19 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff |
db 0xff,0xff,0x69,0x69,0x69,0x84,0x84,0x84,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0x92,0x92,0x92,0x79,0x79,0x79,0x59,0x59,0x59,0x3c |
db 0x3c,0x3c,0x24,0x24,0x24,0x11,0x11,0x11,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x37,0x37,0x37 |
db 0x5d,0x5d,0x5d,0x70,0x70,0x70,0x76,0x76,0x76,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0x75,0x75,0x75,0x51,0x51,0x51,0x31,0x31,0x31 |
db 0x19,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x16,0x16,0x16,0x2d,0x2d,0x2d,0x49,0x49 |
db 0x49,0x53,0x53,0x53,0x54,0x54,0x54,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x78 |
db 0x78,0x78,0x54,0x54,0x54,0x30,0x30,0x30,0x16,0x16 |
db 0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x0f,0x0f,0x0f,0x1f,0x1f,0x1f,0x30,0x30,0x30,0x33 |
db 0x33,0x33,0x33,0x33,0x33,0x3b,0x3b,0x3b,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0x62,0x62,0x62,0x3b,0x3b,0x3b,0x1c,0x1c,0x1c,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08 |
db 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x24,0x24,0x24,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6e,0x6e |
db 0x6e,0x48,0x48,0x48,0x25,0x25,0x25,0x0e,0x0e,0x0e |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00 |
db 0x00,0x00,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x29,0x29,0x29,0xff,0xff,0xff |
db 0xff,0xff,0xff,0x7c,0x7c,0x7c,0x71,0x71,0x71,0x50 |
db 0x50,0x50,0x2b,0x2b,0x2b,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x02,0x02,0x02,0x04,0x04,0x04,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x36,0x56,0x56 |
db 0x56,0x69,0x69,0x69,0x64,0x64,0x64,0x4a,0x4a,0x4a |
db 0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x05,0x05,0x05 |
db 0x00,0x00,0x00,0x21,0x21,0x21,0x39,0x39,0x39,0x49 |
db 0x49,0x49,0x48,0x48,0x48,0x35,0x35,0x35,0x1d,0x1d |
db 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x1d,0x1d,0x1d,0x27,0x27,0x27 |
db 0x27,0x27,0x27,0x1d,0x1d,0x1d,0x0f,0x0f,0x0f,0x06 |
db 0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00 |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
align 4 |
mousepointer: |
db 0x00,0x00,0x00,0x74,0x74,0x74,0x6e,0x6e,0x6e,0x6f |
db 0x6f,0x6f,0x71,0x71,0x71,0x75,0x75,0x75,0x79,0x79 |
db 0x79,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63 |
db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 |
db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0 |
db 0xc0,0xc0,0x00,0x00,0x00,0x54,0x54,0x54,0x57,0x57 |
db 0x57,0x5f,0x5f,0x5f,0x68,0x68,0x68,0x71,0x71,0x71 |
db 0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x47,0x47,0x47,0x50 |
db 0x50,0x50,0x5b,0x5b,0x5b,0x67,0x67,0x67,0x70,0x70 |
db 0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3f,0x3f,0x3f |
db 0x4b,0x4b,0x4b,0x59,0x59,0x59,0x66,0x66,0x66,0x70 |
db 0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e |
db 0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3a,0x3a |
db 0x3a,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66,0x66 |
db 0x70,0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e |
db 0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x39 |
db 0x39,0x39,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66 |
db 0x66,0x71,0x71,0x71,0x78,0x78,0x78,0x7c,0x7c,0x7c |
db 0x7e,0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00 |
db 0x39,0x39,0x39,0x4a,0x4a,0x4a,0x5a,0x5a,0x5a,0x68 |
db 0x68,0x68,0x72,0x72,0x72,0x79,0x79,0x79,0x7d,0x7d |
db 0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00 |
db 0x00,0x3c,0x3c,0x3c,0x4e,0x4e,0x4e,0x5e,0x5e,0x5e |
db 0x6b,0x6b,0x6b,0x75,0x75,0x75,0x7a,0x7a,0x7a,0x7e |
db 0x7e,0x7e,0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00 |
db 0x00,0x00,0x43,0x43,0x43,0x55,0x55,0x55,0x64,0x64 |
db 0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d |
db 0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0 |
db 0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x4e,0x4e,0x4e,0x5f,0x5f,0x5f,0x6d |
db 0x6d,0x6d,0x76,0x76,0x76,0x7c,0x7c,0x7c,0x80,0x80 |
db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 |
db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x14 |
db 0x14,0x14,0x1b,0x1b,0x1b,0x29,0x29,0x29,0x3a,0x3a |
db 0x3a,0x4c,0x4c,0x4c,0x5d,0x5d,0x5d,0x6c,0x6c,0x6c |
db 0x75,0x75,0x75,0x7b,0x7b,0x7b,0x80,0x80,0x80,0xc0 |
db 0xc0,0xc0,0x00,0x00,0x00,0x2f,0x2f,0x2f,0x80,0x80 |
db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 |
db 0x21,0x21,0x21,0x2e,0x2e,0x2e,0x40,0x40,0x40,0x52 |
db 0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f,0x77,0x77 |
db 0x77,0x7c,0x7c,0x7c,0x80,0x80,0x80,0x00,0x00,0x00 |
db 0x47,0x47,0x47,0x3b,0x3b,0x3b,0x80,0x80,0x80,0xff |
db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x25,0x25 |
db 0x25,0x30,0x30,0x30,0x42,0x42,0x42,0x54,0x54,0x54 |
db 0x64,0x64,0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d |
db 0x7d,0x7d,0x00,0x00,0x00,0x62,0x62,0x62,0x52,0x52 |
db 0x52,0x4a,0x4a,0x4a,0x43,0x43,0x43,0x80,0x80,0x80 |
db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x33 |
db 0x33,0x33,0x42,0x42,0x42,0x54,0x54,0x54,0x64,0x64 |
db 0x64,0x71,0x71,0x71,0x79,0x79,0x79,0x7d,0x7d,0x7d |
db 0x72,0x72,0x72,0x6b,0x6b,0x6b,0x5f,0x5f,0x5f,0x5a |
db 0x5a,0x5a,0x54,0x54,0x54,0x80,0x80,0x80,0xff,0xff |
db 0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x35,0x35,0x35 |
db 0x41,0x41,0x41,0x53,0x53,0x53,0x63,0x63,0x63,0x70 |
db 0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d,0x77,0x77 |
db 0x77,0x73,0x73,0x73,0x6c,0x6c,0x6c,0x68,0x68,0x68 |
db 0x62,0x62,0x62,0x5a,0x5a,0x5a,0x80,0x80,0x80,0xff |
db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x41,0x41 |
db 0x41,0x52,0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f |
db 0x78,0x78,0x78,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x79 |
db 0x79,0x79,0x74,0x74,0x74,0x72,0x72,0x72,0x6e,0x6e |
db 0x6e,0x66,0x66,0x66,0x80,0x80,0x80,0xc0,0xc0,0xc0 |
db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x44,0x44,0x44,0x52 |
db 0x52,0x52,0x62,0x62,0x62,0x6e,0x6e,0x6e,0x77,0x77 |
db 0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7c,0x7c,0x7c |
db 0x7a,0x7a,0x7a,0x79,0x79,0x79,0x75,0x75,0x75,0x6f |
db 0x6f,0x6f,0x65,0x65,0x65,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x48,0x48,0x48,0x4b,0x4b,0x4b,0x56,0x56,0x56 |
db 0x65,0x65,0x65,0x70,0x70,0x70,0x78,0x78,0x78,0x7d |
db 0x7d,0x7d,0x80,0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e |
db 0x7e,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76,0x76 |
db 0x6f,0x6f,0x6f,0x65,0x65,0x65,0x5c,0x5c,0x5c,0x56 |
db 0x56,0x56,0x58,0x58,0x58,0x60,0x60,0x60,0x6b,0x6b |
db 0x6b,0x73,0x73,0x73,0x7a,0x7a,0x7a,0x7d,0x7d,0x7d |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7f |
db 0x7f,0x7f,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76 |
db 0x76,0x70,0x70,0x70,0x6a,0x6a,0x6a,0x66,0x66,0x66 |
db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 |
db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x77 |
db 0x77,0x77,0x73,0x73,0x73,0x71,0x71,0x71,0x71,0x71 |
db 0x71,0x74,0x74,0x74,0x78,0x78,0x78,0x7b,0x7b,0x7b |
db 0x7d,0x7d,0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7c,0x7c,0x7c |
db 0x7a,0x7a,0x7a,0x78,0x78,0x78,0x78,0x78,0x78,0x7a |
db 0x7a,0x7a,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7f,0x7f |
db 0x7f,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 |
db 0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e,0x7e,0x7e,0x7e |
db 0x7e,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e |
db 0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 |
db 0x80,0x80 |
mousepointer1: |
db 0xff,0xff,0xff,0x06,0x06,0x06,0x0a,0x0a |
db 0x0a,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x19,0x16 |
db 0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2e,0x2e,0x2e |
db 0x23,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f |
db 0x3f,0x29,0x29,0x29,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x47 |
db 0x47,0x47,0x2c,0x2c,0x2c,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0x47,0x47,0x47,0x29,0x29,0x29 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0x40,0x40,0x40,0x23,0x23 |
db 0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xaa,0xaa,0xaa,0x9f,0x9f,0x9f,0x8c,0x8c,0x8c |
db 0x70,0x70,0x70,0x4f,0x4f,0x4f,0x30,0x30,0x30,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8f,0x8f,0x8f |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0xff,0x9c,0x9c,0x9c,0x87,0x87,0x87,0x6c,0x6c |
db 0x6c,0x4f,0x4f,0x4f,0x32,0x32,0x32,0x19,0x19,0x19 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff |
db 0xff,0xff,0x69,0x69,0x69,0x84,0x84,0x84,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0x92,0x92,0x92,0x79,0x79,0x79,0x59,0x59,0x59,0x3c |
db 0x3c,0x3c,0x24,0x24,0x24,0x11,0x11,0x11,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x37,0x37,0x37 |
db 0x5d,0x5d,0x5d,0x70,0x70,0x70,0x76,0x76,0x76,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0xff,0x75,0x75,0x75,0x51,0x51,0x51,0x31,0x31,0x31 |
db 0x19,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x16,0x16,0x16,0x2d,0x2d,0x2d,0x49,0x49 |
db 0x49,0x53,0x53,0x53,0x54,0x54,0x54,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x78 |
db 0x78,0x78,0x54,0x54,0x54,0x30,0x30,0x30,0x16,0x16 |
db 0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x0f,0x0f,0x0f,0x1f,0x1f,0x1f,0x30,0x30,0x30,0x33 |
db 0x33,0x33,0x33,0x33,0x33,0x3b,0x3b,0x3b,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff |
db 0x62,0x62,0x62,0x3b,0x3b,0x3b,0x1c,0x1c,0x1c,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08 |
db 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x24,0x24,0x24,0xff,0xff,0xff,0xff |
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6e,0x6e |
db 0x6e,0x48,0x48,0x48,0x25,0x25,0x25,0x0e,0x0e,0x0e |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00 |
db 0x00,0x00,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x29,0x29,0x29,0xff,0xff,0xff |
db 0xff,0xff,0xff,0x7c,0x7c,0x7c,0x71,0x71,0x71,0x50 |
db 0x50,0x50,0x2b,0x2b,0x2b,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x02,0x02,0x02,0x04,0x04,0x04,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x36,0x56,0x56 |
db 0x56,0x69,0x69,0x69,0x64,0x64,0x64,0x4a,0x4a,0x4a |
db 0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x05,0x05,0x05 |
db 0x00,0x00,0x00,0x21,0x21,0x21,0x39,0x39,0x39,0x49 |
db 0x49,0x49,0x48,0x48,0x48,0x35,0x35,0x35,0x1d,0x1d |
db 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x1d,0x1d,0x1d,0x27,0x27,0x27 |
db 0x27,0x27,0x27,0x1d,0x1d,0x1d,0x0f,0x0f,0x0f,0x06 |
db 0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 |
db 0x00,0x00,0x00,0x00 |
endg |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/gui/skincode.inc |
---|
1,460 → 1,466 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
include "skindata.inc" |
;skin_data = 0x00778000 |
read_skin_file: |
stdcall load_file, ebx |
test eax, eax |
jz .notfound |
cmp dword [eax], 'SKIN' |
jnz .noskin |
cmp ebx, 32*1024 |
jb @f |
mov ebx, 32*1024 |
@@: |
lea ecx, [ebx+3] |
shr ecx, 2 |
mov esi, eax |
mov edi, skin_data |
rep movsd |
stdcall kernel_free, eax |
call parse_skin_data |
xor eax, eax |
ret |
.notfound: |
xor eax, eax |
inc eax |
ret |
.noskin: |
stdcall kernel_free, eax |
push 2 |
pop eax |
ret |
struct SKIN_HEADER |
.ident dd ? |
.version dd ? |
.params dd ? |
.buttons dd ? |
.bitmaps dd ? |
ends |
struct SKIN_PARAMS |
.skin_height dd ? |
.margin.right dw ? |
.margin.left dw ? |
.margin.bottom dw ? |
.margin.top dw ? |
.colors.inner dd ? |
.colors.outer dd ? |
.colors.frame dd ? |
.colors_1.inner dd ? |
.colors_1.outer dd ? |
.colors_1.frame dd ? |
.dtp.size dd ? |
.dtp.data db 40 dup (?) |
ends |
struct SKIN_BUTTONS |
.type dd ? |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
include "skindata.inc" |
;skin_data = 0x00778000 |
read_skin_file: |
stdcall load_file, ebx |
test eax, eax |
jz .notfound |
cmp dword [eax], 'SKIN' |
jnz .noskin |
cmp ebx, 32*1024 |
jb @f |
mov ebx, 32*1024 |
@@: |
lea ecx, [ebx+3] |
shr ecx, 2 |
mov esi, eax |
mov edi, skin_data |
rep movsd |
stdcall kernel_free, eax |
call parse_skin_data |
xor eax, eax |
ret |
.notfound: |
xor eax, eax |
inc eax |
ret |
.noskin: |
stdcall kernel_free, eax |
push 2 |
pop eax |
ret |
struct SKIN_HEADER |
.ident dd ? |
.version dd ? |
.params dd ? |
.buttons dd ? |
.bitmaps dd ? |
ends |
struct SKIN_PARAMS |
.skin_height dd ? |
.margin.right dw ? |
.margin.left dw ? |
.margin.bottom dw ? |
.margin.top dw ? |
.colors.inner dd ? |
.colors.outer dd ? |
.colors.frame dd ? |
.colors_1.inner dd ? |
.colors_1.outer dd ? |
.colors_1.frame dd ? |
.dtp.size dd ? |
.dtp.data db 40 dup (?) |
ends |
struct SKIN_BUTTONS |
.type dd ? |
.pos: |
.left dw ? |
.top dw ? |
.left dw ? |
.top dw ? |
.size: |
.width dw ? |
.height dw ? |
ends |
struct SKIN_BITMAPS |
.kind dw ? |
.type dw ? |
.data dd ? |
ends |
load_default_skin: |
mov [_skinh],22 |
mov ebx,_skin_file_default |
call read_skin_file |
ret |
parse_skin_data: |
mov ebp,skin_data |
cmp [ebp+SKIN_HEADER.ident],'SKIN' |
jne .exit |
mov edi,skin_udata |
mov ecx,(skin_udata.end-skin_udata)/4 |
xor eax,eax |
cld |
rep stosd |
mov ebx,[ebp+SKIN_HEADER.params] |
add ebx,skin_data |
mov eax,[ebx+SKIN_PARAMS.skin_height] |
mov [_skinh],eax |
mov eax,[ebx+SKIN_PARAMS.colors.inner] |
mov [skin_active.colors.inner],eax |
mov eax,[ebx+SKIN_PARAMS.colors.outer] |
mov [skin_active.colors.outer],eax |
mov eax,[ebx+SKIN_PARAMS.colors.frame] |
mov [skin_active.colors.frame],eax |
mov eax,[ebx+SKIN_PARAMS.colors_1.inner] |
mov [skin_inactive.colors.inner],eax |
mov eax,[ebx+SKIN_PARAMS.colors_1.outer] |
mov [skin_inactive.colors.outer],eax |
mov eax,[ebx+SKIN_PARAMS.colors_1.frame] |
mov [skin_inactive.colors.frame],eax |
lea esi,[ebx+SKIN_PARAMS.dtp.data] |
mov edi,common_colours |
mov ecx,[ebx+SKIN_PARAMS.dtp.size] |
and ecx,127 |
rep movsb |
mov eax,dword[ebx+SKIN_PARAMS.margin.right] |
mov dword[_skinmargins+0],eax |
mov eax,dword[ebx+SKIN_PARAMS.margin.bottom] |
mov dword[_skinmargins+4],eax |
mov ebx,[ebp+SKIN_HEADER.bitmaps] |
add ebx,skin_data |
.lp1: cmp dword[ebx],0 |
je .end_bitmaps |
movzx eax,[ebx+SKIN_BITMAPS.kind] |
movzx ecx,[ebx+SKIN_BITMAPS.type] |
dec eax |
jnz .not_left |
xor eax,eax |
mov edx,skin_active.left.data |
or ecx,ecx |
jnz @f |
mov edx,skin_inactive.left.data |
@@: jmp .next_bitmap |
.not_left: |
dec eax |
jnz .not_oper |
mov esi,[ebx+SKIN_BITMAPS.data] |
add esi,skin_data |
mov eax,[esi+0] |
neg eax |
mov edx,skin_active.oper.data |
or ecx,ecx |
jnz @f |
mov edx,skin_inactive.oper.data |
@@: jmp .next_bitmap |
.not_oper: |
dec eax |
jnz .not_base |
mov eax,[skin_active.left.width] |
mov edx,skin_active.base.data |
or ecx,ecx |
jnz @f |
mov eax,[skin_inactive.left.width] |
mov edx,skin_inactive.base.data |
@@: jmp .next_bitmap |
.not_base: |
add ebx,8 |
jmp .lp1 |
.next_bitmap: |
mov ecx,[ebx+SKIN_BITMAPS.data] |
add ecx,skin_data |
mov [edx+4],eax |
mov eax,[ecx+0] |
mov [edx+8],eax |
add ecx,8 |
mov [edx+0],ecx |
add ebx,8 |
jmp .lp1 |
.end_bitmaps: |
mov ebx,[ebp+SKIN_HEADER.buttons] |
add ebx,skin_data |
.lp2: cmp dword[ebx],0 |
je .end_buttons |
mov eax,[ebx+SKIN_BUTTONS.type] |
dec eax |
jnz .not_close |
mov edx,skin_btn_close |
jmp .next_button |
.not_close: |
dec eax |
jnz .not_minimize |
mov edx,skin_btn_minimize |
jmp .next_button |
.not_minimize: |
add ebx,12 |
jmp .lp2 |
.next_button: |
movsx eax,[ebx+SKIN_BUTTONS.left] |
mov [edx+SKIN_BUTTON.left],eax |
movsx eax,[ebx+SKIN_BUTTONS.top] |
mov [edx+SKIN_BUTTON.top],eax |
movsx eax,[ebx+SKIN_BUTTONS.width] |
mov [edx+SKIN_BUTTON.width],eax |
movsx eax,[ebx+SKIN_BUTTONS.height] |
mov [edx+SKIN_BUTTON.height],eax |
add ebx,12 |
jmp .lp2 |
.end_buttons: |
.exit: |
ret |
sys_putimage_with_check: |
or ebx,ebx |
jz @f |
call sys_putimage.forced |
@@: ret |
drawwindow_IV_caption: |
mov ebp,skin_active |
or al,al |
jnz @f |
mov ebp,skin_inactive |
@@: |
mov esi,[esp+4] |
mov eax,[esi+WDATA.box.width] ; window width |
mov edx,[ebp+SKIN_DATA.left.left] |
shl edx,16 |
mov ecx,[ebp+SKIN_DATA.left.width] |
shl ecx,16 |
add ecx,[_skinh] |
mov ebx, [ebp+SKIN_DATA.left.data] |
call sys_putimage_with_check |
mov esi,[esp+4] |
mov eax,[esi+WDATA.box.width] |
sub eax,[ebp+SKIN_DATA.left.width] |
sub eax,[ebp+SKIN_DATA.oper.width] |
cmp eax,[ebp+SKIN_DATA.base.left] |
jng .non_base |
xor edx,edx |
mov ecx,[ebp+SKIN_DATA.base.width] |
jecxz .non_base |
div ecx |
inc eax |
mov ebx,[ebp+SKIN_DATA.base.data] |
mov ecx,[ebp+SKIN_DATA.base.width] |
shl ecx,16 |
add ecx,[_skinh] |
mov edx,[ebp+SKIN_DATA.base.left] |
sub edx,[ebp+SKIN_DATA.base.width] |
shl edx,16 |
.baseskinloop: |
shr edx,16 |
add edx,[ebp+SKIN_DATA.base.width] |
shl edx,16 |
push eax ebx ecx edx |
call sys_putimage_with_check |
pop edx ecx ebx eax |
dec eax |
jnz .baseskinloop |
.non_base: |
mov esi,[esp+4] |
mov edx,[esi+WDATA.box.width] |
sub edx,[ebp+SKIN_DATA.oper.width] |
inc edx |
shl edx,16 |
mov ebx,[ebp+SKIN_DATA.oper.data] |
mov ecx,[ebp+SKIN_DATA.oper.width] |
shl ecx,16 |
add ecx,[_skinh] |
call sys_putimage_with_check |
ret |
;//mike.dld, 2006-08-02 ] |
drawwindow_IV: |
;param1 - aw_yes |
pusha |
push edx |
mov edi,edx |
mov ebp,skin_active |
cmp byte [esp+32+4+4],0 |
jne @f |
mov ebp,skin_inactive |
@@: |
mov eax,[edi+WDATA.box.left] |
shl eax,16 |
mov ax,word [edi+WDATA.box.left] |
add ax,word [edi+WDATA.box.width] |
mov ebx,[edi+WDATA.box.top] |
shl ebx,16 |
mov bx,word [edi+WDATA.box.top] |
add bx,word [edi+WDATA.box.height] |
; mov esi,[edi+24] |
; shr esi,1 |
; and esi,0x007f7f7f |
mov esi,[ebp+SKIN_DATA.colors.outer] |
call draw_rectangle |
mov ecx,3 |
_dw3l: |
add eax,1*65536-1 |
add ebx,1*65536-1 |
test ax,ax |
js no_skin_add_button |
test bx,bx |
js no_skin_add_button |
mov esi,[ebp+SKIN_DATA.colors.frame] ;[edi+24] |
call draw_rectangle |
dec ecx |
jnz _dw3l |
mov esi,[ebp+SKIN_DATA.colors.inner] |
add eax,1*65536-1 |
add ebx,1*65536-1 |
test ax,ax |
js no_skin_add_button |
test bx,bx |
js no_skin_add_button |
call draw_rectangle |
cmp dword[skin_data],'SKIN' |
je @f |
xor eax,eax |
xor ebx,ebx |
mov esi,[esp] |
mov ecx,[esi+WDATA.box.width] |
inc ecx |
mov edx,[_skinh] |
mov edi,[common_colours+4] ; standard grab color |
call [drawbar] |
jmp draw_clientbar |
@@: |
mov al,[esp+32+4+4] |
call drawwindow_IV_caption |
draw_clientbar: |
mov esi,[esp] |
mov edx,[esi+WDATA.box.top] ; WORK AREA |
add edx,21+5 |
mov ebx,[esi+WDATA.box.top] |
add ebx,[esi+WDATA.box.height] |
cmp edx,ebx |
jg _noinside2 |
mov eax,5 |
mov ebx,[_skinh] |
mov ecx,[esi+WDATA.box.width] |
mov edx,[esi+WDATA.box.height] |
sub ecx,4 |
sub edx,4 |
mov edi,[esi+WDATA.cl_workarea] |
test edi,0x40000000 |
jnz _noinside2 |
call [drawbar] |
_noinside2: |
cmp dword[skin_data],'SKIN' |
jne no_skin_add_button |
;* close button |
mov edi,[BTN_ADDR] |
movzx eax,word [edi] |
cmp eax,1000 |
jge no_skin_add_button |
inc eax |
mov [edi],ax |
shl eax,4 |
add eax,edi |
mov bx,[CURRENT_TASK] |
mov [eax],bx |
add eax,2 ; save button id number |
mov bx,1 |
mov [eax],bx |
add eax,2 ; x start |
xor ebx,ebx |
cmp [skin_btn_close.left],0 |
jge _bCx_at_right |
mov ebx,[esp] |
mov ebx,[ebx+WDATA.box.width] |
inc ebx |
_bCx_at_right: |
add ebx,[skin_btn_close.left] |
mov [eax],bx |
add eax,2 ; x size |
mov ebx,[skin_btn_close.width] |
dec ebx |
mov [eax],bx |
add eax,2 ; y start |
mov ebx,[skin_btn_close.top] |
mov [eax],bx |
add eax,2 ; y size |
mov ebx,[skin_btn_close.height] |
dec ebx |
mov [eax],bx |
;* minimize button |
mov edi,[BTN_ADDR] |
movzx eax,word [edi] |
cmp eax,1000 |
jge no_skin_add_button |
inc eax |
mov [edi],ax |
shl eax,4 |
add eax,edi |
mov bx,[CURRENT_TASK] |
mov [eax],bx |
add eax,2 ; save button id number |
mov bx,65535 ;999 |
mov [eax],bx |
add eax,2 ; x start |
xor ebx,ebx |
cmp [skin_btn_minimize.left],0 |
jge _bMx_at_right |
mov ebx,[esp] |
mov ebx,[ebx+WDATA.box.width] |
inc ebx |
_bMx_at_right: |
add ebx,[skin_btn_minimize.left] |
mov [eax],bx |
add eax,2 ; x size |
mov ebx,[skin_btn_minimize.width] |
dec ebx |
mov [eax],bx |
add eax,2 ; y start |
mov ebx,[skin_btn_minimize.top] |
mov [eax],bx |
add eax,2 ; y size |
mov ebx,[skin_btn_minimize.height] |
dec ebx |
mov [eax],bx |
no_skin_add_button: |
pop edi |
popa |
ret 4 |
.width dw ? |
.height dw ? |
ends |
struct SKIN_BITMAPS |
.kind dw ? |
.type dw ? |
.data dd ? |
ends |
load_default_skin: |
mov [_skinh], 22 |
mov ebx, _skin_file_default |
call read_skin_file |
ret |
parse_skin_data: |
mov ebp, skin_data |
cmp [ebp+SKIN_HEADER.ident], 'SKIN' |
jne .exit |
mov edi, skin_udata |
mov ecx, (skin_udata.end-skin_udata)/4 |
xor eax, eax |
cld |
rep stosd |
mov ebx, [ebp+SKIN_HEADER.params] |
add ebx, skin_data |
mov eax, [ebx+SKIN_PARAMS.skin_height] |
mov [_skinh], eax |
mov eax, [ebx+SKIN_PARAMS.colors.inner] |
mov [skin_active.colors.inner], eax |
mov eax, [ebx+SKIN_PARAMS.colors.outer] |
mov [skin_active.colors.outer], eax |
mov eax, [ebx+SKIN_PARAMS.colors.frame] |
mov [skin_active.colors.frame], eax |
mov eax, [ebx+SKIN_PARAMS.colors_1.inner] |
mov [skin_inactive.colors.inner], eax |
mov eax, [ebx+SKIN_PARAMS.colors_1.outer] |
mov [skin_inactive.colors.outer], eax |
mov eax, [ebx+SKIN_PARAMS.colors_1.frame] |
mov [skin_inactive.colors.frame], eax |
lea esi, [ebx+SKIN_PARAMS.dtp.data] |
mov edi, common_colours |
mov ecx, [ebx+SKIN_PARAMS.dtp.size] |
and ecx, 127 |
rep movsb |
mov eax, dword[ebx+SKIN_PARAMS.margin.right] |
mov dword[_skinmargins+0], eax |
mov eax, dword[ebx+SKIN_PARAMS.margin.bottom] |
mov dword[_skinmargins+4], eax |
mov ebx, [ebp+SKIN_HEADER.bitmaps] |
add ebx, skin_data |
.lp1: |
cmp dword[ebx], 0 |
je .end_bitmaps |
movzx eax, [ebx+SKIN_BITMAPS.kind] |
movzx ecx, [ebx+SKIN_BITMAPS.type] |
dec eax |
jnz .not_left |
xor eax, eax |
mov edx, skin_active.left.data |
or ecx, ecx |
jnz @f |
mov edx, skin_inactive.left.data |
@@: |
jmp .next_bitmap |
.not_left: |
dec eax |
jnz .not_oper |
mov esi, [ebx+SKIN_BITMAPS.data] |
add esi, skin_data |
mov eax, [esi+0] |
neg eax |
mov edx, skin_active.oper.data |
or ecx, ecx |
jnz @f |
mov edx, skin_inactive.oper.data |
@@: |
jmp .next_bitmap |
.not_oper: |
dec eax |
jnz .not_base |
mov eax, [skin_active.left.width] |
mov edx, skin_active.base.data |
or ecx, ecx |
jnz @f |
mov eax, [skin_inactive.left.width] |
mov edx, skin_inactive.base.data |
@@: |
jmp .next_bitmap |
.not_base: |
add ebx, 8 |
jmp .lp1 |
.next_bitmap: |
mov ecx, [ebx+SKIN_BITMAPS.data] |
add ecx, skin_data |
mov [edx+4], eax |
mov eax, [ecx+0] |
mov [edx+8], eax |
add ecx, 8 |
mov [edx+0], ecx |
add ebx, 8 |
jmp .lp1 |
.end_bitmaps: |
mov ebx, [ebp+SKIN_HEADER.buttons] |
add ebx, skin_data |
.lp2: |
cmp dword[ebx], 0 |
je .end_buttons |
mov eax, [ebx+SKIN_BUTTONS.type] |
dec eax |
jnz .not_close |
mov edx, skin_btn_close |
jmp .next_button |
.not_close: |
dec eax |
jnz .not_minimize |
mov edx, skin_btn_minimize |
jmp .next_button |
.not_minimize: |
add ebx, 12 |
jmp .lp2 |
.next_button: |
movsx eax, [ebx+SKIN_BUTTONS.left] |
mov [edx+SKIN_BUTTON.left], eax |
movsx eax, [ebx+SKIN_BUTTONS.top] |
mov [edx+SKIN_BUTTON.top], eax |
movsx eax, [ebx+SKIN_BUTTONS.width] |
mov [edx+SKIN_BUTTON.width], eax |
movsx eax, [ebx+SKIN_BUTTONS.height] |
mov [edx+SKIN_BUTTON.height], eax |
add ebx, 12 |
jmp .lp2 |
.end_buttons: |
.exit: |
ret |
sys_putimage_with_check: |
or ebx, ebx |
jz @f |
call sys_putimage.forced |
@@: |
ret |
drawwindow_IV_caption: |
mov ebp, skin_active |
or al, al |
jnz @f |
mov ebp, skin_inactive |
@@: |
mov esi, [esp+4] |
mov eax, [esi+WDATA.box.width] ; window width |
mov edx, [ebp+SKIN_DATA.left.left] |
shl edx, 16 |
mov ecx, [ebp+SKIN_DATA.left.width] |
shl ecx, 16 |
add ecx, [_skinh] |
mov ebx, [ebp+SKIN_DATA.left.data] |
call sys_putimage_with_check |
mov esi, [esp+4] |
mov eax, [esi+WDATA.box.width] |
sub eax, [ebp+SKIN_DATA.left.width] |
sub eax, [ebp+SKIN_DATA.oper.width] |
cmp eax, [ebp+SKIN_DATA.base.left] |
jng .non_base |
xor edx, edx |
mov ecx, [ebp+SKIN_DATA.base.width] |
jecxz .non_base |
div ecx |
inc eax |
mov ebx, [ebp+SKIN_DATA.base.data] |
mov ecx, [ebp+SKIN_DATA.base.width] |
shl ecx, 16 |
add ecx, [_skinh] |
mov edx, [ebp+SKIN_DATA.base.left] |
sub edx, [ebp+SKIN_DATA.base.width] |
shl edx, 16 |
.baseskinloop: |
shr edx, 16 |
add edx, [ebp+SKIN_DATA.base.width] |
shl edx, 16 |
push eax ebx ecx edx |
call sys_putimage_with_check |
pop edx ecx ebx eax |
dec eax |
jnz .baseskinloop |
.non_base: |
mov esi, [esp+4] |
mov edx, [esi+WDATA.box.width] |
sub edx, [ebp+SKIN_DATA.oper.width] |
inc edx |
shl edx, 16 |
mov ebx, [ebp+SKIN_DATA.oper.data] |
mov ecx, [ebp+SKIN_DATA.oper.width] |
shl ecx, 16 |
add ecx, [_skinh] |
call sys_putimage_with_check |
ret |
;//mike.dld, 2006-08-02 ] |
drawwindow_IV: |
;param1 - aw_yes |
pusha |
push edx |
mov edi, edx |
mov ebp, skin_active |
cmp byte [esp+32+4+4], 0 |
jne @f |
mov ebp, skin_inactive |
@@: |
mov eax, [edi+WDATA.box.left] |
shl eax, 16 |
mov ax, word [edi+WDATA.box.left] |
add ax, word [edi+WDATA.box.width] |
mov ebx, [edi+WDATA.box.top] |
shl ebx, 16 |
mov bx, word [edi+WDATA.box.top] |
add bx, word [edi+WDATA.box.height] |
; mov esi,[edi+24] |
; shr esi,1 |
; and esi,0x007f7f7f |
mov esi, [ebp+SKIN_DATA.colors.outer] |
call draw_rectangle |
mov ecx, 3 |
_dw3l: |
add eax, 1*65536-1 |
add ebx, 1*65536-1 |
test ax, ax |
js no_skin_add_button |
test bx, bx |
js no_skin_add_button |
mov esi, [ebp+SKIN_DATA.colors.frame];[edi+24] |
call draw_rectangle |
dec ecx |
jnz _dw3l |
mov esi, [ebp+SKIN_DATA.colors.inner] |
add eax, 1*65536-1 |
add ebx, 1*65536-1 |
test ax, ax |
js no_skin_add_button |
test bx, bx |
js no_skin_add_button |
call draw_rectangle |
cmp dword[skin_data], 'SKIN' |
je @f |
xor eax, eax |
xor ebx, ebx |
mov esi, [esp] |
mov ecx, [esi+WDATA.box.width] |
inc ecx |
mov edx, [_skinh] |
mov edi, [common_colours+4]; standard grab color |
call [drawbar] |
jmp draw_clientbar |
@@: |
mov al, [esp+32+4+4] |
call drawwindow_IV_caption |
draw_clientbar: |
mov esi, [esp] |
mov edx, [esi+WDATA.box.top] ; WORK AREA |
add edx, 21+5 |
mov ebx, [esi+WDATA.box.top] |
add ebx, [esi+WDATA.box.height] |
cmp edx, ebx |
jg _noinside2 |
mov eax, 5 |
mov ebx, [_skinh] |
mov ecx, [esi+WDATA.box.width] |
mov edx, [esi+WDATA.box.height] |
sub ecx, 4 |
sub edx, 4 |
mov edi, [esi+WDATA.cl_workarea] |
test edi, 0x40000000 |
jnz _noinside2 |
call [drawbar] |
_noinside2: |
cmp dword[skin_data], 'SKIN' |
jne no_skin_add_button |
;* close button |
mov edi, [BTN_ADDR] |
movzx eax, word [edi] |
cmp eax, 1000 |
jge no_skin_add_button |
inc eax |
mov [edi], ax |
shl eax, 4 |
add eax, edi |
mov bx, [CURRENT_TASK] |
mov [eax], bx |
add eax, 2 ; save button id number |
mov bx, 1 |
mov [eax], bx |
add eax, 2 ; x start |
xor ebx, ebx |
cmp [skin_btn_close.left], 0 |
jge _bCx_at_right |
mov ebx, [esp] |
mov ebx, [ebx+WDATA.box.width] |
inc ebx |
_bCx_at_right: |
add ebx, [skin_btn_close.left] |
mov [eax], bx |
add eax, 2 ; x size |
mov ebx, [skin_btn_close.width] |
dec ebx |
mov [eax], bx |
add eax, 2 ; y start |
mov ebx, [skin_btn_close.top] |
mov [eax], bx |
add eax, 2 ; y size |
mov ebx, [skin_btn_close.height] |
dec ebx |
mov [eax], bx |
;* minimize button |
mov edi, [BTN_ADDR] |
movzx eax, word [edi] |
cmp eax, 1000 |
jge no_skin_add_button |
inc eax |
mov [edi], ax |
shl eax, 4 |
add eax, edi |
mov bx, [CURRENT_TASK] |
mov [eax], bx |
add eax, 2 ; save button id number |
mov bx, 65535;999 |
mov [eax], bx |
add eax, 2 ; x start |
xor ebx, ebx |
cmp [skin_btn_minimize.left], 0 |
jge _bMx_at_right |
mov ebx, [esp] |
mov ebx, [ebx+WDATA.box.width] |
inc ebx |
_bMx_at_right: |
add ebx, [skin_btn_minimize.left] |
mov [eax], bx |
add eax, 2 ; x size |
mov ebx, [skin_btn_minimize.width] |
dec ebx |
mov [eax], bx |
add eax, 2 ; y start |
mov ebx, [skin_btn_minimize.top] |
mov [eax], bx |
add eax, 2 ; y size |
mov ebx, [skin_btn_minimize.height] |
dec ebx |
mov [eax], bx |
no_skin_add_button: |
pop edi |
popa |
ret 4 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/gui/skindata.inc |
---|
1,64 → 1,64 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; |
; WINDOW SKIN DATA |
; |
iglobal |
_skin_file_default db '/sys/DEFAULT.SKN',0 |
endg |
struct SKIN_DATA |
.colors.inner dd ? |
.colors.outer dd ? |
.colors.frame dd ? |
.left.data dd ? |
.left.left dd ? |
.left.width dd ? |
.oper.data dd ? |
.oper.left dd ? |
.oper.width dd ? |
.base.data dd ? |
.base.left dd ? |
.base.width dd ? |
ends |
struct SKIN_BUTTON |
.left dd ? |
.top dd ? |
.width dd ? |
.height dd ? |
ends |
uglobal |
align 4 |
skin_udata: |
_skinh dd ? |
_skinmargins: ; rw 4 |
.right dw ? |
.left dw ? |
.bottom dw ? |
.top dw ? |
skin_btn_close SKIN_BUTTON |
skin_btn_minimize SKIN_BUTTON |
skin_active SKIN_DATA |
skin_inactive SKIN_DATA |
align 4 |
skin_udata.end: |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; |
; WINDOW SKIN DATA |
; |
iglobal |
_skin_file_default db '/sys/DEFAULT.SKN',0 |
endg |
struct SKIN_DATA |
.colors.inner dd ? |
.colors.outer dd ? |
.colors.frame dd ? |
.left.data dd ? |
.left.left dd ? |
.left.width dd ? |
.oper.data dd ? |
.oper.left dd ? |
.oper.width dd ? |
.base.data dd ? |
.base.left dd ? |
.base.width dd ? |
ends |
struct SKIN_BUTTON |
.left dd ? |
.top dd ? |
.width dd ? |
.height dd ? |
ends |
uglobal |
align 4 |
skin_udata: |
_skinh dd ? |
_skinmargins: ; rw 4 |
.right dw ? |
.left dw ? |
.bottom dw ? |
.top dw ? |
skin_btn_close SKIN_BUTTON |
skin_btn_minimize SKIN_BUTTON |
skin_active SKIN_DATA |
skin_inactive SKIN_DATA |
align 4 |
skin_udata.end: |
endg |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/gui/window.inc |
---|
56,7 → 56,8 |
call drawwindow_I |
jmp window._.draw_window_caption.2 |
@@: dec al |
@@: |
dec al |
jnz @f |
; type II - only reserve area, no draw |
65,7 → 66,8 |
call [draw_pointer] |
jmp .exit |
@@: dec al |
@@: |
dec al |
jnz @f |
; type III - new style |
73,7 → 75,8 |
jmp window._.draw_window_caption.2 |
; type IV & V - skinned window (resizable & not) |
@@: mov eax, [TASK_COUNT] |
@@: |
mov eax, [TASK_COUNT] |
movzx eax, word[WIN_POS + eax * 2] |
cmp eax, [CURRENT_TASK] |
setz al |
133,7 → 136,8 |
cmp ebx, .sizeof.ftable / 4 |
ja @f |
jmp [.ftable + ebx * 4] |
@@: ret |
@@: |
ret |
align 4 |
167,7 → 171,7 |
and edx, 127 |
mov edi, common_colours |
mov ecx, edx |
rep movsb |
rep movsb |
mov [windowtypechanged], ebx |
ret |
177,7 → 181,7 |
and edx, 127 |
mov esi, common_colours |
mov ecx, edx |
rep movsb |
rep movsb |
ret |
align 4 |
210,11 → 214,13 |
or eax, eax |
jge @f |
xor eax, eax |
@@: mov [screen_workarea.left], eax |
@@: |
mov [screen_workarea.left], eax |
cmp ebx, edi |
jle @f |
mov ebx, edi |
@@: mov [screen_workarea.right], ebx |
@@: |
mov [screen_workarea.right], ebx |
.check_horizontal: |
mov edi, [Screen_Max_Y] |
227,11 → 233,13 |
or eax, eax |
jge @f |
xor eax, eax |
@@: mov [screen_workarea.top], eax |
@@: |
mov [screen_workarea.top], eax |
cmp ebx, edi |
jle @f |
mov ebx, edi |
@@: mov [screen_workarea.bottom], ebx |
@@: |
mov [screen_workarea.bottom], ebx |
.check_if_redraw_needed: |
or esi, esi |
328,17 → 336,21 |
cmp ebx, -1 |
jne @f |
mov ebx, [edi + WDATA.box.left] |
@@: cmp ecx, -1 |
@@: |
cmp ecx, -1 |
jne @f |
mov ecx, [edi + WDATA.box.top] |
@@: cmp edx, -1 |
@@: |
cmp edx, -1 |
jne @f |
mov edx, [edi + WDATA.box.width] |
@@: cmp esi, -1 |
@@: |
cmp esi, -1 |
jne @f |
mov esi, [edi + WDATA.box.height] |
@@: push esi edx ecx ebx |
@@: |
push esi edx ecx ebx |
mov eax, esp |
mov bl, [edi + WDATA.fl_wstate] |
call window._.set_window_box |
399,7 → 411,8 |
push eax ecx |
xor eax, eax |
mov ecx, WIN_STACK |
@@: inc eax |
@@: |
inc eax |
add ecx, 2 |
; process no |
mov [ecx + 0x000], ax |
466,17 → 479,21 |
cmp eax, [esp + RECT.left] |
jae @f |
mov eax, [esp + RECT.left] |
@@: cmp ebx, [esp + RECT.top] |
@@: |
cmp ebx, [esp + RECT.top] |
jae @f |
mov ebx, [esp + RECT.top] |
@@: cmp ecx, [esp + RECT.right] |
@@: |
cmp ecx, [esp + RECT.right] |
jbe @f |
mov ecx, [esp + RECT.right] |
@@: cmp edx, [esp + RECT.bottom] |
@@: |
cmp edx, [esp + RECT.bottom] |
jbe @f |
mov edx, [esp + RECT.bottom] |
@@: push esi |
@@: |
push esi |
movzx esi, word[WIN_POS + esi * 2] |
call window._.set_screen |
pop esi |
520,7 → 537,8 |
sub eax, ebx |
jle @f |
mov [edi + WDATA.box.width], ebx |
@@: sub ebx, [edi + WDATA.box.width] |
@@: |
sub ebx, [edi + WDATA.box.width] |
mov [edi + WDATA.box.left], ebx |
.fix_vertical: |
533,7 → 551,8 |
sub eax, ebx |
jle @f |
mov [edi + WDATA.box.height], ebx |
@@: sub ebx, [edi + WDATA.box.height] |
@@: |
sub ebx, [edi + WDATA.box.height] |
mov [edi + WDATA.box.top], ebx |
jmp .fix_client_box |
655,7 → 674,8 |
cmp ebx, eax |
jbe @f |
mov ebx, eax |
@@: push ebx |
@@: |
push ebx |
xor edi, edi |
674,7 → 694,8 |
jz @f |
sub ecx, 0x00040404 |
mov [esi + WDATA.cl_titlebar], ecx |
@@: and ecx, 0x00ffffff |
@@: |
and ecx, 0x00ffffff |
call [draw_line] |
inc edx |
cmp edx, [esp] |
753,7 → 774,8 |
cmp ebx, eax |
jb @f |
mov ebx, eax |
@@: push ebx |
@@: |
push ebx |
xor edi, edi |
770,10 → 792,12 |
test ecx, 0x40000000 |
jz @f |
add ecx, 0x00040404 |
@@: test ecx, 0x80000000 |
@@: |
test ecx, 0x80000000 |
jz @f |
sub ecx, 0x00040404 |
@@: mov [esi + WDATA.cl_titlebar], ecx |
@@: |
mov [esi + WDATA.cl_titlebar], ecx |
and ecx, 0x00ffffff |
call [draw_line] |
inc edx |
987,7 → 1011,8 |
cmp eax, [TASK_COUNT] |
jz @f |
mov ebp, calculatescreen |
@@: mov eax, [edi + WDATA.box.left] |
@@: |
mov eax, [edi + WDATA.box.left] |
mov ebx, [edi + WDATA.box.top] |
mov ecx, [edi + WDATA.box.width] |
mov edx, [edi + WDATA.box.height] |
1022,7 → 1047,8 |
call minimize_window |
jmp .exit |
@@: call restore_minimized_window |
@@: |
call restore_minimized_window |
.exit: |
ret |
1083,7 → 1109,8 |
mov [ecx + BOX.height], eax |
xchg eax, ecx |
@@: call window._.set_window_box |
@@: |
call window._.set_window_box |
add esp, BOX.sizeof |
.exit: |
1124,7 → 1151,8 |
lea eax, [edx + APPDATA.saved_box] |
jmp .set_box |
@@: mov eax, [screen_workarea.top] |
@@: |
mov eax, [screen_workarea.top] |
push [screen_workarea.bottom] \ |
[edi + WDATA.box.width] \ |
eax \ |
1232,7 → 1260,8 |
cmp ecx, edx |
jle @f |
mov ecx, edx |
@@: mov [draw_limits.left], ecx |
@@: |
mov [draw_limits.left], ecx |
mov ecx, [eax + BOX.left] |
add ecx, [eax + BOX.width] |
add edx, [ebx + BOX.width] |
1239,13 → 1268,15 |
cmp ecx, edx |
jae @f |
mov ecx, edx |
@@: mov [draw_limits.right], ecx |
@@: |
mov [draw_limits.right], ecx |
mov ecx, [eax + BOX.top] |
mov edx, [ebx + BOX.top] |
cmp ecx, edx |
jle @f |
mov ecx, edx |
@@: mov [draw_limits.top], ecx |
@@: |
mov [draw_limits.top], ecx |
mov ecx, [eax + BOX.top] |
add ecx, [eax + BOX.height] |
add edx, [ebx + BOX.height] |
1252,7 → 1283,8 |
cmp ecx, edx |
jae @f |
mov ecx, edx |
@@: mov [draw_limits.bottom], ecx |
@@: |
mov [draw_limits.bottom], ecx |
; recalculate screen buffer at old position |
push ebx |
1296,17 → 1328,17 |
push eax ebx esi |
; don't do anything if the new box is identical to the old |
cmp bl, [edi + WDATA.fl_wstate] |
jnz @f |
mov esi, eax |
push edi |
cmp bl, [edi + WDATA.fl_wstate] |
jnz @f |
mov esi, eax |
push edi |
if WDATA.box |
add edi, WDATA.box |
add edi, WDATA.box |
end if |
mov ecx, 4 |
repz cmpsd |
pop edi |
jz .exit |
mov ecx, 4 |
repz cmpsd |
pop edi |
jz .exit |
@@: |
add esp, -BOX.sizeof |
1315,7 → 1347,7 |
if WDATA.box |
lea esi, [edi + WDATA.box] |
else |
mov esi, edi ; optimization for WDATA.box = 0 |
mov esi, edi ; optimization for WDATA.box = 0 |
end if |
xchg eax, esi |
mov ecx, BOX.sizeof |
1477,7 → 1509,8 |
xor eax, eax |
@@: mov [edi + APPDATA.wnd_caption], eax |
@@: |
mov [edi + APPDATA.wnd_caption], eax |
mov esi, [esp] |
add edi, APPDATA.saved_box |
1601,7 → 1634,8 |
jne @f |
mov eax, [_skinh] |
ret |
@@: mov eax, 21 |
@@: |
mov eax, 21 |
ret |
align 4 |
1619,11 → 1653,13 |
mov eax, [_skinh] |
add eax, 3 |
ret |
@@: or al, al |
@@: |
or al, al |
jnz @f |
mov eax, 21 |
ret |
@@: mov eax, 21 + 2 |
@@: |
mov eax, 21 + 2 |
ret |
align 4 |
1688,10 → 1724,10 |
.next_line: |
push ecx |
shr ecx, 2 |
rep stosd |
rep stosd |
mov ecx, [esp] |
and ecx, 3 |
rep stosb |
rep stosb |
pop ecx |
add edi, esi |
sub edi, ecx |
1765,12 → 1801,13 |
pop edx ebx |
add eax, edi |
call .read_byte |
test al,al |
test al, al |
jz @f |
mov eax, esi |
mov [ebp], al |
; -- end body -- |
@@: inc ebp |
@@: |
inc ebp |
inc edx |
cmp edx, [ff_xsz] |
jb .ff_new_x |
1812,9 → 1849,9 |
; if type of current active window is 3 or 4, it must be redrawn |
mov ebx, [TASK_COUNT] |
; DEBUGF 1, "K : TASK_COUNT (0x%x)\n", ebx |
; DEBUGF 1, "K : TASK_COUNT (0x%x)\n", ebx |
movzx ebx, word[WIN_POS + ebx * 2] |
shl ebx, 5 |
add eax, window_data |
1841,13 → 1878,13 |
cmp eax, [TASK_COUNT] |
jae .move_self_up |
inc eax |
; push ebx |
; xor ebx,ebx |
; mov bx,[WIN_STACK + eax * 2] |
; DEBUGF 1, "K : DEC WIN_STACK (0x%x)\n",ebx |
; pop ebx |
; push ebx |
; xor ebx,ebx |
; mov bx,[WIN_STACK + eax * 2] |
; DEBUGF 1, "K : DEC WIN_STACK (0x%x)\n",ebx |
; pop ebx |
cmp [WIN_STACK + eax * 2], bx |
jbe .next_stack_window |
dec word[WIN_STACK + eax * 2] |
1887,46 → 1924,46 |
;------------------------------------------------------------------------------ |
;> esi = pointer to WIN_POS+ window data |
;------------------------------------------------------------------------------ |
push eax ebx |
push eax ebx |
;------------------------------------------------------------------------------ |
.move_others_up: |
; ax <- process no |
movzx ebx, word[esi] |
; ax <- position in window stack |
movzx ebx, word[WIN_STACK + ebx * 2] |
; up others |
xor eax, eax |
; ax <- process no |
movzx ebx, word[esi] |
; ax <- position in window stack |
movzx ebx, word[WIN_STACK + ebx * 2] |
; up others |
xor eax, eax |
.next_stack_window: |
cmp eax, [TASK_COUNT] |
jae .move_self_down |
inc eax |
cmp [WIN_STACK + eax * 2], bx |
jae .next_stack_window |
inc word[WIN_STACK + eax * 2] |
jmp .next_stack_window |
cmp eax, [TASK_COUNT] |
jae .move_self_down |
inc eax |
cmp [WIN_STACK + eax * 2], bx |
jae .next_stack_window |
inc word[WIN_STACK + eax * 2] |
jmp .next_stack_window |
;---------------------------------------------- |
.move_self_down: |
movzx ebx, word[esi] |
; this is the last (and the low) |
mov [WIN_STACK + ebx * 2], word 1 |
; update on screen - window stack |
xor eax, eax |
movzx ebx, word[esi] |
; this is the last (and the low) |
mov [WIN_STACK + ebx * 2], word 1 |
; update on screen - window stack |
xor eax, eax |
.next_window_pos: |
cmp eax, [TASK_COUNT] |
jae .reset_vars |
inc eax |
movzx ebx, word[WIN_STACK + eax * 2] |
mov [WIN_POS + ebx * 2], ax |
jmp .next_window_pos |
cmp eax, [TASK_COUNT] |
jae .reset_vars |
inc eax |
movzx ebx, word[WIN_STACK + eax * 2] |
mov [WIN_POS + ebx * 2], ax |
jmp .next_window_pos |
;----------------------------------------------- |
.reset_vars: |
mov byte[KEY_COUNT], 0 |
mov byte[BTN_COUNT], 0 |
mov word[MOUSE_SCROLL_H], 0 |
mov word[MOUSE_SCROLL_V], 0 |
pop ebx eax |
ret |
;------------------------------------------------------------------------------ |
mov byte[KEY_COUNT], 0 |
mov byte[BTN_COUNT], 0 |
mov word[MOUSE_SCROLL_H], 0 |
mov word[MOUSE_SCROLL_V], 0 |
pop ebx eax |
ret |
;------------------------------------------------------------------------------ |
align 4 |
;------------------------------------------------------------------------------ |
window._.check_window_draw: ;////////////////////////////////////////////////// |
2014,7 → 2051,8 |
cmp edx, [CURRENT_TASK] |
jne @f |
inc eax |
@@: mov edx, [CURRENT_TASK] |
@@: |
mov edx, [CURRENT_TASK] |
shl edx, 5 |
add edx, window_data |
movzx ebx, [edx + WDATA.fl_wstyle] |
2045,7 → 2083,8 |
call drawwindow_I_caption |
.2: mov edi, [CURRENT_TASK] |
.2: |
mov edi, [CURRENT_TASK] |
shl edi, 5 |
test [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION |
jz .exit |
2149,5 → 2188,5 |
;> edi = pointer to BOX struct |
;------------------------------------------------------------------------------ |
push eax ebx esi |
xor esi,esi |
jmp window._.draw_negative_box.1 |
xor esi, esi |
jmp window._.draw_negative_box.1 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/hid/keyboard.inc |
---|
1,407 → 1,407 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
VKEY_LSHIFT = 0000000000000001b |
VKEY_RSHIFT = 0000000000000010b |
VKEY_LCONTROL = 0000000000000100b |
VKEY_RCONTROL = 0000000000001000b |
VKEY_LALT = 0000000000010000b |
VKEY_RALT = 0000000000100000b |
VKEY_CAPSLOCK = 0000000001000000b |
VKEY_NUMLOCK = 0000000010000000b |
VKEY_SCRLOCK = 0000000100000000b |
VKEY_SHIFT = 0000000000000011b |
VKEY_CONTROL = 0000000000001100b |
VKEY_ALT = 0000000000110000b |
uglobal |
align 4 |
kb_state dd 0 |
ext_code db 0 |
keyboard_mode db 0 |
keyboard_data db 0 |
altmouseb db 0 |
ctrl_alt_del db 0 |
kb_lights db 0 |
align 4 |
hotkey_scancodes rd 256 ; we have 256 scancodes |
hotkey_list rd 256*4 ; max 256 defined hotkeys |
hotkey_buffer rd 120*2 ; buffer for 120 hotkeys |
endg |
iglobal |
hotkey_tests dd hotkey_test0 |
dd hotkey_test1 |
dd hotkey_test2 |
dd hotkey_test3 |
dd hotkey_test4 |
hotkey_tests_num = 5 |
endg |
;--------------------------------------------------------------------- |
hotkey_test0: |
test al,al |
setz al |
ret |
;--------------------------------------------------------------------- |
hotkey_test1: |
test al,al |
setnp al |
ret |
;--------------------------------------------------------------------- |
hotkey_test2: |
cmp al,3 |
setz al |
ret |
;--------------------------------------------------------------------- |
hotkey_test3: |
cmp al,1 |
setz al |
ret |
;--------------------------------------------------------------------- |
hotkey_test4: |
cmp al,2 |
setz al |
ret |
;--------------------------------------------------------------------- |
hotkey_do_test: |
push eax |
mov edx,[kb_state] |
shr edx,cl |
add cl,cl |
mov eax,[eax+4] |
shr eax,cl |
and eax,15 |
cmp al,hotkey_tests_num |
jae .fail |
xchg eax,edx |
and al,3 |
call [hotkey_tests + edx*4] |
cmp al,1 |
pop eax |
ret |
;-------------------------------------- |
.fail: |
stc |
pop eax |
ret |
;--------------------------------------------------------------------- |
align 4 |
set_keyboard_data: |
movzx eax,word[TASK_COUNT] ; top window process |
movzx eax,word[WIN_POS+eax*2] |
shl eax,8 |
mov al,[SLOT_BASE+eax+APPDATA.keyboard_mode] |
mov [keyboard_mode],al |
mov eax,ecx |
push ebx esi edi ebp |
call send_scancode |
pop ebp edi esi ebx |
ret |
;--------------------------------------------------------------------- |
align 4 |
irq1: |
movzx eax,word[TASK_COUNT] ; top window process |
movzx eax,word[WIN_POS+eax*2] |
shl eax,8 |
mov al,[SLOT_BASE+eax+APPDATA.keyboard_mode] |
mov [keyboard_mode],al |
in al,0x60 |
;-------------------------------------- |
send_scancode: |
mov [keyboard_data],al |
; ch = scancode |
; cl = ext_code |
; bh = 0 - normal key |
; bh = 1 - modifier (Shift/Ctrl/Alt) |
; bh = 2 - extended code |
mov ch,al |
cmp al,0xE0 |
je @f |
cmp al,0xE1 |
jne .normal_code |
@@: |
mov bh,2 |
mov [ext_code],al |
jmp .writekey |
;-------------------------------------- |
.normal_code: |
mov cl,0 |
xchg cl,[ext_code] |
and al,0x7F |
mov bh,1 |
@@: |
cmp al,0x2A |
jne @f |
cmp cl,0xE0 |
je .writekey |
mov eax,VKEY_LSHIFT |
jmp .modifier |
;-------------------------------------- |
@@: |
cmp al,0x36 |
jne @f |
cmp cl,0xE0 |
je .writekey |
mov eax,VKEY_RSHIFT |
jmp .modifier |
;-------------------------------------- |
@@: |
cmp al,0x38 |
jne @f |
mov eax,VKEY_LALT |
test cl,cl |
jz .modifier |
mov al,VKEY_RALT |
jmp .modifier |
;-------------------------------------- |
@@: |
cmp al,0x1D |
jne @f |
mov eax,VKEY_LCONTROL |
test cl,cl |
jz .modifier |
mov al,VKEY_RCONTROL |
cmp cl,0xE0 |
jz .modifier |
mov [ext_code],cl |
jmp .writekey |
;-------------------------------------- |
@@: |
cmp al,0x3A |
jne @f |
mov bl,4 |
mov eax,VKEY_CAPSLOCK |
jmp .no_key.xor |
;-------------------------------------- |
@@: |
cmp al,0x45 |
jne @f |
test cl,cl |
jnz .writekey |
mov bl,2 |
mov eax,VKEY_NUMLOCK |
jmp .no_key.xor |
;-------------------------------------- |
@@: |
cmp al,0x46 |
jne @f |
mov bl,1 |
mov eax,VKEY_SCRLOCK |
jmp .no_key.xor |
;-------------------------------------- |
@@: |
xor ebx,ebx |
test ch,ch |
js .writekey |
movzx eax,ch ; plain key |
mov bl,[keymap+eax] |
mov edx,[kb_state] |
test dl,VKEY_CONTROL ; ctrl alt del |
jz .noctrlaltdel |
test dl,VKEY_ALT |
jz .noctrlaltdel |
cmp ch,53h |
jne .noctrlaltdel |
mov [ctrl_alt_del],1 |
.noctrlaltdel: |
test dl,VKEY_CONTROL ; ctrl on ? |
jz @f |
sub bl,0x60 |
@@: |
test dl,VKEY_CAPSLOCK ; caps lock on ? |
jz .no_caps_lock |
test dl,VKEY_SHIFT ; shift on ? |
jz .keymap_shif |
jmp @f |
;-------------------------------------- |
.no_caps_lock: |
test dl,VKEY_SHIFT ; shift on ? |
jz @f |
.keymap_shif: |
mov bl,[keymap_shift+eax] |
@@: |
test dl,VKEY_ALT ; alt on ? |
jz @f |
mov bl,[keymap_alt+eax] |
@@: |
jmp .writekey |
;-------------------------------------- |
.modifier: |
test ch, ch |
js .modifier.up |
or [kb_state],eax |
jmp .writekey |
;-------------------------------------- |
.modifier.up: |
not eax |
and [kb_state],eax |
jmp .writekey |
;-------------------------------------- |
.no_key.xor: |
mov bh,0 |
test ch,ch |
js .writekey |
xor [kb_state],eax |
xor [kb_lights],bl |
call set_lights |
.writekey: |
; test for system hotkeys |
movzx eax,ch |
cmp bh,1 |
ja .nohotkey |
jb @f |
xor eax,eax |
@@: |
mov eax, [hotkey_scancodes + eax*4] |
.hotkey_loop: |
test eax, eax |
jz .nohotkey |
mov cl,0 |
call hotkey_do_test |
jc .hotkey_cont |
mov cl,2 |
call hotkey_do_test |
jc .hotkey_cont |
mov cl,4 |
call hotkey_do_test |
jnc .hotkey_found |
.hotkey_cont: |
mov eax,[eax] |
jmp .hotkey_loop |
;-------------------------------------- |
.hotkey_found: |
mov eax,[eax+8] |
; put key in buffer for process in slot eax |
mov edi,hotkey_buffer |
@@: |
cmp dword [edi],0 |
jz .found_free |
add edi,8 |
cmp edi,hotkey_buffer+120*8 |
jb @b |
; no free space - replace first entry |
mov edi,hotkey_buffer |
.found_free: |
mov [edi],eax |
movzx eax,ch |
cmp bh,1 |
jnz @f |
xor eax, eax |
@@: |
mov [edi+4],ax |
mov eax,[kb_state] |
mov [edi+6],ax |
jmp .exit.irq1 |
;-------------------------------------- |
.nohotkey: |
cmp [keyboard_mode],0 ; return from keymap |
jne .scancode |
test bh,bh |
jnz .exit.irq1 |
test bl,bl |
jz .exit.irq1 |
test [kb_state],VKEY_NUMLOCK |
jz .dowrite |
cmp cl,0xE0 |
jz .dowrite |
cmp ch,55 |
jnz @f |
mov bl,0x2A ;* |
jmp .dowrite |
;-------------------------------------- |
@@: |
cmp ch,71 |
jb .dowrite |
cmp ch,83 |
ja .dowrite |
movzx eax, ch |
mov bl,[numlock_map + eax - 71] |
jmp .dowrite |
;-------------------------------------- |
.scancode: |
mov bl,ch |
.dowrite: |
movzx eax,byte[KEY_COUNT] |
cmp al,120 |
jae .exit.irq1 |
inc eax |
mov [KEY_COUNT],al |
mov [KEY_COUNT+eax],bl |
.exit.irq1: |
mov [check_idle_semaphore],5 |
ret |
;--------------------------------------------------------------------- |
set_lights: |
mov al,0xED |
call kb_write |
mov al,[kb_lights] |
call kb_write |
ret |
;--------------------------------------------------------------------- |
numlock_map: |
db 0x37 ;Num 7 |
db 0x38 ;Num 8 |
db 0x39 ;Num 9 |
db 0x2D ;Num - |
db 0x34 ;Num 4 |
db 0x35 ;Num 5 |
db 0x36 ;Num 6 |
db 0x2B ;Num + |
db 0x31 ;Num 1 |
db 0x32 ;Num 2 |
db 0x33 ;Num 3 |
db 0x30 ;Num 0 |
db 0x2E ;Num . |
;--------------------------------------------------------------------- |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
VKEY_LSHIFT = 0000000000000001b |
VKEY_RSHIFT = 0000000000000010b |
VKEY_LCONTROL = 0000000000000100b |
VKEY_RCONTROL = 0000000000001000b |
VKEY_LALT = 0000000000010000b |
VKEY_RALT = 0000000000100000b |
VKEY_CAPSLOCK = 0000000001000000b |
VKEY_NUMLOCK = 0000000010000000b |
VKEY_SCRLOCK = 0000000100000000b |
VKEY_SHIFT = 0000000000000011b |
VKEY_CONTROL = 0000000000001100b |
VKEY_ALT = 0000000000110000b |
uglobal |
align 4 |
kb_state dd 0 |
ext_code db 0 |
keyboard_mode db 0 |
keyboard_data db 0 |
altmouseb db 0 |
ctrl_alt_del db 0 |
kb_lights db 0 |
align 4 |
hotkey_scancodes rd 256 ; we have 256 scancodes |
hotkey_list rd 256*4 ; max 256 defined hotkeys |
hotkey_buffer rd 120*2 ; buffer for 120 hotkeys |
endg |
iglobal |
hotkey_tests dd hotkey_test0 |
dd hotkey_test1 |
dd hotkey_test2 |
dd hotkey_test3 |
dd hotkey_test4 |
hotkey_tests_num = 5 |
endg |
;--------------------------------------------------------------------- |
hotkey_test0: |
test al, al |
setz al |
ret |
;--------------------------------------------------------------------- |
hotkey_test1: |
test al, al |
setnp al |
ret |
;--------------------------------------------------------------------- |
hotkey_test2: |
cmp al, 3 |
setz al |
ret |
;--------------------------------------------------------------------- |
hotkey_test3: |
cmp al, 1 |
setz al |
ret |
;--------------------------------------------------------------------- |
hotkey_test4: |
cmp al, 2 |
setz al |
ret |
;--------------------------------------------------------------------- |
hotkey_do_test: |
push eax |
mov edx, [kb_state] |
shr edx, cl |
add cl, cl |
mov eax, [eax+4] |
shr eax, cl |
and eax, 15 |
cmp al, hotkey_tests_num |
jae .fail |
xchg eax, edx |
and al, 3 |
call [hotkey_tests + edx*4] |
cmp al, 1 |
pop eax |
ret |
;-------------------------------------- |
.fail: |
stc |
pop eax |
ret |
;--------------------------------------------------------------------- |
align 4 |
set_keyboard_data: |
movzx eax, word[TASK_COUNT]; top window process |
movzx eax, word[WIN_POS+eax*2] |
shl eax, 8 |
mov al, [SLOT_BASE+eax+APPDATA.keyboard_mode] |
mov [keyboard_mode], al |
mov eax, ecx |
push ebx esi edi ebp |
call send_scancode |
pop ebp edi esi ebx |
ret |
;--------------------------------------------------------------------- |
align 4 |
irq1: |
movzx eax, word[TASK_COUNT]; top window process |
movzx eax, word[WIN_POS+eax*2] |
shl eax, 8 |
mov al, [SLOT_BASE+eax+APPDATA.keyboard_mode] |
mov [keyboard_mode], al |
in al, 0x60 |
;-------------------------------------- |
send_scancode: |
mov [keyboard_data], al |
; ch = scancode |
; cl = ext_code |
; bh = 0 - normal key |
; bh = 1 - modifier (Shift/Ctrl/Alt) |
; bh = 2 - extended code |
mov ch, al |
cmp al, 0xE0 |
je @f |
cmp al, 0xE1 |
jne .normal_code |
@@: |
mov bh, 2 |
mov [ext_code], al |
jmp .writekey |
;-------------------------------------- |
.normal_code: |
mov cl, 0 |
xchg cl, [ext_code] |
and al, 0x7F |
mov bh, 1 |
@@: |
cmp al, 0x2A |
jne @f |
cmp cl, 0xE0 |
je .writekey |
mov eax, VKEY_LSHIFT |
jmp .modifier |
;-------------------------------------- |
@@: |
cmp al, 0x36 |
jne @f |
cmp cl, 0xE0 |
je .writekey |
mov eax, VKEY_RSHIFT |
jmp .modifier |
;-------------------------------------- |
@@: |
cmp al, 0x38 |
jne @f |
mov eax, VKEY_LALT |
test cl, cl |
jz .modifier |
mov al, VKEY_RALT |
jmp .modifier |
;-------------------------------------- |
@@: |
cmp al, 0x1D |
jne @f |
mov eax, VKEY_LCONTROL |
test cl, cl |
jz .modifier |
mov al, VKEY_RCONTROL |
cmp cl, 0xE0 |
jz .modifier |
mov [ext_code], cl |
jmp .writekey |
;-------------------------------------- |
@@: |
cmp al, 0x3A |
jne @f |
mov bl, 4 |
mov eax, VKEY_CAPSLOCK |
jmp .no_key.xor |
;-------------------------------------- |
@@: |
cmp al, 0x45 |
jne @f |
test cl, cl |
jnz .writekey |
mov bl, 2 |
mov eax, VKEY_NUMLOCK |
jmp .no_key.xor |
;-------------------------------------- |
@@: |
cmp al, 0x46 |
jne @f |
mov bl, 1 |
mov eax, VKEY_SCRLOCK |
jmp .no_key.xor |
;-------------------------------------- |
@@: |
xor ebx, ebx |
test ch, ch |
js .writekey |
movzx eax, ch ; plain key |
mov bl, [keymap+eax] |
mov edx, [kb_state] |
test dl, VKEY_CONTROL ; ctrl alt del |
jz .noctrlaltdel |
test dl, VKEY_ALT |
jz .noctrlaltdel |
cmp ch, 53h |
jne .noctrlaltdel |
mov [ctrl_alt_del], 1 |
.noctrlaltdel: |
test dl, VKEY_CONTROL ; ctrl on ? |
jz @f |
sub bl, 0x60 |
@@: |
test dl, VKEY_CAPSLOCK ; caps lock on ? |
jz .no_caps_lock |
test dl, VKEY_SHIFT ; shift on ? |
jz .keymap_shif |
jmp @f |
;-------------------------------------- |
.no_caps_lock: |
test dl, VKEY_SHIFT ; shift on ? |
jz @f |
.keymap_shif: |
mov bl, [keymap_shift+eax] |
@@: |
test dl, VKEY_ALT ; alt on ? |
jz @f |
mov bl, [keymap_alt+eax] |
@@: |
jmp .writekey |
;-------------------------------------- |
.modifier: |
test ch, ch |
js .modifier.up |
or [kb_state], eax |
jmp .writekey |
;-------------------------------------- |
.modifier.up: |
not eax |
and [kb_state], eax |
jmp .writekey |
;-------------------------------------- |
.no_key.xor: |
mov bh, 0 |
test ch, ch |
js .writekey |
xor [kb_state], eax |
xor [kb_lights], bl |
call set_lights |
.writekey: |
; test for system hotkeys |
movzx eax, ch |
cmp bh, 1 |
ja .nohotkey |
jb @f |
xor eax, eax |
@@: |
mov eax, [hotkey_scancodes + eax*4] |
.hotkey_loop: |
test eax, eax |
jz .nohotkey |
mov cl, 0 |
call hotkey_do_test |
jc .hotkey_cont |
mov cl, 2 |
call hotkey_do_test |
jc .hotkey_cont |
mov cl, 4 |
call hotkey_do_test |
jnc .hotkey_found |
.hotkey_cont: |
mov eax, [eax] |
jmp .hotkey_loop |
;-------------------------------------- |
.hotkey_found: |
mov eax, [eax+8] |
; put key in buffer for process in slot eax |
mov edi, hotkey_buffer |
@@: |
cmp dword [edi], 0 |
jz .found_free |
add edi, 8 |
cmp edi, hotkey_buffer+120*8 |
jb @b |
; no free space - replace first entry |
mov edi, hotkey_buffer |
.found_free: |
mov [edi], eax |
movzx eax, ch |
cmp bh, 1 |
jnz @f |
xor eax, eax |
@@: |
mov [edi+4], ax |
mov eax, [kb_state] |
mov [edi+6], ax |
jmp .exit.irq1 |
;-------------------------------------- |
.nohotkey: |
cmp [keyboard_mode], 0; return from keymap |
jne .scancode |
test bh, bh |
jnz .exit.irq1 |
test bl, bl |
jz .exit.irq1 |
test [kb_state], VKEY_NUMLOCK |
jz .dowrite |
cmp cl, 0xE0 |
jz .dowrite |
cmp ch, 55 |
jnz @f |
mov bl, 0x2A ;* |
jmp .dowrite |
;-------------------------------------- |
@@: |
cmp ch, 71 |
jb .dowrite |
cmp ch, 83 |
ja .dowrite |
movzx eax, ch |
mov bl, [numlock_map + eax - 71] |
jmp .dowrite |
;-------------------------------------- |
.scancode: |
mov bl, ch |
.dowrite: |
movzx eax, byte[KEY_COUNT] |
cmp al, 120 |
jae .exit.irq1 |
inc eax |
mov [KEY_COUNT], al |
mov [KEY_COUNT+eax], bl |
.exit.irq1: |
mov [check_idle_semaphore], 5 |
ret |
;--------------------------------------------------------------------- |
set_lights: |
mov al, 0xED |
call kb_write |
mov al, [kb_lights] |
call kb_write |
ret |
;--------------------------------------------------------------------- |
numlock_map: |
db 0x37 ;Num 7 |
db 0x38 ;Num 8 |
db 0x39 ;Num 9 |
db 0x2D ;Num - |
db 0x34 ;Num 4 |
db 0x35 ;Num 5 |
db 0x36 ;Num 6 |
db 0x2B ;Num + |
db 0x31 ;Num 1 |
db 0x32 ;Num 2 |
db 0x33 ;Num 3 |
db 0x30 ;Num 0 |
db 0x2E ;Num . |
;--------------------------------------------------------------------- |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/hid/mousedrv.inc |
---|
1,455 → 1,456 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; check mouse |
; |
; |
; FB00 -> FB0F mouse memory 00 chunk count - FB0A-B x - FB0C-D y |
; FB10 -> FB17 mouse color mem |
; FB21 x move |
; FB22 y move |
; FB30 color temp |
; FB28 high bits temp |
; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under |
; FC00 -> FCFE com1/ps2 buffer |
; FCFF com1/ps2 buffer count starting from FC00 |
uglobal |
mousecount dd 0x0 |
mousedata dd 0x0 |
endg |
iglobal |
mouse_delay dd 10 |
mouse_speed_factor: dd 3 |
mouse_timer_ticks dd 0 |
endg |
;include 'm_com.inc' |
;test_mario79: |
; push esi |
; push eax |
; mov [write_error_to],process_test_m79+43 |
; movzx eax,al ;[DevErrorCode] |
; call writehex |
; mov esi,process_test_m79 |
; call sys_msg_board_str |
; pop eax |
; pop esi |
; ret |
;process_test_m79 db 'K : Process - test Mario79 error 00000000',13,10,0 |
draw_mouse_under: |
; return old picture |
cmp [_display.restore_cursor], 0 |
je @F |
pushad |
movzx eax,word [X_UNDER] |
movzx ebx,word [Y_UNDER] |
stdcall [_display.restore_cursor], eax, ebx |
popad |
ret |
@@: |
pushad |
xor ecx,ecx |
xor edx,edx |
align 4 |
mres: |
movzx eax,word [X_UNDER] |
movzx ebx,word [Y_UNDER] |
add eax,ecx |
add ebx,edx |
push ecx |
push edx |
push eax |
push ebx |
mov eax,edx |
shl eax,6 |
shl ecx,2 |
add eax,ecx |
add eax,mouseunder |
mov ecx,[eax] |
pop ebx |
pop eax |
mov edi, 1 ;force |
call [putpixel] |
pop edx |
pop ecx |
inc ecx |
cmp ecx, 16 |
jnz mres |
xor ecx, ecx |
inc edx |
cmp edx, 24 |
jnz mres |
popad |
ret |
save_draw_mouse: |
cmp [_display.move_cursor], 0 |
je .no_hw_cursor |
pushad |
mov [X_UNDER],ax |
mov [Y_UNDER],bx |
movzx eax,word [MOUSE_Y] |
movzx ebx,word [MOUSE_X] |
push eax |
push ebx |
mov ecx, [Screen_Max_X] |
inc ecx |
mul ecx |
add eax, [_WinMapAddress] |
movzx edx, byte [ebx+eax] |
shl edx, 8 |
mov esi, [edx+SLOT_BASE+APPDATA.cursor] |
cmp esi, [current_cursor] |
je .draw |
push esi |
call [_display.select_cursor] |
mov [current_cursor], esi |
.draw: |
stdcall [_display.move_cursor], esi |
popad |
ret |
.fail: |
mov ecx, [def_cursor] |
mov [edx+SLOT_BASE+APPDATA.cursor], ecx |
stdcall [_display.move_cursor], ecx ; stdcall: [esp]=ebx,eax |
popad |
ret |
.no_hw_cursor: |
pushad |
; save & draw |
mov [X_UNDER],ax |
mov [Y_UNDER],bx |
push eax |
push ebx |
mov ecx,0 |
mov edx,0 |
align 4 |
drm: |
push eax |
push ebx |
push ecx |
push edx |
; helloworld |
push ecx |
add eax,ecx ; save picture under mouse |
add ebx,edx |
push ecx |
call getpixel |
mov [COLOR_TEMP],ecx |
pop ecx |
mov eax,edx |
shl eax,6 |
shl ecx,2 |
add eax,ecx |
add eax,mouseunder |
mov ebx,[COLOR_TEMP] |
mov [eax],ebx |
pop ecx |
mov edi,edx ; y cycle |
shl edi,4 ; *16 bytes per row |
add edi,ecx ; x cycle |
mov esi, edi |
add edi, esi |
add edi, esi ; *3 |
add edi,[MOUSE_PICTURE] ; we have our str address |
mov esi, edi |
add esi, 16*24*3 |
push ecx |
mov ecx, [COLOR_TEMP] |
call combine_colors |
mov [MOUSE_COLOR_MEM], ecx |
pop ecx |
pop edx |
pop ecx |
pop ebx |
pop eax |
add eax,ecx ; we have x coord+cycle |
add ebx,edx ; and y coord+cycle |
push ecx |
mov ecx, [MOUSE_COLOR_MEM] |
mov edi, 1 |
call [putpixel] |
pop ecx |
mov ebx,[esp+0] ; pure y coord again |
mov eax,[esp+4] ; and x |
inc ecx ; +1 cycle |
cmp ecx,16 ; if more than 16 |
jnz drm |
xor ecx, ecx |
inc edx |
cmp edx,24 |
jnz drm |
add esp,8 |
popad |
ret |
combine_colors: |
; in |
; ecx - color ( 00 RR GG BB ) |
; edi - ref to new color byte |
; esi - ref to alpha byte |
; |
; out |
; ecx - new color ( roughly (ecx*[esi]>>8)+([edi]*[esi]>>8) ) |
push eax |
push ebx |
push edx |
push ecx |
xor ecx, ecx |
; byte 2 |
mov eax, 0xff |
sub al, [esi+0] |
mov ebx, [esp] |
shr ebx, 16 |
and ebx, 0xff |
mul ebx |
shr eax, 8 |
add ecx, eax |
xor eax, eax |
xor ebx, ebx |
mov al, [edi+0] |
mov bl, [esi+0] |
mul ebx |
shr eax, 8 |
add ecx, eax |
shl ecx, 8 |
; byte 1 |
mov eax, 0xff |
sub al, [esi+1] |
mov ebx, [esp] |
shr ebx, 8 |
and ebx, 0xff |
mul ebx |
shr eax, 8 |
add ecx, eax |
xor eax, eax |
xor ebx, ebx |
mov al, [edi+1] |
mov bl, [esi+1] |
mul ebx |
shr eax, 8 |
add ecx, eax |
shl ecx, 8 |
; byte 2 |
mov eax, 0xff |
sub al, [esi+2] |
mov ebx, [esp] |
and ebx, 0xff |
mul ebx |
shr eax, 8 |
add ecx, eax |
xor eax, eax |
xor ebx, ebx |
mov al, [edi+2] |
mov bl, [esi+2] |
mul ebx |
shr eax, 8 |
add ecx, eax |
pop eax |
pop edx |
pop ebx |
pop eax |
ret |
__sys_disable_mouse: |
cmp dword [MOUSE_VISIBLE],dword 0 |
je @f |
ret |
@@: |
pushad |
cmp [CURRENT_TASK],dword 1 |
je disable_m |
mov edx,[CURRENT_TASK] |
shl edx,5 |
add edx,window_data |
movzx eax, word [MOUSE_X] |
movzx ebx, word [MOUSE_Y] |
mov ecx,[Screen_Max_X] |
inc ecx |
imul ecx,ebx |
add ecx,eax |
add ecx, [_WinMapAddress] |
mov eax, [CURRENT_TASK] |
cmp al, [ecx] |
je yes_mouse_disable |
cmp al, [ecx+16] |
je yes_mouse_disable |
add ebx, 10 |
cmp ebx, [Screen_Max_Y] |
jae no_mouse_disable |
mov ebx,[Screen_Max_X] |
inc ebx |
imul ebx,10 |
add ecx,ebx |
cmp al, [ecx] |
je yes_mouse_disable |
cmp al, [ecx+16] |
je yes_mouse_disable |
jmp no_mouse_disable |
yes_mouse_disable: |
mov edx,[CURRENT_TASK] |
shl edx,5 |
add edx,window_data |
movzx eax, word [MOUSE_X] |
movzx ebx, word [MOUSE_Y] |
mov ecx,[edx+0] ; mouse inside the area ? |
add eax,10 |
cmp eax,ecx |
jb no_mouse_disable |
sub eax,10 |
add ecx,[edx+8] |
cmp eax,ecx |
jg no_mouse_disable |
mov ecx,[edx+4] |
add ebx,14 |
cmp ebx,ecx |
jb no_mouse_disable |
sub ebx,14 |
add ecx,[edx+12] |
cmp ebx,ecx |
jg no_mouse_disable |
disable_m: |
cmp dword [MOUSE_VISIBLE],dword 0 |
jne no_mouse_disable |
pushf |
cli |
call draw_mouse_under |
popf |
mov [MOUSE_VISIBLE],dword 1 |
no_mouse_disable: |
popad |
ret |
__sys_draw_pointer: |
cmp [mouse_pause],0 |
je @f |
ret |
@@: |
push eax |
mov eax,[timer_ticks] |
sub eax,[MouseTickCounter] |
cmp eax,1 |
ja @f |
pop eax |
ret |
@@: |
mov eax,[timer_ticks] |
mov [MouseTickCounter],eax |
pop eax |
pushad |
cmp dword [MOUSE_VISIBLE],dword 0 ; mouse visible ? |
je chms00 |
mov [MOUSE_VISIBLE], dword 0 |
movzx ebx,word [MOUSE_Y] |
movzx eax,word [MOUSE_X] |
pushfd |
cli |
call save_draw_mouse |
popfd |
nodmu2: |
popad |
ret |
chms00: |
movzx ecx,word [X_UNDER] |
movzx edx,word [Y_UNDER] |
movzx ebx,word [MOUSE_Y] |
movzx eax,word [MOUSE_X] |
cmp eax,ecx |
jne redrawmouse |
cmp ebx,edx |
jne redrawmouse |
jmp nodmp |
redrawmouse: |
pushfd |
cli |
call draw_mouse_under |
call save_draw_mouse |
popfd |
nodmp: |
popad |
ret |
proc set_mouse_data stdcall, BtnState:dword, XMoving:dword, YMoving:dword, VScroll:dword, HScroll:dword |
mov eax,[BtnState] |
mov [BTN_DOWN],eax |
mov eax,[XMoving] |
call mouse_acceleration |
add ax,[MOUSE_X] ;[XCoordinate] |
cmp ax,0 |
jge @@M1 |
mov eax,0 |
jmp @@M2 |
@@M1: |
cmp ax,[Screen_Max_X] ;ScreenLength |
jl @@M2 |
mov ax,[Screen_Max_X] ;ScreenLength-1 |
@@M2: |
mov [MOUSE_X],ax ;[XCoordinate] |
mov eax,[YMoving] |
neg eax |
call mouse_acceleration |
add ax,[MOUSE_Y] ;[YCoordinate] |
cmp ax,0 |
jge @@M3 |
mov ax,0 |
jmp @@M4 |
@@M3: |
cmp ax,[Screen_Max_Y] ;ScreenHeigth |
jl @@M4 |
mov ax,[Screen_Max_Y] ;ScreenHeigth-1 |
@@M4: |
mov [MOUSE_Y],ax ;[YCoordinate] |
mov eax,[VScroll] |
add [MOUSE_SCROLL_V],ax |
mov eax,[HScroll] |
add [MOUSE_SCROLL_H],ax |
mov [mouse_active],1 |
mov eax,[timer_ticks] |
mov [mouse_timer_ticks],eax |
ret |
endp |
mouse_acceleration: |
push eax |
mov eax,[timer_ticks] |
sub eax,[mouse_timer_ticks] |
cmp eax,[mouse_delay] |
pop eax |
ja @f |
;push edx |
imul eax,[mouse_speed_factor] |
;pop edx |
@@: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; check mouse |
; |
; |
; FB00 -> FB0F mouse memory 00 chunk count - FB0A-B x - FB0C-D y |
; FB10 -> FB17 mouse color mem |
; FB21 x move |
; FB22 y move |
; FB30 color temp |
; FB28 high bits temp |
; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under |
; FC00 -> FCFE com1/ps2 buffer |
; FCFF com1/ps2 buffer count starting from FC00 |
uglobal |
mousecount dd 0x0 |
mousedata dd 0x0 |
endg |
iglobal |
mouse_delay dd 10 |
mouse_speed_factor: |
dd 3 |
mouse_timer_ticks dd 0 |
endg |
;include 'm_com.inc' |
;test_mario79: |
; push esi |
; push eax |
; mov [write_error_to],process_test_m79+43 |
; movzx eax,al ;[DevErrorCode] |
; call writehex |
; mov esi,process_test_m79 |
; call sys_msg_board_str |
; pop eax |
; pop esi |
; ret |
;process_test_m79 db 'K : Process - test Mario79 error 00000000',13,10,0 |
draw_mouse_under: |
; return old picture |
cmp [_display.restore_cursor], 0 |
je @F |
pushad |
movzx eax, word [X_UNDER] |
movzx ebx, word [Y_UNDER] |
stdcall [_display.restore_cursor], eax, ebx |
popad |
ret |
@@: |
pushad |
xor ecx, ecx |
xor edx, edx |
align 4 |
mres: |
movzx eax, word [X_UNDER] |
movzx ebx, word [Y_UNDER] |
add eax, ecx |
add ebx, edx |
push ecx |
push edx |
push eax |
push ebx |
mov eax, edx |
shl eax, 6 |
shl ecx, 2 |
add eax, ecx |
add eax, mouseunder |
mov ecx, [eax] |
pop ebx |
pop eax |
mov edi, 1;force |
call [putpixel] |
pop edx |
pop ecx |
inc ecx |
cmp ecx, 16 |
jnz mres |
xor ecx, ecx |
inc edx |
cmp edx, 24 |
jnz mres |
popad |
ret |
save_draw_mouse: |
cmp [_display.move_cursor], 0 |
je .no_hw_cursor |
pushad |
mov [X_UNDER], ax |
mov [Y_UNDER], bx |
movzx eax, word [MOUSE_Y] |
movzx ebx, word [MOUSE_X] |
push eax |
push ebx |
mov ecx, [Screen_Max_X] |
inc ecx |
mul ecx |
add eax, [_WinMapAddress] |
movzx edx, byte [ebx+eax] |
shl edx, 8 |
mov esi, [edx+SLOT_BASE+APPDATA.cursor] |
cmp esi, [current_cursor] |
je .draw |
push esi |
call [_display.select_cursor] |
mov [current_cursor], esi |
.draw: |
stdcall [_display.move_cursor], esi |
popad |
ret |
.fail: |
mov ecx, [def_cursor] |
mov [edx+SLOT_BASE+APPDATA.cursor], ecx |
stdcall [_display.move_cursor], ecx ; stdcall: [esp]=ebx,eax |
popad |
ret |
.no_hw_cursor: |
pushad |
; save & draw |
mov [X_UNDER], ax |
mov [Y_UNDER], bx |
push eax |
push ebx |
mov ecx, 0 |
mov edx, 0 |
align 4 |
drm: |
push eax |
push ebx |
push ecx |
push edx |
; helloworld |
push ecx |
add eax, ecx; save picture under mouse |
add ebx, edx |
push ecx |
call getpixel |
mov [COLOR_TEMP], ecx |
pop ecx |
mov eax, edx |
shl eax, 6 |
shl ecx, 2 |
add eax, ecx |
add eax, mouseunder |
mov ebx, [COLOR_TEMP] |
mov [eax], ebx |
pop ecx |
mov edi, edx ; y cycle |
shl edi, 4 ; *16 bytes per row |
add edi, ecx ; x cycle |
mov esi, edi |
add edi, esi |
add edi, esi ; *3 |
add edi, [MOUSE_PICTURE] ; we have our str address |
mov esi, edi |
add esi, 16*24*3 |
push ecx |
mov ecx, [COLOR_TEMP] |
call combine_colors |
mov [MOUSE_COLOR_MEM], ecx |
pop ecx |
pop edx |
pop ecx |
pop ebx |
pop eax |
add eax, ecx ; we have x coord+cycle |
add ebx, edx ; and y coord+cycle |
push ecx |
mov ecx, [MOUSE_COLOR_MEM] |
mov edi, 1 |
call [putpixel] |
pop ecx |
mov ebx, [esp+0] ; pure y coord again |
mov eax, [esp+4] ; and x |
inc ecx ; +1 cycle |
cmp ecx, 16 ; if more than 16 |
jnz drm |
xor ecx, ecx |
inc edx |
cmp edx, 24 |
jnz drm |
add esp, 8 |
popad |
ret |
combine_colors: |
; in |
; ecx - color ( 00 RR GG BB ) |
; edi - ref to new color byte |
; esi - ref to alpha byte |
; |
; out |
; ecx - new color ( roughly (ecx*[esi]>>8)+([edi]*[esi]>>8) ) |
push eax |
push ebx |
push edx |
push ecx |
xor ecx, ecx |
; byte 2 |
mov eax, 0xff |
sub al, [esi+0] |
mov ebx, [esp] |
shr ebx, 16 |
and ebx, 0xff |
mul ebx |
shr eax, 8 |
add ecx, eax |
xor eax, eax |
xor ebx, ebx |
mov al, [edi+0] |
mov bl, [esi+0] |
mul ebx |
shr eax, 8 |
add ecx, eax |
shl ecx, 8 |
; byte 1 |
mov eax, 0xff |
sub al, [esi+1] |
mov ebx, [esp] |
shr ebx, 8 |
and ebx, 0xff |
mul ebx |
shr eax, 8 |
add ecx, eax |
xor eax, eax |
xor ebx, ebx |
mov al, [edi+1] |
mov bl, [esi+1] |
mul ebx |
shr eax, 8 |
add ecx, eax |
shl ecx, 8 |
; byte 2 |
mov eax, 0xff |
sub al, [esi+2] |
mov ebx, [esp] |
and ebx, 0xff |
mul ebx |
shr eax, 8 |
add ecx, eax |
xor eax, eax |
xor ebx, ebx |
mov al, [edi+2] |
mov bl, [esi+2] |
mul ebx |
shr eax, 8 |
add ecx, eax |
pop eax |
pop edx |
pop ebx |
pop eax |
ret |
__sys_disable_mouse: |
cmp dword [MOUSE_VISIBLE], dword 0 |
je @f |
ret |
@@: |
pushad |
cmp [CURRENT_TASK], dword 1 |
je disable_m |
mov edx, [CURRENT_TASK] |
shl edx, 5 |
add edx, window_data |
movzx eax, word [MOUSE_X] |
movzx ebx, word [MOUSE_Y] |
mov ecx, [Screen_Max_X] |
inc ecx |
imul ecx, ebx |
add ecx, eax |
add ecx, [_WinMapAddress] |
mov eax, [CURRENT_TASK] |
cmp al, [ecx] |
je yes_mouse_disable |
cmp al, [ecx+16] |
je yes_mouse_disable |
add ebx, 10 |
cmp ebx, [Screen_Max_Y] |
jae no_mouse_disable |
mov ebx, [Screen_Max_X] |
inc ebx |
imul ebx, 10 |
add ecx, ebx |
cmp al, [ecx] |
je yes_mouse_disable |
cmp al, [ecx+16] |
je yes_mouse_disable |
jmp no_mouse_disable |
yes_mouse_disable: |
mov edx, [CURRENT_TASK] |
shl edx, 5 |
add edx, window_data |
movzx eax, word [MOUSE_X] |
movzx ebx, word [MOUSE_Y] |
mov ecx, [edx+0]; mouse inside the area ? |
add eax, 10 |
cmp eax, ecx |
jb no_mouse_disable |
sub eax, 10 |
add ecx, [edx+8] |
cmp eax, ecx |
jg no_mouse_disable |
mov ecx, [edx+4] |
add ebx, 14 |
cmp ebx, ecx |
jb no_mouse_disable |
sub ebx, 14 |
add ecx, [edx+12] |
cmp ebx, ecx |
jg no_mouse_disable |
disable_m: |
cmp dword [MOUSE_VISIBLE], dword 0 |
jne no_mouse_disable |
pushf |
cli |
call draw_mouse_under |
popf |
mov [MOUSE_VISIBLE], dword 1 |
no_mouse_disable: |
popad |
ret |
__sys_draw_pointer: |
cmp [mouse_pause], 0 |
je @f |
ret |
@@: |
push eax |
mov eax, [timer_ticks] |
sub eax, [MouseTickCounter] |
cmp eax, 1 |
ja @f |
pop eax |
ret |
@@: |
mov eax, [timer_ticks] |
mov [MouseTickCounter], eax |
pop eax |
pushad |
cmp dword [MOUSE_VISIBLE], dword 0; mouse visible ? |
je chms00 |
mov [MOUSE_VISIBLE], dword 0 |
movzx ebx, word [MOUSE_Y] |
movzx eax, word [MOUSE_X] |
pushfd |
cli |
call save_draw_mouse |
popfd |
nodmu2: |
popad |
ret |
chms00: |
movzx ecx, word [X_UNDER] |
movzx edx, word [Y_UNDER] |
movzx ebx, word [MOUSE_Y] |
movzx eax, word [MOUSE_X] |
cmp eax, ecx |
jne redrawmouse |
cmp ebx, edx |
jne redrawmouse |
jmp nodmp |
redrawmouse: |
pushfd |
cli |
call draw_mouse_under |
call save_draw_mouse |
popfd |
nodmp: |
popad |
ret |
proc set_mouse_data stdcall, BtnState:dword, XMoving:dword, YMoving:dword, VScroll:dword, HScroll:dword |
mov eax, [BtnState] |
mov [BTN_DOWN], eax |
mov eax, [XMoving] |
call mouse_acceleration |
add ax, [MOUSE_X];[XCoordinate] |
cmp ax, 0 |
jge @@M1 |
mov eax, 0 |
jmp @@M2 |
@@M1: |
cmp ax, [Screen_Max_X];ScreenLength |
jl @@M2 |
mov ax, [Screen_Max_X];ScreenLength-1 |
@@M2: |
mov [MOUSE_X], ax;[XCoordinate] |
mov eax, [YMoving] |
neg eax |
call mouse_acceleration |
add ax, [MOUSE_Y];[YCoordinate] |
cmp ax, 0 |
jge @@M3 |
mov ax, 0 |
jmp @@M4 |
@@M3: |
cmp ax, [Screen_Max_Y];ScreenHeigth |
jl @@M4 |
mov ax, [Screen_Max_Y];ScreenHeigth-1 |
@@M4: |
mov [MOUSE_Y], ax;[YCoordinate] |
mov eax, [VScroll] |
add [MOUSE_SCROLL_V], ax |
mov eax, [HScroll] |
add [MOUSE_SCROLL_H], ax |
mov [mouse_active], 1 |
mov eax, [timer_ticks] |
mov [mouse_timer_ticks], eax |
ret |
endp |
mouse_acceleration: |
push eax |
mov eax, [timer_ticks] |
sub eax, [mouse_timer_ticks] |
cmp eax, [mouse_delay] |
pop eax |
ja @f |
;push edx |
imul eax, [mouse_speed_factor] |
;pop edx |
@@: |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/hid/set_dtc.inc |
---|
1,203 → 1,203 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;setting date,time,clock and alarm-clock |
;add sys_settime at servetable as for ex. 22 fcn: |
; 22 - SETTING DATE TIME, CLOCK AND ALARM-CLOCK |
; ebx =0 - set time ecx - 00SSMMHH |
; ebx =1 - set date ecx=00DDMMYY |
; ebx =2 - set day of week ecx- 1-7 |
; ebx =3 - set alarm-clock ecx - 00SSMMHH |
; out: 0 -Ok 1 -wrong format 2 -battery low |
sys_settime: |
cli |
mov al,0x0d |
out 0x70,al |
in al,0x71 |
bt ax,7 |
jnc bat_low |
cmp ebx,2 ;day of week |
jne nosetweek |
test ecx,ecx ;test day of week |
je wrongtime |
cmp ecx,7 |
ja wrongtime |
mov edx,0x70 |
call startstopclk |
dec edx |
mov al,6 |
out dx,al |
inc edx |
mov al,cl |
out dx,al |
jmp endsettime |
nosetweek: ;set date |
cmp ebx,1 |
jne nosetdate |
cmp cl,0x99 ;test year |
ja wrongtime |
shl ecx,4 |
cmp cl,0x90 |
ja wrongtime |
cmp ch,0x99 ;test month |
ja wrongtime |
shr ecx,4 |
test ch,ch |
je wrongtime |
cmp ch,0x12 |
ja wrongtime |
shl ecx,8 |
bswap ecx ;ebx=00YYMMDD |
test cl,cl ;test day |
je wrongtime |
shl ecx,4 |
cmp cl,0x90 |
ja wrongtime |
shr ecx,4 |
cmp ch,2 ;February |
jne testday |
cmp cl,0x29 |
ja wrongtime |
jmp setdate |
testday: |
cmp ch,8 |
jb testday1 ;Aug-Dec |
bt cx,8 |
jnc days31 |
jmp days30 |
testday1: |
bt cx,8 ;Jan-Jul ex.Feb |
jnc days30 |
days31: |
cmp cl,0x31 |
ja wrongtime |
jmp setdate |
days30: |
cmp cl,0x30 |
ja wrongtime |
setdate: |
mov edx,0x70 |
call startstopclk |
dec edx |
mov al,7 ;set days |
out dx,al |
inc edx |
mov al,cl |
out dx,al |
dec edx |
mov al,8 ;set months |
out dx,al |
inc edx |
mov al,ch |
out dx,al |
dec edx |
mov al,9 ;set years |
out dx,al |
inc edx |
shr ecx,8 |
mov al,ch |
out dx,al |
jmp endsettime |
nosetdate: ;set time or alarm-clock |
cmp ebx,3 |
ja wrongtime |
cmp cl,0x23 |
ja wrongtime |
cmp ch,0x59 |
ja wrongtime |
shl ecx,4 |
cmp cl,0x90 |
ja wrongtime |
cmp ch,0x92 |
ja wrongtime |
shl ecx,4 |
bswap ecx ;00HHMMSS |
cmp cl,0x59 |
ja wrongtime |
shl ecx,4 |
cmp cl,0x90 |
ja wrongtime |
shr ecx,4 |
mov edx,0x70 |
call startstopclk |
dec edx |
cmp ebx,3 |
je setalarm |
xor eax,eax ;al=0-set seconds |
out dx,al |
inc edx |
mov al,cl |
out dx,al |
dec edx |
mov al,2 ;set minutes |
out dx,al |
inc edx |
mov al,ch |
out dx,al |
dec edx |
mov al,4 ;set hours |
out dx,al |
inc edx |
shr ecx,8 |
mov al,ch |
out dx,al |
jmp endsettime |
setalarm: |
mov al,1 ;set seconds for al. |
out dx,al |
inc edx |
mov al,cl |
out dx,al |
dec edx |
mov al,3 ;set minutes for al. |
out dx,al |
inc edx |
mov al,ch |
out dx,al |
dec edx |
mov al,5 ;set hours for al. |
out dx,al |
inc edx |
shr ecx,8 |
mov al,ch |
out dx,al |
dec edx |
mov al,0x0b ;enable irq's |
out dx,al |
inc dx |
in al,dx |
bts ax,5 ;set bit 5 |
out dx,al |
endsettime: |
dec edx |
call startstopclk |
sti |
and [esp+36-4],dword 0 |
ret |
bat_low: |
sti |
mov [esp+36-4],dword 2 |
ret |
wrongtime: |
sti |
mov [esp+36-4],dword 1 |
ret |
startstopclk: |
mov al,0x0b |
out dx,al |
inc dx |
in al,dx |
btc ax,7 |
out dx,al |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;setting date,time,clock and alarm-clock |
;add sys_settime at servetable as for ex. 22 fcn: |
; 22 - SETTING DATE TIME, CLOCK AND ALARM-CLOCK |
; ebx =0 - set time ecx - 00SSMMHH |
; ebx =1 - set date ecx=00DDMMYY |
; ebx =2 - set day of week ecx- 1-7 |
; ebx =3 - set alarm-clock ecx - 00SSMMHH |
; out: 0 -Ok 1 -wrong format 2 -battery low |
sys_settime: |
cli |
mov al, 0x0d |
out 0x70, al |
in al, 0x71 |
bt ax, 7 |
jnc bat_low |
cmp ebx, 2;day of week |
jne nosetweek |
test ecx, ecx ;test day of week |
je wrongtime |
cmp ecx, 7 |
ja wrongtime |
mov edx, 0x70 |
call startstopclk |
dec edx |
mov al, 6 |
out dx, al |
inc edx |
mov al, cl |
out dx, al |
jmp endsettime |
nosetweek: ;set date |
cmp ebx, 1 |
jne nosetdate |
cmp cl, 0x99;test year |
ja wrongtime |
shl ecx, 4 |
cmp cl, 0x90 |
ja wrongtime |
cmp ch, 0x99;test month |
ja wrongtime |
shr ecx, 4 |
test ch, ch |
je wrongtime |
cmp ch, 0x12 |
ja wrongtime |
shl ecx, 8 |
bswap ecx ;ebx=00YYMMDD |
test cl, cl ;test day |
je wrongtime |
shl ecx, 4 |
cmp cl, 0x90 |
ja wrongtime |
shr ecx, 4 |
cmp ch, 2 ;February |
jne testday |
cmp cl, 0x29 |
ja wrongtime |
jmp setdate |
testday: |
cmp ch, 8 |
jb testday1;Aug-Dec |
bt cx, 8 |
jnc days31 |
jmp days30 |
testday1: |
bt cx, 8 ;Jan-Jul ex.Feb |
jnc days30 |
days31: |
cmp cl, 0x31 |
ja wrongtime |
jmp setdate |
days30: |
cmp cl, 0x30 |
ja wrongtime |
setdate: |
mov edx, 0x70 |
call startstopclk |
dec edx |
mov al, 7 ;set days |
out dx, al |
inc edx |
mov al, cl |
out dx, al |
dec edx |
mov al, 8 ;set months |
out dx, al |
inc edx |
mov al, ch |
out dx, al |
dec edx |
mov al, 9 ;set years |
out dx, al |
inc edx |
shr ecx, 8 |
mov al, ch |
out dx, al |
jmp endsettime |
nosetdate: ;set time or alarm-clock |
cmp ebx, 3 |
ja wrongtime |
cmp cl, 0x23 |
ja wrongtime |
cmp ch, 0x59 |
ja wrongtime |
shl ecx, 4 |
cmp cl, 0x90 |
ja wrongtime |
cmp ch, 0x92 |
ja wrongtime |
shl ecx, 4 |
bswap ecx ;00HHMMSS |
cmp cl, 0x59 |
ja wrongtime |
shl ecx, 4 |
cmp cl, 0x90 |
ja wrongtime |
shr ecx, 4 |
mov edx, 0x70 |
call startstopclk |
dec edx |
cmp ebx, 3 |
je setalarm |
xor eax, eax;al=0-set seconds |
out dx, al |
inc edx |
mov al, cl |
out dx, al |
dec edx |
mov al, 2 ;set minutes |
out dx, al |
inc edx |
mov al, ch |
out dx, al |
dec edx |
mov al, 4 ;set hours |
out dx, al |
inc edx |
shr ecx, 8 |
mov al, ch |
out dx, al |
jmp endsettime |
setalarm: |
mov al, 1;set seconds for al. |
out dx, al |
inc edx |
mov al, cl |
out dx, al |
dec edx |
mov al, 3;set minutes for al. |
out dx, al |
inc edx |
mov al, ch |
out dx, al |
dec edx |
mov al, 5;set hours for al. |
out dx, al |
inc edx |
shr ecx, 8 |
mov al, ch |
out dx, al |
dec edx |
mov al, 0x0b;enable irq's |
out dx, al |
inc dx |
in al, dx |
bts ax, 5;set bit 5 |
out dx, al |
endsettime: |
dec edx |
call startstopclk |
sti |
and [esp+36-4], dword 0 |
ret |
bat_low: |
sti |
mov [esp+36-4], dword 2 |
ret |
wrongtime: |
sti |
mov [esp+36-4], dword 1 |
ret |
startstopclk: |
mov al, 0x0b |
out dx, al |
inc dx |
in al, dx |
btc ax, 7 |
out dx, al |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/imports.inc |
---|
1,27 → 1,27 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;============================================================================ |
; |
; External kernel dependencies |
; |
;============================================================================ |
$Revision$ |
align 4 |
@IMPORT: |
library \ |
libini,'libini.obj' |
import libini, \ |
ini.lib_init,'lib_init',\ |
ini.get_str,'ini.get_str',\ |
ini.enum_keys,'ini.enum_keys',\ |
ini.get_int,'ini.get_int' |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;============================================================================ |
; |
; External kernel dependencies |
; |
;============================================================================ |
$Revision$ |
align 4 |
@IMPORT: |
library \ |
libini,'libini.obj' |
import libini, \ |
ini.lib_init,'lib_init',\ |
ini.get_str,'ini.get_str',\ |
ini.enum_keys,'ini.enum_keys',\ |
ini.get_int,'ini.get_int' |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/init.inc |
---|
1,553 → 1,554 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
MEM_WB equ 6 ;write-back memory |
MEM_WC equ 1 ;write combined memory |
MEM_UC equ 0 ;uncached memory |
align 4 |
proc mem_test |
; if we have BIOS with fn E820, skip the test |
cmp dword [BOOT_VAR-OS_BASE + 0x9100], 0 |
jnz .ret |
mov eax, cr0 |
and eax, not (CR0_CD+CR0_NW) |
or eax, CR0_CD ;disable caching |
mov cr0, eax |
wbinvd ;invalidate cache |
xor edi, edi |
mov ebx, 'TEST' |
@@: |
add edi, 0x100000 |
xchg ebx, dword [edi] |
cmp dword [edi], 'TEST' |
xchg ebx, dword [edi] |
je @b |
and eax, not (CR0_CD+CR0_NW) ;enable caching |
mov cr0, eax |
inc dword [BOOT_VAR-OS_BASE + 0x9100] |
xor eax, eax |
mov [BOOT_VAR-OS_BASE + 0x9104], eax |
mov [BOOT_VAR-OS_BASE + 0x9108], eax |
mov [BOOT_VAR-OS_BASE + 0x910C], edi |
mov [BOOT_VAR-OS_BASE + 0x9110], eax |
.ret: |
ret |
endp |
align 4 |
proc init_mem |
; calculate maximum allocatable address and number of allocatable pages |
mov edi, BOOT_VAR-OS_BASE + 0x9104 |
mov ecx, [edi-4] |
xor esi, esi ; esi will hold total amount of memory |
xor edx, edx ; edx will hold maximum allocatable address |
.calcmax: |
; round all to pages |
mov eax, [edi] |
test eax, 0xFFF |
jz @f |
neg eax |
and eax, 0xFFF |
add [edi], eax |
adc dword [edi+4], 0 |
sub [edi+8], eax |
sbb dword [edi+12], 0 |
jc .unusable |
@@: |
and dword [edi+8], not 0xFFF |
jz .unusable |
; ignore memory after 4 Gb |
cmp dword [edi+4], 0 |
jnz .unusable |
mov eax, [edi] |
cmp dword [edi+12], 0 |
jnz .overflow |
add eax, [edi+8] |
jnc @f |
.overflow: |
mov eax, 0xFFFFF000 |
@@: |
cmp edx, eax |
jae @f |
mov edx, eax |
@@: |
sub eax, [edi] |
mov [edi+8], eax |
add esi, eax |
jmp .usable |
.unusable: |
and dword [edi+8], 0 |
.usable: |
add edi, 20 |
loop .calcmax |
.calculated: |
mov [MEM_AMOUNT-OS_BASE], esi |
mov [pg_data.mem_amount-OS_BASE], esi |
shr esi, 12 |
mov [pg_data.pages_count-OS_BASE], esi |
shr edx, 12 |
add edx, 31 |
and edx, not 31 |
shr edx, 3 |
mov [pg_data.pagemap_size-OS_BASE], edx |
add edx, (sys_pgmap-OS_BASE)+4095 |
and edx, not 4095 |
mov [tmp_page_tabs], edx |
mov edx, esi |
and edx, -1024 |
cmp edx, (OS_BASE/4096) |
jbe @F |
mov edx, (OS_BASE/4096) |
jmp .set |
@@: |
cmp edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096 |
jae .set |
mov edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096 |
.set: |
mov [pg_data.kernel_pages-OS_BASE], edx |
shr edx, 10 |
mov [pg_data.kernel_tables-OS_BASE], edx |
xor eax, eax |
mov edi, sys_pgdir-OS_BASE |
mov ecx, 4096/4 |
cld |
rep stosd |
mov edx, (sys_pgdir-OS_BASE)+ 0x800; (OS_BASE shr 20) |
bt [cpu_caps-OS_BASE], CAPS_PSE |
jnc .no_PSE |
mov ebx, cr4 |
or ebx, CR4_PSE |
mov eax, PG_LARGE+PG_SW |
mov cr4, ebx |
dec [pg_data.kernel_tables-OS_BASE] |
mov [edx], eax |
add edx, 4 |
mov edi, [tmp_page_tabs] |
jmp .map_kernel_heap ; new kernel fits to the first 4Mb - nothing to do with ".map_low" |
.no_PSE: |
mov eax, PG_SW |
mov ecx, [tmp_page_tabs] |
shr ecx, 12 |
.map_low: |
mov edi, [tmp_page_tabs] |
@@: ; |
stosd |
add eax, 0x1000 |
dec ecx |
jnz @B |
.map_kernel_heap: |
mov ecx, [pg_data.kernel_tables-OS_BASE] |
shl ecx, 10 |
xor eax, eax |
rep stosd |
mov ecx, [pg_data.kernel_tables-OS_BASE] |
mov eax, [tmp_page_tabs] |
or eax, PG_SW |
mov edi, edx |
.map_kernel_tabs: |
stosd |
add eax, 0x1000 |
dec ecx |
jnz .map_kernel_tabs |
mov dword [sys_pgdir-OS_BASE+(page_tabs shr 20)], sys_pgdir+PG_SW-OS_BASE |
mov edi, (sys_pgdir-OS_BASE) |
lea esi, [edi+(OS_BASE shr 20)] |
movsd |
movsd |
ret |
endp |
align 4 |
proc init_page_map |
; mark all memory as unavailable |
mov edi, sys_pgmap-OS_BASE |
mov ecx, [pg_data.pagemap_size-OS_BASE] |
shr ecx, 2 |
xor eax, eax |
cld |
rep stosd |
; scan through memory map and mark free areas as available |
mov ebx, BOOT_VAR-OS_BASE + 0x9104 |
mov edx, [ebx-4] |
.scanmap: |
mov ecx, [ebx+8] |
shr ecx, 12 ; ecx = number of pages |
jz .next |
mov edi, [ebx] |
shr edi, 12 ; edi = first page |
mov eax, edi |
shr edi, 5 |
shl edi, 2 |
add edi, sys_pgmap-OS_BASE |
and eax, 31 |
jz .startok |
add ecx, eax |
sub ecx, 32 |
jbe .onedword |
push ecx |
mov ecx, eax |
or eax, -1 |
shl eax, cl |
or [edi], eax |
add edi, 4 |
pop ecx |
.startok: |
push ecx |
shr ecx, 5 |
or eax, -1 |
rep stosd |
pop ecx |
and ecx, 31 |
neg eax |
shl eax, cl |
dec eax |
or [edi], eax |
jmp .next |
.onedword: |
add ecx, 32 |
sub ecx, eax |
@@: |
bts [edi], eax |
inc eax |
loop @b |
.next: |
add ebx, 20 |
dec edx |
jnz .scanmap |
; mark kernel memory as allocated (unavailable) |
mov ecx, [tmp_page_tabs] |
mov edx, [pg_data.pages_count-OS_BASE] |
shr ecx, 12 |
add ecx, [pg_data.kernel_tables-OS_BASE] |
sub edx, ecx |
mov [pg_data.pages_free-OS_BASE], edx |
mov edi, sys_pgmap-OS_BASE |
mov ebx, ecx |
shr ecx, 5 |
xor eax, eax |
rep stosd |
not eax |
mov ecx, ebx |
and ecx, 31 |
shl eax, cl |
and [edi], eax |
add edi, OS_BASE |
mov [page_start-OS_BASE], edi; |
mov ebx, sys_pgmap |
add ebx, [pg_data.pagemap_size-OS_BASE] |
mov [page_end-OS_BASE], ebx |
ret |
endp |
align 4 |
init_BIOS32: |
mov edi, 0xE0000 |
.pcibios_nxt: |
cmp dword[edi], '_32_' ; "magic" word |
je .BIOS32_found |
.pcibios_nxt2: |
add edi, 0x10 |
cmp edi, 0xFFFF0 |
je .BIOS32_not_found |
jmp .pcibios_nxt |
.BIOS32_found: ; magic word found, check control summ |
movzx ecx, byte[edi + 9] |
shl ecx, 4 |
mov esi, edi |
xor eax, eax |
cld ; paranoia |
@@: lodsb |
add ah, al |
loop @b |
jnz .pcibios_nxt2 ; control summ must be zero |
; BIOS32 service found ! |
mov ebp, [edi + 4] |
mov [bios32_entry], ebp |
; check PCI BIOS present |
mov eax, '$PCI' |
xor ebx, ebx |
push cs ; special for 'ret far' from BIOS |
call ebp |
test al, al |
jnz .PCI_BIOS32_not_found |
; çäåñü ñîçäàþòñÿ äèñêðèïòîðû äëÿ PCI BIOS |
add ebx, OS_BASE |
dec ecx |
mov [(pci_code_32-OS_BASE)], cx ;limit 0-15 |
mov [(pci_data_32-OS_BASE)], cx ;limit 0-15 |
mov [(pci_code_32-OS_BASE)+2], bx ;base 0-15 |
mov [(pci_data_32-OS_BASE)+2], bx ;base 0-15 |
shr ebx, 16 |
mov [(pci_code_32-OS_BASE)+4], bl ;base 16-23 |
mov [(pci_data_32-OS_BASE)+4], bl ;base 16-23 |
shr ecx, 16 |
and cl, 0x0F |
mov ch, bh |
add cx, D32 |
mov [(pci_code_32-OS_BASE)+6], cx ;lim 16-19 & |
mov [(pci_data_32-OS_BASE)+6], cx ;base 24-31 |
mov [(pci_bios_entry-OS_BASE)], edx |
; jmp .end |
.PCI_BIOS32_not_found: |
; çäåñü äîëæíà çàïîëíÿòñÿ pci_emu_dat |
.BIOS32_not_found: |
.end: |
ret |
align 4 |
proc test_cpu |
locals |
cpu_type dd ? |
cpu_id dd ? |
cpu_Intel dd ? |
cpu_AMD dd ? |
endl |
xor eax, eax |
mov [cpu_type], eax |
mov [cpu_caps-OS_BASE], eax |
mov [cpu_caps+4-OS_BASE], eax |
pushfd |
pop eax |
mov ecx, eax |
xor eax, 0x40000 |
push eax |
popfd |
pushfd |
pop eax |
xor eax, ecx |
mov [cpu_type], CPU_386 |
jz .end_cpuid |
push ecx |
popfd |
mov [cpu_type], CPU_486 |
mov eax, ecx |
xor eax, 0x200000 |
push eax |
popfd |
pushfd |
pop eax |
xor eax, ecx |
je .end_cpuid |
mov [cpu_id], 1 |
xor eax, eax |
cpuid |
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 |
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 |
.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 |
uglobal |
align 4 |
acpi_rsdp rd 1 |
acpi_rsdt rd 1 |
acpi_madt rd 1 |
acpi_dev_data rd 1 |
acpi_dev_size rd 1 |
acpi_rsdt_base rd 1 |
acpi_madt_base rd 1 |
acpi_lapic_base rd 1 |
acpi_ioapic_base rd 1 |
endg |
ACPI_HI_RSDP_WINDOW_START equ 0x000E0000 |
ACPI_HI_RSDP_WINDOW_END equ 0x00100000 |
ACPI_RSDP_CHECKSUM_LENGTH equ 20 |
ACPI_MADT_SIGN equ 0x43495041 |
acpi_locate: |
push ebx |
mov ebx, ACPI_HI_RSDP_WINDOW_START |
.check: |
cmp [ebx], dword 0x20445352 |
jne .next |
cmp [ebx+4], dword 0x20525450 |
jne .next |
mov edx, ebx |
mov ecx, ACPI_RSDP_CHECKSUM_LENGTH |
xor eax, eax |
.sum: |
add al, [edx] |
inc edx |
loop .sum |
test al, al |
jnz .next |
mov eax, ebx |
pop ebx |
ret |
.next: |
add ebx, 16 |
cmp ebx, ACPI_HI_RSDP_WINDOW_END |
jb .check |
pop ebx |
xor eax, eax |
ret |
align 4 |
rsdt_find: ;ecx= rsdt edx= SIG |
push ebx |
push esi |
lea ebx, [ecx+36] |
mov esi, [ecx+4] |
add esi, ecx |
.next: |
mov eax, [ebx] |
cmp [eax], edx |
je .done |
add ebx, 4 |
cmp ebx, esi |
jb .next |
xor eax, eax |
pop esi |
pop ebx |
ret |
.done: |
mov eax, [ebx] |
pop esi |
pop ebx |
ret |
align 4 |
check_acpi: |
call acpi_locate |
test eax, eax |
jz .done |
mov ecx, [eax+16] |
mov edx, ACPI_MADT_SIGN |
mov [acpi_rsdt_base-OS_BASE], ecx |
call rsdt_find |
test eax, eax |
jz .done |
mov [acpi_madt_base-OS_BASE], eax |
mov ecx, [eax+36] |
mov [acpi_lapic_base-OS_BASE], ecx |
lea edx, [eax+44] |
mov ecx, [eax+4] |
add ecx, eax |
.check: |
mov eax, [edx] |
cmp al, 1 |
je .ioapic |
.next: |
movzx eax, ah |
add edx, eax |
cmp edx, ecx |
jb .check |
.done: |
ret |
.ioapic: |
mov eax, [edx+4] |
mov [acpi_ioapic_base-OS_BASE], eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
MEM_WB equ 6 ;write-back memory |
MEM_WC equ 1 ;write combined memory |
MEM_UC equ 0 ;uncached memory |
align 4 |
proc mem_test |
; if we have BIOS with fn E820, skip the test |
cmp dword [BOOT_VAR-OS_BASE + 0x9100], 0 |
jnz .ret |
mov eax, cr0 |
and eax, not (CR0_CD+CR0_NW) |
or eax, CR0_CD ;disable caching |
mov cr0, eax |
wbinvd ;invalidate cache |
xor edi, edi |
mov ebx, 'TEST' |
@@: |
add edi, 0x100000 |
xchg ebx, dword [edi] |
cmp dword [edi], 'TEST' |
xchg ebx, dword [edi] |
je @b |
and eax, not (CR0_CD+CR0_NW) ;enable caching |
mov cr0, eax |
inc dword [BOOT_VAR-OS_BASE + 0x9100] |
xor eax, eax |
mov [BOOT_VAR-OS_BASE + 0x9104], eax |
mov [BOOT_VAR-OS_BASE + 0x9108], eax |
mov [BOOT_VAR-OS_BASE + 0x910C], edi |
mov [BOOT_VAR-OS_BASE + 0x9110], eax |
.ret: |
ret |
endp |
align 4 |
proc init_mem |
; calculate maximum allocatable address and number of allocatable pages |
mov edi, BOOT_VAR-OS_BASE + 0x9104 |
mov ecx, [edi-4] |
xor esi, esi; esi will hold total amount of memory |
xor edx, edx; edx will hold maximum allocatable address |
.calcmax: |
; round all to pages |
mov eax, [edi] |
test eax, 0xFFF |
jz @f |
neg eax |
and eax, 0xFFF |
add [edi], eax |
adc dword [edi+4], 0 |
sub [edi+8], eax |
sbb dword [edi+12], 0 |
jc .unusable |
@@: |
and dword [edi+8], not 0xFFF |
jz .unusable |
; ignore memory after 4 Gb |
cmp dword [edi+4], 0 |
jnz .unusable |
mov eax, [edi] |
cmp dword [edi+12], 0 |
jnz .overflow |
add eax, [edi+8] |
jnc @f |
.overflow: |
mov eax, 0xFFFFF000 |
@@: |
cmp edx, eax |
jae @f |
mov edx, eax |
@@: |
sub eax, [edi] |
mov [edi+8], eax |
add esi, eax |
jmp .usable |
.unusable: |
and dword [edi+8], 0 |
.usable: |
add edi, 20 |
loop .calcmax |
.calculated: |
mov [MEM_AMOUNT-OS_BASE], esi |
mov [pg_data.mem_amount-OS_BASE], esi |
shr esi, 12 |
mov [pg_data.pages_count-OS_BASE], esi |
shr edx, 12 |
add edx, 31 |
and edx, not 31 |
shr edx, 3 |
mov [pg_data.pagemap_size-OS_BASE], edx |
add edx, (sys_pgmap-OS_BASE)+4095 |
and edx, not 4095 |
mov [tmp_page_tabs], edx |
mov edx, esi |
and edx, -1024 |
cmp edx, (OS_BASE/4096) |
jbe @F |
mov edx, (OS_BASE/4096) |
jmp .set |
@@: |
cmp edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096 |
jae .set |
mov edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096 |
.set: |
mov [pg_data.kernel_pages-OS_BASE], edx |
shr edx, 10 |
mov [pg_data.kernel_tables-OS_BASE], edx |
xor eax, eax |
mov edi, sys_pgdir-OS_BASE |
mov ecx, 4096/4 |
cld |
rep stosd |
mov edx, (sys_pgdir-OS_BASE)+ 0x800; (OS_BASE shr 20) |
bt [cpu_caps-OS_BASE], CAPS_PSE |
jnc .no_PSE |
mov ebx, cr4 |
or ebx, CR4_PSE |
mov eax, PG_LARGE+PG_SW |
mov cr4, ebx |
dec [pg_data.kernel_tables-OS_BASE] |
mov [edx], eax |
add edx, 4 |
mov edi, [tmp_page_tabs] |
jmp .map_kernel_heap ; new kernel fits to the first 4Mb - nothing to do with ".map_low" |
.no_PSE: |
mov eax, PG_SW |
mov ecx, [tmp_page_tabs] |
shr ecx, 12 |
.map_low: |
mov edi, [tmp_page_tabs] |
@@: ; |
stosd |
add eax, 0x1000 |
dec ecx |
jnz @B |
.map_kernel_heap: |
mov ecx, [pg_data.kernel_tables-OS_BASE] |
shl ecx, 10 |
xor eax, eax |
rep stosd |
mov ecx, [pg_data.kernel_tables-OS_BASE] |
mov eax, [tmp_page_tabs] |
or eax, PG_SW |
mov edi, edx |
.map_kernel_tabs: |
stosd |
add eax, 0x1000 |
dec ecx |
jnz .map_kernel_tabs |
mov dword [sys_pgdir-OS_BASE+(page_tabs shr 20)], sys_pgdir+PG_SW-OS_BASE |
mov edi, (sys_pgdir-OS_BASE) |
lea esi, [edi+(OS_BASE shr 20)] |
movsd |
movsd |
ret |
endp |
align 4 |
proc init_page_map |
; mark all memory as unavailable |
mov edi, sys_pgmap-OS_BASE |
mov ecx, [pg_data.pagemap_size-OS_BASE] |
shr ecx, 2 |
xor eax, eax |
cld |
rep stosd |
; scan through memory map and mark free areas as available |
mov ebx, BOOT_VAR-OS_BASE + 0x9104 |
mov edx, [ebx-4] |
.scanmap: |
mov ecx, [ebx+8] |
shr ecx, 12; ecx = number of pages |
jz .next |
mov edi, [ebx] |
shr edi, 12; edi = first page |
mov eax, edi |
shr edi, 5 |
shl edi, 2 |
add edi, sys_pgmap-OS_BASE |
and eax, 31 |
jz .startok |
add ecx, eax |
sub ecx, 32 |
jbe .onedword |
push ecx |
mov ecx, eax |
or eax, -1 |
shl eax, cl |
or [edi], eax |
add edi, 4 |
pop ecx |
.startok: |
push ecx |
shr ecx, 5 |
or eax, -1 |
rep stosd |
pop ecx |
and ecx, 31 |
neg eax |
shl eax, cl |
dec eax |
or [edi], eax |
jmp .next |
.onedword: |
add ecx, 32 |
sub ecx, eax |
@@: |
bts [edi], eax |
inc eax |
loop @b |
.next: |
add ebx, 20 |
dec edx |
jnz .scanmap |
; mark kernel memory as allocated (unavailable) |
mov ecx, [tmp_page_tabs] |
mov edx, [pg_data.pages_count-OS_BASE] |
shr ecx, 12 |
add ecx, [pg_data.kernel_tables-OS_BASE] |
sub edx, ecx |
mov [pg_data.pages_free-OS_BASE], edx |
mov edi, sys_pgmap-OS_BASE |
mov ebx, ecx |
shr ecx, 5 |
xor eax, eax |
rep stosd |
not eax |
mov ecx, ebx |
and ecx, 31 |
shl eax, cl |
and [edi], eax |
add edi, OS_BASE |
mov [page_start-OS_BASE], edi; |
mov ebx, sys_pgmap |
add ebx, [pg_data.pagemap_size-OS_BASE] |
mov [page_end-OS_BASE], ebx |
ret |
endp |
align 4 |
init_BIOS32: |
mov edi, 0xE0000 |
.pcibios_nxt: |
cmp dword[edi], '_32_'; "magic" word |
je .BIOS32_found |
.pcibios_nxt2: |
add edi, 0x10 |
cmp edi, 0xFFFF0 |
je .BIOS32_not_found |
jmp .pcibios_nxt |
.BIOS32_found: ; magic word found, check control summ |
movzx ecx, byte[edi + 9] |
shl ecx, 4 |
mov esi, edi |
xor eax, eax |
cld ; paranoia |
@@: |
lodsb |
add ah, al |
loop @b |
jnz .pcibios_nxt2; control summ must be zero |
; BIOS32 service found ! |
mov ebp, [edi + 4] |
mov [bios32_entry], ebp |
; check PCI BIOS present |
mov eax, '$PCI' |
xor ebx, ebx |
push cs ; special for 'ret far' from BIOS |
call ebp |
test al, al |
jnz .PCI_BIOS32_not_found |
; çäåñü ñîçäàþòñÿ äèñêðèïòîðû äëÿ PCI BIOS |
add ebx, OS_BASE |
dec ecx |
mov [(pci_code_32-OS_BASE)], cx ;limit 0-15 |
mov [(pci_data_32-OS_BASE)], cx ;limit 0-15 |
mov [(pci_code_32-OS_BASE)+2], bx ;base 0-15 |
mov [(pci_data_32-OS_BASE)+2], bx ;base 0-15 |
shr ebx, 16 |
mov [(pci_code_32-OS_BASE)+4], bl ;base 16-23 |
mov [(pci_data_32-OS_BASE)+4], bl ;base 16-23 |
shr ecx, 16 |
and cl, 0x0F |
mov ch, bh |
add cx, D32 |
mov [(pci_code_32-OS_BASE)+6], cx ;lim 16-19 & |
mov [(pci_data_32-OS_BASE)+6], cx ;base 24-31 |
mov [(pci_bios_entry-OS_BASE)], edx |
; jmp .end |
.PCI_BIOS32_not_found: |
; çäåñü äîëæíà çàïîëíÿòñÿ pci_emu_dat |
.BIOS32_not_found: |
.end: |
ret |
align 4 |
proc test_cpu |
locals |
cpu_type dd ? |
cpu_id dd ? |
cpu_Intel dd ? |
cpu_AMD dd ? |
endl |
xor eax, eax |
mov [cpu_type], eax |
mov [cpu_caps-OS_BASE], eax |
mov [cpu_caps+4-OS_BASE], eax |
pushfd |
pop eax |
mov ecx, eax |
xor eax, 0x40000 |
push eax |
popfd |
pushfd |
pop eax |
xor eax, ecx |
mov [cpu_type], CPU_386 |
jz .end_cpuid |
push ecx |
popfd |
mov [cpu_type], CPU_486 |
mov eax, ecx |
xor eax, 0x200000 |
push eax |
popfd |
pushfd |
pop eax |
xor eax, ecx |
je .end_cpuid |
mov [cpu_id], 1 |
xor eax, eax |
cpuid |
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 |
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 |
.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 |
uglobal |
align 4 |
acpi_rsdp rd 1 |
acpi_rsdt rd 1 |
acpi_madt rd 1 |
acpi_dev_data rd 1 |
acpi_dev_size rd 1 |
acpi_rsdt_base rd 1 |
acpi_madt_base rd 1 |
acpi_lapic_base rd 1 |
acpi_ioapic_base rd 1 |
endg |
ACPI_HI_RSDP_WINDOW_START equ 0x000E0000 |
ACPI_HI_RSDP_WINDOW_END equ 0x00100000 |
ACPI_RSDP_CHECKSUM_LENGTH equ 20 |
ACPI_MADT_SIGN equ 0x43495041 |
acpi_locate: |
push ebx |
mov ebx, ACPI_HI_RSDP_WINDOW_START |
.check: |
cmp [ebx], dword 0x20445352 |
jne .next |
cmp [ebx+4], dword 0x20525450 |
jne .next |
mov edx, ebx |
mov ecx, ACPI_RSDP_CHECKSUM_LENGTH |
xor eax, eax |
.sum: |
add al, [edx] |
inc edx |
loop .sum |
test al, al |
jnz .next |
mov eax, ebx |
pop ebx |
ret |
.next: |
add ebx, 16 |
cmp ebx, ACPI_HI_RSDP_WINDOW_END |
jb .check |
pop ebx |
xor eax, eax |
ret |
align 4 |
rsdt_find: ;ecx= rsdt edx= SIG |
push ebx |
push esi |
lea ebx, [ecx+36] |
mov esi, [ecx+4] |
add esi, ecx |
.next: |
mov eax, [ebx] |
cmp [eax], edx |
je .done |
add ebx, 4 |
cmp ebx, esi |
jb .next |
xor eax, eax |
pop esi |
pop ebx |
ret |
.done: |
mov eax, [ebx] |
pop esi |
pop ebx |
ret |
align 4 |
check_acpi: |
call acpi_locate |
test eax, eax |
jz .done |
mov ecx, [eax+16] |
mov edx, ACPI_MADT_SIGN |
mov [acpi_rsdt_base-OS_BASE], ecx |
call rsdt_find |
test eax, eax |
jz .done |
mov [acpi_madt_base-OS_BASE], eax |
mov ecx, [eax+36] |
mov [acpi_lapic_base-OS_BASE], ecx |
lea edx, [eax+44] |
mov ecx, [eax+4] |
add ecx, eax |
.check: |
mov eax, [edx] |
cmp al, 1 |
je .ioapic |
.next: |
movzx eax, ah |
add edx, eax |
cmp edx, ecx |
jb .check |
.done: |
ret |
.ioapic: |
mov eax, [edx+4] |
mov [acpi_ioapic_base-OS_BASE], eax |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/kernel.asm |
---|
1,5088 → 1,5097 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. |
;; PROGRAMMING: |
;; Ivan Poddubny |
;; Marat Zakiyanov (Mario79) |
;; VaStaNi |
;; Trans |
;; Mihail Semenyako (mike.dld) |
;; Sergey Kuzmin (Wildwest) |
;; Andrey Halyavin (halyavin) |
;; Mihail Lisovin (Mihasik) |
;; Andrey Ignatiev (andrew_programmer) |
;; NoName |
;; Evgeny Grechnikov (Diamond) |
;; Iliya Mihailov (Ghost) |
;; Sergey Semyonov (Serge) |
;; Johnny_B |
;; SPraid (simba) |
;; Hidnplayr |
;; Alexey Teplov (<Lrz>) |
;; Rus |
;; Nable |
;; shurf |
;; Alver |
;; Maxis |
;; Galkov |
;; CleverMouse |
;; tsdima |
;; turbanoff |
;; Asper |
;; art_zh |
;; |
;; Data in this file was originally part of MenuetOS project which is |
;; distributed under the terms of GNU GPL. It is modified and redistributed as |
;; part of KolibriOS project under the terms of GNU GPL. |
;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa |
;; PROGRAMMING: |
;; |
;; Ville Mikael Turjanmaa, villemt@itu.jyu.fi |
;; - main os coding/design |
;; Jan-Michael Brummer, BUZZ2@gmx.de |
;; Felix Kaiser, info@felix-kaiser.de |
;; Paolo Minazzi, paolo.minazzi@inwind.it |
;; quickcode@mail.ru |
;; Alexey, kgaz@crosswinds.net |
;; Juan M. Caravaca, bitrider@wanadoo.es |
;; kristol@nic.fi |
;; Mike Hibbett, mikeh@oceanfree.net |
;; Lasse Kuusijarvi, kuusijar@lut.fi |
;; Jarek Pelczar, jarekp3@wp.pl |
;; |
;; KolibriOS is distributed in the hope that it will be useful, but WITHOUT ANY |
;; WARRANTY. No author or distributor accepts responsibility to anyone for the |
;; consequences of using it or for whether it serves any particular purpose or |
;; works at all, unless he says so in writing. Refer to the GNU General Public |
;; License (the "GPL") for full details. |
; |
;; Everyone is granted permission to copy, modify and redistribute KolibriOS, |
;; but only under the conditions described in the GPL. A copy of this license |
;; is supposed to have been given to you along with KolibriOS so you can know |
;; your rights and responsibilities. It should be in a file named COPYING. |
;; Among other things, the copyright notice and this notice must be preserved |
;; on all copies. |
;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include 'macros.inc' |
$Revision$ |
USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices |
; Enabling the next line will enable serial output console |
;debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used |
include "proc32.inc" |
include "kglobals.inc" |
include "lang.inc" |
include "const.inc" |
max_processes equ 255 |
tss_step equ (128+8192) ; tss & i/o - 65535 ports, * 256=557056*4 |
os_stack equ (os_data_l-gdts) ; GDTs |
os_code equ (os_code_l-gdts) |
graph_data equ (3+graph_data_l-gdts) |
tss0 equ (tss0_l-gdts) |
app_code equ (3+app_code_l-gdts) |
app_data equ (3+app_data_l-gdts) |
app_tls equ (3+tls_data_l-gdts) |
pci_code_sel equ (pci_code_32-gdts) |
pci_data_sel equ (pci_data_32-gdts) |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; |
;; Included files: |
;; |
;; Kernel16.inc |
;; - Booteng.inc English text for bootup |
;; - Bootcode.inc Hardware setup |
;; - Pci16.inc PCI functions |
;; |
;; Kernel32.inc |
;; - Sys32.inc Process management |
;; - Shutdown.inc Shutdown and restart |
;; - Fat32.inc Read / write hd |
;; - Vesa12.inc Vesa 1.2 driver |
;; - Vesa20.inc Vesa 2.0 driver |
;; - Vga.inc VGA driver |
;; - Stack.inc Network interface |
;; - Mouse.inc Mouse pointer |
;; - Scincode.inc Window skinning |
;; - Pci32.inc PCI functions |
;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 16 BIT ENTRY FROM BOOTSECTOR ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
use16 |
org 0x0 |
jmp start_of_code |
version db 'Kolibri OS version 0.7.7.0+ ',13,10,13,10,0 |
include "boot/bootstr.inc" ; language-independent boot messages |
include "boot/preboot.inc" |
if lang eq en |
include "boot/booteng.inc" ; english system boot messages |
else if lang eq ru |
include "boot/bootru.inc" ; russian system boot messages |
include "boot/ru.inc" ; Russian font |
else if lang eq et |
include "boot/bootet.inc" ; estonian system boot messages |
include "boot/et.inc" ; Estonian font |
else |
include "boot/bootge.inc" ; german system boot messages |
end if |
include "boot/bootcode.inc" ; 16 bit system boot code |
include "bus/pci/pci16.inc" |
include "detect/biosdisk.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SWITCH TO 32 BIT PROTECTED MODE ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CR0 Flags - Protected mode and Paging |
mov ecx, CR0_PE |
; Enabling 32 bit protected mode |
sidt [cs:old_ints_h] |
cli ; disable all irqs |
cld |
mov al,255 ; mask all irqs |
out 0xa1,al |
out 0x21,al |
l.5: in al, 0x64 ; Enable A20 |
test al, 2 |
jnz l.5 |
mov al, 0xD1 |
out 0x64, al |
l.6: in al, 0x64 |
test al, 2 |
jnz l.6 |
mov al, 0xDF |
out 0x60, al |
l.7: in al, 0x64 |
test al, 2 |
jnz l.7 |
mov al, 0xFF |
out 0x64, al |
lgdt [cs:tmp_gdt] ; Load GDT |
mov eax, cr0 ; protected mode |
or eax, ecx |
and eax, 10011111b *65536*256 + 0xffffff ; caching enabled |
mov cr0, eax |
jmp pword os_code:B32 ; jmp to enable 32 bit mode |
align 8 |
tmp_gdt: |
dw 23 |
dd tmp_gdt+0x10000 |
dw 0 |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10011010b |
db 0x00 |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10010010b |
db 0x00 |
include "data16.inc" |
use32 |
org $+0x10000 |
align 4 |
B32: |
mov ax,os_stack ; Selector for os |
mov ds,ax |
mov es,ax |
mov fs,ax |
mov gs,ax |
mov ss,ax |
mov esp,0x006CC00 ; Set stack |
; CLEAR 0x280000 - HEAP_BASE |
xor eax,eax |
mov edi,CLEAN_ZONE |
mov ecx,(HEAP_BASE-OS_BASE-CLEAN_ZONE) / 4 |
cld |
rep stosd |
; CLEAR KERNEL UNDEFINED GLOBALS |
mov edi, endofcode-OS_BASE |
mov ecx, 0x90000 |
sub ecx, edi |
shr ecx, 2 |
rep stosd |
; SAVE & CLEAR 0-0xffff |
xor esi, esi |
mov edi,(BOOT_VAR-OS_BASE) |
mov ecx,0x10000 / 4 |
rep movsd |
mov edi,0x1000 |
mov ecx,0xf000 / 4 |
rep stosd |
call test_cpu |
bts [cpu_caps-OS_BASE], CAPS_TSC ;force use rdtsc |
call check_acpi |
call init_BIOS32 |
; MEMORY MODEL |
call mem_test |
call init_mem |
call init_page_map |
; ENABLE PAGING |
mov eax, sys_pgdir-OS_BASE |
mov cr3, eax |
mov eax,cr0 |
or eax,CR0_PG+CR0_WP |
mov cr0,eax |
lgdt [gdts] |
jmp pword os_code:high_code |
align 4 |
bios32_entry dd ? |
tmp_page_tabs dd ? |
use16 |
org $-0x10000 |
include "boot/shutdown.inc" ; shutdown or restart |
org $+0x10000 |
use32 |
__DEBUG__ fix 1 |
__DEBUG_LEVEL__ fix 1 |
include 'init.inc' |
org OS_BASE+$ |
align 4 |
high_code: |
mov ax, os_stack |
mov bx, app_data |
mov cx, app_tls |
mov ss, ax |
add esp, OS_BASE |
mov ds, bx |
mov es, bx |
mov fs, cx |
mov gs, bx |
bt [cpu_caps], CAPS_PGE |
jnc @F |
or dword [sys_pgdir+(OS_BASE shr 20)], PG_GLOBAL |
mov ebx, cr4 |
or ebx, CR4_PGE |
mov cr4, ebx |
@@: |
xor eax, eax |
mov dword [sys_pgdir], eax |
mov dword [sys_pgdir+4], eax |
mov eax, cr3 |
mov cr3, eax ; flush TLB |
mov ecx, pg_data.mutex |
call mutex_init |
mov ecx, disk_list_mutex |
call mutex_init |
; SAVE REAL MODE VARIABLES |
mov ax, [BOOT_VAR + 0x9031] |
mov [IDEContrRegsBaseAddr], ax |
; --------------- APM --------------------- |
; init selectors |
mov ebx,[BOOT_VAR+0x9040] ; offset of APM entry point |
movzx eax,word [BOOT_VAR+0x9050] ; real-mode segment base address of |
; protected-mode 32-bit code segment |
movzx ecx,word [BOOT_VAR+0x9052] ; real-mode segment base address of |
; protected-mode 16-bit code segment |
movzx edx,word [BOOT_VAR+0x9054] ; real-mode segment base address of |
; protected-mode 16-bit data segment |
shl eax, 4 |
mov [dword apm_code_32 + 2], ax |
shr eax, 16 |
mov [dword apm_code_32 + 4], al |
shl ecx, 4 |
mov [dword apm_code_16 + 2], cx |
shr ecx, 16 |
mov [dword apm_code_16 + 4], cl |
shl edx, 4 |
mov [dword apm_data_16 + 2], dx |
shr edx, 16 |
mov [dword apm_data_16 + 4], dl |
mov dword[apm_entry], ebx |
mov word [apm_entry + 4], apm_code_32 - gdts |
mov eax, [BOOT_VAR + 0x9044] ; version & flags |
mov [apm_vf], eax |
; ----------------------------------------- |
; movzx eax,byte [BOOT_VAR+0x9010] ; mouse port |
; mov [0xF604],byte 1 ;al |
mov al, [BOOT_VAR+0x901F] ; DMA access |
mov [allow_dma_access], al |
movzx eax, byte [BOOT_VAR+0x9000] ; bpp |
mov [ScreenBPP],al |
mov [_display.bpp], eax |
mov [_display.vrefresh], 60 |
mov [_display.disable_mouse], __sys_disable_mouse |
movzx eax,word [BOOT_VAR+0x900A] ; X max |
mov [_display.width], eax |
dec eax |
mov [Screen_Max_X],eax |
mov [screen_workarea.right],eax |
movzx eax,word [BOOT_VAR+0x900C] ; Y max |
mov [_display.height], eax |
dec eax |
mov [Screen_Max_Y],eax |
mov [screen_workarea.bottom],eax |
movzx eax,word [BOOT_VAR+0x9008] ; screen mode |
mov [SCR_MODE],eax |
mov eax,[BOOT_VAR+0x9014] ; Vesa 1.2 bnk sw add |
mov [BANK_SWITCH],eax |
mov [BytesPerScanLine],word 640*4 ; Bytes PerScanLine |
cmp [SCR_MODE],word 0x13 ; 320x200 |
je @f |
cmp [SCR_MODE],word 0x12 ; VGA 640x480 |
je @f |
movzx eax, word[BOOT_VAR+0x9001] ; for other modes |
mov [BytesPerScanLine],ax |
mov [_display.pitch], eax |
@@: |
mov eax, [_display.width] |
mul [_display.height] |
mov [_WinMapSize], eax |
mov esi, BOOT_VAR+0x9080 |
movzx ecx, byte [esi-1] |
mov [NumBiosDisks], ecx |
mov edi, BiosDisksData |
rep movsd |
; GRAPHICS ADDRESSES |
and byte [BOOT_VAR+0x901e],0x0 |
mov eax,[BOOT_VAR+0x9018] |
mov [LFBAddress],eax |
cmp [SCR_MODE],word 0100000000000000b |
jge setvesa20 |
cmp [SCR_MODE],word 0x13 |
je v20ga32 |
mov [PUTPIXEL],dword Vesa12_putpixel24 ; Vesa 1.2 |
mov [GETPIXEL],dword Vesa12_getpixel24 |
cmp [ScreenBPP],byte 24 |
jz ga24 |
mov [PUTPIXEL],dword Vesa12_putpixel32 |
mov [GETPIXEL],dword Vesa12_getpixel32 |
ga24: |
jmp v20ga24 |
setvesa20: |
mov [PUTPIXEL],dword Vesa20_putpixel24 ; Vesa 2.0 |
mov [GETPIXEL],dword Vesa20_getpixel24 |
cmp [ScreenBPP],byte 24 |
jz v20ga24 |
v20ga32: |
mov [PUTPIXEL],dword Vesa20_putpixel32 |
mov [GETPIXEL],dword Vesa20_getpixel32 |
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: |
; -------- Fast System Call init ---------- |
; Intel SYSENTER/SYSEXIT (AMD CPU support it too) |
bt [cpu_caps], CAPS_SEP |
jnc .SEnP ; SysEnter not Present |
xor edx, edx |
mov ecx, MSR_SYSENTER_CS |
mov eax, os_code |
wrmsr |
mov ecx, MSR_SYSENTER_ESP |
; mov eax, sysenter_stack ; Check it |
xor eax, eax |
wrmsr |
mov ecx, MSR_SYSENTER_EIP |
mov eax, sysenter_entry |
wrmsr |
.SEnP: |
; AMD SYSCALL/SYSRET |
cmp byte[cpu_vendor], 'A' |
jne .noSYSCALL |
mov eax, 0x80000001 |
cpuid |
test edx, 0x800 ; bit_11 - SYSCALL/SYSRET support |
jz .noSYSCALL |
mov ecx, MSR_AMD_EFER |
rdmsr |
or eax, 1 ; bit_0 - System Call Extension (SCE) |
wrmsr |
; !!!! It`s dirty hack, fix it !!! |
; Bits of EDX : |
; Bit 3116 During the SYSRET instruction, this field is copied into the CS register |
; and the contents of this field, plus 8, are copied into the SS register. |
; Bit 150 During the SYSCALL instruction, this field is copied into the CS register |
; and the contents of this field, plus 8, are copied into the SS register. |
; mov edx, (os_code + 16) * 65536 + os_code |
mov edx, 0x1B0008 |
mov eax, syscall_entry |
mov ecx, MSR_AMD_STAR |
wrmsr |
.noSYSCALL: |
; ----------------------------------------- |
stdcall alloc_page |
stdcall map_page, tss-0xF80, eax, PG_SW |
stdcall alloc_page |
inc eax |
mov [SLOT_BASE+256+APPDATA.io_map], eax |
stdcall map_page, tss+0x80, eax, PG_SW |
stdcall alloc_page |
inc eax |
mov dword [SLOT_BASE+256+APPDATA.io_map+4], eax |
stdcall map_page, tss+0x1080, eax, PG_SW |
; LOAD IDT |
call build_interrupt_table ;lidt is executed |
;lidt [idtreg] |
call init_kernel_heap |
stdcall kernel_alloc, RING0_STACK_SIZE+512 |
mov [os_stack_seg], eax |
lea esp, [eax+RING0_STACK_SIZE] |
mov [tss._ss0], os_stack |
mov [tss._esp0], esp |
mov [tss._esp], esp |
mov [tss._cs],os_code |
mov [tss._ss],os_stack |
mov [tss._ds],app_data |
mov [tss._es],app_data |
mov [tss._fs],app_data |
mov [tss._gs],app_data |
mov [tss._io],128 |
;Add IO access table - bit array of permitted ports |
mov edi, tss._io_map_0 |
xor eax, eax |
not eax |
mov ecx, 8192/4 |
rep stosd ; access to 4096*8=65536 ports |
mov ax,tss0 |
ltr ax |
mov [LFBSize], 0x800000 |
call init_LFB |
call init_fpu |
call init_malloc |
stdcall alloc_kernel_space, 0x51000 |
mov [default_io_map], eax |
add eax, 0x2000 |
mov [ipc_tmp], eax |
mov ebx, 0x1000 |
add eax, 0x40000 |
mov [proc_mem_map], eax |
add eax, 0x8000 |
mov [proc_mem_pdir], eax |
add eax, ebx |
mov [proc_mem_tab], eax |
add eax, ebx |
mov [tmp_task_pdir], eax |
add eax, ebx |
mov [tmp_task_ptab], eax |
add eax, ebx |
mov [ipc_pdir], eax |
add eax, ebx |
mov [ipc_ptab], eax |
stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl \ |
(unpack.lc+unpack.lp)))*4 |
mov [unpack.p], eax |
call init_events |
mov eax, srv.fd-SRV_FD_OFFSET |
mov [srv.fd], eax |
mov [srv.bk], eax |
;Set base of graphic segment to linear address of LFB |
mov eax,[LFBAddress] ; set for gs |
mov [graph_data_l+2],ax |
shr eax,16 |
mov [graph_data_l+4],al |
mov [graph_data_l+7],ah |
stdcall kernel_alloc, [_WinMapSize] |
mov [_WinMapAddress], eax |
xor eax,eax |
inc eax |
mov [CURRENT_TASK],eax ;dword 1 |
mov [TASK_COUNT],eax ;dword 1 |
mov [TASK_BASE],dword TASK_DATA |
mov [current_slot], SLOT_BASE+256 |
; set background |
mov [BgrDrawMode],eax |
mov [BgrDataWidth],eax |
mov [BgrDataHeight],eax |
mov [mem_BACKGROUND], 4 |
mov [img_background], static_background_data |
mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE |
stdcall kernel_alloc, 0x10000/8 |
mov edi, eax |
mov [network_free_ports], eax |
or eax, -1 |
mov ecx, 0x10000/32 |
rep stosd |
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f |
call init_irqs |
call PIC_init |
; Initialize system V86 machine |
call init_sys_v86 |
; Initialize system timer (IRQ0) |
call PIT_init |
; Try to Initialize APIC |
call APIC_init |
; Enable timer IRQ (IRQ0) and hard drives IRQs (IRQ14, IRQ15) |
; they are used: when partitions are scanned, hd_read relies on timer |
call unmask_timer |
stdcall enable_irq, 2 ; @#$%! PIC |
stdcall enable_irq, 6 ; FDD |
stdcall enable_irq, 13 ; co-processor |
stdcall enable_irq, 14 |
stdcall enable_irq, 15 |
; Enable interrupts in IDE controller |
mov al, 0 |
mov dx, 0x3F6 |
out dx, al |
mov dl, 0x76 |
out dx, al |
;!!!!!!!!!!!!!!!!!!!!!!!!!! |
include 'detect/disks.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!!!! |
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 |
; CALCULATE FAT CHAIN FOR RAMDISK |
call calculatefatchain |
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} |
je no_lib_load |
; LOADING LIBRARES |
stdcall dll.Load,@IMPORT ; loading librares for kernel (.obj files) |
call load_file_parse_table ; prepare file parse table |
call set_kernel_conf ; configure devices and gui |
no_lib_load: |
end if |
; LOAD FONTS I and II |
stdcall read_file, char, FONT_I, 0, 2304 |
stdcall read_file, char2, FONT_II, 0, 2560 |
mov esi,boot_fonts |
call boot_log |
; Display APIC status |
mov esi, boot_APIC_found |
cmp [irq_mode], IRQ_APIC |
je @f |
mov esi, boot_APIC_nfound |
@@: |
; PRINT AMOUNT OF MEMORY |
mov esi, boot_memdetect |
call boot_log |
movzx ecx, word [boot_y] |
if lang eq ru |
or ecx, (10+30*6) shl 16 |
else |
or ecx, (10+29*6) shl 16 |
end if |
sub ecx, 10 |
mov edx, 0xFFFFFF |
mov ebx, [MEM_AMOUNT] |
shr ebx, 20 |
xor edi,edi |
mov eax, 0x00040000 |
inc edi |
call display_number_force |
; BUILD SCHEDULER |
call build_scheduler ; sys32.inc |
mov esi,boot_devices |
call boot_log |
mov [pci_access_enabled],1 |
; SET PRELIMINARY WINDOW STACK AND POSITIONS |
mov esi,boot_windefs |
call boot_log |
call set_window_defaults |
; SET BACKGROUND DEFAULTS |
mov esi,boot_bgr |
call boot_log |
call init_background |
call calculatebackground |
; RESERVE SYSTEM IRQ'S JA PORT'S |
mov esi,boot_resirqports |
call boot_log |
call reserve_irqs_ports |
; SET UP OS TASK |
mov esi,boot_setostask |
call boot_log |
xor eax, eax |
mov dword [SLOT_BASE+APPDATA.fpu_state], fpu_data |
mov dword [SLOT_BASE+APPDATA.exc_handler], eax |
mov dword [SLOT_BASE+APPDATA.except_mask], eax |
; name for OS/IDLE process |
mov dword [SLOT_BASE+256+APPDATA.app_name], dword 'OS/I' |
mov dword [SLOT_BASE+256+APPDATA.app_name+4], dword 'DLE ' |
mov edi, [os_stack_seg] |
mov dword [SLOT_BASE+256+APPDATA.pl0_stack], edi |
add edi, 0x2000-512 |
mov dword [SLOT_BASE+256+APPDATA.fpu_state], edi |
mov dword [SLOT_BASE+256+APPDATA.saved_esp0], edi ; just for case |
; [SLOT_BASE+256+APPDATA.io_map] was set earlier |
mov esi, fpu_data |
mov ecx, 512/4 |
cld |
rep movsd |
mov dword [SLOT_BASE+256+APPDATA.exc_handler], eax |
mov dword [SLOT_BASE+256+APPDATA.except_mask], eax |
mov ebx, SLOT_BASE+256+APP_OBJ_OFFSET |
mov dword [SLOT_BASE+256+APPDATA.fd_obj], ebx |
mov dword [SLOT_BASE+256+APPDATA.bk_obj], ebx |
mov dword [SLOT_BASE+256+APPDATA.cur_dir], sysdir_path |
mov dword [SLOT_BASE+256+APPDATA.tls_base], eax |
; task list |
mov dword [TASK_DATA+TASKDATA.mem_start],eax ; process base address |
inc eax |
mov dword [CURRENT_TASK],eax |
mov dword [TASK_COUNT],eax |
mov [current_slot], SLOT_BASE+256 |
mov [TASK_BASE],dword TASK_DATA |
mov byte[TASK_DATA+TASKDATA.wnd_number],al ; on screen number |
mov dword [TASK_DATA+TASKDATA.pid], eax ; process id number |
call init_display |
mov eax, [def_cursor] |
mov [SLOT_BASE+APPDATA.cursor],eax |
mov [SLOT_BASE+APPDATA.cursor+256],eax |
; READ TSC / SECOND |
mov esi,boot_tsc |
call boot_log |
cli |
rdtsc ;call _rdtsc |
mov ecx,eax |
mov esi,250 ; wait 1/4 a second |
call delay_ms |
rdtsc ;call _rdtsc |
sti |
sub eax,ecx |
shl eax,2 |
mov [CPU_FREQ],eax ; save tsc / sec |
; mov ebx, 1000000 |
; div ebx |
; ¢®®¡é¥-â® ¯à®¨§¢®¤¨â¥«ì®áâì ¢ ¤ ®¬ ª®ªà¥â®¬ ¬¥á⥠|
; ᮢ¥à襮 ¥ªà¨â¨ç , ® çâ®¡ë § âªãâì «î¡¨â¥«¥© |
; ®¯â¨¬¨§¨àãîé¨å ª®¬¯¨«ïâ®à®¢ ... |
mov edx, 2251799814 |
mul edx |
shr edx, 19 |
mov [stall_mcs], edx |
; PRINT CPU FREQUENCY |
mov esi, boot_cpufreq |
call boot_log |
mov ebx, edx |
movzx ecx, word [boot_y] |
if lang eq ru |
add ecx, (10+19*6) shl 16 - 10; 'Determining amount of memory' |
else |
add ecx, (10+17*6) shl 16 - 10; 'Determining amount of memory' |
end if |
mov edx, 0xFFFFFF |
xor edi,edi |
mov eax, 0x00040000 |
inc edi |
call display_number_force |
; SET VARIABLES |
call set_variables |
; STACK AND FDC |
call stack_init |
call fdc_init |
; PALETTE FOR 320x200 and 640x480 16 col |
cmp [SCR_MODE],word 0x12 |
jne no_pal_vga |
mov esi,boot_pal_vga |
call boot_log |
call paletteVGA |
no_pal_vga: |
cmp [SCR_MODE],word 0x13 |
jne no_pal_ega |
mov esi,boot_pal_ega |
call boot_log |
call palette320x200 |
no_pal_ega: |
; LOAD DEFAULT SKIN |
call load_default_skin |
;protect io permission map |
mov esi, [default_io_map] |
stdcall map_page,esi,[SLOT_BASE+256+APPDATA.io_map], PG_MAP |
add esi, 0x1000 |
stdcall map_page,esi,[SLOT_BASE+256+APPDATA.io_map+4], PG_MAP |
stdcall map_page,tss._io_map_0,\ |
[SLOT_BASE+256+APPDATA.io_map], PG_MAP |
stdcall map_page,tss._io_map_1,\ |
[SLOT_BASE+256+APPDATA.io_map+4], PG_MAP |
mov ax,[OS_BASE+0x10000+bx_from_load] |
cmp ax,'r1' ; if not rused ram disk - load network configuration from files {SPraid.simba} |
je no_st_network |
call set_network_conf |
no_st_network: |
; LOAD FIRST APPLICATION |
cli |
; cmp byte [BOOT_VAR+0x9030],1 |
; jne no_load_vrr_m |
; mov ebp, vrr_m |
; call fs_execute_from_sysdir |
; |
;; cmp eax,2 ; if vrr_m app found (PID=2) |
; sub eax,2 |
; jz first_app_found |
; |
;no_load_vrr_m: |
mov ebp, firstapp |
call fs_execute_from_sysdir |
; cmp eax,2 ; continue if a process has been loaded |
sub eax,2 |
jz first_app_found |
mov esi, boot_failed |
call boot_log |
mov eax, 0xDEADBEEF ; otherwise halt |
hlt |
first_app_found: |
cli |
;mov [TASK_COUNT],dword 2 |
push 1 |
pop dword [CURRENT_TASK] ; set OS task fisrt |
; SET KEYBOARD PARAMETERS |
mov al, 0xf6 ; reset keyboard, scan enabled |
call kb_write |
; wait until 8042 is ready |
xor ecx,ecx |
@@: |
in al,64h |
and al,00000010b |
loopnz @b |
; mov al, 0xED ; Keyboard LEDs - only for testing! |
; call kb_write |
; call kb_read |
; mov al, 111b |
; call kb_write |
; call kb_read |
mov al, 0xF3 ; set repeat rate & delay |
call kb_write |
; call kb_read |
mov al, 0 ; 30 250 ;00100010b ; 24 500 ;00100100b ; 20 500 |
call kb_write |
; call kb_read |
;// mike.dld [ |
call set_lights |
;// mike.dld ] |
stdcall attach_int_handler, 1, irq1, 0 |
; SET MOUSE |
stdcall load_driver, szPS2MDriver |
; stdcall load_driver, szCOM_MDriver |
mov esi,boot_setmouse |
call boot_log |
call setmouse |
; Setup serial output console (if enabled) |
if defined debug_com_base |
; enable Divisor latch |
mov dx, debug_com_base+3 |
mov al, 1 shl 7 |
out dx, al |
; 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 |
; START MULTITASKING |
; A 'All set - press ESC to start' messages if need |
if preboot_blogesc |
mov esi, boot_tasking |
call boot_log |
.bll1: in al, 0x60 ; wait for ESC key press |
cmp al, 129 |
jne .bll1 |
end if |
cmp [IDEContrRegsBaseAddr], 0 |
setnz [dma_hdd] |
mov [timer_ticks_enable],1 ; for cd driver |
sti |
call change_task |
jmp osloop |
; Fly :) |
include 'unpacker.inc' |
include 'fdo.inc' |
align 4 |
boot_log: |
pushad |
mov ebx,10*65536 |
mov bx,word [boot_y] |
add [boot_y],dword 10 |
mov ecx,0x80ffffff ; ASCIIZ string with white color |
xor edi,edi |
mov edx,esi |
inc edi |
call dtext |
mov [novesachecksum],1000 |
call checkVga_N13 |
popad |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; ; |
; MAIN OS LOOP START ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
osloop: |
call [draw_pointer] |
call window_check_events |
call mouse_check_events |
call checkmisc |
call checkVga_N13 |
call stack_handler |
call checkidle |
call check_fdd_motor_status |
call check_ATAPI_device_event |
call check_timers |
jmp osloop |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; ; |
; MAIN OS LOOP END ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
checkidle: |
pushad |
call change_task |
jmp idle_loop_entry |
idle_loop: |
cmp eax,[idlemem] ; eax == [timer_ticks] |
jne idle_exit |
rdtsc ;call _rdtsc |
mov ecx,eax |
hlt |
rdtsc ;call _rdtsc |
sub eax,ecx |
add [idleuse],eax |
idle_loop_entry: |
mov eax,[timer_ticks] ; eax = [timer_ticks] |
cmp [check_idle_semaphore],0 |
je idle_loop |
dec [check_idle_semaphore] |
idle_exit: |
mov [idlemem],eax ; eax == [timer_ticks] |
popad |
ret |
uglobal |
idlemem dd 0x0 |
idleuse dd 0x0 |
idleusesec dd 0x0 |
check_idle_semaphore dd 0x0 |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; ; |
; INCLUDED SYSTEM FILES ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include "kernel32.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; ; |
; KERNEL FUNCTIONS ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
reserve_irqs_ports: |
; RESERVE PORTS |
mov eax, RESERVED_PORTS |
mov ecx, 1 |
mov [eax], dword 4 |
mov [eax+16], ecx |
mov [eax+16+4], dword 0 |
mov [eax+16+4], dword 0x2D |
mov [eax+32], ecx |
mov [eax+32+4], dword 0x30 |
mov [eax+32+8], dword 0x4D |
mov [eax+48], ecx |
mov [eax+48+4], dword 0x50 |
mov [eax+28+8], dword 0xDF |
mov [eax+64], ecx |
mov [eax+64+4], dword 0xE5 |
mov [eax+64+8], dword 0xFF |
ret |
iglobal |
process_number dd 0x1 |
endg |
set_variables: |
mov ecx,0x16 ; flush port 0x60 |
.fl60: |
in al,0x60 |
loop .fl60 |
push eax |
mov ax,[BOOT_VAR+0x900c] |
shr ax,1 |
shl eax,16 |
mov ax,[BOOT_VAR+0x900A] |
shr ax,1 |
mov [MOUSE_X],eax |
xor eax,eax |
mov [BTN_ADDR],dword BUTTON_INFO ; address of button list |
mov byte [MOUSE_BUFF_COUNT],al ; mouse buffer |
mov byte [KEY_COUNT],al ; keyboard buffer |
mov byte [BTN_COUNT],al ; button buffer |
; mov [MOUSE_X],dword 100*65536+100 ; mouse x/y |
;!! IP 04.02.2005: |
mov byte [DONT_SWITCH],al ; change task if possible |
pop eax |
ret |
align 4 |
;input eax=43,bl-byte of output, ecx - number of port |
sys_outport: |
mov edi,ecx ; separate flag for read / write |
and ecx,65535 |
mov eax,[RESERVED_PORTS] |
test eax,eax |
jnz .sopl8 |
inc eax |
mov [esp+32],eax |
ret |
.sopl8: |
mov edx,[TASK_BASE] |
mov edx,[edx+0x4] |
;and ecx,65535 |
;cld - set on interrupt 0x40 |
.sopl1: |
mov esi,eax |
shl esi,4 |
add esi,RESERVED_PORTS |
cmp edx,[esi+0] |
jne .sopl2 |
cmp ecx,[esi+4] |
jb .sopl2 |
cmp ecx,[esi+8] |
jg .sopl2 |
.sopl3: |
test edi,0x80000000 ; read ? |
jnz .sopl4 |
mov eax,ebx |
mov dx,cx ; write |
out dx,al |
and [esp+32],dword 0 |
ret |
.sopl2: |
dec eax |
jnz .sopl1 |
inc eax |
mov [esp+32],eax |
ret |
.sopl4: |
mov dx,cx ; read |
in al,dx |
and eax,0xff |
and [esp+32],dword 0 |
mov [esp+20],eax |
ret |
display_number: |
;It is not optimization |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov edx, esi |
mov esi, edi |
; eax = print type, al=0 -> ebx is number |
; al=1 -> ebx is pointer |
; ah=0 -> display decimal |
; ah=1 -> display hexadecimal |
; ah=2 -> display binary |
; eax bits 16-21 = number of digits to display (0-32) |
; eax bits 22-31 = reserved |
; |
; ebx = number or pointer |
; ecx = x shl 16 + y |
; edx = color |
xor edi, edi |
display_number_force: |
push eax |
and eax,0x3fffffff |
cmp eax,0xffff ; length > 0 ? |
pop eax |
jge cont_displ |
ret |
cont_displ: |
push eax |
and eax,0x3fffffff |
cmp eax,61*0x10000 ; length <= 60 ? |
pop eax |
jb cont_displ2 |
ret |
cont_displ2: |
pushad |
cmp al,1 ; ecx is a pointer ? |
jne displnl1 |
mov ebp,ebx |
add ebp,4 |
mov ebp,[ebp+std_application_base_address] |
mov ebx,[ebx+std_application_base_address] |
displnl1: |
sub esp,64 |
test ah,ah ; DECIMAL |
jnz no_display_desnum |
shr eax,16 |
and eax,0xC03f |
; and eax,0x3f |
push eax |
and eax,0x3f |
mov edi,esp |
add edi,4+64-1 |
mov ecx,eax |
mov eax,ebx |
mov ebx,10 |
d_desnum: |
xor edx,edx |
call division_64_bits |
div ebx |
add dl,48 |
mov [edi],dl |
dec edi |
loop d_desnum |
pop eax |
call normalize_number |
call draw_num_text |
add esp,64 |
popad |
ret |
no_display_desnum: |
cmp ah,0x01 ; HEXADECIMAL |
jne no_display_hexnum |
shr eax,16 |
and eax,0xC03f |
; and eax,0x3f |
push eax |
and eax,0x3f |
mov edi,esp |
add edi,4+64-1 |
mov ecx,eax |
mov eax,ebx |
mov ebx,16 |
d_hexnum: |
xor edx,edx |
call division_64_bits |
div ebx |
hexletters = __fdo_hexdigits |
add edx,hexletters |
mov dl,[edx] |
mov [edi],dl |
dec edi |
loop d_hexnum |
pop eax |
call normalize_number |
call draw_num_text |
add esp,64 |
popad |
ret |
no_display_hexnum: |
cmp ah,0x02 ; BINARY |
jne no_display_binnum |
shr eax,16 |
and eax,0xC03f |
; and eax,0x3f |
push eax |
and eax,0x3f |
mov edi,esp |
add edi,4+64-1 |
mov ecx,eax |
mov eax,ebx |
mov ebx,2 |
d_binnum: |
xor edx,edx |
call division_64_bits |
div ebx |
add dl,48 |
mov [edi],dl |
dec edi |
loop d_binnum |
pop eax |
call normalize_number |
call draw_num_text |
add esp,64 |
popad |
ret |
no_display_binnum: |
add esp,64 |
popad |
ret |
normalize_number: |
test ah,0x80 |
jz .continue |
mov ecx,48 |
and eax,0x3f |
@@: |
inc edi |
cmp [edi],cl |
jne .continue |
dec eax |
cmp eax,1 |
ja @r |
mov al,1 |
.continue: |
and eax,0x3f |
ret |
division_64_bits: |
test [esp+1+4],byte 0x40 |
jz .continue |
push eax |
mov eax,ebp |
div ebx |
mov ebp,eax |
pop eax |
.continue: |
ret |
draw_num_text: |
mov esi,eax |
mov edx,64+4 |
sub edx,eax |
add edx,esp |
mov ebx,[esp+64+32-8+4] |
; add window start x & y |
mov ecx,[TASK_BASE] |
mov edi,[CURRENT_TASK] |
shl edi,8 |
mov eax,[ecx-twdw+WDATA.box.left] |
add eax,[edi+SLOT_BASE+APPDATA.wnd_clientbox.left] |
shl eax,16 |
add eax,[ecx-twdw+WDATA.box.top] |
add eax,[edi+SLOT_BASE+APPDATA.wnd_clientbox.top] |
add ebx,eax |
mov ecx,[esp+64+32-12+4] |
and ecx, not 0x80000000 ; force counted string |
mov eax, [esp+64+8] ; background color (if given) |
mov edi, [esp+64+4] |
jmp dtext |
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 |
; 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 |
; 11 = enable lba read |
; 12 = enable pci access |
and [esp+32],dword 0 |
dec ebx ; MIDI |
jnz nsyse1 |
cmp ecx,0x100 |
jb nsyse1 |
mov esi,65535 |
cmp esi,ecx |
jb nsyse1 |
mov [midi_base],cx ;bx |
mov word [mididp],cx ;bx |
inc cx ;bx |
mov word [midisp],cx ;bx |
ret |
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 |
dec ecx |
jnz kbnobase |
mov ebx,keymap |
mov ecx,128 |
call memmove |
ret |
kbnobase: |
dec ecx |
jnz kbnoshift |
mov ebx,keymap_shift |
mov ecx,128 |
call memmove |
ret |
kbnoshift: |
dec ecx |
jnz kbnoalt |
mov ebx,keymap_alt |
mov ecx,128 |
call memmove |
ret |
kbnoalt: |
sub ecx,6 |
jnz kbnocountry |
mov word [keyboard],dx |
ret |
kbnocountry: |
mov [esp+32],dword 1 |
ret |
nsyse2: |
dec ebx ; CD |
jnz nsyse4 |
test ecx,ecx |
jz nosesl |
cmp ecx, 4 |
ja nosesl |
mov [cd_base],cl |
dec ecx |
jnz noprma |
mov [cdbase],0x1f0 |
mov [cdid],0xa0 |
noprma: |
dec ecx |
jnz noprsl |
mov [cdbase],0x1f0 |
mov [cdid],0xb0 |
noprsl: |
dec ecx |
jnz nosema |
mov [cdbase],0x170 |
mov [cdid],0xa0 |
nosema: |
dec ecx |
jnz nosesl |
mov [cdbase],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: |
sub ebx,2 ; HD BASE |
jnz nsyse7 |
test ecx,ecx |
jz nosethd |
cmp ecx,4 |
ja nosethd |
mov [hd_base],cl |
cmp ecx,1 |
jnz noprmahd |
mov [hdbase],0x1f0 |
and dword [hdid],0x0 |
mov dword [hdpos],ecx |
; call set_FAT32_variables |
noprmahd: |
cmp ecx,2 |
jnz noprslhd |
mov [hdbase],0x1f0 |
mov [hdid],0x10 |
mov dword [hdpos],ecx |
; call set_FAT32_variables |
noprslhd: |
cmp ecx,3 |
jnz nosemahd |
mov [hdbase],0x170 |
and dword [hdid],0x0 |
mov dword [hdpos],ecx |
; call set_FAT32_variables |
nosemahd: |
cmp ecx,4 |
jnz noseslhd |
mov [hdbase],0x170 |
mov [hdid],0x10 |
mov dword [hdpos],ecx |
; call set_FAT32_variables |
noseslhd: |
call reserve_hd1 |
call reserve_hd_channel |
call free_hd_channel |
and dword [hd1_status],0 ; free |
nosethd: |
ret |
iglobal |
hd_base db 0 |
endg |
nsyse7: |
; cmp eax,8 ; HD PARTITION |
dec ebx |
jnz nsyse8 |
mov [fat32part],ecx |
; call set_FAT32_variables |
call reserve_hd1 |
call reserve_hd_channel |
call free_hd_channel |
; pusha |
call choice_necessity_partition_1 |
; popa |
and dword [hd1_status],0 ; free |
ret |
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: |
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 |
; 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=get hs timer tic |
; cmp eax,1 |
dec ebx |
jnz ngsyse1 |
movzx eax,[midi_base] |
mov [esp+32],eax |
ret |
ngsyse1: |
; cmp eax,2 |
dec ebx |
jnz ngsyse2 |
mov edi,[TASK_BASE] |
mov ebx,[edi+TASKDATA.mem_start] |
add ebx,edx |
; cmp ebx,1 |
dec ecx |
jnz kbnobaseret |
mov eax,keymap |
mov ecx,128 |
call memmove |
ret |
kbnobaseret: |
; cmp ebx,2 |
dec ecx |
jnz kbnoshiftret |
mov eax,keymap_shift |
mov ecx,128 |
call memmove |
ret |
kbnoshiftret: |
; cmp ebx,3 |
dec ecx |
jne kbnoaltret |
mov eax,keymap_alt |
mov ecx,128 |
call memmove |
ret |
kbnoaltret: |
; cmp ebx,9 |
sub ecx,6 |
jnz ngsyse2 |
movzx eax,word [keyboard] |
mov [esp+32],eax |
ret |
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 |
movzx eax,[hd_base] |
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 |
sub ebx,2 |
jnz ngsyse11 |
mov eax,[lba_read_enabled] |
mov [esp+32],eax |
ret |
ngsyse11: |
; cmp eax,12 |
dec ebx |
jnz ngsyse12 |
mov eax,[pci_access_enabled] |
mov [esp+32],eax |
ret |
ngsyse12: |
mov [esp+32],dword 1 |
ret |
get_timer_ticks: |
mov eax,[timer_ticks] |
ret |
iglobal |
align 4 |
mousefn dd msscreen, mswin, msbutton, msset |
dd app_load_cursor |
dd app_set_cursor |
dd app_delete_cursor |
dd msz |
endg |
readmousepos: |
; eax=0 screen relative |
; eax=1 window relative |
; eax=2 buttons pressed |
; eax=3 set mouse pos ; reserved |
; eax=4 load cursor |
; eax=5 set cursor |
; eax=6 delete cursor ; reserved |
; eax=7 get mouse_z |
cmp ebx, 7 |
ja msset |
jmp [mousefn+ebx*4] |
msscreen: |
mov eax,[MOUSE_X] |
shl eax,16 |
mov ax,[MOUSE_Y] |
mov [esp+36-4],eax |
ret |
mswin: |
mov eax,[MOUSE_X] |
shl eax,16 |
mov ax,[MOUSE_Y] |
mov esi,[TASK_BASE] |
mov bx, word [esi-twdw+WDATA.box.left] |
shl ebx,16 |
mov bx, word [esi-twdw+WDATA.box.top] |
sub eax,ebx |
mov edi,[CURRENT_TASK] |
shl edi,8 |
sub ax,word[edi+SLOT_BASE+APPDATA.wnd_clientbox.top] |
rol eax,16 |
sub ax,word[edi+SLOT_BASE+APPDATA.wnd_clientbox.left] |
rol eax,16 |
mov [esp+36-4],eax |
ret |
msbutton: |
movzx eax,byte [BTN_DOWN] |
mov [esp+36-4],eax |
ret |
msz: |
mov edi, [TASK_COUNT] |
movzx edi, word [WIN_POS + edi*2] |
cmp edi, [CURRENT_TASK] |
jne @f |
mov ax,[MOUSE_SCROLL_H] |
shl eax,16 |
mov ax,[MOUSE_SCROLL_V] |
mov [esp+36-4],eax |
and [MOUSE_SCROLL_H],word 0 |
and [MOUSE_SCROLL_V],word 0 |
ret |
@@: |
and [esp+36-4],dword 0 |
; ret |
msset: |
ret |
app_load_cursor: |
cmp ecx, OS_BASE |
jae msset |
stdcall load_cursor, ecx, edx |
mov [esp+36-4], eax |
ret |
app_set_cursor: |
stdcall set_cursor, ecx |
mov [esp+36-4], eax |
ret |
app_delete_cursor: |
stdcall delete_cursor, ecx |
mov [esp+36-4], eax |
ret |
is_input: |
push edx |
mov dx,word [midisp] |
in al,dx |
and al,0x80 |
pop edx |
ret |
is_output: |
push edx |
mov dx,word [midisp] |
in al,dx |
and al,0x40 |
pop edx |
ret |
get_mpu_in: |
push edx |
mov dx,word [mididp] |
in al,dx |
pop edx |
ret |
put_mpu_out: |
push edx |
mov dx,word [mididp] |
out dx,al |
pop edx |
ret |
align 4 |
sys_midi: |
cmp [mididp],0 |
jnz sm0 |
mov [esp+36],dword 1 |
ret |
sm0: |
and [esp+36],dword 0 |
dec ebx |
jnz smn1 |
; call setuart |
su1: |
call is_output |
test al,al |
jnz su1 |
mov dx,word [midisp] |
mov al,0xff |
out dx,al |
su2: |
mov dx,word [midisp] |
mov al,0xff |
out dx,al |
call is_input |
test al,al |
jnz su2 |
call get_mpu_in |
cmp al,0xfe |
jnz su2 |
su3: |
call is_output |
test al,al |
jnz su3 |
mov dx,word [midisp] |
mov al,0x3f |
out dx,al |
ret |
smn1: |
dec ebx |
jnz smn2 |
sm10: |
call get_mpu_in |
call is_output |
test al,al |
jnz sm10 |
mov al,bl |
call put_mpu_out |
smn2: |
ret |
detect_devices: |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
;include 'detect/commouse.inc' |
;include 'detect/ps2mouse.inc' |
;include 'detect/dev_fd.inc' |
;include 'detect/dev_hdcd.inc' |
;include 'detect/sear_par.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
ret |
sys_end: |
mov ecx, [current_slot] |
mov eax, [ecx+APPDATA.tls_base] |
test eax, eax |
jz @F |
stdcall user_free, eax |
@@: |
mov eax,[TASK_BASE] |
mov [eax+TASKDATA.state], 3 ; terminate this program |
waitterm: ; wait here for termination |
mov ebx,100 |
call delay_hs |
jmp waitterm |
iglobal |
align 4 |
sys_system_table: |
dd sysfn_deactivate ; 1 = deactivate window |
dd sysfn_terminate ; 2 = terminate thread |
dd sysfn_activate ; 3 = activate window |
dd sysfn_getidletime ; 4 = get idle time |
dd sysfn_getcpuclock ; 5 = get cpu clock |
dd sysfn_saveramdisk ; 6 = save ramdisk |
dd sysfn_getactive ; 7 = get active window |
dd sysfn_sound_flag ; 8 = get/set sound_flag |
dd sysfn_shutdown ; 9 = shutdown with parameter |
dd sysfn_minimize ; 10 = minimize window |
dd sysfn_getdiskinfo ; 11 = get disk subsystem info |
dd sysfn_lastkey ; 12 = get last pressed key |
dd sysfn_getversion ; 13 = get kernel version |
dd sysfn_waitretrace ; 14 = wait retrace |
dd sysfn_centermouse ; 15 = center mouse cursor |
dd sysfn_getfreemem ; 16 = get free memory size |
dd sysfn_getallmem ; 17 = get total memory size |
dd sysfn_terminate2 ; 18 = terminate thread using PID |
; instead of slot |
dd sysfn_mouse_acceleration; 19 = set/get mouse acceleration |
dd sysfn_meminfo ; 20 = get extended memory info |
dd sysfn_pid_to_slot ; 21 = get slot number for pid |
dd sysfn_min_rest_window ; 22 = minimize and restore any window |
sysfn_num = ($ - sys_system_table)/4 |
endg |
;------------------------------------------------------------------------------ |
sys_system: |
dec ebx |
cmp ebx, sysfn_num |
jae @f |
jmp dword [sys_system_table + ebx*4] |
@@: |
ret |
;------------------------------------------------------------------------------ |
sysfn_shutdown: ; 18.9 = system shutdown |
cmp ecx,1 |
jl exit_for_anyone |
cmp ecx,4 |
jg exit_for_anyone |
mov [BOOT_VAR+0x9030],cl |
mov eax,[TASK_COUNT] |
mov [SYS_SHUTDOWN],al |
mov [shutdown_processes],eax |
and dword [esp+32], 0 |
exit_for_anyone: |
ret |
uglobal |
shutdown_processes: dd 0x0 |
endg |
;------------------------------------------------------------------------------ |
sysfn_terminate: ; 18.2 = TERMINATE |
cmp ecx,2 |
jb noprocessterminate |
mov edx,[TASK_COUNT] |
cmp ecx,edx |
ja noprocessterminate |
mov eax,[TASK_COUNT] |
shl ecx,5 |
mov edx,[ecx+CURRENT_TASK+TASKDATA.pid] |
add ecx,CURRENT_TASK+TASKDATA.state |
cmp byte [ecx], 9 |
jz noprocessterminate |
;call MEM_Heap_Lock ;guarantee that process isn't working with heap |
mov [ecx],byte 3 ; clear possible i40's |
;call MEM_Heap_UnLock |
cmp edx,[application_table_status] ; clear app table stat |
jne noatsc |
and [application_table_status],0 |
noatsc: |
noprocessterminate: |
ret |
;------------------------------------------------------------------------------ |
sysfn_terminate2: |
;lock application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
je .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
mov eax,ecx |
call pid_to_slot |
test eax,eax |
jz .not_found |
mov ecx,eax |
cli |
call sysfn_terminate |
and [application_table_status],0 |
sti |
and dword [esp+32],0 |
ret |
.not_found: |
mov [application_table_status],0 |
or dword [esp+32],-1 |
ret |
;------------------------------------------------------------------------------ |
sysfn_deactivate: ; 18.1 = DEACTIVATE WINDOW |
cmp ecx,2 |
jb .nowindowdeactivate |
cmp ecx,[TASK_COUNT] |
ja .nowindowdeactivate |
movzx esi, word [WIN_STACK + ecx*2] |
cmp esi, 1 |
je .nowindowdeactivate ; already deactive |
mov edi, ecx |
shl edi, 5 |
add edi, window_data |
movzx esi, word [WIN_STACK + ecx * 2] |
lea esi, [WIN_POS + esi * 2] |
call window._.window_deactivate |
xor eax, eax |
mov byte[MOUSE_BACKGROUND], al |
mov byte[DONT_DRAW_MOUSE], al |
mov byte[MOUSE_DOWN], 0 |
call syscall_display_settings._.calculate_whole_screen |
call syscall_display_settings._.redraw_whole_screen |
.nowindowdeactivate: |
ret |
;------------------------------------------------------------------------------ |
sysfn_activate: ; 18.3 = ACTIVATE WINDOW |
cmp ecx,2 |
jb .nowindowactivate |
cmp ecx,[TASK_COUNT] |
ja .nowindowactivate |
mov [window_minimize], 2 ; restore window if minimized |
movzx esi, word [WIN_STACK + ecx*2] |
cmp esi, [TASK_COUNT] |
je .nowindowactivate ; already active |
mov edi, ecx |
shl edi, 5 |
add edi, window_data |
movzx esi, word [WIN_STACK + ecx * 2] |
lea esi, [WIN_POS + esi * 2] |
call waredraw |
.nowindowactivate: |
ret |
;------------------------------------------------------------------------------ |
sysfn_getidletime: ; 18.4 = GET IDLETIME |
mov eax,[idleusesec] |
mov [esp+32], eax |
ret |
;------------------------------------------------------------------------------ |
sysfn_getcpuclock: ; 18.5 = GET TSC/SEC |
mov eax,[CPU_FREQ] |
mov [esp+32], eax |
ret |
;------------------------------------------------------------------------------ |
; SAVE ramdisk to /hd/1/menuet.img |
;!!!!!!!!!!!!!!!!!!!!!!!! |
include 'blkdev/rdsave.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!! |
;------------------------------------------------------------------------------ |
align 4 |
sysfn_getactive: ; 18.7 = get active window |
mov eax, [TASK_COUNT] |
movzx eax, word [WIN_POS + eax*2] |
mov [esp+32],eax |
ret |
;------------------------------------------------------------------------------ |
sysfn_sound_flag: ; 18.8 = get/set sound_flag |
; cmp ecx,1 |
dec ecx |
jnz nogetsoundflag |
movzx eax,byte [sound_flag] ; get sound_flag |
mov [esp+32],eax |
ret |
nogetsoundflag: |
; cmp ecx,2 |
dec ecx |
jnz nosoundflag |
xor byte [sound_flag], 1 |
nosoundflag: |
ret |
;------------------------------------------------------------------------------ |
sysfn_minimize: ; 18.10 = minimize window |
mov [window_minimize],1 |
ret |
;------------------------------------------------------------------------------ |
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: |
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,16384 |
cld |
rep movsd |
ret |
;------------------------------------------------------------------------------ |
sysfn_lastkey: ; 18.12 = return 0 (backward compatibility) |
and dword [esp+32], 0 |
ret |
;------------------------------------------------------------------------------ |
sysfn_getversion: ; 18.13 = get kernel ID and version |
mov edi,ecx |
mov esi,version_inf |
mov ecx,version_end-version_inf |
rep movsb |
ret |
;------------------------------------------------------------------------------ |
sysfn_waitretrace: ; 18.14 = sys wait retrace |
;wait retrace functions |
sys_wait_retrace: |
mov edx,0x3da |
WaitRetrace_loop: |
in al,dx |
test al,1000b |
jz WaitRetrace_loop |
and [esp+32],dword 0 |
ret |
;------------------------------------------------------------------------------ |
align 4 |
sysfn_centermouse: ; 18.15 = mouse centered |
; removed here by <Lrz> |
; call mouse_centered |
;* mouse centered - start code- Mario79 |
;mouse_centered: |
; push eax |
mov eax,[Screen_Max_X] |
shr eax,1 |
mov [MOUSE_X],ax |
mov eax,[Screen_Max_Y] |
shr eax,1 |
mov [MOUSE_Y],ax |
; ret |
;* mouse centered - end code- Mario79 |
xor eax,eax |
and [esp+32],eax |
; pop eax |
ret |
;------------------------------------------------------------------------------ |
align 4 |
sysfn_mouse_acceleration: ; 18.19 = set/get mouse features |
test ecx,ecx ; get mouse speed factor |
jnz .set_mouse_acceleration |
xor eax,eax |
mov ax,[mouse_speed_factor] |
mov [esp+32],eax |
ret |
.set_mouse_acceleration: |
; cmp ecx,1 ; set mouse speed factor |
dec ecx |
jnz .get_mouse_delay |
mov [mouse_speed_factor],dx |
ret |
.get_mouse_delay: |
; cmp ecx,2 ; get mouse delay |
dec ecx |
jnz .set_mouse_delay |
mov eax,[mouse_delay] |
mov [esp+32],eax |
ret |
.set_mouse_delay: |
; cmp ecx,3 ; set mouse delay |
dec ecx |
jnz .set_pointer_position |
mov [mouse_delay],edx |
ret |
.set_pointer_position: |
; cmp ecx,4 ; set mouse pointer position |
dec ecx |
jnz .set_mouse_button |
cmp dx, word[Screen_Max_Y] |
ja .end |
rol edx,16 |
cmp dx, word[Screen_Max_X] |
ja .end |
mov [MOUSE_X], edx |
ret |
.set_mouse_button: |
; cmp ecx,5 ; set mouse button features |
dec ecx |
jnz .end |
mov [BTN_DOWN],dl |
mov [mouse_active],1 |
.end: |
ret |
;------------------------------------------------------------------------------ |
sysfn_getfreemem: |
mov eax, [pg_data.pages_free] |
shl eax, 2 |
mov [esp+32],eax |
ret |
sysfn_getallmem: |
mov eax,[MEM_AMOUNT] |
shr eax, 10 |
mov [esp+32],eax |
ret |
; // Alver, 2007-22-08 // { |
sysfn_pid_to_slot: |
mov eax, ecx |
call pid_to_slot |
mov [esp+32], eax |
ret |
sysfn_min_rest_window: |
pushad |
mov eax, edx ; ebx - operating |
shr ecx, 1 |
jnc @f |
call pid_to_slot |
@@: |
or eax, eax ; eax - number of slot |
jz .error |
cmp eax, 255 ; varify maximal slot number |
ja .error |
movzx eax, word [WIN_STACK + eax*2] |
shr ecx, 1 |
jc .restore |
; .minimize: |
call minimize_window |
jmp .exit |
.restore: |
call restore_minimized_window |
.exit: |
popad |
xor eax, eax |
mov [esp+32], eax |
ret |
.error: |
popad |
xor eax, eax |
dec eax |
mov [esp+32], eax |
ret |
; } \\ Alver, 2007-22-08 \\ |
uglobal |
;// mike.dld, 2006-29-01 [ |
screen_workarea RECT |
;// mike.dld, 2006-29-01 ] |
window_minimize db 0 |
sound_flag db 0 |
endg |
UID_NONE=0 |
UID_MENUETOS=1 ;official |
UID_KOLIBRI=2 ;russian |
iglobal |
version_inf: |
db 0,7,7,0 ; version 0.7.7.0 |
db 0 |
dd __REV__ |
version_end: |
endg |
sys_cachetodiskette: |
cmp ebx, 1 |
jne .no_floppy_a_save |
mov [flp_number], 1 |
jmp .save_image_on_floppy |
.no_floppy_a_save: |
cmp ebx, 2 |
jne .no_floppy_b_save |
mov [flp_number], 2 |
.save_image_on_floppy: |
call save_image |
mov [esp + 32], dword 0 |
cmp [FDC_Status], 0 |
je .yes_floppy_save |
.no_floppy_b_save: |
mov [esp + 32], dword 1 |
.yes_floppy_save: |
ret |
uglobal |
; bgrchanged dd 0x0 |
align 4 |
bgrlockpid dd 0 |
bgrlock db 0 |
endg |
sys_background: |
cmp ebx,1 ; BACKGROUND SIZE |
jnz nosb1 |
test ecx,ecx |
; cmp ecx,0 |
jz sbgrr |
test edx,edx |
; cmp edx,0 |
jz sbgrr |
@@: |
;;Maxis use atomic bts for mutexes 4.4.2009 |
bts dword [bgrlock], 0 |
jnc @f |
call change_task |
jmp @b |
@@: |
mov [BgrDataWidth],ecx |
mov [BgrDataHeight],edx |
; mov [bgrchanged],1 |
pushad |
; return memory for old background |
mov eax, [img_background] |
cmp eax, static_background_data |
jz @f |
stdcall kernel_free, eax |
@@: |
; calculate RAW size |
xor eax,eax |
inc eax |
cmp [BgrDataWidth],eax |
jae @f |
mov [BgrDataWidth],eax |
@@: |
cmp [BgrDataHeight],eax |
jae @f |
mov [BgrDataHeight],eax |
@@: |
mov eax,[BgrDataWidth] |
imul eax,[BgrDataHeight] |
lea eax,[eax*3] |
mov [mem_BACKGROUND],eax |
; get memory for new background |
stdcall kernel_alloc, eax |
test eax, eax |
jz .memfailed |
mov [img_background], eax |
jmp .exit |
.memfailed: |
; revert to static monotone data |
mov [img_background], static_background_data |
xor eax, eax |
inc eax |
mov [BgrDataWidth], eax |
mov [BgrDataHeight], eax |
mov [mem_BACKGROUND], 4 |
.exit: |
popad |
mov [bgrlock], 0 |
sbgrr: |
ret |
nosb1: |
cmp ebx,2 ; SET PIXEL |
jnz nosb2 |
mov eax, [img_background] |
test ecx, ecx |
jz @f |
cmp eax, static_background_data |
jz .ret |
@@: |
mov ebx, [mem_BACKGROUND] |
add ebx, 4095 |
and ebx, -4096 |
sub ebx, 4 |
cmp ecx, ebx |
ja .ret |
mov ebx,[eax+ecx] |
and ebx,0xFF000000 ;255*256*256*256 |
and edx,0x00FFFFFF ;255*256*256+255*256+255 |
add edx,ebx |
mov [eax+ecx],edx |
.ret: |
ret |
nosb2: |
cmp ebx,3 ; DRAW BACKGROUND |
jnz nosb3 |
draw_background_temp: |
; cmp [bgrchanged],1 ;0 |
; je nosb31 |
;draw_background_temp: |
; mov [bgrchanged],1 ;0 |
mov [background_defined], 1 |
mov byte[BACKGROUND_CHANGED], 1 |
call force_redraw_background |
nosb31: |
ret |
nosb3: |
cmp ebx,4 ; TILED / STRETCHED |
jnz nosb4 |
cmp ecx,[BgrDrawMode] |
je nosb41 |
mov [BgrDrawMode],ecx |
; mov [bgrchanged],1 |
nosb41: |
ret |
nosb4: |
cmp ebx,5 ; BLOCK MOVE TO BGR |
jnz nosb5 |
cmp [img_background], static_background_data |
jnz @f |
test edx, edx |
jnz .fin |
cmp esi, 4 |
ja .fin |
@@: |
; bughere |
mov eax, ecx |
mov ebx, edx |
add ebx, [img_background] ;IMG_BACKGROUND |
mov ecx, esi |
call memmove |
.fin: |
ret |
nosb5: |
cmp ebx, 6 |
jnz nosb6 |
;;Maxis use atomic bts for mutex 4.4.2009 |
@@: |
bts dword [bgrlock], 0 |
jnc @f |
call change_task |
jmp @b |
@@: |
mov eax, [CURRENT_TASK] |
mov [bgrlockpid], eax |
cmp [img_background], static_background_data |
jz .nomem |
stdcall user_alloc, [mem_BACKGROUND] |
mov [esp+32], eax |
test eax, eax |
jz .nomem |
mov ebx, eax |
shr ebx, 12 |
or dword [page_tabs+(ebx-1)*4], DONT_FREE_BLOCK |
mov esi, [img_background] |
shr esi, 12 |
mov ecx, [mem_BACKGROUND] |
add ecx, 0xFFF |
shr ecx, 12 |
.z: |
mov eax, [page_tabs+ebx*4] |
test al, 1 |
jz @f |
call free_page |
@@: |
mov eax, [page_tabs+esi*4] |
or al, PG_UW |
mov [page_tabs+ebx*4], eax |
mov eax, ebx |
shl eax, 12 |
invlpg [eax] |
inc ebx |
inc esi |
loop .z |
ret |
.nomem: |
and [bgrlockpid], 0 |
mov [bgrlock], 0 |
nosb6: |
cmp ebx, 7 |
jnz nosb7 |
cmp [bgrlock], 0 |
jz .err |
mov eax, [CURRENT_TASK] |
cmp [bgrlockpid], eax |
jnz .err |
mov eax, ecx |
mov ebx, ecx |
shr eax, 12 |
mov ecx, [page_tabs+(eax-1)*4] |
test cl, USED_BLOCK+DONT_FREE_BLOCK |
jz .err |
jnp .err |
push eax |
shr ecx, 12 |
dec ecx |
@@: |
and dword [page_tabs+eax*4], 0 |
mov edx, eax |
shl edx, 12 |
push eax |
invlpg [edx] |
pop eax |
inc eax |
loop @b |
pop eax |
and dword [page_tabs+(eax-1)*4], not DONT_FREE_BLOCK |
stdcall user_free, ebx |
mov [esp+32], eax |
and [bgrlockpid], 0 |
mov [bgrlock], 0 |
ret |
.err: |
and dword [esp+32], 0 |
ret |
nosb7: |
ret |
force_redraw_background: |
and [draw_data+32 + RECT.left], 0 |
and [draw_data+32 + RECT.top], 0 |
push eax ebx |
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 |
inc byte[REDRAW_BACKGROUND] |
ret |
align 4 |
sys_getbackground: |
; cmp eax,1 ; SIZE |
dec ebx |
jnz nogb1 |
mov eax,[BgrDataWidth] |
shl eax,16 |
mov ax,[BgrDataHeight] |
mov [esp+32],eax |
ret |
nogb1: |
; cmp eax,2 ; PIXEL |
dec ebx |
jnz nogb2 |
mov eax, [img_background] |
test ecx, ecx |
jz @f |
cmp eax, static_background_data |
jz .ret |
@@: |
mov ebx, [mem_BACKGROUND] |
add ebx, 4095 |
and ebx, -4096 |
sub ebx, 4 |
cmp ecx, ebx |
ja .ret |
mov eax,[ecx+eax] |
and eax, 0xFFFFFF |
mov [esp+32],eax |
.ret: |
ret |
nogb2: |
; cmp eax,4 ; TILED / STRETCHED |
dec ebx |
dec ebx |
jnz nogb4 |
mov eax,[BgrDrawMode] |
nogb4: |
mov [esp+32],eax |
ret |
align 4 |
sys_getkey: |
mov [esp + 32],dword 1 |
; test main buffer |
mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK |
movzx ecx, word [WIN_STACK + ebx * 2] |
mov edx, [TASK_COUNT] |
cmp ecx, edx |
jne .finish |
cmp [KEY_COUNT], byte 0 |
je .finish |
movzx eax, byte [KEY_BUFF] |
shl eax, 8 |
push eax |
dec byte [KEY_COUNT] |
and byte [KEY_COUNT], 127 |
movzx ecx, byte [KEY_COUNT] |
add ecx, 2 |
mov eax, KEY_BUFF + 1 |
mov ebx, KEY_BUFF |
call memmove |
pop eax |
.ret_eax: |
mov [esp + 32], eax |
ret |
.finish: |
; test hotkeys buffer |
mov ecx, hotkey_buffer |
@@: |
cmp [ecx], ebx |
jz .found |
add ecx, 8 |
cmp ecx, hotkey_buffer + 120 * 8 |
jb @b |
ret |
.found: |
mov ax, [ecx + 6] |
shl eax, 16 |
mov ah, [ecx + 4] |
mov al, 2 |
and dword [ecx + 4], 0 |
and dword [ecx], 0 |
jmp .ret_eax |
align 4 |
sys_getbutton: |
mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK |
mov [esp + 32], dword 1 |
movzx ecx, word [WIN_STACK + ebx * 2] |
mov edx, [TASK_COUNT] ; less than 256 processes |
cmp ecx, edx |
jne .exit |
movzx eax, byte [BTN_COUNT] |
test eax, eax |
jz .exit |
mov eax, [BTN_BUFF] |
and al, 0xFE ; delete left button bit |
mov [BTN_COUNT], byte 0 |
mov [esp + 32], eax |
.exit: |
ret |
align 4 |
sys_cpuusage: |
; RETURN: |
; |
; +00 dword process cpu usage |
; +04 word position in windowing stack |
; +06 word windowing stack value at current position (cpu nro) |
; +10 12 bytes name |
; +22 dword start in mem |
; +26 dword used mem |
; +30 dword PID , process idenfification number |
; |
cmp ecx,-1 ; who am I ? |
jne .no_who_am_i |
mov ecx,[CURRENT_TASK] |
.no_who_am_i: |
cmp ecx, max_processes |
ja .nofillbuf |
; +4: word: position of the window of thread in the window stack |
mov ax, [WIN_STACK + ecx * 2] |
mov [ebx+4], ax |
; +6: word: number of the thread slot, which window has in the window stack |
; position ecx (has no relation to the specific thread) |
mov ax, [WIN_POS + ecx * 2] |
mov [ebx+6], ax |
shl ecx, 5 |
; +0: dword: memory usage |
mov eax, [ecx+CURRENT_TASK+TASKDATA.cpu_usage] |
mov [ebx], eax |
; +10: 11 bytes: name of the process |
push ecx |
lea eax, [ecx*8+SLOT_BASE+APPDATA.app_name] |
add ebx, 10 |
mov ecx, 11 |
call memmove |
pop ecx |
; +22: address of the process in memory |
; +26: size of used memory - 1 |
push edi |
lea edi, [ebx+12] |
xor eax, eax |
mov edx, 0x100000*16 |
cmp ecx, 1 shl 5 |
je .os_mem |
mov edx, [SLOT_BASE+ecx*8+APPDATA.mem_size] |
mov eax, std_application_base_address |
.os_mem: |
stosd |
lea eax, [edx-1] |
stosd |
; +30: PID/TID |
mov eax, [ecx+CURRENT_TASK+TASKDATA.pid] |
stosd |
; window position and size |
push esi |
lea esi, [ecx + window_data + WDATA.box] |
movsd |
movsd |
movsd |
movsd |
; Process state (+50) |
mov eax, dword [ecx+CURRENT_TASK+TASKDATA.state] |
stosd |
; Window client area box |
lea esi, [ecx*8 + SLOT_BASE + APPDATA.wnd_clientbox] |
movsd |
movsd |
movsd |
movsd |
; Window state |
mov al, [ecx+window_data+WDATA.fl_wstate] |
stosb |
; Event mask (+71) |
mov EAX, dword [ECX+CURRENT_TASK+TASKDATA.event_mask] |
stosd |
pop esi |
pop edi |
.nofillbuf: |
; return number of processes |
mov eax,[TASK_COUNT] |
mov [esp+32],eax |
ret |
align 4 |
sys_clock: |
cli |
; Mikhail Lisovin xx Jan 2005 |
@@: mov al, 10 |
out 0x70, al |
in al, 0x71 |
test al, al |
jns @f |
mov esi, 1 |
call delay_ms |
jmp @b |
@@: |
; end Lisovin's fix |
xor al,al ; seconds |
out 0x70,al |
in al,0x71 |
movzx ecx,al |
mov al,02 ; minutes |
shl ecx,16 |
out 0x70,al |
in al,0x71 |
movzx edx,al |
mov al,04 ; hours |
shl edx,8 |
out 0x70,al |
in al,0x71 |
add ecx,edx |
movzx edx,al |
add ecx,edx |
sti |
mov [esp + 32], ecx |
ret |
align 4 |
sys_date: |
cli |
@@: mov al, 10 |
out 0x70, al |
in al, 0x71 |
test al, al |
jns @f |
mov esi, 1 |
call delay_ms |
jmp @b |
@@: |
mov ch,0 |
mov al,7 ; date |
out 0x70,al |
in al,0x71 |
mov cl,al |
mov al,8 ; month |
shl ecx,16 |
out 0x70,al |
in al,0x71 |
mov ch,al |
mov al,9 ; year |
out 0x70,al |
in al,0x71 |
mov cl,al |
sti |
mov [esp+32], ecx |
ret |
; redraw status |
sys_redrawstat: |
cmp ebx, 1 |
jne no_widgets_away |
; buttons away |
mov ecx,[CURRENT_TASK] |
sys_newba2: |
mov edi,[BTN_ADDR] |
cmp [edi], dword 0 ; empty button list ? |
je end_of_buttons_away |
movzx ebx, word [edi] |
inc ebx |
mov eax,edi |
sys_newba: |
dec ebx |
jz end_of_buttons_away |
add eax, 0x10 |
cmp cx, [eax] |
jnz sys_newba |
push eax ebx ecx |
mov ecx,ebx |
inc ecx |
shl ecx, 4 |
mov ebx, eax |
add eax, 0x10 |
call memmove |
dec dword [edi] |
pop ecx ebx eax |
jmp sys_newba2 |
end_of_buttons_away: |
ret |
no_widgets_away: |
cmp ebx, 2 |
jnz srl1 |
mov edx, [TASK_BASE] ; return whole screen draw area for this app |
add edx, draw_data - CURRENT_TASK |
mov [edx + RECT.left], 0 |
mov [edx + RECT.top], 0 |
mov eax, [Screen_Max_X] |
mov [edx + RECT.right], eax |
mov eax, [Screen_Max_Y] |
mov [edx + RECT.bottom], eax |
srl1: |
ret |
;ok - 100% work |
;nt - not tested |
;--------------------------------------------------------------------------------------------- |
;eax |
;0 - task switch counter. Ret switch counter in eax. Block. ok. |
;1 - change task. Ret nothing. Block. ok. |
;2 - performance control |
; ebx |
; 0 - enable or disable (inversion) PCE flag on CR4 for rdmpc in user mode. |
; returned new cr4 in eax. Ret cr4 in eax. Block. ok. |
; 1 - is cache enabled. Ret cr0 in eax if enabled else zero in eax. Block. ok. |
; 2 - enable cache. Ret 1 in eax. Ret nothing. Block. ok. |
; 3 - disable cache. Ret 0 in eax. Ret nothing. Block. ok. |
;eax |
;3 - rdmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. |
;4 - wrmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. |
;--------------------------------------------------------------------------------------------- |
iglobal |
align 4 |
sheduler: |
dd sys_sheduler.00 |
dd change_task |
dd sys_sheduler.02 |
dd sys_sheduler.03 |
dd sys_sheduler.04 |
endg |
sys_sheduler: |
;rewritten by <Lrz> 29.12.2009 |
jmp dword [sheduler+ebx*4] |
;.shed_counter: |
.00: |
mov eax,[context_counter] |
mov [esp+32],eax |
ret |
.02: |
;.perf_control: |
inc ebx ;before ebx=2, ebx=3 |
cmp ebx,ecx ;if ecx=3, ebx=3 |
jz cache_disable |
dec ebx ;ebx=2 |
cmp ebx,ecx ; |
jz cache_enable ;if ecx=2 and ebx=2 |
dec ebx ;ebx=1 |
cmp ebx,ecx |
jz is_cache_enabled ;if ecx=1 and ebx=1 |
dec ebx |
test ebx,ecx ;ebx=0 and ecx=0 |
jz modify_pce ;if ecx=0 |
ret |
.03: |
;.rdmsr_instr: |
;now counter in ecx |
;(edx:eax) esi:edi => edx:esi |
mov eax,esi |
mov ecx,edx |
rdmsr |
mov [esp+32],eax |
mov [esp+20],edx ;ret in ebx? |
ret |
.04: |
;.wrmsr_instr: |
;now counter in ecx |
;(edx:eax) esi:edi => edx:esi |
; Fast Call MSR can't be destroy |
; ® MSR_AMD_EFER ¬®¦® ¨§¬¥ïâì, â.ª. ¢ í⮬ ॣ¨áâॠ«¨è |
; ¢ª«îç îâáï/¢ëª«îç îâáï à áè¨à¥ë¥ ¢®§¬®¦®á⨠|
cmp edx,MSR_SYSENTER_CS |
je @f |
cmp edx,MSR_SYSENTER_ESP |
je @f |
cmp edx,MSR_SYSENTER_EIP |
je @f |
cmp edx,MSR_AMD_STAR |
je @f |
mov eax,esi |
mov ecx,edx |
wrmsr |
; mov [esp + 32], eax |
; mov [esp + 20], edx ;ret in ebx? |
@@: |
ret |
cache_disable: |
mov eax,cr0 |
or eax,01100000000000000000000000000000b |
mov cr0,eax |
wbinvd ;set MESI |
ret |
cache_enable: |
mov eax,cr0 |
and eax,10011111111111111111111111111111b |
mov cr0,eax |
ret |
is_cache_enabled: |
mov eax,cr0 |
mov ebx,eax |
and eax,01100000000000000000000000000000b |
jz cache_disabled |
mov [esp+32],ebx |
cache_disabled: |
mov dword [esp+32],eax ;0 |
ret |
modify_pce: |
mov eax,cr4 |
; mov ebx,0 |
; or bx,100000000b ;pce |
; xor eax,ebx ;invert pce |
bts eax,8 ;pce=cr4[8] |
mov cr4,eax |
mov [esp+32],eax |
ret |
;--------------------------------------------------------------------------------------------- |
; check if pixel is allowed to be drawn |
checkpixel: |
push eax edx |
mov edx,[Screen_Max_X] ; screen x size |
inc edx |
imul edx, ebx |
add eax, [_WinMapAddress] |
mov dl, [eax+edx] ; lea eax, [...] |
xor ecx, ecx |
mov eax, [CURRENT_TASK] |
cmp al, dl |
setne cl |
pop edx eax |
ret |
iglobal |
cpustring db 'CPU',0 |
endg |
uglobal |
background_defined db 0 ; diamond, 11.04.2006 |
endg |
align 4 |
; check misc |
checkmisc: |
cmp [ctrl_alt_del], 1 |
jne nocpustart |
mov ebp, cpustring |
call fs_execute_from_sysdir |
mov [ctrl_alt_del], 0 |
nocpustart: |
cmp [mouse_active], 1 |
jne mouse_not_active |
mov [mouse_active], 0 |
xor edi, edi |
mov ecx, [TASK_COUNT] |
set_mouse_event: |
add edi, 256 |
or [edi+SLOT_BASE+APPDATA.event_mask], dword 100000b |
loop set_mouse_event |
mouse_not_active: |
cmp byte[BACKGROUND_CHANGED], 0 |
jz no_set_bgr_event |
xor edi, edi |
mov ecx, [TASK_COUNT] |
set_bgr_event: |
add edi, 256 |
or [edi+SLOT_BASE+APPDATA.event_mask], 16 |
loop set_bgr_event |
mov byte[BACKGROUND_CHANGED], 0 |
no_set_bgr_event: |
cmp byte[REDRAW_BACKGROUND], 0 ; background update ? |
jz nobackgr |
cmp [background_defined], 0 |
jz nobackgr |
; mov [draw_data+32 + RECT.left],dword 0 |
; mov [draw_data+32 + RECT.top],dword 0 |
; mov eax,[Screen_Max_X] |
; mov ebx,[Screen_Max_Y] |
; mov [draw_data+32 + RECT.right],eax |
; mov [draw_data+32 + RECT.bottom],ebx |
@@: |
call drawbackground |
xor eax, eax |
xchg al, [REDRAW_BACKGROUND] |
test al, al ; got new update request? |
jnz @b |
mov [draw_data+32 + RECT.left], eax |
mov [draw_data+32 + RECT.top], eax |
mov [draw_data+32 + RECT.right], eax |
mov [draw_data+32 + RECT.bottom], eax |
mov [MOUSE_BACKGROUND],byte 0 |
nobackgr: |
; system shutdown request |
cmp [SYS_SHUTDOWN],byte 0 |
je noshutdown |
mov edx,[shutdown_processes] |
cmp [SYS_SHUTDOWN],dl |
jne no_mark_system_shutdown |
lea ecx,[edx-1] |
mov edx,OS_BASE+0x3040 |
jecxz @f |
markz: |
mov [edx+TASKDATA.state],byte 3 |
add edx,0x20 |
loop markz |
@@: |
no_mark_system_shutdown: |
call [_display.disable_mouse] |
dec byte [SYS_SHUTDOWN] |
je system_shutdown |
noshutdown: |
mov eax,[TASK_COUNT] ; termination |
mov ebx,TASK_DATA+TASKDATA.state |
mov esi,1 |
newct: |
mov cl,[ebx] |
cmp cl,byte 3 |
jz terminate |
cmp cl,byte 4 |
jz terminate |
add ebx,0x20 |
inc esi |
dec eax |
jnz newct |
ret |
; redraw screen |
redrawscreen: |
; eax , if process window_data base is eax, do not set flag/limits |
pushad |
push eax |
;;; mov ebx,2 |
;;; call delay_hs |
;mov ecx,0 ; redraw flags for apps |
xor ecx,ecx |
newdw2: |
inc ecx |
push ecx |
mov eax,ecx |
shl eax,5 |
add eax,window_data |
cmp eax,[esp+4] |
je not_this_task |
; check if window in redraw area |
mov edi,eax |
cmp ecx,1 ; limit for background |
jz bgli |
mov eax, [edi + WDATA.box.left] |
mov ebx, [edi + WDATA.box.top] |
mov ecx, [edi + WDATA.box.width] |
mov edx, [edi + WDATA.box.height] |
add ecx,eax |
add edx,ebx |
mov ecx,[draw_limits.bottom] ; ecx = area y end ebx = window y start |
cmp ecx,ebx |
jb ricino |
mov ecx,[draw_limits.right] ; ecx = area x end eax = window x start |
cmp ecx,eax |
jb ricino |
mov eax, [edi + WDATA.box.left] |
mov ebx, [edi + WDATA.box.top] |
mov ecx, [edi + WDATA.box.width] |
mov edx, [edi + WDATA.box.height] |
add ecx, eax |
add edx, ebx |
mov eax,[draw_limits.top] ; eax = area y start edx = window y end |
cmp edx,eax |
jb ricino |
mov eax,[draw_limits.left] ; eax = area x start ecx = window x end |
cmp ecx,eax |
jb ricino |
bgli: |
cmp dword[esp], 1 |
jnz .az |
; cmp byte[BACKGROUND_CHANGED], 0 |
; jnz newdw8 |
cmp byte[REDRAW_BACKGROUND], 0 |
jz .az |
mov dl, 0 |
lea eax,[edi+draw_data-window_data] |
mov ebx,[draw_limits.left] |
cmp ebx,[eax+RECT.left] |
jae @f |
mov [eax+RECT.left],ebx |
mov dl, 1 |
@@: |
mov ebx,[draw_limits.top] |
cmp ebx,[eax+RECT.top] |
jae @f |
mov [eax+RECT.top],ebx |
mov dl, 1 |
@@: |
mov ebx,[draw_limits.right] |
cmp ebx,[eax+RECT.right] |
jbe @f |
mov [eax+RECT.right],ebx |
mov dl, 1 |
@@: |
mov ebx,[draw_limits.bottom] |
cmp ebx,[eax+RECT.bottom] |
jbe @f |
mov [eax+RECT.bottom],ebx |
mov dl, 1 |
@@: |
add byte[REDRAW_BACKGROUND], dl |
jmp newdw8 |
.az: |
mov eax,edi |
add eax,draw_data-window_data |
mov ebx,[draw_limits.left] ; set limits |
mov [eax + RECT.left], ebx |
mov ebx,[draw_limits.top] |
mov [eax + RECT.top], ebx |
mov ebx,[draw_limits.right] |
mov [eax + RECT.right], ebx |
mov ebx,[draw_limits.bottom] |
mov [eax + RECT.bottom], ebx |
sub eax,draw_data-window_data |
cmp dword [esp],1 |
jne nobgrd |
inc byte[REDRAW_BACKGROUND] |
newdw8: |
nobgrd: |
mov [eax + WDATA.fl_redraw],byte 1 ; mark as redraw |
ricino: |
not_this_task: |
pop ecx |
cmp ecx,[TASK_COUNT] |
jle newdw2 |
pop eax |
popad |
ret |
calculatebackground: ; background |
mov edi, [_WinMapAddress] ; set os to use all pixels |
mov eax,0x01010101 |
mov ecx, [_WinMapSize] |
shr ecx, 2 |
rep stosd |
mov byte[REDRAW_BACKGROUND], 0 ; do not draw background! |
mov byte[BACKGROUND_CHANGED], 0 |
ret |
uglobal |
imax dd 0x0 |
endg |
delay_ms: ; delay in 1/1000 sec |
push eax |
push ecx |
mov ecx,esi |
; <CPU clock fix by Sergey Kuzmin aka Wildwest> |
imul ecx, 33941 |
shr ecx, 9 |
; </CPU clock fix> |
in al,0x61 |
and al,0x10 |
mov ah,al |
cld |
cnt1: in al,0x61 |
and al,0x10 |
cmp al,ah |
jz cnt1 |
mov ah,al |
loop cnt1 |
pop ecx |
pop eax |
ret |
set_app_param: |
mov edi, [TASK_BASE] |
mov eax, [edi + TASKDATA.event_mask] |
mov [edi + TASKDATA.event_mask], ebx |
mov [esp+32], eax |
ret |
delay_hs: ; delay in 1/100 secs |
; ebx = delay time |
push ecx |
push edx |
mov edx,[timer_ticks] |
newtic: |
mov ecx,[timer_ticks] |
sub ecx,edx |
cmp ecx,ebx |
jae zerodelay |
call change_task |
jmp newtic |
zerodelay: |
pop edx |
pop ecx |
ret |
align 16 ;very often call this subrutine |
memmove: ; memory move in bytes |
; eax = from |
; ebx = to |
; ecx = no of bytes |
test ecx, ecx |
jle .ret |
push esi edi ecx |
mov edi, ebx |
mov esi, eax |
test ecx, not 11b |
jz @f |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
and ecx, 11b |
jz .finish |
@@: |
rep movsb |
.finish: |
pop ecx edi esi |
.ret: |
ret |
; <diamond> Sysfunction 34, read_floppy_file, is obsolete. Use 58 or 70 function instead. |
;align 4 |
; |
;read_floppy_file: |
; |
;; as input |
;; |
;; eax pointer to file |
;; ebx file lenght |
;; ecx start 512 byte block number |
;; edx number of blocks to read |
;; esi pointer to return/work area (atleast 20 000 bytes) |
;; |
;; |
;; on return |
;; |
;; eax = 0 command succesful |
;; 1 no fd base and/or partition defined |
;; 2 yet unsupported FS |
;; 3 unknown FS |
;; 4 partition not defined at hd |
;; 5 file not found |
;; ebx = size of file |
; |
; mov edi,[TASK_BASE] |
; add edi,0x10 |
; add esi,[edi] |
; add eax,[edi] |
; |
; pushad |
; mov edi,esi |
; add edi,1024 |
; mov esi,0x100000+19*512 |
; sub ecx,1 |
; shl ecx,9 |
; add esi,ecx |
; shl edx,9 |
; mov ecx,edx |
; cld |
; rep movsb |
; popad |
; |
; mov [esp+36],eax |
; mov [esp+24],ebx |
; ret |
align 4 |
set_io_access_rights: |
push edi eax |
mov edi, tss._io_map_0 |
; mov ecx,eax |
; and ecx,7 ; offset in byte |
; shr eax,3 ; number of byte |
; add edi,eax |
; mov ebx,1 |
; shl ebx,cl |
test ebp,ebp |
; cmp ebp,0 ; enable access - ebp = 0 |
jnz .siar1 |
; not ebx |
; and [edi],byte bl |
btr [edi], eax |
pop eax edi |
ret |
.siar1: |
bts [edi], eax |
; or [edi],byte bl ; disable access - ebp = 1 |
pop eax edi |
ret |
;reserve/free group of ports |
; * eax = 46 - number function |
; * ebx = 0 - reserve, 1 - free |
; * ecx = number start arrea of ports |
; * edx = number end arrea of ports (include last number of port) |
;Return value: |
; * eax = 0 - succesful |
; * eax = 1 - error |
; * The system has reserve this ports: |
; 0..0x2d, 0x30..0x4d, 0x50..0xdf, 0xe5..0xff (include last number of port). |
;destroys eax,ebx, ebp |
r_f_port_area: |
test ebx, ebx |
jnz free_port_area |
; je r_port_area |
; jmp free_port_area |
; r_port_area: |
; pushad |
cmp ecx,edx ; beginning > end ? |
ja rpal1 |
cmp edx,65536 |
jae rpal1 |
mov eax,[RESERVED_PORTS] |
test eax,eax ; no reserved areas ? |
je rpal2 |
cmp eax,255 ; max reserved |
jae rpal1 |
rpal3: |
mov ebx,eax |
shl ebx,4 |
add ebx,RESERVED_PORTS |
cmp ecx,[ebx+8] |
ja rpal4 |
cmp edx,[ebx+4] |
jae rpal1 |
; jb rpal4 |
; jmp rpal1 |
rpal4: |
dec eax |
jnz rpal3 |
jmp rpal2 |
rpal1: |
; popad |
; mov eax,1 |
xor eax,eax |
inc eax |
ret |
rpal2: |
; popad |
; enable port access at port IO map |
cli |
pushad ; start enable io map |
cmp edx,65536 ;16384 |
jae no_unmask_io ; jge |
mov eax,ecx |
; push ebp |
xor ebp,ebp ; enable - eax = port |
new_port_access: |
; pushad |
call set_io_access_rights |
; popad |
inc eax |
cmp eax,edx |
jbe new_port_access |
; pop ebp |
no_unmask_io: |
popad ; end enable io map |
sti |
mov eax,[RESERVED_PORTS] |
add eax,1 |
mov [RESERVED_PORTS],eax |
shl eax,4 |
add eax,RESERVED_PORTS |
mov ebx,[TASK_BASE] |
mov ebx,[ebx+TASKDATA.pid] |
mov [eax],ebx |
mov [eax+4],ecx |
mov [eax+8],edx |
xor eax, eax |
ret |
free_port_area: |
; pushad |
mov eax,[RESERVED_PORTS] ; no reserved areas ? |
test eax,eax |
jz frpal2 |
mov ebx,[TASK_BASE] |
mov ebx,[ebx+TASKDATA.pid] |
frpal3: |
mov edi,eax |
shl edi,4 |
add edi,RESERVED_PORTS |
cmp ebx,[edi] |
jne frpal4 |
cmp ecx,[edi+4] |
jne frpal4 |
cmp edx,[edi+8] |
jne frpal4 |
jmp frpal1 |
frpal4: |
dec eax |
jnz frpal3 |
frpal2: |
; popad |
inc eax |
ret |
frpal1: |
push ecx |
mov ecx,256 |
sub ecx,eax |
shl ecx,4 |
mov esi,edi |
add esi,16 |
cld |
rep movsb |
dec dword [RESERVED_PORTS] |
;popad |
;disable port access at port IO map |
; pushad ; start disable io map |
pop eax ;start port |
cmp edx,65536 ;16384 |
jge no_mask_io |
; mov eax,ecx |
xor ebp,ebp |
inc ebp |
new_port_access_disable: |
; pushad |
; mov ebp,1 ; disable - eax = port |
call set_io_access_rights |
; popad |
inc eax |
cmp eax,edx |
jbe new_port_access_disable |
no_mask_io: |
; popad ; end disable io map |
xor eax, eax |
ret |
align 4 |
drawbackground: |
inc [mouse_pause] |
cmp [SCR_MODE],word 0x12 |
je dbrv20 |
dbrv12: |
cmp [SCR_MODE],word 0100000000000000b |
jge dbrv20 |
cmp [SCR_MODE],word 0x13 |
je dbrv20 |
call vesa12_drawbackground |
dec [mouse_pause] |
call [draw_pointer] |
ret |
dbrv20: |
cmp [BgrDrawMode],dword 1 |
jne bgrstr |
call vesa20_drawbackground_tiled |
dec [mouse_pause] |
call [draw_pointer] |
ret |
bgrstr: |
call vesa20_drawbackground_stretch |
dec [mouse_pause] |
call [draw_pointer] |
ret |
align 4 |
syscall_putimage: ; PutImage |
sys_putimage: |
test ecx,0x80008000 |
jnz .exit |
test ecx,0x0000FFFF |
jz .exit |
test ecx,0xFFFF0000 |
jnz @f |
.exit: |
ret |
@@: |
mov edi,[current_slot] |
add dx,word[edi+APPDATA.wnd_clientbox.top] |
rol edx,16 |
add dx,word[edi+APPDATA.wnd_clientbox.left] |
rol edx,16 |
.forced: |
push ebp esi 0 |
mov ebp, putimage_get24bpp |
mov esi, putimage_init24bpp |
sys_putimage_bpp: |
; call [disable_mouse] ; this will be done in xxx_putimage |
; mov eax, vga_putimage |
cmp [SCR_MODE], word 0x12 |
jz @f ;.doit |
mov eax, vesa12_putimage |
cmp [SCR_MODE], word 0100000000000000b |
jae @f |
cmp [SCR_MODE], word 0x13 |
jnz .doit |
@@: |
mov eax, vesa20_putimage |
.doit: |
inc [mouse_pause] |
call eax |
dec [mouse_pause] |
pop ebp esi ebp |
jmp [draw_pointer] |
align 4 |
sys_putimage_palette: |
; ebx = pointer to image |
; ecx = [xsize]*65536 + [ysize] |
; edx = [xstart]*65536 + [ystart] |
; esi = number of bits per pixel, must be 8, 24 or 32 |
; edi = pointer to palette |
; ebp = row delta |
mov eax, [CURRENT_TASK] |
shl eax, 8 |
add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.top] |
rol edx, 16 |
add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.left] |
rol edx, 16 |
.forced: |
cmp esi, 1 |
jnz @f |
push edi |
mov eax, [edi+4] |
sub eax, [edi] |
push eax |
push dword [edi] |
push 0ffffff80h |
mov edi, esp |
call put_mono_image |
add esp, 12 |
pop edi |
ret |
@@: |
cmp esi, 2 |
jnz @f |
push edi |
push 0ffffff80h |
mov edi, esp |
call put_2bit_image |
pop eax |
pop edi |
ret |
@@: |
cmp esi, 4 |
jnz @f |
push edi |
push 0ffffff80h |
mov edi, esp |
call put_4bit_image |
pop eax |
pop edi |
ret |
@@: |
push ebp esi ebp |
cmp esi, 8 |
jnz @f |
mov ebp, putimage_get8bpp |
mov esi, putimage_init8bpp |
jmp sys_putimage_bpp |
@@: |
cmp esi, 15 |
jnz @f |
mov ebp, putimage_get15bpp |
mov esi, putimage_init15bpp |
jmp sys_putimage_bpp |
@@: |
cmp esi, 16 |
jnz @f |
mov ebp, putimage_get16bpp |
mov esi, putimage_init16bpp |
jmp sys_putimage_bpp |
@@: |
cmp esi, 24 |
jnz @f |
mov ebp, putimage_get24bpp |
mov esi, putimage_init24bpp |
jmp sys_putimage_bpp |
@@: |
cmp esi, 32 |
jnz @f |
mov ebp, putimage_get32bpp |
mov esi, putimage_init32bpp |
jmp sys_putimage_bpp |
@@: |
pop ebp esi ebp |
ret |
put_mono_image: |
push ebp esi ebp |
mov ebp, putimage_get1bpp |
mov esi, putimage_init1bpp |
jmp sys_putimage_bpp |
put_2bit_image: |
push ebp esi ebp |
mov ebp, putimage_get2bpp |
mov esi, putimage_init2bpp |
jmp sys_putimage_bpp |
put_4bit_image: |
push ebp esi ebp |
mov ebp, putimage_get4bpp |
mov esi, putimage_init4bpp |
jmp sys_putimage_bpp |
putimage_init24bpp: |
lea eax, [eax*3] |
putimage_init8bpp: |
ret |
align 16 |
putimage_get24bpp: |
movzx eax, byte [esi+2] |
shl eax, 16 |
mov ax, [esi] |
add esi, 3 |
ret 4 |
align 16 |
putimage_get8bpp: |
movzx eax, byte [esi] |
push edx |
mov edx, [esp+8] |
mov eax, [edx+eax*4] |
pop edx |
inc esi |
ret 4 |
putimage_init1bpp: |
add eax, ecx |
push ecx |
add eax, 7 |
add ecx, 7 |
shr eax, 3 |
shr ecx, 3 |
sub eax, ecx |
pop ecx |
ret |
align 16 |
putimage_get1bpp: |
push edx |
mov edx, [esp+8] |
mov al, [edx] |
add al, al |
jnz @f |
lodsb |
adc al, al |
@@: |
mov [edx], al |
sbb eax, eax |
and eax, [edx+8] |
add eax, [edx+4] |
pop edx |
ret 4 |
putimage_init2bpp: |
add eax, ecx |
push ecx |
add ecx, 3 |
add eax, 3 |
shr ecx, 2 |
shr eax, 2 |
sub eax, ecx |
pop ecx |
ret |
align 16 |
putimage_get2bpp: |
push edx |
mov edx, [esp+8] |
mov al, [edx] |
mov ah, al |
shr al, 6 |
shl ah, 2 |
jnz .nonewbyte |
lodsb |
mov ah, al |
shr al, 6 |
shl ah, 2 |
add ah, 1 |
.nonewbyte: |
mov [edx], ah |
mov edx, [edx+4] |
movzx eax, al |
mov eax, [edx+eax*4] |
pop edx |
ret 4 |
putimage_init4bpp: |
add eax, ecx |
push ecx |
add ecx, 1 |
add eax, 1 |
shr ecx, 1 |
shr eax, 1 |
sub eax, ecx |
pop ecx |
ret |
align 16 |
putimage_get4bpp: |
push edx |
mov edx, [esp+8] |
add byte [edx], 80h |
jc @f |
movzx eax, byte [edx+1] |
mov edx, [edx+4] |
and eax, 0x0F |
mov eax, [edx+eax*4] |
pop edx |
ret 4 |
@@: |
movzx eax, byte [esi] |
add esi, 1 |
mov [edx+1], al |
shr eax, 4 |
mov edx, [edx+4] |
mov eax, [edx+eax*4] |
pop edx |
ret 4 |
putimage_init32bpp: |
shl eax, 2 |
ret |
align 16 |
putimage_get32bpp: |
lodsd |
ret 4 |
putimage_init15bpp: |
putimage_init16bpp: |
add eax, eax |
ret |
align 16 |
putimage_get15bpp: |
; 0RRRRRGGGGGBBBBB -> 00000000RRRRR000GGGGG000BBBBB000 |
push ecx edx |
movzx eax, word [esi] |
add esi, 2 |
mov ecx, eax |
mov edx, eax |
and eax, 0x1F |
and ecx, 0x1F shl 5 |
and edx, 0x1F shl 10 |
shl eax, 3 |
shl ecx, 6 |
shl edx, 9 |
or eax, ecx |
or eax, edx |
pop edx ecx |
ret 4 |
align 16 |
putimage_get16bpp: |
; RRRRRGGGGGGBBBBB -> 00000000RRRRR000GGGGGG00BBBBB000 |
push ecx edx |
movzx eax, word [esi] |
add esi, 2 |
mov ecx, eax |
mov edx, eax |
and eax, 0x1F |
and ecx, 0x3F shl 5 |
and edx, 0x1F shl 11 |
shl eax, 3 |
shl ecx, 5 |
shl edx, 8 |
or eax, ecx |
or eax, edx |
pop edx ecx |
ret 4 |
; eax x beginning |
; ebx y beginning |
; ecx x end |
; edx y end |
; edi color |
__sys_drawbar: |
mov esi,[current_slot] |
add eax,[esi+APPDATA.wnd_clientbox.left] |
add ecx,[esi+APPDATA.wnd_clientbox.left] |
add ebx,[esi+APPDATA.wnd_clientbox.top] |
add edx,[esi+APPDATA.wnd_clientbox.top] |
.forced: |
inc [mouse_pause] |
; call [disable_mouse] |
cmp [SCR_MODE],word 0x12 |
je dbv20 |
sdbv20: |
cmp [SCR_MODE],word 0100000000000000b |
jge dbv20 |
cmp [SCR_MODE],word 0x13 |
je dbv20 |
call vesa12_drawbar |
dec [mouse_pause] |
call [draw_pointer] |
ret |
dbv20: |
call vesa20_drawbar |
dec [mouse_pause] |
call [draw_pointer] |
ret |
kb_read: |
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 |
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: |
in al,0x64 |
test al,2 |
jz kw_ok |
loop kw_loop |
mov ah,1 |
jmp kw_exit |
kw_ok: |
mov al,dl |
out 0x60,al |
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's |
kw_loop3: |
in al,0x64 |
test al,2 |
jz kw_ok3 |
loop kw_loop3 |
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: |
xor ah,ah |
kw_exit: |
pop edx ecx |
ret |
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 |
mov [MOUSE_PICTURE],dword mousepointer |
cli |
ret |
if used _rdtsc |
_rdtsc: |
bt [cpu_caps], CAPS_TSC |
jnc ret_rdtsc |
rdtsc |
ret |
ret_rdtsc: |
mov edx,0xffffffff |
mov eax,0xffffffff |
ret |
end if |
sys_msg_board_str: |
pushad |
@@: |
cmp [esi],byte 0 |
je @f |
mov eax,1 |
movzx ebx,byte [esi] |
call sys_msg_board |
inc esi |
jmp @b |
@@: |
popad |
ret |
sys_msg_board_byte: |
; in: al = byte to display |
; out: nothing |
; destroys: nothing |
pushad |
mov ecx, 2 |
shl eax, 24 |
jmp @f |
sys_msg_board_word: |
; in: ax = word to display |
; out: nothing |
; destroys: nothing |
pushad |
mov ecx, 4 |
shl eax, 16 |
jmp @f |
sys_msg_board_dword: |
; in: eax = dword to display |
; out: nothing |
; destroys: nothing |
pushad |
mov ecx, 8 |
@@: |
push ecx |
rol eax, 4 |
push eax |
and al, 0xF |
cmp al, 10 |
sbb al, 69h |
das |
mov bl, al |
xor eax, eax |
inc eax |
call sys_msg_board |
pop eax |
pop ecx |
loop @b |
popad |
ret |
uglobal |
msg_board_data: times 4096 db 0 |
msg_board_count dd 0x0 |
endg |
sys_msg_board: |
; eax=1 : write : bl byte to write |
; eax=2 : read : ebx=0 -> no data, ebx=1 -> data in al |
mov ecx, [msg_board_count] |
cmp eax, 1 |
jne .smbl1 |
if defined debug_com_base |
push dx ax |
@@: ; Wait for empty transmit register (yes, this slows down system..) |
mov dx, debug_com_base+5 |
in al, dx |
test al, 1 shl 5 |
jz @r |
mov dx, debug_com_base ; Output the byte |
mov al, bl |
out dx, al |
pop ax dx |
end if |
mov [msg_board_data+ecx],bl |
inc ecx |
and ecx, 4095 |
mov [msg_board_count], ecx |
mov [check_idle_semaphore], 5 |
ret |
.smbl1: |
cmp eax, 2 |
jne .smbl2 |
test ecx, ecx |
jz .smbl21 |
mov eax, msg_board_data+1 |
mov ebx, msg_board_data |
movzx edx, byte [ebx] |
call memmove |
dec [msg_board_count] |
mov [esp + 36], edx ;eax |
mov [esp + 24], dword 1 |
ret |
.smbl21: |
mov [esp+36], ecx |
mov [esp+24], ecx |
.smbl2: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; 66 sys function. ;; |
;; in eax=66,ebx in [0..5],ecx,edx ;; |
;; out eax ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
iglobal |
align 4 |
f66call: |
dd sys_process_def.1 ; 1 = set keyboard mode |
dd sys_process_def.2 ; 2 = get keyboard mode |
dd sys_process_def.3 ; 3 = get keyboard ctrl, alt, shift |
dd sys_process_def.4 |
dd sys_process_def.5 |
endg |
sys_process_def: |
dec ebx |
cmp ebx,5 |
jae .not_support ;if >=6 then or eax,-1 |
mov edi, [CURRENT_TASK] |
jmp dword [f66call+ebx*4] |
.not_support: |
or eax,-1 |
ret |
.1: |
shl edi,8 |
mov [edi+SLOT_BASE + APPDATA.keyboard_mode],cl |
ret |
.2: ; 2 = get keyboard mode |
shl edi,8 |
movzx eax, byte [SLOT_BASE+edi + APPDATA.keyboard_mode] |
mov [esp+32],eax |
ret |
; xor eax,eax |
; movzx eax,byte [shift] |
; movzx ebx,byte [ctrl] |
; shl ebx,2 |
; add eax,ebx |
; movzx ebx,byte [alt] |
; shl ebx,3 |
; add eax,ebx |
.3: ;3 = get keyboard ctrl, alt, shift |
;// mike.dld [ |
mov eax, [kb_state] |
;// mike.dld ] |
mov [esp+32],eax |
ret |
.4: |
mov eax, hotkey_list |
@@: |
cmp dword [eax+8], 0 |
jz .found_free |
add eax, 16 |
cmp eax, hotkey_list+16*256 |
jb @b |
mov dword [esp+32], 1 |
ret |
.found_free: |
mov [eax+8], edi |
mov [eax+4], edx |
movzx ecx, cl |
lea ecx, [hotkey_scancodes+ecx*4] |
mov edx, [ecx] |
mov [eax], edx |
mov [ecx], eax |
mov [eax+12], ecx |
jecxz @f |
mov [edx+12], eax |
@@: |
and dword [esp+32], 0 |
ret |
.5: |
movzx ebx, cl |
lea ebx, [hotkey_scancodes+ebx*4] |
mov eax, [ebx] |
.scan: |
test eax, eax |
jz .notfound |
cmp [eax+8], edi |
jnz .next |
cmp [eax+4], edx |
jz .found |
.next: |
mov eax, [eax] |
jmp .scan |
.notfound: |
mov dword [esp+32], 1 |
ret |
.found: |
mov ecx, [eax] |
jecxz @f |
mov edx, [eax+12] |
mov [ecx+12], edx |
@@: |
mov ecx, [eax+12] |
mov edx, [eax] |
mov [ecx], edx |
xor edx, edx |
mov [eax+4], edx |
mov [eax+8], edx |
mov [eax+12], edx |
mov [eax], edx |
mov [esp+32], edx |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; 61 sys function. ;; |
;; in eax=61,ebx in [1..3] ;; |
;; out eax ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
iglobal |
align 4 |
f61call: |
dd sys_gs.1 ; resolution |
dd sys_gs.2 ; bits per pixel |
dd sys_gs.3 ; bytes per scanline |
endg |
align 4 |
sys_gs: ; direct screen access |
dec ebx |
cmp ebx,2 |
ja .not_support |
jmp dword [f61call+ebx*4] |
.not_support: |
or [esp+32],dword -1 |
ret |
.1: ; resolution |
mov eax,[Screen_Max_X] |
shl eax,16 |
mov ax,[Screen_Max_Y] |
add eax,0x00010001 |
mov [esp+32],eax |
ret |
.2: ; bits per pixel |
movzx eax,byte [ScreenBPP] |
mov [esp+32],eax |
ret |
.3: ; bytes per scanline |
mov eax,[BytesPerScanLine] |
mov [esp+32],eax |
ret |
align 4 ; system functions |
syscall_setpixel: ; SetPixel |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov edx, [TASK_BASE] |
add eax, [edx-twdw+WDATA.box.left] |
add ebx, [edx-twdw+WDATA.box.top] |
mov edi, [current_slot] |
add eax, [edi+APPDATA.wnd_clientbox.left] |
add ebx, [edi+APPDATA.wnd_clientbox.top] |
xor edi, edi ; no force |
; mov edi, 1 |
call [_display.disable_mouse] |
jmp [putpixel] |
align 4 |
syscall_writetext: ; WriteText |
mov eax,[TASK_BASE] |
mov ebp,[eax-twdw+WDATA.box.left] |
push esi |
mov esi,[current_slot] |
add ebp,[esi+APPDATA.wnd_clientbox.left] |
shl ebp,16 |
add ebp,[eax-twdw+WDATA.box.top] |
add bp,word[esi+APPDATA.wnd_clientbox.top] |
pop esi |
add ebx,ebp |
mov eax,edi |
xor edi,edi |
jmp dtext |
align 4 |
syscall_openramdiskfile: ; OpenRamdiskFile |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov edx, esi |
mov esi, 12 |
call fileread |
mov [esp+32], eax |
ret |
align 4 |
syscall_drawrect: ; DrawRect |
mov edi, edx ; color + gradient |
and edi, 0x80FFFFFF |
test bx, bx ; x.size |
je .drectr |
test cx, cx ; y.size |
je .drectr |
mov eax, ebx ; bad idea |
mov ebx, ecx |
movzx ecx, ax ; ecx - x.size |
shr eax, 16 ; eax - x.coord |
movzx edx, bx ; edx - y.size |
shr ebx, 16 ; ebx - y.coord |
mov esi, [current_slot] |
add eax, [esi + APPDATA.wnd_clientbox.left] |
add ebx, [esi + APPDATA.wnd_clientbox.top] |
add ecx, eax |
add edx, ebx |
jmp [drawbar] |
.drectr: |
ret |
align 4 |
syscall_getscreensize: ; GetScreenSize |
mov ax, [Screen_Max_X] |
shl eax, 16 |
mov ax, [Screen_Max_Y] |
mov [esp + 32], eax |
ret |
align 4 |
syscall_cdaudio: ; CD |
cmp ebx, 4 |
jb .audio |
jz .eject |
cmp ebx, 5 |
jnz .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 eax, ecx |
shr eax, 1 |
and eax, 1 |
inc eax |
mov [ChannelNumber], ax |
mov eax, ecx |
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: ; GetPixel |
mov ecx, [Screen_Max_X] |
inc ecx |
xor edx, edx |
mov eax, ebx |
div ecx |
mov ebx, edx |
xchg eax, ebx |
call dword [GETPIXEL] ; eax - x, ebx - y |
mov [esp + 32], ecx |
ret |
align 4 |
syscall_getarea: |
;eax = 36 |
;ebx = pointer to bufer for img BBGGRRBBGGRR... |
;ecx = [size x]*65536 + [size y] |
;edx = [start x]*65536 + [start y] |
pushad |
inc [mouse_pause] |
; Check of use of the hardware cursor. |
cmp [_display.disable_mouse],__sys_disable_mouse |
jne @f |
; Since the test for the coordinates of the mouse should not be used, |
; then use the call [disable_mouse] is not possible! |
cmp dword [MOUSE_VISIBLE],dword 0 |
jne @f |
pushf |
cli |
call draw_mouse_under |
popf |
mov [MOUSE_VISIBLE],dword 1 |
@@: |
mov edi,ebx |
mov eax,edx |
shr eax,16 |
mov ebx,edx |
and ebx,0xffff |
dec eax |
dec ebx |
; eax - x, ebx - y |
mov edx,ecx |
shr ecx,16 |
and edx,0xffff |
mov esi,ecx |
; ecx - size x, edx - size y |
mov ebp,edx |
dec ebp |
lea ebp,[ebp*3] |
imul ebp,esi |
mov esi,ecx |
dec esi |
lea esi,[esi*3] |
add ebp,esi |
add ebp,edi |
add ebx,edx |
.start_y: |
push ecx edx |
.start_x: |
push eax ebx ecx |
add eax,ecx |
call dword [GETPIXEL] ; eax - x, ebx - y |
mov [ebp],cx |
shr ecx,16 |
mov [ebp+2],cl |
pop ecx ebx eax |
sub ebp,3 |
dec ecx |
jnz .start_x |
pop edx ecx |
dec ebx |
dec edx |
jnz .start_y |
dec [mouse_pause] |
; Check of use of the hardware cursor. |
cmp [_display.disable_mouse],__sys_disable_mouse |
jne @f |
call [draw_pointer] |
@@: |
popad |
ret |
align 4 |
syscall_drawline: ; DrawLine |
mov edi, [TASK_BASE] |
movzx eax, word[edi-twdw+WDATA.box.left] |
mov ebp, eax |
mov esi, [current_slot] |
add ebp, [esi+APPDATA.wnd_clientbox.left] |
add ax, word[esi+APPDATA.wnd_clientbox.left] |
add ebp,ebx |
shl eax, 16 |
movzx ebx, word[edi-twdw+WDATA.box.top] |
add eax, ebp |
mov ebp, ebx |
add ebp, [esi+APPDATA.wnd_clientbox.top] |
add bx, word[esi+APPDATA.wnd_clientbox.top] |
add ebp, ecx |
shl ebx, 16 |
xor edi, edi |
add ebx, ebp |
mov ecx, edx |
jmp [draw_line] |
align 4 |
syscall_reserveportarea: ; ReservePortArea and FreePortArea |
call r_f_port_area |
mov [esp+32],eax |
ret |
align 4 |
syscall_threads: ; CreateThreads |
; eax=1 create thread |
; |
; ebx=thread start |
; ecx=thread stack value |
; |
; on return : eax = pid |
call new_sys_threads |
mov [esp+32],eax |
ret |
align 4 |
stack_driver_stat: |
call app_stack_handler ; Stack status |
; mov [check_idle_semaphore],5 ; enable these for zero delay |
; call change_task ; between sent packet |
mov [esp+32],eax |
ret |
align 4 |
socket: ; Socket interface |
call app_socket_handler |
; mov [check_idle_semaphore],5 ; enable these for zero delay |
; call change_task ; between sent packet |
mov [esp+36],eax |
mov [esp+24],ebx |
ret |
align 4 |
read_from_hd: ; Read from hd - fn not in use |
mov edi,[TASK_BASE] |
add edi,TASKDATA.mem_start |
add eax,[edi] |
add ecx,[edi] |
add edx,[edi] |
call file_read |
mov [esp+36],eax |
mov [esp+24],ebx |
ret |
paleholder: |
ret |
align 4 |
set_screen: |
cmp eax, [Screen_Max_X] |
jne .set |
cmp edx, [Screen_Max_Y] |
jne .set |
ret |
.set: |
pushfd |
cli |
mov [Screen_Max_X], eax |
mov [Screen_Max_Y], edx |
mov [BytesPerScanLine], ecx |
mov [screen_workarea.right],eax |
mov [screen_workarea.bottom], edx |
push ebx |
push esi |
push edi |
pushad |
stdcall kernel_free, [_WinMapAddress] |
mov eax, [_display.width] |
mul [_display.height] |
mov [_WinMapSize], eax |
stdcall kernel_alloc, eax |
mov [_WinMapAddress], eax |
test eax, eax |
jz .epic_fail |
popad |
call repos_windows |
xor eax, eax |
xor ebx, ebx |
mov ecx, [Screen_Max_X] |
mov edx, [Screen_Max_Y] |
call calculatescreen |
pop edi |
pop esi |
pop ebx |
popfd |
ret |
.epic_fail: |
hlt ; Houston, we've had a problem |
; --------------- APM --------------------- |
uglobal |
apm_entry dp 0 |
apm_vf dd 0 |
endg |
align 4 |
sys_apm: |
xor eax,eax |
cmp word [apm_vf], ax ; Check APM BIOS enable |
jne @f |
inc eax |
or dword [esp + 44], eax ; error |
add eax,7 |
mov dword [esp + 32], eax ; 32-bit protected-mode interface not supported |
ret |
@@: |
; xchg eax, ecx |
; xchg ebx, ecx |
cmp dx, 3 |
ja @f |
and [esp + 44], byte 0xfe ; emulate func 0..3 as func 0 |
mov eax,[apm_vf] |
mov [esp + 32], eax |
shr eax, 16 |
mov [esp + 28], eax |
ret |
@@: |
mov esi,[master_tab+(OS_BASE shr 20)] |
xchg [master_tab], esi |
push esi |
mov edi, cr3 |
mov cr3, edi ;flush TLB |
call pword [apm_entry] ;call APM BIOS |
xchg eax, [esp] |
mov [master_tab], eax |
mov eax, cr3 |
mov cr3, eax |
pop eax |
mov [esp + 4 ], edi |
mov [esp + 8], esi |
mov [esp + 20], ebx |
mov [esp + 24], edx |
mov [esp + 28], ecx |
mov [esp + 32], eax |
setc al |
and [esp + 44], byte 0xfe |
or [esp + 44], al |
ret |
; ----------------------------------------- |
align 4 |
undefined_syscall: ; Undefined system call |
mov [esp + 32], dword -1 |
ret |
align 4 |
system_shutdown: ; shut down the system |
cmp byte [BOOT_VAR+0x9030], 1 |
jne @F |
ret |
@@: |
call stop_all_services |
push 3 ; stop playing cd |
pop eax |
call sys_cd_audio |
yes_shutdown_param: |
cli |
if ~ defined extended_primary_loader |
mov eax, kernel_file ; load kernel.mnt to 0x7000:0 |
push 12 |
pop esi |
xor ebx,ebx |
or ecx,-1 |
mov edx, OS_BASE+0x70000 |
call fileread |
mov esi, restart_kernel_4000+OS_BASE+0x10000 ; move kernel re-starter to 0x4000:0 |
mov edi,OS_BASE+0x40000 |
mov ecx,1000 |
rep movsb |
end if |
mov esi, BOOT_VAR ; restore 0x0 - 0xffff |
mov edi, OS_BASE |
mov ecx,0x10000/4 |
cld |
rep movsd |
call restorefatchain |
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 |
; scan for RSDP |
; 1) The first 1 Kb of the Extended BIOS Data Area (EBDA). |
movzx eax, word [OS_BASE + 0x40E] |
shl eax, 4 |
jz @f |
mov ecx, 1024/16 |
call scan_rsdp |
jnc .rsdp_found |
@@: |
; 2) The BIOS read-only memory space between 0E0000h and 0FFFFFh. |
mov eax, 0xE0000 |
mov ecx, 0x2000 |
call scan_rsdp |
jc no_acpi_power_off |
.rsdp_found: |
mov esi, [eax+16] ; esi contains physical address of the RSDT |
mov ebp, [ipc_tmp] |
stdcall map_page, ebp, esi, PG_MAP |
lea eax, [esi+1000h] |
lea edx, [ebp+1000h] |
stdcall map_page, edx, eax, PG_MAP |
and esi, 0xFFF |
add esi, ebp |
cmp dword [esi], 'RSDT' |
jnz no_acpi_power_off |
mov ecx, [esi+4] |
sub ecx, 24h |
jbe no_acpi_power_off |
shr ecx, 2 |
add esi, 24h |
.scan_fadt: |
lodsd |
mov ebx, eax |
lea eax, [ebp+2000h] |
stdcall map_page, eax, ebx, PG_MAP |
lea eax, [ebp+3000h] |
add ebx, 0x1000 |
stdcall map_page, eax, ebx, PG_MAP |
and ebx, 0xFFF |
lea ebx, [ebx+ebp+2000h] |
cmp dword [ebx], 'FACP' |
jz .fadt_found |
loop .scan_fadt |
jmp no_acpi_power_off |
.fadt_found: |
; ebx is linear address of FADT |
mov edi, [ebx+40] ; physical address of the DSDT |
lea eax, [ebp+4000h] |
stdcall map_page, eax, edi, PG_MAP |
lea eax, [ebp+5000h] |
lea esi, [edi+0x1000] |
stdcall map_page, eax, esi, PG_MAP |
and esi, 0xFFF |
sub edi, esi |
cmp dword [esi+ebp+4000h], 'DSDT' |
jnz no_acpi_power_off |
mov eax, [esi+ebp+4004h] ; DSDT length |
sub eax, 36+4 |
jbe no_acpi_power_off |
add esi, 36 |
.scan_dsdt: |
cmp dword [esi+ebp+4000h], '_S5_' |
jnz .scan_dsdt_cont |
cmp byte [esi+ebp+4000h+4], 12h ; DefPackage opcode |
jnz .scan_dsdt_cont |
mov dl, [esi+ebp+4000h+6] |
cmp dl, 4 ; _S5_ package must contain 4 bytes |
; ...in theory; in practice, VirtualBox has 2 bytes |
ja .scan_dsdt_cont |
cmp dl, 1 |
jb .scan_dsdt_cont |
lea esi, [esi+ebp+4000h+7] |
xor ecx, ecx |
cmp byte [esi], 0 ; 0 means zero byte, 0Ah xx means byte xx |
jz @f |
cmp byte [esi], 0xA |
jnz no_acpi_power_off |
inc esi |
mov cl, [esi] |
@@: |
inc esi |
cmp dl, 2 |
jb @f |
cmp byte [esi], 0 |
jz @f |
cmp byte [esi], 0xA |
jnz no_acpi_power_off |
inc esi |
mov ch, [esi] |
@@: |
jmp do_acpi_power_off |
.scan_dsdt_cont: |
inc esi |
cmp esi, 0x1000 |
jb @f |
sub esi, 0x1000 |
add edi, 0x1000 |
push eax |
lea eax, [ebp+4000h] |
stdcall map_page, eax, edi, PG_MAP |
push PG_MAP |
lea eax, [edi+1000h] |
push eax |
lea eax, [ebp+5000h] |
push eax |
stdcall map_page |
pop eax |
@@: |
dec eax |
jnz .scan_dsdt |
jmp no_acpi_power_off |
do_acpi_power_off: |
mov edx, [ebx+48] |
test edx, edx |
jz .nosmi |
mov al, [ebx+52] |
out dx, al |
mov edx, [ebx+64] |
@@: |
in ax, dx |
test al, 1 |
jz @b |
.nosmi: |
and cx, 0x0707 |
shl cx, 2 |
or cx, 0x2020 |
mov edx, [ebx+64] |
in ax, dx |
and ax, 203h |
or ah, cl |
out dx, ax |
mov edx, [ebx+68] |
test edx, edx |
jz @f |
in ax, dx |
and ax, 203h |
or ah, ch |
out dx, ax |
@@: |
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: |
cmp dword [eax], 'RSD ' |
jnz .n |
cmp dword [eax+4], 'PTR ' |
jnz .n |
xor edx, edx |
xor esi, esi |
@@: |
add dl, [eax+esi] |
inc esi |
cmp esi, 20 |
jnz @b |
test dl, dl |
jz .ok |
.n: |
add eax, 10h |
loop .s |
stc |
.ok: |
ret |
end if |
include "data32.inc" |
__REV__ = __REV |
uglobals_size = $ - endofcode |
diff16 "end of kernel code",0,$ |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. |
;; PROGRAMMING: |
;; Ivan Poddubny |
;; Marat Zakiyanov (Mario79) |
;; VaStaNi |
;; Trans |
;; Mihail Semenyako (mike.dld) |
;; Sergey Kuzmin (Wildwest) |
;; Andrey Halyavin (halyavin) |
;; Mihail Lisovin (Mihasik) |
;; Andrey Ignatiev (andrew_programmer) |
;; NoName |
;; Evgeny Grechnikov (Diamond) |
;; Iliya Mihailov (Ghost) |
;; Sergey Semyonov (Serge) |
;; Johnny_B |
;; SPraid (simba) |
;; Hidnplayr |
;; Alexey Teplov (<Lrz>) |
;; Rus |
;; Nable |
;; shurf |
;; Alver |
;; Maxis |
;; Galkov |
;; CleverMouse |
;; tsdima |
;; turbanoff |
;; Asper |
;; art_zh |
;; |
;; Data in this file was originally part of MenuetOS project which is |
;; distributed under the terms of GNU GPL. It is modified and redistributed as |
;; part of KolibriOS project under the terms of GNU GPL. |
;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa |
;; PROGRAMMING: |
;; |
;; Ville Mikael Turjanmaa, villemt@itu.jyu.fi |
;; - main os coding/design |
;; Jan-Michael Brummer, BUZZ2@gmx.de |
;; Felix Kaiser, info@felix-kaiser.de |
;; Paolo Minazzi, paolo.minazzi@inwind.it |
;; quickcode@mail.ru |
;; Alexey, kgaz@crosswinds.net |
;; Juan M. Caravaca, bitrider@wanadoo.es |
;; kristol@nic.fi |
;; Mike Hibbett, mikeh@oceanfree.net |
;; Lasse Kuusijarvi, kuusijar@lut.fi |
;; Jarek Pelczar, jarekp3@wp.pl |
;; |
;; KolibriOS is distributed in the hope that it will be useful, but WITHOUT ANY |
;; WARRANTY. No author or distributor accepts responsibility to anyone for the |
;; consequences of using it or for whether it serves any particular purpose or |
;; works at all, unless he says so in writing. Refer to the GNU General Public |
;; License (the "GPL") for full details. |
; |
;; Everyone is granted permission to copy, modify and redistribute KolibriOS, |
;; but only under the conditions described in the GPL. A copy of this license |
;; is supposed to have been given to you along with KolibriOS so you can know |
;; your rights and responsibilities. It should be in a file named COPYING. |
;; Among other things, the copyright notice and this notice must be preserved |
;; on all copies. |
;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include 'macros.inc' |
$Revision$ |
USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices |
; Enabling the next line will enable serial output console |
;debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used |
include "proc32.inc" |
include "kglobals.inc" |
include "lang.inc" |
include "const.inc" |
max_processes equ 255 |
tss_step equ (128+8192) ; tss & i/o - 65535 ports, * 256=557056*4 |
os_stack equ (os_data_l-gdts) ; GDTs |
os_code equ (os_code_l-gdts) |
graph_data equ (3+graph_data_l-gdts) |
tss0 equ (tss0_l-gdts) |
app_code equ (3+app_code_l-gdts) |
app_data equ (3+app_data_l-gdts) |
app_tls equ (3+tls_data_l-gdts) |
pci_code_sel equ (pci_code_32-gdts) |
pci_data_sel equ (pci_data_32-gdts) |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; |
;; Included files: |
;; |
;; Kernel16.inc |
;; - Booteng.inc English text for bootup |
;; - Bootcode.inc Hardware setup |
;; - Pci16.inc PCI functions |
;; |
;; Kernel32.inc |
;; - Sys32.inc Process management |
;; - Shutdown.inc Shutdown and restart |
;; - Fat32.inc Read / write hd |
;; - Vesa12.inc Vesa 1.2 driver |
;; - Vesa20.inc Vesa 2.0 driver |
;; - Vga.inc VGA driver |
;; - Stack.inc Network interface |
;; - Mouse.inc Mouse pointer |
;; - Scincode.inc Window skinning |
;; - Pci32.inc PCI functions |
;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 16 BIT ENTRY FROM BOOTSECTOR ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
use16 |
org 0x0 |
jmp start_of_code |
version db 'Kolibri OS version 0.7.7.0+ ',13,10,13,10,0 |
include "boot/bootstr.inc" ; language-independent boot messages |
include "boot/preboot.inc" |
if lang eq en |
include "boot/booteng.inc" ; english system boot messages |
else if lang eq ru |
include "boot/bootru.inc" ; russian system boot messages |
include "boot/ru.inc" ; Russian font |
else if lang eq et |
include "boot/bootet.inc" ; estonian system boot messages |
include "boot/et.inc" ; Estonian font |
else |
include "boot/bootge.inc" ; german system boot messages |
end if |
include "boot/bootcode.inc" ; 16 bit system boot code |
include "bus/pci/pci16.inc" |
include "detect/biosdisk.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SWITCH TO 32 BIT PROTECTED MODE ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CR0 Flags - Protected mode and Paging |
mov ecx, CR0_PE |
; Enabling 32 bit protected mode |
sidt [cs:old_ints_h] |
cli ; disable all irqs |
cld |
mov al, 255 ; mask all irqs |
out 0xa1, al |
out 0x21, al |
l.5: |
in al, 0x64 ; Enable A20 |
test al, 2 |
jnz l.5 |
mov al, 0xD1 |
out 0x64, al |
l.6: |
in al, 0x64 |
test al, 2 |
jnz l.6 |
mov al, 0xDF |
out 0x60, al |
l.7: |
in al, 0x64 |
test al, 2 |
jnz l.7 |
mov al, 0xFF |
out 0x64, al |
lgdt [cs:tmp_gdt] ; Load GDT |
mov eax, cr0 ; protected mode |
or eax, ecx |
and eax, 10011111b *65536*256 + 0xffffff ; caching enabled |
mov cr0, eax |
jmp pword os_code:B32 ; jmp to enable 32 bit mode |
align 8 |
tmp_gdt: |
dw 23 |
dd tmp_gdt+0x10000 |
dw 0 |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10011010b |
db 0x00 |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10010010b |
db 0x00 |
include "data16.inc" |
use32 |
org $+0x10000 |
align 4 |
B32: |
mov ax, os_stack ; Selector for os |
mov ds, ax |
mov es, ax |
mov fs, ax |
mov gs, ax |
mov ss, ax |
mov esp, 0x006CC00 ; Set stack |
; CLEAR 0x280000 - HEAP_BASE |
xor eax, eax |
mov edi, CLEAN_ZONE |
mov ecx, (HEAP_BASE-OS_BASE-CLEAN_ZONE) / 4 |
cld |
rep stosd |
; CLEAR KERNEL UNDEFINED GLOBALS |
mov edi, endofcode-OS_BASE |
mov ecx, 0x90000 |
sub ecx, edi |
shr ecx, 2 |
rep stosd |
; SAVE & CLEAR 0-0xffff |
xor esi, esi |
mov edi, (BOOT_VAR-OS_BASE) |
mov ecx, 0x10000 / 4 |
rep movsd |
mov edi, 0x1000 |
mov ecx, 0xf000 / 4 |
rep stosd |
call test_cpu |
bts [cpu_caps-OS_BASE], CAPS_TSC ;force use rdtsc |
call check_acpi |
call init_BIOS32 |
; MEMORY MODEL |
call mem_test |
call init_mem |
call init_page_map |
; ENABLE PAGING |
mov eax, sys_pgdir-OS_BASE |
mov cr3, eax |
mov eax, cr0 |
or eax, CR0_PG+CR0_WP |
mov cr0, eax |
lgdt [gdts] |
jmp pword os_code:high_code |
align 4 |
bios32_entry dd ? |
tmp_page_tabs dd ? |
use16 |
org $-0x10000 |
include "boot/shutdown.inc" ; shutdown or restart |
org $+0x10000 |
use32 |
__DEBUG__ fix 1 |
__DEBUG_LEVEL__ fix 1 |
include 'init.inc' |
org OS_BASE+$ |
align 4 |
high_code: |
mov ax, os_stack |
mov bx, app_data |
mov cx, app_tls |
mov ss, ax |
add esp, OS_BASE |
mov ds, bx |
mov es, bx |
mov fs, cx |
mov gs, bx |
bt [cpu_caps], CAPS_PGE |
jnc @F |
or dword [sys_pgdir+(OS_BASE shr 20)], PG_GLOBAL |
mov ebx, cr4 |
or ebx, CR4_PGE |
mov cr4, ebx |
@@: |
xor eax, eax |
mov dword [sys_pgdir], eax |
mov dword [sys_pgdir+4], eax |
mov eax, cr3 |
mov cr3, eax ; flush TLB |
mov ecx, pg_data.mutex |
call mutex_init |
mov ecx, disk_list_mutex |
call mutex_init |
; SAVE REAL MODE VARIABLES |
mov ax, [BOOT_VAR + 0x9031] |
mov [IDEContrRegsBaseAddr], ax |
; --------------- APM --------------------- |
; init selectors |
mov ebx, [BOOT_VAR+0x9040] ; offset of APM entry point |
movzx eax, word [BOOT_VAR+0x9050]; real-mode segment base address of |
; protected-mode 32-bit code segment |
movzx ecx, word [BOOT_VAR+0x9052]; real-mode segment base address of |
; protected-mode 16-bit code segment |
movzx edx, word [BOOT_VAR+0x9054]; real-mode segment base address of |
; protected-mode 16-bit data segment |
shl eax, 4 |
mov [dword apm_code_32 + 2], ax |
shr eax, 16 |
mov [dword apm_code_32 + 4], al |
shl ecx, 4 |
mov [dword apm_code_16 + 2], cx |
shr ecx, 16 |
mov [dword apm_code_16 + 4], cl |
shl edx, 4 |
mov [dword apm_data_16 + 2], dx |
shr edx, 16 |
mov [dword apm_data_16 + 4], dl |
mov dword[apm_entry], ebx |
mov word [apm_entry + 4], apm_code_32 - gdts |
mov eax, [BOOT_VAR + 0x9044]; version & flags |
mov [apm_vf], eax |
; ----------------------------------------- |
; movzx eax,byte [BOOT_VAR+0x9010] ; mouse port |
; mov [0xF604],byte 1 ;al |
mov al, [BOOT_VAR+0x901F] ; DMA access |
mov [allow_dma_access], al |
movzx eax, byte [BOOT_VAR+0x9000] ; bpp |
mov [ScreenBPP], al |
mov [_display.bpp], eax |
mov [_display.vrefresh], 60 |
mov [_display.disable_mouse], __sys_disable_mouse |
movzx eax, word [BOOT_VAR+0x900A]; X max |
mov [_display.width], eax |
dec eax |
mov [Screen_Max_X], eax |
mov [screen_workarea.right], eax |
movzx eax, word [BOOT_VAR+0x900C]; Y max |
mov [_display.height], eax |
dec eax |
mov [Screen_Max_Y], eax |
mov [screen_workarea.bottom], eax |
movzx eax, word [BOOT_VAR+0x9008]; screen mode |
mov [SCR_MODE], eax |
mov eax, [BOOT_VAR+0x9014] ; Vesa 1.2 bnk sw add |
mov [BANK_SWITCH], eax |
mov [BytesPerScanLine], word 640*4 ; Bytes PerScanLine |
cmp [SCR_MODE], word 0x13 ; 320x200 |
je @f |
cmp [SCR_MODE], word 0x12 ; VGA 640x480 |
je @f |
movzx eax, word[BOOT_VAR+0x9001] ; for other modes |
mov [BytesPerScanLine], ax |
mov [_display.pitch], eax |
@@: |
mov eax, [_display.width] |
mul [_display.height] |
mov [_WinMapSize], eax |
mov esi, BOOT_VAR+0x9080 |
movzx ecx, byte [esi-1] |
mov [NumBiosDisks], ecx |
mov edi, BiosDisksData |
rep movsd |
; GRAPHICS ADDRESSES |
and byte [BOOT_VAR+0x901e], 0x0 |
mov eax, [BOOT_VAR+0x9018] |
mov [LFBAddress], eax |
cmp [SCR_MODE], word 0100000000000000b |
jge setvesa20 |
cmp [SCR_MODE], word 0x13 |
je v20ga32 |
mov [PUTPIXEL], dword Vesa12_putpixel24 ; Vesa 1.2 |
mov [GETPIXEL], dword Vesa12_getpixel24 |
cmp [ScreenBPP], byte 24 |
jz ga24 |
mov [PUTPIXEL], dword Vesa12_putpixel32 |
mov [GETPIXEL], dword Vesa12_getpixel32 |
ga24: |
jmp v20ga24 |
setvesa20: |
mov [PUTPIXEL], dword Vesa20_putpixel24 ; Vesa 2.0 |
mov [GETPIXEL], dword Vesa20_getpixel24 |
cmp [ScreenBPP], byte 24 |
jz v20ga24 |
v20ga32: |
mov [PUTPIXEL], dword Vesa20_putpixel32 |
mov [GETPIXEL], dword Vesa20_getpixel32 |
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: |
; -------- Fast System Call init ---------- |
; Intel SYSENTER/SYSEXIT (AMD CPU support it too) |
bt [cpu_caps], CAPS_SEP |
jnc .SEnP ; SysEnter not Present |
xor edx, edx |
mov ecx, MSR_SYSENTER_CS |
mov eax, os_code |
wrmsr |
mov ecx, MSR_SYSENTER_ESP |
; mov eax, sysenter_stack ; Check it |
xor eax, eax |
wrmsr |
mov ecx, MSR_SYSENTER_EIP |
mov eax, sysenter_entry |
wrmsr |
.SEnP: |
; AMD SYSCALL/SYSRET |
cmp byte[cpu_vendor], 'A' |
jne .noSYSCALL |
mov eax, 0x80000001 |
cpuid |
test edx, 0x800 ; bit_11 - SYSCALL/SYSRET support |
jz .noSYSCALL |
mov ecx, MSR_AMD_EFER |
rdmsr |
or eax, 1 ; bit_0 - System Call Extension (SCE) |
wrmsr |
; !!!! It`s dirty hack, fix it !!! |
; Bits of EDX : |
; Bit 3116 During the SYSRET instruction, this field is copied into the CS register |
; and the contents of this field, plus 8, are copied into the SS register. |
; Bit 150 During the SYSCALL instruction, this field is copied into the CS register |
; and the contents of this field, plus 8, are copied into the SS register. |
; mov edx, (os_code + 16) * 65536 + os_code |
mov edx, 0x1B0008 |
mov eax, syscall_entry |
mov ecx, MSR_AMD_STAR |
wrmsr |
.noSYSCALL: |
; ----------------------------------------- |
stdcall alloc_page |
stdcall map_page, tss-0xF80, eax, PG_SW |
stdcall alloc_page |
inc eax |
mov [SLOT_BASE+256+APPDATA.io_map], eax |
stdcall map_page, tss+0x80, eax, PG_SW |
stdcall alloc_page |
inc eax |
mov dword [SLOT_BASE+256+APPDATA.io_map+4], eax |
stdcall map_page, tss+0x1080, eax, PG_SW |
; LOAD IDT |
call build_interrupt_table ;lidt is executed |
;lidt [idtreg] |
call init_kernel_heap |
stdcall kernel_alloc, RING0_STACK_SIZE+512 |
mov [os_stack_seg], eax |
lea esp, [eax+RING0_STACK_SIZE] |
mov [tss._ss0], os_stack |
mov [tss._esp0], esp |
mov [tss._esp], esp |
mov [tss._cs], os_code |
mov [tss._ss], os_stack |
mov [tss._ds], app_data |
mov [tss._es], app_data |
mov [tss._fs], app_data |
mov [tss._gs], app_data |
mov [tss._io], 128 |
;Add IO access table - bit array of permitted ports |
mov edi, tss._io_map_0 |
xor eax, eax |
not eax |
mov ecx, 8192/4 |
rep stosd ; access to 4096*8=65536 ports |
mov ax, tss0 |
ltr ax |
mov [LFBSize], 0x800000 |
call init_LFB |
call init_fpu |
call init_malloc |
stdcall alloc_kernel_space, 0x51000 |
mov [default_io_map], eax |
add eax, 0x2000 |
mov [ipc_tmp], eax |
mov ebx, 0x1000 |
add eax, 0x40000 |
mov [proc_mem_map], eax |
add eax, 0x8000 |
mov [proc_mem_pdir], eax |
add eax, ebx |
mov [proc_mem_tab], eax |
add eax, ebx |
mov [tmp_task_pdir], eax |
add eax, ebx |
mov [tmp_task_ptab], eax |
add eax, ebx |
mov [ipc_pdir], eax |
add eax, ebx |
mov [ipc_ptab], eax |
stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl \ |
(unpack.lc+unpack.lp)))*4 |
mov [unpack.p], eax |
call init_events |
mov eax, srv.fd-SRV_FD_OFFSET |
mov [srv.fd], eax |
mov [srv.bk], eax |
;Set base of graphic segment to linear address of LFB |
mov eax, [LFBAddress] ; set for gs |
mov [graph_data_l+2], ax |
shr eax, 16 |
mov [graph_data_l+4], al |
mov [graph_data_l+7], ah |
stdcall kernel_alloc, [_WinMapSize] |
mov [_WinMapAddress], eax |
xor eax, eax |
inc eax |
mov [CURRENT_TASK], eax ;dword 1 |
mov [TASK_COUNT], eax ;dword 1 |
mov [TASK_BASE], dword TASK_DATA |
mov [current_slot], SLOT_BASE+256 |
; set background |
mov [BgrDrawMode], eax |
mov [BgrDataWidth], eax |
mov [BgrDataHeight], eax |
mov [mem_BACKGROUND], 4 |
mov [img_background], static_background_data |
mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE |
stdcall kernel_alloc, 0x10000/8 |
mov edi, eax |
mov [network_free_ports], eax |
or eax, -1 |
mov ecx, 0x10000/32 |
rep stosd |
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f |
call init_irqs |
call PIC_init |
; Initialize system V86 machine |
call init_sys_v86 |
; Initialize system timer (IRQ0) |
call PIT_init |
; Try to Initialize APIC |
call APIC_init |
; Enable timer IRQ (IRQ0) and hard drives IRQs (IRQ14, IRQ15) |
; they are used: when partitions are scanned, hd_read relies on timer |
call unmask_timer |
stdcall enable_irq, 2 ; @#$%! PIC |
stdcall enable_irq, 6 ; FDD |
stdcall enable_irq, 13 ; co-processor |
stdcall enable_irq, 14 |
stdcall enable_irq, 15 |
; Enable interrupts in IDE controller |
mov al, 0 |
mov dx, 0x3F6 |
out dx, al |
mov dl, 0x76 |
out dx, al |
;!!!!!!!!!!!!!!!!!!!!!!!!!! |
include 'detect/disks.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!!!! |
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 |
; CALCULATE FAT CHAIN FOR RAMDISK |
call calculatefatchain |
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} |
je no_lib_load |
; LOADING LIBRARES |
stdcall dll.Load, @IMPORT ; loading librares for kernel (.obj files) |
call load_file_parse_table ; prepare file parse table |
call set_kernel_conf ; configure devices and gui |
no_lib_load: |
end if |
; LOAD FONTS I and II |
stdcall read_file, char, FONT_I, 0, 2304 |
stdcall read_file, char2, FONT_II, 0, 2560 |
mov esi, boot_fonts |
call boot_log |
; Display APIC status |
mov esi, boot_APIC_found |
cmp [irq_mode], IRQ_APIC |
je @f |
mov esi, boot_APIC_nfound |
@@: |
; PRINT AMOUNT OF MEMORY |
mov esi, boot_memdetect |
call boot_log |
movzx ecx, word [boot_y] |
if lang eq ru |
or ecx, (10+30*6) shl 16 |
else |
or ecx, (10+29*6) shl 16 |
end if |
sub ecx, 10 |
mov edx, 0xFFFFFF |
mov ebx, [MEM_AMOUNT] |
shr ebx, 20 |
xor edi, edi |
mov eax, 0x00040000 |
inc edi |
call display_number_force |
; BUILD SCHEDULER |
call build_scheduler; sys32.inc |
mov esi, boot_devices |
call boot_log |
mov [pci_access_enabled], 1 |
; SET PRELIMINARY WINDOW STACK AND POSITIONS |
mov esi, boot_windefs |
call boot_log |
call set_window_defaults |
; SET BACKGROUND DEFAULTS |
mov esi, boot_bgr |
call boot_log |
call init_background |
call calculatebackground |
; RESERVE SYSTEM IRQ'S JA PORT'S |
mov esi, boot_resirqports |
call boot_log |
call reserve_irqs_ports |
; SET UP OS TASK |
mov esi, boot_setostask |
call boot_log |
xor eax, eax |
mov dword [SLOT_BASE+APPDATA.fpu_state], fpu_data |
mov dword [SLOT_BASE+APPDATA.exc_handler], eax |
mov dword [SLOT_BASE+APPDATA.except_mask], eax |
; name for OS/IDLE process |
mov dword [SLOT_BASE+256+APPDATA.app_name], dword 'OS/I' |
mov dword [SLOT_BASE+256+APPDATA.app_name+4], dword 'DLE ' |
mov edi, [os_stack_seg] |
mov dword [SLOT_BASE+256+APPDATA.pl0_stack], edi |
add edi, 0x2000-512 |
mov dword [SLOT_BASE+256+APPDATA.fpu_state], edi |
mov dword [SLOT_BASE+256+APPDATA.saved_esp0], edi; just for case |
; [SLOT_BASE+256+APPDATA.io_map] was set earlier |
mov esi, fpu_data |
mov ecx, 512/4 |
cld |
rep movsd |
mov dword [SLOT_BASE+256+APPDATA.exc_handler], eax |
mov dword [SLOT_BASE+256+APPDATA.except_mask], eax |
mov ebx, SLOT_BASE+256+APP_OBJ_OFFSET |
mov dword [SLOT_BASE+256+APPDATA.fd_obj], ebx |
mov dword [SLOT_BASE+256+APPDATA.bk_obj], ebx |
mov dword [SLOT_BASE+256+APPDATA.cur_dir], sysdir_path |
mov dword [SLOT_BASE+256+APPDATA.tls_base], eax |
; task list |
mov dword [TASK_DATA+TASKDATA.mem_start], eax; process base address |
inc eax |
mov dword [CURRENT_TASK], eax |
mov dword [TASK_COUNT], eax |
mov [current_slot], SLOT_BASE+256 |
mov [TASK_BASE], dword TASK_DATA |
mov byte[TASK_DATA+TASKDATA.wnd_number], al ; on screen number |
mov dword [TASK_DATA+TASKDATA.pid], eax ; process id number |
call init_display |
mov eax, [def_cursor] |
mov [SLOT_BASE+APPDATA.cursor], eax |
mov [SLOT_BASE+APPDATA.cursor+256], eax |
; READ TSC / SECOND |
mov esi, boot_tsc |
call boot_log |
cli |
rdtsc ;call _rdtsc |
mov ecx, eax |
mov esi, 250 ; wait 1/4 a second |
call delay_ms |
rdtsc ;call _rdtsc |
sti |
sub eax, ecx |
shl eax, 2 |
mov [CPU_FREQ], eax ; save tsc / sec |
; mov ebx, 1000000 |
; div ebx |
; ¢®®¡é¥-â® ¯à®¨§¢®¤¨â¥«ì®áâì ¢ ¤ ®¬ ª®ªà¥â®¬ ¬¥á⥠|
; ᮢ¥à襮 ¥ªà¨â¨ç , ® çâ®¡ë § âªãâì «î¡¨â¥«¥© |
; ®¯â¨¬¨§¨àãîé¨å ª®¬¯¨«ïâ®à®¢ ... |
mov edx, 2251799814 |
mul edx |
shr edx, 19 |
mov [stall_mcs], edx |
; PRINT CPU FREQUENCY |
mov esi, boot_cpufreq |
call boot_log |
mov ebx, edx |
movzx ecx, word [boot_y] |
if lang eq ru |
add ecx, (10+19*6) shl 16 - 10 ; 'Determining amount of memory' |
else |
add ecx, (10+17*6) shl 16 - 10 ; 'Determining amount of memory' |
end if |
mov edx, 0xFFFFFF |
xor edi, edi |
mov eax, 0x00040000 |
inc edi |
call display_number_force |
; SET VARIABLES |
call set_variables |
; STACK AND FDC |
call stack_init |
call fdc_init |
; PALETTE FOR 320x200 and 640x480 16 col |
cmp [SCR_MODE], word 0x12 |
jne no_pal_vga |
mov esi, boot_pal_vga |
call boot_log |
call paletteVGA |
no_pal_vga: |
cmp [SCR_MODE], word 0x13 |
jne no_pal_ega |
mov esi, boot_pal_ega |
call boot_log |
call palette320x200 |
no_pal_ega: |
; LOAD DEFAULT SKIN |
call load_default_skin |
;protect io permission map |
mov esi, [default_io_map] |
stdcall map_page, esi, [SLOT_BASE+256+APPDATA.io_map], PG_MAP |
add esi, 0x1000 |
stdcall map_page, esi, [SLOT_BASE+256+APPDATA.io_map+4], PG_MAP |
stdcall map_page, tss._io_map_0, \ |
[SLOT_BASE+256+APPDATA.io_map], PG_MAP |
stdcall map_page, tss._io_map_1, \ |
[SLOT_BASE+256+APPDATA.io_map+4], PG_MAP |
mov ax, [OS_BASE+0x10000+bx_from_load] |
cmp ax, 'r1'; if not rused ram disk - load network configuration from files {SPraid.simba} |
je no_st_network |
call set_network_conf |
no_st_network: |
; LOAD FIRST APPLICATION |
cli |
; cmp byte [BOOT_VAR+0x9030],1 |
; jne no_load_vrr_m |
; mov ebp, vrr_m |
; call fs_execute_from_sysdir |
; |
;; cmp eax,2 ; if vrr_m app found (PID=2) |
; sub eax,2 |
; jz first_app_found |
; |
;no_load_vrr_m: |
mov ebp, firstapp |
call fs_execute_from_sysdir |
; cmp eax,2 ; continue if a process has been loaded |
sub eax, 2 |
jz first_app_found |
mov esi, boot_failed |
call boot_log |
mov eax, 0xDEADBEEF ; otherwise halt |
hlt |
first_app_found: |
cli |
;mov [TASK_COUNT],dword 2 |
push 1 |
pop dword [CURRENT_TASK] ; set OS task fisrt |
; SET KEYBOARD PARAMETERS |
mov al, 0xf6 ; reset keyboard, scan enabled |
call kb_write |
; wait until 8042 is ready |
xor ecx, ecx |
@@: |
in al, 64h |
and al, 00000010b |
loopnz @b |
; mov al, 0xED ; Keyboard LEDs - only for testing! |
; call kb_write |
; call kb_read |
; mov al, 111b |
; call kb_write |
; call kb_read |
mov al, 0xF3 ; set repeat rate & delay |
call kb_write |
; call kb_read |
mov al, 0; 30 250 ;00100010b ; 24 500 ;00100100b ; 20 500 |
call kb_write |
; call kb_read |
;// mike.dld [ |
call set_lights |
;// mike.dld ] |
stdcall attach_int_handler, 1, irq1, 0 |
; SET MOUSE |
stdcall load_driver, szPS2MDriver |
; stdcall load_driver, szCOM_MDriver |
mov esi, boot_setmouse |
call boot_log |
call setmouse |
; Setup serial output console (if enabled) |
if defined debug_com_base |
; enable Divisor latch |
mov dx, debug_com_base+3 |
mov al, 1 shl 7 |
out dx, al |
; 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 |
; START MULTITASKING |
; A 'All set - press ESC to start' messages if need |
if preboot_blogesc |
mov esi, boot_tasking |
call boot_log |
.bll1: |
in al, 0x60 ; wait for ESC key press |
cmp al, 129 |
jne .bll1 |
end if |
cmp [IDEContrRegsBaseAddr], 0 |
setnz [dma_hdd] |
mov [timer_ticks_enable], 1 ; for cd driver |
sti |
call change_task |
jmp osloop |
; Fly :) |
include 'unpacker.inc' |
include 'fdo.inc' |
align 4 |
boot_log: |
pushad |
mov ebx, 10*65536 |
mov bx, word [boot_y] |
add [boot_y], dword 10 |
mov ecx, 0x80ffffff; ASCIIZ string with white color |
xor edi, edi |
mov edx, esi |
inc edi |
call dtext |
mov [novesachecksum], 1000 |
call checkVga_N13 |
popad |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; ; |
; MAIN OS LOOP START ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
osloop: |
call [draw_pointer] |
call window_check_events |
call mouse_check_events |
call checkmisc |
call checkVga_N13 |
call stack_handler |
call checkidle |
call check_fdd_motor_status |
call check_ATAPI_device_event |
call check_timers |
jmp osloop |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; ; |
; MAIN OS LOOP END ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
checkidle: |
pushad |
call change_task |
jmp idle_loop_entry |
idle_loop: |
cmp eax, [idlemem] ; eax == [timer_ticks] |
jne idle_exit |
rdtsc ;call _rdtsc |
mov ecx, eax |
hlt |
rdtsc ;call _rdtsc |
sub eax, ecx |
add [idleuse], eax |
idle_loop_entry: |
mov eax, [timer_ticks]; eax = [timer_ticks] |
cmp [check_idle_semaphore], 0 |
je idle_loop |
dec [check_idle_semaphore] |
idle_exit: |
mov [idlemem], eax ; eax == [timer_ticks] |
popad |
ret |
uglobal |
idlemem dd 0x0 |
idleuse dd 0x0 |
idleusesec dd 0x0 |
check_idle_semaphore dd 0x0 |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; ; |
; INCLUDED SYSTEM FILES ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include "kernel32.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; ; |
; KERNEL FUNCTIONS ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
reserve_irqs_ports: |
; RESERVE PORTS |
mov eax, RESERVED_PORTS |
mov ecx, 1 |
mov [eax], dword 4 |
mov [eax+16], ecx |
mov [eax+16+4], dword 0 |
mov [eax+16+4], dword 0x2D |
mov [eax+32], ecx |
mov [eax+32+4], dword 0x30 |
mov [eax+32+8], dword 0x4D |
mov [eax+48], ecx |
mov [eax+48+4], dword 0x50 |
mov [eax+28+8], dword 0xDF |
mov [eax+64], ecx |
mov [eax+64+4], dword 0xE5 |
mov [eax+64+8], dword 0xFF |
ret |
iglobal |
process_number dd 0x1 |
endg |
set_variables: |
mov ecx, 0x16 ; flush port 0x60 |
.fl60: |
in al, 0x60 |
loop .fl60 |
push eax |
mov ax, [BOOT_VAR+0x900c] |
shr ax, 1 |
shl eax, 16 |
mov ax, [BOOT_VAR+0x900A] |
shr ax, 1 |
mov [MOUSE_X], eax |
xor eax, eax |
mov [BTN_ADDR], dword BUTTON_INFO ; address of button list |
mov byte [MOUSE_BUFF_COUNT], al ; mouse buffer |
mov byte [KEY_COUNT], al ; keyboard buffer |
mov byte [BTN_COUNT], al ; button buffer |
; mov [MOUSE_X],dword 100*65536+100 ; mouse x/y |
;!! IP 04.02.2005: |
mov byte [DONT_SWITCH], al; change task if possible |
pop eax |
ret |
align 4 |
;input eax=43,bl-byte of output, ecx - number of port |
sys_outport: |
mov edi, ecx ; separate flag for read / write |
and ecx, 65535 |
mov eax, [RESERVED_PORTS] |
test eax, eax |
jnz .sopl8 |
inc eax |
mov [esp+32], eax |
ret |
.sopl8: |
mov edx, [TASK_BASE] |
mov edx, [edx+0x4] |
;and ecx,65535 |
;cld - set on interrupt 0x40 |
.sopl1: |
mov esi, eax |
shl esi, 4 |
add esi, RESERVED_PORTS |
cmp edx, [esi+0] |
jne .sopl2 |
cmp ecx, [esi+4] |
jb .sopl2 |
cmp ecx, [esi+8] |
jg .sopl2 |
.sopl3: |
test edi, 0x80000000; read ? |
jnz .sopl4 |
mov eax, ebx |
mov dx, cx ; write |
out dx, al |
and [esp+32], dword 0 |
ret |
.sopl2: |
dec eax |
jnz .sopl1 |
inc eax |
mov [esp+32], eax |
ret |
.sopl4: |
mov dx, cx ; read |
in al, dx |
and eax, 0xff |
and [esp+32], dword 0 |
mov [esp+20], eax |
ret |
display_number: |
;It is not optimization |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov edx, esi |
mov esi, edi |
; eax = print type, al=0 -> ebx is number |
; al=1 -> ebx is pointer |
; ah=0 -> display decimal |
; ah=1 -> display hexadecimal |
; ah=2 -> display binary |
; eax bits 16-21 = number of digits to display (0-32) |
; eax bits 22-31 = reserved |
; |
; ebx = number or pointer |
; ecx = x shl 16 + y |
; edx = color |
xor edi, edi |
display_number_force: |
push eax |
and eax, 0x3fffffff |
cmp eax, 0xffff ; length > 0 ? |
pop eax |
jge cont_displ |
ret |
cont_displ: |
push eax |
and eax, 0x3fffffff |
cmp eax, 61*0x10000 ; length <= 60 ? |
pop eax |
jb cont_displ2 |
ret |
cont_displ2: |
pushad |
cmp al, 1 ; ecx is a pointer ? |
jne displnl1 |
mov ebp, ebx |
add ebp, 4 |
mov ebp, [ebp+std_application_base_address] |
mov ebx, [ebx+std_application_base_address] |
displnl1: |
sub esp, 64 |
test ah, ah ; DECIMAL |
jnz no_display_desnum |
shr eax, 16 |
and eax, 0xC03f |
; and eax,0x3f |
push eax |
and eax, 0x3f |
mov edi, esp |
add edi, 4+64-1 |
mov ecx, eax |
mov eax, ebx |
mov ebx, 10 |
d_desnum: |
xor edx, edx |
call division_64_bits |
div ebx |
add dl, 48 |
mov [edi], dl |
dec edi |
loop d_desnum |
pop eax |
call normalize_number |
call draw_num_text |
add esp, 64 |
popad |
ret |
no_display_desnum: |
cmp ah, 0x01 ; HEXADECIMAL |
jne no_display_hexnum |
shr eax, 16 |
and eax, 0xC03f |
; and eax,0x3f |
push eax |
and eax, 0x3f |
mov edi, esp |
add edi, 4+64-1 |
mov ecx, eax |
mov eax, ebx |
mov ebx, 16 |
d_hexnum: |
xor edx, edx |
call division_64_bits |
div ebx |
hexletters = __fdo_hexdigits |
add edx, hexletters |
mov dl, [edx] |
mov [edi], dl |
dec edi |
loop d_hexnum |
pop eax |
call normalize_number |
call draw_num_text |
add esp, 64 |
popad |
ret |
no_display_hexnum: |
cmp ah, 0x02 ; BINARY |
jne no_display_binnum |
shr eax, 16 |
and eax, 0xC03f |
; and eax,0x3f |
push eax |
and eax, 0x3f |
mov edi, esp |
add edi, 4+64-1 |
mov ecx, eax |
mov eax, ebx |
mov ebx, 2 |
d_binnum: |
xor edx, edx |
call division_64_bits |
div ebx |
add dl, 48 |
mov [edi], dl |
dec edi |
loop d_binnum |
pop eax |
call normalize_number |
call draw_num_text |
add esp, 64 |
popad |
ret |
no_display_binnum: |
add esp, 64 |
popad |
ret |
normalize_number: |
test ah, 0x80 |
jz .continue |
mov ecx, 48 |
and eax, 0x3f |
@@: |
inc edi |
cmp [edi], cl |
jne .continue |
dec eax |
cmp eax, 1 |
ja @r |
mov al, 1 |
.continue: |
and eax, 0x3f |
ret |
division_64_bits: |
test [esp+1+4], byte 0x40 |
jz .continue |
push eax |
mov eax, ebp |
div ebx |
mov ebp, eax |
pop eax |
.continue: |
ret |
draw_num_text: |
mov esi, eax |
mov edx, 64+4 |
sub edx, eax |
add edx, esp |
mov ebx, [esp+64+32-8+4] |
; add window start x & y |
mov ecx, [TASK_BASE] |
mov edi, [CURRENT_TASK] |
shl edi, 8 |
mov eax, [ecx-twdw+WDATA.box.left] |
add eax, [edi+SLOT_BASE+APPDATA.wnd_clientbox.left] |
shl eax, 16 |
add eax, [ecx-twdw+WDATA.box.top] |
add eax, [edi+SLOT_BASE+APPDATA.wnd_clientbox.top] |
add ebx, eax |
mov ecx, [esp+64+32-12+4] |
and ecx, not 0x80000000 ; force counted string |
mov eax, [esp+64+8] ; background color (if given) |
mov edi, [esp+64+4] |
jmp dtext |
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 |
; 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 |
; 11 = enable lba read |
; 12 = enable pci access |
and [esp+32], dword 0 |
dec ebx ; MIDI |
jnz nsyse1 |
cmp ecx, 0x100 |
jb nsyse1 |
mov esi, 65535 |
cmp esi, ecx |
jb nsyse1 |
mov [midi_base], cx ;bx |
mov word [mididp], cx;bx |
inc cx ;bx |
mov word [midisp], cx;bx |
ret |
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 |
dec ecx |
jnz kbnobase |
mov ebx, keymap |
mov ecx, 128 |
call memmove |
ret |
kbnobase: |
dec ecx |
jnz kbnoshift |
mov ebx, keymap_shift |
mov ecx, 128 |
call memmove |
ret |
kbnoshift: |
dec ecx |
jnz kbnoalt |
mov ebx, keymap_alt |
mov ecx, 128 |
call memmove |
ret |
kbnoalt: |
sub ecx, 6 |
jnz kbnocountry |
mov word [keyboard], dx |
ret |
kbnocountry: |
mov [esp+32], dword 1 |
ret |
nsyse2: |
dec ebx ; CD |
jnz nsyse4 |
test ecx, ecx |
jz nosesl |
cmp ecx, 4 |
ja nosesl |
mov [cd_base], cl |
dec ecx |
jnz noprma |
mov [cdbase], 0x1f0 |
mov [cdid], 0xa0 |
noprma: |
dec ecx |
jnz noprsl |
mov [cdbase], 0x1f0 |
mov [cdid], 0xb0 |
noprsl: |
dec ecx |
jnz nosema |
mov [cdbase], 0x170 |
mov [cdid], 0xa0 |
nosema: |
dec ecx |
jnz nosesl |
mov [cdbase], 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: |
sub ebx, 2 ; HD BASE |
jnz nsyse7 |
test ecx, ecx |
jz nosethd |
cmp ecx, 4 |
ja nosethd |
mov [hd_base], cl |
cmp ecx, 1 |
jnz noprmahd |
mov [hdbase], 0x1f0 |
and dword [hdid], 0x0 |
mov dword [hdpos], ecx |
; call set_FAT32_variables |
noprmahd: |
cmp ecx, 2 |
jnz noprslhd |
mov [hdbase], 0x1f0 |
mov [hdid], 0x10 |
mov dword [hdpos], ecx |
; call set_FAT32_variables |
noprslhd: |
cmp ecx, 3 |
jnz nosemahd |
mov [hdbase], 0x170 |
and dword [hdid], 0x0 |
mov dword [hdpos], ecx |
; call set_FAT32_variables |
nosemahd: |
cmp ecx, 4 |
jnz noseslhd |
mov [hdbase], 0x170 |
mov [hdid], 0x10 |
mov dword [hdpos], ecx |
; call set_FAT32_variables |
noseslhd: |
call reserve_hd1 |
call reserve_hd_channel |
call free_hd_channel |
and dword [hd1_status], 0 ; free |
nosethd: |
ret |
iglobal |
hd_base db 0 |
endg |
nsyse7: |
; cmp eax,8 ; HD PARTITION |
dec ebx |
jnz nsyse8 |
mov [fat32part], ecx |
; call set_FAT32_variables |
call reserve_hd1 |
call reserve_hd_channel |
call free_hd_channel |
; pusha |
call choice_necessity_partition_1 |
; popa |
and dword [hd1_status], 0 ; free |
ret |
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: |
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 |
; 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=get hs timer tic |
; cmp eax,1 |
dec ebx |
jnz ngsyse1 |
movzx eax, [midi_base] |
mov [esp+32], eax |
ret |
ngsyse1: |
; cmp eax,2 |
dec ebx |
jnz ngsyse2 |
mov edi, [TASK_BASE] |
mov ebx, [edi+TASKDATA.mem_start] |
add ebx, edx |
; cmp ebx,1 |
dec ecx |
jnz kbnobaseret |
mov eax, keymap |
mov ecx, 128 |
call memmove |
ret |
kbnobaseret: |
; cmp ebx,2 |
dec ecx |
jnz kbnoshiftret |
mov eax, keymap_shift |
mov ecx, 128 |
call memmove |
ret |
kbnoshiftret: |
; cmp ebx,3 |
dec ecx |
jne kbnoaltret |
mov eax, keymap_alt |
mov ecx, 128 |
call memmove |
ret |
kbnoaltret: |
; cmp ebx,9 |
sub ecx, 6 |
jnz ngsyse2 |
movzx eax, word [keyboard] |
mov [esp+32], eax |
ret |
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 |
movzx eax, [hd_base] |
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 |
sub ebx, 2 |
jnz ngsyse11 |
mov eax, [lba_read_enabled] |
mov [esp+32], eax |
ret |
ngsyse11: |
; cmp eax,12 |
dec ebx |
jnz ngsyse12 |
mov eax, [pci_access_enabled] |
mov [esp+32], eax |
ret |
ngsyse12: |
mov [esp+32], dword 1 |
ret |
get_timer_ticks: |
mov eax, [timer_ticks] |
ret |
iglobal |
align 4 |
mousefn dd msscreen, mswin, msbutton, msset |
dd app_load_cursor |
dd app_set_cursor |
dd app_delete_cursor |
dd msz |
endg |
readmousepos: |
; eax=0 screen relative |
; eax=1 window relative |
; eax=2 buttons pressed |
; eax=3 set mouse pos ; reserved |
; eax=4 load cursor |
; eax=5 set cursor |
; eax=6 delete cursor ; reserved |
; eax=7 get mouse_z |
cmp ebx, 7 |
ja msset |
jmp [mousefn+ebx*4] |
msscreen: |
mov eax, [MOUSE_X] |
shl eax, 16 |
mov ax, [MOUSE_Y] |
mov [esp+36-4], eax |
ret |
mswin: |
mov eax, [MOUSE_X] |
shl eax, 16 |
mov ax, [MOUSE_Y] |
mov esi, [TASK_BASE] |
mov bx, word [esi-twdw+WDATA.box.left] |
shl ebx, 16 |
mov bx, word [esi-twdw+WDATA.box.top] |
sub eax, ebx |
mov edi, [CURRENT_TASK] |
shl edi, 8 |
sub ax, word[edi+SLOT_BASE+APPDATA.wnd_clientbox.top] |
rol eax, 16 |
sub ax, word[edi+SLOT_BASE+APPDATA.wnd_clientbox.left] |
rol eax, 16 |
mov [esp+36-4], eax |
ret |
msbutton: |
movzx eax, byte [BTN_DOWN] |
mov [esp+36-4], eax |
ret |
msz: |
mov edi, [TASK_COUNT] |
movzx edi, word [WIN_POS + edi*2] |
cmp edi, [CURRENT_TASK] |
jne @f |
mov ax, [MOUSE_SCROLL_H] |
shl eax, 16 |
mov ax, [MOUSE_SCROLL_V] |
mov [esp+36-4], eax |
and [MOUSE_SCROLL_H], word 0 |
and [MOUSE_SCROLL_V], word 0 |
ret |
@@: |
and [esp+36-4], dword 0 |
; ret |
msset: |
ret |
app_load_cursor: |
cmp ecx, OS_BASE |
jae msset |
stdcall load_cursor, ecx, edx |
mov [esp+36-4], eax |
ret |
app_set_cursor: |
stdcall set_cursor, ecx |
mov [esp+36-4], eax |
ret |
app_delete_cursor: |
stdcall delete_cursor, ecx |
mov [esp+36-4], eax |
ret |
is_input: |
push edx |
mov dx, word [midisp] |
in al, dx |
and al, 0x80 |
pop edx |
ret |
is_output: |
push edx |
mov dx, word [midisp] |
in al, dx |
and al, 0x40 |
pop edx |
ret |
get_mpu_in: |
push edx |
mov dx, word [mididp] |
in al, dx |
pop edx |
ret |
put_mpu_out: |
push edx |
mov dx, word [mididp] |
out dx, al |
pop edx |
ret |
align 4 |
sys_midi: |
cmp [mididp], 0 |
jnz sm0 |
mov [esp+36], dword 1 |
ret |
sm0: |
and [esp+36], dword 0 |
dec ebx |
jnz smn1 |
; call setuart |
su1: |
call is_output |
test al, al |
jnz su1 |
mov dx, word [midisp] |
mov al, 0xff |
out dx, al |
su2: |
mov dx, word [midisp] |
mov al, 0xff |
out dx, al |
call is_input |
test al, al |
jnz su2 |
call get_mpu_in |
cmp al, 0xfe |
jnz su2 |
su3: |
call is_output |
test al, al |
jnz su3 |
mov dx, word [midisp] |
mov al, 0x3f |
out dx, al |
ret |
smn1: |
dec ebx |
jnz smn2 |
sm10: |
call get_mpu_in |
call is_output |
test al, al |
jnz sm10 |
mov al, bl |
call put_mpu_out |
smn2: |
ret |
detect_devices: |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
;include 'detect/commouse.inc' |
;include 'detect/ps2mouse.inc' |
;include 'detect/dev_fd.inc' |
;include 'detect/dev_hdcd.inc' |
;include 'detect/sear_par.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
ret |
sys_end: |
mov ecx, [current_slot] |
mov eax, [ecx+APPDATA.tls_base] |
test eax, eax |
jz @F |
stdcall user_free, eax |
@@: |
mov eax, [TASK_BASE] |
mov [eax+TASKDATA.state], 3; terminate this program |
waitterm: ; wait here for termination |
mov ebx, 100 |
call delay_hs |
jmp waitterm |
iglobal |
align 4 |
sys_system_table: |
dd sysfn_deactivate ; 1 = deactivate window |
dd sysfn_terminate ; 2 = terminate thread |
dd sysfn_activate ; 3 = activate window |
dd sysfn_getidletime ; 4 = get idle time |
dd sysfn_getcpuclock ; 5 = get cpu clock |
dd sysfn_saveramdisk ; 6 = save ramdisk |
dd sysfn_getactive ; 7 = get active window |
dd sysfn_sound_flag ; 8 = get/set sound_flag |
dd sysfn_shutdown ; 9 = shutdown with parameter |
dd sysfn_minimize ; 10 = minimize window |
dd sysfn_getdiskinfo ; 11 = get disk subsystem info |
dd sysfn_lastkey ; 12 = get last pressed key |
dd sysfn_getversion ; 13 = get kernel version |
dd sysfn_waitretrace ; 14 = wait retrace |
dd sysfn_centermouse ; 15 = center mouse cursor |
dd sysfn_getfreemem ; 16 = get free memory size |
dd sysfn_getallmem ; 17 = get total memory size |
dd sysfn_terminate2 ; 18 = terminate thread using PID |
; instead of slot |
dd sysfn_mouse_acceleration; 19 = set/get mouse acceleration |
dd sysfn_meminfo ; 20 = get extended memory info |
dd sysfn_pid_to_slot ; 21 = get slot number for pid |
dd sysfn_min_rest_window ; 22 = minimize and restore any window |
sysfn_num = ($ - sys_system_table)/4 |
endg |
;------------------------------------------------------------------------------ |
sys_system: |
dec ebx |
cmp ebx, sysfn_num |
jae @f |
jmp dword [sys_system_table + ebx*4] |
@@: |
ret |
;------------------------------------------------------------------------------ |
sysfn_shutdown: ; 18.9 = system shutdown |
cmp ecx, 1 |
jl exit_for_anyone |
cmp ecx, 4 |
jg exit_for_anyone |
mov [BOOT_VAR+0x9030], cl |
mov eax, [TASK_COUNT] |
mov [SYS_SHUTDOWN], al |
mov [shutdown_processes], eax |
and dword [esp+32], 0 |
exit_for_anyone: |
ret |
uglobal |
shutdown_processes: |
dd 0x0 |
endg |
;------------------------------------------------------------------------------ |
sysfn_terminate: ; 18.2 = TERMINATE |
cmp ecx, 2 |
jb noprocessterminate |
mov edx, [TASK_COUNT] |
cmp ecx, edx |
ja noprocessterminate |
mov eax, [TASK_COUNT] |
shl ecx, 5 |
mov edx, [ecx+CURRENT_TASK+TASKDATA.pid] |
add ecx, CURRENT_TASK+TASKDATA.state |
cmp byte [ecx], 9 |
jz noprocessterminate |
;call MEM_Heap_Lock ;guarantee that process isn't working with heap |
mov [ecx], byte 3; clear possible i40's |
;call MEM_Heap_UnLock |
cmp edx, [application_table_status]; clear app table stat |
jne noatsc |
and [application_table_status], 0 |
noatsc: |
noprocessterminate: |
ret |
;------------------------------------------------------------------------------ |
sysfn_terminate2: |
;lock application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status], 0 |
je .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
mov eax, ecx |
call pid_to_slot |
test eax, eax |
jz .not_found |
mov ecx, eax |
cli |
call sysfn_terminate |
and [application_table_status], 0 |
sti |
and dword [esp+32], 0 |
ret |
.not_found: |
mov [application_table_status], 0 |
or dword [esp+32], -1 |
ret |
;------------------------------------------------------------------------------ |
sysfn_deactivate: ; 18.1 = DEACTIVATE WINDOW |
cmp ecx, 2 |
jb .nowindowdeactivate |
cmp ecx, [TASK_COUNT] |
ja .nowindowdeactivate |
movzx esi, word [WIN_STACK + ecx*2] |
cmp esi, 1 |
je .nowindowdeactivate ; already deactive |
mov edi, ecx |
shl edi, 5 |
add edi, window_data |
movzx esi, word [WIN_STACK + ecx * 2] |
lea esi, [WIN_POS + esi * 2] |
call window._.window_deactivate |
xor eax, eax |
mov byte[MOUSE_BACKGROUND], al |
mov byte[DONT_DRAW_MOUSE], al |
mov byte[MOUSE_DOWN], 0 |
call syscall_display_settings._.calculate_whole_screen |
call syscall_display_settings._.redraw_whole_screen |
.nowindowdeactivate: |
ret |
;------------------------------------------------------------------------------ |
sysfn_activate: ; 18.3 = ACTIVATE WINDOW |
cmp ecx, 2 |
jb .nowindowactivate |
cmp ecx, [TASK_COUNT] |
ja .nowindowactivate |
mov [window_minimize], 2; restore window if minimized |
movzx esi, word [WIN_STACK + ecx*2] |
cmp esi, [TASK_COUNT] |
je .nowindowactivate; already active |
mov edi, ecx |
shl edi, 5 |
add edi, window_data |
movzx esi, word [WIN_STACK + ecx * 2] |
lea esi, [WIN_POS + esi * 2] |
call waredraw |
.nowindowactivate: |
ret |
;------------------------------------------------------------------------------ |
sysfn_getidletime: ; 18.4 = GET IDLETIME |
mov eax, [idleusesec] |
mov [esp+32], eax |
ret |
;------------------------------------------------------------------------------ |
sysfn_getcpuclock: ; 18.5 = GET TSC/SEC |
mov eax, [CPU_FREQ] |
mov [esp+32], eax |
ret |
;------------------------------------------------------------------------------ |
; SAVE ramdisk to /hd/1/menuet.img |
;!!!!!!!!!!!!!!!!!!!!!!!! |
include 'blkdev/rdsave.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!! |
;------------------------------------------------------------------------------ |
align 4 |
sysfn_getactive: ; 18.7 = get active window |
mov eax, [TASK_COUNT] |
movzx eax, word [WIN_POS + eax*2] |
mov [esp+32], eax |
ret |
;------------------------------------------------------------------------------ |
sysfn_sound_flag: ; 18.8 = get/set sound_flag |
; cmp ecx,1 |
dec ecx |
jnz nogetsoundflag |
movzx eax, byte [sound_flag]; get sound_flag |
mov [esp+32], eax |
ret |
nogetsoundflag: |
; cmp ecx,2 |
dec ecx |
jnz nosoundflag |
xor byte [sound_flag], 1 |
nosoundflag: |
ret |
;------------------------------------------------------------------------------ |
sysfn_minimize: ; 18.10 = minimize window |
mov [window_minimize], 1 |
ret |
;------------------------------------------------------------------------------ |
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: |
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, 16384 |
cld |
rep movsd |
ret |
;------------------------------------------------------------------------------ |
sysfn_lastkey: ; 18.12 = return 0 (backward compatibility) |
and dword [esp+32], 0 |
ret |
;------------------------------------------------------------------------------ |
sysfn_getversion: ; 18.13 = get kernel ID and version |
mov edi, ecx |
mov esi, version_inf |
mov ecx, version_end-version_inf |
rep movsb |
ret |
;------------------------------------------------------------------------------ |
sysfn_waitretrace: ; 18.14 = sys wait retrace |
;wait retrace functions |
sys_wait_retrace: |
mov edx, 0x3da |
WaitRetrace_loop: |
in al, dx |
test al, 1000b |
jz WaitRetrace_loop |
and [esp+32], dword 0 |
ret |
;------------------------------------------------------------------------------ |
align 4 |
sysfn_centermouse: ; 18.15 = mouse centered |
; removed here by <Lrz> |
; call mouse_centered |
;* mouse centered - start code- Mario79 |
;mouse_centered: |
; push eax |
mov eax, [Screen_Max_X] |
shr eax, 1 |
mov [MOUSE_X], ax |
mov eax, [Screen_Max_Y] |
shr eax, 1 |
mov [MOUSE_Y], ax |
; ret |
;* mouse centered - end code- Mario79 |
xor eax, eax |
and [esp+32], eax |
; pop eax |
ret |
;------------------------------------------------------------------------------ |
align 4 |
sysfn_mouse_acceleration: ; 18.19 = set/get mouse features |
test ecx, ecx; get mouse speed factor |
jnz .set_mouse_acceleration |
xor eax, eax |
mov ax, [mouse_speed_factor] |
mov [esp+32], eax |
ret |
.set_mouse_acceleration: |
; cmp ecx,1 ; set mouse speed factor |
dec ecx |
jnz .get_mouse_delay |
mov [mouse_speed_factor], dx |
ret |
.get_mouse_delay: |
; cmp ecx,2 ; get mouse delay |
dec ecx |
jnz .set_mouse_delay |
mov eax, [mouse_delay] |
mov [esp+32], eax |
ret |
.set_mouse_delay: |
; cmp ecx,3 ; set mouse delay |
dec ecx |
jnz .set_pointer_position |
mov [mouse_delay], edx |
ret |
.set_pointer_position: |
; cmp ecx,4 ; set mouse pointer position |
dec ecx |
jnz .set_mouse_button |
cmp dx, word[Screen_Max_Y] |
ja .end |
rol edx, 16 |
cmp dx, word[Screen_Max_X] |
ja .end |
mov [MOUSE_X], edx |
ret |
.set_mouse_button: |
; cmp ecx,5 ; set mouse button features |
dec ecx |
jnz .end |
mov [BTN_DOWN], dl |
mov [mouse_active], 1 |
.end: |
ret |
;------------------------------------------------------------------------------ |
sysfn_getfreemem: |
mov eax, [pg_data.pages_free] |
shl eax, 2 |
mov [esp+32], eax |
ret |
sysfn_getallmem: |
mov eax, [MEM_AMOUNT] |
shr eax, 10 |
mov [esp+32], eax |
ret |
; // Alver, 2007-22-08 // { |
sysfn_pid_to_slot: |
mov eax, ecx |
call pid_to_slot |
mov [esp+32], eax |
ret |
sysfn_min_rest_window: |
pushad |
mov eax, edx ; ebx - operating |
shr ecx, 1 |
jnc @f |
call pid_to_slot |
@@: |
or eax, eax ; eax - number of slot |
jz .error |
cmp eax, 255 ; varify maximal slot number |
ja .error |
movzx eax, word [WIN_STACK + eax*2] |
shr ecx, 1 |
jc .restore |
; .minimize: |
call minimize_window |
jmp .exit |
.restore: |
call restore_minimized_window |
.exit: |
popad |
xor eax, eax |
mov [esp+32], eax |
ret |
.error: |
popad |
xor eax, eax |
dec eax |
mov [esp+32], eax |
ret |
; } \\ Alver, 2007-22-08 \\ |
uglobal |
;// mike.dld, 2006-29-01 [ |
screen_workarea RECT |
;// mike.dld, 2006-29-01 ] |
window_minimize db 0 |
sound_flag db 0 |
endg |
UID_NONE=0 |
UID_MENUETOS=1 ;official |
UID_KOLIBRI=2 ;russian |
iglobal |
version_inf: |
db 0,7,7,0 ; version 0.7.7.0 |
db 0 |
dd __REV__ |
version_end: |
endg |
sys_cachetodiskette: |
cmp ebx, 1 |
jne .no_floppy_a_save |
mov [flp_number], 1 |
jmp .save_image_on_floppy |
.no_floppy_a_save: |
cmp ebx, 2 |
jne .no_floppy_b_save |
mov [flp_number], 2 |
.save_image_on_floppy: |
call save_image |
mov [esp + 32], dword 0 |
cmp [FDC_Status], 0 |
je .yes_floppy_save |
.no_floppy_b_save: |
mov [esp + 32], dword 1 |
.yes_floppy_save: |
ret |
uglobal |
; bgrchanged dd 0x0 |
align 4 |
bgrlockpid dd 0 |
bgrlock db 0 |
endg |
sys_background: |
cmp ebx, 1 ; BACKGROUND SIZE |
jnz nosb1 |
test ecx, ecx |
; cmp ecx,0 |
jz sbgrr |
test edx, edx |
; cmp edx,0 |
jz sbgrr |
@@: |
;;Maxis use atomic bts for mutexes 4.4.2009 |
bts dword [bgrlock], 0 |
jnc @f |
call change_task |
jmp @b |
@@: |
mov [BgrDataWidth], ecx |
mov [BgrDataHeight], edx |
; mov [bgrchanged],1 |
pushad |
; return memory for old background |
mov eax, [img_background] |
cmp eax, static_background_data |
jz @f |
stdcall kernel_free, eax |
@@: |
; calculate RAW size |
xor eax, eax |
inc eax |
cmp [BgrDataWidth], eax |
jae @f |
mov [BgrDataWidth], eax |
@@: |
cmp [BgrDataHeight], eax |
jae @f |
mov [BgrDataHeight], eax |
@@: |
mov eax, [BgrDataWidth] |
imul eax, [BgrDataHeight] |
lea eax, [eax*3] |
mov [mem_BACKGROUND], eax |
; get memory for new background |
stdcall kernel_alloc, eax |
test eax, eax |
jz .memfailed |
mov [img_background], eax |
jmp .exit |
.memfailed: |
; revert to static monotone data |
mov [img_background], static_background_data |
xor eax, eax |
inc eax |
mov [BgrDataWidth], eax |
mov [BgrDataHeight], eax |
mov [mem_BACKGROUND], 4 |
.exit: |
popad |
mov [bgrlock], 0 |
sbgrr: |
ret |
nosb1: |
cmp ebx, 2 ; SET PIXEL |
jnz nosb2 |
mov eax, [img_background] |
test ecx, ecx |
jz @f |
cmp eax, static_background_data |
jz .ret |
@@: |
mov ebx, [mem_BACKGROUND] |
add ebx, 4095 |
and ebx, -4096 |
sub ebx, 4 |
cmp ecx, ebx |
ja .ret |
mov ebx, [eax+ecx] |
and ebx, 0xFF000000;255*256*256*256 |
and edx, 0x00FFFFFF;255*256*256+255*256+255 |
add edx, ebx |
mov [eax+ecx], edx |
.ret: |
ret |
nosb2: |
cmp ebx, 3 ; DRAW BACKGROUND |
jnz nosb3 |
draw_background_temp: |
; cmp [bgrchanged],1 ;0 |
; je nosb31 |
;draw_background_temp: |
; mov [bgrchanged],1 ;0 |
mov [background_defined], 1 |
mov byte[BACKGROUND_CHANGED], 1 |
call force_redraw_background |
nosb31: |
ret |
nosb3: |
cmp ebx, 4 ; TILED / STRETCHED |
jnz nosb4 |
cmp ecx, [BgrDrawMode] |
je nosb41 |
mov [BgrDrawMode], ecx |
; mov [bgrchanged],1 |
nosb41: |
ret |
nosb4: |
cmp ebx, 5 ; BLOCK MOVE TO BGR |
jnz nosb5 |
cmp [img_background], static_background_data |
jnz @f |
test edx, edx |
jnz .fin |
cmp esi, 4 |
ja .fin |
@@: |
; bughere |
mov eax, ecx |
mov ebx, edx |
add ebx, [img_background];IMG_BACKGROUND |
mov ecx, esi |
call memmove |
.fin: |
ret |
nosb5: |
cmp ebx, 6 |
jnz nosb6 |
;;Maxis use atomic bts for mutex 4.4.2009 |
@@: |
bts dword [bgrlock], 0 |
jnc @f |
call change_task |
jmp @b |
@@: |
mov eax, [CURRENT_TASK] |
mov [bgrlockpid], eax |
cmp [img_background], static_background_data |
jz .nomem |
stdcall user_alloc, [mem_BACKGROUND] |
mov [esp+32], eax |
test eax, eax |
jz .nomem |
mov ebx, eax |
shr ebx, 12 |
or dword [page_tabs+(ebx-1)*4], DONT_FREE_BLOCK |
mov esi, [img_background] |
shr esi, 12 |
mov ecx, [mem_BACKGROUND] |
add ecx, 0xFFF |
shr ecx, 12 |
.z: |
mov eax, [page_tabs+ebx*4] |
test al, 1 |
jz @f |
call free_page |
@@: |
mov eax, [page_tabs+esi*4] |
or al, PG_UW |
mov [page_tabs+ebx*4], eax |
mov eax, ebx |
shl eax, 12 |
invlpg [eax] |
inc ebx |
inc esi |
loop .z |
ret |
.nomem: |
and [bgrlockpid], 0 |
mov [bgrlock], 0 |
nosb6: |
cmp ebx, 7 |
jnz nosb7 |
cmp [bgrlock], 0 |
jz .err |
mov eax, [CURRENT_TASK] |
cmp [bgrlockpid], eax |
jnz .err |
mov eax, ecx |
mov ebx, ecx |
shr eax, 12 |
mov ecx, [page_tabs+(eax-1)*4] |
test cl, USED_BLOCK+DONT_FREE_BLOCK |
jz .err |
jnp .err |
push eax |
shr ecx, 12 |
dec ecx |
@@: |
and dword [page_tabs+eax*4], 0 |
mov edx, eax |
shl edx, 12 |
push eax |
invlpg [edx] |
pop eax |
inc eax |
loop @b |
pop eax |
and dword [page_tabs+(eax-1)*4], not DONT_FREE_BLOCK |
stdcall user_free, ebx |
mov [esp+32], eax |
and [bgrlockpid], 0 |
mov [bgrlock], 0 |
ret |
.err: |
and dword [esp+32], 0 |
ret |
nosb7: |
ret |
force_redraw_background: |
and [draw_data+32 + RECT.left], 0 |
and [draw_data+32 + RECT.top], 0 |
push eax ebx |
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 |
inc byte[REDRAW_BACKGROUND] |
ret |
align 4 |
sys_getbackground: |
; cmp eax,1 ; SIZE |
dec ebx |
jnz nogb1 |
mov eax, [BgrDataWidth] |
shl eax, 16 |
mov ax, [BgrDataHeight] |
mov [esp+32], eax |
ret |
nogb1: |
; cmp eax,2 ; PIXEL |
dec ebx |
jnz nogb2 |
mov eax, [img_background] |
test ecx, ecx |
jz @f |
cmp eax, static_background_data |
jz .ret |
@@: |
mov ebx, [mem_BACKGROUND] |
add ebx, 4095 |
and ebx, -4096 |
sub ebx, 4 |
cmp ecx, ebx |
ja .ret |
mov eax, [ecx+eax] |
and eax, 0xFFFFFF |
mov [esp+32], eax |
.ret: |
ret |
nogb2: |
; cmp eax,4 ; TILED / STRETCHED |
dec ebx |
dec ebx |
jnz nogb4 |
mov eax, [BgrDrawMode] |
nogb4: |
mov [esp+32], eax |
ret |
align 4 |
sys_getkey: |
mov [esp + 32], dword 1 |
; test main buffer |
mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK |
movzx ecx, word [WIN_STACK + ebx * 2] |
mov edx, [TASK_COUNT] |
cmp ecx, edx |
jne .finish |
cmp [KEY_COUNT], byte 0 |
je .finish |
movzx eax, byte [KEY_BUFF] |
shl eax, 8 |
push eax |
dec byte [KEY_COUNT] |
and byte [KEY_COUNT], 127 |
movzx ecx, byte [KEY_COUNT] |
add ecx, 2 |
mov eax, KEY_BUFF + 1 |
mov ebx, KEY_BUFF |
call memmove |
pop eax |
.ret_eax: |
mov [esp + 32], eax |
ret |
.finish: |
; test hotkeys buffer |
mov ecx, hotkey_buffer |
@@: |
cmp [ecx], ebx |
jz .found |
add ecx, 8 |
cmp ecx, hotkey_buffer + 120 * 8 |
jb @b |
ret |
.found: |
mov ax, [ecx + 6] |
shl eax, 16 |
mov ah, [ecx + 4] |
mov al, 2 |
and dword [ecx + 4], 0 |
and dword [ecx], 0 |
jmp .ret_eax |
align 4 |
sys_getbutton: |
mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK |
mov [esp + 32], dword 1 |
movzx ecx, word [WIN_STACK + ebx * 2] |
mov edx, [TASK_COUNT] ; less than 256 processes |
cmp ecx, edx |
jne .exit |
movzx eax, byte [BTN_COUNT] |
test eax, eax |
jz .exit |
mov eax, [BTN_BUFF] |
and al, 0xFE ; delete left button bit |
mov [BTN_COUNT], byte 0 |
mov [esp + 32], eax |
.exit: |
ret |
align 4 |
sys_cpuusage: |
; RETURN: |
; |
; +00 dword process cpu usage |
; +04 word position in windowing stack |
; +06 word windowing stack value at current position (cpu nro) |
; +10 12 bytes name |
; +22 dword start in mem |
; +26 dword used mem |
; +30 dword PID , process idenfification number |
; |
cmp ecx, -1 ; who am I ? |
jne .no_who_am_i |
mov ecx, [CURRENT_TASK] |
.no_who_am_i: |
cmp ecx, max_processes |
ja .nofillbuf |
; +4: word: position of the window of thread in the window stack |
mov ax, [WIN_STACK + ecx * 2] |
mov [ebx+4], ax |
; +6: word: number of the thread slot, which window has in the window stack |
; position ecx (has no relation to the specific thread) |
mov ax, [WIN_POS + ecx * 2] |
mov [ebx+6], ax |
shl ecx, 5 |
; +0: dword: memory usage |
mov eax, [ecx+CURRENT_TASK+TASKDATA.cpu_usage] |
mov [ebx], eax |
; +10: 11 bytes: name of the process |
push ecx |
lea eax, [ecx*8+SLOT_BASE+APPDATA.app_name] |
add ebx, 10 |
mov ecx, 11 |
call memmove |
pop ecx |
; +22: address of the process in memory |
; +26: size of used memory - 1 |
push edi |
lea edi, [ebx+12] |
xor eax, eax |
mov edx, 0x100000*16 |
cmp ecx, 1 shl 5 |
je .os_mem |
mov edx, [SLOT_BASE+ecx*8+APPDATA.mem_size] |
mov eax, std_application_base_address |
.os_mem: |
stosd |
lea eax, [edx-1] |
stosd |
; +30: PID/TID |
mov eax, [ecx+CURRENT_TASK+TASKDATA.pid] |
stosd |
; window position and size |
push esi |
lea esi, [ecx + window_data + WDATA.box] |
movsd |
movsd |
movsd |
movsd |
; Process state (+50) |
mov eax, dword [ecx+CURRENT_TASK+TASKDATA.state] |
stosd |
; Window client area box |
lea esi, [ecx*8 + SLOT_BASE + APPDATA.wnd_clientbox] |
movsd |
movsd |
movsd |
movsd |
; Window state |
mov al, [ecx+window_data+WDATA.fl_wstate] |
stosb |
; Event mask (+71) |
mov EAX, dword [ECX+CURRENT_TASK+TASKDATA.event_mask] |
stosd |
pop esi |
pop edi |
.nofillbuf: |
; return number of processes |
mov eax, [TASK_COUNT] |
mov [esp+32], eax |
ret |
align 4 |
sys_clock: |
cli |
; Mikhail Lisovin xx Jan 2005 |
@@: |
mov al, 10 |
out 0x70, al |
in al, 0x71 |
test al, al |
jns @f |
mov esi, 1 |
call delay_ms |
jmp @b |
@@: |
; end Lisovin's fix |
xor al, al ; seconds |
out 0x70, al |
in al, 0x71 |
movzx ecx, al |
mov al, 02 ; minutes |
shl ecx, 16 |
out 0x70, al |
in al, 0x71 |
movzx edx, al |
mov al, 04 ; hours |
shl edx, 8 |
out 0x70, al |
in al, 0x71 |
add ecx, edx |
movzx edx, al |
add ecx, edx |
sti |
mov [esp + 32], ecx |
ret |
align 4 |
sys_date: |
cli |
@@: |
mov al, 10 |
out 0x70, al |
in al, 0x71 |
test al, al |
jns @f |
mov esi, 1 |
call delay_ms |
jmp @b |
@@: |
mov ch, 0 |
mov al, 7 ; date |
out 0x70, al |
in al, 0x71 |
mov cl, al |
mov al, 8 ; month |
shl ecx, 16 |
out 0x70, al |
in al, 0x71 |
mov ch, al |
mov al, 9 ; year |
out 0x70, al |
in al, 0x71 |
mov cl, al |
sti |
mov [esp+32], ecx |
ret |
; redraw status |
sys_redrawstat: |
cmp ebx, 1 |
jne no_widgets_away |
; buttons away |
mov ecx, [CURRENT_TASK] |
sys_newba2: |
mov edi, [BTN_ADDR] |
cmp [edi], dword 0 ; empty button list ? |
je end_of_buttons_away |
movzx ebx, word [edi] |
inc ebx |
mov eax, edi |
sys_newba: |
dec ebx |
jz end_of_buttons_away |
add eax, 0x10 |
cmp cx, [eax] |
jnz sys_newba |
push eax ebx ecx |
mov ecx, ebx |
inc ecx |
shl ecx, 4 |
mov ebx, eax |
add eax, 0x10 |
call memmove |
dec dword [edi] |
pop ecx ebx eax |
jmp sys_newba2 |
end_of_buttons_away: |
ret |
no_widgets_away: |
cmp ebx, 2 |
jnz srl1 |
mov edx, [TASK_BASE] ; return whole screen draw area for this app |
add edx, draw_data - CURRENT_TASK |
mov [edx + RECT.left], 0 |
mov [edx + RECT.top], 0 |
mov eax, [Screen_Max_X] |
mov [edx + RECT.right], eax |
mov eax, [Screen_Max_Y] |
mov [edx + RECT.bottom], eax |
srl1: |
ret |
;ok - 100% work |
;nt - not tested |
;--------------------------------------------------------------------------------------------- |
;eax |
;0 - task switch counter. Ret switch counter in eax. Block. ok. |
;1 - change task. Ret nothing. Block. ok. |
;2 - performance control |
; ebx |
; 0 - enable or disable (inversion) PCE flag on CR4 for rdmpc in user mode. |
; returned new cr4 in eax. Ret cr4 in eax. Block. ok. |
; 1 - is cache enabled. Ret cr0 in eax if enabled else zero in eax. Block. ok. |
; 2 - enable cache. Ret 1 in eax. Ret nothing. Block. ok. |
; 3 - disable cache. Ret 0 in eax. Ret nothing. Block. ok. |
;eax |
;3 - rdmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. |
;4 - wrmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. |
;--------------------------------------------------------------------------------------------- |
iglobal |
align 4 |
sheduler: |
dd sys_sheduler.00 |
dd change_task |
dd sys_sheduler.02 |
dd sys_sheduler.03 |
dd sys_sheduler.04 |
endg |
sys_sheduler: |
;rewritten by <Lrz> 29.12.2009 |
jmp dword [sheduler+ebx*4] |
;.shed_counter: |
.00: |
mov eax, [context_counter] |
mov [esp+32], eax |
ret |
.02: |
;.perf_control: |
inc ebx ;before ebx=2, ebx=3 |
cmp ebx, ecx ;if ecx=3, ebx=3 |
jz cache_disable |
dec ebx ;ebx=2 |
cmp ebx, ecx ; |
jz cache_enable ;if ecx=2 and ebx=2 |
dec ebx ;ebx=1 |
cmp ebx, ecx |
jz is_cache_enabled ;if ecx=1 and ebx=1 |
dec ebx |
test ebx, ecx ;ebx=0 and ecx=0 |
jz modify_pce ;if ecx=0 |
ret |
.03: |
;.rdmsr_instr: |
;now counter in ecx |
;(edx:eax) esi:edi => edx:esi |
mov eax, esi |
mov ecx, edx |
rdmsr |
mov [esp+32], eax |
mov [esp+20], edx ;ret in ebx? |
ret |
.04: |
;.wrmsr_instr: |
;now counter in ecx |
;(edx:eax) esi:edi => edx:esi |
; Fast Call MSR can't be destroy |
; ® MSR_AMD_EFER ¬®¦® ¨§¬¥ïâì, â.ª. ¢ í⮬ ॣ¨áâॠ«¨è |
; ¢ª«îç îâáï/¢ëª«îç îâáï à áè¨à¥ë¥ ¢®§¬®¦®á⨠|
cmp edx, MSR_SYSENTER_CS |
je @f |
cmp edx, MSR_SYSENTER_ESP |
je @f |
cmp edx, MSR_SYSENTER_EIP |
je @f |
cmp edx, MSR_AMD_STAR |
je @f |
mov eax, esi |
mov ecx, edx |
wrmsr |
; mov [esp + 32], eax |
; mov [esp + 20], edx ;ret in ebx? |
@@: |
ret |
cache_disable: |
mov eax, cr0 |
or eax, 01100000000000000000000000000000b |
mov cr0, eax |
wbinvd ;set MESI |
ret |
cache_enable: |
mov eax, cr0 |
and eax, 10011111111111111111111111111111b |
mov cr0, eax |
ret |
is_cache_enabled: |
mov eax, cr0 |
mov ebx, eax |
and eax, 01100000000000000000000000000000b |
jz cache_disabled |
mov [esp+32], ebx |
cache_disabled: |
mov dword [esp+32], eax;0 |
ret |
modify_pce: |
mov eax, cr4 |
; mov ebx,0 |
; or bx,100000000b ;pce |
; xor eax,ebx ;invert pce |
bts eax, 8;pce=cr4[8] |
mov cr4, eax |
mov [esp+32], eax |
ret |
;--------------------------------------------------------------------------------------------- |
; check if pixel is allowed to be drawn |
checkpixel: |
push eax edx |
mov edx, [Screen_Max_X] ; screen x size |
inc edx |
imul edx, ebx |
add eax, [_WinMapAddress] |
mov dl, [eax+edx]; lea eax, [...] |
xor ecx, ecx |
mov eax, [CURRENT_TASK] |
cmp al, dl |
setne cl |
pop edx eax |
ret |
iglobal |
cpustring db 'CPU',0 |
endg |
uglobal |
background_defined db 0 ; diamond, 11.04.2006 |
endg |
align 4 |
; check misc |
checkmisc: |
cmp [ctrl_alt_del], 1 |
jne nocpustart |
mov ebp, cpustring |
call fs_execute_from_sysdir |
mov [ctrl_alt_del], 0 |
nocpustart: |
cmp [mouse_active], 1 |
jne mouse_not_active |
mov [mouse_active], 0 |
xor edi, edi |
mov ecx, [TASK_COUNT] |
set_mouse_event: |
add edi, 256 |
or [edi+SLOT_BASE+APPDATA.event_mask], dword 100000b |
loop set_mouse_event |
mouse_not_active: |
cmp byte[BACKGROUND_CHANGED], 0 |
jz no_set_bgr_event |
xor edi, edi |
mov ecx, [TASK_COUNT] |
set_bgr_event: |
add edi, 256 |
or [edi+SLOT_BASE+APPDATA.event_mask], 16 |
loop set_bgr_event |
mov byte[BACKGROUND_CHANGED], 0 |
no_set_bgr_event: |
cmp byte[REDRAW_BACKGROUND], 0 ; background update ? |
jz nobackgr |
cmp [background_defined], 0 |
jz nobackgr |
; mov [draw_data+32 + RECT.left],dword 0 |
; mov [draw_data+32 + RECT.top],dword 0 |
; mov eax,[Screen_Max_X] |
; mov ebx,[Screen_Max_Y] |
; mov [draw_data+32 + RECT.right],eax |
; mov [draw_data+32 + RECT.bottom],ebx |
@@: |
call drawbackground |
xor eax, eax |
xchg al, [REDRAW_BACKGROUND] |
test al, al ; got new update request? |
jnz @b |
mov [draw_data+32 + RECT.left], eax |
mov [draw_data+32 + RECT.top], eax |
mov [draw_data+32 + RECT.right], eax |
mov [draw_data+32 + RECT.bottom], eax |
mov [MOUSE_BACKGROUND], byte 0 |
nobackgr: |
; system shutdown request |
cmp [SYS_SHUTDOWN], byte 0 |
je noshutdown |
mov edx, [shutdown_processes] |
cmp [SYS_SHUTDOWN], dl |
jne no_mark_system_shutdown |
lea ecx, [edx-1] |
mov edx, OS_BASE+0x3040 |
jecxz @f |
markz: |
mov [edx+TASKDATA.state], byte 3 |
add edx, 0x20 |
loop markz |
@@: |
no_mark_system_shutdown: |
call [_display.disable_mouse] |
dec byte [SYS_SHUTDOWN] |
je system_shutdown |
noshutdown: |
mov eax, [TASK_COUNT] ; termination |
mov ebx, TASK_DATA+TASKDATA.state |
mov esi, 1 |
newct: |
mov cl, [ebx] |
cmp cl, byte 3 |
jz terminate |
cmp cl, byte 4 |
jz terminate |
add ebx, 0x20 |
inc esi |
dec eax |
jnz newct |
ret |
; redraw screen |
redrawscreen: |
; eax , if process window_data base is eax, do not set flag/limits |
pushad |
push eax |
;;; mov ebx,2 |
;;; call delay_hs |
;mov ecx,0 ; redraw flags for apps |
xor ecx, ecx |
newdw2: |
inc ecx |
push ecx |
mov eax, ecx |
shl eax, 5 |
add eax, window_data |
cmp eax, [esp+4] |
je not_this_task |
; check if window in redraw area |
mov edi, eax |
cmp ecx, 1 ; limit for background |
jz bgli |
mov eax, [edi + WDATA.box.left] |
mov ebx, [edi + WDATA.box.top] |
mov ecx, [edi + WDATA.box.width] |
mov edx, [edi + WDATA.box.height] |
add ecx, eax |
add edx, ebx |
mov ecx, [draw_limits.bottom] ; ecx = area y end ebx = window y start |
cmp ecx, ebx |
jb ricino |
mov ecx, [draw_limits.right] ; ecx = area x end eax = window x start |
cmp ecx, eax |
jb ricino |
mov eax, [edi + WDATA.box.left] |
mov ebx, [edi + WDATA.box.top] |
mov ecx, [edi + WDATA.box.width] |
mov edx, [edi + WDATA.box.height] |
add ecx, eax |
add edx, ebx |
mov eax, [draw_limits.top] ; eax = area y start edx = window y end |
cmp edx, eax |
jb ricino |
mov eax, [draw_limits.left] ; eax = area x start ecx = window x end |
cmp ecx, eax |
jb ricino |
bgli: |
cmp dword[esp], 1 |
jnz .az |
; cmp byte[BACKGROUND_CHANGED], 0 |
; jnz newdw8 |
cmp byte[REDRAW_BACKGROUND], 0 |
jz .az |
mov dl, 0 |
lea eax, [edi+draw_data-window_data] |
mov ebx, [draw_limits.left] |
cmp ebx, [eax+RECT.left] |
jae @f |
mov [eax+RECT.left], ebx |
mov dl, 1 |
@@: |
mov ebx, [draw_limits.top] |
cmp ebx, [eax+RECT.top] |
jae @f |
mov [eax+RECT.top], ebx |
mov dl, 1 |
@@: |
mov ebx, [draw_limits.right] |
cmp ebx, [eax+RECT.right] |
jbe @f |
mov [eax+RECT.right], ebx |
mov dl, 1 |
@@: |
mov ebx, [draw_limits.bottom] |
cmp ebx, [eax+RECT.bottom] |
jbe @f |
mov [eax+RECT.bottom], ebx |
mov dl, 1 |
@@: |
add byte[REDRAW_BACKGROUND], dl |
jmp newdw8 |
.az: |
mov eax, edi |
add eax, draw_data-window_data |
mov ebx, [draw_limits.left] ; set limits |
mov [eax + RECT.left], ebx |
mov ebx, [draw_limits.top] |
mov [eax + RECT.top], ebx |
mov ebx, [draw_limits.right] |
mov [eax + RECT.right], ebx |
mov ebx, [draw_limits.bottom] |
mov [eax + RECT.bottom], ebx |
sub eax, draw_data-window_data |
cmp dword [esp], 1 |
jne nobgrd |
inc byte[REDRAW_BACKGROUND] |
newdw8: |
nobgrd: |
mov [eax + WDATA.fl_redraw], byte 1 ; mark as redraw |
ricino: |
not_this_task: |
pop ecx |
cmp ecx, [TASK_COUNT] |
jle newdw2 |
pop eax |
popad |
ret |
calculatebackground: ; background |
mov edi, [_WinMapAddress] ; set os to use all pixels |
mov eax, 0x01010101 |
mov ecx, [_WinMapSize] |
shr ecx, 2 |
rep stosd |
mov byte[REDRAW_BACKGROUND], 0 ; do not draw background! |
mov byte[BACKGROUND_CHANGED], 0 |
ret |
uglobal |
imax dd 0x0 |
endg |
delay_ms: ; delay in 1/1000 sec |
push eax |
push ecx |
mov ecx, esi |
; <CPU clock fix by Sergey Kuzmin aka Wildwest> |
imul ecx, 33941 |
shr ecx, 9 |
; </CPU clock fix> |
in al, 0x61 |
and al, 0x10 |
mov ah, al |
cld |
cnt1: |
in al, 0x61 |
and al, 0x10 |
cmp al, ah |
jz cnt1 |
mov ah, al |
loop cnt1 |
pop ecx |
pop eax |
ret |
set_app_param: |
mov edi, [TASK_BASE] |
mov eax, [edi + TASKDATA.event_mask] |
mov [edi + TASKDATA.event_mask], ebx |
mov [esp+32], eax |
ret |
delay_hs: ; delay in 1/100 secs |
; ebx = delay time |
push ecx |
push edx |
mov edx, [timer_ticks] |
newtic: |
mov ecx, [timer_ticks] |
sub ecx, edx |
cmp ecx, ebx |
jae zerodelay |
call change_task |
jmp newtic |
zerodelay: |
pop edx |
pop ecx |
ret |
align 16 ;very often call this subrutine |
memmove: ; memory move in bytes |
; eax = from |
; ebx = to |
; ecx = no of bytes |
test ecx, ecx |
jle .ret |
push esi edi ecx |
mov edi, ebx |
mov esi, eax |
test ecx, not 11b |
jz @f |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
and ecx, 11b |
jz .finish |
@@: |
rep movsb |
.finish: |
pop ecx edi esi |
.ret: |
ret |
; <diamond> Sysfunction 34, read_floppy_file, is obsolete. Use 58 or 70 function instead. |
;align 4 |
; |
;read_floppy_file: |
; |
;; as input |
;; |
;; eax pointer to file |
;; ebx file lenght |
;; ecx start 512 byte block number |
;; edx number of blocks to read |
;; esi pointer to return/work area (atleast 20 000 bytes) |
;; |
;; |
;; on return |
;; |
;; eax = 0 command succesful |
;; 1 no fd base and/or partition defined |
;; 2 yet unsupported FS |
;; 3 unknown FS |
;; 4 partition not defined at hd |
;; 5 file not found |
;; ebx = size of file |
; |
; mov edi,[TASK_BASE] |
; add edi,0x10 |
; add esi,[edi] |
; add eax,[edi] |
; |
; pushad |
; mov edi,esi |
; add edi,1024 |
; mov esi,0x100000+19*512 |
; sub ecx,1 |
; shl ecx,9 |
; add esi,ecx |
; shl edx,9 |
; mov ecx,edx |
; cld |
; rep movsb |
; popad |
; |
; mov [esp+36],eax |
; mov [esp+24],ebx |
; ret |
align 4 |
set_io_access_rights: |
push edi eax |
mov edi, tss._io_map_0 |
; mov ecx,eax |
; and ecx,7 ; offset in byte |
; shr eax,3 ; number of byte |
; add edi,eax |
; mov ebx,1 |
; shl ebx,cl |
test ebp, ebp |
; cmp ebp,0 ; enable access - ebp = 0 |
jnz .siar1 |
; not ebx |
; and [edi],byte bl |
btr [edi], eax |
pop eax edi |
ret |
.siar1: |
bts [edi], eax |
; or [edi],byte bl ; disable access - ebp = 1 |
pop eax edi |
ret |
;reserve/free group of ports |
; * eax = 46 - number function |
; * ebx = 0 - reserve, 1 - free |
; * ecx = number start arrea of ports |
; * edx = number end arrea of ports (include last number of port) |
;Return value: |
; * eax = 0 - succesful |
; * eax = 1 - error |
; * The system has reserve this ports: |
; 0..0x2d, 0x30..0x4d, 0x50..0xdf, 0xe5..0xff (include last number of port). |
;destroys eax,ebx, ebp |
r_f_port_area: |
test ebx, ebx |
jnz free_port_area |
; je r_port_area |
; jmp free_port_area |
; r_port_area: |
; pushad |
cmp ecx, edx ; beginning > end ? |
ja rpal1 |
cmp edx, 65536 |
jae rpal1 |
mov eax, [RESERVED_PORTS] |
test eax, eax ; no reserved areas ? |
je rpal2 |
cmp eax, 255 ; max reserved |
jae rpal1 |
rpal3: |
mov ebx, eax |
shl ebx, 4 |
add ebx, RESERVED_PORTS |
cmp ecx, [ebx+8] |
ja rpal4 |
cmp edx, [ebx+4] |
jae rpal1 |
; jb rpal4 |
; jmp rpal1 |
rpal4: |
dec eax |
jnz rpal3 |
jmp rpal2 |
rpal1: |
; popad |
; mov eax,1 |
xor eax, eax |
inc eax |
ret |
rpal2: |
; popad |
; enable port access at port IO map |
cli |
pushad ; start enable io map |
cmp edx, 65536;16384 |
jae no_unmask_io; jge |
mov eax, ecx |
; push ebp |
xor ebp, ebp ; enable - eax = port |
new_port_access: |
; pushad |
call set_io_access_rights |
; popad |
inc eax |
cmp eax, edx |
jbe new_port_access |
; pop ebp |
no_unmask_io: |
popad ; end enable io map |
sti |
mov eax, [RESERVED_PORTS] |
add eax, 1 |
mov [RESERVED_PORTS], eax |
shl eax, 4 |
add eax, RESERVED_PORTS |
mov ebx, [TASK_BASE] |
mov ebx, [ebx+TASKDATA.pid] |
mov [eax], ebx |
mov [eax+4], ecx |
mov [eax+8], edx |
xor eax, eax |
ret |
free_port_area: |
; pushad |
mov eax, [RESERVED_PORTS]; no reserved areas ? |
test eax, eax |
jz frpal2 |
mov ebx, [TASK_BASE] |
mov ebx, [ebx+TASKDATA.pid] |
frpal3: |
mov edi, eax |
shl edi, 4 |
add edi, RESERVED_PORTS |
cmp ebx, [edi] |
jne frpal4 |
cmp ecx, [edi+4] |
jne frpal4 |
cmp edx, [edi+8] |
jne frpal4 |
jmp frpal1 |
frpal4: |
dec eax |
jnz frpal3 |
frpal2: |
; popad |
inc eax |
ret |
frpal1: |
push ecx |
mov ecx, 256 |
sub ecx, eax |
shl ecx, 4 |
mov esi, edi |
add esi, 16 |
cld |
rep movsb |
dec dword [RESERVED_PORTS] |
;popad |
;disable port access at port IO map |
; pushad ; start disable io map |
pop eax ;start port |
cmp edx, 65536;16384 |
jge no_mask_io |
; mov eax,ecx |
xor ebp, ebp |
inc ebp |
new_port_access_disable: |
; pushad |
; mov ebp,1 ; disable - eax = port |
call set_io_access_rights |
; popad |
inc eax |
cmp eax, edx |
jbe new_port_access_disable |
no_mask_io: |
; popad ; end disable io map |
xor eax, eax |
ret |
align 4 |
drawbackground: |
inc [mouse_pause] |
cmp [SCR_MODE], word 0x12 |
je dbrv20 |
dbrv12: |
cmp [SCR_MODE], word 0100000000000000b |
jge dbrv20 |
cmp [SCR_MODE], word 0x13 |
je dbrv20 |
call vesa12_drawbackground |
dec [mouse_pause] |
call [draw_pointer] |
ret |
dbrv20: |
cmp [BgrDrawMode], dword 1 |
jne bgrstr |
call vesa20_drawbackground_tiled |
dec [mouse_pause] |
call [draw_pointer] |
ret |
bgrstr: |
call vesa20_drawbackground_stretch |
dec [mouse_pause] |
call [draw_pointer] |
ret |
align 4 |
syscall_putimage: ; PutImage |
sys_putimage: |
test ecx, 0x80008000 |
jnz .exit |
test ecx, 0x0000FFFF |
jz .exit |
test ecx, 0xFFFF0000 |
jnz @f |
.exit: |
ret |
@@: |
mov edi, [current_slot] |
add dx, word[edi+APPDATA.wnd_clientbox.top] |
rol edx, 16 |
add dx, word[edi+APPDATA.wnd_clientbox.left] |
rol edx, 16 |
.forced: |
push ebp esi 0 |
mov ebp, putimage_get24bpp |
mov esi, putimage_init24bpp |
sys_putimage_bpp: |
; call [disable_mouse] ; this will be done in xxx_putimage |
; mov eax, vga_putimage |
cmp [SCR_MODE], word 0x12 |
jz @f ;.doit |
mov eax, vesa12_putimage |
cmp [SCR_MODE], word 0100000000000000b |
jae @f |
cmp [SCR_MODE], word 0x13 |
jnz .doit |
@@: |
mov eax, vesa20_putimage |
.doit: |
inc [mouse_pause] |
call eax |
dec [mouse_pause] |
pop ebp esi ebp |
jmp [draw_pointer] |
align 4 |
sys_putimage_palette: |
; ebx = pointer to image |
; ecx = [xsize]*65536 + [ysize] |
; edx = [xstart]*65536 + [ystart] |
; esi = number of bits per pixel, must be 8, 24 or 32 |
; edi = pointer to palette |
; ebp = row delta |
mov eax, [CURRENT_TASK] |
shl eax, 8 |
add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.top] |
rol edx, 16 |
add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.left] |
rol edx, 16 |
.forced: |
cmp esi, 1 |
jnz @f |
push edi |
mov eax, [edi+4] |
sub eax, [edi] |
push eax |
push dword [edi] |
push 0ffffff80h |
mov edi, esp |
call put_mono_image |
add esp, 12 |
pop edi |
ret |
@@: |
cmp esi, 2 |
jnz @f |
push edi |
push 0ffffff80h |
mov edi, esp |
call put_2bit_image |
pop eax |
pop edi |
ret |
@@: |
cmp esi, 4 |
jnz @f |
push edi |
push 0ffffff80h |
mov edi, esp |
call put_4bit_image |
pop eax |
pop edi |
ret |
@@: |
push ebp esi ebp |
cmp esi, 8 |
jnz @f |
mov ebp, putimage_get8bpp |
mov esi, putimage_init8bpp |
jmp sys_putimage_bpp |
@@: |
cmp esi, 15 |
jnz @f |
mov ebp, putimage_get15bpp |
mov esi, putimage_init15bpp |
jmp sys_putimage_bpp |
@@: |
cmp esi, 16 |
jnz @f |
mov ebp, putimage_get16bpp |
mov esi, putimage_init16bpp |
jmp sys_putimage_bpp |
@@: |
cmp esi, 24 |
jnz @f |
mov ebp, putimage_get24bpp |
mov esi, putimage_init24bpp |
jmp sys_putimage_bpp |
@@: |
cmp esi, 32 |
jnz @f |
mov ebp, putimage_get32bpp |
mov esi, putimage_init32bpp |
jmp sys_putimage_bpp |
@@: |
pop ebp esi ebp |
ret |
put_mono_image: |
push ebp esi ebp |
mov ebp, putimage_get1bpp |
mov esi, putimage_init1bpp |
jmp sys_putimage_bpp |
put_2bit_image: |
push ebp esi ebp |
mov ebp, putimage_get2bpp |
mov esi, putimage_init2bpp |
jmp sys_putimage_bpp |
put_4bit_image: |
push ebp esi ebp |
mov ebp, putimage_get4bpp |
mov esi, putimage_init4bpp |
jmp sys_putimage_bpp |
putimage_init24bpp: |
lea eax, [eax*3] |
putimage_init8bpp: |
ret |
align 16 |
putimage_get24bpp: |
movzx eax, byte [esi+2] |
shl eax, 16 |
mov ax, [esi] |
add esi, 3 |
ret 4 |
align 16 |
putimage_get8bpp: |
movzx eax, byte [esi] |
push edx |
mov edx, [esp+8] |
mov eax, [edx+eax*4] |
pop edx |
inc esi |
ret 4 |
putimage_init1bpp: |
add eax, ecx |
push ecx |
add eax, 7 |
add ecx, 7 |
shr eax, 3 |
shr ecx, 3 |
sub eax, ecx |
pop ecx |
ret |
align 16 |
putimage_get1bpp: |
push edx |
mov edx, [esp+8] |
mov al, [edx] |
add al, al |
jnz @f |
lodsb |
adc al, al |
@@: |
mov [edx], al |
sbb eax, eax |
and eax, [edx+8] |
add eax, [edx+4] |
pop edx |
ret 4 |
putimage_init2bpp: |
add eax, ecx |
push ecx |
add ecx, 3 |
add eax, 3 |
shr ecx, 2 |
shr eax, 2 |
sub eax, ecx |
pop ecx |
ret |
align 16 |
putimage_get2bpp: |
push edx |
mov edx, [esp+8] |
mov al, [edx] |
mov ah, al |
shr al, 6 |
shl ah, 2 |
jnz .nonewbyte |
lodsb |
mov ah, al |
shr al, 6 |
shl ah, 2 |
add ah, 1 |
.nonewbyte: |
mov [edx], ah |
mov edx, [edx+4] |
movzx eax, al |
mov eax, [edx+eax*4] |
pop edx |
ret 4 |
putimage_init4bpp: |
add eax, ecx |
push ecx |
add ecx, 1 |
add eax, 1 |
shr ecx, 1 |
shr eax, 1 |
sub eax, ecx |
pop ecx |
ret |
align 16 |
putimage_get4bpp: |
push edx |
mov edx, [esp+8] |
add byte [edx], 80h |
jc @f |
movzx eax, byte [edx+1] |
mov edx, [edx+4] |
and eax, 0x0F |
mov eax, [edx+eax*4] |
pop edx |
ret 4 |
@@: |
movzx eax, byte [esi] |
add esi, 1 |
mov [edx+1], al |
shr eax, 4 |
mov edx, [edx+4] |
mov eax, [edx+eax*4] |
pop edx |
ret 4 |
putimage_init32bpp: |
shl eax, 2 |
ret |
align 16 |
putimage_get32bpp: |
lodsd |
ret 4 |
putimage_init15bpp: |
putimage_init16bpp: |
add eax, eax |
ret |
align 16 |
putimage_get15bpp: |
; 0RRRRRGGGGGBBBBB -> 00000000RRRRR000GGGGG000BBBBB000 |
push ecx edx |
movzx eax, word [esi] |
add esi, 2 |
mov ecx, eax |
mov edx, eax |
and eax, 0x1F |
and ecx, 0x1F shl 5 |
and edx, 0x1F shl 10 |
shl eax, 3 |
shl ecx, 6 |
shl edx, 9 |
or eax, ecx |
or eax, edx |
pop edx ecx |
ret 4 |
align 16 |
putimage_get16bpp: |
; RRRRRGGGGGGBBBBB -> 00000000RRRRR000GGGGGG00BBBBB000 |
push ecx edx |
movzx eax, word [esi] |
add esi, 2 |
mov ecx, eax |
mov edx, eax |
and eax, 0x1F |
and ecx, 0x3F shl 5 |
and edx, 0x1F shl 11 |
shl eax, 3 |
shl ecx, 5 |
shl edx, 8 |
or eax, ecx |
or eax, edx |
pop edx ecx |
ret 4 |
; eax x beginning |
; ebx y beginning |
; ecx x end |
; edx y end |
; edi color |
__sys_drawbar: |
mov esi, [current_slot] |
add eax, [esi+APPDATA.wnd_clientbox.left] |
add ecx, [esi+APPDATA.wnd_clientbox.left] |
add ebx, [esi+APPDATA.wnd_clientbox.top] |
add edx, [esi+APPDATA.wnd_clientbox.top] |
.forced: |
inc [mouse_pause] |
; call [disable_mouse] |
cmp [SCR_MODE], word 0x12 |
je dbv20 |
sdbv20: |
cmp [SCR_MODE], word 0100000000000000b |
jge dbv20 |
cmp [SCR_MODE], word 0x13 |
je dbv20 |
call vesa12_drawbar |
dec [mouse_pause] |
call [draw_pointer] |
ret |
dbv20: |
call vesa20_drawbar |
dec [mouse_pause] |
call [draw_pointer] |
ret |
kb_read: |
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 |
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: |
in al, 0x64 |
test al, 2 |
jz kw_ok |
loop kw_loop |
mov ah, 1 |
jmp kw_exit |
kw_ok: |
mov al, dl |
out 0x60, al |
mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's |
kw_loop3: |
in al, 0x64 |
test al, 2 |
jz kw_ok3 |
loop kw_loop3 |
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: |
xor ah, ah |
kw_exit: |
pop edx ecx |
ret |
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 |
mov [MOUSE_PICTURE], dword mousepointer |
cli |
ret |
if used _rdtsc |
_rdtsc: |
bt [cpu_caps], CAPS_TSC |
jnc ret_rdtsc |
rdtsc |
ret |
ret_rdtsc: |
mov edx, 0xffffffff |
mov eax, 0xffffffff |
ret |
end if |
sys_msg_board_str: |
pushad |
@@: |
cmp [esi], byte 0 |
je @f |
mov eax, 1 |
movzx ebx, byte [esi] |
call sys_msg_board |
inc esi |
jmp @b |
@@: |
popad |
ret |
sys_msg_board_byte: |
; in: al = byte to display |
; out: nothing |
; destroys: nothing |
pushad |
mov ecx, 2 |
shl eax, 24 |
jmp @f |
sys_msg_board_word: |
; in: ax = word to display |
; out: nothing |
; destroys: nothing |
pushad |
mov ecx, 4 |
shl eax, 16 |
jmp @f |
sys_msg_board_dword: |
; in: eax = dword to display |
; out: nothing |
; destroys: nothing |
pushad |
mov ecx, 8 |
@@: |
push ecx |
rol eax, 4 |
push eax |
and al, 0xF |
cmp al, 10 |
sbb al, 69h |
das |
mov bl, al |
xor eax, eax |
inc eax |
call sys_msg_board |
pop eax |
pop ecx |
loop @b |
popad |
ret |
uglobal |
msg_board_data: |
times 4096 db 0 |
msg_board_count dd 0x0 |
endg |
sys_msg_board: |
; eax=1 : write : bl byte to write |
; eax=2 : read : ebx=0 -> no data, ebx=1 -> data in al |
mov ecx, [msg_board_count] |
cmp eax, 1 |
jne .smbl1 |
if defined debug_com_base |
push dx ax |
@@: ; Wait for empty transmit register (yes, this slows down system..) |
mov dx, debug_com_base+5 |
in al, dx |
test al, 1 shl 5 |
jz @r |
mov dx, debug_com_base ; Output the byte |
mov al, bl |
out dx, al |
pop ax dx |
end if |
mov [msg_board_data+ecx], bl |
inc ecx |
and ecx, 4095 |
mov [msg_board_count], ecx |
mov [check_idle_semaphore], 5 |
ret |
.smbl1: |
cmp eax, 2 |
jne .smbl2 |
test ecx, ecx |
jz .smbl21 |
mov eax, msg_board_data+1 |
mov ebx, msg_board_data |
movzx edx, byte [ebx] |
call memmove |
dec [msg_board_count] |
mov [esp + 36], edx ;eax |
mov [esp + 24], dword 1 |
ret |
.smbl21: |
mov [esp+36], ecx |
mov [esp+24], ecx |
.smbl2: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; 66 sys function. ;; |
;; in eax=66,ebx in [0..5],ecx,edx ;; |
;; out eax ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
iglobal |
align 4 |
f66call: |
dd sys_process_def.1 ; 1 = set keyboard mode |
dd sys_process_def.2 ; 2 = get keyboard mode |
dd sys_process_def.3 ; 3 = get keyboard ctrl, alt, shift |
dd sys_process_def.4 |
dd sys_process_def.5 |
endg |
sys_process_def: |
dec ebx |
cmp ebx, 5 |
jae .not_support ;if >=6 then or eax,-1 |
mov edi, [CURRENT_TASK] |
jmp dword [f66call+ebx*4] |
.not_support: |
or eax, -1 |
ret |
.1: |
shl edi, 8 |
mov [edi+SLOT_BASE + APPDATA.keyboard_mode], cl |
ret |
.2: ; 2 = get keyboard mode |
shl edi, 8 |
movzx eax, byte [SLOT_BASE+edi + APPDATA.keyboard_mode] |
mov [esp+32], eax |
ret |
; xor eax,eax |
; movzx eax,byte [shift] |
; movzx ebx,byte [ctrl] |
; shl ebx,2 |
; add eax,ebx |
; movzx ebx,byte [alt] |
; shl ebx,3 |
; add eax,ebx |
.3: ;3 = get keyboard ctrl, alt, shift |
;// mike.dld [ |
mov eax, [kb_state] |
;// mike.dld ] |
mov [esp+32], eax |
ret |
.4: |
mov eax, hotkey_list |
@@: |
cmp dword [eax+8], 0 |
jz .found_free |
add eax, 16 |
cmp eax, hotkey_list+16*256 |
jb @b |
mov dword [esp+32], 1 |
ret |
.found_free: |
mov [eax+8], edi |
mov [eax+4], edx |
movzx ecx, cl |
lea ecx, [hotkey_scancodes+ecx*4] |
mov edx, [ecx] |
mov [eax], edx |
mov [ecx], eax |
mov [eax+12], ecx |
jecxz @f |
mov [edx+12], eax |
@@: |
and dword [esp+32], 0 |
ret |
.5: |
movzx ebx, cl |
lea ebx, [hotkey_scancodes+ebx*4] |
mov eax, [ebx] |
.scan: |
test eax, eax |
jz .notfound |
cmp [eax+8], edi |
jnz .next |
cmp [eax+4], edx |
jz .found |
.next: |
mov eax, [eax] |
jmp .scan |
.notfound: |
mov dword [esp+32], 1 |
ret |
.found: |
mov ecx, [eax] |
jecxz @f |
mov edx, [eax+12] |
mov [ecx+12], edx |
@@: |
mov ecx, [eax+12] |
mov edx, [eax] |
mov [ecx], edx |
xor edx, edx |
mov [eax+4], edx |
mov [eax+8], edx |
mov [eax+12], edx |
mov [eax], edx |
mov [esp+32], edx |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; 61 sys function. ;; |
;; in eax=61,ebx in [1..3] ;; |
;; out eax ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
iglobal |
align 4 |
f61call: |
dd sys_gs.1 ; resolution |
dd sys_gs.2 ; bits per pixel |
dd sys_gs.3 ; bytes per scanline |
endg |
align 4 |
sys_gs: ; direct screen access |
dec ebx |
cmp ebx, 2 |
ja .not_support |
jmp dword [f61call+ebx*4] |
.not_support: |
or [esp+32], dword -1 |
ret |
.1: ; resolution |
mov eax, [Screen_Max_X] |
shl eax, 16 |
mov ax, [Screen_Max_Y] |
add eax, 0x00010001 |
mov [esp+32], eax |
ret |
.2: ; bits per pixel |
movzx eax, byte [ScreenBPP] |
mov [esp+32], eax |
ret |
.3: ; bytes per scanline |
mov eax, [BytesPerScanLine] |
mov [esp+32], eax |
ret |
align 4 ; system functions |
syscall_setpixel: ; SetPixel |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov edx, [TASK_BASE] |
add eax, [edx-twdw+WDATA.box.left] |
add ebx, [edx-twdw+WDATA.box.top] |
mov edi, [current_slot] |
add eax, [edi+APPDATA.wnd_clientbox.left] |
add ebx, [edi+APPDATA.wnd_clientbox.top] |
xor edi, edi ; no force |
; mov edi, 1 |
call [_display.disable_mouse] |
jmp [putpixel] |
align 4 |
syscall_writetext: ; WriteText |
mov eax, [TASK_BASE] |
mov ebp, [eax-twdw+WDATA.box.left] |
push esi |
mov esi, [current_slot] |
add ebp, [esi+APPDATA.wnd_clientbox.left] |
shl ebp, 16 |
add ebp, [eax-twdw+WDATA.box.top] |
add bp, word[esi+APPDATA.wnd_clientbox.top] |
pop esi |
add ebx, ebp |
mov eax, edi |
xor edi, edi |
jmp dtext |
align 4 |
syscall_openramdiskfile: ; OpenRamdiskFile |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov edx, esi |
mov esi, 12 |
call fileread |
mov [esp+32], eax |
ret |
align 4 |
syscall_drawrect: ; DrawRect |
mov edi, edx ; color + gradient |
and edi, 0x80FFFFFF |
test bx, bx ; x.size |
je .drectr |
test cx, cx ; y.size |
je .drectr |
mov eax, ebx ; bad idea |
mov ebx, ecx |
movzx ecx, ax ; ecx - x.size |
shr eax, 16 ; eax - x.coord |
movzx edx, bx ; edx - y.size |
shr ebx, 16 ; ebx - y.coord |
mov esi, [current_slot] |
add eax, [esi + APPDATA.wnd_clientbox.left] |
add ebx, [esi + APPDATA.wnd_clientbox.top] |
add ecx, eax |
add edx, ebx |
jmp [drawbar] |
.drectr: |
ret |
align 4 |
syscall_getscreensize: ; GetScreenSize |
mov ax, [Screen_Max_X] |
shl eax, 16 |
mov ax, [Screen_Max_Y] |
mov [esp + 32], eax |
ret |
align 4 |
syscall_cdaudio: ; CD |
cmp ebx, 4 |
jb .audio |
jz .eject |
cmp ebx, 5 |
jnz .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 eax, ecx |
shr eax, 1 |
and eax, 1 |
inc eax |
mov [ChannelNumber], ax |
mov eax, ecx |
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: ; GetPixel |
mov ecx, [Screen_Max_X] |
inc ecx |
xor edx, edx |
mov eax, ebx |
div ecx |
mov ebx, edx |
xchg eax, ebx |
call dword [GETPIXEL]; eax - x, ebx - y |
mov [esp + 32], ecx |
ret |
align 4 |
syscall_getarea: |
;eax = 36 |
;ebx = pointer to bufer for img BBGGRRBBGGRR... |
;ecx = [size x]*65536 + [size y] |
;edx = [start x]*65536 + [start y] |
pushad |
inc [mouse_pause] |
; Check of use of the hardware cursor. |
cmp [_display.disable_mouse], __sys_disable_mouse |
jne @f |
; Since the test for the coordinates of the mouse should not be used, |
; then use the call [disable_mouse] is not possible! |
cmp dword [MOUSE_VISIBLE], dword 0 |
jne @f |
pushf |
cli |
call draw_mouse_under |
popf |
mov [MOUSE_VISIBLE], dword 1 |
@@: |
mov edi, ebx |
mov eax, edx |
shr eax, 16 |
mov ebx, edx |
and ebx, 0xffff |
dec eax |
dec ebx |
; eax - x, ebx - y |
mov edx, ecx |
shr ecx, 16 |
and edx, 0xffff |
mov esi, ecx |
; ecx - size x, edx - size y |
mov ebp, edx |
dec ebp |
lea ebp, [ebp*3] |
imul ebp, esi |
mov esi, ecx |
dec esi |
lea esi, [esi*3] |
add ebp, esi |
add ebp, edi |
add ebx, edx |
.start_y: |
push ecx edx |
.start_x: |
push eax ebx ecx |
add eax, ecx |
call dword [GETPIXEL]; eax - x, ebx - y |
mov [ebp], cx |
shr ecx, 16 |
mov [ebp+2], cl |
pop ecx ebx eax |
sub ebp, 3 |
dec ecx |
jnz .start_x |
pop edx ecx |
dec ebx |
dec edx |
jnz .start_y |
dec [mouse_pause] |
; Check of use of the hardware cursor. |
cmp [_display.disable_mouse], __sys_disable_mouse |
jne @f |
call [draw_pointer] |
@@: |
popad |
ret |
align 4 |
syscall_drawline: ; DrawLine |
mov edi, [TASK_BASE] |
movzx eax, word[edi-twdw+WDATA.box.left] |
mov ebp, eax |
mov esi, [current_slot] |
add ebp, [esi+APPDATA.wnd_clientbox.left] |
add ax, word[esi+APPDATA.wnd_clientbox.left] |
add ebp, ebx |
shl eax, 16 |
movzx ebx, word[edi-twdw+WDATA.box.top] |
add eax, ebp |
mov ebp, ebx |
add ebp, [esi+APPDATA.wnd_clientbox.top] |
add bx, word[esi+APPDATA.wnd_clientbox.top] |
add ebp, ecx |
shl ebx, 16 |
xor edi, edi |
add ebx, ebp |
mov ecx, edx |
jmp [draw_line] |
align 4 |
syscall_reserveportarea: ; ReservePortArea and FreePortArea |
call r_f_port_area |
mov [esp+32], eax |
ret |
align 4 |
syscall_threads: ; CreateThreads |
; eax=1 create thread |
; |
; ebx=thread start |
; ecx=thread stack value |
; |
; on return : eax = pid |
call new_sys_threads |
mov [esp+32], eax |
ret |
align 4 |
stack_driver_stat: |
call app_stack_handler ; Stack status |
; mov [check_idle_semaphore],5 ; enable these for zero delay |
; call change_task ; between sent packet |
mov [esp+32], eax |
ret |
align 4 |
socket: ; Socket interface |
call app_socket_handler |
; mov [check_idle_semaphore],5 ; enable these for zero delay |
; call change_task ; between sent packet |
mov [esp+36], eax |
mov [esp+24], ebx |
ret |
align 4 |
read_from_hd: ; Read from hd - fn not in use |
mov edi, [TASK_BASE] |
add edi, TASKDATA.mem_start |
add eax, [edi] |
add ecx, [edi] |
add edx, [edi] |
call file_read |
mov [esp+36], eax |
mov [esp+24], ebx |
ret |
paleholder: |
ret |
align 4 |
set_screen: |
cmp eax, [Screen_Max_X] |
jne .set |
cmp edx, [Screen_Max_Y] |
jne .set |
ret |
.set: |
pushfd |
cli |
mov [Screen_Max_X], eax |
mov [Screen_Max_Y], edx |
mov [BytesPerScanLine], ecx |
mov [screen_workarea.right], eax |
mov [screen_workarea.bottom], edx |
push ebx |
push esi |
push edi |
pushad |
stdcall kernel_free, [_WinMapAddress] |
mov eax, [_display.width] |
mul [_display.height] |
mov [_WinMapSize], eax |
stdcall kernel_alloc, eax |
mov [_WinMapAddress], eax |
test eax, eax |
jz .epic_fail |
popad |
call repos_windows |
xor eax, eax |
xor ebx, ebx |
mov ecx, [Screen_Max_X] |
mov edx, [Screen_Max_Y] |
call calculatescreen |
pop edi |
pop esi |
pop ebx |
popfd |
ret |
.epic_fail: |
hlt ; Houston, we've had a problem |
; --------------- APM --------------------- |
uglobal |
apm_entry dp 0 |
apm_vf dd 0 |
endg |
align 4 |
sys_apm: |
xor eax, eax |
cmp word [apm_vf], ax ; Check APM BIOS enable |
jne @f |
inc eax |
or dword [esp + 44], eax ; error |
add eax, 7 |
mov dword [esp + 32], eax ; 32-bit protected-mode interface not supported |
ret |
@@: |
; xchg eax, ecx |
; xchg ebx, ecx |
cmp dx, 3 |
ja @f |
and [esp + 44], byte 0xfe ; emulate func 0..3 as func 0 |
mov eax, [apm_vf] |
mov [esp + 32], eax |
shr eax, 16 |
mov [esp + 28], eax |
ret |
@@: |
mov esi, [master_tab+(OS_BASE shr 20)] |
xchg [master_tab], esi |
push esi |
mov edi, cr3 |
mov cr3, edi ;flush TLB |
call pword [apm_entry] ;call APM BIOS |
xchg eax, [esp] |
mov [master_tab], eax |
mov eax, cr3 |
mov cr3, eax |
pop eax |
mov [esp + 4 ], edi |
mov [esp + 8], esi |
mov [esp + 20], ebx |
mov [esp + 24], edx |
mov [esp + 28], ecx |
mov [esp + 32], eax |
setc al |
and [esp + 44], byte 0xfe |
or [esp + 44], al |
ret |
; ----------------------------------------- |
align 4 |
undefined_syscall: ; Undefined system call |
mov [esp + 32], dword -1 |
ret |
align 4 |
system_shutdown: ; shut down the system |
cmp byte [BOOT_VAR+0x9030], 1 |
jne @F |
ret |
@@: |
call stop_all_services |
push 3 ; stop playing cd |
pop eax |
call sys_cd_audio |
yes_shutdown_param: |
cli |
if ~ defined extended_primary_loader |
mov eax, kernel_file ; load kernel.mnt to 0x7000:0 |
push 12 |
pop esi |
xor ebx, ebx |
or ecx, -1 |
mov edx, OS_BASE+0x70000 |
call fileread |
mov esi, restart_kernel_4000+OS_BASE+0x10000 ; move kernel re-starter to 0x4000:0 |
mov edi, OS_BASE+0x40000 |
mov ecx, 1000 |
rep movsb |
end if |
mov esi, BOOT_VAR ; restore 0x0 - 0xffff |
mov edi, OS_BASE |
mov ecx, 0x10000/4 |
cld |
rep movsd |
call restorefatchain |
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 |
; scan for RSDP |
; 1) The first 1 Kb of the Extended BIOS Data Area (EBDA). |
movzx eax, word [OS_BASE + 0x40E] |
shl eax, 4 |
jz @f |
mov ecx, 1024/16 |
call scan_rsdp |
jnc .rsdp_found |
@@: |
; 2) The BIOS read-only memory space between 0E0000h and 0FFFFFh. |
mov eax, 0xE0000 |
mov ecx, 0x2000 |
call scan_rsdp |
jc no_acpi_power_off |
.rsdp_found: |
mov esi, [eax+16] ; esi contains physical address of the RSDT |
mov ebp, [ipc_tmp] |
stdcall map_page, ebp, esi, PG_MAP |
lea eax, [esi+1000h] |
lea edx, [ebp+1000h] |
stdcall map_page, edx, eax, PG_MAP |
and esi, 0xFFF |
add esi, ebp |
cmp dword [esi], 'RSDT' |
jnz no_acpi_power_off |
mov ecx, [esi+4] |
sub ecx, 24h |
jbe no_acpi_power_off |
shr ecx, 2 |
add esi, 24h |
.scan_fadt: |
lodsd |
mov ebx, eax |
lea eax, [ebp+2000h] |
stdcall map_page, eax, ebx, PG_MAP |
lea eax, [ebp+3000h] |
add ebx, 0x1000 |
stdcall map_page, eax, ebx, PG_MAP |
and ebx, 0xFFF |
lea ebx, [ebx+ebp+2000h] |
cmp dword [ebx], 'FACP' |
jz .fadt_found |
loop .scan_fadt |
jmp no_acpi_power_off |
.fadt_found: |
; ebx is linear address of FADT |
mov edi, [ebx+40] ; physical address of the DSDT |
lea eax, [ebp+4000h] |
stdcall map_page, eax, edi, PG_MAP |
lea eax, [ebp+5000h] |
lea esi, [edi+0x1000] |
stdcall map_page, eax, esi, PG_MAP |
and esi, 0xFFF |
sub edi, esi |
cmp dword [esi+ebp+4000h], 'DSDT' |
jnz no_acpi_power_off |
mov eax, [esi+ebp+4004h] ; DSDT length |
sub eax, 36+4 |
jbe no_acpi_power_off |
add esi, 36 |
.scan_dsdt: |
cmp dword [esi+ebp+4000h], '_S5_' |
jnz .scan_dsdt_cont |
cmp byte [esi+ebp+4000h+4], 12h ; DefPackage opcode |
jnz .scan_dsdt_cont |
mov dl, [esi+ebp+4000h+6] |
cmp dl, 4 ; _S5_ package must contain 4 bytes |
; ...in theory; in practice, VirtualBox has 2 bytes |
ja .scan_dsdt_cont |
cmp dl, 1 |
jb .scan_dsdt_cont |
lea esi, [esi+ebp+4000h+7] |
xor ecx, ecx |
cmp byte [esi], 0 ; 0 means zero byte, 0Ah xx means byte xx |
jz @f |
cmp byte [esi], 0xA |
jnz no_acpi_power_off |
inc esi |
mov cl, [esi] |
@@: |
inc esi |
cmp dl, 2 |
jb @f |
cmp byte [esi], 0 |
jz @f |
cmp byte [esi], 0xA |
jnz no_acpi_power_off |
inc esi |
mov ch, [esi] |
@@: |
jmp do_acpi_power_off |
.scan_dsdt_cont: |
inc esi |
cmp esi, 0x1000 |
jb @f |
sub esi, 0x1000 |
add edi, 0x1000 |
push eax |
lea eax, [ebp+4000h] |
stdcall map_page, eax, edi, PG_MAP |
push PG_MAP |
lea eax, [edi+1000h] |
push eax |
lea eax, [ebp+5000h] |
push eax |
stdcall map_page |
pop eax |
@@: |
dec eax |
jnz .scan_dsdt |
jmp no_acpi_power_off |
do_acpi_power_off: |
mov edx, [ebx+48] |
test edx, edx |
jz .nosmi |
mov al, [ebx+52] |
out dx, al |
mov edx, [ebx+64] |
@@: |
in ax, dx |
test al, 1 |
jz @b |
.nosmi: |
and cx, 0x0707 |
shl cx, 2 |
or cx, 0x2020 |
mov edx, [ebx+64] |
in ax, dx |
and ax, 203h |
or ah, cl |
out dx, ax |
mov edx, [ebx+68] |
test edx, edx |
jz @f |
in ax, dx |
and ax, 203h |
or ah, ch |
out dx, ax |
@@: |
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: |
cmp dword [eax], 'RSD ' |
jnz .n |
cmp dword [eax+4], 'PTR ' |
jnz .n |
xor edx, edx |
xor esi, esi |
@@: |
add dl, [eax+esi] |
inc esi |
cmp esi, 20 |
jnz @b |
test dl, dl |
jz .ok |
.n: |
add eax, 10h |
loop .s |
stc |
.ok: |
ret |
end if |
include "data32.inc" |
__REV__ = __REV |
uglobals_size = $ - endofcode |
diff16 "end of kernel code",0,$ |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/kernel32.inc |
---|
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/kglobals.inc |
---|
1,69 → 1,69 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;------------------------------------------------------------------ |
; use "iglobal" for inserting initialized global data definitions. |
;------------------------------------------------------------------ |
macro iglobal { |
IGlobals equ IGlobals, |
macro __IGlobalBlock { } |
macro iglobal_nested { |
IGlobals equ IGlobals, |
macro __IGlobalBlock \{ } |
;------------------------------------------------------------- |
; use 'uglobal' for inserting uninitialized global definitions. |
; even when you define some data values, these variables |
; will be stored as uninitialized data. |
;------------------------------------------------------------- |
macro uglobal { |
UGlobals equ UGlobals, |
macro __UGlobalBlock { } |
macro uglobal_nested { |
UGlobals equ UGlobals, |
macro __UGlobalBlock \{ } |
endg fix } ; Use endg for ending iglobal and uglobal blocks. |
endg_nested fix \} |
macro IncludeIGlobals{ |
macro IGlobals dummy,[n] \{ __IGlobalBlock |
purge __IGlobalBlock \} |
match I, IGlobals \{ I \} } |
macro IncludeUGlobals{ |
macro UGlobals dummy,[n] \{ |
\common |
\local begin, size |
begin = $ |
virtual at $ |
\forward |
__UGlobalBlock |
purge __UGlobalBlock |
\common |
size = $ - begin |
end virtual |
rb size |
\} |
match U, UGlobals \{ U \} } |
macro IncludeAllGlobals { |
IncludeIGlobals |
IncludeUGlobals |
} |
iglobal |
endg |
uglobal |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;------------------------------------------------------------------ |
; use "iglobal" for inserting initialized global data definitions. |
;------------------------------------------------------------------ |
macro iglobal { |
IGlobals equ IGlobals, |
macro __IGlobalBlock { } |
macro iglobal_nested { |
IGlobals equ IGlobals, |
macro __IGlobalBlock \{ } |
;------------------------------------------------------------- |
; use 'uglobal' for inserting uninitialized global definitions. |
; even when you define some data values, these variables |
; will be stored as uninitialized data. |
;------------------------------------------------------------- |
macro uglobal { |
UGlobals equ UGlobals, |
macro __UGlobalBlock { } |
macro uglobal_nested { |
UGlobals equ UGlobals, |
macro __UGlobalBlock \{ } |
endg fix } ; Use endg for ending iglobal and uglobal blocks. |
endg_nested fix \} |
macro IncludeIGlobals{ |
macro IGlobals dummy,[n] \{ __IGlobalBlock |
purge __IGlobalBlock \} |
match I, IGlobals \{ I \} } |
macro IncludeUGlobals{ |
macro UGlobals dummy,[n] \{ |
\common |
\local begin, size |
begin = $ |
virtual at $ |
\forward |
__UGlobalBlock |
purge __UGlobalBlock |
\common |
size = $ - begin |
end virtual |
rb size |
\} |
match U, UGlobals \{ U \} } |
macro IncludeAllGlobals { |
IncludeIGlobals |
IncludeUGlobals |
} |
iglobal |
endg |
uglobal |
endg |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/macros.inc |
---|
1,138 → 1,138 |
__REV = 0 |
macro $Revision a { |
match =: Num =$,a \{ |
if __REV < Num |
__REV = Num |
end if |
\} |
} |
$Revision$ |
; structure definition helper |
macro struct name, [arg] |
{ |
common |
name@struct equ name |
struc name arg { |
} |
macro declare_sizeof xname,value |
{ sizeof.#xname = value } |
macro struct_helper name |
{ |
match xname,name |
\{ |
virtual at 0 |
xname xname |
declare_sizeof xname, $ - xname |
name equ sizeof.#xname |
end virtual |
\} |
} |
ends fix } struct_helper name@struct |
;// mike.dld, 2006-29-01 [ |
; macros definition |
macro diff16 title,l1,l2 |
{ |
local s,d |
s = l2-l1 |
display title,': 0x' |
repeat 16 |
d = 48 + s shr ((16-%) shl 2) and $0F |
if d > 57 |
d = d + 65-57-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
macro diff10 title,l1,l2 |
{ |
local s,d,z,m |
s = l2-l1 |
z = 0 |
m = 1000000000 |
display title,': ' |
repeat 10 |
d = '0' + s / m |
s = s - (s/m)*m |
m = m / 10 |
if d <> '0' |
z = 1 |
end if |
if z <> 0 |
display d |
end if |
end repeat |
display 13,10 |
} |
include 'kglobals.inc' |
; \begin{diamond}[29.09.2006] |
; may be useful for kernel debugging |
; example 1: |
; dbgstr 'Hello, World!' |
; example 2: |
; dbgstr 'Hello, World!', save_flags |
macro dbgstr string*, f |
{ |
local a |
iglobal_nested |
a db 'K : ',string,13,10,0 |
endg_nested |
if ~ f eq |
pushfd |
end if |
push esi |
mov esi, a |
call sys_msg_board_str |
pop esi |
if ~ f eq |
popfd |
end if |
} |
; \end{diamond}[29.09.2006] |
macro Mov op1,op2,op3 ; op1 = op2 = op3 |
{ |
mov op2,op3 |
mov op1,op2 |
} |
macro __list_add new, prev, next |
{ |
mov [next+LHEAD.prev], new |
mov [new+LHEAD.next], next |
mov [new+LHEAD.prev], prev |
mov [prev+LHEAD.next], new |
} |
macro list_add new, head |
{ |
mov eax, [head+LHEAD.next] |
__list_add new, head, eax |
} |
macro list_add_tail new, head |
{ |
mov eax, [head+LHEAD.prev] |
__list_add new, eax, head |
} |
macro list_del entry |
{ |
mov edx, [entry+list_fd] |
mov ecx, [entry+list_bk] |
mov [edx+list_bk], ecx |
mov [ecx+list_fd], edx |
} |
__REV = 0 |
macro $Revision a { |
match =: Num =$,a \{ |
if __REV < Num |
__REV = Num |
end if |
\} |
} |
$Revision$ |
; structure definition helper |
macro struct name, [arg] |
{ |
common |
name@struct equ name |
struc name arg { |
} |
macro declare_sizeof xname,value |
{ sizeof.#xname = value } |
macro struct_helper name |
{ |
match xname,name |
\{ |
virtual at 0 |
xname xname |
declare_sizeof xname, $ - xname |
name equ sizeof.#xname |
end virtual |
\} |
} |
ends fix } struct_helper name@struct |
;// mike.dld, 2006-29-01 [ |
; macros definition |
macro diff16 title,l1,l2 |
{ |
local s,d |
s = l2-l1 |
display title,': 0x' |
repeat 16 |
d = 48 + s shr ((16-%) shl 2) and $0F |
if d > 57 |
d = d + 65-57-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
macro diff10 title,l1,l2 |
{ |
local s,d,z,m |
s = l2-l1 |
z = 0 |
m = 1000000000 |
display title,': ' |
repeat 10 |
d = '0' + s / m |
s = s - (s/m)*m |
m = m / 10 |
if d <> '0' |
z = 1 |
end if |
if z <> 0 |
display d |
end if |
end repeat |
display 13,10 |
} |
include 'kglobals.inc' |
; \begin{diamond}[29.09.2006] |
; may be useful for kernel debugging |
; example 1: |
; dbgstr 'Hello, World!' |
; example 2: |
; dbgstr 'Hello, World!', save_flags |
macro dbgstr string*, f |
{ |
local a |
iglobal_nested |
a db 'K : ',string,13,10,0 |
endg_nested |
if ~ f eq |
pushfd |
end if |
push esi |
mov esi, a |
call sys_msg_board_str |
pop esi |
if ~ f eq |
popfd |
end if |
} |
; \end{diamond}[29.09.2006] |
macro Mov op1,op2,op3 ; op1 = op2 = op3 |
{ |
mov op2, op3 |
mov op1, op2 |
} |
macro __list_add new, prev, next |
{ |
mov [next+LHEAD.prev], new |
mov [new+LHEAD.next], next |
mov [new+LHEAD.prev], prev |
mov [prev+LHEAD.next], new |
} |
macro list_add new, head |
{ |
mov eax, [head+LHEAD.next] |
__list_add new, head, eax |
} |
macro list_add_tail new, head |
{ |
mov eax, [head+LHEAD.prev] |
__list_add new, eax, head |
} |
macro list_del entry |
{ |
mov edx, [entry+list_fd] |
mov ecx, [entry+list_bk] |
mov [edx+list_bk], ecx |
mov [ecx+list_fd], edx |
} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/memmap.inc |
---|
1,264 → 1,264 |
; |
; MEMORY MAP |
; |
; Boot: |
; |
; 0:9000 byte bits per pixel |
; 0:9001 word scanline length |
; 0:9008 word vesa video mode |
; 0:900A word X res |
; 0:900C word Y res |
; 0:9010 byte mouse port - not used |
; 0:9014 dword Vesa 1.2 pm bank switch |
; 0:9018 dword Vesa 2.0 LFB address |
; 0:901C byte 0 or 1 : enable MTRR graphics acceleration |
; 0:901D byte not used anymore (0 or 1 : enable system log display) |
; 0:901E byte 0 or 1 : enable direct lfb write, paging disabled |
; 0:901F byte DMA write : 1=yes, 2=no |
; 0:9020 8bytes pci data |
; 0:9030 byte VRR start enabled 1, 2-no |
; 0:9031 word IDEContrRegsBaseAddr |
; 0x9040 - dword - entry point of APM BIOS |
; 0x9044 - word - version (BCD) |
; 0x9046 - word - flags |
; 0:907F byte number of BIOS hard disks |
; 0:9080 Nbytes BIOS hard disks |
; 0:9100 word available physical memory map: number of blocks |
; 0:9104 available physical memory map: blocks |
; |
; Runtime: |
; |
; 0x00000000 -> 0x7FFFFFFF application 2Gb |
; 0x80000000 -> 0FFF physical page zero - do not write |
; (used by int 13h in some configurations) |
; |
; 0x80001000 -> 2FFF window_data - 256 entries |
; |
; 0000 dword x start |
; 0004 dword y start |
; 0008 dword x size |
; 000C dword y size |
; 0010 dword color of work area |
; 0014 dword color of grab bar |
; 0018 dword color of frames |
; 001C dword window flags, +30 = window drawn, +31 redraw flag |
; |
; 3000 -> 4FFF task list - 256 entries |
; |
; 00 dword process count |
; 04 dword no of processes |
; 10 dword base of running process at 0x3000+ |
; |
; 20 dword application event mask |
; 24 dword PID - process identification number |
; 2a byte slot state: 0=running, 1,2=suspended |
; 3=zombie, 4=terminate, |
; 5=waiting for event, 9 = not used |
; 2e byte window number on screen |
; 30 dword exact position in memory |
; 34 dword counter sum |
; 38 dword time stamp counter add |
; 3c dword cpu usage in cpu timer tics |
; |
; |
; 5000 -> 68FF free (6k6) |
; 6900 -> 6EFF saved picture under mouse pointer (1k5) |
; |
; 6F00 -> 6FFF free (256) |
; |
; 7000 -> 7FFF used CD driver |
; |
; 8000 -> A3FF used FLOPPY driver |
; |
; A400 -> B0FF free (3k3), unused ACTIVE_PROC_STACK |
; B100 -> B307 IDT for int_0x00..int_0x40 |
; B308 -> BFFF free (3k3) |
; C000 -> C3FF window stack C000 no of windows - all in words |
; C402 -> C7FF window position in stack |
; D000 -> D1FF FDC controller |
; D200 -> D3FF FDC controller for Fat12 |
; D400 -> DFFF free (3k) |
; E000 byte multitasking started |
; E020 dword putpixel address |
; E024 dword getpixel address |
; E030 dword Vesa 1.2 pm bank switch address |
; E034 -> F1FF free (4k5) |
; F200 dword mousepicture -pointer |
; F204 dword mouse appearance counter |
; F208 -> F2FF free (248) |
; F300 dword x & y temp for windowmove |
; F304 -> F3FF free (252) |
; F400 byte no of keys in buffer |
; F401 byte 'buffer' |
; F402 -> F4FF reserved for keys |
; F500 byte no of buttons in buffer |
; F501 dword 'buffer' |
; F502 -> F5FF reserved for buttons |
; F600 dword tsc / second |
; F604 byte (unused?) mouse port: 1 ps2, 2 com1, 3 com2 |
; F605 -> FAFF free (1k2) |
; FB00 -> FB0F mouse memory 00 chunk count, that includes: |
; FB08 word -- mouse H-scroll |
; FB0A word -- mouse x |
; FB0C word -- mouse y |
; FB0E word -- mouse V-scroll |
; FB10 -> FB17 mouse color mem |
; FB21 x move |
; FB22 y move |
; FB28 high bits temp |
; FB30 color temp |
; FB40 byte buttons down |
; FB44 byte 0 mouse down -> do not draw |
; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under |
; FBF1 byte bits per pixel |
; FC00 -> FCFE com1/ps2 buffer |
; FCFF com1/ps2 buffer count starting from FC00 |
; FD00 -> FDFF free (256) |
; FE00 dword screen x size |
; FE04 dword screen y size |
; FE08 dword screen y multiplier |
; FE0C dword screen mode |
; FE10 -> FE7F free (112) |
; FE80 dword address of LFB in physical |
; FE84 dword address of applications memory start in physical ? |
; FE88 dword address of button list |
; FE8C dword memory to use |
; FE90 -> FEFF free (112) |
; FF00 byte 1 = system shutdown request |
; FF01 byte task activation request? |
; FFF0 byte >0 if redraw background request from app |
; FFF1 byte >0 if background changed |
; FFF2 write and read bank in screen |
; FFF4 byte 0 if first mouse draw & do not return picture under |
; FFF5 byte 1 do not draw pointer |
; FFFF byte do not change task for 1/100 sec. |
; |
; 0x80010000 -> 6CBFF kernel, 32-bit run-time code (up to 371 Kb) |
; 0x8006CC00 -> 6DBFF stack at boot time (4Kb) |
; |
; 0x8006DC00 -> 6E5FF basic text font II |
; 0x8006E600 -> 6Efff basic text font I |
; 0x8006F000 -> 6FFFF main page directory |
; 0x80070000 -> 7FFFF data of retrieved disks and partitions (Mario79) |
; 0x80080000 -> 8FFFF additional app info, in 256 byte steps - 256 entries |
; |
; 00 11db name of app running |
; 0x10 dword pointer to fpu save area |
; 0x14 dword event count |
; 0x18 dword user fpu exceptoins handler |
; 0x1c dword user sse exceptions handler |
; 20 dword PL0 stack base |
; 24 dword user heap base |
; 28 dword user heap top |
; 2c dword window cursor handle |
; 30 dword first event in list |
; 34 dword last event in list |
; 38 dword first kernel object in list |
; 3c dword last kernel object in list |
; 40 dword thread esp |
; 44 dword io permission map page 0 |
; 48 dword io permission map page 1 |
; 4c dword debug state: 1= load debug registers |
; 50 dword current directory ptr |
; 54 dword wait timeout |
; 58 dword thread TSS._esp0 (= pl0 stack base + size except for V86) |
; 5C-7F unused |
; |
; 80 dword address of random shaped window area |
; 84 byte shape area scale |
; 88 dword free |
; 8C dword application memory size |
; 90 dword window X position save |
; 94 dword window Y position save |
; 98 dword window X size save |
; 9C dword window Y size save |
; A0 dword IPC memory start |
; A4 dword IPC memory size |
; A8 dword event bits: mouse, stack,.. |
; AC dword 0 or debugger slot |
; B0 dword free |
; B4 byte keyboard mode: 0 = keymap, 1 = scancodes |
; B8 dword physical address of directory table |
; BC dword address of debug event memory |
; C0 5 dd thread debug registers: DR0,DR1,DR2,DR3,DR7 |
; |
; 0x80090000 -> 9FFFF tmp (64k) - unused? |
; 0x800A0000 -> AFFFF screen access area |
; 0x800B0000 -> FFFFF bios rest in peace -area (320k) ? |
; 0x80100000 -> 27FFFF diskette image (1m5) |
; 0x80280000 -> 281FFF ramdisk fat (8k) |
; 0x80282000 -> 283FFF floppy fat (8k) |
; |
; 0x80284000 -> 28BFFF HDD DMA AREA (32k) |
; 0x8028C000 -> 297FFF free (48k) |
; |
; 0x80298000 -> 29ffff auxiliary table for background smoothing code (32k) |
; |
; 0x802A0000 -> 2B00ff wav device buffer (64k) |
; 0x802A0000 -> 2B00ff wav device status (256) |
; 0x802B0100 -> 2Bffff free (63k8) |
; 0x802C0000 -> 2C3fff button info (8k) |
; |
; 0000 word number of buttons |
; first button entry at 0x10 |
; +0000 word process number |
; +0002 word button id number : bits 00-15 |
; +0004 word x start |
; +0006 word x size |
; +0008 word y start |
; +000A word y size |
; +000C word button id number : bits 16-31 |
; |
; 0x802C4000 -> 2CFFFF free (48k) |
; |
; 0x802D0000 -> 2DFFFF reserved port area (64k) |
; |
; 0000 dword no of port areas reserved |
; 0010 dword process id |
; dword start port |
; dword end port |
; dword 0 |
; |
; 0x802E0000 -> 2EFFFF irq data area (64k) |
; 0x802F0000 -> 2FFFFF low memory save (64k) |
; |
; 0x80300000 -> 31FFFF tcp memory (128k) |
; 0x80320000 -> 327FFF tcp memory (32k) |
; |
; 0x80328000 -> 32FFFF !vrr driver (32k) |
; 0x80330000 -> 377FFF skin data (32k) |
; 0x80338000 -> 338FFF draw data - 256 entries (4k) |
; 00 dword draw limit - x start |
; 04 dword draw limit - y start |
; 08 dword draw limit - x end |
; 0C dword draw limit - y end |
; 0x80339000 -> 3BFFF3 free (12k) |
; 0x8033BFF4 -> 33BFFF background info |
; 0x8033C000 page map (length b = memsize shr 15) |
; 0x8033C000 + b start of static pagetables |
; 0x803FFFFF <- no direct address translation beyond this point |
; ============================================================= |
; 0x805FF000 -> 5FFF80 TSS |
; 0x80600000 -> 601FFF i/o maps |
; 0x80800000 -> kernel heap |
; 0x80FFFFFF heap min limit |
; 0xFDBFFFFF heap max limit |
; 0xF0000000 -> 0xF1FFFFFF PCI-express extended config space |
; 0xFDC00000 -> 0xFDFFFFFF page tables 4Mb |
; 0xFE000000 -> 0xFFFFFFFF LFB 32Mb |
; 0xFE000000 -> 0xFE7FFFFF application available LFB 8Mb |
; 0xFE800000 -> 0xFFFFFFFF kernel LFB part 24 Mb |
; |
; MEMORY MAP |
; |
; Boot: |
; |
; 0:9000 byte bits per pixel |
; 0:9001 word scanline length |
; 0:9008 word vesa video mode |
; 0:900A word X res |
; 0:900C word Y res |
; 0:9010 byte mouse port - not used |
; 0:9014 dword Vesa 1.2 pm bank switch |
; 0:9018 dword Vesa 2.0 LFB address |
; 0:901C byte 0 or 1 : enable MTRR graphics acceleration |
; 0:901D byte not used anymore (0 or 1 : enable system log display) |
; 0:901E byte 0 or 1 : enable direct lfb write, paging disabled |
; 0:901F byte DMA write : 1=yes, 2=no |
; 0:9020 8bytes pci data |
; 0:9030 byte VRR start enabled 1, 2-no |
; 0:9031 word IDEContrRegsBaseAddr |
; 0x9040 - dword - entry point of APM BIOS |
; 0x9044 - word - version (BCD) |
; 0x9046 - word - flags |
; 0:907F byte number of BIOS hard disks |
; 0:9080 Nbytes BIOS hard disks |
; 0:9100 word available physical memory map: number of blocks |
; 0:9104 available physical memory map: blocks |
; |
; Runtime: |
; |
; 0x00000000 -> 0x7FFFFFFF application 2Gb |
; 0x80000000 -> 0FFF physical page zero - do not write |
; (used by int 13h in some configurations) |
; |
; 0x80001000 -> 2FFF window_data - 256 entries |
; |
; 0000 dword x start |
; 0004 dword y start |
; 0008 dword x size |
; 000C dword y size |
; 0010 dword color of work area |
; 0014 dword color of grab bar |
; 0018 dword color of frames |
; 001C dword window flags, +30 = window drawn, +31 redraw flag |
; |
; 3000 -> 4FFF task list - 256 entries |
; |
; 00 dword process count |
; 04 dword no of processes |
; 10 dword base of running process at 0x3000+ |
; |
; 20 dword application event mask |
; 24 dword PID - process identification number |
; 2a byte slot state: 0=running, 1,2=suspended |
; 3=zombie, 4=terminate, |
; 5=waiting for event, 9 = not used |
; 2e byte window number on screen |
; 30 dword exact position in memory |
; 34 dword counter sum |
; 38 dword time stamp counter add |
; 3c dword cpu usage in cpu timer tics |
; |
; |
; 5000 -> 68FF free (6k6) |
; 6900 -> 6EFF saved picture under mouse pointer (1k5) |
; |
; 6F00 -> 6FFF free (256) |
; |
; 7000 -> 7FFF used CD driver |
; |
; 8000 -> A3FF used FLOPPY driver |
; |
; A400 -> B0FF free (3k3), unused ACTIVE_PROC_STACK |
; B100 -> B307 IDT for int_0x00..int_0x40 |
; B308 -> BFFF free (3k3) |
; C000 -> C3FF window stack C000 no of windows - all in words |
; C402 -> C7FF window position in stack |
; D000 -> D1FF FDC controller |
; D200 -> D3FF FDC controller for Fat12 |
; D400 -> DFFF free (3k) |
; E000 byte multitasking started |
; E020 dword putpixel address |
; E024 dword getpixel address |
; E030 dword Vesa 1.2 pm bank switch address |
; E034 -> F1FF free (4k5) |
; F200 dword mousepicture -pointer |
; F204 dword mouse appearance counter |
; F208 -> F2FF free (248) |
; F300 dword x & y temp for windowmove |
; F304 -> F3FF free (252) |
; F400 byte no of keys in buffer |
; F401 byte 'buffer' |
; F402 -> F4FF reserved for keys |
; F500 byte no of buttons in buffer |
; F501 dword 'buffer' |
; F502 -> F5FF reserved for buttons |
; F600 dword tsc / second |
; F604 byte (unused?) mouse port: 1 ps2, 2 com1, 3 com2 |
; F605 -> FAFF free (1k2) |
; FB00 -> FB0F mouse memory 00 chunk count, that includes: |
; FB08 word -- mouse H-scroll |
; FB0A word -- mouse x |
; FB0C word -- mouse y |
; FB0E word -- mouse V-scroll |
; FB10 -> FB17 mouse color mem |
; FB21 x move |
; FB22 y move |
; FB28 high bits temp |
; FB30 color temp |
; FB40 byte buttons down |
; FB44 byte 0 mouse down -> do not draw |
; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under |
; FBF1 byte bits per pixel |
; FC00 -> FCFE com1/ps2 buffer |
; FCFF com1/ps2 buffer count starting from FC00 |
; FD00 -> FDFF free (256) |
; FE00 dword screen x size |
; FE04 dword screen y size |
; FE08 dword screen y multiplier |
; FE0C dword screen mode |
; FE10 -> FE7F free (112) |
; FE80 dword address of LFB in physical |
; FE84 dword address of applications memory start in physical ? |
; FE88 dword address of button list |
; FE8C dword memory to use |
; FE90 -> FEFF free (112) |
; FF00 byte 1 = system shutdown request |
; FF01 byte task activation request? |
; FFF0 byte >0 if redraw background request from app |
; FFF1 byte >0 if background changed |
; FFF2 write and read bank in screen |
; FFF4 byte 0 if first mouse draw & do not return picture under |
; FFF5 byte 1 do not draw pointer |
; FFFF byte do not change task for 1/100 sec. |
; |
; 0x80010000 -> 6CBFF kernel, 32-bit run-time code (up to 371 Kb) |
; 0x8006CC00 -> 6DBFF stack at boot time (4Kb) |
; |
; 0x8006DC00 -> 6E5FF basic text font II |
; 0x8006E600 -> 6Efff basic text font I |
; 0x8006F000 -> 6FFFF main page directory |
; 0x80070000 -> 7FFFF data of retrieved disks and partitions (Mario79) |
; 0x80080000 -> 8FFFF additional app info, in 256 byte steps - 256 entries |
; |
; 00 11db name of app running |
; 0x10 dword pointer to fpu save area |
; 0x14 dword event count |
; 0x18 dword user fpu exceptoins handler |
; 0x1c dword user sse exceptions handler |
; 20 dword PL0 stack base |
; 24 dword user heap base |
; 28 dword user heap top |
; 2c dword window cursor handle |
; 30 dword first event in list |
; 34 dword last event in list |
; 38 dword first kernel object in list |
; 3c dword last kernel object in list |
; 40 dword thread esp |
; 44 dword io permission map page 0 |
; 48 dword io permission map page 1 |
; 4c dword debug state: 1= load debug registers |
; 50 dword current directory ptr |
; 54 dword wait timeout |
; 58 dword thread TSS._esp0 (= pl0 stack base + size except for V86) |
; 5C-7F unused |
; |
; 80 dword address of random shaped window area |
; 84 byte shape area scale |
; 88 dword free |
; 8C dword application memory size |
; 90 dword window X position save |
; 94 dword window Y position save |
; 98 dword window X size save |
; 9C dword window Y size save |
; A0 dword IPC memory start |
; A4 dword IPC memory size |
; A8 dword event bits: mouse, stack,.. |
; AC dword 0 or debugger slot |
; B0 dword free |
; B4 byte keyboard mode: 0 = keymap, 1 = scancodes |
; B8 dword physical address of directory table |
; BC dword address of debug event memory |
; C0 5 dd thread debug registers: DR0,DR1,DR2,DR3,DR7 |
; |
; 0x80090000 -> 9FFFF tmp (64k) - unused? |
; 0x800A0000 -> AFFFF screen access area |
; 0x800B0000 -> FFFFF bios rest in peace -area (320k) ? |
; 0x80100000 -> 27FFFF diskette image (1m5) |
; 0x80280000 -> 281FFF ramdisk fat (8k) |
; 0x80282000 -> 283FFF floppy fat (8k) |
; |
; 0x80284000 -> 28BFFF HDD DMA AREA (32k) |
; 0x8028C000 -> 297FFF free (48k) |
; |
; 0x80298000 -> 29ffff auxiliary table for background smoothing code (32k) |
; |
; 0x802A0000 -> 2B00ff wav device buffer (64k) |
; 0x802A0000 -> 2B00ff wav device status (256) |
; 0x802B0100 -> 2Bffff free (63k8) |
; 0x802C0000 -> 2C3fff button info (8k) |
; |
; 0000 word number of buttons |
; first button entry at 0x10 |
; +0000 word process number |
; +0002 word button id number : bits 00-15 |
; +0004 word x start |
; +0006 word x size |
; +0008 word y start |
; +000A word y size |
; +000C word button id number : bits 16-31 |
; |
; 0x802C4000 -> 2CFFFF free (48k) |
; |
; 0x802D0000 -> 2DFFFF reserved port area (64k) |
; |
; 0000 dword no of port areas reserved |
; 0010 dword process id |
; dword start port |
; dword end port |
; dword 0 |
; |
; 0x802E0000 -> 2EFFFF irq data area (64k) |
; 0x802F0000 -> 2FFFFF low memory save (64k) |
; |
; 0x80300000 -> 31FFFF tcp memory (128k) |
; 0x80320000 -> 327FFF tcp memory (32k) |
; |
; 0x80328000 -> 32FFFF !vrr driver (32k) |
; 0x80330000 -> 377FFF skin data (32k) |
; 0x80338000 -> 338FFF draw data - 256 entries (4k) |
; 00 dword draw limit - x start |
; 04 dword draw limit - y start |
; 08 dword draw limit - x end |
; 0C dword draw limit - y end |
; 0x80339000 -> 3BFFF3 free (12k) |
; 0x8033BFF4 -> 33BFFF background info |
; 0x8033C000 page map (length b = memsize shr 15) |
; 0x8033C000 + b start of static pagetables |
; 0x803FFFFF <- no direct address translation beyond this point |
; ============================================================= |
; 0x805FF000 -> 5FFF80 TSS |
; 0x80600000 -> 601FFF i/o maps |
; 0x80800000 -> kernel heap |
; 0x80FFFFFF heap min limit |
; 0xFDBFFFFF heap max limit |
; 0xF0000000 -> 0xF1FFFFFF PCI-express extended config space |
; 0xFDC00000 -> 0xFDFFFFFF page tables 4Mb |
; 0xFE000000 -> 0xFFFFFFFF LFB 32Mb |
; 0xFE000000 -> 0xFE7FFFFF application available LFB 8Mb |
; 0xFE800000 -> 0xFFFFFFFF kernel LFB part 24 Mb |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/arp.inc |
---|
1,556 → 1,557 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ARP.INC ;; |
;; ;; |
;; Address Resolution Protocol ;; |
;; ;; |
;; This file contains the following: ;; |
;; arp_table_manager - Manages an ARPTable ;; |
;; arp_request - Sends an ARP request on the ethernet ;; |
;; arp_handler - Called when an ARP packet is received ;; |
;; ;; |
;; Changes history: ;; |
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; |
;; 11.11.2006 - [Johnny_B] and [smb] ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
ARP_NO_ENTRY equ 0 |
ARP_VALID_MAPPING equ 1 |
ARP_AWAITING_RESPONSE equ 2 |
ARP_RESPONSE_TIMEOUT equ 3 |
struc ARP_ENTRY ;=14 bytes |
{ .IP dd ? ;+00 |
.MAC dp ? ;+04 |
.Status dw ? ;+10 |
.TTL dw ? ;+12 : ( in seconds ) |
} |
virtual at 0 |
ARP_ENTRY ARP_ENTRY |
end virtual |
; The TTL field is decremented every second, and is deleted when it |
; reaches 0. It is refreshed every time a packet is received |
; If the TTL field is 0xFFFF it is a static entry and is never deleted |
; The status field can be the following values: |
; 0x0000 entry not used |
; 0x0001 entry holds a valid mapping |
; 0x0002 entry contains an IP address, awaiting ARP response |
; 0x0003 No response received to ARP request. |
; The last status value is provided to allow the network layer to delete |
; a packet that is queued awaiting an ARP response |
; The follow is the ARP Table. |
; This table must be manually updated and the kernel recompilied if |
; changes are made to it. |
; Empty entries are filled with zeros |
ARP_ENTRY_SIZE equ 14 ; Number of bytes per entry |
ARP_TABLE_SIZE equ 20 ; Size of table |
ARP_TABLE_ENTRIES equ 0 ; Number of static entries in the table |
;TO ADD A STATIC ENTRY, DONT FORGET, PUT "ARPTable" from "uglobal" to "iglobal"!!! |
;AND ALSO - IP and MAC have net byte-order, BUT STATUS AND TTL HAVE A MIRROR BYTE-ORDER!!! |
uglobal |
ARPTable: |
;example, static entry -> db 11,22,33,44, 0x11,0x22,0x33,0x44,0x55,0x66, 0x01,0x00, 0xFF,0xFF |
times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE db 0 |
endg |
iglobal |
NumARP: dd ARP_TABLE_ENTRIES |
ARPTable_ptr dd ARPTable ;pointer to ARPTable |
endg |
ARP_REQ_OPCODE equ 0x0100 ;request |
ARP_REP_OPCODE equ 0x0200 ;reply |
struc ARP_PACKET |
{ .HardwareType dw ? ;+00 |
.ProtocolType dw ? ;+02 |
.HardwareSize db ? ;+04 |
.ProtocolSize db ? ;+05 |
.Opcode dw ? ;+06 |
.SenderMAC dp ? ;+08 |
.SenderIP dd ? ;+14 |
.TargetMAC dp ? ;+18 |
.TargetIP dd ? ;+24 |
} |
virtual at 0 |
ARP_PACKET ARP_PACKET |
end virtual |
;*************************************************************************** |
; Function |
; arp_table_manager [by Johnny_B] |
; |
; Description |
; Does a most required operations with ARP-table |
; IN: |
; Operation: see Opcode's constants below |
; Index: Index of entry in the ARP-table |
; Extra: Extra parameter for some Opcodes |
; OUT: |
; EAX = Returned value depends on opcodes, more detailed see below |
; |
;*************************************************************************** |
;Opcode's constants |
ARP_TABLE_ADD equ 1 |
ARP_TABLE_DEL equ 2 |
ARP_TABLE_GET equ 3 |
ARP_TABLE_GET_ENTRIES_NUMBER equ 4 |
ARP_TABLE_IP_TO_MAC equ 5 |
ARP_TABLE_TIMER equ 6 |
;Index's constants |
EXTRA_IS_ARP_PACKET_PTR equ 0 ;if Extra contain pointer to ARP_PACKET |
EXTRA_IS_ARP_ENTRY_PTR equ -1 ;if Extra contain pointer to ARP_ENTRY |
align 4 |
proc arp_table_manager stdcall uses ebx esi edi ecx edx,\ |
Opcode:DWORD,Index:DWORD,Extra:DWORD |
mov ebx, dword[ARPTable_ptr] ;ARPTable base |
mov ecx, dword[NumARP] ;ARP-entries counter |
mov eax, dword[Opcode] |
cmp eax, ARP_TABLE_TIMER |
je .timer |
cmp eax, ARP_TABLE_ADD |
je .add |
cmp eax, ARP_TABLE_DEL |
je .del |
cmp eax, ARP_TABLE_GET |
je .get |
cmp eax, ARP_TABLE_IP_TO_MAC |
je .ip_to_mac |
cmp eax, ARP_TABLE_GET_ENTRIES_NUMBER |
je .get_entries_number |
jmp .exit ;if unknown opcode |
;;BEGIN TIMER |
;;Description: it must be callback every second. It is responsible for removing expired routes. |
;;IN: Operation: ARP_TABLE_TIMER |
;; Index: must be zero |
;; Extra: must be zero |
;;OUT: |
;; EAX=not defined |
;; |
.timer: |
test ecx, ecx |
jz .exit ;if NumARP=0 nothing to do |
sub ecx, ARP_TABLE_ENTRIES ;ecx=dynamic entries number |
jz .exit ;if NumARP=number of static entries then exit |
add ebx, ARP_TABLE_ENTRIES*ARP_ENTRY_SIZE ;ebx=dynamic entries base |
.timer_loop: |
movsx esi, word [ebx + ARP_ENTRY.TTL] |
cmp esi, 0xFFFFFFFF |
je .timer_loop_end ;if TTL==0xFFFF then it's static entry |
test esi, esi |
jnz .timer_loop_end_with_dec ;if TTL!=0 |
; Ok, TTL is 0 |
;if Status==AWAITING_RESPONSE and TTL==0 |
;then we have to change it to ARP_RESPONSE_TIMEOUT |
cmp word [ebx + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE |
jne @f |
mov word [ebx + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT |
mov word [ebx + ARP_ENTRY.TTL], word 0x000A ;10 sec |
jmp .timer_loop_end |
@@: |
;if TTL==0 and Status==VALID_MAPPING, we have to delete it |
;if TTL==0 and Status==RESPONSE_TIMEOUT, delete too |
mov esi, dword[NumARP] |
sub esi, ecx ;esi=index of entry, will be deleted |
stdcall arp_table_manager,ARP_TABLE_DEL,esi,0 ;opcode,index,extra |
jmp .timer_loop_end |
.timer_loop_end_with_dec: |
dec word [ebx + ARP_ENTRY.TTL] ;decrease TTL |
.timer_loop_end: |
add ebx, ARP_ENTRY_SIZE |
loop .timer_loop |
jmp .exit |
;;END TIMER |
;;BEGIN ADD |
;;Description: it adds an entry in the table. If ARP-table already |
;; contains same IP, it will be updated. |
;;IN: Operation: ARP_TABLE_ADD |
;; Index: specifies what contains Extra-parameter |
;; Extra: if Index==EXTRA_IS_ARP_PACKET_PTR, |
;; then Extra contains pointer to ARP_PACKET, |
;; otherwise Extra contains pointer to ARP_ENTRY |
;;OUT: |
;; EAX=index of entry, that has been added |
;; |
.add: |
sub esp, ARP_ENTRY_SIZE ;Allocate ARP_ENTRY_SIZE byte in stack |
mov esi, [Extra] ;pointer |
mov edi, [Index] ;opcode |
cmp edi, EXTRA_IS_ARP_PACKET_PTR |
je .arp_packet_to_entry ;if Extra contain ptr to ARP_PACKET and we have to form arp-entry |
;else it contain ptr to arp-entry |
cld |
; esi already has been loaded |
mov edi, esp ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) |
mov ecx,ARP_ENTRY_SIZE/2 ;ARP_ENTRY_SIZE must be even number!!! |
rep movsw ;copy |
jmp .search |
.arp_packet_to_entry: |
mov edx, dword[esi + ARP_PACKET.SenderIP] ;esi=base of ARP_PACKET |
mov [esp + ARP_ENTRY.IP], edx |
cld |
lea esi, [esi + ARP_PACKET.SenderMAC] |
lea edi, [esp + ARP_ENTRY.MAC] |
movsd |
movsw |
mov word[esp + ARP_ENTRY.Status], ARP_VALID_MAPPING ; specify the type - a valid entry |
mov word[esp + ARP_ENTRY.TTL], 0x0E10 ; = 1 hour |
.search: |
mov edx, dword[esp + ARP_ENTRY.IP] ;edx=IP-address, which we'll search |
mov ecx, dword[NumARP] ;ecx=ARP-entries counter |
jecxz .add_to_end ;if ARP-entries number == 0 |
imul eax, ecx, ARP_ENTRY_SIZE ;eax=current table size(in bytes) |
@@: |
sub eax, ARP_ENTRY_SIZE |
cmp dword[ebx + eax + ARP_ENTRY.IP], edx |
loopnz @b |
jz .replace ; found, replace existing entry, ptr to it is in eax |
.add_to_end: |
;else add to end |
or eax,-1 ;set eax=0xFFFFFFFF if adding is impossible |
mov ecx, dword[NumARP] |
cmp ecx, ARP_TABLE_SIZE |
je .add_exit ;if arp-entries number is equal to arp-table maxsize |
imul eax, dword[NumARP], ARP_ENTRY_SIZE ;eax=ptr to end of ARPTable |
inc dword [NumARP] ;increase ARP-entries counter |
.replace: |
cld |
mov esi, esp ;esp=base of ARP-entry, that will be added |
lea edi, [ebx + eax] ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) |
mov ecx,ARP_ENTRY_SIZE/2 ;ARP_ENTRY_SIZE must be even number!!! |
rep movsw |
mov ecx, ARP_ENTRY_SIZE |
xor edx, edx ;"div" takes operand from EDX:EAX |
div ecx ;eax=index of entry, which has been added |
.add_exit: |
add esp, ARP_ENTRY_SIZE ;free stack |
jmp .exit |
;;END ADD |
;;BEGIN DEL |
;;Description: it deletes an entry in the table. |
;;IN: Operation: ARP_TABLE_DEL |
;; Index: index of entry, that should be deleted |
;; Extra: must be zero |
;;OUT: |
;; EAX=not defined |
;; |
.del: |
mov esi, [Index] |
imul esi, ARP_ENTRY_SIZE |
mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE |
sub ecx, esi |
lea edi, [ebx + esi] ;edi=ptr to entry that should be deleted |
lea esi, [edi + ARP_ENTRY_SIZE] ;esi=ptr to next entry |
shr ecx,1 ;ecx/2 => ARP_ENTRY_SIZE MUST BE EVEN NUMBER! |
cld |
rep movsw |
dec dword[NumARP] ;decrease arp-entries counter |
jmp .exit |
;;END DEL |
;;BEGIN GET |
;;Description: it reads an entry of table into buffer. |
;;IN: Operation: ARP_TABLE_GET |
;; Index: index of entry, that should be read |
;; Extra: pointer to buffer for reading(size must be equal to ARP_ENTRY_SIZE) |
;;OUT: |
;; EAX=not defined |
;; |
.get: |
mov esi, [Index] |
imul esi, ARP_ENTRY_SIZE ;esi=ptr to required ARP_ENTRY |
mov edi, [Extra] ;edi=buffer for reading |
mov ecx, ARP_ENTRY_SIZE/2 ; must be even number!!! |
cld |
rep movsw |
jmp .exit |
;;END GET |
;;BEGIN IP_TO_MAC |
;;Description: it gets an IP from Index, scans each entry in the table and writes |
;; MAC, that relates to specified IP, into buffer specified in Extra. |
;; And if it cannot find an IP-address in the table, it does an ARP-request of that. |
;;IN: Operation: ARP_TABLE_IP_TO_MAC |
;; Index: IP that should be transformed into MAC |
;; Extra: pointer to buffer where will be written the MAC-address. |
;;OUT: |
;; EAX=ARP table entry status code. |
;; If EAX==ARP_NO_ENTRY, IP isn't found in the table and we have sent the request. |
;; If EAX==ARP_AWAITING_RESPONSE, we wait the response from remote system. |
;; If EAX==ARP_RESPONSE_TIMEOUT, remote system not responds too long. |
;; If EAX==ARP_VALID_MAPPING, all is ok, we've got a true MAC. |
;; |
;; If MAC will equal to a zero, in the buffer. It means, that IP-address was not yet |
;; resolved, or that doesn't exist. I recommend you, to do at most 3-5 calls of this |
;; function with 1sec delay. sure, only if it not return a valid MAC after a first call. |
;; |
.ip_to_mac: |
xor eax, eax |
mov edi, dword[Extra] |
cld |
stosd |
stosw |
; first, check destination IP to see if it is on 'this' network. |
; The test is: |
; if ( destIP & subnet_mask == stack_ip & subnet_mask ) |
; destination is local |
; else |
; destination is remote, so pass to gateway |
mov eax, [Index] ;eax=required IP |
mov esi, eax |
and esi, [subnet_mask] |
mov ecx, [stack_ip] |
and ecx, [subnet_mask] |
cmp esi, ecx |
je @f ;if we and target IP are located in the same network |
mov eax, [gateway_ip] |
mov [Index], eax |
@@: |
cmp dword[NumARP], 0 |
je .ip_to_mac_send_request ;if ARP-table not contain an entries, we have to request IP. |
;EAX will be containing a zero, it's equal to ARP_NO_ENTRY |
mov ecx, dword[NumARP] |
imul esi, ecx, ARP_ENTRY_SIZE ;esi=current ARP-table size |
@@: |
sub esi, ARP_ENTRY_SIZE |
cmp [ebx + esi], eax ; ebx=ARPTable base |
loopnz @b ; Return back if non match |
jnz .ip_to_mac_send_request ; and request IP->MAC if none found in the table |
; Return the entry status in eax |
movzx eax, word[ebx + esi + ARP_ENTRY.Status] |
; esi holds index |
cld |
lea esi, [ebx + esi + ARP_ENTRY.MAC] |
mov edi, [Extra] ;edi=ptr to buffer for write MAC |
movsd |
movsw |
jmp .exit |
.ip_to_mac_send_request: |
stdcall arp_request,[Index],stack_ip,node_addr ;TargetIP,SenderIP_ptr,SenderMAC_ptr |
mov eax, ARP_NO_ENTRY |
jmp .exit |
;;END IP_TO_MAC |
;;BEGIN GET_ENTRIES_NUMBER |
;;Description: returns an ARP-entries number in the ARPTable |
;;IN: Operation: ARP_TABLE_GET_ENTRIES_NUMBER |
;; Index: must be zero |
;; Extra: must be zero |
;;OUT: |
;; EAX=ARP-entries number in the ARPTable |
.get_entries_number: |
mov eax, dword[NumARP] |
jmp .exit |
;;END GET_ENTRIES_NUMBER |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; arp_handler |
; |
; Description |
; Called when an ARP packet is received on the ethernet |
; Header + Data is in Ether_buffer[] |
; It looks to see if the packet is a request to resolve this Hosts |
; IP address. If it is, send the ARP reply packet. |
; This Hosts IP address is in dword [stack_ip] ( in network format ) |
; This Hosts MAC address is in node_addr[6] |
; All registers may be destroyed |
; |
;*************************************************************************** |
arp_handler: |
; Is this a REQUEST? |
; Is this a request for My Host IP |
; Yes - So construct a response message. |
; Send this message to the ethernet card for transmission |
stdcall arp_table_manager,ARP_TABLE_ADD,EXTRA_IS_ARP_PACKET_PTR,ETH_FRAME.Data + ARP_PACKET |
inc dword[arp_rx_count] ;increase ARP-packets counter |
cmp word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REQ_OPCODE ; Is this a request packet? |
jne .exit ; No - so exit |
mov eax, [stack_ip] |
cmp eax, dword[ETH_FRAME.Data + ARP_PACKET.TargetIP] ; Is it looking for my IP address? |
jne .exit ; No - so quit now |
; OK, it is a request for my MAC address. Build the frame and send it |
; We can reuse the packet. |
mov word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REP_OPCODE |
cld |
mov esi, ETH_FRAME.Data + ARP_PACKET.SenderMAC |
mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC |
movsd |
movsw |
mov esi, ETH_FRAME.Data + ARP_PACKET.SenderIP |
mov edi, ETH_FRAME.Data + ARP_PACKET.TargetIP |
movsd |
mov esi, node_addr |
mov edi, ETH_FRAME.Data + ARP_PACKET.SenderMAC |
movsd |
movsw |
mov esi, stack_ip |
mov edi, ETH_FRAME.Data + ARP_PACKET.SenderIP |
movsd |
; Now, send it! |
mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC ;ptr to destination MAC address |
mov bx, ETHER_ARP ;type of protocol |
mov ecx, 28 ;data size |
mov esi, ETH_FRAME.Data + ARP_PACKET ;ptr to data |
push ebp |
call dword [drvr_transmit] ;transmit packet |
pop ebp |
.exit: |
ret |
;*************************************************************************** |
; Function |
; arp_request [by Johnny_B] |
; |
; Description |
; Sends an ARP request on the ethernet |
; IN: |
; TargetIP : requested IP address |
; SenderIP_ptr : POINTER to sender's IP address(our system's address) |
; SenderMAC_ptr : POINTER to sender's MAC address(our system's address) |
; OUT: |
; EAX=0 (if all is ok), otherwise EAX is not defined |
; |
; EBX,ESI,EDI will be saved |
; |
;*************************************************************************** |
proc arp_request stdcall uses ebx esi edi,\ |
TargetIP:DWORD, SenderIP_ptr:DWORD, SenderMAC_ptr:DWORD |
inc dword[arp_tx_count] ; increase counter |
sub esp, 28 ; allocate memory for ARP_PACKET |
mov word[esp + ARP_PACKET.HardwareType],0x0100 ;Ethernet |
mov word[esp + ARP_PACKET.ProtocolType],0x0008 ;IP |
mov byte[esp + ARP_PACKET.HardwareSize],0x06 ;MAC-addr length |
mov byte[esp + ARP_PACKET.ProtocolSize],0x04 ;IP-addr length |
mov word[esp + ARP_PACKET.Opcode],0x0100 ;Request |
cld |
mov esi,[SenderMAC_ptr] |
lea edi,[esp + ARP_PACKET.SenderMAC] ;Our MAC-addr |
movsd |
movsw |
mov esi,[SenderIP_ptr] |
lea edi,[esp + ARP_PACKET.SenderIP] ;Our IP-addr |
movsd |
xor eax, eax |
lea edi, [esp + ARP_PACKET.TargetMAC] ;Required MAC-addr(zeroed) |
stosd |
stosw |
mov esi, dword[TargetIP] |
mov dword[esp + ARP_PACKET.TargetIP],esi ;Required IP-addr(we get it as function parameter) |
; Now, send it! |
mov edi, broadcast_add ; Pointer to 48 bit destination address |
mov bx, ETHER_ARP ; Type of packet |
mov ecx, 28 ; size of packet |
lea esi, [esp + ARP_PACKET]; pointer to packet data |
push ebp |
call dword [drvr_transmit] ; Call the drivers transmit function |
pop ebp |
add esp, 28 ; free memory, allocated before for ARP_PACKET |
; Add an entry in the ARP table, awaiting response |
sub esp, ARP_ENTRY_SIZE ;allocate memory for ARP-entry |
mov esi, dword[TargetIP] |
mov dword[esp + ARP_ENTRY.IP],esi |
lea edi, [esp + ARP_ENTRY.MAC] |
xor eax, eax |
stosd |
stosw |
mov word[esp + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE |
mov word[esp + ARP_ENTRY.TTL], 0x000A ; 10 seconds |
stdcall arp_table_manager,ARP_TABLE_ADD,EXTRA_IS_ARP_ENTRY_PTR,esp |
add esp, ARP_ENTRY_SIZE ; free memory |
.exit: |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ARP.INC ;; |
;; ;; |
;; Address Resolution Protocol ;; |
;; ;; |
;; This file contains the following: ;; |
;; arp_table_manager - Manages an ARPTable ;; |
;; arp_request - Sends an ARP request on the ethernet ;; |
;; arp_handler - Called when an ARP packet is received ;; |
;; ;; |
;; Changes history: ;; |
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; |
;; 11.11.2006 - [Johnny_B] and [smb] ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
ARP_NO_ENTRY equ 0 |
ARP_VALID_MAPPING equ 1 |
ARP_AWAITING_RESPONSE equ 2 |
ARP_RESPONSE_TIMEOUT equ 3 |
struc ARP_ENTRY ;=14 bytes |
{ .IP dd ? ;+00 |
.MAC dp ? ;+04 |
.Status dw ? ;+10 |
.TTL dw ? ;+12 : ( in seconds ) |
} |
virtual at 0 |
ARP_ENTRY ARP_ENTRY |
end virtual |
; The TTL field is decremented every second, and is deleted when it |
; reaches 0. It is refreshed every time a packet is received |
; If the TTL field is 0xFFFF it is a static entry and is never deleted |
; The status field can be the following values: |
; 0x0000 entry not used |
; 0x0001 entry holds a valid mapping |
; 0x0002 entry contains an IP address, awaiting ARP response |
; 0x0003 No response received to ARP request. |
; The last status value is provided to allow the network layer to delete |
; a packet that is queued awaiting an ARP response |
; The follow is the ARP Table. |
; This table must be manually updated and the kernel recompilied if |
; changes are made to it. |
; Empty entries are filled with zeros |
ARP_ENTRY_SIZE equ 14 ; Number of bytes per entry |
ARP_TABLE_SIZE equ 20 ; Size of table |
ARP_TABLE_ENTRIES equ 0 ; Number of static entries in the table |
;TO ADD A STATIC ENTRY, DONT FORGET, PUT "ARPTable" from "uglobal" to "iglobal"!!! |
;AND ALSO - IP and MAC have net byte-order, BUT STATUS AND TTL HAVE A MIRROR BYTE-ORDER!!! |
uglobal |
ARPTable: |
;example, static entry -> db 11,22,33,44, 0x11,0x22,0x33,0x44,0x55,0x66, 0x01,0x00, 0xFF,0xFF |
times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE db 0 |
endg |
iglobal |
NumARP: |
dd ARP_TABLE_ENTRIES |
ARPTable_ptr dd ARPTable ;pointer to ARPTable |
endg |
ARP_REQ_OPCODE equ 0x0100 ;request |
ARP_REP_OPCODE equ 0x0200 ;reply |
struc ARP_PACKET |
{ .HardwareType dw ? ;+00 |
.ProtocolType dw ? ;+02 |
.HardwareSize db ? ;+04 |
.ProtocolSize db ? ;+05 |
.Opcode dw ? ;+06 |
.SenderMAC dp ? ;+08 |
.SenderIP dd ? ;+14 |
.TargetMAC dp ? ;+18 |
.TargetIP dd ? ;+24 |
} |
virtual at 0 |
ARP_PACKET ARP_PACKET |
end virtual |
;*************************************************************************** |
; Function |
; arp_table_manager [by Johnny_B] |
; |
; Description |
; Does a most required operations with ARP-table |
; IN: |
; Operation: see Opcode's constants below |
; Index: Index of entry in the ARP-table |
; Extra: Extra parameter for some Opcodes |
; OUT: |
; EAX = Returned value depends on opcodes, more detailed see below |
; |
;*************************************************************************** |
;Opcode's constants |
ARP_TABLE_ADD equ 1 |
ARP_TABLE_DEL equ 2 |
ARP_TABLE_GET equ 3 |
ARP_TABLE_GET_ENTRIES_NUMBER equ 4 |
ARP_TABLE_IP_TO_MAC equ 5 |
ARP_TABLE_TIMER equ 6 |
;Index's constants |
EXTRA_IS_ARP_PACKET_PTR equ 0 ;if Extra contain pointer to ARP_PACKET |
EXTRA_IS_ARP_ENTRY_PTR equ -1 ;if Extra contain pointer to ARP_ENTRY |
align 4 |
proc arp_table_manager stdcall uses ebx esi edi ecx edx,\ |
Opcode:DWORD,Index:DWORD,Extra:DWORD |
mov ebx, dword[ARPTable_ptr];ARPTable base |
mov ecx, dword[NumARP] ;ARP-entries counter |
mov eax, dword[Opcode] |
cmp eax, ARP_TABLE_TIMER |
je .timer |
cmp eax, ARP_TABLE_ADD |
je .add |
cmp eax, ARP_TABLE_DEL |
je .del |
cmp eax, ARP_TABLE_GET |
je .get |
cmp eax, ARP_TABLE_IP_TO_MAC |
je .ip_to_mac |
cmp eax, ARP_TABLE_GET_ENTRIES_NUMBER |
je .get_entries_number |
jmp .exit ;if unknown opcode |
;;BEGIN TIMER |
;;Description: it must be callback every second. It is responsible for removing expired routes. |
;;IN: Operation: ARP_TABLE_TIMER |
;; Index: must be zero |
;; Extra: must be zero |
;;OUT: |
;; EAX=not defined |
;; |
.timer: |
test ecx, ecx |
jz .exit;if NumARP=0 nothing to do |
sub ecx, ARP_TABLE_ENTRIES;ecx=dynamic entries number |
jz .exit;if NumARP=number of static entries then exit |
add ebx, ARP_TABLE_ENTRIES*ARP_ENTRY_SIZE;ebx=dynamic entries base |
.timer_loop: |
movsx esi, word [ebx + ARP_ENTRY.TTL] |
cmp esi, 0xFFFFFFFF |
je .timer_loop_end;if TTL==0xFFFF then it's static entry |
test esi, esi |
jnz .timer_loop_end_with_dec;if TTL!=0 |
; Ok, TTL is 0 |
;if Status==AWAITING_RESPONSE and TTL==0 |
;then we have to change it to ARP_RESPONSE_TIMEOUT |
cmp word [ebx + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE |
jne @f |
mov word [ebx + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT |
mov word [ebx + ARP_ENTRY.TTL], word 0x000A;10 sec |
jmp .timer_loop_end |
@@: |
;if TTL==0 and Status==VALID_MAPPING, we have to delete it |
;if TTL==0 and Status==RESPONSE_TIMEOUT, delete too |
mov esi, dword[NumARP] |
sub esi, ecx ;esi=index of entry, will be deleted |
stdcall arp_table_manager, ARP_TABLE_DEL, esi, 0;opcode,index,extra |
jmp .timer_loop_end |
.timer_loop_end_with_dec: |
dec word [ebx + ARP_ENTRY.TTL];decrease TTL |
.timer_loop_end: |
add ebx, ARP_ENTRY_SIZE |
loop .timer_loop |
jmp .exit |
;;END TIMER |
;;BEGIN ADD |
;;Description: it adds an entry in the table. If ARP-table already |
;; contains same IP, it will be updated. |
;;IN: Operation: ARP_TABLE_ADD |
;; Index: specifies what contains Extra-parameter |
;; Extra: if Index==EXTRA_IS_ARP_PACKET_PTR, |
;; then Extra contains pointer to ARP_PACKET, |
;; otherwise Extra contains pointer to ARP_ENTRY |
;;OUT: |
;; EAX=index of entry, that has been added |
;; |
.add: |
sub esp, ARP_ENTRY_SIZE;Allocate ARP_ENTRY_SIZE byte in stack |
mov esi, [Extra];pointer |
mov edi, [Index];opcode |
cmp edi, EXTRA_IS_ARP_PACKET_PTR |
je .arp_packet_to_entry;if Extra contain ptr to ARP_PACKET and we have to form arp-entry |
;else it contain ptr to arp-entry |
cld |
; esi already has been loaded |
mov edi, esp ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) |
mov ecx, ARP_ENTRY_SIZE/2;ARP_ENTRY_SIZE must be even number!!! |
rep movsw ;copy |
jmp .search |
.arp_packet_to_entry: |
mov edx, dword[esi + ARP_PACKET.SenderIP];esi=base of ARP_PACKET |
mov [esp + ARP_ENTRY.IP], edx |
cld |
lea esi, [esi + ARP_PACKET.SenderMAC] |
lea edi, [esp + ARP_ENTRY.MAC] |
movsd |
movsw |
mov word[esp + ARP_ENTRY.Status], ARP_VALID_MAPPING; specify the type - a valid entry |
mov word[esp + ARP_ENTRY.TTL], 0x0E10; = 1 hour |
.search: |
mov edx, dword[esp + ARP_ENTRY.IP];edx=IP-address, which we'll search |
mov ecx, dword[NumARP] ;ecx=ARP-entries counter |
jecxz .add_to_end ;if ARP-entries number == 0 |
imul eax, ecx, ARP_ENTRY_SIZE ;eax=current table size(in bytes) |
@@: |
sub eax, ARP_ENTRY_SIZE |
cmp dword[ebx + eax + ARP_ENTRY.IP], edx |
loopnz @b |
jz .replace ; found, replace existing entry, ptr to it is in eax |
.add_to_end: |
;else add to end |
or eax, -1;set eax=0xFFFFFFFF if adding is impossible |
mov ecx, dword[NumARP] |
cmp ecx, ARP_TABLE_SIZE |
je .add_exit;if arp-entries number is equal to arp-table maxsize |
imul eax, dword[NumARP], ARP_ENTRY_SIZE;eax=ptr to end of ARPTable |
inc dword [NumARP];increase ARP-entries counter |
.replace: |
cld |
mov esi, esp ;esp=base of ARP-entry, that will be added |
lea edi, [ebx + eax] ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) |
mov ecx, ARP_ENTRY_SIZE/2;ARP_ENTRY_SIZE must be even number!!! |
rep movsw |
mov ecx, ARP_ENTRY_SIZE |
xor edx, edx;"div" takes operand from EDX:EAX |
div ecx ;eax=index of entry, which has been added |
.add_exit: |
add esp, ARP_ENTRY_SIZE;free stack |
jmp .exit |
;;END ADD |
;;BEGIN DEL |
;;Description: it deletes an entry in the table. |
;;IN: Operation: ARP_TABLE_DEL |
;; Index: index of entry, that should be deleted |
;; Extra: must be zero |
;;OUT: |
;; EAX=not defined |
;; |
.del: |
mov esi, [Index] |
imul esi, ARP_ENTRY_SIZE |
mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE |
sub ecx, esi |
lea edi, [ebx + esi] ;edi=ptr to entry that should be deleted |
lea esi, [edi + ARP_ENTRY_SIZE];esi=ptr to next entry |
shr ecx, 1 ;ecx/2 => ARP_ENTRY_SIZE MUST BE EVEN NUMBER! |
cld |
rep movsw |
dec dword[NumARP];decrease arp-entries counter |
jmp .exit |
;;END DEL |
;;BEGIN GET |
;;Description: it reads an entry of table into buffer. |
;;IN: Operation: ARP_TABLE_GET |
;; Index: index of entry, that should be read |
;; Extra: pointer to buffer for reading(size must be equal to ARP_ENTRY_SIZE) |
;;OUT: |
;; EAX=not defined |
;; |
.get: |
mov esi, [Index] |
imul esi, ARP_ENTRY_SIZE;esi=ptr to required ARP_ENTRY |
mov edi, [Extra] ;edi=buffer for reading |
mov ecx, ARP_ENTRY_SIZE/2; must be even number!!! |
cld |
rep movsw |
jmp .exit |
;;END GET |
;;BEGIN IP_TO_MAC |
;;Description: it gets an IP from Index, scans each entry in the table and writes |
;; MAC, that relates to specified IP, into buffer specified in Extra. |
;; And if it cannot find an IP-address in the table, it does an ARP-request of that. |
;;IN: Operation: ARP_TABLE_IP_TO_MAC |
;; Index: IP that should be transformed into MAC |
;; Extra: pointer to buffer where will be written the MAC-address. |
;;OUT: |
;; EAX=ARP table entry status code. |
;; If EAX==ARP_NO_ENTRY, IP isn't found in the table and we have sent the request. |
;; If EAX==ARP_AWAITING_RESPONSE, we wait the response from remote system. |
;; If EAX==ARP_RESPONSE_TIMEOUT, remote system not responds too long. |
;; If EAX==ARP_VALID_MAPPING, all is ok, we've got a true MAC. |
;; |
;; If MAC will equal to a zero, in the buffer. It means, that IP-address was not yet |
;; resolved, or that doesn't exist. I recommend you, to do at most 3-5 calls of this |
;; function with 1sec delay. sure, only if it not return a valid MAC after a first call. |
;; |
.ip_to_mac: |
xor eax, eax |
mov edi, dword[Extra] |
cld |
stosd |
stosw |
; first, check destination IP to see if it is on 'this' network. |
; The test is: |
; if ( destIP & subnet_mask == stack_ip & subnet_mask ) |
; destination is local |
; else |
; destination is remote, so pass to gateway |
mov eax, [Index] ;eax=required IP |
mov esi, eax |
and esi, [subnet_mask] |
mov ecx, [stack_ip] |
and ecx, [subnet_mask] |
cmp esi, ecx |
je @f ;if we and target IP are located in the same network |
mov eax, [gateway_ip] |
mov [Index], eax |
@@: |
cmp dword[NumARP], 0 |
je .ip_to_mac_send_request;if ARP-table not contain an entries, we have to request IP. |
;EAX will be containing a zero, it's equal to ARP_NO_ENTRY |
mov ecx, dword[NumARP] |
imul esi, ecx, ARP_ENTRY_SIZE;esi=current ARP-table size |
@@: |
sub esi, ARP_ENTRY_SIZE |
cmp [ebx + esi], eax ; ebx=ARPTable base |
loopnz @b ; Return back if non match |
jnz .ip_to_mac_send_request; and request IP->MAC if none found in the table |
; Return the entry status in eax |
movzx eax, word[ebx + esi + ARP_ENTRY.Status] |
; esi holds index |
cld |
lea esi, [ebx + esi + ARP_ENTRY.MAC] |
mov edi, [Extra];edi=ptr to buffer for write MAC |
movsd |
movsw |
jmp .exit |
.ip_to_mac_send_request: |
stdcall arp_request, [Index], stack_ip, node_addr;TargetIP,SenderIP_ptr,SenderMAC_ptr |
mov eax, ARP_NO_ENTRY |
jmp .exit |
;;END IP_TO_MAC |
;;BEGIN GET_ENTRIES_NUMBER |
;;Description: returns an ARP-entries number in the ARPTable |
;;IN: Operation: ARP_TABLE_GET_ENTRIES_NUMBER |
;; Index: must be zero |
;; Extra: must be zero |
;;OUT: |
;; EAX=ARP-entries number in the ARPTable |
.get_entries_number: |
mov eax, dword[NumARP] |
jmp .exit |
;;END GET_ENTRIES_NUMBER |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; arp_handler |
; |
; Description |
; Called when an ARP packet is received on the ethernet |
; Header + Data is in Ether_buffer[] |
; It looks to see if the packet is a request to resolve this Hosts |
; IP address. If it is, send the ARP reply packet. |
; This Hosts IP address is in dword [stack_ip] ( in network format ) |
; This Hosts MAC address is in node_addr[6] |
; All registers may be destroyed |
; |
;*************************************************************************** |
arp_handler: |
; Is this a REQUEST? |
; Is this a request for My Host IP |
; Yes - So construct a response message. |
; Send this message to the ethernet card for transmission |
stdcall arp_table_manager, ARP_TABLE_ADD, EXTRA_IS_ARP_PACKET_PTR, ETH_FRAME.Data + ARP_PACKET |
inc dword[arp_rx_count];increase ARP-packets counter |
cmp word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REQ_OPCODE; Is this a request packet? |
jne .exit ; No - so exit |
mov eax, [stack_ip] |
cmp eax, dword[ETH_FRAME.Data + ARP_PACKET.TargetIP] ; Is it looking for my IP address? |
jne .exit ; No - so quit now |
; OK, it is a request for my MAC address. Build the frame and send it |
; We can reuse the packet. |
mov word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REP_OPCODE |
cld |
mov esi, ETH_FRAME.Data + ARP_PACKET.SenderMAC |
mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC |
movsd |
movsw |
mov esi, ETH_FRAME.Data + ARP_PACKET.SenderIP |
mov edi, ETH_FRAME.Data + ARP_PACKET.TargetIP |
movsd |
mov esi, node_addr |
mov edi, ETH_FRAME.Data + ARP_PACKET.SenderMAC |
movsd |
movsw |
mov esi, stack_ip |
mov edi, ETH_FRAME.Data + ARP_PACKET.SenderIP |
movsd |
; Now, send it! |
mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC;ptr to destination MAC address |
mov bx, ETHER_ARP ;type of protocol |
mov ecx, 28 ;data size |
mov esi, ETH_FRAME.Data + ARP_PACKET ;ptr to data |
push ebp |
call dword [drvr_transmit] ;transmit packet |
pop ebp |
.exit: |
ret |
;*************************************************************************** |
; Function |
; arp_request [by Johnny_B] |
; |
; Description |
; Sends an ARP request on the ethernet |
; IN: |
; TargetIP : requested IP address |
; SenderIP_ptr : POINTER to sender's IP address(our system's address) |
; SenderMAC_ptr : POINTER to sender's MAC address(our system's address) |
; OUT: |
; EAX=0 (if all is ok), otherwise EAX is not defined |
; |
; EBX,ESI,EDI will be saved |
; |
;*************************************************************************** |
proc arp_request stdcall uses ebx esi edi,\ |
TargetIP:DWORD, SenderIP_ptr:DWORD, SenderMAC_ptr:DWORD |
inc dword[arp_tx_count]; increase counter |
sub esp, 28; allocate memory for ARP_PACKET |
mov word[esp + ARP_PACKET.HardwareType], 0x0100;Ethernet |
mov word[esp + ARP_PACKET.ProtocolType], 0x0008;IP |
mov byte[esp + ARP_PACKET.HardwareSize], 0x06;MAC-addr length |
mov byte[esp + ARP_PACKET.ProtocolSize], 0x04;IP-addr length |
mov word[esp + ARP_PACKET.Opcode], 0x0100 ;Request |
cld |
mov esi, [SenderMAC_ptr] |
lea edi, [esp + ARP_PACKET.SenderMAC] ;Our MAC-addr |
movsd |
movsw |
mov esi, [SenderIP_ptr] |
lea edi, [esp + ARP_PACKET.SenderIP] ;Our IP-addr |
movsd |
xor eax, eax |
lea edi, [esp + ARP_PACKET.TargetMAC] ;Required MAC-addr(zeroed) |
stosd |
stosw |
mov esi, dword[TargetIP] |
mov dword[esp + ARP_PACKET.TargetIP], esi;Required IP-addr(we get it as function parameter) |
; Now, send it! |
mov edi, broadcast_add ; Pointer to 48 bit destination address |
mov bx, ETHER_ARP ; Type of packet |
mov ecx, 28 ; size of packet |
lea esi, [esp + ARP_PACKET]; pointer to packet data |
push ebp |
call dword [drvr_transmit]; Call the drivers transmit function |
pop ebp |
add esp, 28; free memory, allocated before for ARP_PACKET |
; Add an entry in the ARP table, awaiting response |
sub esp, ARP_ENTRY_SIZE;allocate memory for ARP-entry |
mov esi, dword[TargetIP] |
mov dword[esp + ARP_ENTRY.IP], esi |
lea edi, [esp + ARP_ENTRY.MAC] |
xor eax, eax |
stosd |
stosw |
mov word[esp + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE |
mov word[esp + ARP_ENTRY.TTL], 0x000A; 10 seconds |
stdcall arp_table_manager, ARP_TABLE_ADD, EXTRA_IS_ARP_ENTRY_PTR, esp |
add esp, ARP_ENTRY_SIZE; free memory |
.exit: |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/drivers/3c59x.inc |
---|
1,2378 → 1,2404 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;; Copyright (c) 2004, Endre Kozma <endre.kozma@axelero.hu> |
;; All rights reserved. |
;; |
;; Redistribution and use in source and binary forms, with or without |
;; modification, are permitted provided that the following conditions are |
;; met: |
;; |
;; 1. Redistributions of source code must retain the above copyright notice, |
;; this list of conditions and the following disclaimer. |
;; |
;; 2. Redistributions in binary form must reproduce the above copyright |
;; notice, this list of conditions and the following disclaimer in the |
;; documentation and/or other materials provided with the distribution. |
;; |
;; 3. The name of the author may not be used to endorse or promote products |
;; derived from this software without specific prior written permission. |
;; |
;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 3C59X.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Driver for 3Com fast etherlink 3c59x and ;; |
;; etherlink XL 3c900 and 3c905 cards ;; |
;; References: ;; |
;; www.3Com.com - data sheets ;; |
;; DP83840A.pdf - ethernet physical layer ;; |
;; 3c59x.c - linux driver ;; |
;; ethernet driver template by Mike Hibbett ;; |
;; ;; |
;; Credits ;; |
;; Mike Hibbett, ;; |
;; who kindly supplied me with a 3Com905C-TX-M card ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; History |
;; ======= |
;; $Log: 3C59X.INC,v $ |
;; Revision 1.3 2004/07/11 12:21:12 kozma |
;; Support of vortex chips (3c59x) added. |
;; Support of 3c920 and 3c982 added. |
;; Corrections. |
;; |
;; Revision 1.2 2004/06/12 19:40:20 kozma |
;; Function e3c59x_set_available_media added in order to set |
;; the default media in case auto detection finds no valid link. |
;; Incorrect mii check removed (3c900 Cyclone works now). |
;; Cleanups. |
;; |
;; Revision 1.1 2004/06/12 18:27:15 kozma |
;; Initial revision |
;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; comment the next line out if you don't want debug info printed |
; on the debug board. This option adds a lot of bytes to the driver |
; so it's worth to comment it out. |
; E3C59X_DEBUG equ 1 |
; forcing full duplex mode makes sense at some cards and link types |
E3C59X_FORCE_FD equ 1 |
macro virt_to_dma reg |
{ |
sub reg, OS_BASE |
} |
macro dma_to_virt reg |
{ |
add reg, OS_BASE |
} |
macro zero_to_virt reg |
{ |
} |
macro virt_to_zero reg |
{ |
} |
macro zero_to_dma reg |
{ |
sub reg, OS_BASE |
} |
macro dma_to_zero reg |
{ |
add reg, OS_BASE |
} |
macro strtbl name, [string] |
{ |
common |
label name dword |
forward |
local label |
dd label |
forward |
label db string, 0 |
} |
; Ethernet frame symbols |
ETH_ALEN equ 6 |
ETH_HLEN equ (2*ETH_ALEN+2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
; PCI programming |
PCI_REG_COMMAND equ 0x4 ; command register |
PCI_REG_STATUS equ 0x6 ; status register |
PCI_REG_LATENCY equ 0xd ; latency timer register |
PCI_REG_CAP_PTR equ 0x34 ; capabilities pointer |
PCI_REG_CAPABILITY_ID equ 0x0 ; capapility ID in pm register block |
PCI_REG_PM_STATUS equ 0x4 ; power management status register |
PCI_REG_PM_CTRL equ 0x4 ; power management control register |
PCI_BIT_PIO equ 0 ; bit0: io space control |
PCI_BIT_MMIO equ 1 ; bit1: memory space control |
PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master |
; Registers |
E3C59X_REG_POWER_MGMT_CTRL equ 0x7c |
E3C59X_REG_UP_LIST_PTR equ 0x38 |
E3C59X_REG_UP_PKT_STATUS equ 0x30 |
E3C59X_REG_TX_FREE_THRESH equ 0x2f |
E3C59X_REG_DN_LIST_PTR equ 0x24 |
E3C59X_REG_DMA_CTRL equ 0x20 |
E3C59X_REG_TX_STATUS equ 0x1b |
E3C59X_REG_RX_STATUS equ 0x18 |
E3C59X_REG_TX_DATA equ 0x10 |
; Common window registers |
E3C59X_REG_INT_STATUS equ 0xe |
E3C59X_REG_COMMAND equ 0xe |
; Register window 7 |
E3C59X_REG_MASTER_STATUS equ 0xc |
E3C59X_REG_POWER_MGMT_EVENT equ 0xc |
E3C59X_REG_MASTER_LEN equ 0x6 |
E3C59X_REG_VLAN_ETHER_TYPE equ 0x4 |
E3C59X_REG_VLAN_MASK equ 0x0 |
E3C59X_REG_MASTER_ADDRESS equ 0x0 |
; Register window 6 |
E3C59X_REG_BYTES_XMITTED_OK equ 0xc |
E3C59X_REG_BYTES_RCVD_OK equ 0xa |
E3C59X_REG_UPPER_FRAMES_OK equ 0x9 |
E3C59X_REG_FRAMES_DEFERRED equ 0x8 |
E3C59X_REG_FRAMES_RCVD_OK equ 0x7 |
E3C59X_REG_FRAMES_XMITTED_OK equ 0x6 |
E3C59X_REG_RX_OVERRUNS equ 0x5 |
E3C59X_REG_LATE_COLLISIONS equ 0x4 |
E3C59X_REG_SINGLE_COLLISIONS equ 0x3 |
E3C59X_REG_MULTIPLE_COLLISIONS equ 0x2 |
E3C59X_REG_SQE_ERRORS equ 0x1 |
E3C59X_REG_CARRIER_LOST equ 0x0 |
; Register window 5 |
E3C59X_REG_INDICATION_ENABLE equ 0xc |
E3C59X_REG_INTERRUPT_ENABLE equ 0xa |
E3C59X_REG_TX_RECLAIM_THRESH equ 0x9 |
E3C59X_REG_RX_FILTER equ 0x8 |
E3C59X_REG_RX_EARLY_THRESH equ 0x6 |
E3C59X_REG_TX_START_THRESH equ 0x0 |
; Register window 4 |
E3C59X_REG_UPPER_BYTES_OK equ 0xe |
E3C59X_REG_BAD_SSD equ 0xc |
E3C59X_REG_MEDIA_STATUS equ 0xa |
E3C59X_REG_PHYSICAL_MGMT equ 0x8 |
E3C59X_REG_NETWORK_DIAGNOSTIC equ 0x6 |
E3C59X_REG_FIFO_DIAGNOSTIC equ 0x4 |
E3C59X_REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported |
; Bits in register window 4 |
E3C59X_BIT_AUTOSELECT equ 24 |
; Register window 3 |
E3C59X_REG_TX_FREE equ 0xc |
E3C59X_REG_RX_FREE equ 0xa |
E3C59X_REG_MEDIA_OPTIONS equ 0x8 |
E3C59X_REG_MAC_CONTROL equ 0x6 |
E3C59X_REG_MAX_PKT_SIZE equ 0x4 |
E3C59X_REG_INTERNAL_CONFIG equ 0x0 |
; Register window 2 |
E3C59X_REG_RESET_OPTIONS equ 0xc |
E3C59X_REG_STATION_MASK_HI equ 0xa |
E3C59X_REG_STATION_MASK_MID equ 0x8 |
E3C59X_REG_STATION_MASK_LO equ 0x6 |
E3C59X_REG_STATION_ADDRESS_HI equ 0x4 |
E3C59X_REG_STATION_ADDRESS_MID equ 0x2 |
E3C59X_REG_STATION_ADDRESS_LO equ 0x0 |
; Register window 1 |
E3C59X_REG_TRIGGER_BITS equ 0xc |
E3C59X_REG_SOS_BITS equ 0xa |
E3C59X_REG_WAKE_ON_TIMER equ 0x8 |
E3C59X_REG_SMB_RXBYTES equ 0x7 |
E3C59X_REG_SMB_DIAG equ 0x5 |
E3C59X_REG_SMB_ARB equ 0x4 |
E3C59X_REG_SMB_STATUS equ 0x2 |
E3C59X_REG_SMB_ADDRESS equ 0x1 |
E3C59X_REG_SMB_FIFO_DATA equ 0x0 |
; Register window 0 |
E3C59X_REG_EEPROM_DATA equ 0xc |
E3C59X_REG_EEPROM_COMMAND equ 0xa |
E3C59X_REG_BIOS_ROM_DATA equ 0x8 |
E3C59X_REG_BIOS_ROM_ADDR equ 0x4 |
; Physical management bits |
E3C59X_BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData |
E3C59X_BIT_MGMT_DATA equ 1 ; MII management data bit |
E3C59X_BIT_MGMT_CLK equ 0 ; MII management clock |
; MII commands |
E3C59X_MII_CMD_MASK equ (1111b shl 10) |
E3C59X_MII_CMD_READ equ (0110b shl 10) |
E3C59X_MII_CMD_WRITE equ (0101b shl 10) |
; MII registers |
E3C59X_REG_MII_BMCR equ 0 ; basic mode control register |
E3C59X_REG_MII_BMSR equ 1 ; basic mode status register |
E3C59X_REG_MII_ANAR equ 4 ; auto negotiation advertisement register |
E3C59X_REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register |
E3C59X_REG_MII_ANER equ 6 ; auto negotiation expansion register |
; MII bits |
E3C59X_BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete |
E3C59X_BIT_MII_PREAMBLE_SUPPRESSION equ 6 |
; eeprom bits and commands |
E3C59X_EEPROM_CMD_READ equ 0x80 |
E3C59X_EEPROM_BIT_BUSY equ 15 |
; eeprom registers |
E3C59X_EEPROM_REG_OEM_NODE_ADDR equ 0xa |
E3C59X_EEPROM_REG_CAPABILITIES equ 0x10 |
; Commands for command register |
E3C59X_SELECT_REGISTER_WINDOW equ (1 shl 11) |
IS_VORTEX equ 0x1 |
IS_BOOMERANG equ 0x2 |
IS_CYCLONE equ 0x4 |
IS_TORNADO equ 0x8 |
EEPROM_8BIT equ 0x10 |
HAS_PWR_CTRL equ 0x20 |
HAS_MII equ 0x40 |
HAS_NWAY equ 0x80 |
HAS_CB_FNS equ 0x100 |
INVERT_MII_PWR equ 0x200 |
INVERT_LED_PWR equ 0x400 |
MAX_COLLISION_RESET equ 0x800 |
EEPROM_OFFSET equ 0x1000 |
HAS_HWCKSM equ 0x2000 |
EXTRA_PREAMBLE equ 0x4000 |
iglobal |
align 4 |
e3c59x_hw_versions: |
dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps |
dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex |
dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex |
dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx |
dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4 |
dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII |
dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT |
dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo |
dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO |
dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo |
dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC |
dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL |
dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx |
dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4 |
dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx |
dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC |
dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx |
dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado |
dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone |
dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone |
dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane |
dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane |
dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS \ |
or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado |
dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS \ |
or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane |
dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus |
dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus |
dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT \ |
or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus |
dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ |
or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus |
dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ |
or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus |
dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ |
or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus |
dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ |
or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus |
dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado |
dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado |
dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A |
dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B |
dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4 |
dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado |
E3C59X_HW_VERSIONS_SIZE= $-e3c59x_hw_versions |
endg |
; RX/TX buffers sizes |
E3C59X_MAX_ETH_PKT_SIZE equ 1536 ; max packet size |
E3C59X_NUM_RX_DESC equ 4 ; a power of 2 number |
E3C59X_NUM_TX_DESC equ 4 ; a power of 2 number |
E3C59X_RX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_RX_DESC) |
E3C59X_TX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_TX_DESC) |
; Download Packet Descriptor |
E3C59X_DPD_DN_NEXT_PTR equ 0 |
E3C59X_DPD_FRAME_START_HDR equ 4 |
E3C59X_DPD_DN_FRAG_ADDR equ 8 ; for packet data |
E3C59X_DPD_DN_FRAG_LEN equ 12 ; for packet data |
E3C59X_DPD_SIZE equ 16 ; a power of 2 number |
; Upload Packet Descriptor |
E3C59X_UPD_UP_NEXT_PTR equ 0 |
E3C59X_UPD_PKT_STATUS equ 4 |
E3C59X_UPD_UP_FRAG_ADDR equ 8 ; for packet data |
E3C59X_UPD_UP_FRAG_LEN equ 12 ; for packet data |
E3C59X_UPD_SIZE equ 16 |
; RX/TX buffers |
if defined E3C59X_LINUX |
E3C59X_MAX_ETH_FRAME_SIZE = 160 ; size of ethernet frame + bytes alignment |
e3c59x_rx_buff = 0 |
else |
E3C59X_MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment |
e3c59x_rx_buff = eth_data_start |
end if |
e3c59x_tx_buff = e3c59x_rx_buff+E3C59X_RX_BUFFER_SIZE |
e3c59x_dpd_buff = e3c59x_tx_buff+E3C59X_TX_BUFFER_SIZE |
e3c59x_upd_buff = e3c59x_dpd_buff+(E3C59X_DPD_SIZE*E3C59X_NUM_TX_DESC) |
uglobal |
e3c59x_curr_upd: dd 0 |
e3c59x_prev_dpd: dd 0 |
e3c59x_prev_tx_frame: dd 0 |
e3c59x_transmit_function: dd 0 |
e3c59x_receive_function: dd 0 |
endg |
iglobal |
e3c59x_ver_id: db 17 |
endg |
uglobal |
e3c59x_full_bus_master: db 0 |
e3c59x_has_hwcksm: db 0 |
e3c59x_preamble: db 0 |
e3c59x_dn_list_ptr_cleared: db 0 |
e3c59x_self_directed_packet: rb 6 |
endg |
if defined E3C59X_DEBUG |
e3c59x_hw_type_str: db "Detected hardware type : ", 0 |
e3c59x_device_str: db "Device ID : 0x" |
e3c59x_device_id_str: db "ffff", 13, 10, 0 |
e3c59x_vendor_str: db "Vendor ID : 0x" |
e3c59x_vendor_id_str: db "ffff", 13, 10, 0 |
e3c59x_io_info_str: db "IO address : 0x" |
e3c59x_io_addr_str: db "ffff", 13, 10, 0 |
e3c59x_mac_info_str: db "MAC address : " |
e3c59x_mac_addr_str: db "ff:ff:ff:ff:ff:ff", 13, 10, 0 |
e3c59x_boomerang_str: db " (boomerang)", 13, 10, 0 |
e3c59x_vortex_str: db " (vortex)", 13, 10, 0 |
e3c59x_link_type_str: db "Established link type : ", 0 |
e3c59x_new_line_str: db 13, 10, 0 |
e3c59x_link_type: dd 0 |
e3c59x_charset: db '0123456789abcdef' |
strtbl e3c59x_link_str, \ |
"No valid link type detected", \ |
"10BASE-T half duplex", \ |
"10BASE-T full-duplex", \ |
"100BASE-TX half duplex", \ |
"100BASE-TX full duplex", \ |
"100BASE-T4", \ |
"100BASE-FX", \ |
"10Mbps AUI", \ |
"10Mbps COAX (BNC)", \ |
"miiDevice - not supported" |
strtbl e3c59x_hw_str, \ |
"3c590 Vortex 10Mbps", \ |
"3c592 EISA 10Mbps Demon/Vortex", \ |
"3c597 EISA Fast Demon/Vortex", \ |
"3c595 Vortex 100baseTx", \ |
"3c595 Vortex 100baseT4", \ |
"3c595 Vortex 100base-MII", \ |
"3c900 Boomerang 10baseT", \ |
"3c900 Boomerang 10Mbps Combo", \ |
"3c900 Cyclone 10Mbps TPO", \ |
"3c900 Cyclone 10Mbps Combo", \ |
"3c900 Cyclone 10Mbps TPC", \ |
"3c900B-FL Cyclone 10base-FL", \ |
"3c905 Boomerang 100baseTx", \ |
"3c905 Boomerang 100baseT4", \ |
"3c905B Cyclone 100baseTx", \ |
"3c905B Cyclone 10/100/BNC", \ |
"3c905B-FX Cyclone 100baseFx", \ |
"3c905C Tornado", \ |
"3c980 Cyclone", \ |
"3c982 Dual Port Server Cyclone", \ |
"3cSOHO100-TX Hurricane", \ |
"3c555 Laptop Hurricane", \ |
"3c556 Laptop Tornado", \ |
"3c556B Laptop Hurricane", \ |
"3c575 [Megahertz] 10/100 LAN CardBus", \ |
"3c575 Boomerang CardBus", \ |
"3CCFE575BT Cyclone CardBus", \ |
"3CCFE575CT Tornado CardBus", \ |
"3CCFE656 Cyclone CardBus", \ |
"3CCFEM656B Cyclone+Winmodem CardBus", \ |
"3CXFEM656C Tornado+Winmodem CardBus", \ |
"3c450 HomePNA Tornado", \ |
"3c920 Tornado", \ |
"3c982 Hydra Dual Port A", \ |
"3c982 Hydra Dual Port B", \ |
"3c905B-T4", \ |
"3c920B-EMB-WNM Tornado" |
end if ; defined E3C59X_DEBUG |
;*************************************************************************** |
; Function |
; e3c59x_debug |
; Description |
; prints debug info to the debug board |
; Parameters |
; ebp - io_addr |
; Return value |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
if defined E3C59X_DEBUG |
align 4 |
e3c59x_debug: |
pushad |
; print device type |
mov esi, e3c59x_hw_type_str |
call sys_msg_board_str |
movzx ecx, byte [e3c59x_ver_id] |
mov esi, [e3c59x_hw_str+ecx*4] |
call sys_msg_board_str |
mov esi, e3c59x_boomerang_str |
cmp dword [e3c59x_transmit_function], e3c59x_boomerang_transmit |
jz .boomerang |
mov esi, e3c59x_vortex_str |
.boomerang: |
call sys_msg_board_str |
; print device/vendor |
mov ax, [pci_data+2] |
mov cl, 2 |
mov ebx, e3c59x_device_id_str |
call e3c59x_print_hex |
mov esi, e3c59x_device_str |
call sys_msg_board_str |
mov ax, [pci_data] |
mov cl, 2 |
mov ebx, e3c59x_vendor_id_str |
call e3c59x_print_hex |
mov esi, e3c59x_vendor_str |
call sys_msg_board_str |
; print io address |
mov ax, [io_addr] |
mov ebx, e3c59x_io_addr_str |
mov cl, 2 |
call e3c59x_print_hex |
mov esi, e3c59x_io_info_str |
call sys_msg_board_str |
; print MAC address |
mov ebx, e3c59x_mac_addr_str |
xor ecx, ecx |
.mac_loop: |
push ecx |
mov al, [node_addr+ecx] |
mov cl, 1 |
call e3c59x_print_hex |
inc ebx |
pop ecx |
inc cl |
cmp cl, 6 |
jne .mac_loop |
mov esi, e3c59x_mac_info_str |
call sys_msg_board_str |
; print link type |
mov esi, e3c59x_link_type_str |
call sys_msg_board_str |
xor eax, eax |
bsr ax, word [e3c59x_link_type] |
jz @f |
sub ax, 4 |
@@: |
mov esi, [e3c59x_link_str+eax*4] |
call sys_msg_board_str |
mov esi, e3c59x_new_line_str |
call sys_msg_board_str |
popad |
ret |
;*************************************************************************** |
; Function |
; e3c59x_print_hex |
; Description |
; prints a hexadecimal value |
; Parameters |
; eax - value to be printed out |
; ebx - where to print |
; cl - value size (1, 2, 4) |
; Return value |
; ebx - end address after the print |
; Destroyed registers |
; eax, ebx |
; |
;*************************************************************************** |
align 4 |
e3c59x_print_hex: |
cmp cl, 1 |
je .print_byte |
cmp cl, 2 |
jz .print_word |
.print_dword: |
push eax |
bswap eax |
xchg ah, al |
call .print_word |
pop eax |
.print_word: |
push eax |
xchg ah, al |
call .print_byte |
pop eax |
.print_byte: |
movzx eax, al |
push eax |
and al, 0xf0 |
shr al, 4 |
mov al, byte [eax+e3c59x_charset] |
mov [ebx], al |
inc ebx |
pop eax |
and al, 0x0f |
mov al, byte [eax+e3c59x_charset] |
mov [ebx], al |
inc ebx |
ret |
end if ; defined E3C59X_DEBUG |
;*************************************************************************** |
; Function |
; e3c59x_try_link_detect |
; Description |
; e3c59x_try_link_detect checks if link exists |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 ; no link detected |
; al - 1 ; link detected |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_try_link_detect: |
; download self-directed packet |
mov edi, node_addr |
mov bx, 0x0608 ; packet type |
mov esi, e3c59x_self_directed_packet |
mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes |
call dword [e3c59x_transmit_function] |
; switch to register window 5 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 |
out dx, ax |
; program RxFilter for promiscuous operation |
mov ax, (10000b shl 11) |
lea edx, [ebp+E3C59X_REG_RX_FILTER] |
in al, dx |
or al, 1111b |
lea edx, [ebp+E3C59X_REG_COMMAND] |
out dx, ax |
; switch to register window 4 |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; check loop |
xor ebx, ebx |
mov ecx, 0xffff ; 65535 tries |
.loop: |
push ecx ebx |
call dword [e3c59x_receive_function] |
pop ebx ecx |
test al, al |
jnz .finish |
.no_packet_received: |
; switch to register window 4 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; read linkbeatdetect |
lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] |
in ax, dx |
test ah, 1000b ; test linkBeatDetect |
jnz .link_detected |
xor al, al |
jmp .finish |
.link_detected: |
; test carrierSense |
test al, 100000b |
jz .no_carrier_sense |
inc ebx |
.no_carrier_sense: |
dec ecx |
jns .loop |
; assume the link is good if 0 < ebx < 25 % |
test ebx, ebx |
setnz al |
jz .finish |
cmp ebx, 16384 ; 25% |
setb al |
.finish: |
if defined E3C59X_DEBUG |
test al, al |
jz @f |
or byte [e3c59x_link_type+1], 100b |
@@: |
end if ; defined E3C59X_DEBUG |
ret |
;*************************************************************************** |
; Function |
; e3c59x_try_phy |
; Description |
; e3c59x_try_phy checks the auto-negotiation function |
; in the PHY at PHY index. It can also be extended to |
; include link detection for non-IEEE 802.3u |
; auto-negotiation devices, for instance the BCM5000. |
; Parameters |
; ah - PHY index |
; ebp - io_addr |
; Return value |
; al - 0 link is auto-negotiated |
; al - 1 no link is auto-negotiated |
; Destroyed registers |
; eax, ebx, ecx, edx, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_try_phy: |
mov al, E3C59X_REG_MII_BMCR |
push eax |
call e3c59x_mdio_read ; returns with window #4 |
or ah, 0x80 ; software reset |
mov ebx, eax |
pop eax |
push eax |
call e3c59x_mdio_write ; returns with window #4 |
; wait for reset to complete |
mov esi, 2000 ; 2000ms = 2s |
call delay_ms |
pop eax |
push eax |
call e3c59x_mdio_read ; returns with window #4 |
test ah, 0x80 |
jnz .fail_finish |
pop eax |
push eax |
; wait for a while after reset |
mov esi, 20 ; 20ms |
call delay_ms |
pop eax |
push eax |
mov al, E3C59X_REG_MII_BMSR |
call e3c59x_mdio_read ; returns with window #4 |
test al, 1 ; extended capability supported? |
jz .no_ext_cap |
; auto-neg capable? |
test al, 1000b |
jz .fail_finish ; not auto-negotiation capable |
; auto-neg complete? |
test al, 100000b |
jnz .auto_neg_ok |
; restart auto-negotiation |
pop eax |
push eax |
mov al, E3C59X_REG_MII_ANAR |
push eax |
call e3c59x_mdio_read ; returns with window #4 |
or ax, (1111b shl 5) ; advertise only 10base-T and 100base-TX |
mov ebx, eax |
pop eax |
call e3c59x_mdio_write ; returns with window #4 |
pop eax |
push eax |
call e3c59x_mdio_read ; returns with window #4 |
mov ebx, eax |
or bh, 10010b ; restart auto-negotiation |
pop eax |
push eax |
call e3c59x_mdio_write ; returns with window #4 |
mov esi, 4000 ; 4000ms = 4 seconds |
call delay_ms |
pop eax |
push eax |
mov al, E3C59X_REG_MII_BMSR |
call e3c59x_mdio_read ; returns with window #4 |
test al, 100000b ; auto-neg complete? |
jnz .auto_neg_ok |
jmp .fail_finish |
.auto_neg_ok: |
; compare advertisement and link partner ability registers |
pop eax |
push eax |
mov al, E3C59X_REG_MII_ANAR |
call e3c59x_mdio_read ; returns with window #4 |
xchg eax, [esp] |
mov al, E3C59X_REG_MII_ANLPAR |
call e3c59x_mdio_read ; returns with window #4 |
pop ebx |
and eax, ebx |
and eax, 1111100000b |
push eax |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], ax |
end if ; defined E3C59X_DEBUG |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; set full-duplex mode |
lea edx, [ebp+E3C59X_REG_MAC_CONTROL] |
in ax, dx |
and ax, not 0x120 ; clear full duplex and flow control |
pop ebx |
test ebx, (1010b shl 5) ; check for full-duplex |
jz .half_duplex |
or ax, 0x120 ; set full duplex and flow control |
.half_duplex: |
out dx, ax |
mov al, 1 |
ret |
.no_ext_cap: |
; not yet implemented BCM5000 |
.fail_finish: |
pop eax |
xor al, al |
ret |
;*************************************************************************** |
; Function |
; e3c59x_try_mii |
; Description |
; e3c59x_try_MII checks the on-chip auto-negotiation logic |
; or an off-chip MII PHY, depending upon what is set in |
; xcvrSelect by the caller. |
; It exits when it finds the first device with a good link. |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 |
; al - 1 |
; Destroyed registers |
; eax, ebx, ecx, edx, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_try_mii: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, (1111b shl 20) |
cmp eax, (1000b shl 20) ; is auto-negotiation set? |
jne .mii_device |
; auto-negotiation is set |
; switch to register window 4 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; PHY==24 is the on-chip auto-negotiation logic |
; it supports only 10base-T and 100base-TX |
mov ah, 24 |
call e3c59x_try_phy |
test al, al |
jz .fail_finish |
mov cl, 24 |
jmp .check_preamble |
.mii_device: |
cmp eax, (0110b shl 20) |
jne .fail_finish |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] |
in ax, dx |
and al, (1 shl E3C59X_BIT_MGMT_DIR) or (1 shl E3C59X_BIT_MGMT_DATA) |
cmp al, (1 shl E3C59X_BIT_MGMT_DATA) |
je .serch_for_phy |
xor al, al |
ret |
.serch_for_phy: |
; search for PHY |
mov cl, 31 |
.search_phy_loop: |
cmp cl, 24 |
je .next_phy |
mov ah, cl ; ah = phy |
mov al, E3C59X_REG_MII_BMCR ; al = Basic Mode Status Register |
push ecx |
call e3c59x_mdio_read |
pop ecx |
test ax, ax |
jz .next_phy |
cmp ax, 0xffff |
je .next_phy |
mov ah, cl ; ah = phy |
push ecx |
call e3c59x_try_phy |
pop ecx |
test al, al |
jnz .check_preamble |
.next_phy: |
dec cl |
jns .search_phy_loop |
.fail_finish: |
xor al, al |
ret |
; epilog |
.check_preamble: |
push eax ; eax contains the return value of e3c59x_try_phy |
; check hard coded preamble forcing |
movzx eax, byte [e3c59x_ver_id] |
test word [eax*4+e3c59x_hw_versions+2], EXTRA_PREAMBLE |
setnz [e3c59x_preamble] ; force preamble |
jnz .finish |
; check mii for preamble suppression |
mov ah, cl |
mov al, E3C59X_REG_MII_BMSR |
call e3c59x_mdio_read |
test al, 1000000b ; preamble suppression? |
setz [e3c59x_preamble] ; no |
.finish: |
pop eax |
ret |
;*************************************************************************** |
; Function |
; e3c59x_test_packet |
; Description |
; e3c59x_try_loopback try a loopback packet for 10BASE2 or AUI port |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 |
; al - 1 |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_test_packet: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; set fullDuplexEnable in MacControl register |
lea edx, [ebp+E3C59X_REG_MAC_CONTROL] |
in ax, dx |
or ax, 0x120 |
out dx, ax |
; switch to register window 5 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 |
out dx, ax |
; set RxFilter to enable individual address matches |
mov ax, (10000b shl 11) |
lea edx, [ebp+E3C59X_REG_RX_FILTER] |
in al, dx |
or al, 1 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
out dx, ax |
; issue RxEnable and TxEnable |
call e3c59x_rx_reset |
call e3c59x_tx_reset |
; download a self-directed test packet |
mov edi, node_addr |
mov bx, 0x0608 ; packet type |
mov esi, e3c59x_self_directed_packet |
mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes |
call dword [e3c59x_transmit_function] |
; wait for 2s |
mov esi, 2000 ; 2000ms = 2s |
call delay_ms |
; check if self-directed packet is received |
call dword [e3c59x_receive_function] |
test al, al |
jnz .finish |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; clear fullDuplexEnable in MacControl register |
lea edx, [ebp+E3C59X_REG_MAC_CONTROL] |
in ax, dx |
and ax, not 0x120 |
out dx, ax |
xor al, al |
.finish: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_try_loopback |
; Description |
; tries a loopback packet for 10BASE2 or AUI port |
; Parameters |
; al - 0: 10Mbps AUI connector |
; 1: 10BASE-2 |
; ebp - io_addr |
; Return value |
; al - 0 |
; al - 1 |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_try_loopback: |
push eax |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
pop eax |
push eax |
if defined E3C59X_DEBUG |
mov bl, al |
inc bl |
shl bl, 3 |
or byte [e3c59x_link_type+1], bl |
end if ; defined E3C59X_DEBUG |
test al, al ; aui or coax? |
jz .complete_loopback |
; enable 100BASE-2 DC-DC converter |
mov ax, (10b shl 11) ; EnableDcConverter |
out dx, ax |
.complete_loopback: |
mov cl, 2 ; give a port 3 chances to complete a loopback |
.next_try: |
push ecx |
call e3c59x_test_packet |
pop ecx |
test al, al |
jnz .finish |
dec cl |
jns .next_try |
.finish: |
xchg eax, [esp] |
test al, al |
jz .aui_finish |
; issue DisableDcConverter command |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10111b shl 11) |
out dx, ax |
.aui_finish: |
pop eax ; al contains the result of operation |
if defined E3C59X_DEBUG |
test al, al |
jnz @f |
and byte [e3c59x_link_type+1], not 11000b |
@@: |
end if ; defined E3C59X_DEBUG |
ret |
;*************************************************************************** |
; Function |
; e3c59x_set_available_media |
; Description |
; sets the first available media |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 |
; al - 1 |
; Destroyed registers |
; eax, edx |
; |
;*************************************************************************** |
align 4 |
e3c59x_set_available_media: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
push eax |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx |
test al, 10b |
jz @f |
; baseTXAvailable |
pop eax |
and eax, not (1111b shl 20) |
or eax, (100b shl 20) |
if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD |
mov word [e3c59x_link_type], (1 shl 8) |
else if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 7) |
end if |
jmp .set_media |
@@: |
test al, 100b |
jz @f |
; baseFXAvailable |
pop eax |
and eax, not (1111b shl 20) |
or eax, (101b shl 20) |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 10) |
end if |
jmp .set_media |
@@: |
test al, 1000000b |
jz @f |
; miiDevice |
pop eax |
and eax, not (1111b shl 20) |
or eax, (0110b shl 20) |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 13) |
end if |
jmp .set_media |
@@: |
test al, 1000b |
jz @f |
.set_default: |
; 10bTAvailable |
pop eax |
and eax, not (1111b shl 20) |
if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD |
mov word [e3c59x_link_type], (1 shl 6) |
else if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 5) |
end if ; E3C59X_FORCE_FD |
jmp .set_media |
@@: |
test al, 10000b |
jz @f |
; coaxAvailable |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10b shl 11) ; EnableDcConverter |
out dx, ax |
pop eax |
and eax, not (1111b shl 20) |
or eax, (11b shl 20) |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 12) |
end if ; defined E3C59X_DEBUG |
jmp .set_media |
@@: |
test al, 10000b |
jz .set_default |
; auiAvailable |
pop eax |
and eax, not (1111b shl 20) |
or eax, (1 shl 20) |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 11) |
end if ; defined E3C59X_DEBUG |
.set_media: |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
out dx, eax |
if defined E3C59X_FORCE_FD |
; set fullDuplexEnable in MacControl register |
lea edx, [ebp+E3C59X_REG_MAC_CONTROL] |
in ax, dx |
or ax, 0x120 |
out dx, ax |
end if ; E3C59X_FORCE_FD |
mov al, 1 |
ret |
;*************************************************************************** |
; Function |
; e3c59x_set_active_port |
; Description |
; It selects the media port (transceiver) to be used |
; Parameters: |
; ebp - io_addr |
; Return value: |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_set_active_port: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
test eax, (1 shl 24) ; check if autoselect enable |
jz .set_first_available_media |
; check 100BASE-TX and 10BASE-T |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx |
test al, 1010b ; check whether 100BASE-TX or 10BASE-T available |
jz .mii_device ; they are not available |
; set auto-negotiation |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (1000b shl 20) |
out dx, eax |
call e3c59x_try_mii |
test al, al |
jz .mii_device |
ret |
.mii_device: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; check for off-chip mii device |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx |
test al, 1000000b ; check miiDevice |
jz .base_fx |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (0110b shl 20) ; set MIIDevice |
out dx, eax |
call e3c59x_try_mii |
test al, al |
jz .base_fx |
ret |
.base_fx: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; check for 100BASE-FX |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx ; read media option register |
test al, 100b ; check 100BASE-FX |
jz .aui_enable |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (0101b shl 20) ; set 100base-FX |
out dx, eax |
call e3c59x_try_link_detect |
test al, al |
jz .aui_enable |
ret |
.aui_enable: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; check for 10Mbps AUI connector |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx ; read media option register |
test al, 100000b ; check 10Mbps AUI connector |
jz .coax_available |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (0001b shl 20) ; set 10Mbps AUI connector |
out dx, eax |
xor al, al ; try 10Mbps AUI connector |
call e3c59x_try_loopback |
test al, al |
jz .coax_available |
ret |
.coax_available: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; check for coaxial 10BASE-2 port |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx ; read media option register |
test al, 10000b ; check 10BASE-2 |
jz .set_first_available_media |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (0011b shl 20) ; set 10BASE-2 |
out dx, eax |
mov al, 1 |
call e3c59x_try_loopback |
test al, al |
jz .set_first_available_media |
ret |
.set_first_available_media: |
jmp e3c59x_set_available_media |
;*************************************************************************** |
; Function |
; e3c59x_wake_up |
; Description |
; set the power state to D0 |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_wake_up: |
; wake up - we directly do it by programming PCI |
; check if the device is power management capable |
mov al, 2 |
mov ah, [pci_bus] |
mov bl, PCI_REG_STATUS |
mov bh, [pci_dev] |
push eax ebx |
call pci_read_reg |
test al, 10000b ; is there "new capabilities" linked list? |
pop ebx eax |
jz .device_awake |
; search for power management register |
mov al, 1 |
mov bl, PCI_REG_CAP_PTR |
push eax ebx |
call pci_read_reg |
mov cl, al |
cmp cl, 0x3f |
pop ebx eax |
jbe .device_awake |
; traverse the list |
mov al, 2 |
.pm_loop: |
mov bl, cl |
push eax ebx |
call pci_read_reg |
cmp al, 1 |
je .set_pm_state |
test ah, ah |
mov cl, ah |
pop ebx eax |
jnz .pm_loop |
jmp .device_awake |
; waku up the device if necessary |
.set_pm_state: |
pop ebx eax |
add bl, PCI_REG_PM_CTRL |
push eax ebx |
call pci_read_reg |
mov cx, ax |
test cl, 3 |
pop ebx eax |
jz .device_awake |
and cl, not 11b ; set state to D0 |
call pci_write_reg |
.device_awake: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_probe: |
movzx ebp, word [io_addr] |
mov al, 2 |
mov ah, [pci_bus] |
mov bh, [pci_dev] |
mov bl, PCI_REG_COMMAND |
push ebp eax ebx |
call pci_read_reg |
mov cx, ax |
or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) |
and cl, not (1 shl PCI_BIT_MMIO) |
pop ebx eax |
call pci_write_reg |
; wake up the card |
call e3c59x_wake_up |
pop ebp |
; get chip version |
mov ax, [pci_data+2] |
mov ecx, E3C59X_HW_VERSIONS_SIZE/4-1 |
.chip_ver_loop: |
cmp ax, [e3c59x_hw_versions+ecx*4] |
jz .chip_ver_found |
dec ecx |
jns .chip_ver_loop |
xor ecx, ecx |
.chip_ver_found: |
mov [e3c59x_ver_id], cl |
test word [e3c59x_hw_versions+2+ecx*4], HAS_HWCKSM |
setnz [e3c59x_has_hwcksm] |
; set pci latency for vortex cards |
test word [e3c59x_hw_versions+2+ecx*4], IS_VORTEX |
jz .not_vortex |
mov cx, 11111000b ; 248 = max latency |
mov al, 1 |
mov ah, [pci_bus] |
mov bl, PCI_REG_LATENCY |
mov bh, [pci_dev] |
call pci_write_reg |
.not_vortex: |
; set RX/TX functions |
mov ax, E3C59X_EEPROM_REG_CAPABILITIES |
call e3c59x_read_eeprom |
test al, 100000b ; full bus master? |
setnz [e3c59x_full_bus_master] |
jnz .boomerang_func |
mov dword [e3c59x_transmit_function], e3c59x_vortex_transmit |
mov dword [e3c59x_receive_function], e3c59x_vortex_poll |
jmp @f |
.boomerang_func: ; full bus master, so use boomerang functions |
mov dword [e3c59x_transmit_function], e3c59x_boomerang_transmit |
mov dword [e3c59x_receive_function], e3c59x_boomerang_poll |
@@: |
; read MAC from eeprom |
mov ecx, 2 |
.mac_loop: |
lea ax, [E3C59X_EEPROM_REG_OEM_NODE_ADDR+ecx] |
call e3c59x_read_eeprom |
xchg ah, al ; htons |
mov [node_addr+ecx*2], ax |
dec ecx |
jns .mac_loop |
test byte [e3c59x_full_bus_master], 0xff |
jz .set_preamble |
; switch to register window 2 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 |
out dx, ax |
; activate xcvr by setting some magic bits |
lea edx, [ebp+E3C59X_REG_RESET_OPTIONS] |
in ax, dx |
and ax, not 0x4010 |
movzx ebx, byte [e3c59x_ver_id] |
test word [ebx*4+e3c59x_hw_versions+2], INVERT_LED_PWR |
jz @f |
or al, 0x10 |
@@: |
test word [ebx*4+e3c59x_hw_versions+2], INVERT_MII_PWR |
jz @f |
or ah, 0x40 |
@@: |
out dx, ax |
.set_preamble: |
; use preamble as default |
mov byte [e3c59x_preamble], 1 ; enable preamble |
;*************************************************************************** |
; Function |
; e3c59x_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
e3c59x_reset: |
; issue global reset |
call e3c59x_global_reset |
; disable interrupts |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (1110b shl 11) |
out dx, ax |
; enable Statistics |
mov ax, (10101b shl 11) |
out dx, ax |
; set indication |
mov ax, (1111b shl 11) or 0x6c6 |
out dx, ax |
; acknowledge (clear) every interrupt indicator |
mov ax, (1101b shl 11) or 0x661 |
out dx, ax |
; switch to register window 2 |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 |
out dx, ax |
; write MAC addres back into the station address registers |
lea edx, [ebp+E3C59X_REG_STATION_ADDRESS_LO] |
mov esi, node_addr |
cld |
outsw |
add edx, 2 |
outsw |
add edx, 2 |
outsw |
add edx, 2 |
; clear station mask |
xor eax, eax |
out dx, ax |
add edx, 2 |
out dx, ax |
add edx, 2 |
out dx, ax |
; switch to register window 6 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+6 |
out dx, ax |
; clear all statistics by reading |
lea edx, [ebp+E3C59X_REG_CARRIER_LOST] |
mov cl, 9 |
.stat_clearing_loop: |
in al, dx |
inc edx |
dec cl |
jns .stat_clearing_loop |
in ax, dx |
add dx, 2 |
in ax, dx |
; switch to register window 4 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; clear BadSSD |
lea edx, [ebp+E3C59X_REG_BAD_SSD] |
in al, dx |
; clear extra statistics bit in NetworkDiagnostic |
lea edx, [ebp+E3C59X_REG_NETWORK_DIAGNOSTIC] |
in ax, dx |
or ax, 0x0040 |
out dx, ax |
; SetRxEarlyThreshold |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10001b shl 11)+(E3C59X_MAX_ETH_PKT_SIZE shr 2) |
out dx, ax |
test byte [e3c59x_full_bus_master], 0xff |
jz .skip_boomerang_setting |
; set upRxEarlyEnable |
lea edx, [ebp+E3C59X_REG_DMA_CTRL] |
in eax, dx |
or eax, 0x20 |
out dx, eax |
; TxFreeThreshold |
lea edx, [ebp+E3C59X_REG_TX_FREE_THRESH] |
mov al, (E3C59X_MAX_ETH_PKT_SIZE / 256) |
out dx, al |
; program DnListPtr |
lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] |
xor eax, eax |
out dx, eax |
.skip_boomerang_setting: |
; initialization |
call e3c59x_rx_reset |
call e3c59x_tx_reset |
call e3c59x_set_active_port |
call e3c59x_rx_reset |
call e3c59x_tx_reset |
; switch to register window 5 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 |
out dx, ax |
; program RxFilter for promiscuous operation |
mov ax, (10000b shl 11) |
lea edx, [ebp+E3C59X_REG_RX_FILTER] |
in al, dx |
or al, 1111b |
lea edx, [ebp+E3C59X_REG_COMMAND] |
out dx, ax |
; switch to register window 4 |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; wait for linkDetect |
lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] |
mov cl, 20 ; wait for max 2s |
mov esi, 100 ; 100ms |
.link_detect_loop: |
call delay_ms |
in ax, dx |
test ah, 1000b ; linkDetect |
jnz @f |
dec cl |
jnz .link_detect_loop |
@@: |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
if defined E3C59X_DEBUG |
call e3c59x_debug |
end if ; defined E3C59X_DEBUG |
ret |
;*************************************************************************** |
; Function |
; e3c59x_global_reset |
; Description |
; resets the device |
; Parameters: |
; ebp - io_addr |
; Return value: |
; Destroyed registers |
; ax, ecx, edx, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_global_reset: |
; GlobalReset |
lea edx, [ebp+E3C59X_REG_COMMAND] |
xor eax, eax |
; or al, 0x14 |
out dx, ax |
; wait for GlobalReset to complete |
mov ecx, 64000 |
.global_reset_loop: |
in ax, dx |
test ah, 10000b ; check CmdInProgress |
jz .finish |
dec ecx |
jnz .global_reset_loop |
.finish: |
; wait for 2 seconds for NIC to boot |
mov esi, 2000 ; 2000ms = 2s |
push ebp |
call delay_ms |
pop ebp |
ret |
;*************************************************************************** |
; Function |
; e3c59x_tx_reset |
; Description |
; resets and enables transmitter engine |
; Parameters: |
; ebp - io_addr |
; Return value: |
; Destroyed registers |
; ax, ecx, edx |
; |
;*************************************************************************** |
align 4 |
e3c59x_tx_reset: |
; TxReset |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (01011b shl 11) |
out dx, ax |
; Wait for TxReset to complete |
mov ecx, 200000 |
.tx_reset_loop: |
in ax, dx |
test ah, 10000b ; check CmdInProgress |
jz .tx_set_prev |
dec ecx |
jns .tx_reset_loop |
.tx_set_prev: |
test byte [e3c59x_full_bus_master], 0xff |
jz .tx_enable |
; init last_dpd |
mov dword [e3c59x_prev_dpd], e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE |
mov dword [e3c59x_prev_tx_frame], e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE |
.tx_enable: |
mov ax, (01001b shl 11) ; TxEnable |
out dx, ax |
ret |
;*************************************************************************** |
; Function |
; e3c59x_rx_reset |
; Description |
; resets and enables receiver engine |
; Parameters: |
; ebp - io_addr |
; Return value: |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_rx_reset: |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (0101b shl 11) or 0x4 ; RxReset |
out dx, ax |
; wait for RxReset to complete |
mov ecx, 200000 |
.rx_reset_loop: |
in ax, dx |
test ah, 10000b ; check CmdInProgress |
jz .setup_upd |
dec ecx |
jns .rx_reset_loop |
.setup_upd: |
; check if full bus mastering |
test byte [e3c59x_full_bus_master], 0xff |
jz .rx_enable |
; create upd ring |
mov eax, e3c59x_upd_buff |
zero_to_virt eax |
mov [e3c59x_curr_upd], eax |
mov esi, eax |
virt_to_dma esi |
mov edi, e3c59x_rx_buff |
zero_to_dma edi |
mov ebx, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE |
zero_to_virt ebx |
mov cl, E3C59X_NUM_RX_DESC-1 |
.upd_loop: |
mov [ebx+E3C59X_UPD_UP_NEXT_PTR], esi |
and dword [eax+E3C59X_UPD_PKT_STATUS], 0 |
mov [eax+E3C59X_UPD_UP_FRAG_ADDR], edi |
mov dword [eax+E3C59X_UPD_UP_FRAG_LEN], E3C59X_MAX_ETH_FRAME_SIZE or (1 shl 31) |
add edi, E3C59X_MAX_ETH_FRAME_SIZE |
add esi, E3C59X_UPD_SIZE |
mov ebx, eax |
add eax, E3C59X_UPD_SIZE |
dec cl |
jns .upd_loop |
mov eax, e3c59x_upd_buff |
zero_to_dma eax |
lea edx, [ebp+E3C59X_REG_UP_LIST_PTR] |
out dx, eax ; write E3C59X_REG_UP_LIST_PTR |
lea edx, [ebp+E3C59X_REG_COMMAND] |
.rx_enable: |
mov ax, (00100b shl 11) ; RxEnable |
out dx, ax |
ret |
;*************************************************************************** |
; Function |
; e3c59x_write_eeprom |
; Description |
; reads eeprom |
; Note : the caller must switch to the register window 0 |
; before calling this function |
; Parameters: |
; ax - register to be read (only the first 63 words can be read) |
; cx - value to be read into the register |
; Return value: |
; ax - word read |
; Destroyed registers |
; ax, ebx, edx |
; |
;*************************************************************************** |
; align 4 |
;e3c59x_write_eeprom: |
; mov edx, [io_addr] |
; add edx, E3C59X_REG_EEPROM_COMMAND |
; cmp ah, 11b |
; ja .finish ; address may have a value of maximal 1023 |
; shl ax, 2 |
; shr al, 2 |
; push eax |
;; wait for busy |
; mov ebx, 0xffff |
;@@: |
; in ax, dx |
; test ah, 0x80 |
; jz .write_enable |
; dec ebx |
; jns @r |
;; write enable |
;.write_enable: |
; xor eax, eax |
; mov eax, (11b shl 4) |
; out dx, ax |
;; wait for busy |
; mov ebx, 0xffff |
;@@: |
; in ax, dx |
; test ah, 0x80 |
; jz .erase_loop |
; dec ebx |
; jns @r |
;.erase_loop: |
; pop eax |
; push eax |
; or ax, (11b shl 6) ; erase register |
; out dx, ax |
; mov ebx, 0xffff |
;@@: |
; in ax, dx |
; test ah, 0x80 |
; jz .write_reg |
; dec ebx |
; jns @r |
;.write_reg: |
; add edx, E3C59X_REG_EEPROM_DATA-E3C59X_REG_EEPROM_COMMAND |
; mov eax, ecx |
; out dx, ax |
;; write enable |
; add edx, E3C59X_REG_EEPROM_COMMAND-E3C59X_REG_EEPROM_DATA |
; xor eax, eax |
; mov eax, (11b shl 4) |
; out dx, ax |
; wait for busy |
; mov ebx, 0xffff |
;@@: |
; in ax, dx |
; test ah, 0x80 |
; jz .issue_write_reg |
; dec ebx |
; jns @r |
;.issue_write_reg: |
; pop eax |
; or ax, 01b shl 6 |
; out dx, ax |
;.finish: |
; ret |
;*************************************************************************** |
; Function |
; e3c59x_read_eeprom |
; Description |
; reads eeprom |
; Parameters: |
; ax - register to be read (only the first 63 words can be read) |
; ebp - io_addr |
; Return value: |
; ax - word read |
; Destroyed registers |
; ax, ebx, edx, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_read_eeprom: |
push eax |
; switch to register window 0 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+0 |
out dx, ax |
pop eax |
and ax, 111111b ; take only the first 6 bits into account |
movzx ebx, byte [e3c59x_ver_id] |
test word [ebx*4+e3c59x_hw_versions+2], EEPROM_8BIT |
jz @f |
add ax, 0x230 ; hardware constant |
jmp .read |
@@: |
add ax, E3C59X_EEPROM_CMD_READ |
test word [ebx*4+e3c59x_hw_versions+2], EEPROM_OFFSET |
jz .read |
add ax, 0x30 |
.read: |
lea edx, [ebp+E3C59X_REG_EEPROM_COMMAND] |
out dx, ax |
mov ebx, 0xffff ; duration of about 162 us ;-) |
.wait_for_reading: |
in ax, dx |
test ah, 0x80 ; check bit eepromBusy |
jz .read_data |
dec ebx |
jns .wait_for_reading |
.read_data: |
lea edx, [ebp+E3C59X_REG_EEPROM_DATA] |
in ax, dx |
ret |
;*************************************************************************** |
; Function |
; e3c59x_mdio_sync |
; Description |
; initial synchronization |
; Parameters |
; ebp - io_addr |
; Return value |
; Destroyed registers |
; ax, edx, cl |
; |
;*************************************************************************** |
align 4 |
e3c59x_mdio_sync: |
; switch to register window 4 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
cmp byte [e3c59x_preamble], 0 |
je .no_preamble |
; send 32 logic ones |
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] |
mov cl, 31 |
.loop: |
mov ax, (1 shl E3C59X_BIT_MGMT_DATA) or (1 shl E3C59X_BIT_MGMT_DIR) |
out dx, ax |
in ax, dx ; delay |
mov ax, (1 shl E3C59X_BIT_MGMT_DATA) \ |
or (1 shl E3C59X_BIT_MGMT_DIR) \ |
or (1 shl E3C59X_BIT_MGMT_CLK) |
out dx, ax |
in ax, dx ; delay |
dec cl |
jns .loop |
.no_preamble: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_mdio_read |
; Description |
; read MII register |
; see page 16 in D83840A.pdf |
; Parameters |
; ah - PHY addr |
; al - register addr |
; ebp - io_addr |
; Return value |
; ax - register read |
; Destroyed registers |
; eax, ebx, cx, edx |
; |
;*************************************************************************** |
align 4 |
e3c59x_mdio_read: |
push eax |
call e3c59x_mdio_sync ; returns with window #4 |
pop eax |
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] |
shl al, 3 |
shr ax, 3 |
and ax, not E3C59X_MII_CMD_MASK |
or ax, E3C59X_MII_CMD_READ |
mov ebx, eax |
xor ecx, ecx |
mov cl, 13 |
.cmd_loop: |
mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii |
bt ebx, ecx |
jnc .zero_bit |
or al, (1 shl E3C59X_BIT_MGMT_DATA) |
.zero_bit: |
out dx, ax |
push eax |
in ax, dx ; delay |
pop eax |
or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write |
out dx, ax |
in ax, dx ; delay |
dec cl |
jns .cmd_loop |
; read data (18 bits with the two transition bits) |
mov cl, 17 |
xor ebx, ebx |
.read_loop: |
shl ebx, 1 |
xor eax, eax ; read comand |
out dx, ax |
in ax, dx ; delay |
in ax, dx |
test al, (1 shl E3C59X_BIT_MGMT_DATA) |
jz .dont_set |
inc ebx |
.dont_set: |
mov ax, (1 shl E3C59X_BIT_MGMT_CLK) |
out dx, ax |
in ax, dx ; delay |
dec cl |
jns .read_loop |
mov eax, ebx |
ret |
;*************************************************************************** |
; Function |
; e3c59x_mdio_write |
; Description |
; write MII register |
; see page 16 in D83840A.pdf |
; Parameters |
; ah - PHY addr |
; al - register addr |
; bx - word to be written |
; ebp - io_addr |
; Return value |
; ax - register read |
; Destroyed registers |
; eax, ebx, cx, edx |
; |
;*************************************************************************** |
align 4 |
e3c59x_mdio_write: |
push eax |
call e3c59x_mdio_sync |
pop eax |
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] |
shl al, 3 |
shr ax, 3 |
and ax, not E3C59X_MII_CMD_MASK |
or ax, E3C59X_MII_CMD_WRITE |
shl eax, 2 |
or eax, 10b ; transition bits |
shl eax, 16 |
mov ax, bx |
mov ebx, eax |
mov ecx, 31 |
.cmd_loop: |
mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii |
bt ebx, ecx |
jnc .zero_bit |
or al, (1 shl E3C59X_BIT_MGMT_DATA) |
.zero_bit: |
out dx, ax |
push eax |
in ax, dx ; delay |
pop eax |
or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write |
out dx, ax |
in ax, dx ; delay |
dec ecx |
jns .cmd_loop |
ret |
;*************************************************************************** |
; Function |
; e3c59x_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; edi - Pointer to 48 bit destination address |
; bx - Type of packet |
; ecx - size of packet |
; esi - pointer to packet data |
; ebp - io_addr |
; Destroyed registers |
; eax, ecx, edx, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_transmit: |
jmp dword [e3c59x_transmit_function] |
;*************************************************************************** |
; Function |
; e3c59x_check_tx_status |
; Description |
; Checks TxStatus queue. |
; Return value |
; al - 0 no error was found |
; al - 1 error was found TxReset is needed |
; Destroyed registers |
; eax, ecx, edx, ebp |
; |
;*************************************************************************** |
e3c59x_check_tx_status: |
movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC |
; clear TxStatus queue |
lea edx, [ebp+E3C59X_REG_TX_STATUS] |
mov cl, 31 ; max number of queue entries |
.tx_status_loop: |
in al, dx |
test al, al |
jz .finish ; no error |
test al, 0x3f |
jnz .finish ; error |
.no_error_found: |
; clear current TxStatus entry which advances the next one |
xor al, al |
out dx, al |
dec cl |
jns .tx_status_loop |
.finish: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_vortex_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; edi - Pointer to 48 bit destination address |
; bx - Type of packet |
; ecx - size of packet |
; esi - pointer to packet data |
; ebp - io_addr |
; Destroyed registers |
; eax, edx, ecx, edi, esi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_vortex_transmit: |
push ecx |
call e3c59x_check_tx_status |
pop ecx |
test al, al |
jz .no_error_found |
jmp e3c59x_tx_reset |
.no_error_found: |
; switch to register window 7 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 |
out dx, ax |
; check for master operation in progress |
lea edx, [ebp+E3C59X_REG_MASTER_STATUS] |
in ax, dx |
test ah, 0x80 |
jnz .finish ; no DMA for sending |
; dword boundary correction |
cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE |
ja .finish ; packet is too long |
; write Frame Start Header |
mov eax, ecx |
; add header length and extend the complete length to dword boundary |
add eax, ETH_HLEN+3 |
and eax, not 3 |
lea edx, [ebp+E3C59X_REG_TX_DATA] |
out dx, eax |
; prepare the complete frame |
push esi |
mov esi, edi |
mov edi, e3c59x_tx_buff |
zero_to_virt edi |
cld |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi, node_addr |
movsd |
movsw |
; copy packet type |
mov [edi], bx |
add edi, 2 |
; copy packet data |
pop esi |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
mov ecx, eax |
; program frame address to be sent |
lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] |
mov eax, e3c59x_tx_buff |
zero_to_dma eax |
out dx, eax |
; program frame length |
lea edx, [ebp+E3C59X_REG_MASTER_LEN] |
mov eax, ecx |
out dx, ax |
; start DMA Down |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10100b shl 11) + 1 ; StartDMADown |
out dx, ax |
.finish: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_boomerang_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; edi - Pointer to 48 bit destination address |
; bx - Type of packet |
; ecx - size of packet |
; esi - pointer to packet data |
; ebp - io_addr |
; Destroyed registers |
; eax, ebx, ecx, edx, esi, edi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_boomerang_transmit: |
push ecx |
call e3c59x_check_tx_status |
pop ecx |
test al, al |
jz .no_error_found |
jmp e3c59x_tx_reset |
.no_error_found: |
cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE |
ja .finish ; packet is too long |
; calculate descriptor address |
mov eax, [e3c59x_prev_dpd] |
cmp eax, e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE |
jb @f |
; wrap around |
mov eax, e3c59x_dpd_buff-E3C59X_DPD_SIZE |
@@: |
add eax, E3C59X_DPD_SIZE |
zero_to_virt eax |
push eax |
; check DnListPtr |
lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] |
in eax, dx |
; mark if Dn_List_Ptr is cleared |
test eax, eax |
setz [e3c59x_dn_list_ptr_cleared] |
; finish if no more free descriptor is available - FIXME! |
cmp eax, [esp] |
pop eax |
jz .finish |
push eax esi |
mov esi, edi |
; calculate tx_buffer address |
mov edi, [e3c59x_prev_tx_frame] |
cmp edi, e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE |
jb @f |
; wrap around |
mov edi, e3c59x_tx_buff-E3C59X_MAX_ETH_FRAME_SIZE |
@@: |
add edi, E3C59X_MAX_ETH_FRAME_SIZE |
zero_to_virt edi |
mov eax, edi |
cld |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi, node_addr |
movsd |
movsw |
; copy packet type |
mov [edi], bx |
add edi, 2 |
; copy packet data |
pop esi |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
push ecx |
and ecx, 3 |
rep movsb |
; padding, do we really need it? |
pop ecx |
add ecx, ETH_HLEN |
cmp ecx, ETH_ZLEN |
jae @f |
mov ecx, ETH_ZLEN |
@@: |
; calculate |
mov ebx, ecx |
;test byte [e3c59x_has_hwcksm], 0xff |
;jz @f |
;or ebx, (1 shl 26) ; set AddTcpChecksum |
;@@: |
or ebx, 0x8000 ; transmission complete notification |
or ecx, 0x80000000 ; last fragment |
; program DPD |
mov edi, eax |
pop eax |
and dword [eax+E3C59X_DPD_DN_NEXT_PTR], 0 |
mov dword [eax+E3C59X_DPD_FRAME_START_HDR], ebx |
virt_to_dma edi |
mov dword [eax+E3C59X_DPD_DN_FRAG_ADDR], edi |
mov [eax+E3C59X_DPD_DN_FRAG_LEN], ecx |
; calculate physical address |
virt_to_dma eax |
push eax |
cmp byte [e3c59x_dn_list_ptr_cleared], 0 |
jz .add_to_list |
; write Dn_List_Ptr |
out dx, eax |
jmp .finish |
.add_to_list: |
; DnStall |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, ((110b shl 11)+2) |
out dx, ax |
; wait for DnStall to complete |
mov ecx, 6000 |
.wait_for_stall: |
in ax, dx ; read E3C59X_REG_INT_STATUS |
test ah, 10000b |
jz .dnstall_ok |
dec ecx |
jnz .wait_for_stall |
.dnstall_ok: |
pop eax |
push eax |
mov ebx, [e3c59x_prev_dpd] |
zero_to_virt ebx |
mov [ebx], eax |
lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] |
in eax, dx |
test eax, eax |
jnz .dnunstall |
; if Dn_List_Ptr has been cleared fill it up |
pop eax |
push eax |
out dx, eax |
.dnunstall: |
; DnUnStall |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, ((110b shl 11)+3) |
out dx, ax |
.finish: |
pop eax |
dma_to_zero eax |
mov [e3c59x_prev_dpd], eax |
dma_to_zero edi |
mov [e3c59x_prev_tx_frame], edi |
ret |
;*************************************************************************** |
; Function |
; e3c59x_poll |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Destroyed registers |
; eax, ebx, edx, ecx, edi, esi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_poll: |
jmp dword [e3c59x_receive_function] |
;*************************************************************************** |
; Function |
; e3c59x_vortex_poll |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 ; no packet received |
; al - 1 ; packet received |
; Destroyed registers |
; eax, ebx, edx, ecx, edi, esi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_vortex_poll: |
and word [eth_rx_data_len], 0 ; assume no packet received |
movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC |
.rx_status_loop: |
; examine RxStatus |
lea edx, [ebp+E3C59X_REG_RX_STATUS] |
in ax, dx |
test ax, ax |
jz .finish |
test ah, 0x80 ; rxIncomplete |
jz .check_error |
jmp .finish |
.check_error: |
test ah, 0x40 |
jz .check_length |
; discard the top frame received advancing the next one |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (01000b shl 11) |
out dx, ax |
jmp .rx_status_loop |
.check_length: |
and eax, 0x1fff |
cmp eax, E3C59X_MAX_ETH_PKT_SIZE |
ja .discard_frame ; frame is too long discard it |
.check_dma: |
push eax |
; switch to register window 7 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 |
out dx, ax |
; check for master operation in progress |
lea edx, [ebp+E3C59X_REG_MASTER_STATUS] |
in ax, dx |
test ah, 0x80 |
jz .read_frame ; no DMA for receiving |
pop eax |
jmp .finish |
.read_frame: |
; program buffer address to read in |
lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] |
if defined E3C59X_LINUX |
mov eax, e3c59x_rx_buff |
zero_to_dma eax |
else |
mov eax, Ether_buffer |
end if |
out dx, eax |
; program frame length |
lea edx, [ebp+E3C59X_REG_MASTER_LEN] |
mov ax, 1560 |
out dx, ax |
; start DMA Up |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10100b shl 11) ; StartDMAUp |
out dx, ax |
; check for master operation in progress |
.dma_loop: |
lea edx, [ebp+E3C59X_REG_MASTER_STATUS] |
in ax, dx |
test ah, 0x80 |
jnz .dma_loop |
; registrate the received packet length |
pop eax |
mov word [eth_rx_data_len], ax |
; discard the top frame received |
.discard_frame: |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (01000b shl 11) |
out dx, ax |
.finish: |
; set return value |
cmp word [eth_rx_data_len], 0 |
setne al |
ret |
;*************************************************************************** |
; Function |
; e3c59x_boomerang_poll |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 ; no packet received |
; al - 1 ; packet received |
; Destroyed registers |
; eax, edx, ecx, edi, esi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_boomerang_poll: |
and word [eth_rx_data_len], 0 ; assume no packet received |
movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC |
; check if packet is uploaded |
mov eax, [e3c59x_curr_upd] |
test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x80 ; upPktComplete |
jnz .check_error |
jmp .finish |
; packet is uploaded check for any error |
.check_error: |
test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x40 ; upError |
jz .copy_packet_length |
and dword [eax+E3C59X_UPD_PKT_STATUS], 0 |
jmp .finish |
.copy_packet_length: |
mov ecx, [eax+E3C59X_UPD_PKT_STATUS] |
and ecx, 0x1fff |
cmp ecx, E3C59X_MAX_ETH_PKT_SIZE |
jbe .copy_packet |
and dword [eax+E3C59X_UPD_PKT_STATUS], 0 |
jmp .finish |
.copy_packet: |
push ecx |
mov word [eth_rx_data_len], cx |
mov esi, [eax+E3C59X_UPD_UP_FRAG_ADDR] |
dma_to_virt esi |
mov edi, Ether_buffer |
shr ecx, 2 ; first copy dword-wise |
cld |
rep movsd ; copy the dwords |
pop ecx |
and ecx, 3 |
rep movsb ; copy the rest bytes |
mov eax, [e3c59x_curr_upd] |
and dword [eax+E3C59X_UPD_PKT_STATUS], 0 |
virt_to_zero eax |
cmp eax, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE |
jb .no_wrap |
; wrap around |
mov eax, e3c59x_upd_buff-E3C59X_UPD_SIZE |
.no_wrap: |
add eax, E3C59X_UPD_SIZE |
zero_to_virt eax |
mov [e3c59x_curr_upd], eax |
.finish: |
; check if the NIC is in the upStall state |
lea edx, [ebp+E3C59X_REG_UP_PKT_STATUS] |
in eax, dx |
test ah, 0x20 ; UpStalled |
jz .noUpUnStall |
; issue upUnStall command |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, ((110b shl 11)+1) ; upUnStall |
out dx, ax |
.noUpUnStall: |
; set return value |
cmp word [eth_rx_data_len], 0 |
setnz al |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;; Copyright (c) 2004, Endre Kozma <endre.kozma@axelero.hu> |
;; All rights reserved. |
;; |
;; Redistribution and use in source and binary forms, with or without |
;; modification, are permitted provided that the following conditions are |
;; met: |
;; |
;; 1. Redistributions of source code must retain the above copyright notice, |
;; this list of conditions and the following disclaimer. |
;; |
;; 2. Redistributions in binary form must reproduce the above copyright |
;; notice, this list of conditions and the following disclaimer in the |
;; documentation and/or other materials provided with the distribution. |
;; |
;; 3. The name of the author may not be used to endorse or promote products |
;; derived from this software without specific prior written permission. |
;; |
;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 3C59X.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Driver for 3Com fast etherlink 3c59x and ;; |
;; etherlink XL 3c900 and 3c905 cards ;; |
;; References: ;; |
;; www.3Com.com - data sheets ;; |
;; DP83840A.pdf - ethernet physical layer ;; |
;; 3c59x.c - linux driver ;; |
;; ethernet driver template by Mike Hibbett ;; |
;; ;; |
;; Credits ;; |
;; Mike Hibbett, ;; |
;; who kindly supplied me with a 3Com905C-TX-M card ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; History |
;; ======= |
;; $Log: 3C59X.INC,v $ |
;; Revision 1.3 2004/07/11 12:21:12 kozma |
;; Support of vortex chips (3c59x) added. |
;; Support of 3c920 and 3c982 added. |
;; Corrections. |
;; |
;; Revision 1.2 2004/06/12 19:40:20 kozma |
;; Function e3c59x_set_available_media added in order to set |
;; the default media in case auto detection finds no valid link. |
;; Incorrect mii check removed (3c900 Cyclone works now). |
;; Cleanups. |
;; |
;; Revision 1.1 2004/06/12 18:27:15 kozma |
;; Initial revision |
;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; comment the next line out if you don't want debug info printed |
; on the debug board. This option adds a lot of bytes to the driver |
; so it's worth to comment it out. |
; E3C59X_DEBUG equ 1 |
; forcing full duplex mode makes sense at some cards and link types |
E3C59X_FORCE_FD equ 1 |
macro virt_to_dma reg |
{ |
sub reg, OS_BASE |
} |
macro dma_to_virt reg |
{ |
add reg, OS_BASE |
} |
macro zero_to_virt reg |
{ |
} |
macro virt_to_zero reg |
{ |
} |
macro zero_to_dma reg |
{ |
sub reg, OS_BASE |
} |
macro dma_to_zero reg |
{ |
add reg, OS_BASE |
} |
macro strtbl name, [string] |
{ |
common |
label name dword |
forward |
local label |
dd label |
forward |
label db string, 0 |
} |
; Ethernet frame symbols |
ETH_ALEN equ 6 |
ETH_HLEN equ (2*ETH_ALEN+2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
; PCI programming |
PCI_REG_COMMAND equ 0x4 ; command register |
PCI_REG_STATUS equ 0x6 ; status register |
PCI_REG_LATENCY equ 0xd ; latency timer register |
PCI_REG_CAP_PTR equ 0x34 ; capabilities pointer |
PCI_REG_CAPABILITY_ID equ 0x0 ; capapility ID in pm register block |
PCI_REG_PM_STATUS equ 0x4 ; power management status register |
PCI_REG_PM_CTRL equ 0x4 ; power management control register |
PCI_BIT_PIO equ 0 ; bit0: io space control |
PCI_BIT_MMIO equ 1 ; bit1: memory space control |
PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master |
; Registers |
E3C59X_REG_POWER_MGMT_CTRL equ 0x7c |
E3C59X_REG_UP_LIST_PTR equ 0x38 |
E3C59X_REG_UP_PKT_STATUS equ 0x30 |
E3C59X_REG_TX_FREE_THRESH equ 0x2f |
E3C59X_REG_DN_LIST_PTR equ 0x24 |
E3C59X_REG_DMA_CTRL equ 0x20 |
E3C59X_REG_TX_STATUS equ 0x1b |
E3C59X_REG_RX_STATUS equ 0x18 |
E3C59X_REG_TX_DATA equ 0x10 |
; Common window registers |
E3C59X_REG_INT_STATUS equ 0xe |
E3C59X_REG_COMMAND equ 0xe |
; Register window 7 |
E3C59X_REG_MASTER_STATUS equ 0xc |
E3C59X_REG_POWER_MGMT_EVENT equ 0xc |
E3C59X_REG_MASTER_LEN equ 0x6 |
E3C59X_REG_VLAN_ETHER_TYPE equ 0x4 |
E3C59X_REG_VLAN_MASK equ 0x0 |
E3C59X_REG_MASTER_ADDRESS equ 0x0 |
; Register window 6 |
E3C59X_REG_BYTES_XMITTED_OK equ 0xc |
E3C59X_REG_BYTES_RCVD_OK equ 0xa |
E3C59X_REG_UPPER_FRAMES_OK equ 0x9 |
E3C59X_REG_FRAMES_DEFERRED equ 0x8 |
E3C59X_REG_FRAMES_RCVD_OK equ 0x7 |
E3C59X_REG_FRAMES_XMITTED_OK equ 0x6 |
E3C59X_REG_RX_OVERRUNS equ 0x5 |
E3C59X_REG_LATE_COLLISIONS equ 0x4 |
E3C59X_REG_SINGLE_COLLISIONS equ 0x3 |
E3C59X_REG_MULTIPLE_COLLISIONS equ 0x2 |
E3C59X_REG_SQE_ERRORS equ 0x1 |
E3C59X_REG_CARRIER_LOST equ 0x0 |
; Register window 5 |
E3C59X_REG_INDICATION_ENABLE equ 0xc |
E3C59X_REG_INTERRUPT_ENABLE equ 0xa |
E3C59X_REG_TX_RECLAIM_THRESH equ 0x9 |
E3C59X_REG_RX_FILTER equ 0x8 |
E3C59X_REG_RX_EARLY_THRESH equ 0x6 |
E3C59X_REG_TX_START_THRESH equ 0x0 |
; Register window 4 |
E3C59X_REG_UPPER_BYTES_OK equ 0xe |
E3C59X_REG_BAD_SSD equ 0xc |
E3C59X_REG_MEDIA_STATUS equ 0xa |
E3C59X_REG_PHYSICAL_MGMT equ 0x8 |
E3C59X_REG_NETWORK_DIAGNOSTIC equ 0x6 |
E3C59X_REG_FIFO_DIAGNOSTIC equ 0x4 |
E3C59X_REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported |
; Bits in register window 4 |
E3C59X_BIT_AUTOSELECT equ 24 |
; Register window 3 |
E3C59X_REG_TX_FREE equ 0xc |
E3C59X_REG_RX_FREE equ 0xa |
E3C59X_REG_MEDIA_OPTIONS equ 0x8 |
E3C59X_REG_MAC_CONTROL equ 0x6 |
E3C59X_REG_MAX_PKT_SIZE equ 0x4 |
E3C59X_REG_INTERNAL_CONFIG equ 0x0 |
; Register window 2 |
E3C59X_REG_RESET_OPTIONS equ 0xc |
E3C59X_REG_STATION_MASK_HI equ 0xa |
E3C59X_REG_STATION_MASK_MID equ 0x8 |
E3C59X_REG_STATION_MASK_LO equ 0x6 |
E3C59X_REG_STATION_ADDRESS_HI equ 0x4 |
E3C59X_REG_STATION_ADDRESS_MID equ 0x2 |
E3C59X_REG_STATION_ADDRESS_LO equ 0x0 |
; Register window 1 |
E3C59X_REG_TRIGGER_BITS equ 0xc |
E3C59X_REG_SOS_BITS equ 0xa |
E3C59X_REG_WAKE_ON_TIMER equ 0x8 |
E3C59X_REG_SMB_RXBYTES equ 0x7 |
E3C59X_REG_SMB_DIAG equ 0x5 |
E3C59X_REG_SMB_ARB equ 0x4 |
E3C59X_REG_SMB_STATUS equ 0x2 |
E3C59X_REG_SMB_ADDRESS equ 0x1 |
E3C59X_REG_SMB_FIFO_DATA equ 0x0 |
; Register window 0 |
E3C59X_REG_EEPROM_DATA equ 0xc |
E3C59X_REG_EEPROM_COMMAND equ 0xa |
E3C59X_REG_BIOS_ROM_DATA equ 0x8 |
E3C59X_REG_BIOS_ROM_ADDR equ 0x4 |
; Physical management bits |
E3C59X_BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData |
E3C59X_BIT_MGMT_DATA equ 1 ; MII management data bit |
E3C59X_BIT_MGMT_CLK equ 0 ; MII management clock |
; MII commands |
E3C59X_MII_CMD_MASK equ (1111b shl 10) |
E3C59X_MII_CMD_READ equ (0110b shl 10) |
E3C59X_MII_CMD_WRITE equ (0101b shl 10) |
; MII registers |
E3C59X_REG_MII_BMCR equ 0 ; basic mode control register |
E3C59X_REG_MII_BMSR equ 1 ; basic mode status register |
E3C59X_REG_MII_ANAR equ 4 ; auto negotiation advertisement register |
E3C59X_REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register |
E3C59X_REG_MII_ANER equ 6 ; auto negotiation expansion register |
; MII bits |
E3C59X_BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete |
E3C59X_BIT_MII_PREAMBLE_SUPPRESSION equ 6 |
; eeprom bits and commands |
E3C59X_EEPROM_CMD_READ equ 0x80 |
E3C59X_EEPROM_BIT_BUSY equ 15 |
; eeprom registers |
E3C59X_EEPROM_REG_OEM_NODE_ADDR equ 0xa |
E3C59X_EEPROM_REG_CAPABILITIES equ 0x10 |
; Commands for command register |
E3C59X_SELECT_REGISTER_WINDOW equ (1 shl 11) |
IS_VORTEX equ 0x1 |
IS_BOOMERANG equ 0x2 |
IS_CYCLONE equ 0x4 |
IS_TORNADO equ 0x8 |
EEPROM_8BIT equ 0x10 |
HAS_PWR_CTRL equ 0x20 |
HAS_MII equ 0x40 |
HAS_NWAY equ 0x80 |
HAS_CB_FNS equ 0x100 |
INVERT_MII_PWR equ 0x200 |
INVERT_LED_PWR equ 0x400 |
MAX_COLLISION_RESET equ 0x800 |
EEPROM_OFFSET equ 0x1000 |
HAS_HWCKSM equ 0x2000 |
EXTRA_PREAMBLE equ 0x4000 |
iglobal |
align 4 |
e3c59x_hw_versions: |
dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps |
dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex |
dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex |
dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx |
dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4 |
dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII |
dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT |
dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo |
dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO |
dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo |
dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC |
dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL |
dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx |
dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4 |
dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx |
dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC |
dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx |
dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado |
dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone |
dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone |
dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane |
dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane |
dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS \ |
or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado |
dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS \ |
or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane |
dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus |
dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus |
dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT \ |
or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus |
dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ |
or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus |
dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ |
or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus |
dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ |
or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus |
dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ |
or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus |
dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado |
dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado |
dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A |
dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B |
dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4 |
dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado |
E3C59X_HW_VERSIONS_SIZE= $-e3c59x_hw_versions |
endg |
; RX/TX buffers sizes |
E3C59X_MAX_ETH_PKT_SIZE equ 1536 ; max packet size |
E3C59X_NUM_RX_DESC equ 4 ; a power of 2 number |
E3C59X_NUM_TX_DESC equ 4 ; a power of 2 number |
E3C59X_RX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_RX_DESC) |
E3C59X_TX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_TX_DESC) |
; Download Packet Descriptor |
E3C59X_DPD_DN_NEXT_PTR equ 0 |
E3C59X_DPD_FRAME_START_HDR equ 4 |
E3C59X_DPD_DN_FRAG_ADDR equ 8 ; for packet data |
E3C59X_DPD_DN_FRAG_LEN equ 12 ; for packet data |
E3C59X_DPD_SIZE equ 16 ; a power of 2 number |
; Upload Packet Descriptor |
E3C59X_UPD_UP_NEXT_PTR equ 0 |
E3C59X_UPD_PKT_STATUS equ 4 |
E3C59X_UPD_UP_FRAG_ADDR equ 8 ; for packet data |
E3C59X_UPD_UP_FRAG_LEN equ 12 ; for packet data |
E3C59X_UPD_SIZE equ 16 |
; RX/TX buffers |
if defined E3C59X_LINUX |
E3C59X_MAX_ETH_FRAME_SIZE = 160 ; size of ethernet frame + bytes alignment |
e3c59x_rx_buff = 0 |
else |
E3C59X_MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment |
e3c59x_rx_buff = eth_data_start |
end if |
e3c59x_tx_buff = e3c59x_rx_buff+E3C59X_RX_BUFFER_SIZE |
e3c59x_dpd_buff = e3c59x_tx_buff+E3C59X_TX_BUFFER_SIZE |
e3c59x_upd_buff = e3c59x_dpd_buff+(E3C59X_DPD_SIZE*E3C59X_NUM_TX_DESC) |
uglobal |
e3c59x_curr_upd: |
dd 0 |
e3c59x_prev_dpd: |
dd 0 |
e3c59x_prev_tx_frame: |
dd 0 |
e3c59x_transmit_function: |
dd 0 |
e3c59x_receive_function: |
dd 0 |
endg |
iglobal |
e3c59x_ver_id: |
db 17 |
endg |
uglobal |
e3c59x_full_bus_master: |
db 0 |
e3c59x_has_hwcksm: |
db 0 |
e3c59x_preamble: |
db 0 |
e3c59x_dn_list_ptr_cleared: |
db 0 |
e3c59x_self_directed_packet: |
rb 6 |
endg |
if defined E3C59X_DEBUG |
e3c59x_hw_type_str: |
db "Detected hardware type : ", 0 |
e3c59x_device_str: |
db "Device ID : 0x" |
e3c59x_device_id_str: |
db "ffff", 13, 10, 0 |
e3c59x_vendor_str: |
db "Vendor ID : 0x" |
e3c59x_vendor_id_str: |
db "ffff", 13, 10, 0 |
e3c59x_io_info_str: |
db "IO address : 0x" |
e3c59x_io_addr_str: |
db "ffff", 13, 10, 0 |
e3c59x_mac_info_str: |
db "MAC address : " |
e3c59x_mac_addr_str: |
db "ff:ff:ff:ff:ff:ff", 13, 10, 0 |
e3c59x_boomerang_str: |
db " (boomerang)", 13, 10, 0 |
e3c59x_vortex_str: |
db " (vortex)", 13, 10, 0 |
e3c59x_link_type_str: |
db "Established link type : ", 0 |
e3c59x_new_line_str: |
db 13, 10, 0 |
e3c59x_link_type: |
dd 0 |
e3c59x_charset: |
db '0123456789abcdef' |
strtbl e3c59x_link_str, \ |
"No valid link type detected", \ |
"10BASE-T half duplex", \ |
"10BASE-T full-duplex", \ |
"100BASE-TX half duplex", \ |
"100BASE-TX full duplex", \ |
"100BASE-T4", \ |
"100BASE-FX", \ |
"10Mbps AUI", \ |
"10Mbps COAX (BNC)", \ |
"miiDevice - not supported" |
strtbl e3c59x_hw_str, \ |
"3c590 Vortex 10Mbps", \ |
"3c592 EISA 10Mbps Demon/Vortex", \ |
"3c597 EISA Fast Demon/Vortex", \ |
"3c595 Vortex 100baseTx", \ |
"3c595 Vortex 100baseT4", \ |
"3c595 Vortex 100base-MII", \ |
"3c900 Boomerang 10baseT", \ |
"3c900 Boomerang 10Mbps Combo", \ |
"3c900 Cyclone 10Mbps TPO", \ |
"3c900 Cyclone 10Mbps Combo", \ |
"3c900 Cyclone 10Mbps TPC", \ |
"3c900B-FL Cyclone 10base-FL", \ |
"3c905 Boomerang 100baseTx", \ |
"3c905 Boomerang 100baseT4", \ |
"3c905B Cyclone 100baseTx", \ |
"3c905B Cyclone 10/100/BNC", \ |
"3c905B-FX Cyclone 100baseFx", \ |
"3c905C Tornado", \ |
"3c980 Cyclone", \ |
"3c982 Dual Port Server Cyclone", \ |
"3cSOHO100-TX Hurricane", \ |
"3c555 Laptop Hurricane", \ |
"3c556 Laptop Tornado", \ |
"3c556B Laptop Hurricane", \ |
"3c575 [Megahertz] 10/100 LAN CardBus", \ |
"3c575 Boomerang CardBus", \ |
"3CCFE575BT Cyclone CardBus", \ |
"3CCFE575CT Tornado CardBus", \ |
"3CCFE656 Cyclone CardBus", \ |
"3CCFEM656B Cyclone+Winmodem CardBus", \ |
"3CXFEM656C Tornado+Winmodem CardBus", \ |
"3c450 HomePNA Tornado", \ |
"3c920 Tornado", \ |
"3c982 Hydra Dual Port A", \ |
"3c982 Hydra Dual Port B", \ |
"3c905B-T4", \ |
"3c920B-EMB-WNM Tornado" |
end if ; defined E3C59X_DEBUG |
;*************************************************************************** |
; Function |
; e3c59x_debug |
; Description |
; prints debug info to the debug board |
; Parameters |
; ebp - io_addr |
; Return value |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
if defined E3C59X_DEBUG |
align 4 |
e3c59x_debug: |
pushad |
; print device type |
mov esi, e3c59x_hw_type_str |
call sys_msg_board_str |
movzx ecx, byte [e3c59x_ver_id] |
mov esi, [e3c59x_hw_str+ecx*4] |
call sys_msg_board_str |
mov esi, e3c59x_boomerang_str |
cmp dword [e3c59x_transmit_function], e3c59x_boomerang_transmit |
jz .boomerang |
mov esi, e3c59x_vortex_str |
.boomerang: |
call sys_msg_board_str |
; print device/vendor |
mov ax, [pci_data+2] |
mov cl, 2 |
mov ebx, e3c59x_device_id_str |
call e3c59x_print_hex |
mov esi, e3c59x_device_str |
call sys_msg_board_str |
mov ax, [pci_data] |
mov cl, 2 |
mov ebx, e3c59x_vendor_id_str |
call e3c59x_print_hex |
mov esi, e3c59x_vendor_str |
call sys_msg_board_str |
; print io address |
mov ax, [io_addr] |
mov ebx, e3c59x_io_addr_str |
mov cl, 2 |
call e3c59x_print_hex |
mov esi, e3c59x_io_info_str |
call sys_msg_board_str |
; print MAC address |
mov ebx, e3c59x_mac_addr_str |
xor ecx, ecx |
.mac_loop: |
push ecx |
mov al, [node_addr+ecx] |
mov cl, 1 |
call e3c59x_print_hex |
inc ebx |
pop ecx |
inc cl |
cmp cl, 6 |
jne .mac_loop |
mov esi, e3c59x_mac_info_str |
call sys_msg_board_str |
; print link type |
mov esi, e3c59x_link_type_str |
call sys_msg_board_str |
xor eax, eax |
bsr ax, word [e3c59x_link_type] |
jz @f |
sub ax, 4 |
@@: |
mov esi, [e3c59x_link_str+eax*4] |
call sys_msg_board_str |
mov esi, e3c59x_new_line_str |
call sys_msg_board_str |
popad |
ret |
;*************************************************************************** |
; Function |
; e3c59x_print_hex |
; Description |
; prints a hexadecimal value |
; Parameters |
; eax - value to be printed out |
; ebx - where to print |
; cl - value size (1, 2, 4) |
; Return value |
; ebx - end address after the print |
; Destroyed registers |
; eax, ebx |
; |
;*************************************************************************** |
align 4 |
e3c59x_print_hex: |
cmp cl, 1 |
je .print_byte |
cmp cl, 2 |
jz .print_word |
.print_dword: |
push eax |
bswap eax |
xchg ah, al |
call .print_word |
pop eax |
.print_word: |
push eax |
xchg ah, al |
call .print_byte |
pop eax |
.print_byte: |
movzx eax, al |
push eax |
and al, 0xf0 |
shr al, 4 |
mov al, byte [eax+e3c59x_charset] |
mov [ebx], al |
inc ebx |
pop eax |
and al, 0x0f |
mov al, byte [eax+e3c59x_charset] |
mov [ebx], al |
inc ebx |
ret |
end if ; defined E3C59X_DEBUG |
;*************************************************************************** |
; Function |
; e3c59x_try_link_detect |
; Description |
; e3c59x_try_link_detect checks if link exists |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 ; no link detected |
; al - 1 ; link detected |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_try_link_detect: |
; download self-directed packet |
mov edi, node_addr |
mov bx, 0x0608 ; packet type |
mov esi, e3c59x_self_directed_packet |
mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes |
call dword [e3c59x_transmit_function] |
; switch to register window 5 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 |
out dx, ax |
; program RxFilter for promiscuous operation |
mov ax, (10000b shl 11) |
lea edx, [ebp+E3C59X_REG_RX_FILTER] |
in al, dx |
or al, 1111b |
lea edx, [ebp+E3C59X_REG_COMMAND] |
out dx, ax |
; switch to register window 4 |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; check loop |
xor ebx, ebx |
mov ecx, 0xffff ; 65535 tries |
.loop: |
push ecx ebx |
call dword [e3c59x_receive_function] |
pop ebx ecx |
test al, al |
jnz .finish |
.no_packet_received: |
; switch to register window 4 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; read linkbeatdetect |
lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] |
in ax, dx |
test ah, 1000b ; test linkBeatDetect |
jnz .link_detected |
xor al, al |
jmp .finish |
.link_detected: |
; test carrierSense |
test al, 100000b |
jz .no_carrier_sense |
inc ebx |
.no_carrier_sense: |
dec ecx |
jns .loop |
; assume the link is good if 0 < ebx < 25 % |
test ebx, ebx |
setnz al |
jz .finish |
cmp ebx, 16384 ; 25% |
setb al |
.finish: |
if defined E3C59X_DEBUG |
test al, al |
jz @f |
or byte [e3c59x_link_type+1], 100b |
@@: |
end if ; defined E3C59X_DEBUG |
ret |
;*************************************************************************** |
; Function |
; e3c59x_try_phy |
; Description |
; e3c59x_try_phy checks the auto-negotiation function |
; in the PHY at PHY index. It can also be extended to |
; include link detection for non-IEEE 802.3u |
; auto-negotiation devices, for instance the BCM5000. |
; Parameters |
; ah - PHY index |
; ebp - io_addr |
; Return value |
; al - 0 link is auto-negotiated |
; al - 1 no link is auto-negotiated |
; Destroyed registers |
; eax, ebx, ecx, edx, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_try_phy: |
mov al, E3C59X_REG_MII_BMCR |
push eax |
call e3c59x_mdio_read ; returns with window #4 |
or ah, 0x80 ; software reset |
mov ebx, eax |
pop eax |
push eax |
call e3c59x_mdio_write ; returns with window #4 |
; wait for reset to complete |
mov esi, 2000 ; 2000ms = 2s |
call delay_ms |
pop eax |
push eax |
call e3c59x_mdio_read ; returns with window #4 |
test ah, 0x80 |
jnz .fail_finish |
pop eax |
push eax |
; wait for a while after reset |
mov esi, 20 ; 20ms |
call delay_ms |
pop eax |
push eax |
mov al, E3C59X_REG_MII_BMSR |
call e3c59x_mdio_read ; returns with window #4 |
test al, 1 ; extended capability supported? |
jz .no_ext_cap |
; auto-neg capable? |
test al, 1000b |
jz .fail_finish ; not auto-negotiation capable |
; auto-neg complete? |
test al, 100000b |
jnz .auto_neg_ok |
; restart auto-negotiation |
pop eax |
push eax |
mov al, E3C59X_REG_MII_ANAR |
push eax |
call e3c59x_mdio_read ; returns with window #4 |
or ax, (1111b shl 5) ; advertise only 10base-T and 100base-TX |
mov ebx, eax |
pop eax |
call e3c59x_mdio_write ; returns with window #4 |
pop eax |
push eax |
call e3c59x_mdio_read ; returns with window #4 |
mov ebx, eax |
or bh, 10010b ; restart auto-negotiation |
pop eax |
push eax |
call e3c59x_mdio_write ; returns with window #4 |
mov esi, 4000 ; 4000ms = 4 seconds |
call delay_ms |
pop eax |
push eax |
mov al, E3C59X_REG_MII_BMSR |
call e3c59x_mdio_read ; returns with window #4 |
test al, 100000b ; auto-neg complete? |
jnz .auto_neg_ok |
jmp .fail_finish |
.auto_neg_ok: |
; compare advertisement and link partner ability registers |
pop eax |
push eax |
mov al, E3C59X_REG_MII_ANAR |
call e3c59x_mdio_read ; returns with window #4 |
xchg eax, [esp] |
mov al, E3C59X_REG_MII_ANLPAR |
call e3c59x_mdio_read ; returns with window #4 |
pop ebx |
and eax, ebx |
and eax, 1111100000b |
push eax |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], ax |
end if ; defined E3C59X_DEBUG |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; set full-duplex mode |
lea edx, [ebp+E3C59X_REG_MAC_CONTROL] |
in ax, dx |
and ax, not 0x120 ; clear full duplex and flow control |
pop ebx |
test ebx, (1010b shl 5) ; check for full-duplex |
jz .half_duplex |
or ax, 0x120 ; set full duplex and flow control |
.half_duplex: |
out dx, ax |
mov al, 1 |
ret |
.no_ext_cap: |
; not yet implemented BCM5000 |
.fail_finish: |
pop eax |
xor al, al |
ret |
;*************************************************************************** |
; Function |
; e3c59x_try_mii |
; Description |
; e3c59x_try_MII checks the on-chip auto-negotiation logic |
; or an off-chip MII PHY, depending upon what is set in |
; xcvrSelect by the caller. |
; It exits when it finds the first device with a good link. |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 |
; al - 1 |
; Destroyed registers |
; eax, ebx, ecx, edx, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_try_mii: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, (1111b shl 20) |
cmp eax, (1000b shl 20) ; is auto-negotiation set? |
jne .mii_device |
; auto-negotiation is set |
; switch to register window 4 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; PHY==24 is the on-chip auto-negotiation logic |
; it supports only 10base-T and 100base-TX |
mov ah, 24 |
call e3c59x_try_phy |
test al, al |
jz .fail_finish |
mov cl, 24 |
jmp .check_preamble |
.mii_device: |
cmp eax, (0110b shl 20) |
jne .fail_finish |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] |
in ax, dx |
and al, (1 shl E3C59X_BIT_MGMT_DIR) or (1 shl E3C59X_BIT_MGMT_DATA) |
cmp al, (1 shl E3C59X_BIT_MGMT_DATA) |
je .serch_for_phy |
xor al, al |
ret |
.serch_for_phy: |
; search for PHY |
mov cl, 31 |
.search_phy_loop: |
cmp cl, 24 |
je .next_phy |
mov ah, cl ; ah = phy |
mov al, E3C59X_REG_MII_BMCR ; al = Basic Mode Status Register |
push ecx |
call e3c59x_mdio_read |
pop ecx |
test ax, ax |
jz .next_phy |
cmp ax, 0xffff |
je .next_phy |
mov ah, cl ; ah = phy |
push ecx |
call e3c59x_try_phy |
pop ecx |
test al, al |
jnz .check_preamble |
.next_phy: |
dec cl |
jns .search_phy_loop |
.fail_finish: |
xor al, al |
ret |
; epilog |
.check_preamble: |
push eax ; eax contains the return value of e3c59x_try_phy |
; check hard coded preamble forcing |
movzx eax, byte [e3c59x_ver_id] |
test word [eax*4+e3c59x_hw_versions+2], EXTRA_PREAMBLE |
setnz [e3c59x_preamble] ; force preamble |
jnz .finish |
; check mii for preamble suppression |
mov ah, cl |
mov al, E3C59X_REG_MII_BMSR |
call e3c59x_mdio_read |
test al, 1000000b ; preamble suppression? |
setz [e3c59x_preamble] ; no |
.finish: |
pop eax |
ret |
;*************************************************************************** |
; Function |
; e3c59x_test_packet |
; Description |
; e3c59x_try_loopback try a loopback packet for 10BASE2 or AUI port |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 |
; al - 1 |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_test_packet: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; set fullDuplexEnable in MacControl register |
lea edx, [ebp+E3C59X_REG_MAC_CONTROL] |
in ax, dx |
or ax, 0x120 |
out dx, ax |
; switch to register window 5 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 |
out dx, ax |
; set RxFilter to enable individual address matches |
mov ax, (10000b shl 11) |
lea edx, [ebp+E3C59X_REG_RX_FILTER] |
in al, dx |
or al, 1 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
out dx, ax |
; issue RxEnable and TxEnable |
call e3c59x_rx_reset |
call e3c59x_tx_reset |
; download a self-directed test packet |
mov edi, node_addr |
mov bx, 0x0608 ; packet type |
mov esi, e3c59x_self_directed_packet |
mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes |
call dword [e3c59x_transmit_function] |
; wait for 2s |
mov esi, 2000 ; 2000ms = 2s |
call delay_ms |
; check if self-directed packet is received |
call dword [e3c59x_receive_function] |
test al, al |
jnz .finish |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; clear fullDuplexEnable in MacControl register |
lea edx, [ebp+E3C59X_REG_MAC_CONTROL] |
in ax, dx |
and ax, not 0x120 |
out dx, ax |
xor al, al |
.finish: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_try_loopback |
; Description |
; tries a loopback packet for 10BASE2 or AUI port |
; Parameters |
; al - 0: 10Mbps AUI connector |
; 1: 10BASE-2 |
; ebp - io_addr |
; Return value |
; al - 0 |
; al - 1 |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_try_loopback: |
push eax |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
pop eax |
push eax |
if defined E3C59X_DEBUG |
mov bl, al |
inc bl |
shl bl, 3 |
or byte [e3c59x_link_type+1], bl |
end if ; defined E3C59X_DEBUG |
test al, al ; aui or coax? |
jz .complete_loopback |
; enable 100BASE-2 DC-DC converter |
mov ax, (10b shl 11) ; EnableDcConverter |
out dx, ax |
.complete_loopback: |
mov cl, 2 ; give a port 3 chances to complete a loopback |
.next_try: |
push ecx |
call e3c59x_test_packet |
pop ecx |
test al, al |
jnz .finish |
dec cl |
jns .next_try |
.finish: |
xchg eax, [esp] |
test al, al |
jz .aui_finish |
; issue DisableDcConverter command |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10111b shl 11) |
out dx, ax |
.aui_finish: |
pop eax ; al contains the result of operation |
if defined E3C59X_DEBUG |
test al, al |
jnz @f |
and byte [e3c59x_link_type+1], not 11000b |
@@: |
end if ; defined E3C59X_DEBUG |
ret |
;*************************************************************************** |
; Function |
; e3c59x_set_available_media |
; Description |
; sets the first available media |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 |
; al - 1 |
; Destroyed registers |
; eax, edx |
; |
;*************************************************************************** |
align 4 |
e3c59x_set_available_media: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
push eax |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx |
test al, 10b |
jz @f |
; baseTXAvailable |
pop eax |
and eax, not (1111b shl 20) |
or eax, (100b shl 20) |
if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD |
mov word [e3c59x_link_type], (1 shl 8) |
else if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 7) |
end if |
jmp .set_media |
@@: |
test al, 100b |
jz @f |
; baseFXAvailable |
pop eax |
and eax, not (1111b shl 20) |
or eax, (101b shl 20) |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 10) |
end if |
jmp .set_media |
@@: |
test al, 1000000b |
jz @f |
; miiDevice |
pop eax |
and eax, not (1111b shl 20) |
or eax, (0110b shl 20) |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 13) |
end if |
jmp .set_media |
@@: |
test al, 1000b |
jz @f |
.set_default: |
; 10bTAvailable |
pop eax |
and eax, not (1111b shl 20) |
if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD |
mov word [e3c59x_link_type], (1 shl 6) |
else if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 5) |
end if ; E3C59X_FORCE_FD |
jmp .set_media |
@@: |
test al, 10000b |
jz @f |
; coaxAvailable |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10b shl 11) ; EnableDcConverter |
out dx, ax |
pop eax |
and eax, not (1111b shl 20) |
or eax, (11b shl 20) |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 12) |
end if ; defined E3C59X_DEBUG |
jmp .set_media |
@@: |
test al, 10000b |
jz .set_default |
; auiAvailable |
pop eax |
and eax, not (1111b shl 20) |
or eax, (1 shl 20) |
if defined E3C59X_DEBUG |
mov word [e3c59x_link_type], (1 shl 11) |
end if ; defined E3C59X_DEBUG |
.set_media: |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
out dx, eax |
if defined E3C59X_FORCE_FD |
; set fullDuplexEnable in MacControl register |
lea edx, [ebp+E3C59X_REG_MAC_CONTROL] |
in ax, dx |
or ax, 0x120 |
out dx, ax |
end if ; E3C59X_FORCE_FD |
mov al, 1 |
ret |
;*************************************************************************** |
; Function |
; e3c59x_set_active_port |
; Description |
; It selects the media port (transceiver) to be used |
; Parameters: |
; ebp - io_addr |
; Return value: |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_set_active_port: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
test eax, (1 shl 24) ; check if autoselect enable |
jz .set_first_available_media |
; check 100BASE-TX and 10BASE-T |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx |
test al, 1010b ; check whether 100BASE-TX or 10BASE-T available |
jz .mii_device ; they are not available |
; set auto-negotiation |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (1000b shl 20) |
out dx, eax |
call e3c59x_try_mii |
test al, al |
jz .mii_device |
ret |
.mii_device: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; check for off-chip mii device |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx |
test al, 1000000b ; check miiDevice |
jz .base_fx |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (0110b shl 20) ; set MIIDevice |
out dx, eax |
call e3c59x_try_mii |
test al, al |
jz .base_fx |
ret |
.base_fx: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; check for 100BASE-FX |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx ; read media option register |
test al, 100b ; check 100BASE-FX |
jz .aui_enable |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (0101b shl 20) ; set 100base-FX |
out dx, eax |
call e3c59x_try_link_detect |
test al, al |
jz .aui_enable |
ret |
.aui_enable: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; check for 10Mbps AUI connector |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx ; read media option register |
test al, 100000b ; check 10Mbps AUI connector |
jz .coax_available |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (0001b shl 20) ; set 10Mbps AUI connector |
out dx, eax |
xor al, al ; try 10Mbps AUI connector |
call e3c59x_try_loopback |
test al, al |
jz .coax_available |
ret |
.coax_available: |
; switch to register window 3 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 |
out dx, ax |
; check for coaxial 10BASE-2 port |
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] |
in ax, dx ; read media option register |
test al, 10000b ; check 10BASE-2 |
jz .set_first_available_media |
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] |
in eax, dx |
and eax, not (1111b shl 20) |
or eax, (0011b shl 20) ; set 10BASE-2 |
out dx, eax |
mov al, 1 |
call e3c59x_try_loopback |
test al, al |
jz .set_first_available_media |
ret |
.set_first_available_media: |
jmp e3c59x_set_available_media |
;*************************************************************************** |
; Function |
; e3c59x_wake_up |
; Description |
; set the power state to D0 |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_wake_up: |
; wake up - we directly do it by programming PCI |
; check if the device is power management capable |
mov al, 2 |
mov ah, [pci_bus] |
mov bl, PCI_REG_STATUS |
mov bh, [pci_dev] |
push eax ebx |
call pci_read_reg |
test al, 10000b ; is there "new capabilities" linked list? |
pop ebx eax |
jz .device_awake |
; search for power management register |
mov al, 1 |
mov bl, PCI_REG_CAP_PTR |
push eax ebx |
call pci_read_reg |
mov cl, al |
cmp cl, 0x3f |
pop ebx eax |
jbe .device_awake |
; traverse the list |
mov al, 2 |
.pm_loop: |
mov bl, cl |
push eax ebx |
call pci_read_reg |
cmp al, 1 |
je .set_pm_state |
test ah, ah |
mov cl, ah |
pop ebx eax |
jnz .pm_loop |
jmp .device_awake |
; waku up the device if necessary |
.set_pm_state: |
pop ebx eax |
add bl, PCI_REG_PM_CTRL |
push eax ebx |
call pci_read_reg |
mov cx, ax |
test cl, 3 |
pop ebx eax |
jz .device_awake |
and cl, not 11b ; set state to D0 |
call pci_write_reg |
.device_awake: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_probe: |
movzx ebp, word [io_addr] |
mov al, 2 |
mov ah, [pci_bus] |
mov bh, [pci_dev] |
mov bl, PCI_REG_COMMAND |
push ebp eax ebx |
call pci_read_reg |
mov cx, ax |
or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) |
and cl, not (1 shl PCI_BIT_MMIO) |
pop ebx eax |
call pci_write_reg |
; wake up the card |
call e3c59x_wake_up |
pop ebp |
; get chip version |
mov ax, [pci_data+2] |
mov ecx, E3C59X_HW_VERSIONS_SIZE/4-1 |
.chip_ver_loop: |
cmp ax, [e3c59x_hw_versions+ecx*4] |
jz .chip_ver_found |
dec ecx |
jns .chip_ver_loop |
xor ecx, ecx |
.chip_ver_found: |
mov [e3c59x_ver_id], cl |
test word [e3c59x_hw_versions+2+ecx*4], HAS_HWCKSM |
setnz [e3c59x_has_hwcksm] |
; set pci latency for vortex cards |
test word [e3c59x_hw_versions+2+ecx*4], IS_VORTEX |
jz .not_vortex |
mov cx, 11111000b ; 248 = max latency |
mov al, 1 |
mov ah, [pci_bus] |
mov bl, PCI_REG_LATENCY |
mov bh, [pci_dev] |
call pci_write_reg |
.not_vortex: |
; set RX/TX functions |
mov ax, E3C59X_EEPROM_REG_CAPABILITIES |
call e3c59x_read_eeprom |
test al, 100000b ; full bus master? |
setnz [e3c59x_full_bus_master] |
jnz .boomerang_func |
mov dword [e3c59x_transmit_function], e3c59x_vortex_transmit |
mov dword [e3c59x_receive_function], e3c59x_vortex_poll |
jmp @f |
.boomerang_func: ; full bus master, so use boomerang functions |
mov dword [e3c59x_transmit_function], e3c59x_boomerang_transmit |
mov dword [e3c59x_receive_function], e3c59x_boomerang_poll |
@@: |
; read MAC from eeprom |
mov ecx, 2 |
.mac_loop: |
lea ax, [E3C59X_EEPROM_REG_OEM_NODE_ADDR+ecx] |
call e3c59x_read_eeprom |
xchg ah, al ; htons |
mov [node_addr+ecx*2], ax |
dec ecx |
jns .mac_loop |
test byte [e3c59x_full_bus_master], 0xff |
jz .set_preamble |
; switch to register window 2 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 |
out dx, ax |
; activate xcvr by setting some magic bits |
lea edx, [ebp+E3C59X_REG_RESET_OPTIONS] |
in ax, dx |
and ax, not 0x4010 |
movzx ebx, byte [e3c59x_ver_id] |
test word [ebx*4+e3c59x_hw_versions+2], INVERT_LED_PWR |
jz @f |
or al, 0x10 |
@@: |
test word [ebx*4+e3c59x_hw_versions+2], INVERT_MII_PWR |
jz @f |
or ah, 0x40 |
@@: |
out dx, ax |
.set_preamble: |
; use preamble as default |
mov byte [e3c59x_preamble], 1 ; enable preamble |
;*************************************************************************** |
; Function |
; e3c59x_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
e3c59x_reset: |
; issue global reset |
call e3c59x_global_reset |
; disable interrupts |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (1110b shl 11) |
out dx, ax |
; enable Statistics |
mov ax, (10101b shl 11) |
out dx, ax |
; set indication |
mov ax, (1111b shl 11) or 0x6c6 |
out dx, ax |
; acknowledge (clear) every interrupt indicator |
mov ax, (1101b shl 11) or 0x661 |
out dx, ax |
; switch to register window 2 |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 |
out dx, ax |
; write MAC addres back into the station address registers |
lea edx, [ebp+E3C59X_REG_STATION_ADDRESS_LO] |
mov esi, node_addr |
cld |
outsw |
add edx, 2 |
outsw |
add edx, 2 |
outsw |
add edx, 2 |
; clear station mask |
xor eax, eax |
out dx, ax |
add edx, 2 |
out dx, ax |
add edx, 2 |
out dx, ax |
; switch to register window 6 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+6 |
out dx, ax |
; clear all statistics by reading |
lea edx, [ebp+E3C59X_REG_CARRIER_LOST] |
mov cl, 9 |
.stat_clearing_loop: |
in al, dx |
inc edx |
dec cl |
jns .stat_clearing_loop |
in ax, dx |
add dx, 2 |
in ax, dx |
; switch to register window 4 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; clear BadSSD |
lea edx, [ebp+E3C59X_REG_BAD_SSD] |
in al, dx |
; clear extra statistics bit in NetworkDiagnostic |
lea edx, [ebp+E3C59X_REG_NETWORK_DIAGNOSTIC] |
in ax, dx |
or ax, 0x0040 |
out dx, ax |
; SetRxEarlyThreshold |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10001b shl 11)+(E3C59X_MAX_ETH_PKT_SIZE shr 2) |
out dx, ax |
test byte [e3c59x_full_bus_master], 0xff |
jz .skip_boomerang_setting |
; set upRxEarlyEnable |
lea edx, [ebp+E3C59X_REG_DMA_CTRL] |
in eax, dx |
or eax, 0x20 |
out dx, eax |
; TxFreeThreshold |
lea edx, [ebp+E3C59X_REG_TX_FREE_THRESH] |
mov al, (E3C59X_MAX_ETH_PKT_SIZE / 256) |
out dx, al |
; program DnListPtr |
lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] |
xor eax, eax |
out dx, eax |
.skip_boomerang_setting: |
; initialization |
call e3c59x_rx_reset |
call e3c59x_tx_reset |
call e3c59x_set_active_port |
call e3c59x_rx_reset |
call e3c59x_tx_reset |
; switch to register window 5 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 |
out dx, ax |
; program RxFilter for promiscuous operation |
mov ax, (10000b shl 11) |
lea edx, [ebp+E3C59X_REG_RX_FILTER] |
in al, dx |
or al, 1111b |
lea edx, [ebp+E3C59X_REG_COMMAND] |
out dx, ax |
; switch to register window 4 |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
; wait for linkDetect |
lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] |
mov cl, 20 ; wait for max 2s |
mov esi, 100 ; 100ms |
.link_detect_loop: |
call delay_ms |
in ax, dx |
test ah, 1000b ; linkDetect |
jnz @f |
dec cl |
jnz .link_detect_loop |
@@: |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
if defined E3C59X_DEBUG |
call e3c59x_debug |
end if ; defined E3C59X_DEBUG |
ret |
;*************************************************************************** |
; Function |
; e3c59x_global_reset |
; Description |
; resets the device |
; Parameters: |
; ebp - io_addr |
; Return value: |
; Destroyed registers |
; ax, ecx, edx, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_global_reset: |
; GlobalReset |
lea edx, [ebp+E3C59X_REG_COMMAND] |
xor eax, eax |
; or al, 0x14 |
out dx, ax |
; wait for GlobalReset to complete |
mov ecx, 64000 |
.global_reset_loop: |
in ax, dx |
test ah, 10000b ; check CmdInProgress |
jz .finish |
dec ecx |
jnz .global_reset_loop |
.finish: |
; wait for 2 seconds for NIC to boot |
mov esi, 2000 ; 2000ms = 2s |
push ebp |
call delay_ms |
pop ebp |
ret |
;*************************************************************************** |
; Function |
; e3c59x_tx_reset |
; Description |
; resets and enables transmitter engine |
; Parameters: |
; ebp - io_addr |
; Return value: |
; Destroyed registers |
; ax, ecx, edx |
; |
;*************************************************************************** |
align 4 |
e3c59x_tx_reset: |
; TxReset |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (01011b shl 11) |
out dx, ax |
; Wait for TxReset to complete |
mov ecx, 200000 |
.tx_reset_loop: |
in ax, dx |
test ah, 10000b ; check CmdInProgress |
jz .tx_set_prev |
dec ecx |
jns .tx_reset_loop |
.tx_set_prev: |
test byte [e3c59x_full_bus_master], 0xff |
jz .tx_enable |
; init last_dpd |
mov dword [e3c59x_prev_dpd], e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE |
mov dword [e3c59x_prev_tx_frame], e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE |
.tx_enable: |
mov ax, (01001b shl 11) ; TxEnable |
out dx, ax |
ret |
;*************************************************************************** |
; Function |
; e3c59x_rx_reset |
; Description |
; resets and enables receiver engine |
; Parameters: |
; ebp - io_addr |
; Return value: |
; Destroyed registers |
; eax, ebx, ecx, edx, edi, esi |
; |
;*************************************************************************** |
align 4 |
e3c59x_rx_reset: |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (0101b shl 11) or 0x4 ; RxReset |
out dx, ax |
; wait for RxReset to complete |
mov ecx, 200000 |
.rx_reset_loop: |
in ax, dx |
test ah, 10000b ; check CmdInProgress |
jz .setup_upd |
dec ecx |
jns .rx_reset_loop |
.setup_upd: |
; check if full bus mastering |
test byte [e3c59x_full_bus_master], 0xff |
jz .rx_enable |
; create upd ring |
mov eax, e3c59x_upd_buff |
zero_to_virt eax |
mov [e3c59x_curr_upd], eax |
mov esi, eax |
virt_to_dma esi |
mov edi, e3c59x_rx_buff |
zero_to_dma edi |
mov ebx, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE |
zero_to_virt ebx |
mov cl, E3C59X_NUM_RX_DESC-1 |
.upd_loop: |
mov [ebx+E3C59X_UPD_UP_NEXT_PTR], esi |
and dword [eax+E3C59X_UPD_PKT_STATUS], 0 |
mov [eax+E3C59X_UPD_UP_FRAG_ADDR], edi |
mov dword [eax+E3C59X_UPD_UP_FRAG_LEN], E3C59X_MAX_ETH_FRAME_SIZE or (1 shl 31) |
add edi, E3C59X_MAX_ETH_FRAME_SIZE |
add esi, E3C59X_UPD_SIZE |
mov ebx, eax |
add eax, E3C59X_UPD_SIZE |
dec cl |
jns .upd_loop |
mov eax, e3c59x_upd_buff |
zero_to_dma eax |
lea edx, [ebp+E3C59X_REG_UP_LIST_PTR] |
out dx, eax ; write E3C59X_REG_UP_LIST_PTR |
lea edx, [ebp+E3C59X_REG_COMMAND] |
.rx_enable: |
mov ax, (00100b shl 11) ; RxEnable |
out dx, ax |
ret |
;*************************************************************************** |
; Function |
; e3c59x_write_eeprom |
; Description |
; reads eeprom |
; Note : the caller must switch to the register window 0 |
; before calling this function |
; Parameters: |
; ax - register to be read (only the first 63 words can be read) |
; cx - value to be read into the register |
; Return value: |
; ax - word read |
; Destroyed registers |
; ax, ebx, edx |
; |
;*************************************************************************** |
; align 4 |
;e3c59x_write_eeprom: |
; mov edx, [io_addr] |
; add edx, E3C59X_REG_EEPROM_COMMAND |
; cmp ah, 11b |
; ja .finish ; address may have a value of maximal 1023 |
; shl ax, 2 |
; shr al, 2 |
; push eax |
;; wait for busy |
; mov ebx, 0xffff |
;@@: |
; in ax, dx |
; test ah, 0x80 |
; jz .write_enable |
; dec ebx |
; jns @r |
;; write enable |
;.write_enable: |
; xor eax, eax |
; mov eax, (11b shl 4) |
; out dx, ax |
;; wait for busy |
; mov ebx, 0xffff |
;@@: |
; in ax, dx |
; test ah, 0x80 |
; jz .erase_loop |
; dec ebx |
; jns @r |
;.erase_loop: |
; pop eax |
; push eax |
; or ax, (11b shl 6) ; erase register |
; out dx, ax |
; mov ebx, 0xffff |
;@@: |
; in ax, dx |
; test ah, 0x80 |
; jz .write_reg |
; dec ebx |
; jns @r |
;.write_reg: |
; add edx, E3C59X_REG_EEPROM_DATA-E3C59X_REG_EEPROM_COMMAND |
; mov eax, ecx |
; out dx, ax |
;; write enable |
; add edx, E3C59X_REG_EEPROM_COMMAND-E3C59X_REG_EEPROM_DATA |
; xor eax, eax |
; mov eax, (11b shl 4) |
; out dx, ax |
; wait for busy |
; mov ebx, 0xffff |
;@@: |
; in ax, dx |
; test ah, 0x80 |
; jz .issue_write_reg |
; dec ebx |
; jns @r |
;.issue_write_reg: |
; pop eax |
; or ax, 01b shl 6 |
; out dx, ax |
;.finish: |
; ret |
;*************************************************************************** |
; Function |
; e3c59x_read_eeprom |
; Description |
; reads eeprom |
; Parameters: |
; ax - register to be read (only the first 63 words can be read) |
; ebp - io_addr |
; Return value: |
; ax - word read |
; Destroyed registers |
; ax, ebx, edx, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_read_eeprom: |
push eax |
; switch to register window 0 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+0 |
out dx, ax |
pop eax |
and ax, 111111b ; take only the first 6 bits into account |
movzx ebx, byte [e3c59x_ver_id] |
test word [ebx*4+e3c59x_hw_versions+2], EEPROM_8BIT |
jz @f |
add ax, 0x230 ; hardware constant |
jmp .read |
@@: |
add ax, E3C59X_EEPROM_CMD_READ |
test word [ebx*4+e3c59x_hw_versions+2], EEPROM_OFFSET |
jz .read |
add ax, 0x30 |
.read: |
lea edx, [ebp+E3C59X_REG_EEPROM_COMMAND] |
out dx, ax |
mov ebx, 0xffff ; duration of about 162 us ;-) |
.wait_for_reading: |
in ax, dx |
test ah, 0x80 ; check bit eepromBusy |
jz .read_data |
dec ebx |
jns .wait_for_reading |
.read_data: |
lea edx, [ebp+E3C59X_REG_EEPROM_DATA] |
in ax, dx |
ret |
;*************************************************************************** |
; Function |
; e3c59x_mdio_sync |
; Description |
; initial synchronization |
; Parameters |
; ebp - io_addr |
; Return value |
; Destroyed registers |
; ax, edx, cl |
; |
;*************************************************************************** |
align 4 |
e3c59x_mdio_sync: |
; switch to register window 4 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 |
out dx, ax |
cmp byte [e3c59x_preamble], 0 |
je .no_preamble |
; send 32 logic ones |
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] |
mov cl, 31 |
.loop: |
mov ax, (1 shl E3C59X_BIT_MGMT_DATA) or (1 shl E3C59X_BIT_MGMT_DIR) |
out dx, ax |
in ax, dx ; delay |
mov ax, (1 shl E3C59X_BIT_MGMT_DATA) \ |
or (1 shl E3C59X_BIT_MGMT_DIR) \ |
or (1 shl E3C59X_BIT_MGMT_CLK) |
out dx, ax |
in ax, dx ; delay |
dec cl |
jns .loop |
.no_preamble: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_mdio_read |
; Description |
; read MII register |
; see page 16 in D83840A.pdf |
; Parameters |
; ah - PHY addr |
; al - register addr |
; ebp - io_addr |
; Return value |
; ax - register read |
; Destroyed registers |
; eax, ebx, cx, edx |
; |
;*************************************************************************** |
align 4 |
e3c59x_mdio_read: |
push eax |
call e3c59x_mdio_sync ; returns with window #4 |
pop eax |
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] |
shl al, 3 |
shr ax, 3 |
and ax, not E3C59X_MII_CMD_MASK |
or ax, E3C59X_MII_CMD_READ |
mov ebx, eax |
xor ecx, ecx |
mov cl, 13 |
.cmd_loop: |
mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii |
bt ebx, ecx |
jnc .zero_bit |
or al, (1 shl E3C59X_BIT_MGMT_DATA) |
.zero_bit: |
out dx, ax |
push eax |
in ax, dx ; delay |
pop eax |
or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write |
out dx, ax |
in ax, dx ; delay |
dec cl |
jns .cmd_loop |
; read data (18 bits with the two transition bits) |
mov cl, 17 |
xor ebx, ebx |
.read_loop: |
shl ebx, 1 |
xor eax, eax ; read comand |
out dx, ax |
in ax, dx ; delay |
in ax, dx |
test al, (1 shl E3C59X_BIT_MGMT_DATA) |
jz .dont_set |
inc ebx |
.dont_set: |
mov ax, (1 shl E3C59X_BIT_MGMT_CLK) |
out dx, ax |
in ax, dx ; delay |
dec cl |
jns .read_loop |
mov eax, ebx |
ret |
;*************************************************************************** |
; Function |
; e3c59x_mdio_write |
; Description |
; write MII register |
; see page 16 in D83840A.pdf |
; Parameters |
; ah - PHY addr |
; al - register addr |
; bx - word to be written |
; ebp - io_addr |
; Return value |
; ax - register read |
; Destroyed registers |
; eax, ebx, cx, edx |
; |
;*************************************************************************** |
align 4 |
e3c59x_mdio_write: |
push eax |
call e3c59x_mdio_sync |
pop eax |
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] |
shl al, 3 |
shr ax, 3 |
and ax, not E3C59X_MII_CMD_MASK |
or ax, E3C59X_MII_CMD_WRITE |
shl eax, 2 |
or eax, 10b ; transition bits |
shl eax, 16 |
mov ax, bx |
mov ebx, eax |
mov ecx, 31 |
.cmd_loop: |
mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii |
bt ebx, ecx |
jnc .zero_bit |
or al, (1 shl E3C59X_BIT_MGMT_DATA) |
.zero_bit: |
out dx, ax |
push eax |
in ax, dx ; delay |
pop eax |
or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write |
out dx, ax |
in ax, dx ; delay |
dec ecx |
jns .cmd_loop |
ret |
;*************************************************************************** |
; Function |
; e3c59x_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; edi - Pointer to 48 bit destination address |
; bx - Type of packet |
; ecx - size of packet |
; esi - pointer to packet data |
; ebp - io_addr |
; Destroyed registers |
; eax, ecx, edx, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_transmit: |
jmp dword [e3c59x_transmit_function] |
;*************************************************************************** |
; Function |
; e3c59x_check_tx_status |
; Description |
; Checks TxStatus queue. |
; Return value |
; al - 0 no error was found |
; al - 1 error was found TxReset is needed |
; Destroyed registers |
; eax, ecx, edx, ebp |
; |
;*************************************************************************** |
e3c59x_check_tx_status: |
movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC |
; clear TxStatus queue |
lea edx, [ebp+E3C59X_REG_TX_STATUS] |
mov cl, 31 ; max number of queue entries |
.tx_status_loop: |
in al, dx |
test al, al |
jz .finish ; no error |
test al, 0x3f |
jnz .finish ; error |
.no_error_found: |
; clear current TxStatus entry which advances the next one |
xor al, al |
out dx, al |
dec cl |
jns .tx_status_loop |
.finish: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_vortex_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; edi - Pointer to 48 bit destination address |
; bx - Type of packet |
; ecx - size of packet |
; esi - pointer to packet data |
; ebp - io_addr |
; Destroyed registers |
; eax, edx, ecx, edi, esi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_vortex_transmit: |
push ecx |
call e3c59x_check_tx_status |
pop ecx |
test al, al |
jz .no_error_found |
jmp e3c59x_tx_reset |
.no_error_found: |
; switch to register window 7 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 |
out dx, ax |
; check for master operation in progress |
lea edx, [ebp+E3C59X_REG_MASTER_STATUS] |
in ax, dx |
test ah, 0x80 |
jnz .finish ; no DMA for sending |
; dword boundary correction |
cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE |
ja .finish ; packet is too long |
; write Frame Start Header |
mov eax, ecx |
; add header length and extend the complete length to dword boundary |
add eax, ETH_HLEN+3 |
and eax, not 3 |
lea edx, [ebp+E3C59X_REG_TX_DATA] |
out dx, eax |
; prepare the complete frame |
push esi |
mov esi, edi |
mov edi, e3c59x_tx_buff |
zero_to_virt edi |
cld |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi, node_addr |
movsd |
movsw |
; copy packet type |
mov [edi], bx |
add edi, 2 |
; copy packet data |
pop esi |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
mov ecx, eax |
; program frame address to be sent |
lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] |
mov eax, e3c59x_tx_buff |
zero_to_dma eax |
out dx, eax |
; program frame length |
lea edx, [ebp+E3C59X_REG_MASTER_LEN] |
mov eax, ecx |
out dx, ax |
; start DMA Down |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10100b shl 11) + 1 ; StartDMADown |
out dx, ax |
.finish: |
ret |
;*************************************************************************** |
; Function |
; e3c59x_boomerang_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; edi - Pointer to 48 bit destination address |
; bx - Type of packet |
; ecx - size of packet |
; esi - pointer to packet data |
; ebp - io_addr |
; Destroyed registers |
; eax, ebx, ecx, edx, esi, edi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_boomerang_transmit: |
push ecx |
call e3c59x_check_tx_status |
pop ecx |
test al, al |
jz .no_error_found |
jmp e3c59x_tx_reset |
.no_error_found: |
cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE |
ja .finish ; packet is too long |
; calculate descriptor address |
mov eax, [e3c59x_prev_dpd] |
cmp eax, e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE |
jb @f |
; wrap around |
mov eax, e3c59x_dpd_buff-E3C59X_DPD_SIZE |
@@: |
add eax, E3C59X_DPD_SIZE |
zero_to_virt eax |
push eax |
; check DnListPtr |
lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] |
in eax, dx |
; mark if Dn_List_Ptr is cleared |
test eax, eax |
setz [e3c59x_dn_list_ptr_cleared] |
; finish if no more free descriptor is available - FIXME! |
cmp eax, [esp] |
pop eax |
jz .finish |
push eax esi |
mov esi, edi |
; calculate tx_buffer address |
mov edi, [e3c59x_prev_tx_frame] |
cmp edi, e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE |
jb @f |
; wrap around |
mov edi, e3c59x_tx_buff-E3C59X_MAX_ETH_FRAME_SIZE |
@@: |
add edi, E3C59X_MAX_ETH_FRAME_SIZE |
zero_to_virt edi |
mov eax, edi |
cld |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi, node_addr |
movsd |
movsw |
; copy packet type |
mov [edi], bx |
add edi, 2 |
; copy packet data |
pop esi |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
push ecx |
and ecx, 3 |
rep movsb |
; padding, do we really need it? |
pop ecx |
add ecx, ETH_HLEN |
cmp ecx, ETH_ZLEN |
jae @f |
mov ecx, ETH_ZLEN |
@@: |
; calculate |
mov ebx, ecx |
;test byte [e3c59x_has_hwcksm], 0xff |
;jz @f |
;or ebx, (1 shl 26) ; set AddTcpChecksum |
;@@: |
or ebx, 0x8000 ; transmission complete notification |
or ecx, 0x80000000 ; last fragment |
; program DPD |
mov edi, eax |
pop eax |
and dword [eax+E3C59X_DPD_DN_NEXT_PTR], 0 |
mov dword [eax+E3C59X_DPD_FRAME_START_HDR], ebx |
virt_to_dma edi |
mov dword [eax+E3C59X_DPD_DN_FRAG_ADDR], edi |
mov [eax+E3C59X_DPD_DN_FRAG_LEN], ecx |
; calculate physical address |
virt_to_dma eax |
push eax |
cmp byte [e3c59x_dn_list_ptr_cleared], 0 |
jz .add_to_list |
; write Dn_List_Ptr |
out dx, eax |
jmp .finish |
.add_to_list: |
; DnStall |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, ((110b shl 11)+2) |
out dx, ax |
; wait for DnStall to complete |
mov ecx, 6000 |
.wait_for_stall: |
in ax, dx ; read E3C59X_REG_INT_STATUS |
test ah, 10000b |
jz .dnstall_ok |
dec ecx |
jnz .wait_for_stall |
.dnstall_ok: |
pop eax |
push eax |
mov ebx, [e3c59x_prev_dpd] |
zero_to_virt ebx |
mov [ebx], eax |
lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] |
in eax, dx |
test eax, eax |
jnz .dnunstall |
; if Dn_List_Ptr has been cleared fill it up |
pop eax |
push eax |
out dx, eax |
.dnunstall: |
; DnUnStall |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, ((110b shl 11)+3) |
out dx, ax |
.finish: |
pop eax |
dma_to_zero eax |
mov [e3c59x_prev_dpd], eax |
dma_to_zero edi |
mov [e3c59x_prev_tx_frame], edi |
ret |
;*************************************************************************** |
; Function |
; e3c59x_poll |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Destroyed registers |
; eax, ebx, edx, ecx, edi, esi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_poll: |
jmp dword [e3c59x_receive_function] |
;*************************************************************************** |
; Function |
; e3c59x_vortex_poll |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 ; no packet received |
; al - 1 ; packet received |
; Destroyed registers |
; eax, ebx, edx, ecx, edi, esi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_vortex_poll: |
and word [eth_rx_data_len], 0 ; assume no packet received |
movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC |
.rx_status_loop: |
; examine RxStatus |
lea edx, [ebp+E3C59X_REG_RX_STATUS] |
in ax, dx |
test ax, ax |
jz .finish |
test ah, 0x80 ; rxIncomplete |
jz .check_error |
jmp .finish |
.check_error: |
test ah, 0x40 |
jz .check_length |
; discard the top frame received advancing the next one |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (01000b shl 11) |
out dx, ax |
jmp .rx_status_loop |
.check_length: |
and eax, 0x1fff |
cmp eax, E3C59X_MAX_ETH_PKT_SIZE |
ja .discard_frame ; frame is too long discard it |
.check_dma: |
push eax |
; switch to register window 7 |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 |
out dx, ax |
; check for master operation in progress |
lea edx, [ebp+E3C59X_REG_MASTER_STATUS] |
in ax, dx |
test ah, 0x80 |
jz .read_frame ; no DMA for receiving |
pop eax |
jmp .finish |
.read_frame: |
; program buffer address to read in |
lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] |
if defined E3C59X_LINUX |
mov eax, e3c59x_rx_buff |
zero_to_dma eax |
else |
mov eax, Ether_buffer |
end if |
out dx, eax |
; program frame length |
lea edx, [ebp+E3C59X_REG_MASTER_LEN] |
mov ax, 1560 |
out dx, ax |
; start DMA Up |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (10100b shl 11) ; StartDMAUp |
out dx, ax |
; check for master operation in progress |
.dma_loop: |
lea edx, [ebp+E3C59X_REG_MASTER_STATUS] |
in ax, dx |
test ah, 0x80 |
jnz .dma_loop |
; registrate the received packet length |
pop eax |
mov word [eth_rx_data_len], ax |
; discard the top frame received |
.discard_frame: |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, (01000b shl 11) |
out dx, ax |
.finish: |
; set return value |
cmp word [eth_rx_data_len], 0 |
setne al |
ret |
;*************************************************************************** |
; Function |
; e3c59x_boomerang_poll |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Parameters |
; ebp - io_addr |
; Return value |
; al - 0 ; no packet received |
; al - 1 ; packet received |
; Destroyed registers |
; eax, edx, ecx, edi, esi, ebp |
; |
;*************************************************************************** |
align 4 |
e3c59x_boomerang_poll: |
and word [eth_rx_data_len], 0 ; assume no packet received |
movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC |
; check if packet is uploaded |
mov eax, [e3c59x_curr_upd] |
test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x80 ; upPktComplete |
jnz .check_error |
jmp .finish |
; packet is uploaded check for any error |
.check_error: |
test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x40 ; upError |
jz .copy_packet_length |
and dword [eax+E3C59X_UPD_PKT_STATUS], 0 |
jmp .finish |
.copy_packet_length: |
mov ecx, [eax+E3C59X_UPD_PKT_STATUS] |
and ecx, 0x1fff |
cmp ecx, E3C59X_MAX_ETH_PKT_SIZE |
jbe .copy_packet |
and dword [eax+E3C59X_UPD_PKT_STATUS], 0 |
jmp .finish |
.copy_packet: |
push ecx |
mov word [eth_rx_data_len], cx |
mov esi, [eax+E3C59X_UPD_UP_FRAG_ADDR] |
dma_to_virt esi |
mov edi, Ether_buffer |
shr ecx, 2 ; first copy dword-wise |
cld |
rep movsd ; copy the dwords |
pop ecx |
and ecx, 3 |
rep movsb ; copy the rest bytes |
mov eax, [e3c59x_curr_upd] |
and dword [eax+E3C59X_UPD_PKT_STATUS], 0 |
virt_to_zero eax |
cmp eax, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE |
jb .no_wrap |
; wrap around |
mov eax, e3c59x_upd_buff-E3C59X_UPD_SIZE |
.no_wrap: |
add eax, E3C59X_UPD_SIZE |
zero_to_virt eax |
mov [e3c59x_curr_upd], eax |
.finish: |
; check if the NIC is in the upStall state |
lea edx, [ebp+E3C59X_REG_UP_PKT_STATUS] |
in eax, dx |
test ah, 0x20 ; UpStalled |
jz .noUpUnStall |
; issue upUnStall command |
lea edx, [ebp+E3C59X_REG_COMMAND] |
mov ax, ((110b shl 11)+1) ; upUnStall |
out dx, ax |
.noUpUnStall: |
; set return value |
cmp word [eth_rx_data_len], 0 |
setnz al |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/drivers/forcedeth.inc |
---|
42,236 → 42,236 |
; forcedeth Register Definitions |
;************************************************************************** |
PCI_REG_COMMAND equ 0x04 ; command register |
PCI_REG_COMMAND equ 0x04 ; command register |
PCI_COMMAND_IO equ 0x01 ; Enable response in I/O space |
PCI_COMMAND_MASTER equ 0x04 ; Enable bus mastering |
PCI_LATENCY_TIMER equ 0x0d ; 8 bits |
PCI_COMMAND_IO equ 0x01 ; Enable response in I/O space |
PCI_COMMAND_MASTER equ 0x04 ; Enable bus mastering |
PCI_LATENCY_TIMER equ 0x0d ; 8 bits |
PCI_VENDOR_ID equ 0x00 ; 16 bit |
PCI_REVISION_ID equ 0x08 ; 8 bits |
PCI_VENDOR_ID equ 0x00 ; 16 bit |
PCI_REVISION_ID equ 0x08 ; 8 bits |
PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits |
PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits |
PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits |
PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits |
PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits |
PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits |
PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits |
PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits |
PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits |
PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits |
PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits |
PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits |
PCI_BASE_ADDRESS_SPACE_IO equ 0x01 |
PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) |
PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) |
PCI_BASE_ADDRESS_SPACE_IO equ 0x01 |
PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) |
PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) |
PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 |
PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address |
PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] |
PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address |
PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 |
PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address |
PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] |
PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address |
; NIC specific static variables go here |
PCI_DEVICE_ID_NVIDIA_NVENET_1 equ 0x01c3 |
PCI_DEVICE_ID_NVIDIA_NVENET_2 equ 0x0066 |
PCI_DEVICE_ID_NVIDIA_NVENET_4 equ 0x0086 |
PCI_DEVICE_ID_NVIDIA_NVENET_5 equ 0x008c |
PCI_DEVICE_ID_NVIDIA_NVENET_3 equ 0x00d6 |
PCI_DEVICE_ID_NVIDIA_NVENET_7 equ 0x00df |
PCI_DEVICE_ID_NVIDIA_NVENET_6 equ 0x00e6 |
PCI_DEVICE_ID_NVIDIA_NVENET_8 equ 0x0056 |
PCI_DEVICE_ID_NVIDIA_NVENET_9 equ 0x0057 |
PCI_DEVICE_ID_NVIDIA_NVENET_10 equ 0x0037 |
PCI_DEVICE_ID_NVIDIA_NVENET_11 equ 0x0038 |
PCI_DEVICE_ID_NVIDIA_NVENET_12 equ 0x0268 |
PCI_DEVICE_ID_NVIDIA_NVENET_13 equ 0x0269 |
PCI_DEVICE_ID_NVIDIA_NVENET_14 equ 0x0372 |
PCI_DEVICE_ID_NVIDIA_NVENET_15 equ 0x0373 |
PCI_DEVICE_ID_NVIDIA_NVENET_1 equ 0x01c3 |
PCI_DEVICE_ID_NVIDIA_NVENET_2 equ 0x0066 |
PCI_DEVICE_ID_NVIDIA_NVENET_4 equ 0x0086 |
PCI_DEVICE_ID_NVIDIA_NVENET_5 equ 0x008c |
PCI_DEVICE_ID_NVIDIA_NVENET_3 equ 0x00d6 |
PCI_DEVICE_ID_NVIDIA_NVENET_7 equ 0x00df |
PCI_DEVICE_ID_NVIDIA_NVENET_6 equ 0x00e6 |
PCI_DEVICE_ID_NVIDIA_NVENET_8 equ 0x0056 |
PCI_DEVICE_ID_NVIDIA_NVENET_9 equ 0x0057 |
PCI_DEVICE_ID_NVIDIA_NVENET_10 equ 0x0037 |
PCI_DEVICE_ID_NVIDIA_NVENET_11 equ 0x0038 |
PCI_DEVICE_ID_NVIDIA_NVENET_12 equ 0x0268 |
PCI_DEVICE_ID_NVIDIA_NVENET_13 equ 0x0269 |
PCI_DEVICE_ID_NVIDIA_NVENET_14 equ 0x0372 |
PCI_DEVICE_ID_NVIDIA_NVENET_15 equ 0x0373 |
ETH_DATA_LEN equ 1500 |
ETH_DATA_LEN equ 1500 |
; rx/tx mac addr + type + vlan + align + slack |
RX_NIC_BUFSIZE equ (ETH_DATA_LEN + 64) |
RX_NIC_BUFSIZE equ (ETH_DATA_LEN + 64) |
; even more slack |
RX_ALLOC_BUFSIZE equ (ETH_DATA_LEN + 128) |
RX_ALLOC_BUFSIZE equ (ETH_DATA_LEN + 128) |
NvRegIrqStatus equ 0x00 |
NvRegIrqMask equ 0x04 |
NvRegUnknownSetupReg6 equ 0x08 |
NvRegPollingInterval equ 0x0c |
NvRegMacReset equ 0x3c |
NvRegMisc1 equ 0x80 |
NvRegTransmitterControl equ 0x84 |
NvRegTransmitterStatus equ 0x88 |
NvRegPacketFilterFlags equ 0x8c |
NvRegOffloadConfig equ 0x90 |
NvRegReceiverControl equ 0x94 |
NvRegReceiverStatus equ 0x98 |
NvRegRandomSeed equ 0x9c |
NvRegUnknownSetupReg1 equ 0xA0 |
NvRegUnknownSetupReg2 equ 0xA4 |
NvRegMacAddrA equ 0xA8 ; MAC address low |
NvRegMacAddrB equ 0xAC ; MAC address high |
NvRegMulticastAddrA equ 0xB0 |
NvRegMulticastAddrB equ 0xB4 |
NvRegMulticastMaskA equ 0xB8 |
NvRegMulticastMaskB equ 0xBC |
NvRegPhyInterface equ 0xC0 |
NvRegTxRingPhysAddr equ 0x100 |
NvRegRxRingPhysAddr equ 0x104 |
NvRegRingSizes equ 0x108 |
NvRegUnknownTransmitterReg equ 0x10c |
NvRegLinkSpeed equ 0x110 |
NvRegUnknownSetupReg5 equ 0x130 |
NvRegUnknownSetupReg3 equ 0x13c |
NvRegTxRxControl equ 0x144 |
NvRegMIIStatus equ 0x180 |
NvRegUnknownSetupReg4 equ 0x184 |
NvRegAdapterControl equ 0x188 |
NvRegMIISpeed equ 0x18c |
NvRegMIIControl equ 0x190 |
NvRegMIIData equ 0x194 |
NvRegWakeUpFlags equ 0x200 |
NvRegPowerState equ 0x26c |
NvRegPowerState2 equ 0x600 |
NvRegIrqStatus equ 0x00 |
NvRegIrqMask equ 0x04 |
NvRegUnknownSetupReg6 equ 0x08 |
NvRegPollingInterval equ 0x0c |
NvRegMacReset equ 0x3c |
NvRegMisc1 equ 0x80 |
NvRegTransmitterControl equ 0x84 |
NvRegTransmitterStatus equ 0x88 |
NvRegPacketFilterFlags equ 0x8c |
NvRegOffloadConfig equ 0x90 |
NvRegReceiverControl equ 0x94 |
NvRegReceiverStatus equ 0x98 |
NvRegRandomSeed equ 0x9c |
NvRegUnknownSetupReg1 equ 0xA0 |
NvRegUnknownSetupReg2 equ 0xA4 |
NvRegMacAddrA equ 0xA8 ; MAC address low |
NvRegMacAddrB equ 0xAC ; MAC address high |
NvRegMulticastAddrA equ 0xB0 |
NvRegMulticastAddrB equ 0xB4 |
NvRegMulticastMaskA equ 0xB8 |
NvRegMulticastMaskB equ 0xBC |
NvRegPhyInterface equ 0xC0 |
NvRegTxRingPhysAddr equ 0x100 |
NvRegRxRingPhysAddr equ 0x104 |
NvRegRingSizes equ 0x108 |
NvRegUnknownTransmitterReg equ 0x10c |
NvRegLinkSpeed equ 0x110 |
NvRegUnknownSetupReg5 equ 0x130 |
NvRegUnknownSetupReg3 equ 0x13c |
NvRegTxRxControl equ 0x144 |
NvRegMIIStatus equ 0x180 |
NvRegUnknownSetupReg4 equ 0x184 |
NvRegAdapterControl equ 0x188 |
NvRegMIISpeed equ 0x18c |
NvRegMIIControl equ 0x190 |
NvRegMIIData equ 0x194 |
NvRegWakeUpFlags equ 0x200 |
NvRegPowerState equ 0x26c |
NvRegPowerState2 equ 0x600 |
NVREG_UNKSETUP1_VAL equ 0x16070f |
NVREG_UNKSETUP2_VAL equ 0x16 |
NVREG_UNKSETUP3_VAL1 equ 0x200010 |
NVREG_UNKSETUP4_VAL equ 8 |
NVREG_UNKSETUP5_BIT31 equ (1 shl 31) |
NVREG_UNKSETUP6_VAL equ 3 |
NVREG_UNKSETUP1_VAL equ 0x16070f |
NVREG_UNKSETUP2_VAL equ 0x16 |
NVREG_UNKSETUP3_VAL1 equ 0x200010 |
NVREG_UNKSETUP4_VAL equ 8 |
NVREG_UNKSETUP5_BIT31 equ (1 shl 31) |
NVREG_UNKSETUP6_VAL equ 3 |
NVREG_TXRXCTL_RXCHECK equ 0x0400 |
NVREG_MIISTAT_ERROR equ 0x0001 |
NVREG_MIISTAT_MASK equ 0x000f |
NVREG_MIISTAT_MASK2 equ 0x000f |
NVREG_MIICTL_INUSE equ 0x08000 |
NVREG_MIICTL_WRITE equ 0x00400 |
NVREG_MIICTL_ADDRSHIFT equ 5 |
NVREG_TXRXCTL_RXCHECK equ 0x0400 |
NVREG_MIISTAT_ERROR equ 0x0001 |
NVREG_MIISTAT_MASK equ 0x000f |
NVREG_MIISTAT_MASK2 equ 0x000f |
NVREG_MIICTL_INUSE equ 0x08000 |
NVREG_MIICTL_WRITE equ 0x00400 |
NVREG_MIICTL_ADDRSHIFT equ 5 |
NVREG_MIISPEED_BIT8 equ (1 shl 8) |
NVREG_MIIDELAY equ 5 |
NVREG_MIISPEED_BIT8 equ (1 shl 8) |
NVREG_MIIDELAY equ 5 |
NVREG_IRQ_RX_ERROR equ 0x0001 |
NVREG_IRQ_RX equ 0x0002 |
NVREG_IRQ_RX_NOBUF equ 0x0004 |
NVREG_IRQ_LINK equ 0x0040 |
NVREG_IRQ_TIMER equ 0x0020 |
NVREG_IRQMASK_WANTED_2 equ 0x0147 |
NVREG_IRQ_RX_ERROR equ 0x0001 |
NVREG_IRQ_RX equ 0x0002 |
NVREG_IRQ_RX_NOBUF equ 0x0004 |
NVREG_IRQ_LINK equ 0x0040 |
NVREG_IRQ_TIMER equ 0x0020 |
NVREG_IRQMASK_WANTED_2 equ 0x0147 |
NVREG_IRQ_RX_ALL equ (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) |
NVREG_IRQ_TX_ALL equ 0 ; ??????????? |
NVREG_IRQ_OTHER_ALL equ (NVREG_IRQ_LINK or NVREG_IRQ_TIMER) |
NVREG_IRQ_RX_ALL equ (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) |
NVREG_IRQ_TX_ALL equ 0 ; ??????????? |
NVREG_IRQ_OTHER_ALL equ (NVREG_IRQ_LINK or NVREG_IRQ_TIMER) |
NVREG_IRQSTAT_MASK equ 0x1ff |
NVREG_IRQSTAT_MASK equ 0x1ff |
NVREG_TXRXCTL_KICK equ 0x0001 |
NVREG_TXRXCTL_BIT1 equ 0x0002 |
NVREG_TXRXCTL_BIT2 equ 0x0004 |
NVREG_TXRXCTL_IDLE equ 0x0008 |
NVREG_TXRXCTL_RESET equ 0x0010 |
NVREG_TXRXCTL_RXCHECK equ 0x0400 |
NVREG_TXRXCTL_KICK equ 0x0001 |
NVREG_TXRXCTL_BIT1 equ 0x0002 |
NVREG_TXRXCTL_BIT2 equ 0x0004 |
NVREG_TXRXCTL_IDLE equ 0x0008 |
NVREG_TXRXCTL_RESET equ 0x0010 |
NVREG_TXRXCTL_RXCHECK equ 0x0400 |
NVREG_MCASTADDRA_FORCE equ 0x01 |
NVREG_MCASTADDRA_FORCE equ 0x01 |
NVREG_MAC_RESET_ASSERT equ 0x0F3 |
NVREG_MAC_RESET_ASSERT equ 0x0F3 |
NVREG_MISC1_HD equ 0x02 |
NVREG_MISC1_FORCE equ 0x3b0f3c |
NVREG_MISC1_HD equ 0x02 |
NVREG_MISC1_FORCE equ 0x3b0f3c |
NVREG_PFF_ALWAYS equ 0x7F0008 |
NVREG_PFF_PROMISC equ 0x80 |
NVREG_PFF_MYADDR equ 0x20 |
NVREG_PFF_ALWAYS equ 0x7F0008 |
NVREG_PFF_PROMISC equ 0x80 |
NVREG_PFF_MYADDR equ 0x20 |
NVREG_OFFLOAD_HOMEPHY equ 0x601 |
NVREG_OFFLOAD_NORMAL equ RX_NIC_BUFSIZE |
NVREG_OFFLOAD_HOMEPHY equ 0x601 |
NVREG_OFFLOAD_NORMAL equ RX_NIC_BUFSIZE |
NVREG_RNDSEED_MASK equ 0x00ff |
NVREG_RNDSEED_FORCE equ 0x7f00 |
NVREG_RNDSEED_FORCE2 equ 0x2d00 |
NVREG_RNDSEED_FORCE3 equ 0x7400 |
NVREG_RNDSEED_MASK equ 0x00ff |
NVREG_RNDSEED_FORCE equ 0x7f00 |
NVREG_RNDSEED_FORCE2 equ 0x2d00 |
NVREG_RNDSEED_FORCE3 equ 0x7400 |
; NVREG_POLL_DEFAULT is the interval length of the timer source on the nic |
; NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms |
NVREG_POLL_DEFAULT equ 970 |
NVREG_POLL_DEFAULT equ 970 |
NVREG_ADAPTCTL_START equ 0x02 |
NVREG_ADAPTCTL_LINKUP equ 0x04 |
NVREG_ADAPTCTL_PHYVALID equ 0x40000 |
NVREG_ADAPTCTL_RUNNING equ 0x100000 |
NVREG_ADAPTCTL_PHYSHIFT equ 24 |
NVREG_ADAPTCTL_START equ 0x02 |
NVREG_ADAPTCTL_LINKUP equ 0x04 |
NVREG_ADAPTCTL_PHYVALID equ 0x40000 |
NVREG_ADAPTCTL_RUNNING equ 0x100000 |
NVREG_ADAPTCTL_PHYSHIFT equ 24 |
NVREG_WAKEUPFLAGS_VAL equ 0x7770 |
NVREG_WAKEUPFLAGS_VAL equ 0x7770 |
NVREG_POWERSTATE_POWEREDUP equ 0x8000 |
NVREG_POWERSTATE_VALID equ 0x0100 |
NVREG_POWERSTATE_MASK equ 0x0003 |
NVREG_POWERSTATE_D0 equ 0x0000 |
NVREG_POWERSTATE_D1 equ 0x0001 |
NVREG_POWERSTATE_D2 equ 0x0002 |
NVREG_POWERSTATE_D3 equ 0x0003 |
NVREG_POWERSTATE_POWEREDUP equ 0x8000 |
NVREG_POWERSTATE_VALID equ 0x0100 |
NVREG_POWERSTATE_MASK equ 0x0003 |
NVREG_POWERSTATE_D0 equ 0x0000 |
NVREG_POWERSTATE_D1 equ 0x0001 |
NVREG_POWERSTATE_D2 equ 0x0002 |
NVREG_POWERSTATE_D3 equ 0x0003 |
NVREG_POWERSTATE2_POWERUP_MASK equ 0x0F11 |
NVREG_POWERSTATE2_POWERUP_REV_A3 equ 0x0001 |
NVREG_POWERSTATE2_POWERUP_MASK equ 0x0F11 |
NVREG_POWERSTATE2_POWERUP_REV_A3 equ 0x0001 |
NVREG_RCVCTL_START equ 0x01 |
NVREG_RCVSTAT_BUSY equ 0x01 |
NVREG_RCVCTL_START equ 0x01 |
NVREG_RCVSTAT_BUSY equ 0x01 |
NVREG_XMITCTL_START equ 0x01 |
NVREG_XMITCTL_START equ 0x01 |
NVREG_LINKSPEED_FORCE equ 0x10000 |
NVREG_LINKSPEED_10 equ 1000 |
NVREG_LINKSPEED_100 equ 100 |
NVREG_LINKSPEED_1000 equ 50 |
NVREG_LINKSPEED_FORCE equ 0x10000 |
NVREG_LINKSPEED_10 equ 1000 |
NVREG_LINKSPEED_100 equ 100 |
NVREG_LINKSPEED_1000 equ 50 |
NVREG_RINGSZ_TXSHIFT equ 0 |
NVREG_RINGSZ_RXSHIFT equ 16 |
NVREG_RINGSZ_TXSHIFT equ 0 |
NVREG_RINGSZ_RXSHIFT equ 16 |
LPA_1000FULL equ 0x0800 |
LPA_1000FULL equ 0x0800 |
; Link partner ability register. |
LPA_SLCT equ 0x001f ; Same as advertise selector |
LPA_10HALF equ 0x0020 ; Can do 10mbps half-duplex |
LPA_10FULL equ 0x0040 ; Can do 10mbps full-duplex |
LPA_100HALF equ 0x0080 ; Can do 100mbps half-duplex |
LPA_100FULL equ 0x0100 ; Can do 100mbps full-duplex |
LPA_100BASE4 equ 0x0200 ; Can do 100mbps 4k packets |
LPA_RESV equ 0x1c00 ; Unused... |
LPA_RFAULT equ 0x2000 ; Link partner faulted |
LPA_LPACK equ 0x4000 ; Link partner acked us |
LPA_NPAGE equ 0x8000 ; Next page bit |
LPA_SLCT equ 0x001f ; Same as advertise selector |
LPA_10HALF equ 0x0020 ; Can do 10mbps half-duplex |
LPA_10FULL equ 0x0040 ; Can do 10mbps full-duplex |
LPA_100HALF equ 0x0080 ; Can do 100mbps half-duplex |
LPA_100FULL equ 0x0100 ; Can do 100mbps full-duplex |
LPA_100BASE4 equ 0x0200 ; Can do 100mbps 4k packets |
LPA_RESV equ 0x1c00 ; Unused... |
LPA_RFAULT equ 0x2000 ; Link partner faulted |
LPA_LPACK equ 0x4000 ; Link partner acked us |
LPA_NPAGE equ 0x8000 ; Next page bit |
MII_READ equ (-1) |
MII_PHYSID1 equ 0x02 ; PHYS ID 1 |
MII_PHYSID2 equ 0x03 ; PHYS ID 2 |
MII_BMCR equ 0x00 ; Basic mode control register |
MII_BMSR equ 0x01 ; Basic mode status register |
MII_ADVERTISE equ 0x04 ; Advertisement control reg |
MII_LPA equ 0x05 ; Link partner ability reg |
MII_SREVISION equ 0x16 ; Silicon revision |
MII_RESV1 equ 0x17 ; Reserved... |
MII_NCONFIG equ 0x1c ; Network interface config |
MII_READ equ (-1) |
MII_PHYSID1 equ 0x02 ; PHYS ID 1 |
MII_PHYSID2 equ 0x03 ; PHYS ID 2 |
MII_BMCR equ 0x00 ; Basic mode control register |
MII_BMSR equ 0x01 ; Basic mode status register |
MII_ADVERTISE equ 0x04 ; Advertisement control reg |
MII_LPA equ 0x05 ; Link partner ability reg |
MII_SREVISION equ 0x16 ; Silicon revision |
MII_RESV1 equ 0x17 ; Reserved... |
MII_NCONFIG equ 0x1c ; Network interface config |
; PHY defines |
PHY_OUI_MARVELL equ 0x5043 |
PHY_OUI_CICADA equ 0x03f1 |
PHYID1_OUI_MASK equ 0x03ff |
PHYID1_OUI_SHFT equ 6 |
PHYID2_OUI_MASK equ 0xfc00 |
PHYID2_OUI_SHFT equ 10 |
PHY_INIT1 equ 0x0f000 |
PHY_INIT2 equ 0x0e00 |
PHY_INIT3 equ 0x01000 |
PHY_INIT4 equ 0x0200 |
PHY_INIT5 equ 0x0004 |
PHY_INIT6 equ 0x02000 |
PHY_GIGABIT equ 0x0100 |
PHY_OUI_MARVELL equ 0x5043 |
PHY_OUI_CICADA equ 0x03f1 |
PHYID1_OUI_MASK equ 0x03ff |
PHYID1_OUI_SHFT equ 6 |
PHYID2_OUI_MASK equ 0xfc00 |
PHYID2_OUI_SHFT equ 10 |
PHY_INIT1 equ 0x0f000 |
PHY_INIT2 equ 0x0e00 |
PHY_INIT3 equ 0x01000 |
PHY_INIT4 equ 0x0200 |
PHY_INIT5 equ 0x0004 |
PHY_INIT6 equ 0x02000 |
PHY_GIGABIT equ 0x0100 |
PHY_TIMEOUT equ 0x1 |
PHY_ERROR equ 0x2 |
PHY_TIMEOUT equ 0x1 |
PHY_ERROR equ 0x2 |
PHY_100 equ 0x1 |
PHY_1000 equ 0x2 |
PHY_HALF equ 0x100 |
PHY_100 equ 0x1 |
PHY_1000 equ 0x2 |
PHY_HALF equ 0x100 |
PHY_RGMII equ 0x10000000 |
PHY_RGMII equ 0x10000000 |
; desc_ver values: |
; This field has two purposes: |
278,176 → 278,176 |
; - Newer nics uses a different ring layout. The layout is selected by |
; comparing np->desc_ver with DESC_VER_xy. |
; - It contains bits that are forced on when writing to NvRegTxRxControl. |
DESC_VER_1 equ 0x0 |
DESC_VER_2 equ (0x02100 or NVREG_TXRXCTL_RXCHECK) |
DESC_VER_1 equ 0x0 |
DESC_VER_2 equ (0x02100 or NVREG_TXRXCTL_RXCHECK) |
MAC_ADDR_LEN equ 6 |
MAC_ADDR_LEN equ 6 |
NV_TX_LASTPACKET equ (1 shl 16) |
NV_TX_RETRYERROR equ (1 shl 19) |
NV_TX_LASTPACKET1 equ (1 shl 24) |
NV_TX_DEFERRED equ (1 shl 26) |
NV_TX_CARRIERLOST equ (1 shl 27) |
NV_TX_LATECOLLISION equ (1 shl 28) |
NV_TX_UNDERFLOW equ (1 shl 29) |
NV_TX_ERROR equ (1 shl 30) |
NV_TX_VALID equ (1 shl 31) |
NV_TX_LASTPACKET equ (1 shl 16) |
NV_TX_RETRYERROR equ (1 shl 19) |
NV_TX_LASTPACKET1 equ (1 shl 24) |
NV_TX_DEFERRED equ (1 shl 26) |
NV_TX_CARRIERLOST equ (1 shl 27) |
NV_TX_LATECOLLISION equ (1 shl 28) |
NV_TX_UNDERFLOW equ (1 shl 29) |
NV_TX_ERROR equ (1 shl 30) |
NV_TX_VALID equ (1 shl 31) |
NV_TX2_LASTPACKET equ (1 shl 29) |
NV_TX2_RETRYERROR equ (1 shl 18) |
NV_TX2_LASTPACKET1 equ (1 shl 23) |
NV_TX2_DEFERRED equ (1 shl 25) |
NV_TX2_CARRIERLOST equ (1 shl 26) |
NV_TX2_LATECOLLISION equ (1 shl 27) |
NV_TX2_UNDERFLOW equ (1 shl 28) |
NV_TX2_LASTPACKET equ (1 shl 29) |
NV_TX2_RETRYERROR equ (1 shl 18) |
NV_TX2_LASTPACKET1 equ (1 shl 23) |
NV_TX2_DEFERRED equ (1 shl 25) |
NV_TX2_CARRIERLOST equ (1 shl 26) |
NV_TX2_LATECOLLISION equ (1 shl 27) |
NV_TX2_UNDERFLOW equ (1 shl 28) |
; error and valid are the same for both |
NV_TX2_ERROR equ (1 shl 30) |
NV_TX2_VALID equ (1 shl 31) |
NV_TX2_ERROR equ (1 shl 30) |
NV_TX2_VALID equ (1 shl 31) |
NV_RX_DESCRIPTORVALID equ (1 shl 16) |
NV_RX_AVAIL equ (1 shl 31) |
NV_RX_DESCRIPTORVALID equ (1 shl 16) |
NV_RX_AVAIL equ (1 shl 31) |
NV_RX2_DESCRIPTORVALID equ (1 shl 29) |
NV_RX2_DESCRIPTORVALID equ (1 shl 29) |
RX_RING equ 4 |
TX_RING equ 2 |
RX_RING equ 4 |
TX_RING equ 2 |
FLAG_MASK_V1 equ 0xffff0000 |
FLAG_MASK_V2 equ 0xffffc000 |
LEN_MASK_V1 equ (0xffffffff xor FLAG_MASK_V1) |
LEN_MASK_V2 equ (0xffffffff xor FLAG_MASK_V2) |
FLAG_MASK_V1 equ 0xffff0000 |
FLAG_MASK_V2 equ 0xffffc000 |
LEN_MASK_V1 equ (0xffffffff xor FLAG_MASK_V1) |
LEN_MASK_V2 equ (0xffffffff xor FLAG_MASK_V2) |
; Miscelaneous hardware related defines: |
NV_PCI_REGSZ_VER1 equ 0x270 |
NV_PCI_REGSZ_VER2 equ 0x604 |
NV_PCI_REGSZ_VER1 equ 0x270 |
NV_PCI_REGSZ_VER2 equ 0x604 |
; various timeout delays: all in usec |
NV_TXRX_RESET_DELAY equ 4 |
NV_TXSTOP_DELAY1 equ 10 |
NV_TXSTOP_DELAY1MAX equ 500000 |
NV_TXSTOP_DELAY2 equ 100 |
NV_RXSTOP_DELAY1 equ 10 |
NV_RXSTOP_DELAY1MAX equ 500000 |
NV_RXSTOP_DELAY2 equ 100 |
NV_SETUP5_DELAY equ 5 |
NV_SETUP5_DELAYMAX equ 50000 |
NV_POWERUP_DELAY equ 5 |
NV_POWERUP_DELAYMAX equ 5000 |
NV_MIIBUSY_DELAY equ 50 |
NV_MIIPHY_DELAY equ 10 |
NV_MIIPHY_DELAYMAX equ 10000 |
NV_MAC_RESET_DELAY equ 64 |
NV_WAKEUPPATTERNS equ 5 |
NV_WAKEUPMASKENTRIES equ 4 |
NV_TXRX_RESET_DELAY equ 4 |
NV_TXSTOP_DELAY1 equ 10 |
NV_TXSTOP_DELAY1MAX equ 500000 |
NV_TXSTOP_DELAY2 equ 100 |
NV_RXSTOP_DELAY1 equ 10 |
NV_RXSTOP_DELAY1MAX equ 500000 |
NV_RXSTOP_DELAY2 equ 100 |
NV_SETUP5_DELAY equ 5 |
NV_SETUP5_DELAYMAX equ 50000 |
NV_POWERUP_DELAY equ 5 |
NV_POWERUP_DELAYMAX equ 5000 |
NV_MIIBUSY_DELAY equ 50 |
NV_MIIPHY_DELAY equ 10 |
NV_MIIPHY_DELAYMAX equ 10000 |
NV_MAC_RESET_DELAY equ 64 |
NV_WAKEUPPATTERNS equ 5 |
NV_WAKEUPMASKENTRIES equ 4 |
; Advertisement control register. |
ADVERTISE_SLCT equ 0x001f ; Selector bits |
ADVERTISE_CSMA equ 0x0001 ; Only selector supported |
ADVERTISE_10HALF equ 0x0020 ; Try for 10mbps half-duplex |
ADVERTISE_10FULL equ 0x0040 ; Try for 10mbps full-duplex |
ADVERTISE_100HALF equ 0x0080 ; Try for 100mbps half-duplex |
ADVERTISE_100FULL equ 0x0100 ; Try for 100mbps full-duplex |
ADVERTISE_100BASE4 equ 0x0200 ; Try for 100mbps 4k packets |
ADVERTISE_RESV equ 0x1c00 ; Unused... |
ADVERTISE_RFAULT equ 0x2000 ; Say we can detect faults |
ADVERTISE_LPACK equ 0x4000 ; Ack link partners response |
ADVERTISE_NPAGE equ 0x8000 ; Next page bit |
ADVERTISE_SLCT equ 0x001f ; Selector bits |
ADVERTISE_CSMA equ 0x0001 ; Only selector supported |
ADVERTISE_10HALF equ 0x0020 ; Try for 10mbps half-duplex |
ADVERTISE_10FULL equ 0x0040 ; Try for 10mbps full-duplex |
ADVERTISE_100HALF equ 0x0080 ; Try for 100mbps half-duplex |
ADVERTISE_100FULL equ 0x0100 ; Try for 100mbps full-duplex |
ADVERTISE_100BASE4 equ 0x0200 ; Try for 100mbps 4k packets |
ADVERTISE_RESV equ 0x1c00 ; Unused... |
ADVERTISE_RFAULT equ 0x2000 ; Say we can detect faults |
ADVERTISE_LPACK equ 0x4000 ; Ack link partners response |
ADVERTISE_NPAGE equ 0x8000 ; Next page bit |
ADVERTISE_FULL equ (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA) |
ADVERTISE_ALL equ (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL) |
ADVERTISE_FULL equ (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA) |
ADVERTISE_ALL equ (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL) |
MII_1000BT_CR equ 0x09 |
MII_1000BT_SR equ 0x0a |
ADVERTISE_1000FULL equ 0x0200 |
ADVERTISE_1000HALF equ 0x0100 |
MII_1000BT_CR equ 0x09 |
MII_1000BT_SR equ 0x0a |
ADVERTISE_1000FULL equ 0x0200 |
ADVERTISE_1000HALF equ 0x0100 |
BMCR_ANRESTART equ 0x0200 ; Auto negotiation restart |
BMCR_ANENABLE equ 0x1000 ; Enable auto negotiation |
BMCR_SPEED100 equ 0x2000 ; Select 100Mbps |
BMCR_LOOPBACK equ 0x4000 ; TXD loopback bits |
BMCR_RESET equ 0x8000 ; Reset the DP83840 |
BMCR_ANRESTART equ 0x0200 ; Auto negotiation restart |
BMCR_ANENABLE equ 0x1000 ; Enable auto negotiation |
BMCR_SPEED100 equ 0x2000 ; Select 100Mbps |
BMCR_LOOPBACK equ 0x4000 ; TXD loopback bits |
BMCR_RESET equ 0x8000 ; Reset the DP83840 |
; Basic mode status register. |
BMSR_ERCAP equ 0x0001 ; Ext-reg capability |
BMSR_JCD equ 0x0002 ; Jabber detected |
BMSR_LSTATUS equ 0x0004 ; Link status |
BMSR_ANEGCAPABLE equ 0x0008 ; Able to do auto-negotiation |
BMSR_RFAULT equ 0x0010 ; Remote fault detected |
BMSR_ANEGCOMPLETE equ 0x0020 ; Auto-negotiation complete |
BMSR_RESV equ 0x07c0 ; Unused... |
BMSR_10HALF equ 0x0800 ; Can do 10mbps, half-duplex |
BMSR_10FULL equ 0x1000 ; Can do 10mbps, full-duplex |
BMSR_100HALF equ 0x2000 ; Can do 100mbps, half-duplex |
BMSR_100FULL equ 0x4000 ; Can do 100mbps, full-duplex |
BMSR_100BASE4 equ 0x8000 ; Can do 100mbps, 4k packets |
BMSR_ERCAP equ 0x0001 ; Ext-reg capability |
BMSR_JCD equ 0x0002 ; Jabber detected |
BMSR_LSTATUS equ 0x0004 ; Link status |
BMSR_ANEGCAPABLE equ 0x0008 ; Able to do auto-negotiation |
BMSR_RFAULT equ 0x0010 ; Remote fault detected |
BMSR_ANEGCOMPLETE equ 0x0020 ; Auto-negotiation complete |
BMSR_RESV equ 0x07c0 ; Unused... |
BMSR_10HALF equ 0x0800 ; Can do 10mbps, half-duplex |
BMSR_10FULL equ 0x1000 ; Can do 10mbps, full-duplex |
BMSR_100HALF equ 0x2000 ; Can do 100mbps, half-duplex |
BMSR_100FULL equ 0x4000 ; Can do 100mbps, full-duplex |
BMSR_100BASE4 equ 0x8000 ; Can do 100mbps, 4k packets |
ETH_ALEN equ 6 |
ETH_HLEN equ (2 * ETH_ALEN + 2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
ETH_ALEN equ 6 |
ETH_HLEN equ (2 * ETH_ALEN + 2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
uglobal |
forcedeth_mmio_addr dd 0 ; memory map physical address |
forcedeth_mmio_size dd 0 ; size of memory bar |
forcedeth_vendor_id dw 0 ; Vendor ID |
forcedeth_device_id dw 0 ; Device ID |
forcedeth_orig_mac0 dd 0 ; MAC |
forcedeth_orig_mac1 dd 0 ; MAC |
forcedeth_mapio_addr dd 0 ; mapped IO address |
forcedeth_txflags dd 0 ; |
forcedeth_desc_ver dd 0 ; |
forcedeth_irqmask dd 0 ; IRQ-mask |
forcedeth_wolenabled dd 0 ; WOL |
forcedeth_in_shutdown dd 0 ; |
forcedeth_cur_rx dd 0 ; |
forcedeth_refill_rx dd 0 ; |
forcedeth_phyaddr dd 0 ; |
forcedeth_phy_oui dd 0 ; |
forcedeth_gigabit dd 0 ; |
forcedeth_needs_mac_reset dd 0 ; |
forcedeth_linkspeed dd 0 ; |
forcedeth_duplex dd 0 ; |
forcedeth_next_tx dd 0 ; next TX descriptor number |
forcedeth_nic_tx dd 0 ; ??? d'nt used ??? |
forcedeth_packetlen dd 0 ; |
forcedeth_nocable dd 0 ; no cable present |
forcedeth_mmio_addr dd 0 ; memory map physical address |
forcedeth_mmio_size dd 0 ; size of memory bar |
forcedeth_vendor_id dw 0 ; Vendor ID |
forcedeth_device_id dw 0 ; Device ID |
forcedeth_orig_mac0 dd 0 ; MAC |
forcedeth_orig_mac1 dd 0 ; MAC |
forcedeth_mapio_addr dd 0 ; mapped IO address |
forcedeth_txflags dd 0 ; |
forcedeth_desc_ver dd 0 ; |
forcedeth_irqmask dd 0 ; IRQ-mask |
forcedeth_wolenabled dd 0 ; WOL |
forcedeth_in_shutdown dd 0 ; |
forcedeth_cur_rx dd 0 ; |
forcedeth_refill_rx dd 0 ; |
forcedeth_phyaddr dd 0 ; |
forcedeth_phy_oui dd 0 ; |
forcedeth_gigabit dd 0 ; |
forcedeth_needs_mac_reset dd 0 ; |
forcedeth_linkspeed dd 0 ; |
forcedeth_duplex dd 0 ; |
forcedeth_next_tx dd 0 ; next TX descriptor number |
forcedeth_nic_tx dd 0 ; ??? d'nt used ??? |
forcedeth_packetlen dd 0 ; |
forcedeth_nocable dd 0 ; no cable present |
endg |
struc forcedeth_TxDesc { |
.PacketBuffer dd ? |
.FlagLen dd ? |
struc forcedeth_TxDesc { |
.PacketBuffer dd ? |
.FlagLen dd ? |
} |
virtual at 0 |
forcedeth_TxDesc forcedeth_TxDesc |
sizeof.forcedeth_TxDesc = $ - forcedeth_TxDesc |
virtual at 0 |
forcedeth_TxDesc forcedeth_TxDesc |
sizeof.forcedeth_TxDesc = $ - forcedeth_TxDesc |
end virtual |
struc forcedeth_RxDesc { |
.PacketBuffer dd ? |
.FlagLen dd ? |
struc forcedeth_RxDesc { |
.PacketBuffer dd ? |
.FlagLen dd ? |
} |
virtual at 0 |
forcedeth_RxDesc forcedeth_RxDesc |
sizeof.forcedeth_RxDesc = $ - forcedeth_RxDesc |
virtual at 0 |
forcedeth_RxDesc forcedeth_RxDesc |
sizeof.forcedeth_RxDesc = $ - forcedeth_RxDesc |
end virtual |
virtual at eth_data_start |
; Define the TX Descriptor |
align 256 |
forcedeth_tx_ring rb TX_RING * sizeof.forcedeth_TxDesc |
; Create a static buffer of size RX_BUF_SZ for each |
; TX Descriptor. All descriptors point to a |
; part of this buffer |
align 256 |
forcedeth_txb rb TX_RING * RX_NIC_BUFSIZE |
; Define the RX Descriptor |
align 256 |
forcedeth_rx_ring rb RX_RING * sizeof.forcedeth_RxDesc |
; Create a static buffer of size RX_BUF_SZ for each |
; RX Descriptor. All descriptors point to a |
; part of this buffer |
align 256 |
forcedeth_rxb rb RX_RING * RX_NIC_BUFSIZE |
; Define the TX Descriptor |
align 256 |
forcedeth_tx_ring rb TX_RING * sizeof.forcedeth_TxDesc |
; Create a static buffer of size RX_BUF_SZ for each |
; TX Descriptor. All descriptors point to a |
; part of this buffer |
align 256 |
forcedeth_txb rb TX_RING * RX_NIC_BUFSIZE |
; Define the RX Descriptor |
align 256 |
forcedeth_rx_ring rb RX_RING * sizeof.forcedeth_RxDesc |
; Create a static buffer of size RX_BUF_SZ for each |
; RX Descriptor. All descriptors point to a |
; part of this buffer |
align 256 |
forcedeth_rxb rb RX_RING * RX_NIC_BUFSIZE |
end virtual |
462,266 → 462,266 |
;*************************************************************************** |
forcedeth_reset: |
; 1) erase previous misconfiguration |
; 4.1-1: stop adapter: ignored, 4.3 seems to be overkill |
; 1) erase previous misconfiguration |
; 4.1-1: stop adapter: ignored, 4.3 seems to be overkill |
; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE |
; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE |
; writel(0, base + NvRegMulticastAddrB) |
mov dword [edi+NvRegMulticastAddrB], 0 |
; writel(0, base + NvRegMulticastMaskA) |
mov dword [edi+NvRegMulticastMaskA], 0 |
; writel(0, base + NvRegMulticastMaskB) |
mov dword [edi+NvRegMulticastMaskB], 0 |
; writel(0, base + NvRegMulticastAddrB) |
mov dword [edi+NvRegMulticastAddrB], 0 |
; writel(0, base + NvRegMulticastMaskA) |
mov dword [edi+NvRegMulticastMaskA], 0 |
; writel(0, base + NvRegMulticastMaskB) |
mov dword [edi+NvRegMulticastMaskB], 0 |
; writel(0, base + NvRegPacketFilterFlags) |
mov dword [edi+NvRegPacketFilterFlags], 0 |
; writel(0, base + NvRegTransmitterControl) |
mov dword [edi+NvRegTransmitterControl], 0 |
; writel(0, base + NvRegReceiverControl) |
mov dword [edi+NvRegReceiverControl], 0 |
; writel(0, base + NvRegPacketFilterFlags) |
mov dword [edi+NvRegPacketFilterFlags], 0 |
; writel(0, base + NvRegTransmitterControl) |
mov dword [edi+NvRegTransmitterControl], 0 |
; writel(0, base + NvRegReceiverControl) |
mov dword [edi+NvRegReceiverControl], 0 |
; writel(0, base + NvRegAdapterControl) |
mov dword [edi+NvRegAdapterControl], 0 |
; writel(0, base + NvRegAdapterControl) |
mov dword [edi+NvRegAdapterControl], 0 |
; 2) initialize descriptor rings |
; init_ring(nic) |
call forcedeth_init_ring |
; 2) initialize descriptor rings |
; init_ring(nic) |
call forcedeth_init_ring |
; writel(0, base + NvRegLinkSpeed) |
mov dword [edi+NvRegLinkSpeed], 0 |
; writel(0, base + NvRegUnknownTransmitterReg) |
mov dword [edi+NvRegUnknownTransmitterReg], 0 |
; writel(0, base + NvRegLinkSpeed) |
mov dword [edi+NvRegLinkSpeed], 0 |
; writel(0, base + NvRegUnknownTransmitterReg) |
mov dword [edi+NvRegUnknownTransmitterReg], 0 |
; txrx_reset(nic) |
call forcedeth_txrx_reset |
; writel(0, base + NvRegUnknownSetupReg6) |
mov dword [edi+NvRegUnknownSetupReg6], 0 |
; txrx_reset(nic) |
call forcedeth_txrx_reset |
; writel(0, base + NvRegUnknownSetupReg6) |
mov dword [edi+NvRegUnknownSetupReg6], 0 |
; np->in_shutdown = 0 |
mov dword [forcedeth_in_shutdown], 0 |
; np->in_shutdown = 0 |
mov dword [forcedeth_in_shutdown], 0 |
; 3) set mac address |
; writel(mac[0], base + NvRegMacAddrA) |
mov eax, dword [forcedeth_orig_mac0] |
mov dword [edi+NvRegMacAddrA], eax |
; writel(mac[1], base + NvRegMacAddrB) |
mov eax, dword [forcedeth_orig_mac1] |
mov dword [edi+NvRegMacAddrB], eax |
; 3) set mac address |
; writel(mac[0], base + NvRegMacAddrA) |
mov eax, dword [forcedeth_orig_mac0] |
mov dword [edi+NvRegMacAddrA], eax |
; writel(mac[1], base + NvRegMacAddrB) |
mov eax, dword [forcedeth_orig_mac1] |
mov dword [edi+NvRegMacAddrB], eax |
; 4) give hw rings |
; writel((u32) virt_to_le32desc(&rx_ring[0]), base + NvRegRxRingPhysAddr) |
mov eax, forcedeth_rx_ring |
; 4) give hw rings |
; writel((u32) virt_to_le32desc(&rx_ring[0]), base + NvRegRxRingPhysAddr) |
mov eax, forcedeth_rx_ring |
;DEBUGF 1," K : FORCEDETH: rx_ring at 0x%x\n", eax |
sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov dword [edi+NvRegRxRingPhysAddr], eax |
sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov dword [edi+NvRegRxRingPhysAddr], eax |
; writel((u32) virt_to_le32desc(&tx_ring[0]), base + NvRegTxRingPhysAddr) |
mov eax, forcedeth_tx_ring |
sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov dword [edi+NvRegTxRingPhysAddr], eax |
; writel((u32) virt_to_le32desc(&tx_ring[0]), base + NvRegTxRingPhysAddr) |
mov eax, forcedeth_tx_ring |
sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov dword [edi+NvRegTxRingPhysAddr], eax |
; writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes) |
mov dword [edi+NvRegRingSizes], (((RX_RING - 1) shl NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) shl NVREG_RINGSZ_TXSHIFT)) |
; writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes) |
mov dword [edi+NvRegRingSizes], (((RX_RING - 1) shl NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) shl NVREG_RINGSZ_TXSHIFT)) |
; 5) continue setup |
; np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_linkspeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; np->duplex = 0 |
mov dword [forcedeth_duplex], 0 |
; 5) continue setup |
; np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_linkspeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; np->duplex = 0 |
mov dword [forcedeth_duplex], 0 |
; writel(np->linkspeed, base + NvRegLinkSpeed) |
mov dword [edi+NvRegLinkSpeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; writel(np->linkspeed, base + NvRegLinkSpeed) |
mov dword [edi+NvRegLinkSpeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3) |
mov dword [edi+NvRegUnknownSetupReg3], NVREG_UNKSETUP3_VAL1 |
; writel(np->desc_ver, base + NvRegTxRxControl) |
mov eax, dword [forcedeth_desc_ver] |
mov dword [edi+NvRegTxRxControl], eax |
; pci_push(base) |
call forcedeth_pci_push |
; writel(NVREG_TXRXCTL_BIT1 | np->desc_ver, base + NvRegTxRxControl) |
or eax, NVREG_TXRXCTL_BIT1 |
mov dword [edi+NvRegTxRxControl], eax |
; writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3) |
mov dword [edi+NvRegUnknownSetupReg3], NVREG_UNKSETUP3_VAL1 |
; writel(np->desc_ver, base + NvRegTxRxControl) |
mov eax, dword [forcedeth_desc_ver] |
mov dword [edi+NvRegTxRxControl], eax |
; pci_push(base) |
call forcedeth_pci_push |
; writel(NVREG_TXRXCTL_BIT1 | np->desc_ver, base + NvRegTxRxControl) |
or eax, NVREG_TXRXCTL_BIT1 |
mov dword [edi+NvRegTxRxControl], eax |
; reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, "open: SetupReg5, Bit 31 remained off\n") |
push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; |
stdcall forcedeth_reg_delay,NvRegUnknownSetupReg5,NVREG_UNKSETUP5_BIT31,NVREG_UNKSETUP5_BIT31,NV_SETUP5_DELAY,NV_SETUP5_DELAYMAX,0 |
pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; |
; reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, "open: SetupReg5, Bit 31 remained off\n") |
push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; |
stdcall forcedeth_reg_delay, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, 0 |
pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; |
; writel(0, base + NvRegUnknownSetupReg4) |
mov dword [edi+NvRegUnknownSetupReg4], 0 |
; writel(0, base + NvRegUnknownSetupReg4) |
mov dword [edi+NvRegUnknownSetupReg4], 0 |
; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) |
mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 |
; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) |
mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 |
; printf("%d-Mbs Link, %s-Duplex\n", np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100, np->duplex ? "Full" : "Half") |
; printf("%d-Mbs Link, %s-Duplex\n", np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100, np->duplex ? "Full" : "Half") |
;;;;;;;;;;; DEBUGF |
; 6) continue setup |
; writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1) |
mov dword [edi+NvRegMisc1], (NVREG_MISC1_FORCE or NVREG_MISC1_HD) |
; writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus) |
mov eax, dword [edi+NvRegTransmitterStatus] |
mov dword [edi+NvRegTransmitterStatus], eax |
; 6) continue setup |
; writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1) |
mov dword [edi+NvRegMisc1], (NVREG_MISC1_FORCE or NVREG_MISC1_HD) |
; writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus) |
mov eax, dword [edi+NvRegTransmitterStatus] |
mov dword [edi+NvRegTransmitterStatus], eax |
; writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags) |
mov dword [edi+NvRegPacketFilterFlags], NVREG_PFF_ALWAYS |
; writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags) |
mov dword [edi+NvRegPacketFilterFlags], NVREG_PFF_ALWAYS |
; writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig) |
mov dword [edi+NvRegOffloadConfig], NVREG_OFFLOAD_NORMAL |
; writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig) |
mov dword [edi+NvRegOffloadConfig], NVREG_OFFLOAD_NORMAL |
; writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus) |
mov eax, dword [edi+NvRegReceiverStatus] |
mov dword [edi+NvRegReceiverStatus], eax |
; writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus) |
mov eax, dword [edi+NvRegReceiverStatus] |
mov dword [edi+NvRegReceiverStatus], eax |
; Get a random number |
; i = random() |
push edi |
stdcall sys_clock ; eax = 0x00SSMMHH (current system time) |
pop edi |
; Get a random number |
; i = random() |
push edi |
stdcall sys_clock ; eax = 0x00SSMMHH (current system time) |
pop edi |
; writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK), base + NvRegRandomSeed) |
and eax, NVREG_RNDSEED_MASK |
or eax, NVREG_RNDSEED_FORCE |
mov dword [edi+NvRegRandomSeed], eax |
; writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK), base + NvRegRandomSeed) |
and eax, NVREG_RNDSEED_MASK |
or eax, NVREG_RNDSEED_FORCE |
mov dword [edi+NvRegRandomSeed], eax |
; writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1) |
mov dword [edi+NvRegUnknownSetupReg1], NVREG_UNKSETUP1_VAL |
; writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2) |
mov dword [edi+NvRegUnknownSetupReg2], NVREG_UNKSETUP2_VAL |
; writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval) |
mov dword [edi+NvRegPollingInterval], NVREG_POLL_DEFAULT |
; writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6) |
mov dword [edi+NvRegUnknownSetupReg6], NVREG_UNKSETUP6_VAL |
; writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1) |
mov dword [edi+NvRegUnknownSetupReg1], NVREG_UNKSETUP1_VAL |
; writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2) |
mov dword [edi+NvRegUnknownSetupReg2], NVREG_UNKSETUP2_VAL |
; writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval) |
mov dword [edi+NvRegPollingInterval], NVREG_POLL_DEFAULT |
; writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6) |
mov dword [edi+NvRegUnknownSetupReg6], NVREG_UNKSETUP6_VAL |
; writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT) | NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING, |
; base + NvRegAdapterControl) |
mov eax, dword [forcedeth_phyaddr] |
shl eax, NVREG_ADAPTCTL_PHYSHIFT |
or eax, (NVREG_ADAPTCTL_PHYVALID or NVREG_ADAPTCTL_RUNNING) |
mov dword [edi+NvRegAdapterControl], eax |
; writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed) |
mov dword [edi+NvRegMIISpeed], (NVREG_MIISPEED_BIT8 or NVREG_MIIDELAY) |
; writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT) | NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING, |
; base + NvRegAdapterControl) |
mov eax, dword [forcedeth_phyaddr] |
shl eax, NVREG_ADAPTCTL_PHYSHIFT |
or eax, (NVREG_ADAPTCTL_PHYVALID or NVREG_ADAPTCTL_RUNNING) |
mov dword [edi+NvRegAdapterControl], eax |
; writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed) |
mov dword [edi+NvRegMIISpeed], (NVREG_MIISPEED_BIT8 or NVREG_MIIDELAY) |
; writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4) |
mov dword [edi+NvRegUnknownSetupReg4], NVREG_UNKSETUP4_VAL |
; writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4) |
mov dword [edi+NvRegUnknownSetupReg4], NVREG_UNKSETUP4_VAL |
; writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags) |
mov dword [edi+NvRegWakeUpFlags], NVREG_WAKEUPFLAGS_VAL |
; i = readl(base + NvRegPowerState) |
mov eax, dword [edi+NvRegPowerState] |
; writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags) |
mov dword [edi+NvRegWakeUpFlags], NVREG_WAKEUPFLAGS_VAL |
; i = readl(base + NvRegPowerState) |
mov eax, dword [edi+NvRegPowerState] |
; if ((i & NVREG_POWERSTATE_POWEREDUP) == 0) |
test eax, NVREG_POWERSTATE_POWEREDUP |
jnz @f |
; writel(NVREG_POWERSTATE_POWEREDUP | i, base + NvRegPowerState) |
or eax, NVREG_POWERSTATE_POWEREDUP |
mov dword [edi+NvRegPowerState], eax |
; if ((i & NVREG_POWERSTATE_POWEREDUP) == 0) |
test eax, NVREG_POWERSTATE_POWEREDUP |
jnz @f |
; writel(NVREG_POWERSTATE_POWEREDUP | i, base + NvRegPowerState) |
or eax, NVREG_POWERSTATE_POWEREDUP |
mov dword [edi+NvRegPowerState], eax |
@@: |
; pci_push(base) |
call forcedeth_pci_push |
; pci_push(base) |
call forcedeth_pci_push |
; nv_udelay(10) |
mov esi, 10 |
call forcedeth_nv_udelay |
; nv_udelay(10) |
mov esi, 10 |
call forcedeth_nv_udelay |
; writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState) |
mov eax, dword [edi+NvRegPowerState] |
or eax, NVREG_POWERSTATE_VALID |
mov dword [edi+NvRegPowerState], eax |
; writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState) |
mov eax, dword [edi+NvRegPowerState] |
or eax, NVREG_POWERSTATE_VALID |
mov dword [edi+NvRegPowerState], eax |
; ??? disable all interrupts ??? |
; writel(0, base + NvRegIrqMask) |
mov dword [edi+NvRegIrqMask], 0 |
; ??? disable all interrupts ??? |
; writel(0, base + NvRegIrqMask) |
mov dword [edi+NvRegIrqMask], 0 |
;;; ; ??? Mask RX interrupts |
;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_RX_ALL |
;;; ; ??? Mask TX interrupts |
;;; ;mov dword [edi+NvRegIrqMask], NVREG_IRQ_TX_ALL |
;;; ; ??? Mask OTHER interrupts |
;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_OTHER_ALL |
; pci_push(base) |
call forcedeth_pci_push |
;;; ; ??? Mask RX interrupts |
;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_RX_ALL |
;;; ; ??? Mask TX interrupts |
;;; ;mov dword [edi+NvRegIrqMask], NVREG_IRQ_TX_ALL |
;;; ; ??? Mask OTHER interrupts |
;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_OTHER_ALL |
; pci_push(base) |
call forcedeth_pci_push |
; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) |
mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 |
; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) |
mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 |
; writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus) |
mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK |
; writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus) |
mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK |
; pci_push(base) |
call forcedeth_pci_push |
; pci_push(base) |
call forcedeth_pci_push |
; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) |
mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE |
; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) |
mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE |
; writel(0, base + NvRegMulticastAddrB) |
mov dword [edi+NvRegMulticastAddrB], 0 |
; writel(0, base + NvRegMulticastAddrB) |
mov dword [edi+NvRegMulticastAddrB], 0 |
; writel(0, base + NvRegMulticastMaskA) |
mov dword [edi+NvRegMulticastMaskA], 0 |
; writel(0, base + NvRegMulticastMaskA) |
mov dword [edi+NvRegMulticastMaskA], 0 |
; writel(0, base + NvRegMulticastMaskB) |
mov dword [edi+NvRegMulticastMaskB], 0 |
; writel(0, base + NvRegMulticastMaskB) |
mov dword [edi+NvRegMulticastMaskB], 0 |
; writel(NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags) |
mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_ALWAYS or NVREG_PFF_MYADDR) |
; writel(NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags) |
mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_ALWAYS or NVREG_PFF_MYADDR) |
; set_multicast(nic) |
call forcedeth_set_multicast |
; One manual link speed update: Interrupts are enabled, future link |
; speed changes cause interrupts and are handled by nv_link_irq(). |
; set_multicast(nic) |
call forcedeth_set_multicast |
; One manual link speed update: Interrupts are enabled, future link |
; speed changes cause interrupts and are handled by nv_link_irq(). |
; miistat = readl(base + NvRegMIIStatus) |
mov eax, dword [edi+NvRegMIIStatus] |
; miistat = readl(base + NvRegMIIStatus) |
mov eax, dword [edi+NvRegMIIStatus] |
; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); |
mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK |
; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); |
mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK |
; dprintf(("startup: got 0x%hX.\n", miistat)); |
;;; DEBUGF 1," K : FORCEDETH: startup: got 0x%x\n", eax |
; dprintf(("startup: got 0x%hX.\n", miistat)); |
;;; DEBUGF 1," K : FORCEDETH: startup: got 0x%x\n", eax |
; ret = update_linkspeed(nic) |
call forcedeth_update_linkspeed |
push eax |
; ret = update_linkspeed(nic) |
call forcedeth_update_linkspeed |
push eax |
; start_tx(nic) |
call forcedeth_start_tx |
; start_tx(nic) |
call forcedeth_start_tx |
pop eax |
pop eax |
; if (ret) { |
; //Start Connection netif_carrier_on(dev); |
729,17 → 729,17 |
; printf("no link during initialization.\n"); |
; } |
;*** added by shurf (21.09.2008) |
mov dword [forcedeth_nocable], 0 |
;*** |
;*** added by shurf (21.09.2008) |
mov dword [forcedeth_nocable], 0 |
;*** |
test eax, eax |
jnz .return |
DEBUGF 1," K : FORCEDETH: no link during initialization.\n" |
test eax, eax |
jnz .return |
DEBUGF 1," K : FORCEDETH: no link during initialization.\n" |
;*** added by shurf (21.09.2008) |
mov dword [forcedeth_nocable], 1 |
;*** |
;*** added by shurf (21.09.2008) |
mov dword [forcedeth_nocable], 1 |
;*** |
.return: |
746,8 → 746,8 |
; Indicate that we have successfully reset the card |
mov eax, dword [pci_data] |
mov dword [eth_status], eax |
ret |
ret |
;*************************************************************************** |
760,339 → 760,343 |
;*************************************************************************** |
forcedeth_probe: |
; DEBUGF 1," K : FORCEDETH: 0x%x 0x%x, 0x%x\n", [io_addr]:8,[pci_bus]:2,[pci_dev]:2 |
; DEBUGF 1," K : FORCEDETH: 0x%x 0x%x, 0x%x\n", [io_addr]:8,[pci_bus]:2,[pci_dev]:2 |
mov dword [forcedeth_needs_mac_reset], 0 |
mov dword [forcedeth_needs_mac_reset], 0 |
; BEGIN of adjust_pci_device() |
; read word from PCI-device |
mov al, 1 ;;;;;;;;;;;;;;2 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_REG_COMMAND |
call pci_read_reg |
mov bx, ax ; new command |
or bx, PCI_COMMAND_MASTER |
or bx, PCI_COMMAND_IO |
cmp bx, ax |
je @f |
; Enabling PCI-device (make card as bus master) |
DEBUGF 1," K : FORCEDETH: Updating PCI command 0x%x->0x%x\n", ax, bx |
mov cx, bx |
mov al, 1 ;;;;;;;;;;;;2 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_REG_COMMAND |
call pci_write_reg |
; read word from PCI-device |
mov al, 1 ;;;;;;;;;;;;;;2 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_REG_COMMAND |
call pci_read_reg |
mov bx, ax ; new command |
or bx, PCI_COMMAND_MASTER |
or bx, PCI_COMMAND_IO |
cmp bx, ax |
je @f |
; Enabling PCI-device (make card as bus master) |
DEBUGF 1," K : FORCEDETH: Updating PCI command 0x%x->0x%x\n", ax, bx |
mov cx, bx |
mov al, 1 ;;;;;;;;;;;;2 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_REG_COMMAND |
call pci_write_reg |
; Check latency settings |
; Check latency settings |
@@: |
; Get current latency settings from Latency timer register (byte) |
mov al, 0 ;;;;;;;;;1 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_LATENCY_TIMER |
call pci_read_reg |
; Get current latency settings from Latency timer register (byte) |
mov al, 0 ;;;;;;;;;1 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_LATENCY_TIMER |
call pci_read_reg |
; see if its at least 32 |
cmp al, 32 |
jge @f |
; set latency to 32 |
; see if its at least 32 |
cmp al, 32 |
jge @f |
; set latency to 32 |
DEBUGF 1, "K : FORCEDETH: PCI latency timer (CFLT) is unreasonably low at %d.\n", al |
DEBUGF 1, "K : FORCEDETH: Setting to 32 clocks.\n" |
mov cl, 32 |
mov al, 0 ;;;;;;;1 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_LATENCY_TIMER |
call pci_write_reg |
mov cl, 32 |
mov al, 0 ;;;;;;;1 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_LATENCY_TIMER |
call pci_write_reg |
; END of adjust_pci_device() |
@@: |
; BEGIN of pci_bar_start (addr = pci_bar_start(pci, PCI_BASE_ADDRESS_0)) |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
call pci_read_reg |
test eax, PCI_BASE_ADDRESS_SPACE_IO |
jz @f |
and eax, PCI_BASE_ADDRESS_IO_MASK |
jmp .next |
@@: push eax |
and eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK |
cmp eax, PCI_BASE_ADDRESS_MEM_TYPE_64 |
jne .not64 |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 + 4 |
call pci_read_reg |
or eax, eax |
jz .not64 |
DEBUGF 1,"K : FORCEDETH: pci_bar_start: Unhandled 64bit BAR\n" |
or eax, -1 |
jmp .next |
.not64: |
pop eax |
and eax, PCI_BASE_ADDRESS_MEM_MASK |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
call pci_read_reg |
test eax, PCI_BASE_ADDRESS_SPACE_IO |
jz @f |
and eax, PCI_BASE_ADDRESS_IO_MASK |
jmp .next |
@@: |
push eax |
and eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK |
cmp eax, PCI_BASE_ADDRESS_MEM_TYPE_64 |
jne .not64 |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 + 4 |
call pci_read_reg |
or eax, eax |
jz .not64 |
DEBUGF 1,"K : FORCEDETH: pci_bar_start: Unhandled 64bit BAR\n" |
or eax, -1 |
jmp .next |
.not64: |
pop eax |
and eax, PCI_BASE_ADDRESS_MEM_MASK |
.next: |
; END of pci_bar_start |
; addr = eax |
mov dword [forcedeth_mmio_addr], eax |
mov dword [forcedeth_mmio_addr], eax |
; BEGIN of pci_bar_size (sz = pci_bar_size(pci, PCI_BASE_ADDRESS_0)) |
; Save original bar |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
call pci_read_reg |
mov dword [forcedeth_tmp_start], eax |
; Compute which bits can be set |
; (ecx - value to write) |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
mov ecx, (not 0) |
call pci_write_reg |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
call pci_read_reg |
push eax |
; Restore the original size |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
mov ecx, dword [forcedeth_tmp_start] |
call pci_write_reg |
; Find the significant bits |
pop eax |
test dword [forcedeth_tmp_start], PCI_BASE_ADDRESS_SPACE_IO |
jz @f |
and eax, PCI_BASE_ADDRESS_IO_MASK |
jmp .next2 |
@@: and eax, PCI_BASE_ADDRESS_MEM_MASK |
; Save original bar |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
call pci_read_reg |
mov dword [forcedeth_tmp_start], eax |
; Compute which bits can be set |
; (ecx - value to write) |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
mov ecx, (not 0) |
call pci_write_reg |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
call pci_read_reg |
push eax |
; Restore the original size |
mov al, 2 ; dword |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_BASE_ADDRESS_0 |
mov ecx, dword [forcedeth_tmp_start] |
call pci_write_reg |
; Find the significant bits |
pop eax |
test dword [forcedeth_tmp_start], PCI_BASE_ADDRESS_SPACE_IO |
jz @f |
and eax, PCI_BASE_ADDRESS_IO_MASK |
jmp .next2 |
@@: |
and eax, PCI_BASE_ADDRESS_MEM_MASK |
.next2: |
; Find the lowest bit set |
mov ecx, eax |
sub eax, 1 |
not eax |
and ecx, eax |
; Find the lowest bit set |
mov ecx, eax |
sub eax, 1 |
not eax |
and ecx, eax |
; END of pci_bar_start |
mov dword [forcedeth_mmio_size], ecx |
mov dword [forcedeth_mmio_size], ecx |
DEBUGF 1," K : FORCEDETH: mmio_addr= 0x%x [mmio_size= 0x%x]\n", [forcedeth_mmio_addr]:8, [forcedeth_mmio_size]:8 |
DEBUGF 1," K : FORCEDETH: mmio_addr= 0x%x [mmio_size= 0x%x]\n", [forcedeth_mmio_addr]:8, [forcedeth_mmio_size]:8 |
; Get Vendor and Device ID |
mov al, 2 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_VENDOR_ID |
call pci_read_reg |
mov word [forcedeth_vendor_id], ax |
shr eax, 16 |
mov word [forcedeth_device_id], ax |
; Get Vendor and Device ID |
mov al, 2 |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_VENDOR_ID |
call pci_read_reg |
mov word [forcedeth_vendor_id], ax |
shr eax, 16 |
mov word [forcedeth_device_id], ax |
DEBUGF 1," K : FORCEDETH: vendor_id= 0x%x device_id= 0x%x\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 |
DEBUGF 1," K : FORCEDETH: vendor_id= 0x%x device_id= 0x%x\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 |
; handle different descriptor versions |
mov eax, dword [forcedeth_device_id] |
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_1 |
je .ver1 |
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_2 |
je .ver1 |
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_3 |
je .ver1 |
mov dword [forcedeth_desc_ver], DESC_VER_2 |
jmp @f |
.ver1: mov dword [forcedeth_desc_ver], DESC_VER_1 |
; handle different descriptor versions |
mov eax, dword [forcedeth_device_id] |
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_1 |
je .ver1 |
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_2 |
je .ver1 |
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_3 |
je .ver1 |
mov dword [forcedeth_desc_ver], DESC_VER_2 |
jmp @f |
.ver1: |
mov dword [forcedeth_desc_ver], DESC_VER_1 |
@@: |
; read the mac address |
; map memory |
stdcall map_io_mem, [forcedeth_mmio_addr], [forcedeth_mmio_size], (PG_SW+PG_NOCACHE) |
test eax, eax |
jz .fail |
; read the mac address |
; map memory |
stdcall map_io_mem, [forcedeth_mmio_addr], [forcedeth_mmio_size], (PG_SW+PG_NOCACHE) |
test eax, eax |
jz .fail |
mov dword [forcedeth_mapio_addr], eax |
mov edi, eax |
mov eax, dword [edi+NvRegMacAddrA] |
mov dword [forcedeth_orig_mac0], eax |
mov edx, dword [edi+NvRegMacAddrB] |
mov dword [forcedeth_orig_mac1], edx |
mov dword [forcedeth_mapio_addr], eax |
mov edi, eax |
mov eax, dword [edi+NvRegMacAddrA] |
mov dword [forcedeth_orig_mac0], eax |
mov edx, dword [edi+NvRegMacAddrB] |
mov dword [forcedeth_orig_mac1], edx |
; save MAC-address to global variable node_addr |
mov dword [node_addr], eax |
mov word [node_addr+4], dx |
; save MAC-address to global variable node_addr |
mov dword [node_addr], eax |
mov word [node_addr+4], dx |
; reverse if desired |
cmp word [forcedeth_device_id], 0x03E5 |
jae .no_reverse_mac |
mov al, byte [node_addr] |
xchg al, byte [node_addr+5] |
mov byte [node_addr], al |
mov al, byte [node_addr+1] |
xchg al, byte [node_addr+4] |
mov byte [node_addr+4], al |
mov al, byte [node_addr+2] |
xchg al, byte [node_addr+3] |
mov byte [node_addr+3], al |
; reverse if desired |
cmp word [forcedeth_device_id], 0x03E5 |
jae .no_reverse_mac |
mov al, byte [node_addr] |
xchg al, byte [node_addr+5] |
mov byte [node_addr], al |
mov al, byte [node_addr+1] |
xchg al, byte [node_addr+4] |
mov byte [node_addr+4], al |
mov al, byte [node_addr+2] |
xchg al, byte [node_addr+3] |
mov byte [node_addr+3], al |
.no_reverse_mac: |
; DEBUGF 1," K : FORCEDETH: orig_mac0= 0x%x\n", [forcedeth_orig_mac0]:8 |
; DEBUGF 1," K : FORCEDETH: orig_mac1= 0x%x\n", [forcedeth_orig_mac1]:8 |
DEBUGF 1," K : FORCEDETH: MAC = %x-%x-%x-%x-%x-%x\n", [node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2, |
; DEBUGF 1," K : FORCEDETH: orig_mac0= 0x%x\n", [forcedeth_orig_mac0]:8 |
; DEBUGF 1," K : FORCEDETH: orig_mac1= 0x%x\n", [forcedeth_orig_mac1]:8 |
DEBUGF 1," K : FORCEDETH: MAC = %x-%x-%x-%x-%x-%x\n", [node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2, |
; disable WOL |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegWakeUpFlags], 0 |
mov dword [forcedeth_wolenabled], 0 |
mov dword [forcedeth_txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID) |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
mov dword [forcedeth_txflags], (NV_TX_LASTPACKET or NV_TX_VALID) |
@@: |
; disable WOL |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegWakeUpFlags], 0 |
mov dword [forcedeth_wolenabled], 0 |
mov dword [forcedeth_txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID) |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
mov dword [forcedeth_txflags], (NV_TX_LASTPACKET or NV_TX_VALID) |
@@: |
; BEGIN of switch (pci->dev_id) |
cmp word [forcedeth_device_id], 0x01C3 |
jne .next_0x0066 |
; nforce |
mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) |
jmp .end_switch |
cmp word [forcedeth_device_id], 0x01C3 |
jne .next_0x0066 |
; nforce |
mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) |
jmp .end_switch |
.next_0x0066: |
cmp word [forcedeth_device_id], 0x0066 |
je @f |
cmp word [forcedeth_device_id], 0x00D6 |
je @f |
jmp .next_0x0086 |
@@: |
mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
or dword [forcedeth_txflags], NV_TX_LASTPACKET1 |
jmp .end_switch |
@@: or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 |
jmp .end_switch |
cmp word [forcedeth_device_id], 0x0066 |
je @f |
cmp word [forcedeth_device_id], 0x00D6 |
je @f |
jmp .next_0x0086 |
@@: |
mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
or dword [forcedeth_txflags], NV_TX_LASTPACKET1 |
jmp .end_switch |
@@: |
or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 |
jmp .end_switch |
.next_0x0086: |
cmp word [forcedeth_device_id], 0x0086 |
je @f |
cmp word [forcedeth_device_id], 0x008c |
je @f |
cmp word [forcedeth_device_id], 0x00e6 |
je @f |
cmp word [forcedeth_device_id], 0x00df |
je @f |
cmp word [forcedeth_device_id], 0x0056 |
je @f |
cmp word [forcedeth_device_id], 0x0057 |
je @f |
cmp word [forcedeth_device_id], 0x0037 |
je @f |
cmp word [forcedeth_device_id], 0x0038 |
je @f |
jmp .next_0x0268 |
@@: |
; np->irqmask = NVREG_IRQMASK_WANTED_2; |
; np->irqmask |= NVREG_IRQ_TIMER; |
mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) |
cmp word [forcedeth_device_id], 0x0086 |
je @f |
cmp word [forcedeth_device_id], 0x008c |
je @f |
cmp word [forcedeth_device_id], 0x00e6 |
je @f |
cmp word [forcedeth_device_id], 0x00df |
je @f |
cmp word [forcedeth_device_id], 0x0056 |
je @f |
cmp word [forcedeth_device_id], 0x0057 |
je @f |
cmp word [forcedeth_device_id], 0x0037 |
je @f |
cmp word [forcedeth_device_id], 0x0038 |
je @f |
jmp .next_0x0268 |
@@: |
; np->irqmask = NVREG_IRQMASK_WANTED_2; |
; np->irqmask |= NVREG_IRQ_TIMER; |
mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) |
; if (np->desc_ver == DESC_VER_1) |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
; np->tx_flags |= NV_TX_LASTPACKET1; |
or dword [forcedeth_txflags], NV_TX_LASTPACKET1 |
jmp .end_switch |
; else |
; if (np->desc_ver == DESC_VER_1) |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
; np->tx_flags |= NV_TX_LASTPACKET1; |
or dword [forcedeth_txflags], NV_TX_LASTPACKET1 |
jmp .end_switch |
; else |
@@: |
; np->tx_flags |= NV_TX2_LASTPACKET1; |
or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 |
; np->tx_flags |= NV_TX2_LASTPACKET1; |
or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 |
; break; |
jmp .end_switch |
; break; |
jmp .end_switch |
.next_0x0268: |
; cmp word [forcedeth_device_id], 0x0268 |
; je @f |
; cmp word [forcedeth_device_id], 0x0269 |
; je @f |
; cmp word [forcedeth_device_id], 0x0372 |
; je @f |
; cmp word [forcedeth_device_id], 0x0373 |
; je @f |
; jmp .default_switch |
; cmp word [forcedeth_device_id], 0x0268 |
; je @f |
; cmp word [forcedeth_device_id], 0x0269 |
; je @f |
; cmp word [forcedeth_device_id], 0x0372 |
; je @f |
; cmp word [forcedeth_device_id], 0x0373 |
; je @f |
; jmp .default_switch |
;@@: |
cmp word [forcedeth_device_id], 0x0268 |
jb .default_switch |
; pci_read_config_byte(pci, PCI_REVISION_ID, &revision_id); |
mov al, 0 ; byte |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_REVISION_ID |
call pci_read_reg |
mov ecx, eax ; cl = revision_id |
cmp word [forcedeth_device_id], 0x0268 |
jb .default_switch |
; pci_read_config_byte(pci, PCI_REVISION_ID, &revision_id); |
mov al, 0 ; byte |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, PCI_REVISION_ID |
call pci_read_reg |
mov ecx, eax ; cl = revision_id |
; take phy and nic out of low power mode |
; powerstate = readl(base + NvRegPowerState2); |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegPowerState2] ; eax = powerstate |
; powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; |
and eax, not NVREG_POWERSTATE2_POWERUP_MASK |
; if ((pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_12||pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_13)&&revision_id>=0xA3) |
cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12 |
je @f |
cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13 |
je @f |
jmp .end_if |
; take phy and nic out of low power mode |
; powerstate = readl(base + NvRegPowerState2); |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegPowerState2] ; eax = powerstate |
; powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; |
and eax, not NVREG_POWERSTATE2_POWERUP_MASK |
; if ((pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_12||pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_13)&&revision_id>=0xA3) |
cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12 |
je @f |
cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13 |
je @f |
jmp .end_if |
@@: |
cmp cl, 0xA3 |
jl .end_if |
; powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; |
or eax, NVREG_POWERSTATE2_POWERUP_REV_A3 |
cmp cl, 0xA3 |
jl .end_if |
; powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; |
or eax, NVREG_POWERSTATE2_POWERUP_REV_A3 |
.end_if: |
; writel(powerstate, base + NvRegPowerState2); |
mov dword [edi+NvRegPowerState2], eax |
; writel(powerstate, base + NvRegPowerState2); |
mov dword [edi+NvRegPowerState2], eax |
; //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ |
; np->irqmask = NVREG_IRQMASK_WANTED_2; |
; np->irqmask |= NVREG_IRQ_TIMER; |
mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) |
; needs_mac_reset = 1; |
mov dword [forcedeth_needs_mac_reset], 1 |
; if (np->desc_ver == DESC_VER_1) |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
; np->tx_flags |= NV_TX_LASTPACKET1; |
or dword [forcedeth_txflags], NV_TX_LASTPACKET1 |
jmp .end_if2 |
; //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ |
; np->irqmask = NVREG_IRQMASK_WANTED_2; |
; np->irqmask |= NVREG_IRQ_TIMER; |
mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) |
; needs_mac_reset = 1; |
mov dword [forcedeth_needs_mac_reset], 1 |
; if (np->desc_ver == DESC_VER_1) |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
; np->tx_flags |= NV_TX_LASTPACKET1; |
or dword [forcedeth_txflags], NV_TX_LASTPACKET1 |
jmp .end_if2 |
@@: |
; else |
; np->tx_flags |= NV_TX2_LASTPACKET1; |
or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 |
; else |
; np->tx_flags |= NV_TX2_LASTPACKET1; |
or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 |
.end_if2: |
; break; |
jmp .end_switch |
; break; |
jmp .end_switch |
.default_switch: |
DEBUGF 1," K : FORCEDETH: Your card was undefined in this driver.\n" |
DEBUGF 1," K : FORCEDETH: Review driver_data in Kolibri driver and send a patch\n" |
DEBUGF 1," K : FORCEDETH: Your card was undefined in this driver.\n" |
DEBUGF 1," K : FORCEDETH: Review driver_data in Kolibri driver and send a patch\n" |
.end_switch: |
1099,147 → 1103,147 |
; END of switch (pci->dev_id) |
; Find a suitable phy |
mov dword [forcedeth_tmp_i], 1 |
; Find a suitable phy |
mov dword [forcedeth_tmp_i], 1 |
.for_loop: |
; for (i = 1; i <= 32; i++) |
; phyaddr = i & 0x1f |
mov ebx, dword [forcedeth_tmp_i] |
and ebx, 0x1f |
; for (i = 1; i <= 32; i++) |
; phyaddr = i & 0x1f |
mov ebx, dword [forcedeth_tmp_i] |
and ebx, 0x1f |
; id1 = mii_rw(phyaddr, MII_PHYSID1, MII_READ) |
; id1 = mii_rw(phyaddr, MII_PHYSID1, MII_READ) |
;EBX - addr, EAX - miireg, ECX - value |
mov eax, MII_PHYSID1 |
mov ecx, MII_READ |
call forcedeth_mii_rw ; id1 = eax |
mov eax, MII_PHYSID1 |
mov ecx, MII_READ |
call forcedeth_mii_rw ; id1 = eax |
; if (id1 < 0 || id1 == 0xffff) |
cmp eax, 0xffffffff |
je .continue_for |
test eax, 0x80000000 |
jnz .continue_for |
mov dword [forcedeth_tmp_id1], eax |
; if (id1 < 0 || id1 == 0xffff) |
cmp eax, 0xffffffff |
je .continue_for |
test eax, 0x80000000 |
jnz .continue_for |
mov dword [forcedeth_tmp_id1], eax |
; id2 = mii_rw(nic, phyaddr, MII_PHYSID2, MII_READ) |
mov eax, MII_PHYSID2 |
mov ecx, MII_READ |
call forcedeth_mii_rw ; id2 = eax |
; id2 = mii_rw(nic, phyaddr, MII_PHYSID2, MII_READ) |
mov eax, MII_PHYSID2 |
mov ecx, MII_READ |
call forcedeth_mii_rw ; id2 = eax |
; if (id2 < 0 || id2 == 0xffff) |
cmp eax, 0xffffffff |
je .continue_for |
test eax, 0x80000000 |
jnz .continue_for |
mov dword [forcedeth_tmp_id2], eax |
; if (id2 < 0 || id2 == 0xffff) |
cmp eax, 0xffffffff |
je .continue_for |
test eax, 0x80000000 |
jnz .continue_for |
mov dword [forcedeth_tmp_id2], eax |
jmp .break_for |
jmp .break_for |
.continue_for: |
inc dword [forcedeth_tmp_i] |
cmp dword [forcedeth_tmp_i], 32 |
jle .for_loop |
jmp .end_for |
inc dword [forcedeth_tmp_i] |
cmp dword [forcedeth_tmp_i], 32 |
jle .for_loop |
jmp .end_for |
.break_for: |
;;;; DEBUGF 1," K : FORCEDETH: id1=0x%x id2=0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8 |
;;;; DEBUGF 1," K : FORCEDETH: id1=0x%x id2=0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8 |
; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT |
mov eax, dword [forcedeth_tmp_id1] |
and eax, PHYID1_OUI_MASK |
shl eax, PHYID1_OUI_SHFT |
mov dword [forcedeth_tmp_id1], eax |
; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT |
mov eax, dword [forcedeth_tmp_id1] |
and eax, PHYID1_OUI_MASK |
shl eax, PHYID1_OUI_SHFT |
mov dword [forcedeth_tmp_id1], eax |
; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT |
mov eax, dword [forcedeth_tmp_id2] |
and eax, PHYID2_OUI_MASK |
shr eax, PHYID2_OUI_SHFT |
mov dword [forcedeth_tmp_id2], eax |
; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT |
mov eax, dword [forcedeth_tmp_id2] |
and eax, PHYID2_OUI_MASK |
shr eax, PHYID2_OUI_SHFT |
mov dword [forcedeth_tmp_id2], eax |
DEBUGF 1," K : FORCEDETH: Found PHY 0x%x:0x%x at address 0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8, ebx |
DEBUGF 1," K : FORCEDETH: Found PHY 0x%x:0x%x at address 0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8, ebx |
; np->phyaddr = phyaddr; |
mov dword [forcedeth_phyaddr], ebx |
; np->phyaddr = phyaddr; |
mov dword [forcedeth_phyaddr], ebx |
; np->phy_oui = id1 | id2; |
mov eax, dword [forcedeth_tmp_id1] |
or eax, dword [forcedeth_tmp_id2] |
mov dword [forcedeth_phy_oui], eax |
; np->phy_oui = id1 | id2; |
mov eax, dword [forcedeth_tmp_id1] |
or eax, dword [forcedeth_tmp_id2] |
mov dword [forcedeth_phy_oui], eax |
.end_for: |
; if (i == 33) |
cmp dword [forcedeth_tmp_i], 33 |
jne @f |
; PHY in isolate mode? No phy attached and user wants to |
; test loopback? Very odd, but can be correct. |
DEBUGF 1," K : FORCEDETH: Could not find a valid PHY.\n" |
; if (i == 33) |
cmp dword [forcedeth_tmp_i], 33 |
jne @f |
; PHY in isolate mode? No phy attached and user wants to |
; test loopback? Very odd, but can be correct. |
DEBUGF 1," K : FORCEDETH: Could not find a valid PHY.\n" |
jmp .next3 |
jmp .next3 |
@@: |
; if (i != 33) |
; reset it |
call forcedeth_phy_init |
; if (i != 33) |
; reset it |
call forcedeth_phy_init |
.next3: |
; dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n", |
; pci->name, pci->vendor, pci->dev_id, pci->name)); |
DEBUGF 1," K : FORCEDETH: subsystem: 0x%x:0x%x bound to forcedeth\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 |
DEBUGF 1," K : FORCEDETH: subsystem: 0x%x:0x%x bound to forcedeth\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 |
; if(needs_mac_reset) mac_reset(nic); |
cmp dword [forcedeth_needs_mac_reset], 0 |
je @f |
call forcedeth_mac_reset |
cmp dword [forcedeth_needs_mac_reset], 0 |
je @f |
call forcedeth_mac_reset |
@@: |
; if(!forcedeth_reset(nic)) return 0; // no valid link |
call forcedeth_reset |
test eax, eax |
jnz @f |
mov eax, 0 |
jmp .return |
; if(!forcedeth_reset(nic)) return 0; // no valid link |
call forcedeth_reset |
test eax, eax |
jnz @f |
mov eax, 0 |
jmp .return |
@@: |
; point to NIC specific routines |
; dev->disable = forcedeth_disable; |
; nic->poll = forcedeth_poll; |
; nic->transmit = forcedeth_transmit; |
; nic->irq = forcedeth_irq; |
;;;;;;;;;stdcall attach_int_handler, 11, forcedeth_int_handler, 0 |
; point to NIC specific routines |
; dev->disable = forcedeth_disable; |
; nic->poll = forcedeth_poll; |
; nic->transmit = forcedeth_transmit; |
; nic->irq = forcedeth_irq; |
;;;;;;;;;stdcall attach_int_handler, 11, forcedeth_int_handler, 0 |
; return 1 |
mov eax, 1 |
jmp .return |
; return 1 |
mov eax, 1 |
jmp .return |
.fail: |
mov eax, 0 |
mov eax, 0 |
.return: |
ret |
ret |
uglobal |
forcedeth_tmp_start dd ? |
forcedeth_tmp_reg dd ? |
forcedeth_tmp_i dd ? |
forcedeth_tmp_id1 dd ? |
forcedeth_tmp_id2 dd ? |
forcedeth_tmp_phyinterface dd ? |
forcedeth_tmp_newls dd ? |
forcedeth_tmp_newdup dd ? |
forcedeth_tmp_retval dd ? |
forcedeth_tmp_control_1000 dd ? |
forcedeth_tmp_lpa dd ? |
forcedeth_tmp_adv dd ? |
forcedeth_tmp_len dd ? |
forcedeth_tmp_valid dd ? |
forcedeth_tmp_nr dd ? |
forcedeth_tmp_ptxb dd ? |
forcedeth_tmp_start dd ? |
forcedeth_tmp_reg dd ? |
forcedeth_tmp_i dd ? |
forcedeth_tmp_id1 dd ? |
forcedeth_tmp_id2 dd ? |
forcedeth_tmp_phyinterface dd ? |
forcedeth_tmp_newls dd ? |
forcedeth_tmp_newdup dd ? |
forcedeth_tmp_retval dd ? |
forcedeth_tmp_control_1000 dd ? |
forcedeth_tmp_lpa dd ? |
forcedeth_tmp_adv dd ? |
forcedeth_tmp_len dd ? |
forcedeth_tmp_valid dd ? |
forcedeth_tmp_nr dd ? |
forcedeth_tmp_ptxb dd ? |
endg |
;*************************************************************************** |
1253,146 → 1257,146 |
;*************************************************************************** |
forcedeth_poll: |
mov word [eth_rx_data_len], 0 |
mov word [eth_rx_data_len], 0 |
; ???????????????????????????? |
; ??? Clear events? ??? |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK |
; ???????????????????????????? |
; ???????????????????????????? |
; ??? Clear events? ??? |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK |
; ???????????????????????????? |
.top: |
; i = np->cur_rx % RX_RING |
mov eax, dword [forcedeth_cur_rx] |
and eax, (RX_RING-1) |
mov dword [forcedeth_tmp_i], eax |
; i = np->cur_rx % RX_RING |
mov eax, dword [forcedeth_cur_rx] |
and eax, (RX_RING-1) |
mov dword [forcedeth_tmp_i], eax |
; Flags = le32_to_cpu(rx_ring[i].FlagLen) |
; Flags = rx_ring[i].FlagLen |
mov cl, sizeof.forcedeth_RxDesc |
mul cl |
add eax, forcedeth_rx_ring |
mov ebx, eax |
mov eax, [ebx + forcedeth_RxDesc.FlagLen] |
; Flags = le32_to_cpu(rx_ring[i].FlagLen) |
; Flags = rx_ring[i].FlagLen |
mov cl, sizeof.forcedeth_RxDesc |
mul cl |
add eax, forcedeth_rx_ring |
mov ebx, eax |
mov eax, [ebx + forcedeth_RxDesc.FlagLen] |
; if (Flags & NV_RX_AVAIL) |
test eax, NV_RX_AVAIL |
; return 0; /* still owned by hardware, */ |
; still owned by hardware |
jnz .return0 |
; if (Flags & NV_RX_AVAIL) |
test eax, NV_RX_AVAIL |
; return 0; /* still owned by hardware, */ |
; still owned by hardware |
jnz .return0 |
;;;;; DEBUGF 1,"poll: FlagLen = %x\n", eax |
;;;;; DEBUGF 1,"poll: FlagLen = %x\n", eax |
; if (np->desc_ver == DESC_VER_1) { |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
; if (!(Flags & NV_RX_DESCRIPTORVALID)) |
test eax, NV_RX_DESCRIPTORVALID |
; return 0; |
jz .return0 |
jmp .next |
; } else { |
; if (np->desc_ver == DESC_VER_1) { |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
; if (!(Flags & NV_RX_DESCRIPTORVALID)) |
test eax, NV_RX_DESCRIPTORVALID |
; return 0; |
jz .return0 |
jmp .next |
; } else { |
@@: |
; if (!(Flags & NV_RX2_DESCRIPTORVALID)) |
test eax, NV_RX2_DESCRIPTORVALID |
; return 0; |
jz .return0 |
; } |
; if (!(Flags & NV_RX2_DESCRIPTORVALID)) |
test eax, NV_RX2_DESCRIPTORVALID |
; return 0; |
jz .return0 |
; } |
.next: |
; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) |
; len = rx_ring[i].FlagLen & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2); |
; eax = FlagLen |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
and eax, LEN_MASK_V1 |
jmp .next2 |
; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) |
; len = rx_ring[i].FlagLen & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2); |
; eax = FlagLen |
cmp dword [forcedeth_desc_ver], DESC_VER_1 |
jne @f |
and eax, LEN_MASK_V1 |
jmp .next2 |
@@: |
and eax, LEN_MASK_V2 |
and eax, LEN_MASK_V2 |
.next2: |
; mov dword [forcedeth_tmp_len], eax |
; mov dword [forcedeth_tmp_len], eax |
; valid = 1 |
mov dword [forcedeth_tmp_valid], 1 |
; got a valid packet - forward it to the network core |
; nic->packetlen = len; |
mov dword [forcedeth_packetlen], eax |
; |
mov word [eth_rx_data_len], ax |
;;;;;;;;; DEBUGF 1,"poll: packet len = 0x%x\n", [forcedeth_packetlen] |
; valid = 1 |
mov dword [forcedeth_tmp_valid], 1 |
; got a valid packet - forward it to the network core |
; nic->packetlen = len; |
mov dword [forcedeth_packetlen], eax |
; |
mov word [eth_rx_data_len], ax |
;;;;;;;;; DEBUGF 1,"poll: packet len = 0x%x\n", [forcedeth_packetlen] |
; memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen); |
; Copy packet to system buffer (Ether_buffer) |
;???? ecx = (len-4) |
mov ecx, eax |
push ecx |
shr ecx, 2 |
; memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen); |
; Copy packet to system buffer (Ether_buffer) |
;???? ecx = (len-4) |
mov ecx, eax |
push ecx |
shr ecx, 2 |
; rxb + (i * RX_NIC_BUFSIZE) |
mov eax, dword [forcedeth_tmp_i] |
mov bx, RX_NIC_BUFSIZE |
mul bx |
add eax, forcedeth_rxb |
; rxb + (i * RX_NIC_BUFSIZE) |
mov eax, dword [forcedeth_tmp_i] |
mov bx, RX_NIC_BUFSIZE |
mul bx |
add eax, forcedeth_rxb |
mov esi, eax |
mov esi, eax |
mov edi, Ether_buffer |
cld ; set to increment |
rep movsd ; mov dword from [esi++] to [edi++] |
pop ecx |
and ecx, 3 ; copy rest 1-3 bytes |
rep movsb |
cld ; set to increment |
rep movsd ; mov dword from [esi++] to [edi++] |
pop ecx |
and ecx, 3 ; copy rest 1-3 bytes |
rep movsb |
; wmb(); |
; ??? |
; wmb(); |
; ??? |
; np->cur_rx++; |
inc dword [forcedeth_cur_rx] |
; np->cur_rx++; |
inc dword [forcedeth_cur_rx] |
; if (!valid) |
cmp dword [forcedeth_tmp_valid], 0 |
jne @f |
; goto top; |
jmp .top |
; if (!valid) |
cmp dword [forcedeth_tmp_valid], 0 |
jne @f |
; goto top; |
jmp .top |
@@: |
; alloc_rx(nic); |
call forcedeth_alloc_rx |
; alloc_rx(nic); |
call forcedeth_alloc_rx |
; return 1; |
jmp .return1 |
; return 1; |
jmp .return1 |
;;;;; DEBUGF 1,"K : FORCEDETH: poll: ...\n" |
;;;;; DEBUGF 1,"K : FORCEDETH: poll: ...\n" |
.return0: |
mov eax, 0 |
jmp .return |
mov eax, 0 |
jmp .return |
.return1: |
mov eax, 1 |
mov eax, 1 |
.return: |
;;push eax |
;;push eax |
; ???????????????????????????????????????????????? |
; ????? clear interrupt mask/status |
; read IRQ status |
;;mov edi, dword [forcedeth_mapio_addr] |
;;mov eax, dword [edi+NvRegIrqStatus] |
; ???????????????????????????????????????????????? |
; ????? clear interrupt mask/status |
; read IRQ status |
;;mov edi, dword [forcedeth_mapio_addr] |
;;mov eax, dword [edi+NvRegIrqStatus] |
; clear events |
;;and eax, not (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF or NVREG_IRQ_LINK or NVREG_IRQ_TIMER) |
; clear events |
;;and eax, not (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF or NVREG_IRQ_LINK or NVREG_IRQ_TIMER) |
; write IRQ status |
;;mov dword [edi+NvRegIrqStatus], eax |
; ???????????????????????????????????????????????? |
; write IRQ status |
;;mov dword [edi+NvRegIrqStatus], eax |
; ???????????????????????????????????????????????? |
;;pop eax |
ret |
;;pop eax |
ret |
;*************************************************************************** |
1409,114 → 1413,114 |
;*************************************************************************** |
forcedeth_transmit: |
; send the packet to destination |
; send the packet to destination |
;pusha |
;DEBUGF 1,"K : FORCEDETH: transmit: packet type = 0x%x\n", ebx |
;DEBUGF 1,"K : FORCEDETH: transmit: packet len = 0x%x\n", ecx |
;mov eax, dword [edi] |
;DEBUGF 1,"K : FORCEDETH: transmit: dest adr = 0x%x\n", eax |
;mov eax, dword [edi+4] |
;DEBUGF 1,"K : FORCEDETH: transmit: dest adr2 = 0x%x\n", eax |
;mov eax, dword [node_addr] |
;DEBUGF 1,"K : FORCEDETH: transmit: src adr = 0x%x\n", eax |
;mov eax, dword [node_addr+4] |
;DEBUGF 1,"K : FORCEDETH: transmit: src adr2 = 0x%x\n", eax |
;DEBUGF 1,"K : FORCEDETH: transmit: packet type = 0x%x\n", ebx |
;DEBUGF 1,"K : FORCEDETH: transmit: packet len = 0x%x\n", ecx |
;mov eax, dword [edi] |
;DEBUGF 1,"K : FORCEDETH: transmit: dest adr = 0x%x\n", eax |
;mov eax, dword [edi+4] |
;DEBUGF 1,"K : FORCEDETH: transmit: dest adr2 = 0x%x\n", eax |
;mov eax, dword [node_addr] |
;DEBUGF 1,"K : FORCEDETH: transmit: src adr = 0x%x\n", eax |
;mov eax, dword [node_addr+4] |
;DEBUGF 1,"K : FORCEDETH: transmit: src adr2 = 0x%x\n", eax |
;popa |
; int nr = np->next_tx % TX_RING |
mov eax, dword [forcedeth_next_tx] |
and eax, (TX_RING-1) |
mov dword [forcedeth_tmp_nr], eax |
; point to the current txb incase multiple tx_rings are used |
; ptxb = txb + (nr * RX_NIC_BUFSIZE) |
push ecx |
mov cx, RX_NIC_BUFSIZE |
mul cx ; AX*CX, result to DX:AX |
add eax, forcedeth_txb |
mov dword [forcedeth_tmp_ptxb], eax |
push esi |
mov esi, edi ; dst MAC |
mov edi, eax ; packet buffer |
cld ; set to increment |
; copy the packet to ring buffer |
; memcpy(ptxb, d, ETH_ALEN); /* dst */ |
movsd |
movsw |
; memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ |
mov esi, node_addr |
movsd |
movsw |
; int nr = np->next_tx % TX_RING |
mov eax, dword [forcedeth_next_tx] |
and eax, (TX_RING-1) |
mov dword [forcedeth_tmp_nr], eax |
; point to the current txb incase multiple tx_rings are used |
; ptxb = txb + (nr * RX_NIC_BUFSIZE) |
push ecx |
mov cx, RX_NIC_BUFSIZE |
mul cx ; AX*CX, result to DX:AX |
add eax, forcedeth_txb |
mov dword [forcedeth_tmp_ptxb], eax |
push esi |
mov esi, edi ; dst MAC |
mov edi, eax ; packet buffer |
cld ; set to increment |
; copy the packet to ring buffer |
; memcpy(ptxb, d, ETH_ALEN); /* dst */ |
movsd |
movsw |
; memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ |
mov esi, node_addr |
movsd |
movsw |
; nstype = htons((u16) t); /* type */ |
; memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); /* type */ |
mov word [edi], bx |
add edi, 2 |
; memcpy(ptxb + ETH_HLEN, p, s); |
pop esi |
pop ecx |
push ecx |
shr ecx, 2 ; count in dwords |
rep movsd ; copy dwords from [esi+=4] to [edi+=4] |
pop ecx |
push ecx |
and ecx, 3 ; copy rest 1-3 bytes |
rep movsb ; copy bytess from [esi++] to [edi++] |
; nstype = htons((u16) t); /* type */ |
; memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); /* type */ |
mov word [edi], bx |
add edi, 2 |
; memcpy(ptxb + ETH_HLEN, p, s); |
pop esi |
pop ecx |
push ecx |
shr ecx, 2 ; count in dwords |
rep movsd ; copy dwords from [esi+=4] to [edi+=4] |
pop ecx |
push ecx |
and ecx, 3 ; copy rest 1-3 bytes |
rep movsb ; copy bytess from [esi++] to [edi++] |
; s += ETH_HLEN; |
; while (s < ETH_ZLEN) /* pad to min length */ |
; ptxb[s++] = '\0'; |
; pad to min length |
pop ecx |
add ecx, ETH_HLEN |
push ecx ; header length + data length |
cmp ecx, ETH_ZLEN |
jge @f |
mov eax, ETH_ZLEN |
sub eax, ecx |
xchg eax, ecx |
mov al, 0 |
rep stosb ; copy byte from al to [edi++] |
; s += ETH_HLEN; |
; while (s < ETH_ZLEN) /* pad to min length */ |
; ptxb[s++] = '\0'; |
; pad to min length |
pop ecx |
add ecx, ETH_HLEN |
push ecx ; header length + data length |
cmp ecx, ETH_ZLEN |
jge @f |
mov eax, ETH_ZLEN |
sub eax, ecx |
xchg eax, ecx |
mov al, 0 |
rep stosb ; copy byte from al to [edi++] |
@@: |
; tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb); |
mov eax, dword [forcedeth_tmp_nr] |
mov cl, sizeof.forcedeth_TxDesc |
mul cl |
add eax, forcedeth_tx_ring |
mov ebx, eax |
mov eax, dword [forcedeth_tmp_ptxb] |
sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov [ebx + forcedeth_TxDesc.PacketBuffer], eax |
; tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb); |
mov eax, dword [forcedeth_tmp_nr] |
mov cl, sizeof.forcedeth_TxDesc |
mul cl |
add eax, forcedeth_tx_ring |
mov ebx, eax |
mov eax, dword [forcedeth_tmp_ptxb] |
sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov [ebx + forcedeth_TxDesc.PacketBuffer], eax |
;DEBUGF 1,"K : FORCEDETH: transmit: PacketBuffer = 0x%x\n", eax |
;DEBUGF 1,"K : FORCEDETH: transmit: txflags = 0x%x\n", [forcedeth_txflags]:8 |
;DEBUGF 1,"K : FORCEDETH: transmit: PacketBuffer = 0x%x\n", eax |
;DEBUGF 1,"K : FORCEDETH: transmit: txflags = 0x%x\n", [forcedeth_txflags]:8 |
; wmb(); |
; tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags); |
pop eax ; header length + data length |
mov ecx, dword [forcedeth_txflags] |
or eax, ecx |
mov [ebx + forcedeth_TxDesc.FlagLen], eax |
; wmb(); |
; tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags); |
pop eax ; header length + data length |
mov ecx, dword [forcedeth_txflags] |
or eax, ecx |
mov [ebx + forcedeth_TxDesc.FlagLen], eax |
; writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl); |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [forcedeth_desc_ver] |
or eax, NVREG_TXRXCTL_KICK |
mov dword [edi+NvRegTxRxControl], eax |
; writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl); |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [forcedeth_desc_ver] |
or eax, NVREG_TXRXCTL_KICK |
mov dword [edi+NvRegTxRxControl], eax |
; pci_push(base); |
call forcedeth_pci_push |
; pci_push(base); |
call forcedeth_pci_push |
; np->next_tx++ |
inc dword [forcedeth_next_tx] ; may be need to reset? Overflow? |
; np->next_tx++ |
inc dword [forcedeth_next_tx]; may be need to reset? Overflow? |
ret |
ret |
;*************************************************************************** |
; Function |
1523,96 → 1527,96 |
; forcedeth_cable |
; |
; Description |
; Return AL=0, if cable is not connected |
; Returm AL=1, if cable is connected |
; Return AL=0, if cable is not connected |
; Returm AL=1, if cable is connected |
; |
;*************************************************************************** |
forcedeth_cable: |
mov al, 1 |
cmp dword [forcedeth_nocable], 1 |
jne .return |
mov al, 0 |
mov al, 1 |
cmp dword [forcedeth_nocable], 1 |
jne .return |
mov al, 0 |
.return: |
ret |
ret |
;*************************************************************************** |
; read/write a register on the PHY. |
; Caller must guarantee serialization |
; Input: EAX - miireg, EBX - addr, ECX - value |
; Output: EAX - retval |
forcedeth_mii_rw: |
push ebx |
push eax ; save miireg |
; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus) |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK |
push ebx |
push eax ; save miireg |
; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus) |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK |
; reg = readl(base + NvRegMIIControl) |
mov eax, dword [edi+NvRegMIIControl] |
test eax, NVREG_MIICTL_INUSE |
jz @f |
; writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl) |
mov dword [edi+NvRegMIIControl], NVREG_MIICTL_INUSE |
; nv_udelay(NV_MIIBUSY_DELAY) |
mov esi, NV_MIIBUSY_DELAY |
call forcedeth_nv_udelay |
; reg = readl(base + NvRegMIIControl) |
mov eax, dword [edi+NvRegMIIControl] |
test eax, NVREG_MIICTL_INUSE |
jz @f |
; writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl) |
mov dword [edi+NvRegMIIControl], NVREG_MIICTL_INUSE |
; nv_udelay(NV_MIIBUSY_DELAY) |
mov esi, NV_MIIBUSY_DELAY |
call forcedeth_nv_udelay |
@@: |
; reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg |
pop edx ; restore miireg |
mov eax, ebx |
shl eax, NVREG_MIICTL_ADDRSHIFT |
or eax, edx |
mov dword [forcedeth_tmp_reg], eax |
; reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg |
pop edx ; restore miireg |
mov eax, ebx |
shl eax, NVREG_MIICTL_ADDRSHIFT |
or eax, edx |
mov dword [forcedeth_tmp_reg], eax |
cmp ecx, MII_READ |
je @f |
; writel(value, base + NvRegMIIData) |
mov dword [edi+NvRegMIIData], ecx |
; reg |= NVREG_MIICTL_WRITE |
or dword [forcedeth_tmp_reg], NVREG_MIICTL_WRITE |
cmp ecx, MII_READ |
je @f |
; writel(value, base + NvRegMIIData) |
mov dword [edi+NvRegMIIData], ecx |
; reg |= NVREG_MIICTL_WRITE |
or dword [forcedeth_tmp_reg], NVREG_MIICTL_WRITE |
@@: |
; writel(reg, base + NvRegMIIControl) |
mov eax, dword [forcedeth_tmp_reg] |
mov dword [edi+NvRegMIIControl], eax |
; writel(reg, base + NvRegMIIControl) |
mov eax, dword [forcedeth_tmp_reg] |
mov dword [edi+NvRegMIIControl], eax |
push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; |
push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; |
; reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL) |
stdcall forcedeth_reg_delay,NvRegMIIControl,NVREG_MIICTL_INUSE,0,NV_MIIPHY_DELAY,NV_MIIPHY_DELAYMAX,0 |
; reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL) |
stdcall forcedeth_reg_delay, NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0 |
pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; |
pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; |
test eax, eax |
jz @f |
;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d timed out.\n", edx, ebx |
mov eax, 0xffffffff |
jmp .return |
test eax, eax |
jz @f |
;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d timed out.\n", edx, ebx |
mov eax, 0xffffffff |
jmp .return |
@@: |
cmp ecx, MII_READ |
je @f |
;it was a write operation - fewer failures are detectable |
;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw wrote 0x%x to reg %d at PHY %d\n", ecx, edx, ebx |
mov eax, 0 |
jmp .return |
cmp ecx, MII_READ |
je @f |
;it was a write operation - fewer failures are detectable |
;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw wrote 0x%x to reg %d at PHY %d\n", ecx, edx, ebx |
mov eax, 0 |
jmp .return |
@@: |
; readl(base + NvRegMIIStatus) |
mov eax, dword [edi+NvRegMIIStatus] |
test eax, NVREG_MIISTAT_ERROR |
jz @f |
;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d failed.\n", edx, ebx |
mov eax, 0xffffffff |
jmp .return |
; readl(base + NvRegMIIStatus) |
mov eax, dword [edi+NvRegMIIStatus] |
test eax, NVREG_MIISTAT_ERROR |
jz @f |
;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d failed.\n", edx, ebx |
mov eax, 0xffffffff |
jmp .return |
@@: |
; retval = readl(base + NvRegMIIData) |
mov eax, dword [edi+NvRegMIIData] |
;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw read from reg %d at PHY %d: 0x%x.\n", edx, ebx, eax |
; retval = readl(base + NvRegMIIData) |
mov eax, dword [edi+NvRegMIIData] |
;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw read from reg %d at PHY %d: 0x%x.\n", edx, ebx, eax |
.return: |
pop ebx |
ret |
pop ebx |
ret |
1620,37 → 1624,37 |
; Output: none |
forcedeth_nv_udelay: |
push ebx |
cmp dword [forcedeth_in_shutdown], 0 |
jne @f |
call forcedeth_udelay ; delay on ESI |
jmp .return |
push ebx |
cmp dword [forcedeth_in_shutdown], 0 |
jne @f |
call forcedeth_udelay ; delay on ESI |
jmp .return |
@@: |
.loop: |
cmp esi, 0 |
je .return |
; Don't allow an rx_ring overflow to happen |
; while shutting down the NIC it will |
; kill the receive function. |
cmp esi, 0 |
je .return |
; Don't allow an rx_ring overflow to happen |
; while shutting down the NIC it will |
; kill the receive function. |
call forcedeth_drop_rx |
mov ebx, 3 ; sleep = 3 |
cmp ebx, esi ; if(sleep > delay) |
jle @f |
mov ebx, esi ; sleep = delay |
call forcedeth_drop_rx |
mov ebx, 3 ; sleep = 3 |
cmp ebx, esi ; if(sleep > delay) |
jle @f |
mov ebx, esi ; sleep = delay |
@@: |
push esi |
mov esi, ebx |
; udelay(sleep) |
call forcedeth_udelay ; delay on ESI |
pop esi |
sub esi, ebx ; delay -= sleep |
jmp .loop |
push esi |
mov esi, ebx |
; udelay(sleep) |
call forcedeth_udelay ; delay on ESI |
pop esi |
sub esi, ebx ; delay -= sleep |
jmp .loop |
.return: |
pop ebx |
ret |
pop ebx |
ret |
; Input: none |
1657,47 → 1661,47 |
; Output: none |
forcedeth_drop_rx: |
push eax ebx ecx edi |
push eax ebx ecx edi |
; events = readl(base + NvRegIrqStatus) |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegIrqStatus] |
; events = readl(base + NvRegIrqStatus) |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegIrqStatus] |
test eax, eax |
jz @f |
; writel(events, base + NvRegIrqStatus) |
mov dword [edi+NvRegIrqStatus], eax |
test eax, eax |
jz @f |
; writel(events, base + NvRegIrqStatus) |
mov dword [edi+NvRegIrqStatus], eax |
@@: |
;if (!(events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF))) |
test eax, (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) |
jz .return |
.loop: |
; i = np->cur_rx % RX_RING |
mov eax, dword [forcedeth_cur_rx] |
and eax, (RX_RING-1) |
; //Flags = le32_to_cpu(rx_ring[i].FlagLen) |
; Flags = rx_ring[i].FlagLen |
mov cl, sizeof.forcedeth_RxDesc |
mul cl |
add eax, forcedeth_rx_ring |
mov ebx, eax |
mov eax, [ebx + forcedeth_RxDesc.FlagLen] |
; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) |
; > len = Flags & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2) |
; ??? len don't used later !!! ??? |
; ... |
test eax, NV_RX_AVAIL |
jnz .return ; still owned by hardware, |
; wmb() |
; ??? may be empty function ??? |
; np->cur_rx++ |
inc dword [forcedeth_cur_rx] |
; alloc_rx(NULL) |
call forcedeth_alloc_rx |
.return: |
pop edi ecx ebx eax |
ret |
;if (!(events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF))) |
test eax, (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) |
jz .return |
.loop: |
; i = np->cur_rx % RX_RING |
mov eax, dword [forcedeth_cur_rx] |
and eax, (RX_RING-1) |
; //Flags = le32_to_cpu(rx_ring[i].FlagLen) |
; Flags = rx_ring[i].FlagLen |
mov cl, sizeof.forcedeth_RxDesc |
mul cl |
add eax, forcedeth_rx_ring |
mov ebx, eax |
mov eax, [ebx + forcedeth_RxDesc.FlagLen] |
; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) |
; > len = Flags & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2) |
; ??? len don't used later !!! ??? |
; ... |
test eax, NV_RX_AVAIL |
jnz .return ; still owned by hardware, |
; wmb() |
; ??? may be empty function ??? |
; np->cur_rx++ |
inc dword [forcedeth_cur_rx] |
; alloc_rx(NULL) |
call forcedeth_alloc_rx |
.return: |
pop edi ecx ebx eax |
ret |
; Fill rx ring entries. |
1707,42 → 1711,42 |
; Output: none |
forcedeth_alloc_rx: |
push eax ebx ecx edx |
; refill_rx = np->refill_rx |
mov ecx, dword [forcedeth_refill_rx] |
push eax ebx ecx edx |
; refill_rx = np->refill_rx |
mov ecx, dword [forcedeth_refill_rx] |
.loop: |
cmp dword [forcedeth_cur_rx], ecx |
je .loop_end |
; nr = refill_rx % RX_RING |
mov eax, ecx |
and eax, (RX_RING-1) ; nr |
; rx_ring[nr].PacketBuffer = &rxb[nr * RX_NIC_BUFSIZE] |
push ecx |
push eax |
mov cl, sizeof.forcedeth_RxDesc |
mul cl |
add eax, forcedeth_rx_ring |
mov ebx, eax |
pop eax |
mov cx, RX_NIC_BUFSIZE |
mul cx |
pop ecx |
add eax, forcedeth_rxb |
sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov [ebx + forcedeth_RxDesc.PacketBuffer], eax |
; wmb() |
; ... |
; rx_ring[nr].FlagLen = RX_NIC_BUFSIZE | NV_RX_AVAIL |
mov [ebx + forcedeth_RxDesc.FlagLen], (RX_NIC_BUFSIZE or NV_RX_AVAIL) |
inc ecx |
jmp .loop |
cmp dword [forcedeth_cur_rx], ecx |
je .loop_end |
; nr = refill_rx % RX_RING |
mov eax, ecx |
and eax, (RX_RING-1) ; nr |
; rx_ring[nr].PacketBuffer = &rxb[nr * RX_NIC_BUFSIZE] |
push ecx |
push eax |
mov cl, sizeof.forcedeth_RxDesc |
mul cl |
add eax, forcedeth_rx_ring |
mov ebx, eax |
pop eax |
mov cx, RX_NIC_BUFSIZE |
mul cx |
pop ecx |
add eax, forcedeth_rxb |
sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov [ebx + forcedeth_RxDesc.PacketBuffer], eax |
; wmb() |
; ... |
; rx_ring[nr].FlagLen = RX_NIC_BUFSIZE | NV_RX_AVAIL |
mov [ebx + forcedeth_RxDesc.FlagLen], (RX_NIC_BUFSIZE or NV_RX_AVAIL) |
inc ecx |
jmp .loop |
.loop_end: |
; np->refill_rx = refill_rx |
mov [forcedeth_refill_rx], ecx |
; np->refill_rx = refill_rx |
mov [forcedeth_refill_rx], ecx |
.return: |
pop edx ecx ebx eax |
ret |
pop edx ecx ebx eax |
ret |
; Delay in millisec |
1750,41 → 1754,41 |
; Output: none |
forcedeth_udelay: |
call delay_ms |
ret |
ret |
; Input: offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword |
; Output: EAX - 0|1 |
;;;;proc forcedeth_reg_delay,offset:word,mask:dword,target:dword,delay:word,delaymax:word,msg:dword |
proc forcedeth_reg_delay,offset:dword,mask:dword,target:dword,delay:dword,delaymax:dword,msg:dword |
;;;;proc forcedeth_reg_delay,offset:word,mask:dword,target:dword,delay:word,delaymax:word,msg:dword |
proc forcedeth_reg_delay,offset:dword,mask:dword,target:dword,delay:dword,delaymax:dword,msg:dword |
push ebx esi edi |
; pci_push(base) |
call forcedeth_pci_push |
push ebx esi edi |
; pci_push(base) |
call forcedeth_pci_push |
.loop: |
; nv_udelay(delay) |
mov esi, dword [delay] |
call forcedeth_nv_udelay ; delay in esi |
mov eax, dword [delaymax] |
sub eax, dword [delay] |
mov dword [delaymax], eax |
; if (delaymax < 0) |
test dword [delaymax], 0x80000000 |
jz @f |
; return 1 |
mov eax, 1 |
jmp .return |
; nv_udelay(delay) |
mov esi, dword [delay] |
call forcedeth_nv_udelay ; delay in esi |
mov eax, dword [delaymax] |
sub eax, dword [delay] |
mov dword [delaymax], eax |
; if (delaymax < 0) |
test dword [delaymax], 0x80000000 |
jz @f |
; return 1 |
mov eax, 1 |
jmp .return |
@@: |
; while ((readl(base + offset) & mask) != target) |
mov edi, dword [forcedeth_mapio_addr] |
mov ebx, dword [offset] |
mov eax, dword [edi+ebx] |
and eax, dword [mask] |
cmp eax, dword [target] |
jne .loop |
xor eax, eax |
; while ((readl(base + offset) & mask) != target) |
mov edi, dword [forcedeth_mapio_addr] |
mov ebx, dword [offset] |
mov eax, dword [edi+ebx] |
and eax, dword [mask] |
cmp eax, dword [target] |
jne .loop |
xor eax, eax |
.return: |
pop edi esi ebx |
ret |
pop edi esi ebx |
ret |
endp |
1791,12 → 1795,12 |
; Input: none |
; Output: none |
forcedeth_pci_push: |
push eax edi |
;force out pending posted writes |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi] |
pop edi eax |
ret |
push eax edi |
;force out pending posted writes |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi] |
pop edi eax |
ret |
; Input: none |
1803,220 → 1807,220 |
; Output: EAX - result (0 = OK, other = error) |
forcedeth_phy_init: |
push ebx ecx |
; set advertise register |
; reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); |
push ebx ecx |
; set advertise register |
; reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); |
; EBX - addr, EAX - miireg, ECX - value |
mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_ADVERTISE |
mov ecx, MII_READ |
call forcedeth_mii_rw ; reg = eax |
mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_ADVERTISE |
mov ecx, MII_READ |
call forcedeth_mii_rw ; reg = eax |
; reg |= |
; (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | |
; ADVERTISE_100FULL | 0x800 | 0x400); |
or eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400) |
; reg |= |
; (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | |
; ADVERTISE_100FULL | 0x800 | 0x400); |
or eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400) |
; if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg)) |
; if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg)) |
; EBX - addr, EAX - miireg, ECX - value |
mov ecx, eax ; reg |
mov eax, MII_ADVERTISE |
call forcedeth_mii_rw ; eax -> return |
mov ecx, eax ; reg |
mov eax, MII_ADVERTISE |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz @f |
; printf("phy write to advertise failed.\n"); |
DEBUGF 1," K : FORCEDETH: phy write to advertise failed.\n" |
test eax, eax |
jz @f |
; printf("phy write to advertise failed.\n"); |
DEBUGF 1," K : FORCEDETH: phy write to advertise failed.\n" |
; return PHY_ERROR; |
mov eax, PHY_ERROR |
jmp .return |
; return PHY_ERROR; |
mov eax, PHY_ERROR |
jmp .return |
@@: |
; get phy interface type |
; phyinterface = readl(base + NvRegPhyInterface); |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegPhyInterface] ; phyinterface = eax |
mov dword [forcedeth_tmp_phyinterface], eax |
; get phy interface type |
; phyinterface = readl(base + NvRegPhyInterface); |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegPhyInterface] ; phyinterface = eax |
mov dword [forcedeth_tmp_phyinterface], eax |
;;;;;;;;;;;;;;;;;;;;;;;;; |
DEBUGF 1," K : FORCEDETH: phy interface type = 0x%x\n", [forcedeth_tmp_phyinterface]:8 |
;;;;;;;;;;;;;;;;;;;;;;;;; |
; see if gigabit phy |
; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); |
; see if gigabit phy |
; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); |
; EBX - addr, EAX - miireg, ECX - value |
mov eax, MII_BMSR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_status = eax |
; if (mii_status & PHY_GIGABIT) |
test eax, PHY_GIGABIT |
jnz .gigabit |
; np->gigabit = 0; |
mov dword [forcedeth_gigabit], 0 |
jmp .next_if |
mov eax, MII_BMSR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_status = eax |
; if (mii_status & PHY_GIGABIT) |
test eax, PHY_GIGABIT |
jnz .gigabit |
; np->gigabit = 0; |
mov dword [forcedeth_gigabit], 0 |
jmp .next_if |
.gigabit: |
; np->gigabit = PHY_GIGABIT; |
mov dword [forcedeth_gigabit], PHY_GIGABIT |
; np->gigabit = PHY_GIGABIT; |
mov dword [forcedeth_gigabit], PHY_GIGABIT |
; mii_control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ); |
; mii_control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ); |
; EBX - addr, EAX - miireg, ECX - value |
mov eax, MII_1000BT_CR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_control_1000 = eax |
; mii_control_1000 &= ~ADVERTISE_1000HALF; |
and eax, (not ADVERTISE_1000HALF) |
mov eax, MII_1000BT_CR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_control_1000 = eax |
; mii_control_1000 &= ~ADVERTISE_1000HALF; |
and eax, (not ADVERTISE_1000HALF) |
; if (phyinterface & PHY_RGMII) |
test dword [forcedeth_tmp_phyinterface], PHY_RGMII |
jz @f |
; mii_control_1000 |= ADVERTISE_1000FULL |
or eax, ADVERTISE_1000FULL |
jmp .next |
; if (phyinterface & PHY_RGMII) |
test dword [forcedeth_tmp_phyinterface], PHY_RGMII |
jz @f |
; mii_control_1000 |= ADVERTISE_1000FULL |
or eax, ADVERTISE_1000FULL |
jmp .next |
@@: |
; mii_control_1000 &= ~ADVERTISE_1000FULL |
and eax, (not ADVERTISE_1000FULL) |
; mii_control_1000 &= ~ADVERTISE_1000FULL |
and eax, (not ADVERTISE_1000FULL) |
.next: |
; if (mii_rw(nic, np->phyaddr, MII_1000BT_CR, mii_control_1000)) |
; if (mii_rw(nic, np->phyaddr, MII_1000BT_CR, mii_control_1000)) |
; EBX - addr, EAX - miireg, ECX - value |
mov ecx, eax |
mov eax, MII_1000BT_CR |
call forcedeth_mii_rw ; eax -> return |
mov ecx, eax |
mov eax, MII_1000BT_CR |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz .next_if |
test eax, eax |
jz .next_if |
; printf("phy init failed.\n"); |
DEBUGF 1," K : FORCEDETH: phy init failed.\n" |
; printf("phy init failed.\n"); |
DEBUGF 1," K : FORCEDETH: phy init failed.\n" |
; return PHY_ERROR; |
mov eax, PHY_ERROR |
jmp .return |
; return PHY_ERROR; |
mov eax, PHY_ERROR |
jmp .return |
.next_if: |
; reset the phy |
; if (phy_reset(nic)) |
call forcedeth_phy_reset |
test eax, eax |
jz @f |
; printf("phy reset failed\n") |
DEBUGF 1," K : FORCEDETH: phy reset failed.\n" |
; return PHY_ERROR |
mov eax, PHY_ERROR |
jmp .return |
; reset the phy |
; if (phy_reset(nic)) |
call forcedeth_phy_reset |
test eax, eax |
jz @f |
; printf("phy reset failed\n") |
DEBUGF 1," K : FORCEDETH: phy reset failed.\n" |
; return PHY_ERROR |
mov eax, PHY_ERROR |
jmp .return |
@@: |
; phy vendor specific configuration |
; if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII)) |
cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA |
jne .next_if2 |
test dword [forcedeth_tmp_phyinterface], PHY_RGMII |
jz .next_if2 |
; phy vendor specific configuration |
; if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII)) |
cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA |
jne .next_if2 |
test dword [forcedeth_tmp_phyinterface], PHY_RGMII |
jz .next_if2 |
; phy_reserved = mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ) |
; phy_reserved = mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ) |
; EBX - addr, EAX - miireg, ECX - value |
mov eax, MII_RESV1 |
mov ecx, MII_READ |
call forcedeth_mii_rw ; phy_reserved = eax |
; phy_reserved &= ~(PHY_INIT1 | PHY_INIT2) |
and eax, (not (PHY_INIT1 or PHY_INIT2)) |
; phy_reserved |= (PHY_INIT3 | PHY_INIT4) |
or eax, (PHY_INIT3 or PHY_INIT4) |
; if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved)) |
mov eax, MII_RESV1 |
mov ecx, MII_READ |
call forcedeth_mii_rw ; phy_reserved = eax |
; phy_reserved &= ~(PHY_INIT1 | PHY_INIT2) |
and eax, (not (PHY_INIT1 or PHY_INIT2)) |
; phy_reserved |= (PHY_INIT3 | PHY_INIT4) |
or eax, (PHY_INIT3 or PHY_INIT4) |
; if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved)) |
; EBX - addr, EAX - miireg, ECX - value |
mov ecx, eax |
mov eax, MII_RESV1 |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz @f |
; printf("phy init failed.\n") |
DEBUGF 1," K : FORCEDETH: phy init failed.\n" |
; return PHY_ERROR |
mov eax, PHY_ERROR |
jmp .return |
mov ecx, eax |
mov eax, MII_RESV1 |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz @f |
; printf("phy init failed.\n") |
DEBUGF 1," K : FORCEDETH: phy init failed.\n" |
; return PHY_ERROR |
mov eax, PHY_ERROR |
jmp .return |
@@: |
; phy_reserved = mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ); |
; phy_reserved = mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ); |
; EBX - addr, EAX - miireg, ECX - value |
mov eax, MII_NCONFIG |
mov ecx, MII_READ |
call forcedeth_mii_rw ; phy_reserved = eax |
mov eax, MII_NCONFIG |
mov ecx, MII_READ |
call forcedeth_mii_rw ; phy_reserved = eax |
; phy_reserved |= PHY_INIT5 |
or eax, PHY_INIT5 |
; if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved)) |
; phy_reserved |= PHY_INIT5 |
or eax, PHY_INIT5 |
; if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved)) |
; EBX - addr, EAX - miireg, ECX - value |
mov ecx, eax |
mov eax, MII_NCONFIG |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz .next_if2 |
; printf("phy init failed.\n") |
DEBUGF 1," K : FORCEDETH: phy init failed.\n" |
; return PHY_ERROR |
mov eax, PHY_ERROR |
jmp .return |
mov ecx, eax |
mov eax, MII_NCONFIG |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz .next_if2 |
; printf("phy init failed.\n") |
DEBUGF 1," K : FORCEDETH: phy init failed.\n" |
; return PHY_ERROR |
mov eax, PHY_ERROR |
jmp .return |
.next_if2: |
; if (np->phy_oui == PHY_OUI_CICADA) |
cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA |
jne .restart |
; phy_reserved = mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ) |
; if (np->phy_oui == PHY_OUI_CICADA) |
cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA |
jne .restart |
; phy_reserved = mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ) |
; EBX - addr, EAX - miireg, ECX - value |
mov eax, MII_SREVISION |
mov ecx, MII_READ |
call forcedeth_mii_rw ; phy_reserved = eax |
; phy_reserved |= PHY_INIT6 |
or eax, PHY_INIT6 |
; if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved)) |
mov ecx, eax |
mov eax, MII_SREVISION |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz .restart |
; printf("phy init failed.\n"); |
DEBUGF 1," K : FORCEDETH: phy init failed.\n" |
; return PHY_ERROR; |
jmp .return |
mov eax, MII_SREVISION |
mov ecx, MII_READ |
call forcedeth_mii_rw ; phy_reserved = eax |
; phy_reserved |= PHY_INIT6 |
or eax, PHY_INIT6 |
; if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved)) |
mov ecx, eax |
mov eax, MII_SREVISION |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz .restart |
; printf("phy init failed.\n"); |
DEBUGF 1," K : FORCEDETH: phy init failed.\n" |
; return PHY_ERROR; |
jmp .return |
.restart: |
; restart auto negotiation |
; mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ) |
; restart auto negotiation |
; mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ) |
; EBX - addr, EAX - miireg, ECX - value |
mov eax, MII_BMCR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_control = eax |
mov eax, MII_BMCR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_control = eax |
; mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE) |
or eax, (BMCR_ANRESTART or BMCR_ANENABLE) |
; if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control)) |
mov ecx, eax |
mov eax, MII_BMCR |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz .ok |
; mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE) |
or eax, (BMCR_ANRESTART or BMCR_ANENABLE) |
; if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control)) |
mov ecx, eax |
mov eax, MII_BMCR |
call forcedeth_mii_rw ; eax -> return |
test eax, eax |
jz .ok |
; return PHY_ERROR; |
mov eax, PHY_ERROR |
jmp .return |
; return PHY_ERROR; |
mov eax, PHY_ERROR |
jmp .return |
.ok: |
mov eax, 0 |
mov eax, 0 |
.return: |
pop ecx ebx |
ret |
pop ecx ebx |
ret |
; Input: none |
2023,670 → 2027,670 |
; Output: EAX - result (0 = OK, other = error) |
forcedeth_phy_reset: |
push ebx ecx edx |
push ebx ecx edx |
; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); |
; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); |
; EBX - addr, EAX - miireg, ECX - value |
mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_BMCR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; miicontrol = eax |
mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_BMCR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; miicontrol = eax |
; miicontrol |= BMCR_RESET; |
or eax, BMCR_RESET |
push eax |
; miicontrol |= BMCR_RESET; |
or eax, BMCR_RESET |
push eax |
; if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol)) |
; if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol)) |
; EBX - addr, EAX - miireg, ECX - value |
mov ecx, eax |
mov eax, MII_BMCR |
call forcedeth_mii_rw ; miicontrol = eax |
mov ecx, eax |
mov eax, MII_BMCR |
call forcedeth_mii_rw ; miicontrol = eax |
test eax, eax |
jz @f |
pop eax |
mov eax, 0xffffffff |
jmp .return |
test eax, eax |
jz @f |
pop eax |
mov eax, 0xffffffff |
jmp .return |
@@: |
pop eax |
pop eax |
; wait for 500ms |
; mdelay(500) |
mov esi, 500 |
call forcedeth_udelay |
; wait for 500ms |
; mdelay(500) |
mov esi, 500 |
call forcedeth_udelay |
; must wait till reset is deasserted |
; while (miicontrol & BMCR_RESET) { |
mov edx, 100 |
; must wait till reset is deasserted |
; while (miicontrol & BMCR_RESET) { |
mov edx, 100 |
.while_loop: |
test eax, BMCR_RESET |
jz .while_loop_exit |
test eax, BMCR_RESET |
jz .while_loop_exit |
; mdelay(10); |
mov esi, 10 |
call forcedeth_udelay |
; mdelay(10); |
mov esi, 10 |
call forcedeth_udelay |
; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); |
; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); |
; EBX - addr, EAX - miireg, ECX - value |
mov eax, MII_BMCR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; miicontrol = eax |
mov eax, MII_BMCR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; miicontrol = eax |
; FIXME: 100 tries seem excessive |
; if (tries++ > 100) |
dec edx |
jnz .while_loop |
; return -1; |
mov eax, 0xffffffff |
jmp .return |
; FIXME: 100 tries seem excessive |
; if (tries++ > 100) |
dec edx |
jnz .while_loop |
; return -1; |
mov eax, 0xffffffff |
jmp .return |
.while_loop_exit: |
; return 0 |
mov eax, 0 |
.return: |
pop edx ecx ebx |
ret |
; return 0 |
mov eax, 0 |
.return: |
pop edx ecx ebx |
ret |
; Input: none |
; Output: none |
forcedeth_mac_reset: |
push esi edi |
push esi edi |
; dprintf("mac_reset\n") |
DEBUGF 1," K : FORCEDETH: mac_reset.\n" |
; dprintf("mac_reset\n") |
DEBUGF 1," K : FORCEDETH: mac_reset.\n" |
; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [forcedeth_desc_ver] |
or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) |
mov dword [edi+NvRegTxRxControl], eax |
; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [forcedeth_desc_ver] |
or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) |
mov dword [edi+NvRegTxRxControl], eax |
; pci_push(base) |
call forcedeth_pci_push |
; writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset) |
mov dword [edi+NvRegMacReset], NVREG_MAC_RESET_ASSERT |
; pci_push(base) |
call forcedeth_pci_push |
; writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset) |
mov dword [edi+NvRegMacReset], NVREG_MAC_RESET_ASSERT |
; pci_push(base) |
call forcedeth_pci_push |
; pci_push(base) |
call forcedeth_pci_push |
; udelay(NV_MAC_RESET_DELAY) |
mov esi, NV_MAC_RESET_DELAY |
call forcedeth_nv_udelay |
; udelay(NV_MAC_RESET_DELAY) |
mov esi, NV_MAC_RESET_DELAY |
call forcedeth_nv_udelay |
; writel(0, base + NvRegMacReset) |
mov dword [edi+NvRegMacReset], 0 |
; writel(0, base + NvRegMacReset) |
mov dword [edi+NvRegMacReset], 0 |
; pci_push(base) |
call forcedeth_pci_push |
; udelay(NV_MAC_RESET_DELAY) |
mov esi, NV_MAC_RESET_DELAY |
call forcedeth_nv_udelay |
; pci_push(base) |
call forcedeth_pci_push |
; udelay(NV_MAC_RESET_DELAY) |
mov esi, NV_MAC_RESET_DELAY |
call forcedeth_nv_udelay |
; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) |
mov eax, dword [forcedeth_desc_ver] |
or eax, NVREG_TXRXCTL_BIT2 |
mov dword [edi+NvRegTxRxControl], eax |
; pci_push(base) |
call forcedeth_pci_push |
; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) |
mov eax, dword [forcedeth_desc_ver] |
or eax, NVREG_TXRXCTL_BIT2 |
mov dword [edi+NvRegTxRxControl], eax |
; pci_push(base) |
call forcedeth_pci_push |
pop edi esi |
ret |
pop edi esi |
ret |
; Input: none |
; Output: none |
forcedeth_init_ring: |
push eax ebx ecx |
push eax ebx ecx |
; np->next_tx = np->nic_tx = 0 |
mov dword[forcedeth_next_tx], 0 |
mov dword[forcedeth_nic_tx], 0 |
mov dword[forcedeth_next_tx], 0 |
mov dword[forcedeth_nic_tx], 0 |
; for (i = 0; i < TX_RING; i++) |
mov ecx, TX_RING |
mov ecx, TX_RING |
.for_loop: |
; tx_ring[i].FlagLen = 0; |
mov eax, ecx |
dec eax |
mov bl, sizeof.forcedeth_TxDesc |
mul bl |
add eax, forcedeth_tx_ring |
mov ebx, eax |
mov dword [ebx + forcedeth_TxDesc.FlagLen], 0 |
loop .for_loop |
mov eax, ecx |
dec eax |
mov bl, sizeof.forcedeth_TxDesc |
mul bl |
add eax, forcedeth_tx_ring |
mov ebx, eax |
mov dword [ebx + forcedeth_TxDesc.FlagLen], 0 |
loop .for_loop |
; np->cur_rx = RX_RING; |
mov dword [forcedeth_cur_rx], RX_RING |
mov dword [forcedeth_cur_rx], RX_RING |
; np->refill_rx = 0; |
mov dword [forcedeth_refill_rx], 0 |
mov dword [forcedeth_refill_rx], 0 |
;for (i = 0; i < RX_RING; i++) |
mov ecx, RX_RING |
;for (i = 0; i < RX_RING; i++) |
mov ecx, RX_RING |
.for_loop2: |
; rx_ring[i].FlagLen = 0; |
mov eax, ecx |
dec eax |
mov bl, sizeof.forcedeth_RxDesc |
mul bl |
add eax, forcedeth_rx_ring |
mov ebx, eax |
mov dword [ebx + forcedeth_RxDesc.FlagLen], 0 |
loop .for_loop2 |
mov eax, ecx |
dec eax |
mov bl, sizeof.forcedeth_RxDesc |
mul bl |
add eax, forcedeth_rx_ring |
mov ebx, eax |
mov dword [ebx + forcedeth_RxDesc.FlagLen], 0 |
loop .for_loop2 |
; alloc_rx(nic); |
call forcedeth_alloc_rx |
; alloc_rx(nic); |
call forcedeth_alloc_rx |
.return: |
pop ecx ebx eax |
ret |
pop ecx ebx eax |
ret |
; Input: none |
; Output: none |
forcedeth_txrx_reset: |
push eax esi edi |
push eax esi edi |
; dprintf(("txrx_reset\n")) |
DEBUGF 1," K : FORCEDETH: txrx_reset.\n" |
; dprintf(("txrx_reset\n")) |
DEBUGF 1," K : FORCEDETH: txrx_reset.\n" |
; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [forcedeth_desc_ver] |
or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) |
mov dword [edi+NvRegTxRxControl], eax |
; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [forcedeth_desc_ver] |
or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) |
mov dword [edi+NvRegTxRxControl], eax |
; pci_push(base) |
call forcedeth_pci_push |
; pci_push(base) |
call forcedeth_pci_push |
; nv_udelay(NV_TXRX_RESET_DELAY) |
mov esi, NV_TXRX_RESET_DELAY |
call forcedeth_nv_udelay |
; nv_udelay(NV_TXRX_RESET_DELAY) |
mov esi, NV_TXRX_RESET_DELAY |
call forcedeth_nv_udelay |
; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) |
mov eax, dword [forcedeth_desc_ver] |
or eax, NVREG_TXRXCTL_BIT2 |
mov dword [edi+NvRegTxRxControl], eax |
; pci_push(base) |
call forcedeth_pci_push |
; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) |
mov eax, dword [forcedeth_desc_ver] |
or eax, NVREG_TXRXCTL_BIT2 |
mov dword [edi+NvRegTxRxControl], eax |
; pci_push(base) |
call forcedeth_pci_push |
.return: |
pop edi esi eax |
ret |
pop edi esi eax |
ret |
; Input: none |
; Output: none |
forcedeth_set_multicast: |
push edi |
push edi |
; u32 addr[2]; |
; u32 mask[2]; |
; u32 pff; |
; u32 alwaysOff[2]; |
; u32 alwaysOn[2]; |
; |
; memset(addr, 0, sizeof(addr)); |
; memset(mask, 0, sizeof(mask)); |
; |
; pff = NVREG_PFF_MYADDR; |
; |
; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0; |
; |
; addr[0] = alwaysOn[0]; |
; addr[1] = alwaysOn[1]; |
; mask[0] = alwaysOn[0] | alwaysOff[0]; |
; mask[1] = alwaysOn[1] | alwaysOff[1]; |
; |
; addr[0] |= NVREG_MCASTADDRA_FORCE; |
; pff |= NVREG_PFF_ALWAYS; |
; stop_rx(); |
call forcedeth_stop_rx |
; writel(addr[0], base + NvRegMulticastAddrA); |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE |
; writel(addr[1], base + NvRegMulticastAddrB); |
mov dword [edi+NvRegMulticastAddrB], 0 |
; writel(mask[0], base + NvRegMulticastMaskA); |
mov dword [edi+NvRegMulticastMaskA], 0 |
; writel(mask[1], base + NvRegMulticastMaskB); |
mov dword [edi+NvRegMulticastMaskB], 0 |
; writel(pff, base + NvRegPacketFilterFlags); |
mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_MYADDR or NVREG_PFF_ALWAYS) |
; start_rx(nic); |
call forcedeth_start_rx |
; u32 addr[2]; |
; u32 mask[2]; |
; u32 pff; |
; u32 alwaysOff[2]; |
; u32 alwaysOn[2]; |
; |
; memset(addr, 0, sizeof(addr)); |
; memset(mask, 0, sizeof(mask)); |
; |
; pff = NVREG_PFF_MYADDR; |
; |
; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0; |
; |
; addr[0] = alwaysOn[0]; |
; addr[1] = alwaysOn[1]; |
; mask[0] = alwaysOn[0] | alwaysOff[0]; |
; mask[1] = alwaysOn[1] | alwaysOff[1]; |
; |
; addr[0] |= NVREG_MCASTADDRA_FORCE; |
; pff |= NVREG_PFF_ALWAYS; |
; stop_rx(); |
call forcedeth_stop_rx |
; writel(addr[0], base + NvRegMulticastAddrA); |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE |
; writel(addr[1], base + NvRegMulticastAddrB); |
mov dword [edi+NvRegMulticastAddrB], 0 |
; writel(mask[0], base + NvRegMulticastMaskA); |
mov dword [edi+NvRegMulticastMaskA], 0 |
; writel(mask[1], base + NvRegMulticastMaskB); |
mov dword [edi+NvRegMulticastMaskB], 0 |
; writel(pff, base + NvRegPacketFilterFlags); |
mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_MYADDR or NVREG_PFF_ALWAYS) |
; start_rx(nic); |
call forcedeth_start_rx |
.return: |
pop edi |
ret |
pop edi |
ret |
; Input: none |
; Output: none |
forcedeth_start_rx: |
push edi |
push edi |
; dprintf(("start_rx\n")) |
DEBUGF 1," K : FORCEDETH: start_rx.\n" |
; dprintf(("start_rx\n")) |
DEBUGF 1," K : FORCEDETH: start_rx.\n" |
; Already running? Stop it. |
; if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) { |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegReceiverControl] |
test eax, NVREG_RCVCTL_START |
jz @f |
; writel(0, base + NvRegReceiverControl) |
mov dword [edi+NvRegReceiverControl], 0 |
; pci_push(base) |
call forcedeth_pci_push |
; Already running? Stop it. |
; if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) { |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegReceiverControl] |
test eax, NVREG_RCVCTL_START |
jz @f |
; writel(0, base + NvRegReceiverControl) |
mov dword [edi+NvRegReceiverControl], 0 |
; pci_push(base) |
call forcedeth_pci_push |
@@: |
; writel(np->linkspeed, base + NvRegLinkSpeed); |
mov eax, dword [forcedeth_linkspeed] |
mov dword [edi+NvRegLinkSpeed], eax |
; pci_push(base); |
call forcedeth_pci_push |
; writel(NVREG_RCVCTL_START, base + NvRegReceiverControl); |
mov dword [edi+NvRegReceiverControl], NVREG_RCVCTL_START |
; pci_push(base); |
call forcedeth_pci_push |
; writel(np->linkspeed, base + NvRegLinkSpeed); |
mov eax, dword [forcedeth_linkspeed] |
mov dword [edi+NvRegLinkSpeed], eax |
; pci_push(base); |
call forcedeth_pci_push |
; writel(NVREG_RCVCTL_START, base + NvRegReceiverControl); |
mov dword [edi+NvRegReceiverControl], NVREG_RCVCTL_START |
; pci_push(base); |
call forcedeth_pci_push |
.return: |
pop edi |
ret |
pop edi |
ret |
; Input: none |
; Output: none |
forcedeth_stop_rx: |
push esi edi |
push esi edi |
; dprintf(("stop_rx\n")) |
DEBUGF 1," K : FORCEDETH: stop_rx.\n" |
; dprintf(("stop_rx\n")) |
DEBUGF 1," K : FORCEDETH: stop_rx.\n" |
; writel(0, base + NvRegReceiverControl) |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegReceiverControl], 0 |
; writel(0, base + NvRegReceiverControl) |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegReceiverControl], 0 |
push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; |
; reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, "stop_rx: ReceiverStatus remained busy"); |
stdcall forcedeth_reg_delay,NvRegReceiverStatus,NVREG_RCVSTAT_BUSY,0,NV_RXSTOP_DELAY1,NV_RXSTOP_DELAY1MAX,0 |
pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; |
push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; |
; reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, "stop_rx: ReceiverStatus remained busy"); |
stdcall forcedeth_reg_delay, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0 |
pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; |
; nv_udelay(NV_RXSTOP_DELAY2) |
mov esi, NV_RXSTOP_DELAY2 |
call forcedeth_nv_udelay |
; nv_udelay(NV_RXSTOP_DELAY2) |
mov esi, NV_RXSTOP_DELAY2 |
call forcedeth_nv_udelay |
; writel(0, base + NvRegLinkSpeed) |
mov dword [edi+NvRegLinkSpeed], 0 |
; writel(0, base + NvRegLinkSpeed) |
mov dword [edi+NvRegLinkSpeed], 0 |
.return: |
pop edi esi |
ret |
pop edi esi |
ret |
; Input: none |
; Output: EAX |
forcedeth_update_linkspeed: |
push ebx ecx esi edi |
push ebx ecx esi edi |
; BMSR_LSTATUS is latched, read it twice: |
; we want the current value. |
; mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) |
; BMSR_LSTATUS is latched, read it twice: |
; we want the current value. |
; mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) |
;EBX - addr, EAX - miireg, ECX - value |
mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_BMSR |
mov ecx, MII_READ |
call forcedeth_mii_rw |
mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_BMSR |
mov ecx, MII_READ |
call forcedeth_mii_rw |
; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) |
; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) |
;EBX - addr, EAX - miireg, ECX - value |
mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_BMSR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_status = eax |
; yhlu |
mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_BMSR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_status = eax |
; yhlu |
; for(i=0;i<30;i++) { |
mov ecx, 30 |
; for(i=0;i<30;i++) { |
mov ecx, 30 |
.for_loop: |
push ecx |
push ecx |
; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); |
; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); |
;EBX - addr, EAX - miireg, ECX - value |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_BMSR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_status = eax |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_BMSR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; mii_status = eax |
; if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break; |
test eax, BMSR_LSTATUS |
jz @f |
test eax, BMSR_ANEGCOMPLETE |
jz @f |
; break |
pop ecx |
jmp .break |
; if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break; |
test eax, BMSR_LSTATUS |
jz @f |
test eax, BMSR_ANEGCOMPLETE |
jz @f |
; break |
pop ecx |
jmp .break |
@@: |
; mdelay(100); |
push eax ; ??? |
mov esi, 100 |
call forcedeth_udelay |
pop eax ; ??? |
; mdelay(100); |
push eax ; ??? |
mov esi, 100 |
call forcedeth_udelay |
pop eax ; ??? |
pop ecx |
loop .for_loop |
pop ecx |
loop .for_loop |
.break: |
; if (!(mii_status & BMSR_LSTATUS)) { |
test eax, BMSR_LSTATUS |
jnz @f |
; if (!(mii_status & BMSR_LSTATUS)) { |
test eax, BMSR_LSTATUS |
jnz @f |
; printf("no link detected by phy - falling back to 10HD.\n") |
DEBUGF 1," K : FORCEDETH: update_linkspeed: no link detected by phy - falling back to 10HD.\n" |
; printf("no link detected by phy - falling back to 10HD.\n") |
DEBUGF 1," K : FORCEDETH: update_linkspeed: no link detected by phy - falling back to 10HD.\n" |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; newdup = 0; |
mov dword [forcedeth_tmp_newdup], 0 |
; retval = 0; |
mov dword [forcedeth_tmp_retval], 0 |
; newdup = 0; |
mov dword [forcedeth_tmp_newdup], 0 |
; retval = 0; |
mov dword [forcedeth_tmp_retval], 0 |
; goto set_speed; |
jmp .set_speed |
; goto set_speed; |
jmp .set_speed |
@@: |
; check auto negotiation is complete |
; if (!(mii_status & BMSR_ANEGCOMPLETE)) { |
test eax, BMSR_ANEGCOMPLETE |
jnz @f |
; check auto negotiation is complete |
; if (!(mii_status & BMSR_ANEGCOMPLETE)) { |
test eax, BMSR_ANEGCOMPLETE |
jnz @f |
; still in autonegotiation - configure nic for 10 MBit HD and wait. |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; still in autonegotiation - configure nic for 10 MBit HD and wait. |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; newdup = 0 |
mov dword [forcedeth_tmp_newdup], 0 |
; newdup = 0 |
mov dword [forcedeth_tmp_newdup], 0 |
; retval = 0 |
mov dword [forcedeth_tmp_retval], 0 |
; retval = 0 |
mov dword [forcedeth_tmp_retval], 0 |
; printf("autoneg not completed - falling back to 10HD.\n") |
DEBUGF 1," K : FORCEDETH: update_linkspeed: autoneg not completed - falling back to 10HD.\n" |
; printf("autoneg not completed - falling back to 10HD.\n") |
DEBUGF 1," K : FORCEDETH: update_linkspeed: autoneg not completed - falling back to 10HD.\n" |
; goto set_speed |
jmp .set_speed |
; goto set_speed |
jmp .set_speed |
@@: |
; retval = 1 |
mov dword [forcedeth_tmp_retval], 1 |
; if (np->gigabit == PHY_GIGABIT) { |
cmp dword [forcedeth_gigabit], PHY_GIGABIT |
jne .end_if |
; control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ) |
; retval = 1 |
mov dword [forcedeth_tmp_retval], 1 |
; if (np->gigabit == PHY_GIGABIT) { |
cmp dword [forcedeth_gigabit], PHY_GIGABIT |
jne .end_if |
; control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ) |
;EBX - addr, EAX - miireg, ECX - value |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_1000BT_CR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; control_1000 = eax |
mov dword [forcedeth_tmp_control_1000], eax |
; status_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ) |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_1000BT_CR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; control_1000 = eax |
mov dword [forcedeth_tmp_control_1000], eax |
; status_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ) |
;EBX - addr, EAX - miireg, ECX - value |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_1000BT_SR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; status_1000 = eax |
;mov dword [forcedeth_tmp_status_1000], eax |
; if ((control_1000 & ADVERTISE_1000FULL) && |
; (status_1000 & LPA_1000FULL)) { |
test eax, LPA_1000FULL |
jz .end_if |
test dword [forcedeth_tmp_control_1000], ADVERTISE_1000FULL |
jz .end_if |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_1000BT_SR |
mov ecx, MII_READ |
call forcedeth_mii_rw ; status_1000 = eax |
;mov dword [forcedeth_tmp_status_1000], eax |
; if ((control_1000 & ADVERTISE_1000FULL) && |
; (status_1000 & LPA_1000FULL)) { |
test eax, LPA_1000FULL |
jz .end_if |
test dword [forcedeth_tmp_control_1000], ADVERTISE_1000FULL |
jz .end_if |
; printf ("update_linkspeed: GBit ethernet detected.\n") |
DEBUGF 1," K : FORCEDETH: update_linkspeed: GBit ethernet detected.\n" |
; printf ("update_linkspeed: GBit ethernet detected.\n") |
DEBUGF 1," K : FORCEDETH: update_linkspeed: GBit ethernet detected.\n" |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_1000) |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_1000) |
; newdup = 1 |
mov dword [forcedeth_tmp_newdup], 1 |
; newdup = 1 |
mov dword [forcedeth_tmp_newdup], 1 |
; goto set_speed |
jmp .set_speed |
; goto set_speed |
jmp .set_speed |
.end_if: |
; adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); |
; adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); |
;EBX - addr, EAX - miireg, ECX - value |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_ADVERTISE |
mov ecx, MII_READ |
call forcedeth_mii_rw ; adv = eax |
mov dword [forcedeth_tmp_adv], eax |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_ADVERTISE |
mov ecx, MII_READ |
call forcedeth_mii_rw ; adv = eax |
mov dword [forcedeth_tmp_adv], eax |
; lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ); |
; lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ); |
;EBX - addr, EAX - miireg, ECX - value |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_LPA |
mov ecx, MII_READ |
call forcedeth_mii_rw ; lpa = eax |
mov dword [forcedeth_tmp_lpa], eax |
;mov ebx, dword [forcedeth_phyaddr] |
mov eax, MII_LPA |
mov ecx, MII_READ |
call forcedeth_mii_rw ; lpa = eax |
mov dword [forcedeth_tmp_lpa], eax |
; dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n", adv, lpa)); |
DEBUGF 1," K : FORCEDETH: update_linkspeed: PHY advertises 0x%x, lpa 0x%x.\n", [forcedeth_tmp_adv]:8, [forcedeth_tmp_lpa]:8 |
; dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n", adv, lpa)); |
DEBUGF 1," K : FORCEDETH: update_linkspeed: PHY advertises 0x%x, lpa 0x%x.\n", [forcedeth_tmp_adv]:8, [forcedeth_tmp_lpa]:8 |
; FIXME: handle parallel detection properly, handle gigabit ethernet |
; lpa = lpa & adv |
mov eax, dword [forcedeth_tmp_adv] |
and dword [forcedeth_tmp_lpa], eax |
; FIXME: handle parallel detection properly, handle gigabit ethernet |
; lpa = lpa & adv |
mov eax, dword [forcedeth_tmp_adv] |
and dword [forcedeth_tmp_lpa], eax |
mov eax, dword [forcedeth_tmp_lpa] |
mov eax, dword [forcedeth_tmp_lpa] |
; if (lpa & LPA_100FULL) { |
test eax, LPA_100FULL |
jz @f |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) |
; newdup = 1 |
mov dword [forcedeth_tmp_newdup], 1 |
jmp .set_speed |
; if (lpa & LPA_100FULL) { |
test eax, LPA_100FULL |
jz @f |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) |
; newdup = 1 |
mov dword [forcedeth_tmp_newdup], 1 |
jmp .set_speed |
@@: |
; } else if (lpa & LPA_100HALF) { |
test eax, LPA_100HALF |
jz @f |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) |
; newdup = 0 |
mov dword [forcedeth_tmp_newdup], 0 |
jmp .set_speed |
; } else if (lpa & LPA_100HALF) { |
test eax, LPA_100HALF |
jz @f |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) |
; newdup = 0 |
mov dword [forcedeth_tmp_newdup], 0 |
jmp .set_speed |
@@: |
; } else if (lpa & LPA_10FULL) { |
test eax, LPA_10FULL |
jz @f |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; newdup = 1 |
mov dword [forcedeth_tmp_newdup], 1 |
jmp .set_speed |
; } else if (lpa & LPA_10FULL) { |
test eax, LPA_10FULL |
jz @f |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; newdup = 1 |
mov dword [forcedeth_tmp_newdup], 1 |
jmp .set_speed |
@@: |
; } else if (lpa & LPA_10HALF) { |
test eax, LPA_10HALF |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10; |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; newdup = 0; |
mov dword [forcedeth_tmp_newdup], 0 |
jmp .set_speed |
; } else if (lpa & LPA_10HALF) { |
test eax, LPA_10HALF |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10; |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; newdup = 0; |
mov dword [forcedeth_tmp_newdup], 0 |
jmp .set_speed |
@@: |
; } else { |
; printf("bad ability %hX - falling back to 10HD.\n", lpa) |
DEBUGF 1," K : FORCEDETH: update_linkspeed: bad ability 0x%x - falling back to 10HD.\n", eax |
; } else { |
; printf("bad ability %hX - falling back to 10HD.\n", lpa) |
DEBUGF 1," K : FORCEDETH: update_linkspeed: bad ability 0x%x - falling back to 10HD.\n", eax |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; newdup = 0 |
mov dword [forcedeth_tmp_newdup], 0 |
; } |
; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 |
mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) |
; newdup = 0 |
mov dword [forcedeth_tmp_newdup], 0 |
; } |
.set_speed: |
; if (np->duplex == newdup && np->linkspeed == newls) |
mov eax, dword [forcedeth_tmp_newdup] |
cmp eax, dword [forcedeth_duplex] |
jne .end_if2 |
mov eax, dword [forcedeth_tmp_newls] |
cmp eax, dword [forcedeth_linkspeed] |
jne .end_if2 |
; return retval; |
jmp .return |
; if (np->duplex == newdup && np->linkspeed == newls) |
mov eax, dword [forcedeth_tmp_newdup] |
cmp eax, dword [forcedeth_duplex] |
jne .end_if2 |
mov eax, dword [forcedeth_tmp_newls] |
cmp eax, dword [forcedeth_linkspeed] |
jne .end_if2 |
; return retval; |
jmp .return |
.end_if2: |
; dprintf(("changing link setting from %d/%s to %d/%s.\n", |
; np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex")) |
DEBUGF 1," K : FORCEDETH: update_linkspeed: changing link from %x/XD to %x/XD.\n", [forcedeth_linkspeed]:8, [forcedeth_tmp_newls]:8 ; !!!!!!!!!!!!!!!!!!!!!!!!!!!! |
; dprintf(("changing link setting from %d/%s to %d/%s.\n", |
; np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex")) |
DEBUGF 1," K : FORCEDETH: update_linkspeed: changing link from %x/XD to %x/XD.\n", [forcedeth_linkspeed]:8, [forcedeth_tmp_newls]:8 ; !!!!!!!!!!!!!!!!!!!!!!!!!!!! |
; np->duplex = newdup |
mov eax, dword [forcedeth_tmp_newdup] |
mov dword [forcedeth_duplex], eax |
; np->duplex = newdup |
mov eax, dword [forcedeth_tmp_newdup] |
mov dword [forcedeth_duplex], eax |
; np->linkspeed = newls |
mov eax, [forcedeth_tmp_newls] |
mov dword [forcedeth_linkspeed], eax |
; np->linkspeed = newls |
mov eax, [forcedeth_tmp_newls] |
mov dword [forcedeth_linkspeed], eax |
; if (np->gigabit == PHY_GIGABIT) { |
cmp dword [forcedeth_gigabit], PHY_GIGABIT |
jne .end_if3 |
; if (np->gigabit == PHY_GIGABIT) { |
cmp dword [forcedeth_gigabit], PHY_GIGABIT |
jne .end_if3 |
; phyreg = readl(base + NvRegRandomSeed); |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegRandomSeed] |
; phyreg = readl(base + NvRegRandomSeed); |
mov edi, dword [forcedeth_mapio_addr] |
mov eax, dword [edi+NvRegRandomSeed] |
; phyreg &= ~(0x3FF00); |
and eax, not (0x3FF00) |
mov ecx, eax ; phyreg = ecx |
; phyreg &= ~(0x3FF00); |
and eax, not (0x3FF00) |
mov ecx, eax ; phyreg = ecx |
; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) |
mov eax, dword [forcedeth_linkspeed] |
and eax, 0xFFF |
cmp eax, NVREG_LINKSPEED_10 |
jne @f |
; phyreg |= NVREG_RNDSEED_FORCE3 |
or ecx, NVREG_RNDSEED_FORCE3 |
jmp .end_if4 |
; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) |
mov eax, dword [forcedeth_linkspeed] |
and eax, 0xFFF |
cmp eax, NVREG_LINKSPEED_10 |
jne @f |
; phyreg |= NVREG_RNDSEED_FORCE3 |
or ecx, NVREG_RNDSEED_FORCE3 |
jmp .end_if4 |
@@: |
; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) |
cmp eax, NVREG_LINKSPEED_100 |
jne @f |
; phyreg |= NVREG_RNDSEED_FORCE2 |
or ecx, NVREG_RNDSEED_FORCE2 |
jmp .end_if4 |
; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) |
cmp eax, NVREG_LINKSPEED_100 |
jne @f |
; phyreg |= NVREG_RNDSEED_FORCE2 |
or ecx, NVREG_RNDSEED_FORCE2 |
jmp .end_if4 |
@@: |
; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) |
cmp eax, NVREG_LINKSPEED_1000 |
jne .end_if4 |
; phyreg |= NVREG_RNDSEED_FORCE |
or ecx, NVREG_RNDSEED_FORCE |
; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) |
cmp eax, NVREG_LINKSPEED_1000 |
jne .end_if4 |
; phyreg |= NVREG_RNDSEED_FORCE |
or ecx, NVREG_RNDSEED_FORCE |
.end_if4: |
; writel(phyreg, base + NvRegRandomSeed) |
mov dword [edi+NvRegRandomSeed], ecx |
; writel(phyreg, base + NvRegRandomSeed) |
mov dword [edi+NvRegRandomSeed], ecx |
.end_if3: |
; phyreg = readl(base + NvRegPhyInterface) |
mov ecx, dword [edi+NvRegPhyInterface] |
; phyreg = readl(base + NvRegPhyInterface) |
mov ecx, dword [edi+NvRegPhyInterface] |
; phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000) |
and ecx, not (PHY_HALF or PHY_100 or PHY_1000) |
; if (np->duplex == 0) |
cmp dword [forcedeth_duplex], 0 |
jne @f |
; phyreg |= PHY_HALF |
or ecx, PHY_HALF |
; phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000) |
and ecx, not (PHY_HALF or PHY_100 or PHY_1000) |
; if (np->duplex == 0) |
cmp dword [forcedeth_duplex], 0 |
jne @f |
; phyreg |= PHY_HALF |
or ecx, PHY_HALF |
@@: |
; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) |
mov eax, dword [forcedeth_linkspeed] |
and eax, 0xFFF |
cmp eax, NVREG_LINKSPEED_100 |
jne @f |
; phyreg |= PHY_100 |
or ecx, PHY_100 |
jmp .end_if5 |
; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) |
mov eax, dword [forcedeth_linkspeed] |
and eax, 0xFFF |
cmp eax, NVREG_LINKSPEED_100 |
jne @f |
; phyreg |= PHY_100 |
or ecx, PHY_100 |
jmp .end_if5 |
@@: |
; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) |
cmp eax, NVREG_LINKSPEED_1000 |
jne .end_if5 |
; phyreg |= PHY_1000 |
or ecx, PHY_1000 |
; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) |
cmp eax, NVREG_LINKSPEED_1000 |
jne .end_if5 |
; phyreg |= PHY_1000 |
or ecx, PHY_1000 |
.end_if5: |
; writel(phyreg, base + NvRegPhyInterface) |
mov dword [edi+NvRegPhyInterface], ecx |
; writel(phyreg, base + NvRegPhyInterface) |
mov dword [edi+NvRegPhyInterface], ecx |
; writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1); |
cmp dword [forcedeth_duplex], 0 |
je @f |
mov ecx, 0 |
jmp .next |
; writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1); |
cmp dword [forcedeth_duplex], 0 |
je @f |
mov ecx, 0 |
jmp .next |
@@: |
mov ecx, NVREG_MISC1_HD |
mov ecx, NVREG_MISC1_HD |
.next: |
or ecx, NVREG_MISC1_FORCE |
mov dword [edi+NvRegMisc1], ecx |
or ecx, NVREG_MISC1_FORCE |
mov dword [edi+NvRegMisc1], ecx |
; pci_push(base) |
call forcedeth_pci_push |
; pci_push(base) |
call forcedeth_pci_push |
; writel(np->linkspeed, base + NvRegLinkSpeed) |
mov eax, dword [forcedeth_linkspeed] |
mov dword [edi+NvRegLinkSpeed], eax |
; writel(np->linkspeed, base + NvRegLinkSpeed) |
mov eax, dword [forcedeth_linkspeed] |
mov dword [edi+NvRegLinkSpeed], eax |
; pci_push(base) |
call forcedeth_pci_push |
; pci_push(base) |
call forcedeth_pci_push |
.return: |
; return retval |
mov eax, dword [forcedeth_tmp_retval] |
pop edi esi ecx ebx |
ret |
; return retval |
mov eax, dword [forcedeth_tmp_retval] |
pop edi esi ecx ebx |
ret |
; Input: none |
; Output: none |
forcedeth_start_tx: |
push edi |
; dprintf(("start_tx\n")) |
DEBUGF 1," K : FORCEDETH: start_tx.\n" |
push edi |
; dprintf(("start_tx\n")) |
DEBUGF 1," K : FORCEDETH: start_tx.\n" |
; writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl) |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegTransmitterControl], NVREG_XMITCTL_START |
; writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl) |
mov edi, dword [forcedeth_mapio_addr] |
mov dword [edi+NvRegTransmitterControl], NVREG_XMITCTL_START |
; pci_push(base) |
call forcedeth_pci_push |
; pci_push(base) |
call forcedeth_pci_push |
.return: |
pop edi |
ret |
pop edi |
ret |
; Interrupt handler |
forcedeth_int_handler: |
DEBUGF 1," K : FORCEDETH: interrupt handler.\n" |
DEBUGF 1," K : FORCEDETH: interrupt handler.\n" |
ret |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/drivers/i8255x.inc |
---|
1,760 → 1,794 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; I8255X.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.3 11 August 2003 ;; |
;; ;; |
;; This driver is based on the eepro100 driver from ;; |
;; the etherboot 5.0.6 project. The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2002 Mike Hibbett, ;; |
;; mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************** |
; Interface |
; I8255x_reset |
; I8255x_probe |
; I8255x_poll |
; I8255x_transmit |
; |
; These functions are referenced in ethernet.inc |
; |
;******************************************************************** |
rxfd_status equ eth_data_start |
rxfd_command equ eth_data_start + 2 |
rxfd_link equ eth_data_start + 4 |
rxfd_rx_buf_addr equ eth_data_start + 8 |
rxfd_count equ eth_data_start + 12 |
rxfd_size equ eth_data_start + 14 |
rxfd_packet equ eth_data_start + 16 |
uglobal |
eeprom_data: times 16 dd 0 |
align 4 |
lstats: |
tx_good_frames: dd 0 |
tx_coll16_errs: dd 0 |
tx_late_colls: dd 0 |
tx_underruns: dd 0 |
tx_lost_carrier: dd 0 |
tx_deferred: dd 0 |
tx_one_colls: dd 0 |
tx_multi_colls: dd 0 |
tx_total_colls: dd 0 |
rx_good_frames: dd 0 |
rx_crc_errs: dd 0 |
rx_align_errs: dd 0 |
rx_resource_errs: dd 0 |
rx_overrun_errs: dd 0 |
rx_colls_errs: dd 0 |
rx_runt_errs: dd 0 |
done_marker: dd 0 |
align 4 |
confcmd: |
confcmd_status: dw 0 |
confcmd_command: dw 0 |
confcmd_link: dd 0 |
endg |
iglobal |
confcmd_data: db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1 |
db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2 |
db 0x80, 0x3f, 0x05 |
endg |
uglobal |
align 4 |
txfd: |
txfd_status: dw 0 |
txfd_command: dw 0 |
txfd_link: dd 0 |
txfd_tx_desc_addr: dd 0 |
txfd_count: dd 0 |
txfd_tx_buf_addr0: dd 0 |
txfd_tx_buf_size0: dd 0 |
txfd_tx_buf_addr1: dd 0 |
txfd_tx_buf_size1: dd 0 |
align 4 |
hdr: |
hdr_dst_addr: times 6 db 0 |
hdr_src_addr: times 6 db 0 |
hdr_type: dw 0 |
endg |
;*************************************************************************** |
; Function |
; wait_for_cmd_done |
; |
; Description |
; waits for the hardware to complete a command |
; port address in edx |
; |
; al destroyed |
;*************************************************************************** |
wait_for_cmd_done: |
in al, dx |
cmp al, 0 |
jne wait_for_cmd_done |
ret |
;*************************************************************************** |
; Function |
; mdio_read |
; |
; Description |
; This probably reads a register in the "physical media interface chip" |
; Phy_id in ebx |
; location in ecx |
; |
; Data returned in eax |
; |
;*************************************************************************** |
mdio_read: |
mov edx, [io_addr] |
add edx, 16 ; SCBCtrlMDI |
mov eax, 0x08000000 |
shl ecx, 16 |
or eax, ecx |
shl ebx, 21 |
or eax, ebx |
out dx, eax |
mrlp: |
call delay_us |
in eax, dx |
mov ecx, eax |
and ecx, 0x10000000 |
jz mrlp |
and eax, 0xffff |
ret |
;*************************************************************************** |
; Function |
; mdio_write |
; |
; Description |
; This probably writes a register in the "physical media interface chip" |
; Phy_id in ebx |
; location in ecx |
; data in edx |
; Data returned in eax |
; |
;*************************************************************************** |
mdio_write: |
mov eax, 0x04000000 |
shl ecx, 16 |
or eax, ecx |
shl ebx, 21 |
or eax, ebx |
or eax, edx |
mov edx, [io_addr] |
add edx, 16 ; SCBCtrlMDI |
out dx, eax |
mwlp: |
call delay_us |
in eax, dx |
mov ecx, eax |
and ecx, 0x10000000 |
jz mwlp |
and eax, 0xffff |
ret |
;/***********************************************************************/ |
;/* I82557 related defines */ |
;/***********************************************************************/ |
; Serial EEPROM section. |
; A "bit" grungy, but we work our way through bit-by-bit :->. |
; EEPROM_Ctrl bits. |
EE_SHIFT_CLK equ 0x01 ; EEPROM shift clock. |
EE_CS equ 0x02 ; EEPROM chip select. |
EE_DATA_WRITE equ 0x04 ; EEPROM chip data in. |
EE_DATA_READ equ 0x08 ; EEPROM chip data out. |
EE_WRITE_0 equ 0x4802 |
EE_WRITE_1 equ 0x4806 |
EE_ENB equ 0x4802 |
; The EEPROM commands include the alway-set leading bit. |
EE_READ_CMD equ 6 |
; The SCB accepts the following controls for the Tx and Rx units: |
CU_START equ 0x0010 |
CU_RESUME equ 0x0020 |
CU_STATSADDR equ 0x0040 |
CU_SHOWSTATS equ 0x0050 ; Dump statistics counters. |
CU_CMD_BASE equ 0x0060 ; Base address to add to add CU commands. |
CU_DUMPSTATS equ 0x0070 ; Dump then reset stats counters. |
RX_START equ 0x0001 |
RX_RESUME equ 0x0002 |
RX_ABORT equ 0x0004 |
RX_ADDR_LOAD equ 0x0006 |
RX_RESUMENR equ 0x0007 |
INT_MASK equ 0x0100 |
DRVR_INT equ 0x0200 ; Driver generated interrupt. |
;*************************************************************************** |
; Function |
; do_eeprom_cmd |
; |
; Description |
; writes a cmd to the ethernet cards eeprom, by bit bashing |
; cmd in ebx |
; cmd length in ecx |
; return in eax |
;*************************************************************************** |
do_eeprom_cmd: |
mov edx, [io_addr] ; We only require the value in dx |
add dx, 14 ; the value SCBeeprom |
mov ax, EE_ENB |
out dx, ax |
call delay_us |
mov ax, 0x4803 ; EE_ENB | EE_SHIFT_CLK |
out dx, ax |
call delay_us |
; dx holds ee_addr |
; ecx holds count |
; eax holds cmd |
xor edi, edi ; this will be the receive data |
dec_001: |
mov esi, 1 |
dec ecx |
shl esi, cl |
inc ecx |
and esi, ebx |
mov eax, EE_WRITE_0 ; I am assuming this doesnt affect the flags.. |
cmp esi,0 |
jz dec_002 |
mov eax, EE_WRITE_1 |
dec_002: |
out dx, ax |
call delay_us |
or ax, EE_SHIFT_CLK |
out dx, ax |
call delay_us |
shl edi,1 |
in ax, dx |
and ax, EE_DATA_READ |
cmp ax,0 |
jz dec_003 |
inc edi |
dec_003: |
loop dec_001 |
mov ax, EE_ENB |
out dx, ax |
call delay_us |
mov ax, 0x4800 |
out dx, ax |
call delay_us |
mov eax, edi |
ret |
;*************************************************************************** |
; Function |
; I8255x_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; |
;*************************************************************************** |
I8255x_probe: |
DEBUGF 1," K : Probing i8255x device \n" |
mov eax, [io_addr] |
mov ebx, [pci_bus] |
mov ecx, [pci_dev] |
mov edx, 0x04 ; PCI_COMMAND |
call pcibios_read_config_word |
or ax, 0x05 |
mov ebx, [pci_bus] |
mov ecx, [pci_dev] |
mov edx, 0x04 ; PCI_COMMAND |
call pcibios_write_config_word |
mov ebx, 0x6000000 |
mov ecx, 27 |
call do_eeprom_cmd |
and eax, 0xffe0000 |
cmp eax, 0xffe0000 |
je bige |
mov ebx, 0x1800000 |
mov ecx, 0x40 |
jmp doread |
bige: |
mov ebx, 0x6000000 |
mov ecx, 0x100 |
doread: |
; do-eeprom-cmd will destroy all registers |
; we have eesize in ecx |
; read_cmd in ebx |
; Ignore full eeprom - just load the mac address |
mov ecx, 0 |
drlp: |
push ecx ; save count |
push ebx |
mov eax, ecx |
shl eax, 16 |
or ebx, eax |
mov ecx, 27 |
call do_eeprom_cmd |
pop ebx |
pop ecx |
mov edx, ecx |
shl edx, 2 |
mov esi, eeprom_data |
add esi, edx |
mov [esi], eax |
inc ecx |
cmp ecx, 16 |
jne drlp |
; OK, we have the MAC address. |
; Now reset the card |
mov edx, [io_addr] |
add dx, 8 ; SCBPort |
xor eax, eax ; The reset cmd == 0 |
out dx, eax |
mov esi, 10 |
call delay_ms ; Give the card time to warm up. |
mov eax, lstats |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
out dx, eax |
mov eax, 0x0140 ; INT_MASK | CU_STATSADDR |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
out dx, ax |
call wait_for_cmd_done |
mov eax, 0 |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
out dx, eax |
mov eax, 0x0106 ; INT_MASK | RX_ADDR_LOAD |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
out dx, ax |
call wait_for_cmd_done |
; build rxrd structure |
mov ax, 0x0001 |
mov [rxfd_status], ax |
mov ax, 0x0000 |
mov [rxfd_command], ax |
mov eax, rxfd_status |
sub eax, OS_BASE |
mov [rxfd_link], eax |
mov eax, Ether_buffer |
sub eax, OS_BASE |
mov [rxfd_rx_buf_addr], eax |
mov ax, 0 |
mov [rxfd_count], ax |
mov ax, 1528 |
mov [rxfd_size], ax |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
mov eax, rxfd_status |
sub eax, OS_BASE |
out dx, eax |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
mov ax, 0x0101 ; INT_MASK | RX_START |
out dx, ax |
call wait_for_cmd_done |
; start the reciver |
mov ax, 0 |
mov [rxfd_status], ax |
mov ax, 0xc000 |
mov [rxfd_command], ax |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
mov eax, rxfd_status |
sub eax, OS_BASE |
out dx, eax |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
mov ax, 0x0101 ; INT_MASK | RX_START |
out dx, ax |
; Init TX Stuff |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
mov eax, 0 |
out dx, eax |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
mov ax, 0x0160 ; INT_MASK | CU_CMD_BASE |
out dx, ax |
call wait_for_cmd_done |
; Set TX Base address |
; First, set up confcmd values |
mov ax, 2 |
mov [confcmd_command], ax |
mov eax, txfd |
sub eax, OS_BASE |
mov [confcmd_link], eax |
mov ax, 1 |
mov [txfd_command], ax ; CmdIASetup |
mov ax, 0 |
mov [txfd_status], ax |
mov eax, confcmd |
sub eax, OS_BASE |
mov [txfd_link], eax |
; ETH_ALEN is 6 bytes |
mov esi, eeprom_data |
mov edi, node_addr |
mov ecx, 3 |
drp000: |
mov eax, [esi] |
mov [edi], al |
shr eax, 8 |
inc edi |
mov [edi], al |
inc edi |
add esi, 4 |
loop drp000 |
; Hard code your MAC address into node_addr at this point, |
; If you cannot read the MAC address from the eeprom in the previous step. |
; You also have to write the mac address into txfd_tx_desc_addr, rather |
; than taking data from eeprom_data |
mov esi, eeprom_data |
mov edi, txfd_tx_desc_addr |
mov ecx, 3 |
drp001: |
mov eax, [esi] |
mov [edi], al |
shr eax, 8 |
inc edi |
mov [edi], al |
inc edi |
add esi, 4 |
loop drp001 |
mov esi, eeprom_data + (6 * 4) |
mov eax, [esi] |
shr eax, 8 |
and eax, 0x3f |
cmp eax, 4 ; DP83840 |
je drp002 |
cmp eax, 10 ; DP83840A |
je drp002 |
jmp drp003 |
drp002: |
mov ebx, [esi] |
and ebx, 0x1f |
push ebx |
mov ecx, 23 |
call mdio_read |
pop ebx |
or eax, 0x0422 |
mov ecx, 23 |
mov edx, eax |
call mdio_write |
drp003: |
mov ax, 0x4002 ; Cmdsuspend | CmdConfigure |
mov [confcmd_command], ax |
mov ax, 0 |
mov [confcmd_status], ax |
mov eax, txfd |
mov [confcmd_link], eax |
mov ebx, confcmd_data |
mov al, 0x88 ; fifo of 8 each |
mov [ebx + 1], al |
mov al, 0 |
mov [ebx + 4], al |
mov al, 0x80 |
mov [ebx + 5], al |
mov al, 0x48 |
mov [ebx + 15], al |
mov al, 0x80 |
mov [ebx + 19], al |
mov al, 0x05 |
mov [ebx + 21], al |
mov eax, txfd |
sub eax, OS_BASE |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
out dx, eax |
mov eax, 0x0110 ; INT_MASK | CU_START |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
out dx, ax |
call wait_for_cmd_done |
jmp skip |
; wait for thing to start |
drp004: |
mov ax, [txfd_status] |
cmp ax, 0 |
je drp004 |
skip: |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
I8255x_exit: |
ret |
;*************************************************************************** |
; Function |
; I8255x_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; No inputs |
; All registers destroyed |
; |
;*************************************************************************** |
I8255x_reset: |
ret |
;*************************************************************************** |
; Function |
; I8255x_poll |
; |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; |
;*************************************************************************** |
I8255x_poll: |
mov ax, 0 ; assume no data |
mov [eth_rx_data_len], ax |
mov ax, [rxfd_status] |
cmp ax, 0 |
je i8p_exit |
mov ax, 0 |
mov [rxfd_status], ax |
mov ax, 0xc000 |
mov [rxfd_command], ax |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
mov eax, rxfd_status |
sub eax, OS_BASE |
out dx, eax |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
mov ax, 0x0101 ; INT_MASK | RX_START |
out dx, ax |
call wait_for_cmd_done |
mov esi, rxfd_packet |
mov edi, Ether_buffer |
mov ecx, 1518 |
cld |
rep movsb |
mov ax, [rxfd_count] |
and ax, 0x3fff |
mov [eth_rx_data_len], ax |
i8p_exit: |
ret |
;*************************************************************************** |
; Function |
; I8255x_transmit |
; |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
; |
;*************************************************************************** |
I8255x_transmit: |
mov [hdr_type], bx |
mov eax, [edi] |
mov [hdr_dst_addr], eax |
mov ax, [edi+4] |
mov [hdr_dst_addr+4], ax |
mov eax, [node_addr] |
mov [hdr_src_addr], eax |
mov ax, [node_addr+4] |
mov [hdr_src_addr+4], ax |
mov edx, [io_addr] |
in ax, dx |
and ax, 0xfc00 |
out dx, ax |
xor ax, ax |
mov [txfd_status], ax |
mov ax, 0x400C ; Cmdsuspend | CmdTx | CmdTxFlex |
mov [txfd_command], ax |
mov eax, txfd |
mov [txfd_link], eax |
mov eax, 0x02208000 |
mov [txfd_count], eax |
mov eax, txfd_tx_buf_addr0 |
sub eax, OS_BASE |
mov [txfd_tx_desc_addr], eax |
mov eax, hdr |
sub eax, OS_BASE |
mov [txfd_tx_buf_addr0], eax |
mov eax, 14 ; sizeof hdr |
mov [txfd_tx_buf_size0], eax |
; Copy the buffer address and size in |
mov eax, esi |
sub eax, OS_BASE |
mov [txfd_tx_buf_addr1], eax |
mov eax, ecx |
mov [txfd_tx_buf_size1], eax |
mov eax, txfd |
sub eax, OS_BASE |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
out dx, eax |
mov ax, 0x0110 ; INT_MASK | CU_START |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
out dx, ax |
call wait_for_cmd_done |
mov edx, [io_addr] |
in ax, dx |
I8t_001: |
mov ax, [txfd_status] |
cmp ax, 0 |
je I8t_001 |
mov edx, [io_addr] |
in ax, dx |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; I8255X.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.3 11 August 2003 ;; |
;; ;; |
;; This driver is based on the eepro100 driver from ;; |
;; the etherboot 5.0.6 project. The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2002 Mike Hibbett, ;; |
;; mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************** |
; Interface |
; I8255x_reset |
; I8255x_probe |
; I8255x_poll |
; I8255x_transmit |
; |
; These functions are referenced in ethernet.inc |
; |
;******************************************************************** |
rxfd_status equ eth_data_start |
rxfd_command equ eth_data_start + 2 |
rxfd_link equ eth_data_start + 4 |
rxfd_rx_buf_addr equ eth_data_start + 8 |
rxfd_count equ eth_data_start + 12 |
rxfd_size equ eth_data_start + 14 |
rxfd_packet equ eth_data_start + 16 |
uglobal |
eeprom_data: |
times 16 dd 0 |
align 4 |
lstats: |
tx_good_frames: |
dd 0 |
tx_coll16_errs: |
dd 0 |
tx_late_colls: |
dd 0 |
tx_underruns: |
dd 0 |
tx_lost_carrier: |
dd 0 |
tx_deferred: |
dd 0 |
tx_one_colls: |
dd 0 |
tx_multi_colls: |
dd 0 |
tx_total_colls: |
dd 0 |
rx_good_frames: |
dd 0 |
rx_crc_errs: |
dd 0 |
rx_align_errs: |
dd 0 |
rx_resource_errs: |
dd 0 |
rx_overrun_errs: |
dd 0 |
rx_colls_errs: |
dd 0 |
rx_runt_errs: |
dd 0 |
done_marker: |
dd 0 |
align 4 |
confcmd: |
confcmd_status: |
dw 0 |
confcmd_command: |
dw 0 |
confcmd_link: |
dd 0 |
endg |
iglobal |
confcmd_data: |
db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1 |
db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2 |
db 0x80, 0x3f, 0x05 |
endg |
uglobal |
align 4 |
txfd: |
txfd_status: |
dw 0 |
txfd_command: |
dw 0 |
txfd_link: |
dd 0 |
txfd_tx_desc_addr: |
dd 0 |
txfd_count: |
dd 0 |
txfd_tx_buf_addr0: |
dd 0 |
txfd_tx_buf_size0: |
dd 0 |
txfd_tx_buf_addr1: |
dd 0 |
txfd_tx_buf_size1: |
dd 0 |
align 4 |
hdr: |
hdr_dst_addr: |
times 6 db 0 |
hdr_src_addr: |
times 6 db 0 |
hdr_type: |
dw 0 |
endg |
;*************************************************************************** |
; Function |
; wait_for_cmd_done |
; |
; Description |
; waits for the hardware to complete a command |
; port address in edx |
; |
; al destroyed |
;*************************************************************************** |
wait_for_cmd_done: |
in al, dx |
cmp al, 0 |
jne wait_for_cmd_done |
ret |
;*************************************************************************** |
; Function |
; mdio_read |
; |
; Description |
; This probably reads a register in the "physical media interface chip" |
; Phy_id in ebx |
; location in ecx |
; |
; Data returned in eax |
; |
;*************************************************************************** |
mdio_read: |
mov edx, [io_addr] |
add edx, 16 ; SCBCtrlMDI |
mov eax, 0x08000000 |
shl ecx, 16 |
or eax, ecx |
shl ebx, 21 |
or eax, ebx |
out dx, eax |
mrlp: |
call delay_us |
in eax, dx |
mov ecx, eax |
and ecx, 0x10000000 |
jz mrlp |
and eax, 0xffff |
ret |
;*************************************************************************** |
; Function |
; mdio_write |
; |
; Description |
; This probably writes a register in the "physical media interface chip" |
; Phy_id in ebx |
; location in ecx |
; data in edx |
; Data returned in eax |
; |
;*************************************************************************** |
mdio_write: |
mov eax, 0x04000000 |
shl ecx, 16 |
or eax, ecx |
shl ebx, 21 |
or eax, ebx |
or eax, edx |
mov edx, [io_addr] |
add edx, 16 ; SCBCtrlMDI |
out dx, eax |
mwlp: |
call delay_us |
in eax, dx |
mov ecx, eax |
and ecx, 0x10000000 |
jz mwlp |
and eax, 0xffff |
ret |
;/***********************************************************************/ |
;/* I82557 related defines */ |
;/***********************************************************************/ |
; Serial EEPROM section. |
; A "bit" grungy, but we work our way through bit-by-bit :->. |
; EEPROM_Ctrl bits. |
EE_SHIFT_CLK equ 0x01 ; EEPROM shift clock. |
EE_CS equ 0x02 ; EEPROM chip select. |
EE_DATA_WRITE equ 0x04 ; EEPROM chip data in. |
EE_DATA_READ equ 0x08 ; EEPROM chip data out. |
EE_WRITE_0 equ 0x4802 |
EE_WRITE_1 equ 0x4806 |
EE_ENB equ 0x4802 |
; The EEPROM commands include the alway-set leading bit. |
EE_READ_CMD equ 6 |
; The SCB accepts the following controls for the Tx and Rx units: |
CU_START equ 0x0010 |
CU_RESUME equ 0x0020 |
CU_STATSADDR equ 0x0040 |
CU_SHOWSTATS equ 0x0050 ; Dump statistics counters. |
CU_CMD_BASE equ 0x0060 ; Base address to add to add CU commands. |
CU_DUMPSTATS equ 0x0070 ; Dump then reset stats counters. |
RX_START equ 0x0001 |
RX_RESUME equ 0x0002 |
RX_ABORT equ 0x0004 |
RX_ADDR_LOAD equ 0x0006 |
RX_RESUMENR equ 0x0007 |
INT_MASK equ 0x0100 |
DRVR_INT equ 0x0200 ; Driver generated interrupt. |
;*************************************************************************** |
; Function |
; do_eeprom_cmd |
; |
; Description |
; writes a cmd to the ethernet cards eeprom, by bit bashing |
; cmd in ebx |
; cmd length in ecx |
; return in eax |
;*************************************************************************** |
do_eeprom_cmd: |
mov edx, [io_addr]; We only require the value in dx |
add dx, 14 ; the value SCBeeprom |
mov ax, EE_ENB |
out dx, ax |
call delay_us |
mov ax, 0x4803 ; EE_ENB | EE_SHIFT_CLK |
out dx, ax |
call delay_us |
; dx holds ee_addr |
; ecx holds count |
; eax holds cmd |
xor edi, edi ; this will be the receive data |
dec_001: |
mov esi, 1 |
dec ecx |
shl esi, cl |
inc ecx |
and esi, ebx |
mov eax, EE_WRITE_0; I am assuming this doesnt affect the flags.. |
cmp esi, 0 |
jz dec_002 |
mov eax, EE_WRITE_1 |
dec_002: |
out dx, ax |
call delay_us |
or ax, EE_SHIFT_CLK |
out dx, ax |
call delay_us |
shl edi, 1 |
in ax, dx |
and ax, EE_DATA_READ |
cmp ax, 0 |
jz dec_003 |
inc edi |
dec_003: |
loop dec_001 |
mov ax, EE_ENB |
out dx, ax |
call delay_us |
mov ax, 0x4800 |
out dx, ax |
call delay_us |
mov eax, edi |
ret |
;*************************************************************************** |
; Function |
; I8255x_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; |
;*************************************************************************** |
I8255x_probe: |
DEBUGF 1," K : Probing i8255x device \n" |
mov eax, [io_addr] |
mov ebx, [pci_bus] |
mov ecx, [pci_dev] |
mov edx, 0x04 ; PCI_COMMAND |
call pcibios_read_config_word |
or ax, 0x05 |
mov ebx, [pci_bus] |
mov ecx, [pci_dev] |
mov edx, 0x04 ; PCI_COMMAND |
call pcibios_write_config_word |
mov ebx, 0x6000000 |
mov ecx, 27 |
call do_eeprom_cmd |
and eax, 0xffe0000 |
cmp eax, 0xffe0000 |
je bige |
mov ebx, 0x1800000 |
mov ecx, 0x40 |
jmp doread |
bige: |
mov ebx, 0x6000000 |
mov ecx, 0x100 |
doread: |
; do-eeprom-cmd will destroy all registers |
; we have eesize in ecx |
; read_cmd in ebx |
; Ignore full eeprom - just load the mac address |
mov ecx, 0 |
drlp: |
push ecx ; save count |
push ebx |
mov eax, ecx |
shl eax, 16 |
or ebx, eax |
mov ecx, 27 |
call do_eeprom_cmd |
pop ebx |
pop ecx |
mov edx, ecx |
shl edx, 2 |
mov esi, eeprom_data |
add esi, edx |
mov [esi], eax |
inc ecx |
cmp ecx, 16 |
jne drlp |
; OK, we have the MAC address. |
; Now reset the card |
mov edx, [io_addr] |
add dx, 8 ; SCBPort |
xor eax, eax ; The reset cmd == 0 |
out dx, eax |
mov esi, 10 |
call delay_ms ; Give the card time to warm up. |
mov eax, lstats |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
out dx, eax |
mov eax, 0x0140 ; INT_MASK | CU_STATSADDR |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
out dx, ax |
call wait_for_cmd_done |
mov eax, 0 |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
out dx, eax |
mov eax, 0x0106 ; INT_MASK | RX_ADDR_LOAD |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
out dx, ax |
call wait_for_cmd_done |
; build rxrd structure |
mov ax, 0x0001 |
mov [rxfd_status], ax |
mov ax, 0x0000 |
mov [rxfd_command], ax |
mov eax, rxfd_status |
sub eax, OS_BASE |
mov [rxfd_link], eax |
mov eax, Ether_buffer |
sub eax, OS_BASE |
mov [rxfd_rx_buf_addr], eax |
mov ax, 0 |
mov [rxfd_count], ax |
mov ax, 1528 |
mov [rxfd_size], ax |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
mov eax, rxfd_status |
sub eax, OS_BASE |
out dx, eax |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
mov ax, 0x0101 ; INT_MASK | RX_START |
out dx, ax |
call wait_for_cmd_done |
; start the reciver |
mov ax, 0 |
mov [rxfd_status], ax |
mov ax, 0xc000 |
mov [rxfd_command], ax |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
mov eax, rxfd_status |
sub eax, OS_BASE |
out dx, eax |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
mov ax, 0x0101 ; INT_MASK | RX_START |
out dx, ax |
; Init TX Stuff |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
mov eax, 0 |
out dx, eax |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
mov ax, 0x0160 ; INT_MASK | CU_CMD_BASE |
out dx, ax |
call wait_for_cmd_done |
; Set TX Base address |
; First, set up confcmd values |
mov ax, 2 |
mov [confcmd_command], ax |
mov eax, txfd |
sub eax, OS_BASE |
mov [confcmd_link], eax |
mov ax, 1 |
mov [txfd_command], ax ; CmdIASetup |
mov ax, 0 |
mov [txfd_status], ax |
mov eax, confcmd |
sub eax, OS_BASE |
mov [txfd_link], eax |
; ETH_ALEN is 6 bytes |
mov esi, eeprom_data |
mov edi, node_addr |
mov ecx, 3 |
drp000: |
mov eax, [esi] |
mov [edi], al |
shr eax, 8 |
inc edi |
mov [edi], al |
inc edi |
add esi, 4 |
loop drp000 |
; Hard code your MAC address into node_addr at this point, |
; If you cannot read the MAC address from the eeprom in the previous step. |
; You also have to write the mac address into txfd_tx_desc_addr, rather |
; than taking data from eeprom_data |
mov esi, eeprom_data |
mov edi, txfd_tx_desc_addr |
mov ecx, 3 |
drp001: |
mov eax, [esi] |
mov [edi], al |
shr eax, 8 |
inc edi |
mov [edi], al |
inc edi |
add esi, 4 |
loop drp001 |
mov esi, eeprom_data + (6 * 4) |
mov eax, [esi] |
shr eax, 8 |
and eax, 0x3f |
cmp eax, 4 ; DP83840 |
je drp002 |
cmp eax, 10 ; DP83840A |
je drp002 |
jmp drp003 |
drp002: |
mov ebx, [esi] |
and ebx, 0x1f |
push ebx |
mov ecx, 23 |
call mdio_read |
pop ebx |
or eax, 0x0422 |
mov ecx, 23 |
mov edx, eax |
call mdio_write |
drp003: |
mov ax, 0x4002 ; Cmdsuspend | CmdConfigure |
mov [confcmd_command], ax |
mov ax, 0 |
mov [confcmd_status], ax |
mov eax, txfd |
mov [confcmd_link], eax |
mov ebx, confcmd_data |
mov al, 0x88 ; fifo of 8 each |
mov [ebx + 1], al |
mov al, 0 |
mov [ebx + 4], al |
mov al, 0x80 |
mov [ebx + 5], al |
mov al, 0x48 |
mov [ebx + 15], al |
mov al, 0x80 |
mov [ebx + 19], al |
mov al, 0x05 |
mov [ebx + 21], al |
mov eax, txfd |
sub eax, OS_BASE |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
out dx, eax |
mov eax, 0x0110 ; INT_MASK | CU_START |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
out dx, ax |
call wait_for_cmd_done |
jmp skip |
; wait for thing to start |
drp004: |
mov ax, [txfd_status] |
cmp ax, 0 |
je drp004 |
skip: |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
I8255x_exit: |
ret |
;*************************************************************************** |
; Function |
; I8255x_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; No inputs |
; All registers destroyed |
; |
;*************************************************************************** |
I8255x_reset: |
ret |
;*************************************************************************** |
; Function |
; I8255x_poll |
; |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; |
;*************************************************************************** |
I8255x_poll: |
mov ax, 0 ; assume no data |
mov [eth_rx_data_len], ax |
mov ax, [rxfd_status] |
cmp ax, 0 |
je i8p_exit |
mov ax, 0 |
mov [rxfd_status], ax |
mov ax, 0xc000 |
mov [rxfd_command], ax |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
mov eax, rxfd_status |
sub eax, OS_BASE |
out dx, eax |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
mov ax, 0x0101 ; INT_MASK | RX_START |
out dx, ax |
call wait_for_cmd_done |
mov esi, rxfd_packet |
mov edi, Ether_buffer |
mov ecx, 1518 |
cld |
rep movsb |
mov ax, [rxfd_count] |
and ax, 0x3fff |
mov [eth_rx_data_len], ax |
i8p_exit: |
ret |
;*************************************************************************** |
; Function |
; I8255x_transmit |
; |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
; |
;*************************************************************************** |
I8255x_transmit: |
mov [hdr_type], bx |
mov eax, [edi] |
mov [hdr_dst_addr], eax |
mov ax, [edi+4] |
mov [hdr_dst_addr+4], ax |
mov eax, [node_addr] |
mov [hdr_src_addr], eax |
mov ax, [node_addr+4] |
mov [hdr_src_addr+4], ax |
mov edx, [io_addr] |
in ax, dx |
and ax, 0xfc00 |
out dx, ax |
xor ax, ax |
mov [txfd_status], ax |
mov ax, 0x400C ; Cmdsuspend | CmdTx | CmdTxFlex |
mov [txfd_command], ax |
mov eax, txfd |
mov [txfd_link], eax |
mov eax, 0x02208000 |
mov [txfd_count], eax |
mov eax, txfd_tx_buf_addr0 |
sub eax, OS_BASE |
mov [txfd_tx_desc_addr], eax |
mov eax, hdr |
sub eax, OS_BASE |
mov [txfd_tx_buf_addr0], eax |
mov eax, 14; sizeof hdr |
mov [txfd_tx_buf_size0], eax |
; Copy the buffer address and size in |
mov eax, esi |
sub eax, OS_BASE |
mov [txfd_tx_buf_addr1], eax |
mov eax, ecx |
mov [txfd_tx_buf_size1], eax |
mov eax, txfd |
sub eax, OS_BASE |
mov edx, [io_addr] |
add edx, 4 ; SCBPointer |
out dx, eax |
mov ax, 0x0110 ; INT_MASK | CU_START |
mov edx, [io_addr] |
add edx, 2 ; SCBCmd |
out dx, ax |
call wait_for_cmd_done |
mov edx, [io_addr] |
in ax, dx |
I8t_001: |
mov ax, [txfd_status] |
cmp ax, 0 |
je I8t_001 |
mov edx, [io_addr] |
in ax, dx |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/drivers/pcnet32.inc |
---|
1,848 → 1,848 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; PCNET32.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; - Version 1.0 31 July 2004: ;; |
;; Initial release ;; |
;; ;; |
;; - Version 1.01 29 March 2008: ;; |
;; Adapted to work with kolibrios flat kernel ;; |
;; Debug info is updated, and now uses DEBUGF macro ;; |
;; by hidnplayr@kolibrios.org ;; |
;; ;; |
;; This driver is based on the PCNet32 driver from ;; |
;; the etherboot 5.0.6 project. The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2004 Jarek Pelczar, ;; |
;; jpelczar@interia.pl ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
PCNET32_PORT_AUI equ 0x00 |
PCNET32_PORT_10BT equ 0x01 |
PCNET32_PORT_GPSI equ 0x02 |
PCNET32_PORT_MII equ 0x03 |
PCNET32_PORT_PORTSEL equ 0x03 |
PCNET32_PORT_ASEL equ 0x04 |
PCNET32_PORT_100 equ 0x40 |
PCNET32_PORT_FD equ 0x80 |
PCNET32_DMA_MASK equ 0xffffffff |
PCNET32_LOG_TX_BUFFERS equ 1 |
PCNET32_LOG_RX_BUFFERS equ 2 |
PCNET32_TX_RING_SIZE equ (1 shl PCNET32_LOG_TX_BUFFERS) |
PCNET32_TX_RING_MOD_MASK equ (PCNET32_TX_RING_SIZE-1) |
PCNET32_TX_RING_LEN_BITS equ 0 |
PCNET32_RX_RING_SIZE equ (1 shl PCNET32_LOG_RX_BUFFERS) |
PCNET32_RX_RING_MOD_MASK equ (PCNET32_RX_RING_SIZE-1) |
PCNET32_RX_RING_LEN_BITS equ (PCNET32_LOG_RX_BUFFERS shl 4) |
PCNET32_PKT_BUF_SZ equ 1544 |
PCNET32_PKT_BUF_SZ_NEG equ 0xf9f8 |
pcnet32_txb equ (eth_data_start) |
pcnet32_rxb equ ((pcnet32_txb+(PCNET32_PKT_BUF_SZ*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) |
pcnet32_tx_ring equ ((pcnet32_rxb+(PCNET32_PKT_BUF_SZ*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) |
pcnet32_rx_ring equ ((pcnet32_tx_ring+(16*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) |
virtual at ((pcnet32_rx_ring+(16*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) |
pcnet32_private: |
.mode dw ? |
.tlen_rlen dw ? |
.phys_addr db ?,?,?,?,?,? |
.reserved dw ? |
.filter dd ?,? |
.rx_ring dd ? |
.tx_ring dd ? |
.cur_rx dd ? |
.cur_tx dd ? |
.dirty_rx dd ? |
.dirty_tx dd ? |
.tx_full db ? |
.options dd ? |
.full_duplex db ? |
.chip_version dd ? |
.mii db ? |
.ltint db ? |
.dxsuflo db ? |
.fset db ? |
.fdx db ? |
end virtual |
virtual at 0 |
pcnet32_rx_head: |
.base dd ? |
.buf_length dw ? |
.status dw ? |
.msg_length dd ? |
.reserved dd ? |
end virtual |
virtual at 0 |
pcnet32_tx_head: |
.base dd ? |
.length dw ? |
.status dw ? |
.misc dd ? |
.reserved dd ? |
end virtual |
uglobal |
pcnet32_access: |
.read_csr dd ? |
.write_csr dd ? |
.read_bcr dd ? |
.write_bcr dd ? |
.read_rap dd ? |
.write_rap dd ? |
.reset dd ? |
endg |
iglobal |
pcnet32_options_mapping: |
dd PCNET32_PORT_ASEL ; 0 Auto-select |
dd PCNET32_PORT_AUI ; 1 BNC/AUI |
dd PCNET32_PORT_AUI ; 2 AUI/BNC |
dd PCNET32_PORT_ASEL ; 3 not supported |
dd PCNET32_PORT_10BT or PCNET32_PORT_FD ; 4 10baseT-FD |
dd PCNET32_PORT_ASEL ; 5 not supported |
dd PCNET32_PORT_ASEL ; 6 not supported |
dd PCNET32_PORT_ASEL ; 7 not supported |
dd PCNET32_PORT_ASEL ; 8 not supported |
dd PCNET32_PORT_MII ; 9 MII 10baseT |
dd PCNET32_PORT_MII or PCNET32_PORT_FD ; 10 MII 10baseT-FD |
dd PCNET32_PORT_MII ; 11 MII (autosel) |
dd PCNET32_PORT_10BT ; 12 10BaseT |
dd PCNET32_PORT_MII or PCNET32_PORT_100 ; 13 MII 100BaseTx |
dd PCNET32_PORT_MII or PCNET32_PORT_100 or PCNET32_PORT_FD ; 14 MII 100BaseTx-FD |
dd PCNET32_PORT_ASEL ; 15 not supported |
endg |
PCNET32_WIO_RDP equ 0x10 |
PCNET32_WIO_RAP equ 0x12 |
PCNET32_WIO_RESET equ 0x14 |
PCNET32_WIO_BDP equ 0x16 |
PCNET32_DWIO_RDP equ 0x10 |
PCNET32_DWIO_RAP equ 0x14 |
PCNET32_DWIO_RESET equ 0x18 |
PCNET32_DWIO_BDP equ 0x1C |
PCNET32_TOTAL_SIZE equ 0x20 |
; ebx - index |
; return: |
; eax - data |
pcnet32_wio_read_csr: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
mov ax,bx |
out dx,ax |
lea edx,[ebp+PCNET32_WIO_RDP] |
in ax,dx |
and eax,0xffff |
pop edx |
ret |
; eax - data |
; ebx - index |
pcnet32_wio_write_csr: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
xchg eax,ebx |
out dx,ax |
xchg eax,ebx |
lea edx,[ebp+PCNET32_WIO_RDP] |
out dx,ax |
pop edx |
ret |
; ebx - index |
; return: |
; eax - data |
pcnet32_wio_read_bcr: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
mov ax,bx |
out dx,ax |
lea edx,[ebp+PCNET32_WIO_BDP] |
in ax,dx |
and eax,0xffff |
pop edx |
ret |
; eax - data |
; ebx - index |
pcnet32_wio_write_bcr: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
xchg eax,ebx |
out dx,ax |
xchg eax,ebx |
lea edx,[ebp+PCNET32_WIO_BDP] |
out dx,ax |
pop edx |
ret |
pcnet32_wio_read_rap: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
in ax,dx |
and eax,0xffff |
pop edx |
ret |
; eax - val |
pcnet32_wio_write_rap: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
out dx,ax |
pop edx |
ret |
pcnet32_wio_reset: |
push edx |
push eax |
lea edx,[ebp+PCNET32_WIO_RESET] |
in ax,dx |
pop eax |
pop edx |
ret |
pcnet32_wio_check: |
push edx |
mov ax,88 |
lea edx,[ebp+PCNET32_WIO_RAP] |
out dx,ax |
nop |
nop |
in ax,dx |
cmp ax,88 |
sete al |
pop edx |
ret |
iglobal |
pcnet32_wio: |
dd pcnet32_wio_read_csr |
dd pcnet32_wio_write_csr |
dd pcnet32_wio_read_bcr |
dd pcnet32_wio_write_bcr |
dd pcnet32_wio_read_rap |
dd pcnet32_wio_write_rap |
dd pcnet32_wio_reset |
endg |
; ebx - index |
; return: |
; eax - data |
pcnet32_dwio_read_csr: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
mov ebx,eax |
out dx,eax |
lea edx,[ebp+PCNET32_DWIO_RDP] |
in eax,dx |
and eax,0xffff |
pop edx |
ret |
; ebx - index |
; eax - data |
pcnet32_dwio_write_csr: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
xchg eax,ebx |
out dx,eax |
lea edx,[ebp+PCNET32_DWIO_RDP] |
xchg eax,ebx |
out dx,eax |
pop edx |
ret |
; ebx - index |
; return: |
; eax - data |
pcnet32_dwio_read_bcr: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
mov ebx,eax |
out dx,eax |
lea edx,[ebp+PCNET32_DWIO_BDP] |
in eax,dx |
and eax,0xffff |
pop edx |
ret |
; ebx - index |
; eax - data |
pcnet32_dwio_write_bcr: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
xchg eax,ebx |
out dx,eax |
lea edx,[ebp+PCNET32_DWIO_BDP] |
xchg eax,ebx |
out dx,eax |
pop edx |
ret |
pcnet32_dwio_read_rap: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
in eax,dx |
and eax,0xffff |
pop edx |
ret |
; eax - val |
pcnet32_dwio_write_rap: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
out dx,eax |
pop edx |
ret |
pcnet32_dwio_reset: |
push edx |
push eax |
lea edx,[ebp+PCNET32_DWIO_RESET] |
in eax,dx |
pop eax |
pop edx |
ret |
pcnet32_dwio_check: |
push edx |
lea edx,[PCNET32_DWIO_RAP] |
mov eax,88 |
out dx,eax |
nop |
nop |
in eax,dx |
and eax,0xffff |
cmp eax,88 |
sete al |
pop edx |
ret |
iglobal |
pcnet32_dwio: |
dd pcnet32_dwio_read_csr |
dd pcnet32_dwio_write_csr |
dd pcnet32_dwio_read_bcr |
dd pcnet32_dwio_write_bcr |
dd pcnet32_dwio_read_rap |
dd pcnet32_dwio_write_rap |
dd pcnet32_dwio_reset |
endg |
pcnet32_init_ring: |
mov [pcnet32_private.tx_full],0 |
mov [pcnet32_private.cur_rx],0 |
mov [pcnet32_private.cur_tx],0 |
mov [pcnet32_private.dirty_rx],0 |
mov [pcnet32_private.dirty_tx],0 |
mov edi,pcnet32_rx_ring |
mov ecx,PCNET32_RX_RING_SIZE |
mov ebx,pcnet32_rxb |
sub ebx,OS_BASE |
.rx_init: |
mov [edi+pcnet32_rx_head.base],ebx |
mov [edi+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG |
mov [edi+pcnet32_rx_head.status],word 0x8000 |
add ebx,PCNET32_PKT_BUF_SZ |
; inc ebx |
add edi,16 |
loop .rx_init |
mov edi,pcnet32_tx_ring |
mov ecx,PCNET32_TX_RING_SIZE |
.tx_init: |
mov [edi+pcnet32_tx_head.base],dword 0 |
mov [edi+pcnet32_tx_head.status],word 0 |
add edi,16 |
loop .tx_init |
mov [pcnet32_private.tlen_rlen],(PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) |
mov esi,node_addr |
mov edi,pcnet32_private.phys_addr |
cld |
movsd |
movsw |
mov eax,pcnet32_rx_ring |
sub eax,OS_BASE |
mov dword [pcnet32_private.rx_ring],eax |
mov eax,pcnet32_tx_ring |
sub eax,OS_BASE |
mov dword [pcnet32_private.tx_ring],eax |
ret |
pcnet32_reset: |
; Reset PCNET32 |
mov ebp,[io_addr] |
call dword [pcnet32_access.reset] |
; set 32bit mode |
mov ebx,20 |
mov eax,2 |
call dword [pcnet32_access.write_bcr] |
; set/reset autoselect bit |
mov ebx,2 |
call dword [pcnet32_access.read_bcr] |
and eax,not 2 |
test [pcnet32_private.options],PCNET32_PORT_ASEL |
jz .L1 |
or eax,2 |
.L1: |
call dword [pcnet32_access.write_bcr] |
; Handle full duplex setting |
cmp byte [pcnet32_private.full_duplex],0 |
je .L2 |
mov ebx,9 |
call dword [pcnet32_access.read_bcr] |
and eax,not 3 |
test [pcnet32_private.options],PCNET32_PORT_FD |
jz .L3 |
or eax,1 |
cmp [pcnet32_private.options],PCNET32_PORT_FD or PCNET32_PORT_AUI |
jne .L4 |
or eax,2 |
jmp .L4 |
.L3: |
test [pcnet32_private.options],PCNET32_PORT_ASEL |
jz .L4 |
cmp [pcnet32_private.chip_version],0x2627 |
jne .L4 |
or eax,3 |
.L4: |
mov ebx,9 |
call dword [pcnet32_access.write_bcr] |
.L2: |
; set/reset GPSI bit |
mov ebx,124 |
call dword [pcnet32_access.read_csr] |
mov ecx,[pcnet32_private.options] |
and ecx,PCNET32_PORT_PORTSEL |
cmp ecx,PCNET32_PORT_GPSI |
jne .L5 |
or eax,0x10 |
.L5: |
call dword [pcnet32_access.write_csr] |
cmp [pcnet32_private.mii],0 |
je .L6 |
test [pcnet32_private.options],PCNET32_PORT_ASEL |
jnz .L6 |
mov ebx,32 |
call dword [pcnet32_access.read_bcr] |
and eax,not 0x38 |
test [pcnet32_private.options],PCNET32_PORT_FD |
jz .L7 |
or eax,0x10 |
.L7: |
test [pcnet32_private.options],PCNET32_PORT_100 |
jz .L8 |
or eax,0x08 |
.L8: |
call dword [pcnet32_access.write_bcr] |
jmp .L9 |
.L6: |
test [pcnet32_private.options],PCNET32_PORT_ASEL |
jz .L9 |
mov ebx,32 |
; DEBUGF 1," K : ASEL, enable auto-negotiation\n" |
call dword [pcnet32_access.read_bcr] |
and eax,not 0x98 |
or eax,0x20 |
call dword [pcnet32_access.write_bcr] |
.L9: |
cmp [pcnet32_private.ltint],0 |
je .L10 |
mov ebx,5 |
call dword [pcnet32_access.read_csr] |
or eax,(1 shl 14) |
call dword [pcnet32_access.write_csr] |
.L10: |
mov eax,[pcnet32_private.options] |
and eax,PCNET32_PORT_PORTSEL |
shl eax,7 |
mov [pcnet32_private.mode],ax |
mov [pcnet32_private.filter],dword 0xffffffff |
mov [pcnet32_private.filter+4],dword 0xffffffff |
call pcnet32_init_ring |
mov ebx,1 |
mov eax,pcnet32_private |
sub eax,OS_BASE |
and eax,0xffff |
call dword [pcnet32_access.write_csr] |
mov eax,pcnet32_private |
sub eax,OS_BASE |
mov ebx,2 |
shr eax,16 |
call dword [pcnet32_access.write_csr] |
mov ebx,4 |
mov eax,0x0915 |
call dword [pcnet32_access.write_csr] |
mov ebx,0 |
mov eax,1 |
call dword [pcnet32_access.write_csr] |
mov ecx,100 |
.L11: |
xor ebx,ebx |
call dword [pcnet32_access.read_csr] |
test ax,0x100 |
jnz .L12 |
loop .L11 |
.L12: |
; DEBUGF 1," K : hardware reset\n" |
xor ebx,ebx |
mov eax,0x0002 |
call dword [pcnet32_access.write_csr] |
xor ebx,ebx |
call dword [pcnet32_access.read_csr] |
; DEBUGF 1," K : PCNET reset complete\n" |
ret |
pcnet32_adjust_pci_device: |
;*******Get current setting************************ |
mov al, 2 ;read a word |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, 0x04 ;from command Register |
call pci_read_reg |
;******see if its already set as bus master******** |
mov bx, ax |
and bx,5 |
cmp bx,5 |
je pcnet32_adjust_pci_device_Latency |
;******Make card a bus master******* |
mov cx, ax ;value to write |
mov bh, [pci_dev] |
mov al, 2 ;write a word |
or cx,5 |
mov ah, [pci_bus] |
mov bl, 0x04 ;to command register |
call pci_write_reg |
;******Check latency setting*********** |
pcnet32_adjust_pci_device_Latency: |
;*******Get current latency setting************************ |
; mov al, 1 ;read a byte |
; mov bh, [pci_dev] |
; mov ah, [pci_bus] |
; mov bl, 0x0D ;from Lantency Timer Register |
; call pci_read_reg |
;******see if its aat least 64 clocks******** |
; cmp ax,64 |
; jge pcnet32_adjust_pci_device_Done |
;******Set latency to 32 clocks******* |
; mov cx, 64 ;value to write |
; mov bh, [pci_dev] |
; mov al, 1 ;write a byte |
; mov ah, [pci_bus] |
; mov bl, 0x0D ;to Lantency Timer Register |
; call pci_write_reg |
;******Check latency setting*********** |
pcnet32_adjust_pci_device_Done: |
ret |
pcnet32_probe: |
mov ebp,[io_addr] |
call pcnet32_wio_reset |
xor ebx,ebx |
call pcnet32_wio_read_csr |
cmp eax,4 |
jne .try_dwio |
call pcnet32_wio_check |
and al,al |
jz .try_dwio |
; DEBUGF 1," K : Using WIO\n" |
mov esi,pcnet32_wio |
jmp .L1 |
.try_dwio: |
call pcnet32_dwio_reset |
xor ebx,ebx |
call pcnet32_dwio_read_csr |
cmp eax,4 |
jne .no_dev |
call pcnet32_dwio_check |
and al,al |
jz .no_dev |
; DEBUGF 1," K : Using DWIO\n" |
mov esi,pcnet32_dwio |
jmp .L1 |
.no_dev: |
DEBUGF 1," K : PCNET32 not found\n" |
ret |
.L1: |
mov edi,pcnet32_access |
mov ecx,7 |
cld |
rep movsd |
mov ebx,88 |
call dword [pcnet32_access.read_csr] |
mov ecx,eax |
mov ebx,89 |
call dword [pcnet32_access.read_csr] |
shl eax,16 |
or eax,ecx |
mov ecx,eax |
and ecx,0xfff |
cmp ecx,3 |
jne .no_dev |
shr eax,12 |
and eax,0xffff |
mov [pcnet32_private.chip_version],eax |
; DEBUGF 1," K : PCNET32 chip version OK\n" |
mov [pcnet32_private.fdx],0 |
mov [pcnet32_private.mii],0 |
mov [pcnet32_private.fset],0 |
mov [pcnet32_private.dxsuflo],0 |
mov [pcnet32_private.ltint],0 |
mov eax,[pcnet32_private.chip_version] |
cmp eax,0x2420 |
je .L2 |
cmp eax,0x2430 |
je .L3 |
cmp eax,0x2621 |
je .L4 |
cmp eax,0x2623 |
je .L5 |
cmp eax,0x2624 |
je .L6 |
cmp eax,0x2625 |
je .L7 |
cmp eax,0x2626 |
je .L8 |
cmp eax,0x2627 |
je .L9 |
DEBUGF 1," K : Invalid chip rev\n" |
jmp .no_dev |
.L2: |
; DEBUGF 1," K : PCnet/PCI 79C970\n" |
jmp .L10 |
.L3: |
; DEBUGF 1," K : PCnet/PCI 79C970\n" |
jmp .L10 |
.L4: |
; DEBUGF 1," K : PCnet/PCI II 79C970A\n" |
mov [pcnet32_private.fdx],1 |
jmp .L10 |
.L5: |
; DEBUGF 1," K : PCnet/FAST 79C971\n" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
mov [pcnet32_private.fset],1 |
mov [pcnet32_private.ltint],1 |
jmp .L10 |
.L6: |
; DEBUGF 1," K : PCnet/FAST+ 79C972\n" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
mov [pcnet32_private.fset],1 |
jmp .L10 |
.L7: |
; DEBUGF 1," K : PCnet/FAST III 79C973\n" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
jmp .L10 |
.L8: |
; DEBUGF 1," K : PCnet/Home 79C978\n" |
mov [pcnet32_private.fdx],1 |
mov ebx,49 |
call dword [pcnet32_access.read_bcr] |
call dword [pcnet32_access.write_bcr] |
jmp .L10 |
.L9: |
; DEBUGF 1," K : PCnet/FAST III 79C975\n" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
.L10: |
cmp [pcnet32_private.fset],1 |
jne .L11 |
mov ebx,18 |
call dword [pcnet32_access.read_bcr] |
or eax,0x800 |
call dword [pcnet32_access.write_bcr] |
mov ebx,80 |
call dword [pcnet32_access.read_csr] |
and eax,0xc00 |
or eax,0xc00 |
call dword [pcnet32_access.write_csr] |
mov [pcnet32_private.dxsuflo],1 |
mov [pcnet32_private.ltint],1 |
.L11: |
; read MAC |
mov edi,node_addr |
mov edx,ebp |
mov ecx,6 |
.Lmac: |
in al,dx |
stosb |
inc edx |
loop .Lmac |
; DEBUGF 1," K : MAC read\n" |
call pcnet32_adjust_pci_device |
; DEBUGF 1," K : PCI done\n" |
mov eax,PCNET32_PORT_ASEL |
mov [pcnet32_private.options],eax |
mov [pcnet32_private.mode],word 0x0003 |
mov [pcnet32_private.tlen_rlen],word (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) |
mov esi,node_addr |
mov edi,pcnet32_private.phys_addr |
cld |
movsd |
movsw |
mov [pcnet32_private.filter],dword 0 |
mov [pcnet32_private.filter+4],dword 0 |
mov eax,pcnet32_rx_ring |
sub eax,OS_BASE |
mov dword [pcnet32_private.rx_ring],eax |
mov eax,pcnet32_tx_ring |
sub eax,OS_BASE |
mov dword [pcnet32_private.tx_ring],eax |
; DEBUGF 1," K : Switching to 32\n" |
mov ebx,20 |
mov eax,2 |
call dword [pcnet32_access.write_bcr] |
mov ebx,1 |
mov eax,(pcnet32_private and 0xffff) |
call dword [pcnet32_access.write_csr] |
mov ebx,2 |
mov eax,(pcnet32_private shr 16) and 0xffff |
call dword [pcnet32_access.write_csr] |
mov ebx,0 |
mov eax,1 |
call dword [pcnet32_access.write_csr] |
mov esi,1 |
call delay_ms |
call pcnet32_reset |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
pcnet32_poll: |
xor ax,ax |
mov [eth_rx_data_len],ax |
mov eax,[pcnet32_private.cur_rx] |
and eax,PCNET32_RX_RING_MOD_MASK |
mov ebx,eax |
imul esi,eax,PCNET32_PKT_BUF_SZ |
add esi,pcnet32_rxb |
shl ebx,4 |
add ebx,pcnet32_rx_ring |
mov cx,[ebx+pcnet32_rx_head.status] |
test cx,0x8000 |
jnz .L1 |
cmp ch,3 |
jne .L1 |
mov ecx,[ebx+pcnet32_rx_head.msg_length] |
and ecx,0xfff |
sub ecx,4 |
mov [eth_rx_data_len],cx |
; DEBUGF 1," K : PCNETRX: %ub\n",cx |
push ecx |
shr ecx,2 |
mov edi,Ether_buffer |
cld |
rep movsd |
pop ecx |
and ecx,3 |
rep movsb |
mov [ebx+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG |
or [ebx+pcnet32_rx_head.status],word 0x8000 |
inc [pcnet32_private.cur_rx] |
.L1: |
ret |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
pcnet32_xmit: |
push edi |
push esi |
push ebx |
push ecx |
; DEBUGF 1," K : PCNETTX\n" |
mov esi,edi |
mov edi,[pcnet32_private.cur_tx] |
imul edi,PCNET32_PKT_BUF_SZ |
add edi,pcnet32_txb ; edi=ptxb |
mov eax,edi |
cld ; copy MAC |
movsd |
movsw |
mov esi,node_addr |
cld |
movsd |
movsw |
mov [edi],bx |
add edi,2 |
mov esi,[esp+8] |
mov ecx,[esp] |
push ecx |
shr ecx,2 |
cld |
rep movsd |
pop ecx |
and ecx,3 |
rep movsb |
; mov ecx,[esp] |
; add ecx,14 ; ETH_HLEN |
; xor eax,eax |
; pad to min length (60=ETH_ZLEN) |
; cmp ecx,60 |
; jae .L1 |
; sub ecx,60 |
; cld |
; rep stosb |
;.L1: |
mov edi,pcnet32_tx_ring+0 ; entry=0 |
mov ecx,[esp] |
add ecx,14 |
cmp cx,60 |
jae .L1 |
mov cx,60 |
.L1: |
neg cx |
mov [edi+pcnet32_tx_head.length],cx |
mov [edi+pcnet32_tx_head.misc],dword 0 |
sub eax,OS_BASE |
mov [edi+pcnet32_tx_head.base],eax |
mov [edi+pcnet32_tx_head.status],word 0x8300 |
; trigger an immediate send poll |
mov ebx,0 |
mov eax,0x0008 ; 0x0048 |
mov ebp,[io_addr] |
call dword [pcnet32_access.write_csr] |
mov dword [pcnet32_private.cur_tx],0 |
; wait for TX to complete |
mov ecx,[timer_ticks];[0xfdf0] |
add ecx,100 |
.L2: |
mov ax,[edi+pcnet32_tx_head.status] |
test ax,0x8000 |
jz .L3 |
cmp ecx,[timer_ticks];[0xfdf0] |
jb .L4 |
mov esi,10 |
call delay_ms |
jnz .L2 |
.L4: |
DEBUGF 1," K : PCNET: Send timeout\n" |
.L3: |
mov dword [edi+pcnet32_tx_head.base],0 |
pop ecx |
pop ebx |
pop esi |
pop edi |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; PCNET32.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; - Version 1.0 31 July 2004: ;; |
;; Initial release ;; |
;; ;; |
;; - Version 1.01 29 March 2008: ;; |
;; Adapted to work with kolibrios flat kernel ;; |
;; Debug info is updated, and now uses DEBUGF macro ;; |
;; by hidnplayr@kolibrios.org ;; |
;; ;; |
;; This driver is based on the PCNet32 driver from ;; |
;; the etherboot 5.0.6 project. The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2004 Jarek Pelczar, ;; |
;; jpelczar@interia.pl ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
PCNET32_PORT_AUI equ 0x00 |
PCNET32_PORT_10BT equ 0x01 |
PCNET32_PORT_GPSI equ 0x02 |
PCNET32_PORT_MII equ 0x03 |
PCNET32_PORT_PORTSEL equ 0x03 |
PCNET32_PORT_ASEL equ 0x04 |
PCNET32_PORT_100 equ 0x40 |
PCNET32_PORT_FD equ 0x80 |
PCNET32_DMA_MASK equ 0xffffffff |
PCNET32_LOG_TX_BUFFERS equ 1 |
PCNET32_LOG_RX_BUFFERS equ 2 |
PCNET32_TX_RING_SIZE equ (1 shl PCNET32_LOG_TX_BUFFERS) |
PCNET32_TX_RING_MOD_MASK equ (PCNET32_TX_RING_SIZE-1) |
PCNET32_TX_RING_LEN_BITS equ 0 |
PCNET32_RX_RING_SIZE equ (1 shl PCNET32_LOG_RX_BUFFERS) |
PCNET32_RX_RING_MOD_MASK equ (PCNET32_RX_RING_SIZE-1) |
PCNET32_RX_RING_LEN_BITS equ (PCNET32_LOG_RX_BUFFERS shl 4) |
PCNET32_PKT_BUF_SZ equ 1544 |
PCNET32_PKT_BUF_SZ_NEG equ 0xf9f8 |
pcnet32_txb equ (eth_data_start) |
pcnet32_rxb equ ((pcnet32_txb+(PCNET32_PKT_BUF_SZ*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) |
pcnet32_tx_ring equ ((pcnet32_rxb+(PCNET32_PKT_BUF_SZ*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) |
pcnet32_rx_ring equ ((pcnet32_tx_ring+(16*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) |
virtual at ((pcnet32_rx_ring+(16*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) |
pcnet32_private: |
.mode dw ? |
.tlen_rlen dw ? |
.phys_addr db ?,?,?,?,?,? |
.reserved dw ? |
.filter dd ?,? |
.rx_ring dd ? |
.tx_ring dd ? |
.cur_rx dd ? |
.cur_tx dd ? |
.dirty_rx dd ? |
.dirty_tx dd ? |
.tx_full db ? |
.options dd ? |
.full_duplex db ? |
.chip_version dd ? |
.mii db ? |
.ltint db ? |
.dxsuflo db ? |
.fset db ? |
.fdx db ? |
end virtual |
virtual at 0 |
pcnet32_rx_head: |
.base dd ? |
.buf_length dw ? |
.status dw ? |
.msg_length dd ? |
.reserved dd ? |
end virtual |
virtual at 0 |
pcnet32_tx_head: |
.base dd ? |
.length dw ? |
.status dw ? |
.misc dd ? |
.reserved dd ? |
end virtual |
uglobal |
pcnet32_access: |
.read_csr dd ? |
.write_csr dd ? |
.read_bcr dd ? |
.write_bcr dd ? |
.read_rap dd ? |
.write_rap dd ? |
.reset dd ? |
endg |
iglobal |
pcnet32_options_mapping: |
dd PCNET32_PORT_ASEL ; 0 Auto-select |
dd PCNET32_PORT_AUI ; 1 BNC/AUI |
dd PCNET32_PORT_AUI ; 2 AUI/BNC |
dd PCNET32_PORT_ASEL ; 3 not supported |
dd PCNET32_PORT_10BT or PCNET32_PORT_FD ; 4 10baseT-FD |
dd PCNET32_PORT_ASEL ; 5 not supported |
dd PCNET32_PORT_ASEL ; 6 not supported |
dd PCNET32_PORT_ASEL ; 7 not supported |
dd PCNET32_PORT_ASEL ; 8 not supported |
dd PCNET32_PORT_MII ; 9 MII 10baseT |
dd PCNET32_PORT_MII or PCNET32_PORT_FD ; 10 MII 10baseT-FD |
dd PCNET32_PORT_MII ; 11 MII (autosel) |
dd PCNET32_PORT_10BT ; 12 10BaseT |
dd PCNET32_PORT_MII or PCNET32_PORT_100 ; 13 MII 100BaseTx |
dd PCNET32_PORT_MII or PCNET32_PORT_100 or PCNET32_PORT_FD ; 14 MII 100BaseTx-FD |
dd PCNET32_PORT_ASEL ; 15 not supported |
endg |
PCNET32_WIO_RDP equ 0x10 |
PCNET32_WIO_RAP equ 0x12 |
PCNET32_WIO_RESET equ 0x14 |
PCNET32_WIO_BDP equ 0x16 |
PCNET32_DWIO_RDP equ 0x10 |
PCNET32_DWIO_RAP equ 0x14 |
PCNET32_DWIO_RESET equ 0x18 |
PCNET32_DWIO_BDP equ 0x1C |
PCNET32_TOTAL_SIZE equ 0x20 |
; ebx - index |
; return: |
; eax - data |
pcnet32_wio_read_csr: |
push edx |
lea edx, [ebp+PCNET32_WIO_RAP] |
mov ax, bx |
out dx, ax |
lea edx, [ebp+PCNET32_WIO_RDP] |
in ax, dx |
and eax, 0xffff |
pop edx |
ret |
; eax - data |
; ebx - index |
pcnet32_wio_write_csr: |
push edx |
lea edx, [ebp+PCNET32_WIO_RAP] |
xchg eax, ebx |
out dx, ax |
xchg eax, ebx |
lea edx, [ebp+PCNET32_WIO_RDP] |
out dx, ax |
pop edx |
ret |
; ebx - index |
; return: |
; eax - data |
pcnet32_wio_read_bcr: |
push edx |
lea edx, [ebp+PCNET32_WIO_RAP] |
mov ax, bx |
out dx, ax |
lea edx, [ebp+PCNET32_WIO_BDP] |
in ax, dx |
and eax, 0xffff |
pop edx |
ret |
; eax - data |
; ebx - index |
pcnet32_wio_write_bcr: |
push edx |
lea edx, [ebp+PCNET32_WIO_RAP] |
xchg eax, ebx |
out dx, ax |
xchg eax, ebx |
lea edx, [ebp+PCNET32_WIO_BDP] |
out dx, ax |
pop edx |
ret |
pcnet32_wio_read_rap: |
push edx |
lea edx, [ebp+PCNET32_WIO_RAP] |
in ax, dx |
and eax, 0xffff |
pop edx |
ret |
; eax - val |
pcnet32_wio_write_rap: |
push edx |
lea edx, [ebp+PCNET32_WIO_RAP] |
out dx, ax |
pop edx |
ret |
pcnet32_wio_reset: |
push edx |
push eax |
lea edx, [ebp+PCNET32_WIO_RESET] |
in ax, dx |
pop eax |
pop edx |
ret |
pcnet32_wio_check: |
push edx |
mov ax, 88 |
lea edx, [ebp+PCNET32_WIO_RAP] |
out dx, ax |
nop |
nop |
in ax, dx |
cmp ax, 88 |
sete al |
pop edx |
ret |
iglobal |
pcnet32_wio: |
dd pcnet32_wio_read_csr |
dd pcnet32_wio_write_csr |
dd pcnet32_wio_read_bcr |
dd pcnet32_wio_write_bcr |
dd pcnet32_wio_read_rap |
dd pcnet32_wio_write_rap |
dd pcnet32_wio_reset |
endg |
; ebx - index |
; return: |
; eax - data |
pcnet32_dwio_read_csr: |
push edx |
lea edx, [ebp+PCNET32_DWIO_RAP] |
mov ebx, eax |
out dx, eax |
lea edx, [ebp+PCNET32_DWIO_RDP] |
in eax, dx |
and eax, 0xffff |
pop edx |
ret |
; ebx - index |
; eax - data |
pcnet32_dwio_write_csr: |
push edx |
lea edx, [ebp+PCNET32_DWIO_RAP] |
xchg eax, ebx |
out dx, eax |
lea edx, [ebp+PCNET32_DWIO_RDP] |
xchg eax, ebx |
out dx, eax |
pop edx |
ret |
; ebx - index |
; return: |
; eax - data |
pcnet32_dwio_read_bcr: |
push edx |
lea edx, [ebp+PCNET32_DWIO_RAP] |
mov ebx, eax |
out dx, eax |
lea edx, [ebp+PCNET32_DWIO_BDP] |
in eax, dx |
and eax, 0xffff |
pop edx |
ret |
; ebx - index |
; eax - data |
pcnet32_dwio_write_bcr: |
push edx |
lea edx, [ebp+PCNET32_DWIO_RAP] |
xchg eax, ebx |
out dx, eax |
lea edx, [ebp+PCNET32_DWIO_BDP] |
xchg eax, ebx |
out dx, eax |
pop edx |
ret |
pcnet32_dwio_read_rap: |
push edx |
lea edx, [ebp+PCNET32_DWIO_RAP] |
in eax, dx |
and eax, 0xffff |
pop edx |
ret |
; eax - val |
pcnet32_dwio_write_rap: |
push edx |
lea edx, [ebp+PCNET32_DWIO_RAP] |
out dx, eax |
pop edx |
ret |
pcnet32_dwio_reset: |
push edx |
push eax |
lea edx, [ebp+PCNET32_DWIO_RESET] |
in eax, dx |
pop eax |
pop edx |
ret |
pcnet32_dwio_check: |
push edx |
lea edx, [PCNET32_DWIO_RAP] |
mov eax, 88 |
out dx, eax |
nop |
nop |
in eax, dx |
and eax, 0xffff |
cmp eax, 88 |
sete al |
pop edx |
ret |
iglobal |
pcnet32_dwio: |
dd pcnet32_dwio_read_csr |
dd pcnet32_dwio_write_csr |
dd pcnet32_dwio_read_bcr |
dd pcnet32_dwio_write_bcr |
dd pcnet32_dwio_read_rap |
dd pcnet32_dwio_write_rap |
dd pcnet32_dwio_reset |
endg |
pcnet32_init_ring: |
mov [pcnet32_private.tx_full], 0 |
mov [pcnet32_private.cur_rx], 0 |
mov [pcnet32_private.cur_tx], 0 |
mov [pcnet32_private.dirty_rx], 0 |
mov [pcnet32_private.dirty_tx], 0 |
mov edi, pcnet32_rx_ring |
mov ecx, PCNET32_RX_RING_SIZE |
mov ebx, pcnet32_rxb |
sub ebx, OS_BASE |
.rx_init: |
mov [edi+pcnet32_rx_head.base], ebx |
mov [edi+pcnet32_rx_head.buf_length], word PCNET32_PKT_BUF_SZ_NEG |
mov [edi+pcnet32_rx_head.status], word 0x8000 |
add ebx, PCNET32_PKT_BUF_SZ |
; inc ebx |
add edi, 16 |
loop .rx_init |
mov edi, pcnet32_tx_ring |
mov ecx, PCNET32_TX_RING_SIZE |
.tx_init: |
mov [edi+pcnet32_tx_head.base], dword 0 |
mov [edi+pcnet32_tx_head.status], word 0 |
add edi, 16 |
loop .tx_init |
mov [pcnet32_private.tlen_rlen], (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) |
mov esi, node_addr |
mov edi, pcnet32_private.phys_addr |
cld |
movsd |
movsw |
mov eax, pcnet32_rx_ring |
sub eax, OS_BASE |
mov dword [pcnet32_private.rx_ring], eax |
mov eax, pcnet32_tx_ring |
sub eax, OS_BASE |
mov dword [pcnet32_private.tx_ring], eax |
ret |
pcnet32_reset: |
; Reset PCNET32 |
mov ebp, [io_addr] |
call dword [pcnet32_access.reset] |
; set 32bit mode |
mov ebx, 20 |
mov eax, 2 |
call dword [pcnet32_access.write_bcr] |
; set/reset autoselect bit |
mov ebx, 2 |
call dword [pcnet32_access.read_bcr] |
and eax, not 2 |
test [pcnet32_private.options], PCNET32_PORT_ASEL |
jz .L1 |
or eax, 2 |
.L1: |
call dword [pcnet32_access.write_bcr] |
; Handle full duplex setting |
cmp byte [pcnet32_private.full_duplex], 0 |
je .L2 |
mov ebx, 9 |
call dword [pcnet32_access.read_bcr] |
and eax, not 3 |
test [pcnet32_private.options], PCNET32_PORT_FD |
jz .L3 |
or eax, 1 |
cmp [pcnet32_private.options], PCNET32_PORT_FD or PCNET32_PORT_AUI |
jne .L4 |
or eax, 2 |
jmp .L4 |
.L3: |
test [pcnet32_private.options], PCNET32_PORT_ASEL |
jz .L4 |
cmp [pcnet32_private.chip_version], 0x2627 |
jne .L4 |
or eax, 3 |
.L4: |
mov ebx, 9 |
call dword [pcnet32_access.write_bcr] |
.L2: |
; set/reset GPSI bit |
mov ebx, 124 |
call dword [pcnet32_access.read_csr] |
mov ecx, [pcnet32_private.options] |
and ecx, PCNET32_PORT_PORTSEL |
cmp ecx, PCNET32_PORT_GPSI |
jne .L5 |
or eax, 0x10 |
.L5: |
call dword [pcnet32_access.write_csr] |
cmp [pcnet32_private.mii], 0 |
je .L6 |
test [pcnet32_private.options], PCNET32_PORT_ASEL |
jnz .L6 |
mov ebx, 32 |
call dword [pcnet32_access.read_bcr] |
and eax, not 0x38 |
test [pcnet32_private.options], PCNET32_PORT_FD |
jz .L7 |
or eax, 0x10 |
.L7: |
test [pcnet32_private.options], PCNET32_PORT_100 |
jz .L8 |
or eax, 0x08 |
.L8: |
call dword [pcnet32_access.write_bcr] |
jmp .L9 |
.L6: |
test [pcnet32_private.options], PCNET32_PORT_ASEL |
jz .L9 |
mov ebx, 32 |
; DEBUGF 1," K : ASEL, enable auto-negotiation\n" |
call dword [pcnet32_access.read_bcr] |
and eax, not 0x98 |
or eax, 0x20 |
call dword [pcnet32_access.write_bcr] |
.L9: |
cmp [pcnet32_private.ltint], 0 |
je .L10 |
mov ebx, 5 |
call dword [pcnet32_access.read_csr] |
or eax, (1 shl 14) |
call dword [pcnet32_access.write_csr] |
.L10: |
mov eax, [pcnet32_private.options] |
and eax, PCNET32_PORT_PORTSEL |
shl eax, 7 |
mov [pcnet32_private.mode], ax |
mov [pcnet32_private.filter], dword 0xffffffff |
mov [pcnet32_private.filter+4], dword 0xffffffff |
call pcnet32_init_ring |
mov ebx, 1 |
mov eax, pcnet32_private |
sub eax, OS_BASE |
and eax, 0xffff |
call dword [pcnet32_access.write_csr] |
mov eax, pcnet32_private |
sub eax, OS_BASE |
mov ebx, 2 |
shr eax, 16 |
call dword [pcnet32_access.write_csr] |
mov ebx, 4 |
mov eax, 0x0915 |
call dword [pcnet32_access.write_csr] |
mov ebx, 0 |
mov eax, 1 |
call dword [pcnet32_access.write_csr] |
mov ecx, 100 |
.L11: |
xor ebx, ebx |
call dword [pcnet32_access.read_csr] |
test ax, 0x100 |
jnz .L12 |
loop .L11 |
.L12: |
; DEBUGF 1," K : hardware reset\n" |
xor ebx, ebx |
mov eax, 0x0002 |
call dword [pcnet32_access.write_csr] |
xor ebx, ebx |
call dword [pcnet32_access.read_csr] |
; DEBUGF 1," K : PCNET reset complete\n" |
ret |
pcnet32_adjust_pci_device: |
;*******Get current setting************************ |
mov al, 2 ;read a word |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, 0x04 ;from command Register |
call pci_read_reg |
;******see if its already set as bus master******** |
mov bx, ax |
and bx, 5 |
cmp bx, 5 |
je pcnet32_adjust_pci_device_Latency |
;******Make card a bus master******* |
mov cx, ax ;value to write |
mov bh, [pci_dev] |
mov al, 2 ;write a word |
or cx, 5 |
mov ah, [pci_bus] |
mov bl, 0x04 ;to command register |
call pci_write_reg |
;******Check latency setting*********** |
pcnet32_adjust_pci_device_Latency: |
;*******Get current latency setting************************ |
; mov al, 1 ;read a byte |
; mov bh, [pci_dev] |
; mov ah, [pci_bus] |
; mov bl, 0x0D ;from Lantency Timer Register |
; call pci_read_reg |
;******see if its aat least 64 clocks******** |
; cmp ax,64 |
; jge pcnet32_adjust_pci_device_Done |
;******Set latency to 32 clocks******* |
; mov cx, 64 ;value to write |
; mov bh, [pci_dev] |
; mov al, 1 ;write a byte |
; mov ah, [pci_bus] |
; mov bl, 0x0D ;to Lantency Timer Register |
; call pci_write_reg |
;******Check latency setting*********** |
pcnet32_adjust_pci_device_Done: |
ret |
pcnet32_probe: |
mov ebp, [io_addr] |
call pcnet32_wio_reset |
xor ebx, ebx |
call pcnet32_wio_read_csr |
cmp eax, 4 |
jne .try_dwio |
call pcnet32_wio_check |
and al, al |
jz .try_dwio |
; DEBUGF 1," K : Using WIO\n" |
mov esi, pcnet32_wio |
jmp .L1 |
.try_dwio: |
call pcnet32_dwio_reset |
xor ebx, ebx |
call pcnet32_dwio_read_csr |
cmp eax, 4 |
jne .no_dev |
call pcnet32_dwio_check |
and al, al |
jz .no_dev |
; DEBUGF 1," K : Using DWIO\n" |
mov esi, pcnet32_dwio |
jmp .L1 |
.no_dev: |
DEBUGF 1," K : PCNET32 not found\n" |
ret |
.L1: |
mov edi, pcnet32_access |
mov ecx, 7 |
cld |
rep movsd |
mov ebx, 88 |
call dword [pcnet32_access.read_csr] |
mov ecx, eax |
mov ebx, 89 |
call dword [pcnet32_access.read_csr] |
shl eax, 16 |
or eax, ecx |
mov ecx, eax |
and ecx, 0xfff |
cmp ecx, 3 |
jne .no_dev |
shr eax, 12 |
and eax, 0xffff |
mov [pcnet32_private.chip_version], eax |
; DEBUGF 1," K : PCNET32 chip version OK\n" |
mov [pcnet32_private.fdx], 0 |
mov [pcnet32_private.mii], 0 |
mov [pcnet32_private.fset], 0 |
mov [pcnet32_private.dxsuflo], 0 |
mov [pcnet32_private.ltint], 0 |
mov eax, [pcnet32_private.chip_version] |
cmp eax, 0x2420 |
je .L2 |
cmp eax, 0x2430 |
je .L3 |
cmp eax, 0x2621 |
je .L4 |
cmp eax, 0x2623 |
je .L5 |
cmp eax, 0x2624 |
je .L6 |
cmp eax, 0x2625 |
je .L7 |
cmp eax, 0x2626 |
je .L8 |
cmp eax, 0x2627 |
je .L9 |
DEBUGF 1," K : Invalid chip rev\n" |
jmp .no_dev |
.L2: |
; DEBUGF 1," K : PCnet/PCI 79C970\n" |
jmp .L10 |
.L3: |
; DEBUGF 1," K : PCnet/PCI 79C970\n" |
jmp .L10 |
.L4: |
; DEBUGF 1," K : PCnet/PCI II 79C970A\n" |
mov [pcnet32_private.fdx], 1 |
jmp .L10 |
.L5: |
; DEBUGF 1," K : PCnet/FAST 79C971\n" |
mov [pcnet32_private.fdx], 1 |
mov [pcnet32_private.mii], 1 |
mov [pcnet32_private.fset], 1 |
mov [pcnet32_private.ltint], 1 |
jmp .L10 |
.L6: |
; DEBUGF 1," K : PCnet/FAST+ 79C972\n" |
mov [pcnet32_private.fdx], 1 |
mov [pcnet32_private.mii], 1 |
mov [pcnet32_private.fset], 1 |
jmp .L10 |
.L7: |
; DEBUGF 1," K : PCnet/FAST III 79C973\n" |
mov [pcnet32_private.fdx], 1 |
mov [pcnet32_private.mii], 1 |
jmp .L10 |
.L8: |
; DEBUGF 1," K : PCnet/Home 79C978\n" |
mov [pcnet32_private.fdx], 1 |
mov ebx, 49 |
call dword [pcnet32_access.read_bcr] |
call dword [pcnet32_access.write_bcr] |
jmp .L10 |
.L9: |
; DEBUGF 1," K : PCnet/FAST III 79C975\n" |
mov [pcnet32_private.fdx], 1 |
mov [pcnet32_private.mii], 1 |
.L10: |
cmp [pcnet32_private.fset], 1 |
jne .L11 |
mov ebx, 18 |
call dword [pcnet32_access.read_bcr] |
or eax, 0x800 |
call dword [pcnet32_access.write_bcr] |
mov ebx, 80 |
call dword [pcnet32_access.read_csr] |
and eax, 0xc00 |
or eax, 0xc00 |
call dword [pcnet32_access.write_csr] |
mov [pcnet32_private.dxsuflo], 1 |
mov [pcnet32_private.ltint], 1 |
.L11: |
; read MAC |
mov edi, node_addr |
mov edx, ebp |
mov ecx, 6 |
.Lmac: |
in al, dx |
stosb |
inc edx |
loop .Lmac |
; DEBUGF 1," K : MAC read\n" |
call pcnet32_adjust_pci_device |
; DEBUGF 1," K : PCI done\n" |
mov eax, PCNET32_PORT_ASEL |
mov [pcnet32_private.options], eax |
mov [pcnet32_private.mode], word 0x0003 |
mov [pcnet32_private.tlen_rlen], word (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) |
mov esi, node_addr |
mov edi, pcnet32_private.phys_addr |
cld |
movsd |
movsw |
mov [pcnet32_private.filter], dword 0 |
mov [pcnet32_private.filter+4], dword 0 |
mov eax, pcnet32_rx_ring |
sub eax, OS_BASE |
mov dword [pcnet32_private.rx_ring], eax |
mov eax, pcnet32_tx_ring |
sub eax, OS_BASE |
mov dword [pcnet32_private.tx_ring], eax |
; DEBUGF 1," K : Switching to 32\n" |
mov ebx, 20 |
mov eax, 2 |
call dword [pcnet32_access.write_bcr] |
mov ebx, 1 |
mov eax, (pcnet32_private and 0xffff) |
call dword [pcnet32_access.write_csr] |
mov ebx, 2 |
mov eax, (pcnet32_private shr 16) and 0xffff |
call dword [pcnet32_access.write_csr] |
mov ebx, 0 |
mov eax, 1 |
call dword [pcnet32_access.write_csr] |
mov esi, 1 |
call delay_ms |
call pcnet32_reset |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
pcnet32_poll: |
xor ax, ax |
mov [eth_rx_data_len], ax |
mov eax, [pcnet32_private.cur_rx] |
and eax, PCNET32_RX_RING_MOD_MASK |
mov ebx, eax |
imul esi, eax, PCNET32_PKT_BUF_SZ |
add esi, pcnet32_rxb |
shl ebx, 4 |
add ebx, pcnet32_rx_ring |
mov cx, [ebx+pcnet32_rx_head.status] |
test cx, 0x8000 |
jnz .L1 |
cmp ch, 3 |
jne .L1 |
mov ecx, [ebx+pcnet32_rx_head.msg_length] |
and ecx, 0xfff |
sub ecx, 4 |
mov [eth_rx_data_len], cx |
; DEBUGF 1," K : PCNETRX: %ub\n",cx |
push ecx |
shr ecx, 2 |
mov edi, Ether_buffer |
cld |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
mov [ebx+pcnet32_rx_head.buf_length], word PCNET32_PKT_BUF_SZ_NEG |
or [ebx+pcnet32_rx_head.status], word 0x8000 |
inc [pcnet32_private.cur_rx] |
.L1: |
ret |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
pcnet32_xmit: |
push edi |
push esi |
push ebx |
push ecx |
; DEBUGF 1," K : PCNETTX\n" |
mov esi, edi |
mov edi, [pcnet32_private.cur_tx] |
imul edi, PCNET32_PKT_BUF_SZ |
add edi, pcnet32_txb; edi=ptxb |
mov eax, edi |
cld ; copy MAC |
movsd |
movsw |
mov esi, node_addr |
cld |
movsd |
movsw |
mov [edi], bx |
add edi, 2 |
mov esi, [esp+8] |
mov ecx, [esp] |
push ecx |
shr ecx, 2 |
cld |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
; mov ecx,[esp] |
; add ecx,14 ; ETH_HLEN |
; xor eax,eax |
; pad to min length (60=ETH_ZLEN) |
; cmp ecx,60 |
; jae .L1 |
; sub ecx,60 |
; cld |
; rep stosb |
;.L1: |
mov edi, pcnet32_tx_ring+0; entry=0 |
mov ecx, [esp] |
add ecx, 14 |
cmp cx, 60 |
jae .L1 |
mov cx, 60 |
.L1: |
neg cx |
mov [edi+pcnet32_tx_head.length], cx |
mov [edi+pcnet32_tx_head.misc], dword 0 |
sub eax, OS_BASE |
mov [edi+pcnet32_tx_head.base], eax |
mov [edi+pcnet32_tx_head.status], word 0x8300 |
; trigger an immediate send poll |
mov ebx, 0 |
mov eax, 0x0008; 0x0048 |
mov ebp, [io_addr] |
call dword [pcnet32_access.write_csr] |
mov dword [pcnet32_private.cur_tx], 0 |
; wait for TX to complete |
mov ecx, [timer_ticks];[0xfdf0] |
add ecx, 100 |
.L2: |
mov ax, [edi+pcnet32_tx_head.status] |
test ax, 0x8000 |
jz .L3 |
cmp ecx, [timer_ticks];[0xfdf0] |
jb .L4 |
mov esi, 10 |
call delay_ms |
jnz .L2 |
.L4: |
DEBUGF 1," K : PCNET: Send timeout\n" |
.L3: |
mov dword [edi+pcnet32_tx_head.base], 0 |
pop ecx |
pop ebx |
pop esi |
pop edi |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/drivers/r6040.inc |
---|
1,813 → 1,813 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; R6040 driver for KolibriOS ;; |
;; ;; |
;; based on R6040.c from linux ;; |
;; ;; |
;; Written by Asper (asper.85@mail.ru) ;; |
;; and hidnplayr (hidnplayr@gmail.com) ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************** |
; Interface |
; r6040_reset |
; r6040_probe |
; r6040_poll |
; r6040_transmit |
; |
; These functions are referenced in ethernet.inc |
; |
;******************************************************************** |
;; A few user-configurable values. |
TX_RING_SIZE equ 4 |
RX_RING_SIZE equ 4 |
; ethernet address length |
ETH_ALEN equ 6 |
ETH_HLEN equ (2 * ETH_ALEN + 2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
; system timer frequency |
HZ equ 1000 |
; max time out delay time |
W_MAX_TIMEOUT equ 0x0FFF |
;; Size of the in-memory receive ring. |
RX_BUF_LEN_IDX equ 3 ;; 0==8K, 1==16K, 2==32K, 3==64K |
RX_BUF_LEN equ (8192 << RX_BUF_LEN_IDX) |
;-; Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). |
;-TX_BUF_SIZE equ 1536 |
;-RX_BUF_SIZE equ 1536 |
;; PCI Tuning Parameters |
; Threshold is bytes transferred to chip before transmission starts. |
TX_FIFO_THRESH equ 256 ;; In bytes, rounded down to 32 byte units. |
;; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. |
RX_FIFO_THRESH equ 4 ;; Rx buffer level before first PCI xfer. |
RX_DMA_BURST equ 4 ;; Maximum PCI burst, '4' is 256 bytes |
TX_DMA_BURST equ 4 |
;; Operational parameters that usually are not changed. |
PHY1_ADDR equ 1 ;For MAC1 |
PHY2_ADDR equ 3 ;For MAC2 |
PHY_MODE equ 0x3100 ;PHY CHIP Register 0 |
PHY_CAP equ 0x01E1 ;PHY CHIP Register 4 |
;; Time in jiffies before concluding the transmitter is hung. |
TX_TIMEOUT equ ((6000*HZ)/1000) |
R6040_IO_SIZE equ 256 ; RDC MAC I/O Size |
MAX_MAC equ 2 ; MAX RDC MAC |
;************************************************************************** |
; RDC R6040 Register Definitions |
;************************************************************************** |
MCR0 equ 0x00 ;Control register 0 |
MCR1 equ 0x01 ;Control register 1 |
MAC_RST equ 0x0001 ;Reset the MAC |
MBCR equ 0x08 ;Bus control |
MT_ICR equ 0x0C ;TX interrupt control |
MR_ICR equ 0x10 ;RX interrupt control |
MTPR equ 0x14 ;TX poll command register |
MR_BSR equ 0x18 ;RX buffer size |
MR_DCR equ 0x1A ;RX descriptor control |
MLSR equ 0x1C ;Last status |
MMDIO equ 0x20 ;MDIO control register |
MDIO_WRITE equ 0x4000 ;MDIO write |
MDIO_READ equ 0x2000 ;MDIO read |
MMRD equ 0x24 ;MDIO read data register |
MMWD equ 0x28 ;MDIO write data register |
MTD_SA0 equ 0x2C ;TX descriptor start address 0 |
MTD_SA1 equ 0x30 ;TX descriptor start address 1 |
MRD_SA0 equ 0x34 ;RX descriptor start address 0 |
MRD_SA1 equ 0x38 ;RX descriptor start address 1 |
MISR equ 0x3C ;Status register |
MIER equ 0x40 ;INT enable register |
MSK_INT equ 0x0000 ;Mask off interrupts |
RX_FINISH equ 0x0001 ;RX finished |
RX_NO_DESC equ 0x0002 ;No RX descriptor available |
RX_FIFO_FULL equ 0x0004 ;RX FIFO full |
RX_EARLY equ 0x0008 ;RX early |
TX_FINISH equ 0x0010 ;TX finished |
TX_EARLY equ 0x0080 ;TX early |
EVENT_OVRFL equ 0x0100 ;Event counter overflow |
LINK_CHANGED equ 0x0200 ;PHY link changed |
ME_CISR equ 0x44 ;Event counter INT status |
ME_CIER equ 0x48 ;Event counter INT enable |
MR_CNT equ 0x50 ;Successfully received packet counter |
ME_CNT0 equ 0x52 ;Event counter 0 |
ME_CNT1 equ 0x54 ;Event counter 1 |
ME_CNT2 equ 0x56 ;Event counter 2 |
ME_CNT3 equ 0x58 ;Event counter 3 |
MT_CNT equ 0x5A ;Successfully transmit packet counter |
ME_CNT4 equ 0x5C ;Event counter 4 |
MP_CNT equ 0x5E ;Pause frame counter register |
MAR0 equ 0x60 ;Hash table 0 |
MAR1 equ 0x62 ;Hash table 1 |
MAR2 equ 0x64 ;Hash table 2 |
MAR3 equ 0x66 ;Hash table 3 |
MID_0L equ 0x68 ;Multicast address MID0 Low |
MID_0M equ 0x6A ;Multicast address MID0 Medium |
MID_0H equ 0x6C ;Multicast address MID0 High |
MID_1L equ 0x70 ;MID1 Low |
MID_1M equ 0x72 ;MID1 Medium |
MID_1H equ 0x74 ;MID1 High |
MID_2L equ 0x78 ;MID2 Low |
MID_2M equ 0x7A ;MID2 Medium |
MID_2H equ 0x7C ;MID2 High |
MID_3L equ 0x80 ;MID3 Low |
MID_3M equ 0x82 ;MID3 Medium |
MID_3H equ 0x84 ;MID3 High |
PHY_CC equ 0x88 ;PHY status change configuration register |
PHY_ST equ 0x8A ;PHY status register |
MAC_SM equ 0xAC ;MAC status machine |
MAC_ID equ 0xBE ;Identifier register |
MAX_BUF_SIZE equ 0x600 ;1536 |
MBCR_DEFAULT equ 0x012A ;MAC Bus Control Register |
MCAST_MAX equ 3 ;Max number multicast addresses to filter |
;Descriptor status |
DSC_OWNER_MAC equ 0x8000 ;MAC is the owner of this descriptor |
DSC_RX_OK equ 0x4000 ;RX was successfull |
DSC_RX_ERR equ 0x0800 ;RX PHY error |
DSC_RX_ERR_DRI equ 0x0400 ;RX dribble packet |
DSC_RX_ERR_BUF equ 0x0200 ;RX length exceeds buffer size |
DSC_RX_ERR_LONG equ 0x0100 ;RX length > maximum packet length |
DSC_RX_ERR_RUNT equ 0x0080 ;RX packet length < 64 byte |
DSC_RX_ERR_CRC equ 0x0040 ;RX CRC error |
DSC_RX_BCAST equ 0x0020 ;RX broadcast (no error) |
DSC_RX_MCAST equ 0x0010 ;RX multicast (no error) |
DSC_RX_MCH_HIT equ 0x0008 ;RX multicast hit in hash table (no error) |
DSC_RX_MIDH_HIT equ 0x0004 ;RX MID table hit (no error) |
DSC_RX_IDX_MID_MASK equ 3 ;RX mask for the index of matched MIDx |
;PHY settings |
ICPLUS_PHY_ID equ 0x0243 |
RX_INTS equ RX_FIFO_FULL or RX_NO_DESC or RX_FINISH |
TX_INTS equ TX_FINISH |
INT_MASK equ RX_INTS or TX_INTS |
r6040_txb equ (eth_data_start) |
r6040_rxb equ ((r6040_txb+(MAX_BUF_SIZE*TX_RING_SIZE)+32) and 0xfffffff0) |
r6040_tx_ring equ ((r6040_rxb+(MAX_BUF_SIZE*RX_RING_SIZE)+32) and 0xfffffff0) |
r6040_rx_ring equ ((r6040_tx_ring+(r6040_x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0) |
virtual at ((r6040_rx_ring+(r6040_x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0) |
r6040_private: |
.rx_ring dd ? |
.tx_ring dd ? |
.cur_rx dw ? |
.cur_tx dw ? |
.phy_addr dw ? |
.phy_mode dw ? |
.mcr0 dw ? |
.mcr1 dw ? |
.switch_sig dw ? |
end virtual |
virtual at 0 |
r6040_x_head: |
.status dw ? ;0-1 |
.len dw ? ;2-3 |
.buf dd ? ;4-7 |
.ndesc dd ? ;8-B |
.rev1 dd ? ;C-F |
.vbufp dd ? ;10-13 |
.vndescp dd ? ;14-17 |
.skb_ptr dd ? ;18-1B |
.rev2 dd ? ;1C-1F |
.sizeof: |
end virtual |
; Read a word data from PHY Chip |
proc r6040_phy_read stdcall, phy_addr:dword, reg:dword |
push ecx edx |
mov eax, [phy_addr] |
shl eax, 8 |
add eax, [reg] |
add eax, MDIO_READ |
mov edx, [io_addr] |
add edx, MMDIO |
out dx, ax |
;Wait for the read bit to be cleared. |
mov ecx, 2048 ;limit |
xor eax, eax |
.read: |
in ax, dx |
test ax, MDIO_READ |
jz @f |
dec ecx |
test ecx, ecx |
jnz .read |
@@: |
mov edx, [io_addr] |
add edx, MMRD |
in ax, dx |
and eax, 0xFFFF |
pop edx ecx |
ret |
endp |
; Write a word data to PHY Chip |
proc r6040_phy_write stdcall, phy_addr:dword, reg:dword, val:dword |
push eax ecx edx |
mov eax, [val] |
mov edx, [io_addr] |
add edx, MMWD |
out dx, ax |
;Write the command to the MDIO bus |
mov eax, [phy_addr] |
shl eax, 8 |
add eax, [reg] |
add eax, MDIO_WRITE |
mov edx, [io_addr] |
add edx, MMDIO |
out dx, ax |
;Wait for the write bit to be cleared. |
mov ecx, 2048 ;limit |
xor eax, eax |
.write: |
in ax, dx |
test ax, MDIO_WRITE |
jz @f |
dec ecx |
test ecx, ecx |
jnz .write |
@@: |
pop edx ecx eax |
ret |
endp |
macro r6040_mdio_write reg, val { |
stdcall r6040_phy_read, [io_addr], [r6040_private.phy_addr], reg |
} |
macro r6040_mdio_write reg, val { |
stdcall r6040_phy_write, [io_addr], [r6040_private.phy_addr], reg, val |
} |
proc r6040_init_ring_desc stdcall, desc_ring:dword, size:dword |
push eax ecx esi |
mov ecx, [size] |
test ecx, ecx |
jz .out |
mov esi, [desc_ring] |
mov eax, esi |
.next_desc: |
add eax, r6040_x_head.sizeof - OS_BASE |
mov [esi+r6040_x_head.ndesc], eax |
add eax, OS_BASE |
mov [esi+r6040_x_head.vndescp], eax |
mov esi, eax |
dec ecx |
jnz .next_desc |
sub esi, r6040_x_head.sizeof |
mov eax, [desc_ring] |
mov [esi+r6040_x_head.vndescp], eax |
sub eax, OS_BASE |
mov [esi+r6040_x_head.ndesc], eax |
.out: |
pop esi ecx eax |
ret |
endp |
r6040_init_rxbufs: |
stdcall r6040_init_ring_desc, r6040_rx_ring, RX_RING_SIZE |
; Allocate skbs for the rx descriptors |
mov esi, r6040_rx_ring |
mov ebx, r6040_rxb |
mov ecx, RX_RING_SIZE |
mov eax, r6040_rx_ring |
.next_desc: |
mov [esi+r6040_x_head.skb_ptr], ebx |
mov [esi+r6040_x_head.buf], ebx |
sub [esi+r6040_x_head.buf], OS_BASE |
mov [esi+r6040_x_head.status], DSC_OWNER_MAC |
mov eax, [esi+r6040_x_head.vndescp] |
mov esi, eax |
add ebx, MAX_BUF_SIZE |
dec ecx |
jnz .next_desc |
xor eax, eax |
.out: |
ret |
r6040_probe: |
DEBUGF 1, "Probing r6040\n" |
call adjust_pci_device |
; If PHY status change register is still set to zero |
; it means the bootloader didn't initialize it |
mov edx, [io_addr] |
add edx, PHY_CC |
in ax, dx |
test ax, ax |
jnz @f |
mov eax, 0x9F07 |
out dx, ax |
@@: |
; Set MAC address |
mov ecx, 3 |
mov edi, node_addr |
mov edx, [io_addr] |
add edx, MID_0L |
.mac: |
in ax, dx |
stosw |
add edx, 2 |
dec ecx |
jnz .mac |
; Some bootloaders/BIOSes do not initialize |
; MAC address, warn about that |
and eax, 0xFF |
or eax, [node_addr] |
test eax, eax |
jnz @f |
DEBUGF 1, "K : MAC address not initialized\n" ;, generating random" |
;Asper: Add here generate function call! |
; Temporary workaround: init by constant adress |
mov dword [node_addr], 0x00006000 |
mov word [node_addr+4], 0x0001 |
@@: |
; Init RDC private data |
mov [r6040_private.mcr0], 0x1002 |
;mov [r6040_private.phy_addr], 1 ; Asper: Only one network card is supported now. |
mov [r6040_private.switch_sig], 0 |
; Check the vendor ID on the PHY, if 0xFFFF assume none attached |
stdcall r6040_phy_read, 1, 2 |
cmp ax, 0xFFFF |
jne @f |
DEBUGF 1, "K : Failed to detect an attached PHY\n" ;, generating random" |
mov eax, -1 |
ret |
@@: |
; Set MAC address |
call r6040_mac_address |
; Initialize and alloc RX/TX buffers |
stdcall r6040_init_ring_desc, r6040_tx_ring, TX_RING_SIZE |
call r6040_init_rxbufs ;r6040_alloc_rxbufs |
test eax, eax |
jnz .out |
; Read the PHY ID |
mov [r6040_private.phy_mode], 0x8000 |
stdcall r6040_phy_read, 0, 2 |
mov [r6040_private.switch_sig], ax |
cmp ax, ICPLUS_PHY_ID |
jne @f |
stdcall r6040_phy_write, 29, 31, 0x175C ; Enable registers |
jmp .phy_readen |
@@: |
; PHY Mode Check |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_write, eax, 4, PHY_CAP |
stdcall r6040_phy_write, eax, 0, PHY_MODE |
; if PHY_MODE = 0x3100 |
call r6040_phy_mode_chk |
mov [r6040_private.phy_mode], ax |
jmp .phy_readen |
; end if |
; if not (PHY_MODE and 0x0100) |
mov [r6040_private.phy_mode], 0 |
; end if |
.phy_readen: |
; Set duplex mode |
mov ax, [r6040_private.phy_mode] |
or [r6040_private.mcr0], ax |
; improve performance (by RDC guys) |
stdcall r6040_phy_read, 30, 17 |
or ax, 0x4000 |
stdcall r6040_phy_write, 30, 17, eax |
stdcall r6040_phy_read, 30, 17 |
xor ax, -1 |
or ax, 0x2000 |
xor ax, -1 |
stdcall r6040_phy_write, 30, 17, eax |
stdcall r6040_phy_write, 0, 19, 0x0000 |
stdcall r6040_phy_write, 0, 30, 0x01F0 |
; Initialize all Mac registers |
call r6040_reset |
xor eax, eax |
.out: |
ret |
align 4 |
r6040_reset: |
DEBUGF 1, "Resetting r6040\n" |
push eax ecx edx |
; Mask off Interrupt |
mov eax, MSK_INT |
mov edx, [io_addr] |
add edx, MIER |
out dx, ax |
;Reset RDC MAC |
mov eax, MAC_RST |
mov edx, [io_addr] |
add edx, MCR1 |
out dx, ax |
mov ecx, 2048 ;limit |
.read: |
in ax, dx |
test ax, 0x1 |
jnz @f |
dec ecx |
test ecx, ecx |
jnz .read |
@@: |
;Reset internal state machine |
mov ax, 2 |
mov edx, [io_addr] |
add edx, MAC_SM |
out dx, ax |
xor ax, ax |
out dx, ax |
mov esi, 5 |
call delay_ms |
;MAC Bus Control Register |
mov ax, MBCR_DEFAULT |
mov edx, [io_addr] |
add edx, MBCR |
out dx, ax |
;Buffer Size Register |
mov ax, MAX_BUF_SIZE |
mov edx, [io_addr] |
add edx, MR_BSR |
out dx, ax |
;Write TX ring start address |
mov eax, r6040_tx_ring - OS_BASE ;Asper: Maybe we can just write dword? Hidnplayr: better use word, as described in datasheet. |
mov edx, [io_addr] |
add edx, MTD_SA0 |
out dx, ax |
shr eax, 16 |
add edx, MTD_SA1 - MTD_SA0 |
out dx, ax |
;Write RX ring start address |
mov eax, r6040_rx_ring - OS_BASE ;Asper: Maybe we can just write dword? |
mov edx, [io_addr] |
add edx, MRD_SA0 |
out dx, ax |
shr eax, 16 |
add edx, MRD_SA1 - MRD_SA0 |
out dx, ax |
;Set interrupt waiting time and packet numbers |
xor ax, ax |
mov edx, [io_addr] |
add edx, MT_ICR |
out dx, ax |
;Asper: ~ Disable ints ;Enable interrupts |
;mov ax, MSK_INT ;INT_MASK ;Asper ~ |
;mov edx, [io_addr] |
;add edx, MIER |
;out dx, ax |
;Enable TX and RX |
mov ax, [r6040_private.mcr0] |
or ax, 0x0002 |
mov edx, [io_addr] |
out dx, ax |
;Let TX poll the descriptors |
;we may got called by r6040_tx_timeout which has left |
;some unset tx buffers |
xor ax, ax |
inc ax |
mov edx, [io_addr] |
add edx, MTPR |
out dx, ax |
pop edx ecx eax |
DEBUGF 1, "reset ok!\n" |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
proc r6040_tx_timeout |
push eax edx |
;... |
inc [stats.tx_errors] |
;Reset MAC and re-init all registers |
call r6040_init_mac_regs |
pop edx eax |
ret |
endp |
proc r6040_get_stats |
push eax edx |
mov edx, [io_addr] |
add edx, ME_CNT1 |
in al, dx |
add [stats.rx_crc_errors], al |
mov edx, [io_addr] |
add edx, ME_CNT0 |
in al, dx |
add [stats.multicast], al |
pop edx eax |
ret |
endp |
;... |
proc r6040_phy_mode_chk |
push ebx |
;PHY Link Status Check |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 1 |
test eax, 0x4 |
jnz @f |
mov eax, 0x8000 ;Link Failed, full duplex |
@@: |
;PHY Chip Auto-Negotiation Status |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 1 |
test eax, 0x0020 |
jz .force_mode |
;Auto Negotuiation Mode |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 5 |
mov ebx, eax |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 4 |
and eax, ebx |
test eax, 0x140 |
jz .ret_0 |
jmp .ret_0x8000 |
.force_mode: |
;Force Mode |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 0 |
test eax, 0x100 |
jz .ret_0 |
.ret_0x8000: |
mov eax, 0x8000 |
pop ebx |
ret |
.ret_0: |
xor eax, eax |
pop ebx |
ret |
endp |
;*************************************************************************** |
; Function |
; r6040_rx |
; Description |
; polls card to see if there is a packet waiting |
; |
; Currently only supports one descriptor per packet, if packet is fragmented |
; between multiple descriptors you will lose part of the packet |
;*************************************************************************** |
r6040_poll: |
push ebx ecx esi edi |
xor eax, eax |
mov [eth_rx_data_len], ax |
movzx eax, [r6040_private.cur_rx] |
mov ebx, eax |
shl ebx, 5 |
mov cx, [ebx+r6040_rx_ring+r6040_x_head.status] ; Read the descriptor status |
test cx, DSC_OWNER_MAC |
jnz .out |
test cx, DSC_RX_ERR ; Global error status set |
jz .no_dsc_rx_err |
;... |
jmp .out |
.no_dsc_rx_err: |
; Packet successfully received |
movzx ecx, [ebx+r6040_rx_ring+r6040_x_head.len] |
and ecx, 0xFFF |
sub ecx, 4 ; Do not count the CRC |
mov [eth_rx_data_len], cx |
mov esi, [ebx+r6040_rx_ring+r6040_x_head.skb_ptr] |
push ecx |
shr ecx, 2 |
mov edi, Ether_buffer |
cld |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
or [ebx+r6040_rx_ring+r6040_x_head.status], DSC_OWNER_MAC |
inc [r6040_private.cur_rx] |
and [r6040_private.cur_rx], RX_RING_SIZE-1 |
xor eax, eax |
.out: |
pop edi esi ecx ebx |
ret |
;*************************************************************************** |
; Function |
; r6040_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
; |
;*************************************************************************** |
r6040_transmit: |
cmp ecx, MAX_BUF_SIZE |
jg .out ; packet is too long |
push edi esi ebx ecx |
movzx eax, [r6040_private.cur_tx] |
shl eax, 5 |
; DEBUGF 1,"R6040: TX buffer status: 0x%x, eax=%u\n", [eax + r6040_tx_ring + r6040_x_head.status]:4, eax |
test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 ; check if buffer is available |
jz .l3 |
push ecx esi |
mov ecx, [timer_ticks] |
add ecx, 100 |
.l2: |
test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 |
jz .l5 |
cmp ecx, [timer_ticks] |
jb .l4 |
mov esi, 10 |
call delay_ms |
jmp .l2 |
.l4: |
pop esi ecx |
DEBUGF 1,"R6040: Send timeout\n" |
jmp .out |
.l5: |
pop esi ecx |
.l3: |
push eax |
mov esi, edi |
; point to the current tx buffer |
movzx edi, [r6040_private.cur_tx] |
imul edi, MAX_BUF_SIZE |
add edi, r6040_txb |
lea eax, [edi - OS_BASE] ; real buffer address in eax |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi, node_addr |
movsd |
movsw |
; copy packet type |
mov [edi], bx |
add edi, 2 |
mov esi, [esp+8+4] |
mov ecx, [esp+4] |
; copy the packet data |
push ecx |
shr ecx,2 |
rep movsd |
pop ecx |
and ecx,3 |
rep movsb |
pop edi |
mov ecx, [esp] |
add ecx, ETH_HLEN |
cmp cx, ETH_ZLEN |
jae @f |
mov cx, ETH_ZLEN |
@@: |
mov [r6040_tx_ring + edi + r6040_x_head.len], cx |
mov [r6040_tx_ring + edi + r6040_x_head.buf], eax |
mov [r6040_tx_ring + edi + r6040_x_head.status], 0x8000 |
; Trigger the MAC to check the TX descriptor |
mov ax, 0x01 |
mov edx, [io_addr] |
add edx, MTPR |
out dx, ax |
inc [r6040_private.cur_tx] |
and [r6040_private.cur_tx], TX_RING_SIZE-1 |
xor eax, eax |
pop ecx ebx esi edi |
.out: |
ret |
r6040_mac_address: |
push eax ecx edx esi edi |
; MAC operation register |
mov ax, 1 |
mov edx, [io_addr] |
add edx, MCR1 |
out dx, ax |
; Reset MAC |
mov ax, 2 |
mov edx, [io_addr] |
add edx, MAC_SM |
out dx, ax |
; Reset internal state machine |
xor ax, ax |
out dx, ax |
mov esi, 5 |
call delay_ms |
; Restore MAC Address |
mov ecx, 3 |
mov edi, node_addr |
mov edx, [io_addr] |
add edx, MID_0L |
.mac: |
in ax, dx |
stosw |
add edx, 2 |
dec ecx |
jnz .mac |
pop edi esi edx ecx eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; R6040 driver for KolibriOS ;; |
;; ;; |
;; based on R6040.c from linux ;; |
;; ;; |
;; Written by Asper (asper.85@mail.ru) ;; |
;; and hidnplayr (hidnplayr@gmail.com) ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************** |
; Interface |
; r6040_reset |
; r6040_probe |
; r6040_poll |
; r6040_transmit |
; |
; These functions are referenced in ethernet.inc |
; |
;******************************************************************** |
;; A few user-configurable values. |
TX_RING_SIZE equ 4 |
RX_RING_SIZE equ 4 |
; ethernet address length |
ETH_ALEN equ 6 |
ETH_HLEN equ (2 * ETH_ALEN + 2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
; system timer frequency |
HZ equ 1000 |
; max time out delay time |
W_MAX_TIMEOUT equ 0x0FFF |
;; Size of the in-memory receive ring. |
RX_BUF_LEN_IDX equ 3 ;; 0==8K, 1==16K, 2==32K, 3==64K |
RX_BUF_LEN equ (8192 << RX_BUF_LEN_IDX) |
;-; Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). |
;-TX_BUF_SIZE equ 1536 |
;-RX_BUF_SIZE equ 1536 |
;; PCI Tuning Parameters |
; Threshold is bytes transferred to chip before transmission starts. |
TX_FIFO_THRESH equ 256 ;; In bytes, rounded down to 32 byte units. |
;; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. |
RX_FIFO_THRESH equ 4 ;; Rx buffer level before first PCI xfer. |
RX_DMA_BURST equ 4 ;; Maximum PCI burst, '4' is 256 bytes |
TX_DMA_BURST equ 4 |
;; Operational parameters that usually are not changed. |
PHY1_ADDR equ 1 ;For MAC1 |
PHY2_ADDR equ 3 ;For MAC2 |
PHY_MODE equ 0x3100 ;PHY CHIP Register 0 |
PHY_CAP equ 0x01E1 ;PHY CHIP Register 4 |
;; Time in jiffies before concluding the transmitter is hung. |
TX_TIMEOUT equ ((6000*HZ)/1000) |
R6040_IO_SIZE equ 256 ; RDC MAC I/O Size |
MAX_MAC equ 2 ; MAX RDC MAC |
;************************************************************************** |
; RDC R6040 Register Definitions |
;************************************************************************** |
MCR0 equ 0x00 ;Control register 0 |
MCR1 equ 0x01 ;Control register 1 |
MAC_RST equ 0x0001 ;Reset the MAC |
MBCR equ 0x08 ;Bus control |
MT_ICR equ 0x0C ;TX interrupt control |
MR_ICR equ 0x10 ;RX interrupt control |
MTPR equ 0x14 ;TX poll command register |
MR_BSR equ 0x18 ;RX buffer size |
MR_DCR equ 0x1A ;RX descriptor control |
MLSR equ 0x1C ;Last status |
MMDIO equ 0x20 ;MDIO control register |
MDIO_WRITE equ 0x4000 ;MDIO write |
MDIO_READ equ 0x2000 ;MDIO read |
MMRD equ 0x24 ;MDIO read data register |
MMWD equ 0x28 ;MDIO write data register |
MTD_SA0 equ 0x2C ;TX descriptor start address 0 |
MTD_SA1 equ 0x30 ;TX descriptor start address 1 |
MRD_SA0 equ 0x34 ;RX descriptor start address 0 |
MRD_SA1 equ 0x38 ;RX descriptor start address 1 |
MISR equ 0x3C ;Status register |
MIER equ 0x40 ;INT enable register |
MSK_INT equ 0x0000 ;Mask off interrupts |
RX_FINISH equ 0x0001 ;RX finished |
RX_NO_DESC equ 0x0002 ;No RX descriptor available |
RX_FIFO_FULL equ 0x0004 ;RX FIFO full |
RX_EARLY equ 0x0008 ;RX early |
TX_FINISH equ 0x0010 ;TX finished |
TX_EARLY equ 0x0080 ;TX early |
EVENT_OVRFL equ 0x0100 ;Event counter overflow |
LINK_CHANGED equ 0x0200 ;PHY link changed |
ME_CISR equ 0x44 ;Event counter INT status |
ME_CIER equ 0x48 ;Event counter INT enable |
MR_CNT equ 0x50 ;Successfully received packet counter |
ME_CNT0 equ 0x52 ;Event counter 0 |
ME_CNT1 equ 0x54 ;Event counter 1 |
ME_CNT2 equ 0x56 ;Event counter 2 |
ME_CNT3 equ 0x58 ;Event counter 3 |
MT_CNT equ 0x5A ;Successfully transmit packet counter |
ME_CNT4 equ 0x5C ;Event counter 4 |
MP_CNT equ 0x5E ;Pause frame counter register |
MAR0 equ 0x60 ;Hash table 0 |
MAR1 equ 0x62 ;Hash table 1 |
MAR2 equ 0x64 ;Hash table 2 |
MAR3 equ 0x66 ;Hash table 3 |
MID_0L equ 0x68 ;Multicast address MID0 Low |
MID_0M equ 0x6A ;Multicast address MID0 Medium |
MID_0H equ 0x6C ;Multicast address MID0 High |
MID_1L equ 0x70 ;MID1 Low |
MID_1M equ 0x72 ;MID1 Medium |
MID_1H equ 0x74 ;MID1 High |
MID_2L equ 0x78 ;MID2 Low |
MID_2M equ 0x7A ;MID2 Medium |
MID_2H equ 0x7C ;MID2 High |
MID_3L equ 0x80 ;MID3 Low |
MID_3M equ 0x82 ;MID3 Medium |
MID_3H equ 0x84 ;MID3 High |
PHY_CC equ 0x88 ;PHY status change configuration register |
PHY_ST equ 0x8A ;PHY status register |
MAC_SM equ 0xAC ;MAC status machine |
MAC_ID equ 0xBE ;Identifier register |
MAX_BUF_SIZE equ 0x600 ;1536 |
MBCR_DEFAULT equ 0x012A ;MAC Bus Control Register |
MCAST_MAX equ 3 ;Max number multicast addresses to filter |
;Descriptor status |
DSC_OWNER_MAC equ 0x8000 ;MAC is the owner of this descriptor |
DSC_RX_OK equ 0x4000 ;RX was successfull |
DSC_RX_ERR equ 0x0800 ;RX PHY error |
DSC_RX_ERR_DRI equ 0x0400 ;RX dribble packet |
DSC_RX_ERR_BUF equ 0x0200 ;RX length exceeds buffer size |
DSC_RX_ERR_LONG equ 0x0100 ;RX length > maximum packet length |
DSC_RX_ERR_RUNT equ 0x0080 ;RX packet length < 64 byte |
DSC_RX_ERR_CRC equ 0x0040 ;RX CRC error |
DSC_RX_BCAST equ 0x0020 ;RX broadcast (no error) |
DSC_RX_MCAST equ 0x0010 ;RX multicast (no error) |
DSC_RX_MCH_HIT equ 0x0008 ;RX multicast hit in hash table (no error) |
DSC_RX_MIDH_HIT equ 0x0004 ;RX MID table hit (no error) |
DSC_RX_IDX_MID_MASK equ 3 ;RX mask for the index of matched MIDx |
;PHY settings |
ICPLUS_PHY_ID equ 0x0243 |
RX_INTS equ RX_FIFO_FULL or RX_NO_DESC or RX_FINISH |
TX_INTS equ TX_FINISH |
INT_MASK equ RX_INTS or TX_INTS |
r6040_txb equ (eth_data_start) |
r6040_rxb equ ((r6040_txb+(MAX_BUF_SIZE*TX_RING_SIZE)+32) and 0xfffffff0) |
r6040_tx_ring equ ((r6040_rxb+(MAX_BUF_SIZE*RX_RING_SIZE)+32) and 0xfffffff0) |
r6040_rx_ring equ ((r6040_tx_ring+(r6040_x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0) |
virtual at ((r6040_rx_ring+(r6040_x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0) |
r6040_private: |
.rx_ring dd ? |
.tx_ring dd ? |
.cur_rx dw ? |
.cur_tx dw ? |
.phy_addr dw ? |
.phy_mode dw ? |
.mcr0 dw ? |
.mcr1 dw ? |
.switch_sig dw ? |
end virtual |
virtual at 0 |
r6040_x_head: |
.status dw ? ;0-1 |
.len dw ? ;2-3 |
.buf dd ? ;4-7 |
.ndesc dd ? ;8-B |
.rev1 dd ? ;C-F |
.vbufp dd ? ;10-13 |
.vndescp dd ? ;14-17 |
.skb_ptr dd ? ;18-1B |
.rev2 dd ? ;1C-1F |
.sizeof: |
end virtual |
; Read a word data from PHY Chip |
proc r6040_phy_read stdcall, phy_addr:dword, reg:dword |
push ecx edx |
mov eax, [phy_addr] |
shl eax, 8 |
add eax, [reg] |
add eax, MDIO_READ |
mov edx, [io_addr] |
add edx, MMDIO |
out dx, ax |
;Wait for the read bit to be cleared. |
mov ecx, 2048 ;limit |
xor eax, eax |
.read: |
in ax, dx |
test ax, MDIO_READ |
jz @f |
dec ecx |
test ecx, ecx |
jnz .read |
@@: |
mov edx, [io_addr] |
add edx, MMRD |
in ax, dx |
and eax, 0xFFFF |
pop edx ecx |
ret |
endp |
; Write a word data to PHY Chip |
proc r6040_phy_write stdcall, phy_addr:dword, reg:dword, val:dword |
push eax ecx edx |
mov eax, [val] |
mov edx, [io_addr] |
add edx, MMWD |
out dx, ax |
;Write the command to the MDIO bus |
mov eax, [phy_addr] |
shl eax, 8 |
add eax, [reg] |
add eax, MDIO_WRITE |
mov edx, [io_addr] |
add edx, MMDIO |
out dx, ax |
;Wait for the write bit to be cleared. |
mov ecx, 2048 ;limit |
xor eax, eax |
.write: |
in ax, dx |
test ax, MDIO_WRITE |
jz @f |
dec ecx |
test ecx, ecx |
jnz .write |
@@: |
pop edx ecx eax |
ret |
endp |
macro r6040_mdio_write reg, val { |
stdcall r6040_phy_read, [io_addr], [r6040_private.phy_addr], reg |
} |
macro r6040_mdio_write reg, val { |
stdcall r6040_phy_write, [io_addr], [r6040_private.phy_addr], reg, val |
} |
proc r6040_init_ring_desc stdcall, desc_ring:dword, size:dword |
push eax ecx esi |
mov ecx, [size] |
test ecx, ecx |
jz .out |
mov esi, [desc_ring] |
mov eax, esi |
.next_desc: |
add eax, r6040_x_head.sizeof - OS_BASE |
mov [esi+r6040_x_head.ndesc], eax |
add eax, OS_BASE |
mov [esi+r6040_x_head.vndescp], eax |
mov esi, eax |
dec ecx |
jnz .next_desc |
sub esi, r6040_x_head.sizeof |
mov eax, [desc_ring] |
mov [esi+r6040_x_head.vndescp], eax |
sub eax, OS_BASE |
mov [esi+r6040_x_head.ndesc], eax |
.out: |
pop esi ecx eax |
ret |
endp |
r6040_init_rxbufs: |
stdcall r6040_init_ring_desc, r6040_rx_ring, RX_RING_SIZE |
; Allocate skbs for the rx descriptors |
mov esi, r6040_rx_ring |
mov ebx, r6040_rxb |
mov ecx, RX_RING_SIZE |
mov eax, r6040_rx_ring |
.next_desc: |
mov [esi+r6040_x_head.skb_ptr], ebx |
mov [esi+r6040_x_head.buf], ebx |
sub [esi+r6040_x_head.buf], OS_BASE |
mov [esi+r6040_x_head.status], DSC_OWNER_MAC |
mov eax, [esi+r6040_x_head.vndescp] |
mov esi, eax |
add ebx, MAX_BUF_SIZE |
dec ecx |
jnz .next_desc |
xor eax, eax |
.out: |
ret |
r6040_probe: |
DEBUGF 1, "Probing r6040\n" |
call adjust_pci_device |
; If PHY status change register is still set to zero |
; it means the bootloader didn't initialize it |
mov edx, [io_addr] |
add edx, PHY_CC |
in ax, dx |
test ax, ax |
jnz @f |
mov eax, 0x9F07 |
out dx, ax |
@@: |
; Set MAC address |
mov ecx, 3 |
mov edi, node_addr |
mov edx, [io_addr] |
add edx, MID_0L |
.mac: |
in ax, dx |
stosw |
add edx, 2 |
dec ecx |
jnz .mac |
; Some bootloaders/BIOSes do not initialize |
; MAC address, warn about that |
and eax, 0xFF |
or eax, [node_addr] |
test eax, eax |
jnz @f |
DEBUGF 1, "K : MAC address not initialized\n" ;, generating random" |
;Asper: Add here generate function call! |
; Temporary workaround: init by constant adress |
mov dword [node_addr], 0x00006000 |
mov word [node_addr+4], 0x0001 |
@@: |
; Init RDC private data |
mov [r6040_private.mcr0], 0x1002 |
;mov [r6040_private.phy_addr], 1 ; Asper: Only one network card is supported now. |
mov [r6040_private.switch_sig], 0 |
; Check the vendor ID on the PHY, if 0xFFFF assume none attached |
stdcall r6040_phy_read, 1, 2 |
cmp ax, 0xFFFF |
jne @f |
DEBUGF 1, "K : Failed to detect an attached PHY\n" ;, generating random" |
mov eax, -1 |
ret |
@@: |
; Set MAC address |
call r6040_mac_address |
; Initialize and alloc RX/TX buffers |
stdcall r6040_init_ring_desc, r6040_tx_ring, TX_RING_SIZE |
call r6040_init_rxbufs ;r6040_alloc_rxbufs |
test eax, eax |
jnz .out |
; Read the PHY ID |
mov [r6040_private.phy_mode], 0x8000 |
stdcall r6040_phy_read, 0, 2 |
mov [r6040_private.switch_sig], ax |
cmp ax, ICPLUS_PHY_ID |
jne @f |
stdcall r6040_phy_write, 29, 31, 0x175C ; Enable registers |
jmp .phy_readen |
@@: |
; PHY Mode Check |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_write, eax, 4, PHY_CAP |
stdcall r6040_phy_write, eax, 0, PHY_MODE |
; if PHY_MODE = 0x3100 |
call r6040_phy_mode_chk |
mov [r6040_private.phy_mode], ax |
jmp .phy_readen |
; end if |
; if not (PHY_MODE and 0x0100) |
mov [r6040_private.phy_mode], 0 |
; end if |
.phy_readen: |
; Set duplex mode |
mov ax, [r6040_private.phy_mode] |
or [r6040_private.mcr0], ax |
; improve performance (by RDC guys) |
stdcall r6040_phy_read, 30, 17 |
or ax, 0x4000 |
stdcall r6040_phy_write, 30, 17, eax |
stdcall r6040_phy_read, 30, 17 |
xor ax, -1 |
or ax, 0x2000 |
xor ax, -1 |
stdcall r6040_phy_write, 30, 17, eax |
stdcall r6040_phy_write, 0, 19, 0x0000 |
stdcall r6040_phy_write, 0, 30, 0x01F0 |
; Initialize all Mac registers |
call r6040_reset |
xor eax, eax |
.out: |
ret |
align 4 |
r6040_reset: |
DEBUGF 1, "Resetting r6040\n" |
push eax ecx edx |
; Mask off Interrupt |
mov eax, MSK_INT |
mov edx, [io_addr] |
add edx, MIER |
out dx, ax |
;Reset RDC MAC |
mov eax, MAC_RST |
mov edx, [io_addr] |
add edx, MCR1 |
out dx, ax |
mov ecx, 2048 ;limit |
.read: |
in ax, dx |
test ax, 0x1 |
jnz @f |
dec ecx |
test ecx, ecx |
jnz .read |
@@: |
;Reset internal state machine |
mov ax, 2 |
mov edx, [io_addr] |
add edx, MAC_SM |
out dx, ax |
xor ax, ax |
out dx, ax |
mov esi, 5 |
call delay_ms |
;MAC Bus Control Register |
mov ax, MBCR_DEFAULT |
mov edx, [io_addr] |
add edx, MBCR |
out dx, ax |
;Buffer Size Register |
mov ax, MAX_BUF_SIZE |
mov edx, [io_addr] |
add edx, MR_BSR |
out dx, ax |
;Write TX ring start address |
mov eax, r6040_tx_ring - OS_BASE ;Asper: Maybe we can just write dword? Hidnplayr: better use word, as described in datasheet. |
mov edx, [io_addr] |
add edx, MTD_SA0 |
out dx, ax |
shr eax, 16 |
add edx, MTD_SA1 - MTD_SA0 |
out dx, ax |
;Write RX ring start address |
mov eax, r6040_rx_ring - OS_BASE ;Asper: Maybe we can just write dword? |
mov edx, [io_addr] |
add edx, MRD_SA0 |
out dx, ax |
shr eax, 16 |
add edx, MRD_SA1 - MRD_SA0 |
out dx, ax |
;Set interrupt waiting time and packet numbers |
xor ax, ax |
mov edx, [io_addr] |
add edx, MT_ICR |
out dx, ax |
;Asper: ~ Disable ints ;Enable interrupts |
;mov ax, MSK_INT ;INT_MASK ;Asper ~ |
;mov edx, [io_addr] |
;add edx, MIER |
;out dx, ax |
;Enable TX and RX |
mov ax, [r6040_private.mcr0] |
or ax, 0x0002 |
mov edx, [io_addr] |
out dx, ax |
;Let TX poll the descriptors |
;we may got called by r6040_tx_timeout which has left |
;some unset tx buffers |
xor ax, ax |
inc ax |
mov edx, [io_addr] |
add edx, MTPR |
out dx, ax |
pop edx ecx eax |
DEBUGF 1, "reset ok!\n" |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
proc r6040_tx_timeout |
push eax edx |
;... |
inc [stats.tx_errors] |
;Reset MAC and re-init all registers |
call r6040_init_mac_regs |
pop edx eax |
ret |
endp |
proc r6040_get_stats |
push eax edx |
mov edx, [io_addr] |
add edx, ME_CNT1 |
in al, dx |
add [stats.rx_crc_errors], al |
mov edx, [io_addr] |
add edx, ME_CNT0 |
in al, dx |
add [stats.multicast], al |
pop edx eax |
ret |
endp |
;... |
proc r6040_phy_mode_chk |
push ebx |
;PHY Link Status Check |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 1 |
test eax, 0x4 |
jnz @f |
mov eax, 0x8000 ;Link Failed, full duplex |
@@: |
;PHY Chip Auto-Negotiation Status |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 1 |
test eax, 0x0020 |
jz .force_mode |
;Auto Negotuiation Mode |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 5 |
mov ebx, eax |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 4 |
and eax, ebx |
test eax, 0x140 |
jz .ret_0 |
jmp .ret_0x8000 |
.force_mode: |
;Force Mode |
movzx eax, [r6040_private.phy_addr] |
stdcall r6040_phy_read, eax, 0 |
test eax, 0x100 |
jz .ret_0 |
.ret_0x8000: |
mov eax, 0x8000 |
pop ebx |
ret |
.ret_0: |
xor eax, eax |
pop ebx |
ret |
endp |
;*************************************************************************** |
; Function |
; r6040_rx |
; Description |
; polls card to see if there is a packet waiting |
; |
; Currently only supports one descriptor per packet, if packet is fragmented |
; between multiple descriptors you will lose part of the packet |
;*************************************************************************** |
r6040_poll: |
push ebx ecx esi edi |
xor eax, eax |
mov [eth_rx_data_len], ax |
movzx eax, [r6040_private.cur_rx] |
mov ebx, eax |
shl ebx, 5 |
mov cx, [ebx+r6040_rx_ring+r6040_x_head.status] ; Read the descriptor status |
test cx, DSC_OWNER_MAC |
jnz .out |
test cx, DSC_RX_ERR ; Global error status set |
jz .no_dsc_rx_err |
;... |
jmp .out |
.no_dsc_rx_err: |
; Packet successfully received |
movzx ecx, [ebx+r6040_rx_ring+r6040_x_head.len] |
and ecx, 0xFFF |
sub ecx, 4 ; Do not count the CRC |
mov [eth_rx_data_len], cx |
mov esi, [ebx+r6040_rx_ring+r6040_x_head.skb_ptr] |
push ecx |
shr ecx, 2 |
mov edi, Ether_buffer |
cld |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
or [ebx+r6040_rx_ring+r6040_x_head.status], DSC_OWNER_MAC |
inc [r6040_private.cur_rx] |
and [r6040_private.cur_rx], RX_RING_SIZE-1 |
xor eax, eax |
.out: |
pop edi esi ecx ebx |
ret |
;*************************************************************************** |
; Function |
; r6040_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
; |
;*************************************************************************** |
r6040_transmit: |
cmp ecx, MAX_BUF_SIZE |
jg .out ; packet is too long |
push edi esi ebx ecx |
movzx eax, [r6040_private.cur_tx] |
shl eax, 5 |
; DEBUGF 1,"R6040: TX buffer status: 0x%x, eax=%u\n", [eax + r6040_tx_ring + r6040_x_head.status]:4, eax |
test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 ; check if buffer is available |
jz .l3 |
push ecx esi |
mov ecx, [timer_ticks] |
add ecx, 100 |
.l2: |
test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 |
jz .l5 |
cmp ecx, [timer_ticks] |
jb .l4 |
mov esi, 10 |
call delay_ms |
jmp .l2 |
.l4: |
pop esi ecx |
DEBUGF 1,"R6040: Send timeout\n" |
jmp .out |
.l5: |
pop esi ecx |
.l3: |
push eax |
mov esi, edi |
; point to the current tx buffer |
movzx edi, [r6040_private.cur_tx] |
imul edi, MAX_BUF_SIZE |
add edi, r6040_txb |
lea eax, [edi - OS_BASE] ; real buffer address in eax |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi, node_addr |
movsd |
movsw |
; copy packet type |
mov [edi], bx |
add edi, 2 |
mov esi, [esp+8+4] |
mov ecx, [esp+4] |
; copy the packet data |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
pop edi |
mov ecx, [esp] |
add ecx, ETH_HLEN |
cmp cx, ETH_ZLEN |
jae @f |
mov cx, ETH_ZLEN |
@@: |
mov [r6040_tx_ring + edi + r6040_x_head.len], cx |
mov [r6040_tx_ring + edi + r6040_x_head.buf], eax |
mov [r6040_tx_ring + edi + r6040_x_head.status], 0x8000 |
; Trigger the MAC to check the TX descriptor |
mov ax, 0x01 |
mov edx, [io_addr] |
add edx, MTPR |
out dx, ax |
inc [r6040_private.cur_tx] |
and [r6040_private.cur_tx], TX_RING_SIZE-1 |
xor eax, eax |
pop ecx ebx esi edi |
.out: |
ret |
r6040_mac_address: |
push eax ecx edx esi edi |
; MAC operation register |
mov ax, 1 |
mov edx, [io_addr] |
add edx, MCR1 |
out dx, ax |
; Reset MAC |
mov ax, 2 |
mov edx, [io_addr] |
add edx, MAC_SM |
out dx, ax |
; Reset internal state machine |
xor ax, ax |
out dx, ax |
mov esi, 5 |
call delay_ms |
; Restore MAC Address |
mov ecx, 3 |
mov edi, node_addr |
mov edx, [io_addr] |
add edx, MID_0L |
.mac: |
in ax, dx |
stosw |
add edx, 2 |
dec ecx |
jnz .mac |
pop edi esi edx ecx eax |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/drivers/rtl8029.inc |
---|
1,959 → 1,976 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; RTL8029.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.2 31 July 2002 ;; |
;; ;; |
;; This driver is based on the ns8390 driver from ;; |
;; the etherboot 5.0.6 project. The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2002 Mike Hibbett, ;; |
;; mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; While this implementation handles only PCI bus RTL8029 ;; |
;; hardware, it can be easily adapted to other NE2000 clone ;; |
;; products. I just dont have any to try! ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************** |
; Interface |
; rtl8029_reset |
; rtl8029_probe |
; rtl8029_poll |
; rtl8029_transmit |
; |
;******************************************************************** |
;************************************************************************** |
; 8390 Register Definitions |
;************************************************************************** |
D8390_P0_COMMAND equ 0x00 |
D8390_P0_PSTART equ 0x01 |
D8390_P0_PSTOP equ 0x02 |
D8390_P0_BOUND equ 0x03 |
D8390_P0_TSR equ 0x04 |
D8390_P0_TPSR equ 0x04 |
D8390_P0_TBCR0 equ 0x05 |
D8390_P0_TBCR1 equ 0x06 |
D8390_P0_ISR equ 0x07 |
D8390_P0_RSAR0 equ 0x08 |
D8390_P0_RSAR1 equ 0x09 |
D8390_P0_RBCR0 equ 0x0A |
D8390_P0_RBCR1 equ 0x0B |
D8390_P0_RSR equ 0x0C |
D8390_P0_RCR equ 0x0C |
D8390_P0_TCR equ 0x0D |
D8390_P0_DCR equ 0x0E |
D8390_P0_IMR equ 0x0F |
D8390_P1_COMMAND equ 0x00 |
D8390_P1_PAR0 equ 0x01 |
D8390_P1_PAR1 equ 0x02 |
D8390_P1_PAR2 equ 0x03 |
D8390_P1_PAR3 equ 0x04 |
D8390_P1_PAR4 equ 0x05 |
D8390_P1_PAR5 equ 0x06 |
D8390_P1_CURR equ 0x07 |
D8390_P1_MAR0 equ 0x08 |
D8390_COMMAND_PS0 equ 0x0 ; Page 0 select |
D8390_COMMAND_PS1 equ 0x40 ; Page 1 select |
D8390_COMMAND_PS2 equ 0x80 ; Page 2 select |
D8390_COMMAND_RD2 equ 0x20 ; Remote DMA control |
D8390_COMMAND_RD1 equ 0x10 |
D8390_COMMAND_RD0 equ 0x08 |
D8390_COMMAND_TXP equ 0x04 ; transmit packet |
D8390_COMMAND_STA equ 0x02 ; start |
D8390_COMMAND_STP equ 0x01 ; stop |
D8390_COMMAND_RD2_STA equ 0x22 |
D8390_COMMAND_RD2_STP equ 0x21 |
D8390_COMMAND_RD1_STA equ 0x12 |
D8390_COMMAND_RD0_STA equ 0x0A |
D8390_COMMAND_PS0_RD2_STP equ 0x21 |
D8390_COMMAND_PS1_RD2_STP equ 0x61 |
D8390_COMMAND_PS0_RD2_STA equ 0x22 |
D8390_COMMAND_PS0_TXP_RD2_STA equ 0x26 |
D8390_RCR_MON equ 0x20 ; monitor mode |
D8390_DCR_FT1 equ 0x40 |
D8390_DCR_LS equ 0x08 ; Loopback select |
D8390_DCR_WTS equ 0x01 ; Word transfer select |
D8390_DCR_FT1_LS equ 0x48 |
D8390_DCR_WTS_FT1_LS equ 0x49 |
D8390_ISR_PRX equ 0x01 ; successful recv |
D8390_ISR_PTX equ 0x02 ; successful xmit |
D8390_ISR_RXE equ 0x04 ; receive error |
D8390_ISR_TXE equ 0x08 ; transmit error |
D8390_ISR_OVW equ 0x10 ; Overflow |
D8390_ISR_CNT equ 0x20 ; Counter overflow |
D8390_ISR_RDC equ 0x40 ; Remote DMA complete |
D8390_ISR_RST equ 0x80 ; reset |
D8390_RSTAT_PRX equ 0x01 ; successful recv |
D8390_RSTAT_CRC equ 0x02 ; CRC error |
D8390_RSTAT_FAE equ 0x04 ; Frame alignment error |
D8390_RSTAT_OVER equ 0x08 ; FIFO overrun |
D8390_TXBUF_SIZE equ 6 |
D8390_RXBUF_END equ 32 |
D8390_PAGE_SIZE equ 256 |
ETH_ALEN equ 6 |
ETH_HLEN equ 14 |
ETH_ZLEN equ 60 |
ETH_FRAME_LEN equ 1514 |
FLAG_PIO equ 0x01 |
FLAG_16BIT equ 0x02 |
ASIC_PIO equ 0 |
VENDOR_NONE equ 0 |
VENDOR_WD equ 1 |
VENDOR_NOVELL equ 2 |
VENDOR_3COM equ 3 |
NE_ASIC_OFFSET equ 0x10 |
NE_RESET equ 0x0F ; Used to reset card |
NE_DATA equ 0x00 ; Used to read/write NIC mem |
MEM_8192 equ 32 |
MEM_16384 equ 64 |
MEM_32768 equ 128 |
ISA_MAX_ADDR equ 0x400 |
uglobal |
eth_flags: db 0 |
eth_vendor: db 0 |
eth_nic_base: dw 0 |
eth_asic_base: dw 0 |
eth_memsize: db 0 |
eth_rx_start: db 0 |
eth_tx_start: db 0 |
eth_bmem: dd 0 |
eth_rmem: dd 0 |
romdata: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
endg |
iglobal |
test_data: db 'NE*000 memory',0 |
test_buffer: db ' ',0 |
endg |
uglobal |
eth_type: dw 0 |
pkthdr: db 0,0,0,0 ; status, next, (short) len |
pktoff: dw 0 |
eth_rx_data_ptr: dd 0 |
eth_tmp_len: dw 0 |
endg |
;*************************************************************************** |
; Function |
; eth_pio_read |
; |
; Description |
; Read a frame from the ethernet card via Programmed I/O |
; src in ebx |
; cnt in ecx |
; dst in edi |
;*************************************************************************** |
eth_pio_read: |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, 0 |
je epr_001 |
inc ecx |
and ecx, 0xFFFFFFFE |
epr_001: |
mov al, D8390_COMMAND_RD2_STA |
mov dx, [eth_nic_base] |
add dx, D8390_P0_COMMAND |
out dx, al |
mov al, cl |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RBCR0 |
out dx, al |
mov al, ch |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RBCR1 |
out dx, al |
mov al, bl |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RSAR0 |
out dx, al |
mov al, bh |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RSAR1 |
out dx, al |
mov al, D8390_COMMAND_RD0_STA |
mov dx, [eth_nic_base] |
add dx, D8390_P0_COMMAND |
out dx, al |
mov dx, [eth_asic_base] |
add dx, ASIC_PIO |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, 0 |
je epr_003 |
shr ecx, 1 |
epr_002: |
; 2 bytes at a time |
in ax, dx |
mov [edi], ax |
add edi, 2 |
loop epr_002 |
ret |
epr_003: |
; 1 byte at a time |
in al, dx |
mov [edi], al |
inc edi |
loop epr_003 |
ret |
;*************************************************************************** |
; Function |
; eth_pio_write |
; |
; Description |
; writes a frame to the ethernet card via Programmed I/O |
; dst in ebx |
; cnt in ecx |
; src in esi |
;*************************************************************************** |
eth_pio_write: |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, 0 |
je epw_001 |
inc ecx |
and ecx, 0xFFFFFFFE |
epw_001: |
mov al, D8390_COMMAND_RD2_STA |
mov dx, [eth_nic_base] |
add dx, D8390_P0_COMMAND |
out dx, al |
mov al, D8390_ISR_RDC |
mov dx, [eth_nic_base] |
add dx, D8390_P0_ISR |
out dx, al |
mov al, cl |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RBCR0 |
out dx, al |
mov al, ch |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RBCR1 |
out dx, al |
mov al, bl |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RSAR0 |
out dx, al |
mov al, bh |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RSAR1 |
out dx, al |
mov al, D8390_COMMAND_RD1_STA |
mov dx, [eth_nic_base] |
add dx, D8390_P0_COMMAND |
out dx, al |
mov dx, [eth_asic_base] |
add dx, ASIC_PIO |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, 0 |
je epw_003 |
shr ecx, 1 |
epw_002: |
; 2 bytes at a time |
mov ax, [esi] |
add esi, 2 |
out dx, ax |
loop epw_002 |
jmp epw_004 |
epw_003: |
; 1 byte at a time |
mov al, [esi] |
inc esi |
out dx, al |
loop epw_003 |
epw_004: |
mov dx, [eth_nic_base] |
add dx, D8390_P0_ISR |
epw_005: |
in al, dx |
and al, D8390_ISR_RDC |
cmp al, D8390_ISR_RDC |
jne epw_005 |
ret |
;*************************************************************************** |
; Function |
; rtl8029_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; No inputs |
; All registers destroyed |
; |
;*************************************************************************** |
rtl8029_reset: |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0_RD2_STP |
out dx, al |
mov dx, bx |
add dx, D8390_P0_DCR |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, FLAG_16BIT |
jne nsr_001 |
mov al, 0x49 |
jmp nsr_002 |
nsr_001: |
mov al, 0x48 |
nsr_002: |
out dx, al |
xor al, al |
mov dx, bx |
add dx, D8390_P0_RBCR0 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_RBCR1 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_RCR |
mov al, 0x20 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TCR |
mov al, 2 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TPSR |
mov al, [eth_tx_start] |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTART |
mov al, [eth_rx_start] |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTOP |
mov al, [eth_memsize] |
out dx, al |
mov dx, bx |
add dx, D8390_P0_BOUND |
mov al, [eth_memsize] |
dec al |
out dx, al |
mov dx, bx |
add dx, D8390_P0_ISR |
mov al, 0xff |
out dx, al |
mov dx, bx |
add dx, D8390_P0_IMR |
xor al, al |
out dx, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS1_RD2_STP |
out dx, al |
mov dx, bx |
add dx, D8390_P1_PAR0 |
mov esi, node_addr |
mov ecx, ETH_ALEN |
nsr_003: |
mov al, [esi] |
out dx, al |
inc esi |
inc dx |
loop nsr_003 |
mov dx, bx |
add dx, D8390_P1_MAR0 |
mov ecx, ETH_ALEN |
mov al, 0xff |
nsr_004: |
out dx, al |
inc dx |
loop nsr_004 |
mov dx, bx |
add dx, D8390_P1_CURR |
mov al, [eth_rx_start] |
out dx, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0_RD2_STA |
out dx, al |
mov dx, bx |
add dx, D8390_P0_ISR |
mov al, 0xff |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TCR |
mov al, 0 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_RCR |
mov al, 4 |
out dx, al |
ret |
;*************************************************************************** |
; Function |
; rtl8029_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; |
;*************************************************************************** |
rtl8029_probe: |
mov eax, [io_addr] |
mov [eth_nic_base], ax ; The IO address space is 16 bit only |
mov al, VENDOR_NONE |
mov [eth_vendor], al |
mov al, [eth_vendor] |
cmp al, VENDOR_NONE |
jne ep_check_have_vendor |
xor eax, eax |
mov [eth_bmem], eax |
mov al, FLAG_PIO |
mov [eth_flags], al |
mov ax, [eth_nic_base] |
add ax, NE_ASIC_OFFSET |
mov [eth_asic_base], ax |
mov al, MEM_16384 |
mov [eth_memsize], al |
mov al, 32 |
mov [eth_tx_start], al |
add al, D8390_TXBUF_SIZE |
mov [eth_rx_start], al |
mov dx, [eth_asic_base] |
add dx, NE_RESET |
in al, dx |
out dx, al |
in al, 0x84 |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_RD2_STP |
out dx, al |
mov dx, bx |
add dx, D8390_P0_RCR |
mov al, D8390_RCR_MON |
out dx, al |
mov dx, bx |
add dx, D8390_P0_DCR |
mov al, D8390_DCR_FT1_LS |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTART |
mov al, MEM_8192 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTOP |
mov al, MEM_16384 |
out dx, al |
mov esi, test_data |
mov ebx, 8192 |
mov ecx, 14 |
call eth_pio_write |
mov ebx, 8192 |
mov ecx, 14 |
mov edi, test_buffer |
call eth_pio_read |
mov esi, test_buffer |
mov edi, test_data |
mov ecx, 13 |
cld |
rep cmpsb |
je ep_set_vendor |
mov al, [eth_flags] |
or al, FLAG_16BIT |
mov [eth_flags], al |
mov al, MEM_32768 |
mov [eth_memsize], al |
mov al, 64 |
mov [eth_tx_start], al |
add al, D8390_TXBUF_SIZE |
mov [eth_rx_start], al |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_DCR |
mov al, D8390_DCR_WTS_FT1_LS |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTART |
mov al, MEM_16384 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTOP |
mov al, MEM_32768 |
out dx, al |
mov esi, test_data |
mov ebx, 16384 |
mov ecx, 14 |
call eth_pio_write |
mov ebx, 16384 |
mov ecx, 14 |
mov edi, test_buffer |
call eth_pio_read |
mov esi, test_buffer |
mov edi, test_data |
mov ecx, 13 |
cld |
rep cmpsb |
ep_set_vendor: |
; this bit is odd - probably left over from my hacking |
mov ax, [eth_nic_base] |
cmp ax, 0 |
je rtl8029_exit |
cmp ax, ISA_MAX_ADDR |
jbe ep_001 |
mov al, [eth_flags] |
or al, FLAG_16BIT |
mov [eth_flags], al |
ep_001: |
mov al, VENDOR_NOVELL |
mov [eth_vendor], al |
mov ebx, 0 |
mov ecx, 16 |
mov edi, romdata |
call eth_pio_read |
mov ecx, ETH_ALEN |
mov esi, romdata |
mov edi, node_addr |
mov bl, [eth_flags] |
and bl, FLAG_16BIT |
ep_002: |
mov al, [esi] |
mov [edi], al |
inc edi |
inc esi |
cmp bl, FLAG_16BIT |
jne ep_003 |
inc esi |
ep_003: |
loop ep_002 |
ep_check_have_vendor: |
mov al, [eth_vendor] |
cmp al, VENDOR_NONE |
je rtl8029_exit |
cmp al, VENDOR_3COM |
je ep_reset_card |
mov eax, [eth_bmem] |
mov [eth_rmem], eax |
ep_reset_card: |
; Reset the card |
call rtl8029_reset |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
rtl8029_exit: |
ret |
;*************************************************************************** |
; Function |
; rtl8029_poll |
; |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; |
;*************************************************************************** |
rtl8029_poll: |
mov eax, Ether_buffer |
mov [eth_rx_data_ptr], eax |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_RSR |
in al, dx |
and al, D8390_RSTAT_PRX |
cmp al, D8390_RSTAT_PRX |
jne nsp_exit |
mov dx, bx |
add dx, D8390_P0_BOUND |
in al, dx |
inc al |
cmp al, [eth_memsize] |
jb nsp_001 |
mov al, [eth_rx_start] |
nsp_001: |
mov ch, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS1 |
out dx, al |
mov dx, bx |
add dx, D8390_P1_CURR |
in al, dx ; get current page |
mov cl, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0 |
out dx, al |
cmp cl, [eth_memsize] |
jb nsp_002 |
mov cl, [eth_rx_start] |
nsp_002: |
cmp cl, ch |
je nsp_exit |
xor ax, ax |
mov ah, ch |
mov [pktoff], ax |
mov al, [eth_flags] |
and al, FLAG_PIO |
cmp al, FLAG_PIO |
jne nsp_003 |
movzx ebx, word [pktoff] |
mov edi, pkthdr |
mov ecx, 4 |
call eth_pio_read |
jmp nsp_004 |
nsp_003: |
mov edi, [eth_rmem] |
movzx eax, word [pktoff] |
add edi, eax |
mov eax, [edi] |
mov [pkthdr], eax |
nsp_004: |
mov ax, [pktoff] |
add ax, 4 |
mov [pktoff], ax |
mov ax, [pkthdr + 2] |
sub ax, 4 |
mov [eth_tmp_len], ax |
cmp ax, ETH_ZLEN |
jb nsp_exit |
cmp ax, ETH_FRAME_LEN |
ja nsp_exit |
mov al, [pkthdr] |
and al, D8390_RSTAT_PRX |
cmp al, D8390_RSTAT_PRX |
jne nsp_exit |
; Right, we can now get the data |
mov ax, [eth_tmp_len] |
mov [eth_rx_data_len], ax |
xor ebx, ebx |
mov bh, [eth_memsize] |
sub bx, [pktoff] |
cmp [eth_tmp_len], bx |
jbe nsp_005 |
mov al, [eth_flags] |
and al, FLAG_PIO |
cmp al, FLAG_PIO |
jne nsp_006 |
push ebx |
mov ecx, ebx |
xor ebx, ebx |
mov bx, [pktoff] |
mov edi, [eth_rx_data_ptr] |
call eth_pio_read |
pop ebx |
jmp nsp_007 |
nsp_006: |
; Not implemented, as we are using PIO mode on this card |
nsp_007: |
xor ax, ax |
mov ah, [eth_rx_start] |
mov [pktoff], ax |
mov eax, [eth_rx_data_ptr] |
add eax, ebx |
mov [eth_rx_data_ptr], eax |
mov ax, [eth_tmp_len] |
sub ax, bx |
mov [eth_tmp_len], ax |
nsp_005: |
mov al, [eth_flags] |
and al, FLAG_PIO |
cmp al, FLAG_PIO |
jne nsp_008 |
xor ebx, ebx |
mov bx, [pktoff] |
xor ecx, ecx |
mov cx, [eth_tmp_len] |
mov edi, [eth_rx_data_ptr] |
call eth_pio_read |
jmp nsp_009 |
nsp_008: |
; Not implemented, as we are using PIO mode on this card |
nsp_009: |
mov al, [pkthdr+1] |
cmp al, [eth_rx_start] |
jne nsp_010 |
mov al, [eth_memsize] |
nsp_010: |
mov dx, [eth_nic_base] |
add dx, D8390_P0_BOUND |
dec al |
out dx, al |
nsp_exit: |
ret |
;*************************************************************************** |
; Function |
; rtl8029_transmit |
; |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
; |
;*************************************************************************** |
rtl8029_transmit: |
mov [eth_type], bx |
pusha |
mov esi, edi |
xor bx, bx |
mov bh, [eth_tx_start] |
mov ecx, ETH_ALEN |
call eth_pio_write |
mov esi, node_addr |
xor bx, bx |
mov bh, [eth_tx_start] |
add bx, ETH_ALEN |
mov ecx, ETH_ALEN |
call eth_pio_write |
mov esi, eth_type |
xor bx, bx |
mov bh, [eth_tx_start] |
add bx, ETH_ALEN |
add bx, ETH_ALEN |
mov ecx, 2 |
call eth_pio_write |
popa |
xor bx, bx |
mov bh, [eth_tx_start] |
add bx, ETH_HLEN |
push ecx |
call eth_pio_write |
pop ecx |
add ecx, ETH_HLEN |
cmp ecx, ETH_ZLEN |
jae nst_001 |
mov ecx, ETH_ZLEN |
nst_001: |
push ecx |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0_RD2_STA |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TPSR |
mov al, [eth_tx_start] |
out dx, al |
pop ecx |
mov dx, bx |
add dx, D8390_P0_TBCR0 |
mov al, cl |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TBCR1 |
mov al, ch |
out dx, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0_TXP_RD2_STA |
out dx, al |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; RTL8029.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.2 31 July 2002 ;; |
;; ;; |
;; This driver is based on the ns8390 driver from ;; |
;; the etherboot 5.0.6 project. The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2002 Mike Hibbett, ;; |
;; mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; While this implementation handles only PCI bus RTL8029 ;; |
;; hardware, it can be easily adapted to other NE2000 clone ;; |
;; products. I just dont have any to try! ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************** |
; Interface |
; rtl8029_reset |
; rtl8029_probe |
; rtl8029_poll |
; rtl8029_transmit |
; |
;******************************************************************** |
;************************************************************************** |
; 8390 Register Definitions |
;************************************************************************** |
D8390_P0_COMMAND equ 0x00 |
D8390_P0_PSTART equ 0x01 |
D8390_P0_PSTOP equ 0x02 |
D8390_P0_BOUND equ 0x03 |
D8390_P0_TSR equ 0x04 |
D8390_P0_TPSR equ 0x04 |
D8390_P0_TBCR0 equ 0x05 |
D8390_P0_TBCR1 equ 0x06 |
D8390_P0_ISR equ 0x07 |
D8390_P0_RSAR0 equ 0x08 |
D8390_P0_RSAR1 equ 0x09 |
D8390_P0_RBCR0 equ 0x0A |
D8390_P0_RBCR1 equ 0x0B |
D8390_P0_RSR equ 0x0C |
D8390_P0_RCR equ 0x0C |
D8390_P0_TCR equ 0x0D |
D8390_P0_DCR equ 0x0E |
D8390_P0_IMR equ 0x0F |
D8390_P1_COMMAND equ 0x00 |
D8390_P1_PAR0 equ 0x01 |
D8390_P1_PAR1 equ 0x02 |
D8390_P1_PAR2 equ 0x03 |
D8390_P1_PAR3 equ 0x04 |
D8390_P1_PAR4 equ 0x05 |
D8390_P1_PAR5 equ 0x06 |
D8390_P1_CURR equ 0x07 |
D8390_P1_MAR0 equ 0x08 |
D8390_COMMAND_PS0 equ 0x0 ; Page 0 select |
D8390_COMMAND_PS1 equ 0x40 ; Page 1 select |
D8390_COMMAND_PS2 equ 0x80 ; Page 2 select |
D8390_COMMAND_RD2 equ 0x20 ; Remote DMA control |
D8390_COMMAND_RD1 equ 0x10 |
D8390_COMMAND_RD0 equ 0x08 |
D8390_COMMAND_TXP equ 0x04 ; transmit packet |
D8390_COMMAND_STA equ 0x02 ; start |
D8390_COMMAND_STP equ 0x01 ; stop |
D8390_COMMAND_RD2_STA equ 0x22 |
D8390_COMMAND_RD2_STP equ 0x21 |
D8390_COMMAND_RD1_STA equ 0x12 |
D8390_COMMAND_RD0_STA equ 0x0A |
D8390_COMMAND_PS0_RD2_STP equ 0x21 |
D8390_COMMAND_PS1_RD2_STP equ 0x61 |
D8390_COMMAND_PS0_RD2_STA equ 0x22 |
D8390_COMMAND_PS0_TXP_RD2_STA equ 0x26 |
D8390_RCR_MON equ 0x20 ; monitor mode |
D8390_DCR_FT1 equ 0x40 |
D8390_DCR_LS equ 0x08 ; Loopback select |
D8390_DCR_WTS equ 0x01 ; Word transfer select |
D8390_DCR_FT1_LS equ 0x48 |
D8390_DCR_WTS_FT1_LS equ 0x49 |
D8390_ISR_PRX equ 0x01 ; successful recv |
D8390_ISR_PTX equ 0x02 ; successful xmit |
D8390_ISR_RXE equ 0x04 ; receive error |
D8390_ISR_TXE equ 0x08 ; transmit error |
D8390_ISR_OVW equ 0x10 ; Overflow |
D8390_ISR_CNT equ 0x20 ; Counter overflow |
D8390_ISR_RDC equ 0x40 ; Remote DMA complete |
D8390_ISR_RST equ 0x80 ; reset |
D8390_RSTAT_PRX equ 0x01 ; successful recv |
D8390_RSTAT_CRC equ 0x02 ; CRC error |
D8390_RSTAT_FAE equ 0x04 ; Frame alignment error |
D8390_RSTAT_OVER equ 0x08 ; FIFO overrun |
D8390_TXBUF_SIZE equ 6 |
D8390_RXBUF_END equ 32 |
D8390_PAGE_SIZE equ 256 |
ETH_ALEN equ 6 |
ETH_HLEN equ 14 |
ETH_ZLEN equ 60 |
ETH_FRAME_LEN equ 1514 |
FLAG_PIO equ 0x01 |
FLAG_16BIT equ 0x02 |
ASIC_PIO equ 0 |
VENDOR_NONE equ 0 |
VENDOR_WD equ 1 |
VENDOR_NOVELL equ 2 |
VENDOR_3COM equ 3 |
NE_ASIC_OFFSET equ 0x10 |
NE_RESET equ 0x0F ; Used to reset card |
NE_DATA equ 0x00 ; Used to read/write NIC mem |
MEM_8192 equ 32 |
MEM_16384 equ 64 |
MEM_32768 equ 128 |
ISA_MAX_ADDR equ 0x400 |
uglobal |
eth_flags: |
db 0 |
eth_vendor: |
db 0 |
eth_nic_base: |
dw 0 |
eth_asic_base: |
dw 0 |
eth_memsize: |
db 0 |
eth_rx_start: |
db 0 |
eth_tx_start: |
db 0 |
eth_bmem: |
dd 0 |
eth_rmem: |
dd 0 |
romdata: |
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
endg |
iglobal |
test_data: |
db 'NE*000 memory',0 |
test_buffer: |
db ' ',0 |
endg |
uglobal |
eth_type: |
dw 0 |
pkthdr: |
db 0,0,0,0 ; status, next, (short) len |
pktoff: |
dw 0 |
eth_rx_data_ptr: |
dd 0 |
eth_tmp_len: |
dw 0 |
endg |
;*************************************************************************** |
; Function |
; eth_pio_read |
; |
; Description |
; Read a frame from the ethernet card via Programmed I/O |
; src in ebx |
; cnt in ecx |
; dst in edi |
;*************************************************************************** |
eth_pio_read: |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, 0 |
je epr_001 |
inc ecx |
and ecx, 0xFFFFFFFE |
epr_001: |
mov al, D8390_COMMAND_RD2_STA |
mov dx, [eth_nic_base] |
add dx, D8390_P0_COMMAND |
out dx, al |
mov al, cl |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RBCR0 |
out dx, al |
mov al, ch |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RBCR1 |
out dx, al |
mov al, bl |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RSAR0 |
out dx, al |
mov al, bh |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RSAR1 |
out dx, al |
mov al, D8390_COMMAND_RD0_STA |
mov dx, [eth_nic_base] |
add dx, D8390_P0_COMMAND |
out dx, al |
mov dx, [eth_asic_base] |
add dx, ASIC_PIO |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, 0 |
je epr_003 |
shr ecx, 1 |
epr_002: |
; 2 bytes at a time |
in ax, dx |
mov [edi], ax |
add edi, 2 |
loop epr_002 |
ret |
epr_003: |
; 1 byte at a time |
in al, dx |
mov [edi], al |
inc edi |
loop epr_003 |
ret |
;*************************************************************************** |
; Function |
; eth_pio_write |
; |
; Description |
; writes a frame to the ethernet card via Programmed I/O |
; dst in ebx |
; cnt in ecx |
; src in esi |
;*************************************************************************** |
eth_pio_write: |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, 0 |
je epw_001 |
inc ecx |
and ecx, 0xFFFFFFFE |
epw_001: |
mov al, D8390_COMMAND_RD2_STA |
mov dx, [eth_nic_base] |
add dx, D8390_P0_COMMAND |
out dx, al |
mov al, D8390_ISR_RDC |
mov dx, [eth_nic_base] |
add dx, D8390_P0_ISR |
out dx, al |
mov al, cl |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RBCR0 |
out dx, al |
mov al, ch |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RBCR1 |
out dx, al |
mov al, bl |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RSAR0 |
out dx, al |
mov al, bh |
mov dx, [eth_nic_base] |
add dx, D8390_P0_RSAR1 |
out dx, al |
mov al, D8390_COMMAND_RD1_STA |
mov dx, [eth_nic_base] |
add dx, D8390_P0_COMMAND |
out dx, al |
mov dx, [eth_asic_base] |
add dx, ASIC_PIO |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, 0 |
je epw_003 |
shr ecx, 1 |
epw_002: |
; 2 bytes at a time |
mov ax, [esi] |
add esi, 2 |
out dx, ax |
loop epw_002 |
jmp epw_004 |
epw_003: |
; 1 byte at a time |
mov al, [esi] |
inc esi |
out dx, al |
loop epw_003 |
epw_004: |
mov dx, [eth_nic_base] |
add dx, D8390_P0_ISR |
epw_005: |
in al, dx |
and al, D8390_ISR_RDC |
cmp al, D8390_ISR_RDC |
jne epw_005 |
ret |
;*************************************************************************** |
; Function |
; rtl8029_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; No inputs |
; All registers destroyed |
; |
;*************************************************************************** |
rtl8029_reset: |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0_RD2_STP |
out dx, al |
mov dx, bx |
add dx, D8390_P0_DCR |
mov al, [eth_flags] |
and al, FLAG_16BIT |
cmp al, FLAG_16BIT |
jne nsr_001 |
mov al, 0x49 |
jmp nsr_002 |
nsr_001: |
mov al, 0x48 |
nsr_002: |
out dx, al |
xor al, al |
mov dx, bx |
add dx, D8390_P0_RBCR0 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_RBCR1 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_RCR |
mov al, 0x20 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TCR |
mov al, 2 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TPSR |
mov al, [eth_tx_start] |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTART |
mov al, [eth_rx_start] |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTOP |
mov al, [eth_memsize] |
out dx, al |
mov dx, bx |
add dx, D8390_P0_BOUND |
mov al, [eth_memsize] |
dec al |
out dx, al |
mov dx, bx |
add dx, D8390_P0_ISR |
mov al, 0xff |
out dx, al |
mov dx, bx |
add dx, D8390_P0_IMR |
xor al, al |
out dx, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS1_RD2_STP |
out dx, al |
mov dx, bx |
add dx, D8390_P1_PAR0 |
mov esi, node_addr |
mov ecx, ETH_ALEN |
nsr_003: |
mov al, [esi] |
out dx, al |
inc esi |
inc dx |
loop nsr_003 |
mov dx, bx |
add dx, D8390_P1_MAR0 |
mov ecx, ETH_ALEN |
mov al, 0xff |
nsr_004: |
out dx, al |
inc dx |
loop nsr_004 |
mov dx, bx |
add dx, D8390_P1_CURR |
mov al, [eth_rx_start] |
out dx, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0_RD2_STA |
out dx, al |
mov dx, bx |
add dx, D8390_P0_ISR |
mov al, 0xff |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TCR |
mov al, 0 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_RCR |
mov al, 4 |
out dx, al |
ret |
;*************************************************************************** |
; Function |
; rtl8029_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; |
;*************************************************************************** |
rtl8029_probe: |
mov eax, [io_addr] |
mov [eth_nic_base], ax ; The IO address space is 16 bit only |
mov al, VENDOR_NONE |
mov [eth_vendor], al |
mov al, [eth_vendor] |
cmp al, VENDOR_NONE |
jne ep_check_have_vendor |
xor eax, eax |
mov [eth_bmem], eax |
mov al, FLAG_PIO |
mov [eth_flags], al |
mov ax, [eth_nic_base] |
add ax, NE_ASIC_OFFSET |
mov [eth_asic_base], ax |
mov al, MEM_16384 |
mov [eth_memsize], al |
mov al, 32 |
mov [eth_tx_start], al |
add al, D8390_TXBUF_SIZE |
mov [eth_rx_start], al |
mov dx, [eth_asic_base] |
add dx, NE_RESET |
in al, dx |
out dx, al |
in al, 0x84 |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_RD2_STP |
out dx, al |
mov dx, bx |
add dx, D8390_P0_RCR |
mov al, D8390_RCR_MON |
out dx, al |
mov dx, bx |
add dx, D8390_P0_DCR |
mov al, D8390_DCR_FT1_LS |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTART |
mov al, MEM_8192 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTOP |
mov al, MEM_16384 |
out dx, al |
mov esi, test_data |
mov ebx, 8192 |
mov ecx, 14 |
call eth_pio_write |
mov ebx, 8192 |
mov ecx, 14 |
mov edi, test_buffer |
call eth_pio_read |
mov esi, test_buffer |
mov edi, test_data |
mov ecx, 13 |
cld |
rep cmpsb |
je ep_set_vendor |
mov al, [eth_flags] |
or al, FLAG_16BIT |
mov [eth_flags], al |
mov al, MEM_32768 |
mov [eth_memsize], al |
mov al, 64 |
mov [eth_tx_start], al |
add al, D8390_TXBUF_SIZE |
mov [eth_rx_start], al |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_DCR |
mov al, D8390_DCR_WTS_FT1_LS |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTART |
mov al, MEM_16384 |
out dx, al |
mov dx, bx |
add dx, D8390_P0_PSTOP |
mov al, MEM_32768 |
out dx, al |
mov esi, test_data |
mov ebx, 16384 |
mov ecx, 14 |
call eth_pio_write |
mov ebx, 16384 |
mov ecx, 14 |
mov edi, test_buffer |
call eth_pio_read |
mov esi, test_buffer |
mov edi, test_data |
mov ecx, 13 |
cld |
rep cmpsb |
ep_set_vendor: |
; this bit is odd - probably left over from my hacking |
mov ax, [eth_nic_base] |
cmp ax, 0 |
je rtl8029_exit |
cmp ax, ISA_MAX_ADDR |
jbe ep_001 |
mov al, [eth_flags] |
or al, FLAG_16BIT |
mov [eth_flags], al |
ep_001: |
mov al, VENDOR_NOVELL |
mov [eth_vendor], al |
mov ebx, 0 |
mov ecx, 16 |
mov edi, romdata |
call eth_pio_read |
mov ecx, ETH_ALEN |
mov esi, romdata |
mov edi, node_addr |
mov bl, [eth_flags] |
and bl, FLAG_16BIT |
ep_002: |
mov al, [esi] |
mov [edi], al |
inc edi |
inc esi |
cmp bl, FLAG_16BIT |
jne ep_003 |
inc esi |
ep_003: |
loop ep_002 |
ep_check_have_vendor: |
mov al, [eth_vendor] |
cmp al, VENDOR_NONE |
je rtl8029_exit |
cmp al, VENDOR_3COM |
je ep_reset_card |
mov eax, [eth_bmem] |
mov [eth_rmem], eax |
ep_reset_card: |
; Reset the card |
call rtl8029_reset |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
rtl8029_exit: |
ret |
;*************************************************************************** |
; Function |
; rtl8029_poll |
; |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; |
;*************************************************************************** |
rtl8029_poll: |
mov eax, Ether_buffer |
mov [eth_rx_data_ptr], eax |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_RSR |
in al, dx |
and al, D8390_RSTAT_PRX |
cmp al, D8390_RSTAT_PRX |
jne nsp_exit |
mov dx, bx |
add dx, D8390_P0_BOUND |
in al, dx |
inc al |
cmp al, [eth_memsize] |
jb nsp_001 |
mov al, [eth_rx_start] |
nsp_001: |
mov ch, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS1 |
out dx, al |
mov dx, bx |
add dx, D8390_P1_CURR |
in al, dx ; get current page |
mov cl, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0 |
out dx, al |
cmp cl, [eth_memsize] |
jb nsp_002 |
mov cl, [eth_rx_start] |
nsp_002: |
cmp cl, ch |
je nsp_exit |
xor ax, ax |
mov ah, ch |
mov [pktoff], ax |
mov al, [eth_flags] |
and al, FLAG_PIO |
cmp al, FLAG_PIO |
jne nsp_003 |
movzx ebx, word [pktoff] |
mov edi, pkthdr |
mov ecx, 4 |
call eth_pio_read |
jmp nsp_004 |
nsp_003: |
mov edi, [eth_rmem] |
movzx eax, word [pktoff] |
add edi, eax |
mov eax, [edi] |
mov [pkthdr], eax |
nsp_004: |
mov ax, [pktoff] |
add ax, 4 |
mov [pktoff], ax |
mov ax, [pkthdr + 2] |
sub ax, 4 |
mov [eth_tmp_len], ax |
cmp ax, ETH_ZLEN |
jb nsp_exit |
cmp ax, ETH_FRAME_LEN |
ja nsp_exit |
mov al, [pkthdr] |
and al, D8390_RSTAT_PRX |
cmp al, D8390_RSTAT_PRX |
jne nsp_exit |
; Right, we can now get the data |
mov ax, [eth_tmp_len] |
mov [eth_rx_data_len], ax |
xor ebx, ebx |
mov bh, [eth_memsize] |
sub bx, [pktoff] |
cmp [eth_tmp_len], bx |
jbe nsp_005 |
mov al, [eth_flags] |
and al, FLAG_PIO |
cmp al, FLAG_PIO |
jne nsp_006 |
push ebx |
mov ecx, ebx |
xor ebx, ebx |
mov bx, [pktoff] |
mov edi, [eth_rx_data_ptr] |
call eth_pio_read |
pop ebx |
jmp nsp_007 |
nsp_006: |
; Not implemented, as we are using PIO mode on this card |
nsp_007: |
xor ax, ax |
mov ah, [eth_rx_start] |
mov [pktoff], ax |
mov eax, [eth_rx_data_ptr] |
add eax, ebx |
mov [eth_rx_data_ptr], eax |
mov ax, [eth_tmp_len] |
sub ax, bx |
mov [eth_tmp_len], ax |
nsp_005: |
mov al, [eth_flags] |
and al, FLAG_PIO |
cmp al, FLAG_PIO |
jne nsp_008 |
xor ebx, ebx |
mov bx, [pktoff] |
xor ecx, ecx |
mov cx, [eth_tmp_len] |
mov edi, [eth_rx_data_ptr] |
call eth_pio_read |
jmp nsp_009 |
nsp_008: |
; Not implemented, as we are using PIO mode on this card |
nsp_009: |
mov al, [pkthdr+1] |
cmp al, [eth_rx_start] |
jne nsp_010 |
mov al, [eth_memsize] |
nsp_010: |
mov dx, [eth_nic_base] |
add dx, D8390_P0_BOUND |
dec al |
out dx, al |
nsp_exit: |
ret |
;*************************************************************************** |
; Function |
; rtl8029_transmit |
; |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
; |
;*************************************************************************** |
rtl8029_transmit: |
mov [eth_type], bx |
pusha |
mov esi, edi |
xor bx, bx |
mov bh, [eth_tx_start] |
mov ecx, ETH_ALEN |
call eth_pio_write |
mov esi, node_addr |
xor bx, bx |
mov bh, [eth_tx_start] |
add bx, ETH_ALEN |
mov ecx, ETH_ALEN |
call eth_pio_write |
mov esi, eth_type |
xor bx, bx |
mov bh, [eth_tx_start] |
add bx, ETH_ALEN |
add bx, ETH_ALEN |
mov ecx, 2 |
call eth_pio_write |
popa |
xor bx, bx |
mov bh, [eth_tx_start] |
add bx, ETH_HLEN |
push ecx |
call eth_pio_write |
pop ecx |
add ecx, ETH_HLEN |
cmp ecx, ETH_ZLEN |
jae nst_001 |
mov ecx, ETH_ZLEN |
nst_001: |
push ecx |
mov bx, [eth_nic_base] |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0_RD2_STA |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TPSR |
mov al, [eth_tx_start] |
out dx, al |
pop ecx |
mov dx, bx |
add dx, D8390_P0_TBCR0 |
mov al, cl |
out dx, al |
mov dx, bx |
add dx, D8390_P0_TBCR1 |
mov al, ch |
out dx, al |
mov dx, bx |
add dx, D8390_P0_COMMAND |
mov al, D8390_COMMAND_PS0_TXP_RD2_STA |
out dx, al |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/drivers/rtl8139.inc |
---|
1,621 → 1,624 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; RTL8139.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.2 11 August 2003 ;; |
;; ;; |
;; Driver for chips of RealTek 8139 family ;; |
;; References: ;; |
;; www.realtek.com.hw - data sheets ;; |
;; rtl8139.c - linux driver ;; |
;; 8139too.c - linux driver ;; |
;; ethernet driver template by Mike Hibbett ;; |
;; ;; |
;; The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; Copyright 2003 Endre Kozma, ;; |
;; endre.kozma@axelero.hu ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; 10.01.2007 Bugfix for l8139_transmit from Paolo Franchetti ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
ETH_ALEN equ 6 |
ETH_HLEN equ (2 * ETH_ALEN + 2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
PCI_REG_COMMAND equ 0x04 ; command register |
PCI_BIT_PIO equ 0 ; bit0: io space control |
PCI_BIT_MMIO equ 1 ; bit1: memory space control |
PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master |
RTL8139_REG_MAR0 equ 0x08 ; multicast filter register 0 |
RTL8139_REG_MAR4 equ 0x0c ; multicast filter register 4 |
RTL8139_REG_TSD0 equ 0x10 ; transmit status of descriptor |
RTL8139_REG_TSAD0 equ 0x20 ; transmit start address of descriptor |
RTL8139_REG_RBSTART equ 0x30 ; RxBuffer start address |
RTL8139_REG_COMMAND equ 0x37 ; command register |
RTL8139_REG_CAPR equ 0x38 ; current address of packet read |
RTL8139_REG_IMR equ 0x3c ; interrupt mask register |
RTL8139_REG_ISR equ 0x3e ; interrupt status register |
RTL8139_REG_TXCONFIG equ 0x40 ; transmit configuration register |
RTL8139_REG_TXCONFIG_0 equ 0x40 ; transmit configuration register 0 |
RTL8139_REG_TXCONFIG_1 equ 0x41 ; transmit configuration register 1 |
RTL8139_REG_TXCONFIG_2 equ 0x42 ; transmit configuration register 2 |
RTL8139_REG_TXCONFIG_3 equ 0x43 ; transmit configuration register 3 |
RTL8139_REG_RXCONFIG equ 0x44 ; receive configuration register 0 |
RTL8139_REG_RXCONFIG_0 equ 0x44 ; receive configuration register 0 |
RTL8139_REG_RXCONFIG_1 equ 0x45 ; receive configuration register 1 |
RTL8139_REG_RXCONFIG_2 equ 0x46 ; receive configuration register 2 |
RTL8139_REG_RXCONFIG_3 equ 0x47 ; receive configuration register 3 |
RTL8139_REG_MPC equ 0x4c ; missed packet counter |
RTL8139_REG_9346CR equ 0x50 ; serial eeprom 93C46 command register |
RTL8139_REG_CONFIG1 equ 0x52 ; configuration register 1 |
RTL8139_REG_CONFIG4 equ 0x5a ; configuration register 4 |
RTL8139_REG_HLTCLK equ 0x5b ; undocumented halt clock register |
RTL8139_REG_BMCR equ 0x62 ; basic mode control register |
RTL8139_REG_ANAR equ 0x66 ; auto negotiation advertisement register |
; 5.1 packet header |
RTL8139_BIT_RUNT equ 4 ; total packet length < 64 bytes |
RTL8139_BIT_LONG equ 3 ; total packet length > 4k |
RTL8139_BIT_CRC equ 2 ; crc error occured |
RTL8139_BIT_FAE equ 1 ; frame alignment error occured |
RTL8139_BIT_ROK equ 0 ; received packet is ok |
; 5.4 command register |
RTL8139_BIT_RST equ 4 ; reset bit |
RTL8139_BIT_RE equ 3 ; receiver enabled |
RTL8139_BIT_TE equ 2 ; transmitter enabled |
RTL8139_BIT_BUFE equ 0 ; rx buffer is empty, no packet stored |
; 5.6 interrupt status register |
RTL8139_BIT_ISR_TOK equ 2 ; transmit ok |
RTL8139_BIT_ISR_RER equ 1 ; receive error interrupt |
RTL8139_BIT_ISR_ROK equ 0 ; receive ok |
; 5.7 transmit configyration register |
RTL8139_BIT_TX_MXDMA equ 8 ; Max DMA burst size per Tx DMA burst |
RTL8139_BIT_TXRR equ 4 ; Tx Retry count 16+(TXRR*16) |
; 5.8 receive configuration register |
RTL8139_BIT_RXFTH equ 13 ; Rx fifo threshold |
RTL8139_BIT_RBLEN equ 11 ; Ring buffer length indicator |
RTL8139_BIT_RX_MXDMA equ 8 ; Max DMA burst size per Rx DMA burst |
RTL8139_BIT_NOWRAP equ 7 ; transfered data wrapping |
RTL8139_BIT_9356SEL equ 6 ; eeprom selector 9346/9356 |
RTL8139_BIT_AER equ 5 ; accept error packets |
RTL8139_BIT_AR equ 4 ; accept runt packets |
RTL8139_BIT_AB equ 3 ; accept broadcast packets |
RTL8139_BIT_AM equ 2 ; accept multicast packets |
RTL8139_BIT_APM equ 1 ; accept physical match packets |
RTL8139_BIT_AAP equ 0 ; accept all packets |
; 5.9 93C46/93C56 command register |
RTL8139_BIT_93C46_EEM1 equ 7 ; RTL8139 eeprom operating mode1 |
RTL8139_BIT_93C46_EEM0 equ 6 ; RTL8139 eeprom operating mode0 |
RTL8139_BIT_93C46_EECS equ 3 ; chip select |
RTL8139_BIT_93C46_EESK equ 2 ; serial data clock |
RTL8139_BIT_93C46_EEDI equ 1 ; serial data input |
RTL8139_BIT_93C46_EEDO equ 0 ; serial data output |
; 5.11 configuration register 1 |
RTL8139_BIT_LWACT equ 4 ; see RTL8139_REG_CONFIG1 |
RTL8139_BIT_SLEEP equ 1 ; sleep bit at older chips |
RTL8139_BIT_PWRDWN equ 0 ; power down bit at older chips |
RTL8139_BIT_PMEn equ 0 ; power management enabled |
; 5.14 configuration register 4 |
RTL8139_BIT_LWPTN equ 2 ; see RTL8139_REG_CONFIG4 |
; 6.2 transmit status register |
RTL8139_BIT_ERTXTH equ 16 ; early TX threshold |
RTL8139_BIT_TOK equ 15 ; transmit ok |
RTL8139_BIT_OWN equ 13 ; tx DMA operation is completed |
; 6.18 basic mode control register |
RTL8139_BIT_ANE equ 12 ; auto negotiation enable |
; 6.20 auto negotiation advertisement register |
RTL8139_BIT_TXFD equ 8 ; 100base-T full duplex |
RTL8139_BIT_TX equ 7 ; 100base-T |
RTL8139_BIT_10FD equ 6 ; 10base-T full duplex |
RTL8139_BIT_10 equ 5 ; 10base-T |
RTL8139_BIT_SELECTOR equ 0 ; binary encoded selector CSMA/CD=00001 |
; RX/TX buffer size |
RTL8139_RBLEN equ 0 ; 0==8K 1==16k 2==32k 3==64k |
RTL8139_RX_BUFFER_SIZE equ (8192 shl RTL8139_RBLEN) |
MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC |
RTL8139_NUM_TX_DESC equ 4 |
RTL8139_TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE * RTL8139_NUM_TX_DESC) |
RTL8139_TXRR equ 8 ; total retries = 16+(TXRR*16) |
RTL8139_TX_MXDMA equ 6 ; 0==16 1==32 2==64 3==128 |
; 4==256 5==512 6==1024 7==2048 |
RTL8139_ERTXTH equ 8 ; in unit of 32 bytes e.g:(8*32)=256 |
RTL8139_RX_MXDMA equ 7 ; 0==16 1==32 2==64 3==128 |
; 4==256 5==512 6==1024 7==unlimited |
RTL8139_RXFTH equ 7 ; 0==16 1==32 2==64 3==128 |
; 4==256 5==512 6==1024 7==no threshold |
RTL8139_RX_CONFIG equ ((RTL8139_RBLEN shl RTL8139_BIT_RBLEN) \ |
or (RTL8139_RX_MXDMA shl RTL8139_BIT_RX_MXDMA) \ |
or (1 shl RTL8139_BIT_NOWRAP) \ |
or (RTL8139_RXFTH shl RTL8139_BIT_RXFTH) \ |
or (1 shl RTL8139_BIT_AB) or (1 shl RTL8139_BIT_APM) \ |
or (1 shl RTL8139_BIT_AER) or (1 shl RTL8139_BIT_AR) \ |
or (1 shl RTL8139_BIT_AM)) |
RTL8139_TX_TIMEOUT equ 30 ; 300 milliseconds timeout |
EE_93C46_REG_ETH_ID equ 7 ; MAC offset |
EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address |
EE_93C56_READ_CMD equ (6 shl 8) ; 110b + 8bit address |
EE_93C46_CMD_LENGTH equ 9 ; start bit + cmd + 6bit address |
EE_93C56_CMD_LENGTH equ 11 ; start bit + cmd + 8bit ddress |
VER_RTL8139 equ 1100000b |
VER_RTL8139A equ 1110000b |
; VER_RTL8139AG equ 1110100b |
VER_RTL8139B equ 1111000b |
VER_RTL8130 equ VER_RTL8139B |
VER_RTL8139C equ 1110100b |
VER_RTL8100 equ 1111010b |
VER_RTL8100B equ 1110101b |
VER_RTL8139D equ VER_RTL8100B |
VER_RTL8139CP equ 1110110b |
VER_RTL8101 equ 1110111b |
IDX_RTL8139 equ 0 |
IDX_RTL8139A equ 1 |
IDX_RTL8139B equ 2 |
IDX_RTL8139C equ 3 |
IDX_RTL8100 equ 4 |
IDX_RTL8139D equ 5 |
IDX_RTL8139D equ 6 |
IDX_RTL8101 equ 7 |
; These two must be 4 byte aligned ( which they are ) |
rtl8139_rx_buff equ eth_data_start |
rtl8139_tx_buff equ rtl8139_rx_buff + (RTL8139_RX_BUFFER_SIZE + MAX_ETH_FRAME_SIZE) |
uglobal |
align 4 |
rtl8139_rx_buff_offset: dd 0 |
curr_tx_desc dd 0 |
endg |
iglobal |
hw_ver_array: db VER_RTL8139, VER_RTL8139A, VER_RTL8139B, VER_RTL8139C |
db VER_RTL8100, VER_RTL8139D, VER_RTL8139CP, VER_RTL8101 |
HW_VER_ARRAY_SIZE = $-hw_ver_array |
endg |
uglobal |
hw_ver_id: db 0 |
endg |
;*************************************************************************** |
; Function |
; rtl8139_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
rtl8139_probe: |
; enable the device |
mov al, 2 |
mov ah, [pci_bus] |
mov bh, [pci_dev] |
mov bl, PCI_REG_COMMAND |
call pci_read_reg |
mov cx, ax |
or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) |
and cl, not (1 shl PCI_BIT_MMIO) |
mov al, 2 |
mov ah, [pci_bus] |
mov bh, [pci_dev] |
mov bl, PCI_REG_COMMAND |
call pci_write_reg |
; get chip version |
mov edx, [io_addr] |
add edx, RTL8139_REG_TXCONFIG_2 |
in ax, dx |
shr ah, 2 |
shr ax, 6 |
and al, 01111111b |
mov ecx, HW_VER_ARRAY_SIZE-1 |
.chip_ver_loop: |
cmp al, [hw_ver_array+ecx] |
je .chip_ver_found |
dec ecx |
jns .chip_ver_loop |
xor cl, cl ; default RTL8139 |
.chip_ver_found: |
mov [hw_ver_id], cl |
; wake up the chip |
mov edx, [io_addr] |
add edx, RTL8139_REG_HLTCLK |
mov al, 'R' ; run the clock |
out dx, al |
; unlock config and BMCR registers |
add edx, RTL8139_REG_9346CR - RTL8139_REG_HLTCLK |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) |
out dx, al |
; enable power management |
add edx, RTL8139_REG_CONFIG1 - RTL8139_REG_9346CR |
in al, dx |
cmp byte [hw_ver_id], IDX_RTL8139B |
jl .old_chip |
; set LWAKE pin to active high (default value). |
; it is for Wake-On-LAN functionality of some motherboards. |
; this signal is used to inform the motherboard to execute a wake-up process. |
; only at newer chips. |
or al, (1 shl RTL8139_BIT_PMEn) |
and al, not (1 shl RTL8139_BIT_LWACT) |
out dx, al |
add edx, RTL8139_REG_CONFIG4 - RTL8139_REG_CONFIG1 |
in al, dx |
and al, not (1 shl RTL8139_BIT_LWPTN) |
out dx, al |
jmp .finish_wake_up |
.old_chip: |
; wake up older chips |
and al, not ((1 shl RTL8139_BIT_SLEEP) or (1 shl RTL8139_BIT_PWRDWN)) |
out dx, al |
.finish_wake_up: |
; lock config and BMCR registers |
xor al, al |
mov edx, [io_addr] |
add edx, RTL8139_REG_9346CR |
out dx, al |
;*************************************************************************** |
; Function |
; rt8139_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
rtl8139_reset: |
mov edx, [io_addr] |
add edx, RTL8139_REG_COMMAND |
mov al, 1 shl RTL8139_BIT_RST |
out dx, al |
mov cx, 1000 ; wait no longer for the reset |
.wait_for_reset: |
in al, dx |
test al, 1 shl RTL8139_BIT_RST |
jz .reset_completed ; RST remains 1 during reset |
dec cx |
jns .wait_for_reset |
.reset_completed: |
; get MAC (hardware address) |
mov ecx, 2 |
.mac_read_loop: |
lea eax, [EE_93C46_REG_ETH_ID+ecx] |
push ecx |
call rtl8139_read_eeprom |
pop ecx |
mov [node_addr+ecx*2], ax |
dec ecx |
jns .mac_read_loop |
; unlock config and BMCR registers |
mov edx, [io_addr] |
add edx, RTL8139_REG_9346CR |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) |
out dx, al |
; initialize multicast registers (no filtering) |
mov eax, 0xffffffff |
add edx, RTL8139_REG_MAR0 - RTL8139_REG_9346CR |
out dx, eax |
add edx, RTL8139_REG_MAR4 - RTL8139_REG_MAR0 |
out dx, eax |
; enable Rx/Tx |
mov al, (1 shl RTL8139_BIT_RE) or (1 shl RTL8139_BIT_TE) |
add edx, RTL8139_REG_COMMAND - RTL8139_REG_MAR4 |
out dx, al |
; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold |
; accept broadcast packets, accept physical match packets |
mov eax, RTL8139_RX_CONFIG |
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND |
out dx, eax |
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144 |
mov eax, (RTL8139_TX_MXDMA shl RTL8139_BIT_TX_MXDMA) \ |
or (RTL8139_TXRR shl RTL8139_BIT_TXRR) |
add edx, RTL8139_REG_TXCONFIG - RTL8139_REG_RXCONFIG |
out dx, eax |
; enable auto negotiation |
add edx, RTL8139_REG_BMCR - RTL8139_REG_TXCONFIG |
in ax, dx |
or ax, (1 shl RTL8139_BIT_ANE) |
out dx, ax |
; set auto negotiation advertisement |
add edx, RTL8139_REG_ANAR - RTL8139_REG_BMCR |
in ax, dx |
or ax, (1 shl RTL8139_BIT_SELECTOR) or (1 shl RTL8139_BIT_10) \ |
or (1 shl RTL8139_BIT_10FD) or (1 shl RTL8139_BIT_TX) \ |
or (1 shl RTL8139_BIT_TXFD) |
out dx, ax |
; lock config and BMCR registers |
xor eax, eax |
add edx, RTL8139_REG_9346CR - RTL8139_REG_ANAR |
out dx, al |
; init RX/TX pointers |
mov [rtl8139_rx_buff_offset], eax |
mov [curr_tx_desc], eax |
; clear missing packet counter |
add edx, RTL8139_REG_MPC - RTL8139_REG_9346CR |
out dx, eax |
; disable all interrupts |
add edx, RTL8139_REG_IMR - RTL8139_REG_MPC |
out dx, ax |
; set RxBuffer address, init RX buffer offset, init TX ring |
mov eax, rtl8139_rx_buff ; simba |
sub eax,OS_BASE |
add edx, RTL8139_REG_RBSTART - RTL8139_REG_IMR |
out dx, eax |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
;*************************************************************************** |
; Function |
; rtl8139_read_eeprom |
; Description |
; reads eeprom type 93c46 and 93c56 |
; Parameters |
; al - word to be read (6bit in case of 93c46 and 8bit otherwise) |
; Return value |
; ax - word read in |
; Destroyed register(s) |
; eax, cx, ebx, edx |
; |
;*************************************************************************** |
rtl8139_read_eeprom: |
movzx ebx, al |
mov edx, [io_addr] |
add edx, RTL8139_REG_RXCONFIG |
in al, dx |
test al, (1 shl RTL8139_BIT_9356SEL) |
jz .type_93c46 |
; and bl, 01111111b ; don't care first bit |
or bx, EE_93C56_READ_CMD ; it contains start bit |
mov cx, EE_93C56_CMD_LENGTH-1 ; cmd_loop counter |
jmp .read_eeprom |
.type_93c46: |
and bl, 00111111b |
or bx, EE_93C46_READ_CMD ; it contains start bit |
mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter |
.read_eeprom: |
add edx, RTL8139_REG_9346CR - RTL8139_REG_RXCONFIG_0 |
; mov al, (1 shl RTL8139_BIT_93C46_EEM1) |
; out dx, al |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ |
or (1 shl RTL8139_BIT_93C46_EECS) ; wake up the eeprom |
out dx, al |
.cmd_loop: |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) |
bt bx, cx |
jnc .zero_bit |
or al, (1 shl RTL8139_BIT_93C46_EEDI) |
.zero_bit: |
out dx, al |
; push eax |
; in eax, dx ; eeprom delay |
; pop eax |
or al, (1 shl RTL8139_BIT_93C46_EESK) |
out dx, al |
; in eax, dx ; eeprom delay |
dec cx |
jns .cmd_loop |
; in eax, dx ; eeprom delay |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) |
out dx, al |
mov cl, 0xf |
.read_loop: |
shl ebx, 1 |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ |
or (1 shl RTL8139_BIT_93C46_EECS) \ |
or (1 shl RTL8139_BIT_93C46_EESK) |
out dx, al |
; in eax, dx ; eeprom delay |
in al, dx |
and al, (1 shl RTL8139_BIT_93C46_EEDO) |
jz .dont_set |
inc ebx |
.dont_set: |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ |
or (1 shl RTL8139_BIT_93C46_EECS) |
out dx, al |
; in eax, dx ; eeprom delay |
dec cl |
jns .read_loop |
xor al, al |
out dx, al |
mov ax, bx |
ret |
;*************************************************************************** |
; Function |
; rtl8139_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; Size of packet in ecx |
; Pointer to packet data in esi |
; Destroyed registers |
; eax, edx, esi, edi |
; ToDo |
; for waiting of timeout the rtl8139 internal timer |
; should be used |
; |
;*************************************************************************** |
rtl8139_transmit: |
cmp ecx, MAX_ETH_FRAME_SIZE |
jg .finish ; packet is too long |
push ecx |
; check descriptor |
mov ecx, [curr_tx_desc] |
mov edx, [io_addr] |
lea edx, [edx+ecx*4+RTL8139_REG_TSD0] |
push edx ebx |
in ax, dx |
test ax, 0x1fff ; or no size given |
jz .send_packet |
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) |
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) |
jz .send_packet |
; wait for timeout |
mov ebx, RTL8139_TX_TIMEOUT |
mov eax, 0x5 ; delay x/100 secs |
int 0x40 |
in ax, dx |
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) |
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) |
jz .send_packet |
; chip hung, reset it |
call rtl8139_reset |
; reset the card |
.send_packet: |
; calculate tx_buffer address |
pop ebx |
push esi |
mov eax, MAX_ETH_FRAME_SIZE |
mul dword [curr_tx_desc] |
mov esi, edi |
lea edi, [rtl8139_tx_buff+eax] |
mov eax, edi |
cld |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi, node_addr |
movsd |
movsw |
; copy packet type |
mov [edi], bx |
add edi, 2 |
; copy the packet data |
pop esi edx ecx |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
push ecx |
and ecx, 3 |
rep movsb |
; set address |
sub eax,OS_BASE |
add edx, RTL8139_REG_TSAD0 - RTL8139_REG_TSD0 |
out dx, eax |
; set size and early threshold |
pop eax ; pick up the size |
add eax, ETH_HLEN |
cmp eax, ETH_ZLEN |
jnc .no_pad |
mov eax, ETH_ZLEN |
.no_pad: |
or eax, (RTL8139_ERTXTH shl RTL8139_BIT_ERTXTH) |
add edx, RTL8139_REG_TSD0 - RTL8139_REG_TSAD0 |
out dx, eax |
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ... |
inc dword [curr_tx_desc] |
and dword [curr_tx_desc], 3 |
.finish: |
ret |
;*************************************************************************** |
; Function |
; rtl8139_poll |
; |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Destroyed register(s) |
; eax, edx, ecx |
; |
;*************************************************************************** |
rtl8139_poll: |
mov word [eth_rx_data_len], 0 |
mov edx, [io_addr] |
add edx, RTL8139_REG_COMMAND |
in al, dx |
test al, (1 shl RTL8139_BIT_BUFE) |
jnz .finish |
; new packet received copy it from rx_buffer into Ether_buffer |
mov eax, rtl8139_rx_buff |
add eax, [rtl8139_rx_buff_offset] |
; check if packet is ok |
test byte [eax], (1 shl RTL8139_BIT_ROK) |
jz .reset_rx |
; packet is ok copy it into the Ether_buffer |
movzx ecx, word [eax+2] ; packet length |
sub ecx, 4 ; don't copy CRC |
mov word [eth_rx_data_len], cx |
push ecx |
shr ecx, 2 ; first copy dword-wise |
lea esi, [eax+4] ; don't copy the packet header |
mov edi, Ether_buffer |
cld |
rep movsd ; copy the dwords |
pop ecx |
and ecx, 3 |
rep movsb ; copy the rest bytes |
; update rtl8139_rx_buff_offset |
movzx eax, word [eax+2] ; packet length |
add eax, [rtl8139_rx_buff_offset] |
add eax, 4+3 ; packet header is 4 bytes long + dword alignment |
and eax, not 3 ; dword alignment |
cmp eax, RTL8139_RX_BUFFER_SIZE |
jl .no_wrap |
sub eax, RTL8139_RX_BUFFER_SIZE |
.no_wrap: |
mov [rtl8139_rx_buff_offset], eax |
; update CAPR register |
sub eax, 0x10 ; value 0x10 is a constant for CAPR |
add edx, RTL8139_REG_CAPR - RTL8139_REG_COMMAND |
out dx, ax |
.finish: |
; clear active interrupt sources |
mov edx, [io_addr] |
add edx, RTL8139_REG_ISR |
in ax, dx |
out dx, ax |
ret |
.reset_rx: |
in al, dx ; read command register |
push eax |
and al, not (1 shl RTL8139_BIT_RE) |
out dx, al |
pop eax |
out dx, al |
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND |
mov ax, RTL8139_RX_CONFIG |
out dx, ax |
ret |
rtl8139_cable: |
pusha |
mov edx, [io_addr] |
add edx, 0x58 |
in al,dx |
test al,1 SHL 2 |
jnz .notconnected |
popa |
xor al,al |
inc al |
ret |
.notconnected: |
popa |
xor al,al |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; RTL8139.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.2 11 August 2003 ;; |
;; ;; |
;; Driver for chips of RealTek 8139 family ;; |
;; References: ;; |
;; www.realtek.com.hw - data sheets ;; |
;; rtl8139.c - linux driver ;; |
;; 8139too.c - linux driver ;; |
;; ethernet driver template by Mike Hibbett ;; |
;; ;; |
;; The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; Copyright 2003 Endre Kozma, ;; |
;; endre.kozma@axelero.hu ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; 10.01.2007 Bugfix for l8139_transmit from Paolo Franchetti ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
ETH_ALEN equ 6 |
ETH_HLEN equ (2 * ETH_ALEN + 2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
PCI_REG_COMMAND equ 0x04 ; command register |
PCI_BIT_PIO equ 0 ; bit0: io space control |
PCI_BIT_MMIO equ 1 ; bit1: memory space control |
PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master |
RTL8139_REG_MAR0 equ 0x08 ; multicast filter register 0 |
RTL8139_REG_MAR4 equ 0x0c ; multicast filter register 4 |
RTL8139_REG_TSD0 equ 0x10 ; transmit status of descriptor |
RTL8139_REG_TSAD0 equ 0x20 ; transmit start address of descriptor |
RTL8139_REG_RBSTART equ 0x30 ; RxBuffer start address |
RTL8139_REG_COMMAND equ 0x37 ; command register |
RTL8139_REG_CAPR equ 0x38 ; current address of packet read |
RTL8139_REG_IMR equ 0x3c ; interrupt mask register |
RTL8139_REG_ISR equ 0x3e ; interrupt status register |
RTL8139_REG_TXCONFIG equ 0x40 ; transmit configuration register |
RTL8139_REG_TXCONFIG_0 equ 0x40 ; transmit configuration register 0 |
RTL8139_REG_TXCONFIG_1 equ 0x41 ; transmit configuration register 1 |
RTL8139_REG_TXCONFIG_2 equ 0x42 ; transmit configuration register 2 |
RTL8139_REG_TXCONFIG_3 equ 0x43 ; transmit configuration register 3 |
RTL8139_REG_RXCONFIG equ 0x44 ; receive configuration register 0 |
RTL8139_REG_RXCONFIG_0 equ 0x44 ; receive configuration register 0 |
RTL8139_REG_RXCONFIG_1 equ 0x45 ; receive configuration register 1 |
RTL8139_REG_RXCONFIG_2 equ 0x46 ; receive configuration register 2 |
RTL8139_REG_RXCONFIG_3 equ 0x47 ; receive configuration register 3 |
RTL8139_REG_MPC equ 0x4c ; missed packet counter |
RTL8139_REG_9346CR equ 0x50 ; serial eeprom 93C46 command register |
RTL8139_REG_CONFIG1 equ 0x52 ; configuration register 1 |
RTL8139_REG_CONFIG4 equ 0x5a ; configuration register 4 |
RTL8139_REG_HLTCLK equ 0x5b ; undocumented halt clock register |
RTL8139_REG_BMCR equ 0x62 ; basic mode control register |
RTL8139_REG_ANAR equ 0x66 ; auto negotiation advertisement register |
; 5.1 packet header |
RTL8139_BIT_RUNT equ 4 ; total packet length < 64 bytes |
RTL8139_BIT_LONG equ 3 ; total packet length > 4k |
RTL8139_BIT_CRC equ 2 ; crc error occured |
RTL8139_BIT_FAE equ 1 ; frame alignment error occured |
RTL8139_BIT_ROK equ 0 ; received packet is ok |
; 5.4 command register |
RTL8139_BIT_RST equ 4 ; reset bit |
RTL8139_BIT_RE equ 3 ; receiver enabled |
RTL8139_BIT_TE equ 2 ; transmitter enabled |
RTL8139_BIT_BUFE equ 0 ; rx buffer is empty, no packet stored |
; 5.6 interrupt status register |
RTL8139_BIT_ISR_TOK equ 2 ; transmit ok |
RTL8139_BIT_ISR_RER equ 1 ; receive error interrupt |
RTL8139_BIT_ISR_ROK equ 0 ; receive ok |
; 5.7 transmit configyration register |
RTL8139_BIT_TX_MXDMA equ 8 ; Max DMA burst size per Tx DMA burst |
RTL8139_BIT_TXRR equ 4 ; Tx Retry count 16+(TXRR*16) |
; 5.8 receive configuration register |
RTL8139_BIT_RXFTH equ 13 ; Rx fifo threshold |
RTL8139_BIT_RBLEN equ 11 ; Ring buffer length indicator |
RTL8139_BIT_RX_MXDMA equ 8 ; Max DMA burst size per Rx DMA burst |
RTL8139_BIT_NOWRAP equ 7 ; transfered data wrapping |
RTL8139_BIT_9356SEL equ 6 ; eeprom selector 9346/9356 |
RTL8139_BIT_AER equ 5 ; accept error packets |
RTL8139_BIT_AR equ 4 ; accept runt packets |
RTL8139_BIT_AB equ 3 ; accept broadcast packets |
RTL8139_BIT_AM equ 2 ; accept multicast packets |
RTL8139_BIT_APM equ 1 ; accept physical match packets |
RTL8139_BIT_AAP equ 0 ; accept all packets |
; 5.9 93C46/93C56 command register |
RTL8139_BIT_93C46_EEM1 equ 7 ; RTL8139 eeprom operating mode1 |
RTL8139_BIT_93C46_EEM0 equ 6 ; RTL8139 eeprom operating mode0 |
RTL8139_BIT_93C46_EECS equ 3 ; chip select |
RTL8139_BIT_93C46_EESK equ 2 ; serial data clock |
RTL8139_BIT_93C46_EEDI equ 1 ; serial data input |
RTL8139_BIT_93C46_EEDO equ 0 ; serial data output |
; 5.11 configuration register 1 |
RTL8139_BIT_LWACT equ 4 ; see RTL8139_REG_CONFIG1 |
RTL8139_BIT_SLEEP equ 1 ; sleep bit at older chips |
RTL8139_BIT_PWRDWN equ 0 ; power down bit at older chips |
RTL8139_BIT_PMEn equ 0 ; power management enabled |
; 5.14 configuration register 4 |
RTL8139_BIT_LWPTN equ 2 ; see RTL8139_REG_CONFIG4 |
; 6.2 transmit status register |
RTL8139_BIT_ERTXTH equ 16 ; early TX threshold |
RTL8139_BIT_TOK equ 15 ; transmit ok |
RTL8139_BIT_OWN equ 13 ; tx DMA operation is completed |
; 6.18 basic mode control register |
RTL8139_BIT_ANE equ 12 ; auto negotiation enable |
; 6.20 auto negotiation advertisement register |
RTL8139_BIT_TXFD equ 8 ; 100base-T full duplex |
RTL8139_BIT_TX equ 7 ; 100base-T |
RTL8139_BIT_10FD equ 6 ; 10base-T full duplex |
RTL8139_BIT_10 equ 5 ; 10base-T |
RTL8139_BIT_SELECTOR equ 0 ; binary encoded selector CSMA/CD=00001 |
; RX/TX buffer size |
RTL8139_RBLEN equ 0 ; 0==8K 1==16k 2==32k 3==64k |
RTL8139_RX_BUFFER_SIZE equ (8192 shl RTL8139_RBLEN) |
MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC |
RTL8139_NUM_TX_DESC equ 4 |
RTL8139_TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE * RTL8139_NUM_TX_DESC) |
RTL8139_TXRR equ 8 ; total retries = 16+(TXRR*16) |
RTL8139_TX_MXDMA equ 6 ; 0==16 1==32 2==64 3==128 |
; 4==256 5==512 6==1024 7==2048 |
RTL8139_ERTXTH equ 8 ; in unit of 32 bytes e.g:(8*32)=256 |
RTL8139_RX_MXDMA equ 7 ; 0==16 1==32 2==64 3==128 |
; 4==256 5==512 6==1024 7==unlimited |
RTL8139_RXFTH equ 7 ; 0==16 1==32 2==64 3==128 |
; 4==256 5==512 6==1024 7==no threshold |
RTL8139_RX_CONFIG equ ((RTL8139_RBLEN shl RTL8139_BIT_RBLEN) \ |
or (RTL8139_RX_MXDMA shl RTL8139_BIT_RX_MXDMA) \ |
or (1 shl RTL8139_BIT_NOWRAP) \ |
or (RTL8139_RXFTH shl RTL8139_BIT_RXFTH) \ |
or (1 shl RTL8139_BIT_AB) or (1 shl RTL8139_BIT_APM) \ |
or (1 shl RTL8139_BIT_AER) or (1 shl RTL8139_BIT_AR) \ |
or (1 shl RTL8139_BIT_AM)) |
RTL8139_TX_TIMEOUT equ 30 ; 300 milliseconds timeout |
EE_93C46_REG_ETH_ID equ 7 ; MAC offset |
EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address |
EE_93C56_READ_CMD equ (6 shl 8) ; 110b + 8bit address |
EE_93C46_CMD_LENGTH equ 9 ; start bit + cmd + 6bit address |
EE_93C56_CMD_LENGTH equ 11 ; start bit + cmd + 8bit ddress |
VER_RTL8139 equ 1100000b |
VER_RTL8139A equ 1110000b |
; VER_RTL8139AG equ 1110100b |
VER_RTL8139B equ 1111000b |
VER_RTL8130 equ VER_RTL8139B |
VER_RTL8139C equ 1110100b |
VER_RTL8100 equ 1111010b |
VER_RTL8100B equ 1110101b |
VER_RTL8139D equ VER_RTL8100B |
VER_RTL8139CP equ 1110110b |
VER_RTL8101 equ 1110111b |
IDX_RTL8139 equ 0 |
IDX_RTL8139A equ 1 |
IDX_RTL8139B equ 2 |
IDX_RTL8139C equ 3 |
IDX_RTL8100 equ 4 |
IDX_RTL8139D equ 5 |
IDX_RTL8139D equ 6 |
IDX_RTL8101 equ 7 |
; These two must be 4 byte aligned ( which they are ) |
rtl8139_rx_buff equ eth_data_start |
rtl8139_tx_buff equ rtl8139_rx_buff + (RTL8139_RX_BUFFER_SIZE + MAX_ETH_FRAME_SIZE) |
uglobal |
align 4 |
rtl8139_rx_buff_offset: |
dd 0 |
curr_tx_desc dd 0 |
endg |
iglobal |
hw_ver_array: |
db VER_RTL8139, VER_RTL8139A, VER_RTL8139B, VER_RTL8139C |
db VER_RTL8100, VER_RTL8139D, VER_RTL8139CP, VER_RTL8101 |
HW_VER_ARRAY_SIZE = $-hw_ver_array |
endg |
uglobal |
hw_ver_id: |
db 0 |
endg |
;*************************************************************************** |
; Function |
; rtl8139_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
rtl8139_probe: |
; enable the device |
mov al, 2 |
mov ah, [pci_bus] |
mov bh, [pci_dev] |
mov bl, PCI_REG_COMMAND |
call pci_read_reg |
mov cx, ax |
or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) |
and cl, not (1 shl PCI_BIT_MMIO) |
mov al, 2 |
mov ah, [pci_bus] |
mov bh, [pci_dev] |
mov bl, PCI_REG_COMMAND |
call pci_write_reg |
; get chip version |
mov edx, [io_addr] |
add edx, RTL8139_REG_TXCONFIG_2 |
in ax, dx |
shr ah, 2 |
shr ax, 6 |
and al, 01111111b |
mov ecx, HW_VER_ARRAY_SIZE-1 |
.chip_ver_loop: |
cmp al, [hw_ver_array+ecx] |
je .chip_ver_found |
dec ecx |
jns .chip_ver_loop |
xor cl, cl ; default RTL8139 |
.chip_ver_found: |
mov [hw_ver_id], cl |
; wake up the chip |
mov edx, [io_addr] |
add edx, RTL8139_REG_HLTCLK |
mov al, 'R' ; run the clock |
out dx, al |
; unlock config and BMCR registers |
add edx, RTL8139_REG_9346CR - RTL8139_REG_HLTCLK |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) |
out dx, al |
; enable power management |
add edx, RTL8139_REG_CONFIG1 - RTL8139_REG_9346CR |
in al, dx |
cmp byte [hw_ver_id], IDX_RTL8139B |
jl .old_chip |
; set LWAKE pin to active high (default value). |
; it is for Wake-On-LAN functionality of some motherboards. |
; this signal is used to inform the motherboard to execute a wake-up process. |
; only at newer chips. |
or al, (1 shl RTL8139_BIT_PMEn) |
and al, not (1 shl RTL8139_BIT_LWACT) |
out dx, al |
add edx, RTL8139_REG_CONFIG4 - RTL8139_REG_CONFIG1 |
in al, dx |
and al, not (1 shl RTL8139_BIT_LWPTN) |
out dx, al |
jmp .finish_wake_up |
.old_chip: |
; wake up older chips |
and al, not ((1 shl RTL8139_BIT_SLEEP) or (1 shl RTL8139_BIT_PWRDWN)) |
out dx, al |
.finish_wake_up: |
; lock config and BMCR registers |
xor al, al |
mov edx, [io_addr] |
add edx, RTL8139_REG_9346CR |
out dx, al |
;*************************************************************************** |
; Function |
; rt8139_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
rtl8139_reset: |
mov edx, [io_addr] |
add edx, RTL8139_REG_COMMAND |
mov al, 1 shl RTL8139_BIT_RST |
out dx, al |
mov cx, 1000 ; wait no longer for the reset |
.wait_for_reset: |
in al, dx |
test al, 1 shl RTL8139_BIT_RST |
jz .reset_completed ; RST remains 1 during reset |
dec cx |
jns .wait_for_reset |
.reset_completed: |
; get MAC (hardware address) |
mov ecx, 2 |
.mac_read_loop: |
lea eax, [EE_93C46_REG_ETH_ID+ecx] |
push ecx |
call rtl8139_read_eeprom |
pop ecx |
mov [node_addr+ecx*2], ax |
dec ecx |
jns .mac_read_loop |
; unlock config and BMCR registers |
mov edx, [io_addr] |
add edx, RTL8139_REG_9346CR |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) |
out dx, al |
; initialize multicast registers (no filtering) |
mov eax, 0xffffffff |
add edx, RTL8139_REG_MAR0 - RTL8139_REG_9346CR |
out dx, eax |
add edx, RTL8139_REG_MAR4 - RTL8139_REG_MAR0 |
out dx, eax |
; enable Rx/Tx |
mov al, (1 shl RTL8139_BIT_RE) or (1 shl RTL8139_BIT_TE) |
add edx, RTL8139_REG_COMMAND - RTL8139_REG_MAR4 |
out dx, al |
; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold |
; accept broadcast packets, accept physical match packets |
mov eax, RTL8139_RX_CONFIG |
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND |
out dx, eax |
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144 |
mov eax, (RTL8139_TX_MXDMA shl RTL8139_BIT_TX_MXDMA) \ |
or (RTL8139_TXRR shl RTL8139_BIT_TXRR) |
add edx, RTL8139_REG_TXCONFIG - RTL8139_REG_RXCONFIG |
out dx, eax |
; enable auto negotiation |
add edx, RTL8139_REG_BMCR - RTL8139_REG_TXCONFIG |
in ax, dx |
or ax, (1 shl RTL8139_BIT_ANE) |
out dx, ax |
; set auto negotiation advertisement |
add edx, RTL8139_REG_ANAR - RTL8139_REG_BMCR |
in ax, dx |
or ax, (1 shl RTL8139_BIT_SELECTOR) or (1 shl RTL8139_BIT_10) \ |
or (1 shl RTL8139_BIT_10FD) or (1 shl RTL8139_BIT_TX) \ |
or (1 shl RTL8139_BIT_TXFD) |
out dx, ax |
; lock config and BMCR registers |
xor eax, eax |
add edx, RTL8139_REG_9346CR - RTL8139_REG_ANAR |
out dx, al |
; init RX/TX pointers |
mov [rtl8139_rx_buff_offset], eax |
mov [curr_tx_desc], eax |
; clear missing packet counter |
add edx, RTL8139_REG_MPC - RTL8139_REG_9346CR |
out dx, eax |
; disable all interrupts |
add edx, RTL8139_REG_IMR - RTL8139_REG_MPC |
out dx, ax |
; set RxBuffer address, init RX buffer offset, init TX ring |
mov eax, rtl8139_rx_buff ; simba |
sub eax, OS_BASE |
add edx, RTL8139_REG_RBSTART - RTL8139_REG_IMR |
out dx, eax |
; Indicate that we have successfully reset the card |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
;*************************************************************************** |
; Function |
; rtl8139_read_eeprom |
; Description |
; reads eeprom type 93c46 and 93c56 |
; Parameters |
; al - word to be read (6bit in case of 93c46 and 8bit otherwise) |
; Return value |
; ax - word read in |
; Destroyed register(s) |
; eax, cx, ebx, edx |
; |
;*************************************************************************** |
rtl8139_read_eeprom: |
movzx ebx, al |
mov edx, [io_addr] |
add edx, RTL8139_REG_RXCONFIG |
in al, dx |
test al, (1 shl RTL8139_BIT_9356SEL) |
jz .type_93c46 |
; and bl, 01111111b ; don't care first bit |
or bx, EE_93C56_READ_CMD ; it contains start bit |
mov cx, EE_93C56_CMD_LENGTH-1 ; cmd_loop counter |
jmp .read_eeprom |
.type_93c46: |
and bl, 00111111b |
or bx, EE_93C46_READ_CMD ; it contains start bit |
mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter |
.read_eeprom: |
add edx, RTL8139_REG_9346CR - RTL8139_REG_RXCONFIG_0 |
; mov al, (1 shl RTL8139_BIT_93C46_EEM1) |
; out dx, al |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ |
or (1 shl RTL8139_BIT_93C46_EECS) ; wake up the eeprom |
out dx, al |
.cmd_loop: |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) |
bt bx, cx |
jnc .zero_bit |
or al, (1 shl RTL8139_BIT_93C46_EEDI) |
.zero_bit: |
out dx, al |
; push eax |
; in eax, dx ; eeprom delay |
; pop eax |
or al, (1 shl RTL8139_BIT_93C46_EESK) |
out dx, al |
; in eax, dx ; eeprom delay |
dec cx |
jns .cmd_loop |
; in eax, dx ; eeprom delay |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) |
out dx, al |
mov cl, 0xf |
.read_loop: |
shl ebx, 1 |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ |
or (1 shl RTL8139_BIT_93C46_EECS) \ |
or (1 shl RTL8139_BIT_93C46_EESK) |
out dx, al |
; in eax, dx ; eeprom delay |
in al, dx |
and al, (1 shl RTL8139_BIT_93C46_EEDO) |
jz .dont_set |
inc ebx |
.dont_set: |
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ |
or (1 shl RTL8139_BIT_93C46_EECS) |
out dx, al |
; in eax, dx ; eeprom delay |
dec cl |
jns .read_loop |
xor al, al |
out dx, al |
mov ax, bx |
ret |
;*************************************************************************** |
; Function |
; rtl8139_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; Size of packet in ecx |
; Pointer to packet data in esi |
; Destroyed registers |
; eax, edx, esi, edi |
; ToDo |
; for waiting of timeout the rtl8139 internal timer |
; should be used |
; |
;*************************************************************************** |
rtl8139_transmit: |
cmp ecx, MAX_ETH_FRAME_SIZE |
jg .finish ; packet is too long |
push ecx |
; check descriptor |
mov ecx, [curr_tx_desc] |
mov edx, [io_addr] |
lea edx, [edx+ecx*4+RTL8139_REG_TSD0] |
push edx ebx |
in ax, dx |
test ax, 0x1fff ; or no size given |
jz .send_packet |
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) |
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) |
jz .send_packet |
; wait for timeout |
mov ebx, RTL8139_TX_TIMEOUT |
mov eax, 0x5 ; delay x/100 secs |
int 0x40 |
in ax, dx |
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) |
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) |
jz .send_packet |
; chip hung, reset it |
call rtl8139_reset |
; reset the card |
.send_packet: |
; calculate tx_buffer address |
pop ebx |
push esi |
mov eax, MAX_ETH_FRAME_SIZE |
mul dword [curr_tx_desc] |
mov esi, edi |
lea edi, [rtl8139_tx_buff+eax] |
mov eax, edi |
cld |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi, node_addr |
movsd |
movsw |
; copy packet type |
mov [edi], bx |
add edi, 2 |
; copy the packet data |
pop esi edx ecx |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
push ecx |
and ecx, 3 |
rep movsb |
; set address |
sub eax, OS_BASE |
add edx, RTL8139_REG_TSAD0 - RTL8139_REG_TSD0 |
out dx, eax |
; set size and early threshold |
pop eax ; pick up the size |
add eax, ETH_HLEN |
cmp eax, ETH_ZLEN |
jnc .no_pad |
mov eax, ETH_ZLEN |
.no_pad: |
or eax, (RTL8139_ERTXTH shl RTL8139_BIT_ERTXTH) |
add edx, RTL8139_REG_TSD0 - RTL8139_REG_TSAD0 |
out dx, eax |
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ... |
inc dword [curr_tx_desc] |
and dword [curr_tx_desc], 3 |
.finish: |
ret |
;*************************************************************************** |
; Function |
; rtl8139_poll |
; |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Destroyed register(s) |
; eax, edx, ecx |
; |
;*************************************************************************** |
rtl8139_poll: |
mov word [eth_rx_data_len], 0 |
mov edx, [io_addr] |
add edx, RTL8139_REG_COMMAND |
in al, dx |
test al, (1 shl RTL8139_BIT_BUFE) |
jnz .finish |
; new packet received copy it from rx_buffer into Ether_buffer |
mov eax, rtl8139_rx_buff |
add eax, [rtl8139_rx_buff_offset] |
; check if packet is ok |
test byte [eax], (1 shl RTL8139_BIT_ROK) |
jz .reset_rx |
; packet is ok copy it into the Ether_buffer |
movzx ecx, word [eax+2] ; packet length |
sub ecx, 4 ; don't copy CRC |
mov word [eth_rx_data_len], cx |
push ecx |
shr ecx, 2 ; first copy dword-wise |
lea esi, [eax+4] ; don't copy the packet header |
mov edi, Ether_buffer |
cld |
rep movsd ; copy the dwords |
pop ecx |
and ecx, 3 |
rep movsb ; copy the rest bytes |
; update rtl8139_rx_buff_offset |
movzx eax, word [eax+2] ; packet length |
add eax, [rtl8139_rx_buff_offset] |
add eax, 4+3 ; packet header is 4 bytes long + dword alignment |
and eax, not 3 ; dword alignment |
cmp eax, RTL8139_RX_BUFFER_SIZE |
jl .no_wrap |
sub eax, RTL8139_RX_BUFFER_SIZE |
.no_wrap: |
mov [rtl8139_rx_buff_offset], eax |
; update CAPR register |
sub eax, 0x10 ; value 0x10 is a constant for CAPR |
add edx, RTL8139_REG_CAPR - RTL8139_REG_COMMAND |
out dx, ax |
.finish: |
; clear active interrupt sources |
mov edx, [io_addr] |
add edx, RTL8139_REG_ISR |
in ax, dx |
out dx, ax |
ret |
.reset_rx: |
in al, dx ; read command register |
push eax |
and al, not (1 shl RTL8139_BIT_RE) |
out dx, al |
pop eax |
out dx, al |
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND |
mov ax, RTL8139_RX_CONFIG |
out dx, ax |
ret |
rtl8139_cable: |
pusha |
mov edx, [io_addr] |
add edx, 0x58 |
in al, dx |
test al, 1 SHL 2 |
jnz .notconnected |
popa |
xor al, al |
inc al |
ret |
.notconnected: |
popa |
xor al, al |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/drivers/rtl8169.inc |
---|
1,1219 → 1,1239 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; RTL8169.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.1 11 February 2007 ;; |
;; ;; |
;; Driver for chips of RealTek 8169 family ;; |
;; References: ;; |
;; r8169.c - linux driver (etherboot project) ;; |
;; ethernet driver template by Mike Hibbett ;; |
;; ;; |
;; The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; Copyright 2007 mike.dld, ;; |
;; mike.dld@gmail.com ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
ETH_ALEN equ 6 |
ETH_HLEN equ (2 * ETH_ALEN + 2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
RTL8169_REG_MAC0 equ 0x0 ; Ethernet hardware address |
RTL8169_REG_MAR0 equ 0x8 ; Multicast filter |
RTL8169_REG_TxDescStartAddr equ 0x20 |
RTL8169_REG_TxHDescStartAddr equ 0x28 |
RTL8169_REG_FLASH equ 0x30 |
RTL8169_REG_ERSR equ 0x36 |
RTL8169_REG_ChipCmd equ 0x37 |
RTL8169_REG_TxPoll equ 0x38 |
RTL8169_REG_IntrMask equ 0x3C |
RTL8169_REG_IntrStatus equ 0x3E |
RTL8169_REG_TxConfig equ 0x40 |
RTL8169_REG_RxConfig equ 0x44 |
RTL8169_REG_RxMissed equ 0x4C |
RTL8169_REG_Cfg9346 equ 0x50 |
RTL8169_REG_Config0 equ 0x51 |
RTL8169_REG_Config1 equ 0x52 |
RTL8169_REG_Config2 equ 0x53 |
RTL8169_REG_Config3 equ 0x54 |
RTL8169_REG_Config4 equ 0x55 |
RTL8169_REG_Config5 equ 0x56 |
RTL8169_REG_MultiIntr equ 0x5C |
RTL8169_REG_PHYAR equ 0x60 |
RTL8169_REG_TBICSR equ 0x64 |
RTL8169_REG_TBI_ANAR equ 0x68 |
RTL8169_REG_TBI_LPAR equ 0x6A |
RTL8169_REG_PHYstatus equ 0x6C |
RTL8169_REG_RxMaxSize equ 0xDA |
RTL8169_REG_CPlusCmd equ 0xE0 |
RTL8169_REG_RxDescStartAddr equ 0xE4 |
RTL8169_REG_ETThReg equ 0xEC |
RTL8169_REG_FuncEvent equ 0xF0 |
RTL8169_REG_FuncEventMask equ 0xF4 |
RTL8169_REG_FuncPresetState equ 0xF8 |
RTL8169_REG_FuncForceEvent equ 0xFC |
; InterruptStatusBits |
RTL8169_ISB_SYSErr equ 0x8000 |
RTL8169_ISB_PCSTimeout equ 0x4000 |
RTL8169_ISB_SWInt equ 0x0100 |
RTL8169_ISB_TxDescUnavail equ 0x80 |
RTL8169_ISB_RxFIFOOver equ 0x40 |
RTL8169_ISB_LinkChg equ 0x20 |
RTL8169_ISB_RxOverflow equ 0x10 |
RTL8169_ISB_TxErr equ 0x08 |
RTL8169_ISB_TxOK equ 0x04 |
RTL8169_ISB_RxErr equ 0x02 |
RTL8169_ISB_RxOK equ 0x01 |
; RxStatusDesc |
RTL8169_SD_RxRES equ 0x00200000 |
RTL8169_SD_RxCRC equ 0x00080000 |
RTL8169_SD_RxRUNT equ 0x00100000 |
RTL8169_SD_RxRWT equ 0x00400000 |
; ChipCmdBits |
RTL8169_CMD_Reset equ 0x10 |
RTL8169_CMD_RxEnb equ 0x08 |
RTL8169_CMD_TxEnb equ 0x04 |
RTL8169_CMD_RxBufEmpty equ 0x01 |
; Cfg9346Bits |
RTL8169_CFG_9346_Lock equ 0x00 |
RTL8169_CFG_9346_Unlock equ 0xC0 |
; rx_mode_bits |
RTL8169_RXM_AcceptErr equ 0x20 |
RTL8169_RXM_AcceptRunt equ 0x10 |
RTL8169_RXM_AcceptBroadcast equ 0x08 |
RTL8169_RXM_AcceptMulticast equ 0x04 |
RTL8169_RXM_AcceptMyPhys equ 0x02 |
RTL8169_RXM_AcceptAllPhys equ 0x01 |
; RxConfigBits |
RTL8169_RXC_FIFOShift equ 13 |
RTL8169_RXC_DMAShift equ 8 |
; TxConfigBits |
RTL8169_TXC_InterFrameGapShift equ 24 |
RTL8169_TXC_DMAShift equ 8 ; DMA burst value (0-7) is shift this many bits |
; rtl8169_PHYstatus |
RTL8169_PHYS_TBI_Enable equ 0x80 |
RTL8169_PHYS_TxFlowCtrl equ 0x40 |
RTL8169_PHYS_RxFlowCtrl equ 0x20 |
RTL8169_PHYS_1000bpsF equ 0x10 |
RTL8169_PHYS_100bps equ 0x08 |
RTL8169_PHYS_10bps equ 0x04 |
RTL8169_PHYS_LinkStatus equ 0x02 |
RTL8169_PHYS_FullDup equ 0x01 |
; GIGABIT_PHY_registers |
RTL8169_PHY_CTRL_REG equ 0 |
RTL8169_PHY_STAT_REG equ 1 |
RTL8169_PHY_AUTO_NEGO_REG equ 4 |
RTL8169_PHY_1000_CTRL_REG equ 9 |
; GIGABIT_PHY_REG_BIT |
RTL8169_PHY_Restart_Auto_Nego equ 0x0200 |
RTL8169_PHY_Enable_Auto_Nego equ 0x1000 |
; PHY_STAT_REG = 1; |
RTL8169_PHY_Auto_Neco_Comp equ 0x0020 |
; PHY_AUTO_NEGO_REG = 4; |
RTL8169_PHY_Cap_10_Half equ 0x0020 |
RTL8169_PHY_Cap_10_Full equ 0x0040 |
RTL8169_PHY_Cap_100_Half equ 0x0080 |
RTL8169_PHY_Cap_100_Full equ 0x0100 |
; PHY_1000_CTRL_REG = 9; |
RTL8169_PHY_Cap_1000_Full equ 0x0200 |
RTL8169_PHY_Cap_1000_Half equ 0x0100 |
RTL8169_PHY_Cap_PAUSE equ 0x0400 |
RTL8169_PHY_Cap_ASYM_PAUSE equ 0x0800 |
RTL8169_PHY_Cap_Null equ 0x0 |
; _MediaType |
RTL8169_MT_10_Half equ 0x01 |
RTL8169_MT_10_Full equ 0x02 |
RTL8169_MT_100_Half equ 0x04 |
RTL8169_MT_100_Full equ 0x08 |
RTL8169_MT_1000_Full equ 0x10 |
; _TBICSRBit |
RTL8169_TBI_LinkOK equ 0x02000000 |
; _DescStatusBit |
RTL8169_DSB_OWNbit equ 0x80000000 |
RTL8169_DSB_EORbit equ 0x40000000 |
RTL8169_DSB_FSbit equ 0x20000000 |
RTL8169_DSB_LSbit equ 0x10000000 |
; MAC address length |
MAC_ADDR_LEN equ 6 |
; max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4) |
MAX_ETH_FRAME_SIZE equ 1536 |
TX_FIFO_THRESH equ 256 ; In bytes |
RX_FIFO_THRESH equ 7 ; 7 means NO threshold, Rx buffer level before first PCI xfer |
RX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 |
TX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 |
ETTh equ 0x3F ; 0x3F means NO threshold |
EarlyTxThld equ 0x3F ; 0x3F means NO early transmit |
RxPacketMaxSize equ 0x0800 ; Maximum size supported is 16K-1 |
InterFrameGap equ 0x03 ; 3 means InterFrameGap = the shortest one |
NUM_TX_DESC equ 1 ; Number of Tx descriptor registers |
NUM_RX_DESC equ 4 ; Number of Rx descriptor registers |
RX_BUF_SIZE equ 1536 ; Rx Buffer size |
HZ equ 1000 |
RTL_MIN_IO_SIZE equ 0x80 |
TX_TIMEOUT equ (6*HZ) |
RTL8169_TIMER_EXPIRE_TIME equ 100 |
ETH_HDR_LEN equ 14 |
DEFAULT_MTU equ 1500 |
DEFAULT_RX_BUF_LEN equ 1536 |
;#ifdef RTL8169_JUMBO_FRAME_SUPPORT |
;#define MAX_JUMBO_FRAME_MTU ( 10000 ) |
;#define MAX_RX_SKBDATA_SIZE ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN ) |
;#else |
MAX_RX_SKBDATA_SIZE equ 1600 |
;#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT |
;#ifdef RTL8169_USE_IO |
;!!!#define RTL_W8(reg, val8) outb ((val8), ioaddr + (reg)) |
macro RTL_W8 reg,val8 { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
if ~val8 eq al |
mov al,val8 |
end if |
out dx,al |
} |
;!!!#define RTL_W16(reg, val16) outw ((val16), ioaddr + (reg)) |
macro RTL_W16 reg,val16 { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
if ~val16 eq ax |
mov ax,val16 |
end if |
out dx,ax |
} |
;!!!#define RTL_W32(reg, val32) outl ((val32), ioaddr + (reg)) |
macro RTL_W32 reg,val32 { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
if ~val32 eq eax |
mov eax,val32 |
end if |
out dx,eax |
} |
;!!!#define RTL_R8(reg) inb (ioaddr + (reg)) |
macro RTL_R8 reg { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
in al,dx |
} |
;!!!#define RTL_R16(reg) inw (ioaddr + (reg)) |
macro RTL_R16 reg { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
in ax,dx |
} |
;!!!#define RTL_R32(reg) ((unsigned long) inl (ioaddr + (reg))) |
macro RTL_R32 reg { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
in eax,dx |
} |
;#else |
; write/read MMIO register |
;#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) |
;#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) |
;#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) |
;#define RTL_R8(reg) readb (ioaddr + (reg)) |
;#define RTL_R16(reg) readw (ioaddr + (reg)) |
;#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) |
;#endif |
MCFG_METHOD_01 equ 0x01 |
MCFG_METHOD_02 equ 0x02 |
MCFG_METHOD_03 equ 0x03 |
MCFG_METHOD_04 equ 0x04 |
MCFG_METHOD_05 equ 0x05 |
MCFG_METHOD_11 equ 0x0b |
MCFG_METHOD_12 equ 0x0c |
MCFG_METHOD_13 equ 0x0d |
MCFG_METHOD_14 equ 0x0e |
MCFG_METHOD_15 equ 0x0f |
PCFG_METHOD_1 equ 0x01 ; PHY Reg 0x03 bit0-3 == 0x0000 |
PCFG_METHOD_2 equ 0x02 ; PHY Reg 0x03 bit0-3 == 0x0001 |
PCFG_METHOD_3 equ 0x03 ; PHY Reg 0x03 bit0-3 == 0x0002 |
PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space |
PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space |
PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering |
PCI_LATENCY_TIMER equ 0x0d ; 8 bits |
PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles |
PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate |
PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping |
PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking |
PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping |
PCI_COMMAND_SERR equ 0x100 ; Enable SERR |
PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes |
struc rtl8169_TxDesc { |
.status dd ? |
.vlan_tag dd ? |
.buf_addr dd ? |
.buf_Haddr dd ? |
} |
virtual at 0 |
rtl8169_TxDesc rtl8169_TxDesc |
sizeof.rtl8169_TxDesc = $ - rtl8169_TxDesc |
end virtual |
struc rtl8169_RxDesc { |
.status dd ? |
.vlan_tag dd ? |
.buf_addr dd ? |
.buf_Haddr dd ? |
} |
virtual at 0 |
rtl8169_RxDesc rtl8169_RxDesc |
sizeof.rtl8169_RxDesc = $ - rtl8169_RxDesc |
end virtual |
virtual at eth_data_start |
; Define the TX Descriptor |
align 256 |
rtl8169_tx_ring rb NUM_TX_DESC * sizeof.rtl8169_TxDesc |
; Create a static buffer of size RX_BUF_SZ for each |
; TX Descriptor. All descriptors point to a |
; part of this buffer |
align 256 |
rtl8169_txb rb NUM_TX_DESC * RX_BUF_SIZE |
; Define the RX Descriptor |
align 256 |
rtl8169_rx_ring rb NUM_RX_DESC * sizeof.rtl8169_RxDesc |
; Create a static buffer of size RX_BUF_SZ for each |
; RX Descriptor All descriptors point to a |
; part of this buffer |
align 256 |
rtl8169_rxb rb NUM_RX_DESC * RX_BUF_SIZE |
rtl8169_tpc: |
.mmio_addr dd ? ; memory map physical address |
.chipset dd ? |
.pcfg dd ? |
.mcfg dd ? |
.cur_rx dd ? ; Index into the Rx descriptor buffer of next Rx pkt |
.cur_tx dd ? ; Index into the Tx descriptor buffer of next Rx pkt |
.TxDescArrays dd ? ; Index of Tx Descriptor buffer |
.RxDescArrays dd ? ; Index of Rx Descriptor buffer |
.TxDescArray dd ? ; Index of 256-alignment Tx Descriptor buffer |
.RxDescArray dd ? ; Index of 256-alignment Rx Descriptor buffer |
.RxBufferRing rd NUM_RX_DESC ; Index of Rx Buffer array |
.Tx_skbuff rd NUM_TX_DESC |
end virtual |
rtl8169_intr_mask = RTL8169_ISB_LinkChg or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxFIFOOver or RTL8169_ISB_TxErr or RTL8169_ISB_TxOK or RTL8169_ISB_RxErr or RTL8169_ISB_RxOK |
rtl8169_rx_config = (RX_FIFO_THRESH shl RTL8169_RXC_FIFOShift) or (RX_DMA_BURST shl RTL8169_RXC_DMAShift) or 0x0000000E |
iglobal |
;static struct { |
; const char *name; |
; u8 mcfg; /* depend on RTL8169 docs */ |
; u32 RxConfigMask; /* should clear the bits supported by this chip */ |
;} |
rtl_chip_info dd \ |
MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169 |
MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s |
MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s |
MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb |
MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc |
MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E |
MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E |
MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e // PCI-E 8139 |
MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e // PCI-E 8139 |
MCFG_METHOD_15, 0xff7e1880 ; RTL8100e // PCI-E 8139 |
mac_info dd \ |
0x38800000, MCFG_METHOD_15, \ |
0x38000000, MCFG_METHOD_12, \ |
0x34000000, MCFG_METHOD_13, \ |
0x30800000, MCFG_METHOD_14, \ |
0x30000000, MCFG_METHOD_11, \ |
0x18000000, MCFG_METHOD_05, \ |
0x10000000, MCFG_METHOD_04, \ |
0x04000000, MCFG_METHOD_03, \ |
0x00800000, MCFG_METHOD_02, \ |
0x00000000, MCFG_METHOD_01 ; catch-all |
endg |
PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space |
PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space |
PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering |
PCI_LATENCY_TIMER equ 0x0d ; 8 bits |
PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles |
PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate |
PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping |
PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking |
PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping |
PCI_COMMAND_SERR equ 0x100 ; Enable SERR |
PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes |
PCI_VENDOR_ID equ 0x00 ; 16 bits |
PCI_DEVICE_ID equ 0x02 ; 16 bits |
PCI_COMMAND equ 0x04 ; 16 bits |
PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits |
PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits |
PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits |
PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits |
PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits |
PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits |
PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 |
PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address |
PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] |
PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address |
PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) |
PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) |
PCI_BASE_ADDRESS_SPACE_IO equ 0x01 |
PCI_ROM_ADDRESS equ 0x30 ; 32 bits |
proc CONFIG_CMD,where:byte |
movzx eax,byte[pci_bus] |
shl eax,8 |
mov al,[pci_dev] |
shl eax,8 |
mov al,[where] |
and al,not 3 |
or eax,0x80000000 |
ret |
endp |
proc pci_read_config_byte,where:dword |
push edx |
stdcall CONFIG_CMD,[where] |
mov dx,0xCF8 |
out dx,eax |
mov edx,[where] |
and edx,3 |
add edx,0xCFC |
in al,dx |
pop edx |
ret |
endp |
proc pci_read_config_word,where:dword |
push edx |
stdcall CONFIG_CMD,[where] |
mov dx,0xCF8 |
out dx,eax |
mov edx,[where] |
and edx,2 |
add edx,0xCFC |
in ax,dx |
pop edx |
ret |
endp |
proc pci_read_config_dword,where:dword |
push edx |
stdcall CONFIG_CMD,[where] |
mov edx,0xCF8 |
out dx,eax |
mov edx,0xCFC |
in eax,dx |
pop edx |
ret |
endp |
proc pci_write_config_byte,where:dword,value:byte |
push edx |
stdcall CONFIG_CMD,[where] |
mov dx,0xCF8 |
out dx,eax |
mov edx,[where] |
and edx,3 |
add edx,0xCFC |
mov al,[value] |
out dx,al |
pop edx |
ret |
endp |
proc pci_write_config_word,where:dword,value:word |
push edx |
stdcall CONFIG_CMD,[where] |
mov dx,0xCF8 |
out dx,eax |
mov edx,[where] |
and edx,2 |
add edx,0xCFC |
mov ax,[value] |
out dx,ax |
pop edx |
ret |
endp |
proc pci_write_config_dword,where:dword,value:dword |
push edx |
stdcall CONFIG_CMD,[where] |
mov edx,0xCF8 |
out dx,eax |
mov edx,0xCFC |
mov eax,[value] |
out dx,eax |
pop edx |
ret |
endp |
; Set device to be a busmaster in case BIOS neglected to do so. |
; Also adjust PCI latency timer to a reasonable value, 32. |
proc adjust_pci_device |
; DEBUGF 1,"K : adjust_pci_device\n" |
stdcall pci_read_config_word,PCI_COMMAND |
mov bx,ax |
or bx,PCI_COMMAND_MASTER or PCI_COMMAND_IO |
cmp ax,bx |
je @f |
; DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2 |
stdcall pci_write_config_word,PCI_COMMAND,ebx |
@@: |
stdcall pci_read_config_byte,PCI_LATENCY_TIMER |
cmp al,32 |
jae @f |
; DEBUGF 1,"K : adjust_pci_device: PCI latency timer (CFLT) is unreasonably low at %d.\nK : Setting to 32 clocks.\n",al |
stdcall pci_write_config_byte,PCI_LATENCY_TIMER,32 |
@@: |
ret |
endp |
; Find the start of a pci resource |
proc pci_bar_start,index:dword |
stdcall pci_read_config_dword,[index] |
test eax,PCI_BASE_ADDRESS_SPACE_IO |
jz @f |
and eax,PCI_BASE_ADDRESS_IO_MASK |
jmp .exit |
@@: push eax |
and eax,PCI_BASE_ADDRESS_MEM_TYPE_MASK |
cmp eax,PCI_BASE_ADDRESS_MEM_TYPE_64 |
jne .not64 |
mov eax,[index] |
add eax,4 |
stdcall pci_read_config_dword,eax |
or eax,eax |
jz .not64 |
; DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n" |
add esp,4 |
or eax,-1 |
ret |
.not64: |
pop eax |
and eax,PCI_BASE_ADDRESS_MEM_MASK |
.exit: |
ret |
endp |
proc rtl8169_init_board |
; DEBUGF 1,"K : rtl8169_init_board\n" |
call adjust_pci_device |
stdcall pci_bar_start,PCI_BASE_ADDRESS_0 |
mov [rtl8169_tpc.mmio_addr],eax |
; Soft reset the chip |
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset |
; Check that the chip has finished the reset |
mov ecx,1000 |
@@: RTL_R8 RTL8169_REG_ChipCmd |
test al,RTL8169_CMD_Reset |
jz @f |
stdcall udelay,10 |
loop @b |
@@: |
; identify config method |
RTL_R32 RTL8169_REG_TxConfig |
and eax,0x7c800000 |
; DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax |
mov esi,mac_info-8 |
@@: add esi,8 |
mov ecx,eax |
and ecx,[esi] |
cmp ecx,[esi] |
jne @b |
mov eax,[esi+4] |
mov [rtl8169_tpc.mcfg],eax |
mov [rtl8169_tpc.pcfg],PCFG_METHOD_3 |
stdcall RTL8169_READ_GMII_REG,3 |
and al,0x0f |
or al,al |
jnz @f |
mov [rtl8169_tpc.pcfg],PCFG_METHOD_1 |
jmp .pconf |
@@: dec al |
jnz .pconf |
mov [rtl8169_tpc.pcfg],PCFG_METHOD_2 |
.pconf: |
; identify chip attached to board |
mov ecx,10 |
mov eax,[rtl8169_tpc.mcfg] |
@@: dec ecx |
js @f |
cmp eax,[rtl_chip_info+ecx*8] |
jne @b |
mov [rtl8169_tpc.chipset],ecx |
jmp .match |
@@: |
; if unknown chip, assume array element #0, original RTL-8169 in this case |
; DEBUGF 1,"K : rtl8169_init_board: PCI device: unknown chip version, assuming RTL-8169\n" |
RTL_R32 RTL8169_REG_TxConfig |
; DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax |
mov [rtl8169_tpc.chipset],0 |
xor eax,eax |
inc eax |
ret |
.match: |
xor eax,eax |
ret |
endp |
proc rtl8169_hw_PHY_config |
; DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg] |
; DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg); |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_04 |
jne .not_4 |
; stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0001 |
; stdcall RTL8169_WRITE_GMII_REG,0x1b,0x841e |
; stdcall RTL8169_WRITE_GMII_REG,0x0e,0x7bfb |
; stdcall RTL8169_WRITE_GMII_REG,0x09,0x273a |
stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0002 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0x90D0 |
stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0000 |
jmp .exit |
.not_4: |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_02 |
je @f |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_03 |
jne .not_2_or_3 |
@@: stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0001 |
stdcall RTL8169_WRITE_GMII_REG,0x15,0x1000 |
stdcall RTL8169_WRITE_GMII_REG,0x18,0x65C7 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x0000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0x00A1 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0x0008 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0x1020 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0x1000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x0800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x0000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x7000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0xFF41 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0xDE60 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0x0140 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0x0077 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x7800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x7000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xA000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0xDF01 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0xDF20 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0xFF95 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0xFA00 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xA800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xA000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xB000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0xFF41 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0xDE20 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0x0140 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0x00BB |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xB800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xB000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xF000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0xDF01 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0xDF20 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0xFF95 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0xBF00 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xF800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xF000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x0000 |
stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0000 |
stdcall RTL8169_WRITE_GMII_REG,0x0B,0x0000 |
jmp .exit |
.not_2_or_3: |
; DBG_PRINT("tpc->mcfg=%d. Discard hw PHY config.\n", tpc->mcfg); |
; DEBUGF 1,"K : tpc.mcfg=%d, discard hw PHY config\n",[rtl8169_tpc.mcfg] |
.exit: |
ret |
endp |
;proc pci_write_config_byte |
; ret |
;endp |
proc RTL8169_WRITE_GMII_REG,RegAddr:byte,value:dword |
;;; DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value] |
movzx eax,[RegAddr] |
shl eax,16 |
or eax,[value] |
or eax,0x80000000 |
RTL_W32 RTL8169_REG_PHYAR,eax |
stdcall udelay,1 ;;;1000 |
mov ecx,2000 |
; Check if the RTL8169 has completed writing to the specified MII register |
@@: RTL_R32 RTL8169_REG_PHYAR |
test eax,0x80000000 |
jz .exit |
stdcall udelay,1 ;;;100 |
loop @b |
.exit: |
ret |
endp |
proc RTL8169_READ_GMII_REG,RegAddr:byte |
;;; DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2 |
push ecx |
movzx eax,[RegAddr] |
shl eax,16 |
; or eax,0x0 |
RTL_W32 RTL8169_REG_PHYAR,eax |
stdcall udelay,1 ;;;1000 |
mov ecx,2000 |
; Check if the RTL8169 has completed retrieving data from the specified MII register |
@@: RTL_R32 RTL8169_REG_PHYAR |
test eax,0x80000000 |
jnz .exit |
stdcall udelay,1 ;;;100 |
loop @b |
or eax,-1 |
pop ecx |
ret |
.exit: |
RTL_R32 RTL8169_REG_PHYAR |
and eax,0xFFFF |
pop ecx |
ret |
endp |
proc rtl8169_set_rx_mode |
; DEBUGF 1,"K : rtl8169_set_rx_mode\n" |
; IFF_ALLMULTI |
; Too many to filter perfectly -- accept all multicasts |
RTL_R32 RTL8169_REG_RxConfig |
mov ecx,[rtl8169_tpc.chipset] |
and eax,[rtl_chip_info + ecx * 8 + 4] ; RxConfigMask |
or eax,rtl8169_rx_config or (RTL8169_RXM_AcceptBroadcast or RTL8169_RXM_AcceptMulticast or RTL8169_RXM_AcceptMyPhys) |
RTL_W32 RTL8169_REG_RxConfig,eax |
; Multicast hash filter |
RTL_W32 RTL8169_REG_MAR0 + 0,0xffffffff |
RTL_W32 RTL8169_REG_MAR0 + 4,0xffffffff |
ret |
endp |
proc rtl8169_init_ring |
; DEBUGF 1,"K : rtl8169_init_ring\n" |
xor eax,eax |
mov [rtl8169_tpc.cur_rx],eax |
mov [rtl8169_tpc.cur_tx],eax |
mov edi,[rtl8169_tpc.TxDescArray] |
mov ecx,(NUM_TX_DESC * sizeof.rtl8169_TxDesc) / 4 |
cld |
rep stosd |
mov edi,[rtl8169_tpc.RxDescArray] |
mov ecx,(NUM_RX_DESC * sizeof.rtl8169_RxDesc) / 4 |
rep stosd |
mov edi,rtl8169_tpc.Tx_skbuff |
mov eax,rtl8169_txb |
mov ecx,NUM_TX_DESC |
@@: stosd |
inc eax ; add eax,RX_BUF_SIZE ??? |
loop @b |
;!!! for (i = 0; i < NUM_RX_DESC; i++) { |
;!!! if (i == (NUM_RX_DESC - 1)) |
;!!! tpc->RxDescArray[i].status = (OWNbit | EORbit) | RX_BUF_SIZE; |
;!!! else |
;!!! tpc->RxDescArray[i].status = OWNbit | RX_BUF_SIZE; |
;!!! tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; |
;!!! tpc->RxDescArray[i].buf_addr = virt_to_bus(tpc->RxBufferRing[i]); |
;!!! } |
mov esi,rtl8169_tpc.RxBufferRing |
mov edi,[rtl8169_tpc.RxDescArray] |
mov eax,rtl8169_rxb |
mov ecx,NUM_RX_DESC |
@@: mov [esi],eax |
mov [edi+rtl8169_RxDesc.buf_addr],eax |
sub [edi+rtl8169_RxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 |
mov [edi+rtl8169_RxDesc.status],RTL8169_DSB_OWNbit or RX_BUF_SIZE |
add esi,4 |
add edi,sizeof.rtl8169_RxDesc |
add eax,RX_BUF_SIZE |
loop @b |
or [edi - sizeof.rtl8169_RxDesc + rtl8169_RxDesc.status],RTL8169_DSB_EORbit |
ret |
endp |
proc rtl8169_hw_start |
; DEBUGF 1,"K : rtl8169_hw_start\n" |
; Soft reset the chip |
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset |
; Check that the chip has finished the reset |
mov ecx,1000 |
@@: RTL_R8 RTL8169_REG_ChipCmd |
and al,RTL8169_CMD_Reset |
jz @f |
stdcall udelay,10 |
loop @b |
@@: |
RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Unlock |
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_TxEnb or RTL8169_CMD_RxEnb |
RTL_W8 RTL8169_REG_ETThReg,ETTh |
; For gigabit rtl8169 |
RTL_W16 RTL8169_REG_RxMaxSize,RxPacketMaxSize |
; Set Rx Config register |
RTL_R32 RTL8169_REG_RxConfig |
mov ecx,[rtl8169_tpc.chipset] |
and eax,[rtl_chip_info + ecx * 8 + 4] ; RxConfigMask |
or eax,rtl8169_rx_config |
RTL_W32 RTL8169_REG_RxConfig,eax |
; Set DMA burst size and Interframe Gap Time |
RTL_W32 RTL8169_REG_TxConfig,(TX_DMA_BURST shl RTL8169_TXC_DMAShift) or (InterFrameGap shl RTL8169_TXC_InterFrameGapShift) |
RTL_R16 RTL8169_REG_CPlusCmd |
RTL_W16 RTL8169_REG_CPlusCmd,ax |
RTL_R16 RTL8169_REG_CPlusCmd |
or ax,1 shl 3 |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_02 |
jne @f |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_03 |
jne @f |
or ax,1 shl 14 |
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n" |
jmp .set |
@@:;DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3\n" |
.set: RTL_W16 RTL8169_REG_CPlusCmd,ax |
; RTL_W16 0xE2,0x1517 |
; RTL_W16 0xE2,0x152a |
; RTL_W16 0xE2,0x282a |
RTL_W16 0xE2,0x0000 |
MOV [rtl8169_tpc.cur_rx],0 |
push eax ; shurf 28.09.2008 |
mov eax, [rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 |
sub eax, OS_BASE ; shurf 28.09.2008 |
RTL_W32 RTL8169_REG_TxDescStartAddr,eax ;[rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 |
mov eax, [rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 |
sub eax, OS_BASE ; shurf 28.09.2008 |
RTL_W32 RTL8169_REG_RxDescStartAddr,eax ;[rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 |
pop eax ; shurf 28.09.2008 |
RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Lock |
stdcall udelay,10 |
RTL_W32 RTL8169_REG_RxMissed,0 |
call rtl8169_set_rx_mode |
; no early-rx interrupts |
RTL_R16 RTL8169_REG_MultiIntr |
and ax,0xF000 |
RTL_W16 RTL8169_REG_MultiIntr,ax |
RTL_W16 RTL8169_REG_IntrMask,0 ; rtl8169_intr_mask |
ret |
endp |
proc udelay,msec:dword |
push esi |
mov esi,[msec] |
call delay_ms |
pop esi |
ret |
endp |
;*************************************************************************** |
; Function |
; rtl8169_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
proc rtl8169_probe |
; DEBUGF 1,"K : rtl8169_probe: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 |
call rtl8169_init_board |
mov ecx,MAC_ADDR_LEN |
mov edx,[rtl8169_tpc.mmio_addr] |
add edx,RTL8169_REG_MAC0 |
xor ebx,ebx |
; Get MAC address. FIXME: read EEPROM |
@@: RTL_R8 dx |
mov [node_addr+ebx],al |
inc edx |
inc ebx |
loop @b |
; DEBUGF 1,"K : rtl8169_probe: MAC = %x-%x-%x-%x-%x-%x\n",[node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2 |
; Config PHY |
stdcall rtl8169_hw_PHY_config |
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" |
RTL_W8 0x82,0x01 |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_03 |
jae @f |
; DEBUGF 1,"K : Set PCI Latency=0x40\n" |
; stdcall pci_write_config_byte,PCI_LATENCY_TIMER,0x40 |
@@: |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_02 |
jne @f |
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" |
RTL_W8 0x82,0x01 |
; DEBUGF 1,"K : Set PHY Reg 0x0bh = 0x00h\n" |
stdcall RTL8169_WRITE_GMII_REG,0x0b,0x0000 ; w 0x0b 15 0 0 |
@@: |
; if TBI is not enabled |
RTL_R8 RTL8169_REG_PHYstatus |
test al,RTL8169_PHYS_TBI_Enable |
jz .tbi_dis |
stdcall RTL8169_READ_GMII_REG,RTL8169_PHY_AUTO_NEGO_REG |
; enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged |
and eax,0x0C1F |
or eax,RTL8169_PHY_Cap_10_Half or RTL8169_PHY_Cap_10_Full or RTL8169_PHY_Cap_100_Half or RTL8169_PHY_Cap_100_Full |
stdcall RTL8169_WRITE_GMII_REG,RTL8169_PHY_AUTO_NEGO_REG,eax |
; enable 1000 Full Mode |
stdcall RTL8169_WRITE_GMII_REG,RTL8169_PHY_1000_CTRL_REG,RTL8169_PHY_Cap_1000_Full or RTL8169_PHY_Cap_1000_Half ; rtl8168 |
; Enable auto-negotiation and restart auto-nigotiation |
stdcall RTL8169_WRITE_GMII_REG,RTL8169_PHY_CTRL_REG,RTL8169_PHY_Enable_Auto_Nego or RTL8169_PHY_Restart_Auto_Nego |
stdcall udelay,100 |
mov ecx,10000 |
; wait for auto-negotiation process |
@@: dec ecx |
jz @f |
stdcall RTL8169_READ_GMII_REG,RTL8169_PHY_STAT_REG |
stdcall udelay,100 |
test eax,RTL8169_PHY_Auto_Neco_Comp |
jz @b |
RTL_R8 RTL8169_REG_PHYstatus |
jmp @f |
.tbi_dis: |
stdcall udelay,100 |
@@: |
call rtl8169_reset |
ret |
endp |
;*************************************************************************** |
; Function |
; rt8169_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
proc rtl8169_reset |
; DEBUGF 1,"K : rtl8169_reset: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 |
mov [rtl8169_tpc.TxDescArrays],rtl8169_tx_ring |
; Tx Desscriptor needs 256 bytes alignment |
mov [rtl8169_tpc.TxDescArray],rtl8169_tx_ring |
mov [rtl8169_tpc.RxDescArrays],rtl8169_rx_ring |
; Rx Desscriptor needs 256 bytes alignment |
mov [rtl8169_tpc.RxDescArray],rtl8169_rx_ring |
call rtl8169_init_ring |
call rtl8169_hw_start |
; Construct a perfect filter frame with the mac address as first match |
; and broadcast for all others |
mov edi,rtl8169_txb |
or al,-1 |
mov ecx,192 |
cld |
rep stosb |
mov esi,node_addr |
mov edi,rtl8169_txb |
movsd |
movsw |
mov eax,[pci_data] |
mov [eth_status],eax |
ret |
endp |
;*************************************************************************** |
; Function |
; rtl8169_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; d - edi - Pointer to 48 bit destination address |
; t - bx - Type of packet |
; s - ecx - size of packet |
; p - esi - pointer to packet data |
; Destroyed registers |
; eax, edx, esi, edi |
; |
;*************************************************************************** |
proc rtl8169_transmit |
; DEBUGF 1,"K : rtl8169_transmit\n" ;: 0x%x : 0x%x 0x%x 0x%x 0x%x\n",[io_addr]:8,edi,bx,ecx,esi |
push ecx edx esi |
mov eax,MAX_ETH_FRAME_SIZE |
mul [rtl8169_tpc.cur_tx] |
mov esi,edi |
; point to the current txb incase multiple tx_rings are used |
mov edi,[rtl8169_tpc.Tx_skbuff + eax * 4] |
mov eax,edi |
cld |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi,node_addr |
movsd |
movsw |
; copy packet type |
mov [edi],bx |
add edi,2 |
; copy the packet data |
pop esi edx ecx |
push ecx |
shr ecx,2 |
rep movsd |
pop ecx |
push ecx |
and ecx,3 |
rep movsb |
;!!! s += ETH_HLEN; |
;!!! s &= 0x0FFF; |
;!!! while (s < ETH_ZLEN) |
;!!! ptxb[s++] = '\0'; |
mov edi,eax |
pop ecx |
push eax |
add ecx,ETH_HLEN |
and ecx,0x0FFF |
xor al,al |
add edi,ecx |
@@: cmp ecx,ETH_ZLEN |
jae @f |
stosb |
inc ecx |
jmp @b |
@@: pop eax |
mov ebx,eax |
mov eax,sizeof.rtl8169_TxDesc |
mul [rtl8169_tpc.cur_tx] |
add eax,[rtl8169_tpc.TxDescArray] |
xchg eax,ebx |
mov [ebx + rtl8169_TxDesc.buf_addr],eax |
sub [ebx + rtl8169_TxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 |
mov eax,ecx |
cmp eax,ETH_ZLEN |
jae @f |
mov eax,ETH_ZLEN |
@@: or eax,RTL8169_DSB_OWNbit or RTL8169_DSB_FSbit or RTL8169_DSB_LSbit |
cmp [rtl8169_tpc.cur_tx],NUM_TX_DESC - 1 |
jne @f |
or eax,RTL8169_DSB_EORbit |
@@: mov [ebx + rtl8169_TxDesc.status],eax |
RTL_W8 RTL8169_REG_TxPoll,0x40 ; set polling bit |
inc [rtl8169_tpc.cur_tx] |
and [rtl8169_tpc.cur_tx],NUM_TX_DESC - 1 |
;!!! to = currticks() + TX_TIMEOUT; |
;!!! while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ |
mov ecx,TX_TIMEOUT / 10 |
@@: test [ebx + rtl8169_TxDesc.status],RTL8169_DSB_OWNbit |
jnz @f |
stdcall udelay,10 |
loop @b |
; DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n" |
@@: |
ret |
endp |
;*************************************************************************** |
; Function |
; rtl8169_poll |
; |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Destroyed register(s) |
; eax, edx, ecx |
; |
;*************************************************************************** |
proc rtl8169_poll |
; DEBUGF 1,"K : rtl8169_poll\n" ;: 0x%x : none\n",[io_addr]:8 |
mov word[eth_rx_data_len],0 |
mov eax,sizeof.rtl8169_RxDesc |
mul [rtl8169_tpc.cur_rx] |
add eax,[rtl8169_tpc.RxDescArray] |
mov ebx,eax |
; DEBUGF 1,"K : rtl8169_RxDesc.status = 0x%x\n",[ebx + rtl8169_RxDesc.status] |
test [ebx + rtl8169_RxDesc.status],RTL8169_DSB_OWNbit ; 0x80000600 |
jnz .exit |
; DEBUGF 1,"K : rtl8169_tpc.cur_rx = %u\n",[rtl8169_tpc.cur_rx] |
; h/w no longer present (hotplug?) or major error, bail |
RTL_R16 RTL8169_REG_IntrStatus |
; DEBUGF 1,"K : IntrStatus = 0x%x\n",ax |
cmp ax,0xFFFF |
je .exit |
push eax |
and ax,not (RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK) |
RTL_W16 RTL8169_REG_IntrStatus,ax |
mov eax,[ebx + rtl8169_RxDesc.status] |
; DEBUGF 1,"K : RxDesc.status = 0x%x\n",eax |
test eax,RTL8169_SD_RxRES |
jnz .else |
and eax,0x00001FFF |
; jz .exit.pop |
add eax,-4 |
mov [eth_rx_data_len],ax |
; DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax |
push eax |
mov ecx,eax |
shr ecx,2 |
mov eax,[rtl8169_tpc.cur_rx] |
mov edx,[rtl8169_tpc.RxBufferRing + eax * 4] |
mov esi,edx |
mov edi,Ether_buffer |
cld |
rep movsd |
pop ecx |
and ecx,3 |
rep movsb |
mov eax,RTL8169_DSB_OWNbit or RX_BUF_SIZE |
cmp [rtl8169_tpc.cur_rx],NUM_RX_DESC - 1 |
jne @f |
or eax,RTL8169_DSB_EORbit |
@@: mov [ebx + rtl8169_RxDesc.status],eax |
mov [ebx + rtl8169_RxDesc.buf_addr],edx |
sub [ebx + rtl8169_RxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 |
jmp @f |
.else: |
; DEBUGF 1,"K : rtl8169_poll: Rx Error\n" |
; FIXME: shouldn't I reset the status on an error |
@@: |
inc [rtl8169_tpc.cur_rx] |
and [rtl8169_tpc.cur_rx],NUM_RX_DESC - 1 |
.exit.pop: |
pop eax |
and ax,RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK |
RTL_W16 RTL8169_REG_IntrStatus,ax |
.exit: |
ret |
endp |
proc rtl8169_cable |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; RTL8169.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.1 11 February 2007 ;; |
;; ;; |
;; Driver for chips of RealTek 8169 family ;; |
;; References: ;; |
;; r8169.c - linux driver (etherboot project) ;; |
;; ethernet driver template by Mike Hibbett ;; |
;; ;; |
;; The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; Copyright 2007 mike.dld, ;; |
;; mike.dld@gmail.com ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
ETH_ALEN equ 6 |
ETH_HLEN equ (2 * ETH_ALEN + 2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
RTL8169_REG_MAC0 equ 0x0 ; Ethernet hardware address |
RTL8169_REG_MAR0 equ 0x8 ; Multicast filter |
RTL8169_REG_TxDescStartAddr equ 0x20 |
RTL8169_REG_TxHDescStartAddr equ 0x28 |
RTL8169_REG_FLASH equ 0x30 |
RTL8169_REG_ERSR equ 0x36 |
RTL8169_REG_ChipCmd equ 0x37 |
RTL8169_REG_TxPoll equ 0x38 |
RTL8169_REG_IntrMask equ 0x3C |
RTL8169_REG_IntrStatus equ 0x3E |
RTL8169_REG_TxConfig equ 0x40 |
RTL8169_REG_RxConfig equ 0x44 |
RTL8169_REG_RxMissed equ 0x4C |
RTL8169_REG_Cfg9346 equ 0x50 |
RTL8169_REG_Config0 equ 0x51 |
RTL8169_REG_Config1 equ 0x52 |
RTL8169_REG_Config2 equ 0x53 |
RTL8169_REG_Config3 equ 0x54 |
RTL8169_REG_Config4 equ 0x55 |
RTL8169_REG_Config5 equ 0x56 |
RTL8169_REG_MultiIntr equ 0x5C |
RTL8169_REG_PHYAR equ 0x60 |
RTL8169_REG_TBICSR equ 0x64 |
RTL8169_REG_TBI_ANAR equ 0x68 |
RTL8169_REG_TBI_LPAR equ 0x6A |
RTL8169_REG_PHYstatus equ 0x6C |
RTL8169_REG_RxMaxSize equ 0xDA |
RTL8169_REG_CPlusCmd equ 0xE0 |
RTL8169_REG_RxDescStartAddr equ 0xE4 |
RTL8169_REG_ETThReg equ 0xEC |
RTL8169_REG_FuncEvent equ 0xF0 |
RTL8169_REG_FuncEventMask equ 0xF4 |
RTL8169_REG_FuncPresetState equ 0xF8 |
RTL8169_REG_FuncForceEvent equ 0xFC |
; InterruptStatusBits |
RTL8169_ISB_SYSErr equ 0x8000 |
RTL8169_ISB_PCSTimeout equ 0x4000 |
RTL8169_ISB_SWInt equ 0x0100 |
RTL8169_ISB_TxDescUnavail equ 0x80 |
RTL8169_ISB_RxFIFOOver equ 0x40 |
RTL8169_ISB_LinkChg equ 0x20 |
RTL8169_ISB_RxOverflow equ 0x10 |
RTL8169_ISB_TxErr equ 0x08 |
RTL8169_ISB_TxOK equ 0x04 |
RTL8169_ISB_RxErr equ 0x02 |
RTL8169_ISB_RxOK equ 0x01 |
; RxStatusDesc |
RTL8169_SD_RxRES equ 0x00200000 |
RTL8169_SD_RxCRC equ 0x00080000 |
RTL8169_SD_RxRUNT equ 0x00100000 |
RTL8169_SD_RxRWT equ 0x00400000 |
; ChipCmdBits |
RTL8169_CMD_Reset equ 0x10 |
RTL8169_CMD_RxEnb equ 0x08 |
RTL8169_CMD_TxEnb equ 0x04 |
RTL8169_CMD_RxBufEmpty equ 0x01 |
; Cfg9346Bits |
RTL8169_CFG_9346_Lock equ 0x00 |
RTL8169_CFG_9346_Unlock equ 0xC0 |
; rx_mode_bits |
RTL8169_RXM_AcceptErr equ 0x20 |
RTL8169_RXM_AcceptRunt equ 0x10 |
RTL8169_RXM_AcceptBroadcast equ 0x08 |
RTL8169_RXM_AcceptMulticast equ 0x04 |
RTL8169_RXM_AcceptMyPhys equ 0x02 |
RTL8169_RXM_AcceptAllPhys equ 0x01 |
; RxConfigBits |
RTL8169_RXC_FIFOShift equ 13 |
RTL8169_RXC_DMAShift equ 8 |
; TxConfigBits |
RTL8169_TXC_InterFrameGapShift equ 24 |
RTL8169_TXC_DMAShift equ 8 ; DMA burst value (0-7) is shift this many bits |
; rtl8169_PHYstatus |
RTL8169_PHYS_TBI_Enable equ 0x80 |
RTL8169_PHYS_TxFlowCtrl equ 0x40 |
RTL8169_PHYS_RxFlowCtrl equ 0x20 |
RTL8169_PHYS_1000bpsF equ 0x10 |
RTL8169_PHYS_100bps equ 0x08 |
RTL8169_PHYS_10bps equ 0x04 |
RTL8169_PHYS_LinkStatus equ 0x02 |
RTL8169_PHYS_FullDup equ 0x01 |
; GIGABIT_PHY_registers |
RTL8169_PHY_CTRL_REG equ 0 |
RTL8169_PHY_STAT_REG equ 1 |
RTL8169_PHY_AUTO_NEGO_REG equ 4 |
RTL8169_PHY_1000_CTRL_REG equ 9 |
; GIGABIT_PHY_REG_BIT |
RTL8169_PHY_Restart_Auto_Nego equ 0x0200 |
RTL8169_PHY_Enable_Auto_Nego equ 0x1000 |
; PHY_STAT_REG = 1; |
RTL8169_PHY_Auto_Neco_Comp equ 0x0020 |
; PHY_AUTO_NEGO_REG = 4; |
RTL8169_PHY_Cap_10_Half equ 0x0020 |
RTL8169_PHY_Cap_10_Full equ 0x0040 |
RTL8169_PHY_Cap_100_Half equ 0x0080 |
RTL8169_PHY_Cap_100_Full equ 0x0100 |
; PHY_1000_CTRL_REG = 9; |
RTL8169_PHY_Cap_1000_Full equ 0x0200 |
RTL8169_PHY_Cap_1000_Half equ 0x0100 |
RTL8169_PHY_Cap_PAUSE equ 0x0400 |
RTL8169_PHY_Cap_ASYM_PAUSE equ 0x0800 |
RTL8169_PHY_Cap_Null equ 0x0 |
; _MediaType |
RTL8169_MT_10_Half equ 0x01 |
RTL8169_MT_10_Full equ 0x02 |
RTL8169_MT_100_Half equ 0x04 |
RTL8169_MT_100_Full equ 0x08 |
RTL8169_MT_1000_Full equ 0x10 |
; _TBICSRBit |
RTL8169_TBI_LinkOK equ 0x02000000 |
; _DescStatusBit |
RTL8169_DSB_OWNbit equ 0x80000000 |
RTL8169_DSB_EORbit equ 0x40000000 |
RTL8169_DSB_FSbit equ 0x20000000 |
RTL8169_DSB_LSbit equ 0x10000000 |
; MAC address length |
MAC_ADDR_LEN equ 6 |
; max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4) |
MAX_ETH_FRAME_SIZE equ 1536 |
TX_FIFO_THRESH equ 256 ; In bytes |
RX_FIFO_THRESH equ 7 ; 7 means NO threshold, Rx buffer level before first PCI xfer |
RX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 |
TX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 |
ETTh equ 0x3F ; 0x3F means NO threshold |
EarlyTxThld equ 0x3F ; 0x3F means NO early transmit |
RxPacketMaxSize equ 0x0800 ; Maximum size supported is 16K-1 |
InterFrameGap equ 0x03 ; 3 means InterFrameGap = the shortest one |
NUM_TX_DESC equ 1 ; Number of Tx descriptor registers |
NUM_RX_DESC equ 4 ; Number of Rx descriptor registers |
RX_BUF_SIZE equ 1536 ; Rx Buffer size |
HZ equ 1000 |
RTL_MIN_IO_SIZE equ 0x80 |
TX_TIMEOUT equ (6*HZ) |
RTL8169_TIMER_EXPIRE_TIME equ 100 |
ETH_HDR_LEN equ 14 |
DEFAULT_MTU equ 1500 |
DEFAULT_RX_BUF_LEN equ 1536 |
;#ifdef RTL8169_JUMBO_FRAME_SUPPORT |
;#define MAX_JUMBO_FRAME_MTU ( 10000 ) |
;#define MAX_RX_SKBDATA_SIZE ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN ) |
;#else |
MAX_RX_SKBDATA_SIZE equ 1600 |
;#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT |
;#ifdef RTL8169_USE_IO |
;!!!#define RTL_W8(reg, val8) outb ((val8), ioaddr + (reg)) |
macro RTL_W8 reg,val8 { |
if ~reg eq dx |
mov dx, word[rtl8169_tpc.mmio_addr] |
add dx, reg |
end if |
if ~val8 eq al |
mov al, val8 |
end if |
out dx, al |
} |
;!!!#define RTL_W16(reg, val16) outw ((val16), ioaddr + (reg)) |
macro RTL_W16 reg,val16 { |
if ~reg eq dx |
mov dx, word[rtl8169_tpc.mmio_addr] |
add dx, reg |
end if |
if ~val16 eq ax |
mov ax, val16 |
end if |
out dx, ax |
} |
;!!!#define RTL_W32(reg, val32) outl ((val32), ioaddr + (reg)) |
macro RTL_W32 reg,val32 { |
if ~reg eq dx |
mov dx, word[rtl8169_tpc.mmio_addr] |
add dx, reg |
end if |
if ~val32 eq eax |
mov eax, val32 |
end if |
out dx, eax |
} |
;!!!#define RTL_R8(reg) inb (ioaddr + (reg)) |
macro RTL_R8 reg { |
if ~reg eq dx |
mov dx, word[rtl8169_tpc.mmio_addr] |
add dx, reg |
end if |
in al, dx |
} |
;!!!#define RTL_R16(reg) inw (ioaddr + (reg)) |
macro RTL_R16 reg { |
if ~reg eq dx |
mov dx, word[rtl8169_tpc.mmio_addr] |
add dx, reg |
end if |
in ax, dx |
} |
;!!!#define RTL_R32(reg) ((unsigned long) inl (ioaddr + (reg))) |
macro RTL_R32 reg { |
if ~reg eq dx |
mov dx, word[rtl8169_tpc.mmio_addr] |
add dx, reg |
end if |
in eax, dx |
} |
;#else |
; write/read MMIO register |
;#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) |
;#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) |
;#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) |
;#define RTL_R8(reg) readb (ioaddr + (reg)) |
;#define RTL_R16(reg) readw (ioaddr + (reg)) |
;#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) |
;#endif |
MCFG_METHOD_01 equ 0x01 |
MCFG_METHOD_02 equ 0x02 |
MCFG_METHOD_03 equ 0x03 |
MCFG_METHOD_04 equ 0x04 |
MCFG_METHOD_05 equ 0x05 |
MCFG_METHOD_11 equ 0x0b |
MCFG_METHOD_12 equ 0x0c |
MCFG_METHOD_13 equ 0x0d |
MCFG_METHOD_14 equ 0x0e |
MCFG_METHOD_15 equ 0x0f |
PCFG_METHOD_1 equ 0x01 ; PHY Reg 0x03 bit0-3 == 0x0000 |
PCFG_METHOD_2 equ 0x02 ; PHY Reg 0x03 bit0-3 == 0x0001 |
PCFG_METHOD_3 equ 0x03 ; PHY Reg 0x03 bit0-3 == 0x0002 |
PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space |
PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space |
PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering |
PCI_LATENCY_TIMER equ 0x0d ; 8 bits |
PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles |
PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate |
PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping |
PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking |
PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping |
PCI_COMMAND_SERR equ 0x100 ; Enable SERR |
PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes |
struc rtl8169_TxDesc { |
.status dd ? |
.vlan_tag dd ? |
.buf_addr dd ? |
.buf_Haddr dd ? |
} |
virtual at 0 |
rtl8169_TxDesc rtl8169_TxDesc |
sizeof.rtl8169_TxDesc = $ - rtl8169_TxDesc |
end virtual |
struc rtl8169_RxDesc { |
.status dd ? |
.vlan_tag dd ? |
.buf_addr dd ? |
.buf_Haddr dd ? |
} |
virtual at 0 |
rtl8169_RxDesc rtl8169_RxDesc |
sizeof.rtl8169_RxDesc = $ - rtl8169_RxDesc |
end virtual |
virtual at eth_data_start |
; Define the TX Descriptor |
align 256 |
rtl8169_tx_ring rb NUM_TX_DESC * sizeof.rtl8169_TxDesc |
; Create a static buffer of size RX_BUF_SZ for each |
; TX Descriptor. All descriptors point to a |
; part of this buffer |
align 256 |
rtl8169_txb rb NUM_TX_DESC * RX_BUF_SIZE |
; Define the RX Descriptor |
align 256 |
rtl8169_rx_ring rb NUM_RX_DESC * sizeof.rtl8169_RxDesc |
; Create a static buffer of size RX_BUF_SZ for each |
; RX Descriptor All descriptors point to a |
; part of this buffer |
align 256 |
rtl8169_rxb rb NUM_RX_DESC * RX_BUF_SIZE |
rtl8169_tpc: |
.mmio_addr dd ? ; memory map physical address |
.chipset dd ? |
.pcfg dd ? |
.mcfg dd ? |
.cur_rx dd ? ; Index into the Rx descriptor buffer of next Rx pkt |
.cur_tx dd ? ; Index into the Tx descriptor buffer of next Rx pkt |
.TxDescArrays dd ? ; Index of Tx Descriptor buffer |
.RxDescArrays dd ? ; Index of Rx Descriptor buffer |
.TxDescArray dd ? ; Index of 256-alignment Tx Descriptor buffer |
.RxDescArray dd ? ; Index of 256-alignment Rx Descriptor buffer |
.RxBufferRing rd NUM_RX_DESC ; Index of Rx Buffer array |
.Tx_skbuff rd NUM_TX_DESC |
end virtual |
rtl8169_intr_mask = RTL8169_ISB_LinkChg or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxFIFOOver or RTL8169_ISB_TxErr or RTL8169_ISB_TxOK or RTL8169_ISB_RxErr or RTL8169_ISB_RxOK |
rtl8169_rx_config = (RX_FIFO_THRESH shl RTL8169_RXC_FIFOShift) or (RX_DMA_BURST shl RTL8169_RXC_DMAShift) or 0x0000000E |
iglobal |
;static struct { |
; const char *name; |
; u8 mcfg; /* depend on RTL8169 docs */ |
; u32 RxConfigMask; /* should clear the bits supported by this chip */ |
;} |
rtl_chip_info dd \ |
MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169 |
MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s |
MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s |
MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb |
MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc |
MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E |
MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E |
MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e // PCI-E 8139 |
MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e // PCI-E 8139 |
MCFG_METHOD_15, 0xff7e1880 ; RTL8100e // PCI-E 8139 |
mac_info dd \ |
0x38800000, MCFG_METHOD_15, \ |
0x38000000, MCFG_METHOD_12, \ |
0x34000000, MCFG_METHOD_13, \ |
0x30800000, MCFG_METHOD_14, \ |
0x30000000, MCFG_METHOD_11, \ |
0x18000000, MCFG_METHOD_05, \ |
0x10000000, MCFG_METHOD_04, \ |
0x04000000, MCFG_METHOD_03, \ |
0x00800000, MCFG_METHOD_02, \ |
0x00000000, MCFG_METHOD_01 ; catch-all |
endg |
PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space |
PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space |
PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering |
PCI_LATENCY_TIMER equ 0x0d ; 8 bits |
PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles |
PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate |
PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping |
PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking |
PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping |
PCI_COMMAND_SERR equ 0x100 ; Enable SERR |
PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes |
PCI_VENDOR_ID equ 0x00 ; 16 bits |
PCI_DEVICE_ID equ 0x02 ; 16 bits |
PCI_COMMAND equ 0x04 ; 16 bits |
PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits |
PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits |
PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits |
PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits |
PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits |
PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits |
PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 |
PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address |
PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] |
PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address |
PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) |
PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) |
PCI_BASE_ADDRESS_SPACE_IO equ 0x01 |
PCI_ROM_ADDRESS equ 0x30 ; 32 bits |
proc CONFIG_CMD,where:byte |
movzx eax, byte[pci_bus] |
shl eax, 8 |
mov al, [pci_dev] |
shl eax, 8 |
mov al, [where] |
and al, not 3 |
or eax, 0x80000000 |
ret |
endp |
proc pci_read_config_byte,where:dword |
push edx |
stdcall CONFIG_CMD, [where] |
mov dx, 0xCF8 |
out dx, eax |
mov edx, [where] |
and edx, 3 |
add edx, 0xCFC |
in al, dx |
pop edx |
ret |
endp |
proc pci_read_config_word,where:dword |
push edx |
stdcall CONFIG_CMD, [where] |
mov dx, 0xCF8 |
out dx, eax |
mov edx, [where] |
and edx, 2 |
add edx, 0xCFC |
in ax, dx |
pop edx |
ret |
endp |
proc pci_read_config_dword,where:dword |
push edx |
stdcall CONFIG_CMD, [where] |
mov edx, 0xCF8 |
out dx, eax |
mov edx, 0xCFC |
in eax, dx |
pop edx |
ret |
endp |
proc pci_write_config_byte,where:dword,value:byte |
push edx |
stdcall CONFIG_CMD, [where] |
mov dx, 0xCF8 |
out dx, eax |
mov edx, [where] |
and edx, 3 |
add edx, 0xCFC |
mov al, [value] |
out dx, al |
pop edx |
ret |
endp |
proc pci_write_config_word,where:dword,value:word |
push edx |
stdcall CONFIG_CMD, [where] |
mov dx, 0xCF8 |
out dx, eax |
mov edx, [where] |
and edx, 2 |
add edx, 0xCFC |
mov ax, [value] |
out dx, ax |
pop edx |
ret |
endp |
proc pci_write_config_dword,where:dword,value:dword |
push edx |
stdcall CONFIG_CMD, [where] |
mov edx, 0xCF8 |
out dx, eax |
mov edx, 0xCFC |
mov eax, [value] |
out dx, eax |
pop edx |
ret |
endp |
; Set device to be a busmaster in case BIOS neglected to do so. |
; Also adjust PCI latency timer to a reasonable value, 32. |
proc adjust_pci_device |
; DEBUGF 1,"K : adjust_pci_device\n" |
stdcall pci_read_config_word, PCI_COMMAND |
mov bx, ax |
or bx, PCI_COMMAND_MASTER or PCI_COMMAND_IO |
cmp ax, bx |
je @f |
; DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2 |
stdcall pci_write_config_word, PCI_COMMAND, ebx |
@@: |
stdcall pci_read_config_byte, PCI_LATENCY_TIMER |
cmp al, 32 |
jae @f |
; DEBUGF 1,"K : adjust_pci_device: PCI latency timer (CFLT) is unreasonably low at %d.\nK : Setting to 32 clocks.\n",al |
stdcall pci_write_config_byte, PCI_LATENCY_TIMER, 32 |
@@: |
ret |
endp |
; Find the start of a pci resource |
proc pci_bar_start,index:dword |
stdcall pci_read_config_dword, [index] |
test eax, PCI_BASE_ADDRESS_SPACE_IO |
jz @f |
and eax, PCI_BASE_ADDRESS_IO_MASK |
jmp .exit |
@@: |
push eax |
and eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK |
cmp eax, PCI_BASE_ADDRESS_MEM_TYPE_64 |
jne .not64 |
mov eax, [index] |
add eax, 4 |
stdcall pci_read_config_dword, eax |
or eax, eax |
jz .not64 |
; DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n" |
add esp, 4 |
or eax, -1 |
ret |
.not64: |
pop eax |
and eax, PCI_BASE_ADDRESS_MEM_MASK |
.exit: |
ret |
endp |
proc rtl8169_init_board |
; DEBUGF 1,"K : rtl8169_init_board\n" |
call adjust_pci_device |
stdcall pci_bar_start, PCI_BASE_ADDRESS_0 |
mov [rtl8169_tpc.mmio_addr], eax |
; Soft reset the chip |
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset |
; Check that the chip has finished the reset |
mov ecx, 1000 |
@@: |
RTL_R8 RTL8169_REG_ChipCmd |
test al, RTL8169_CMD_Reset |
jz @f |
stdcall udelay, 10 |
loop @b |
@@: |
; identify config method |
RTL_R32 RTL8169_REG_TxConfig |
and eax, 0x7c800000 |
; DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax |
mov esi, mac_info-8 |
@@: |
add esi, 8 |
mov ecx, eax |
and ecx, [esi] |
cmp ecx, [esi] |
jne @b |
mov eax, [esi+4] |
mov [rtl8169_tpc.mcfg], eax |
mov [rtl8169_tpc.pcfg], PCFG_METHOD_3 |
stdcall RTL8169_READ_GMII_REG, 3 |
and al, 0x0f |
or al, al |
jnz @f |
mov [rtl8169_tpc.pcfg], PCFG_METHOD_1 |
jmp .pconf |
@@: |
dec al |
jnz .pconf |
mov [rtl8169_tpc.pcfg], PCFG_METHOD_2 |
.pconf: |
; identify chip attached to board |
mov ecx, 10 |
mov eax, [rtl8169_tpc.mcfg] |
@@: |
dec ecx |
js @f |
cmp eax, [rtl_chip_info+ecx*8] |
jne @b |
mov [rtl8169_tpc.chipset], ecx |
jmp .match |
@@: |
; if unknown chip, assume array element #0, original RTL-8169 in this case |
; DEBUGF 1,"K : rtl8169_init_board: PCI device: unknown chip version, assuming RTL-8169\n" |
RTL_R32 RTL8169_REG_TxConfig |
; DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax |
mov [rtl8169_tpc.chipset], 0 |
xor eax, eax |
inc eax |
ret |
.match: |
xor eax, eax |
ret |
endp |
proc rtl8169_hw_PHY_config |
; DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg] |
; DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg); |
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_04 |
jne .not_4 |
; stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0001 |
; stdcall RTL8169_WRITE_GMII_REG,0x1b,0x841e |
; stdcall RTL8169_WRITE_GMII_REG,0x0e,0x7bfb |
; stdcall RTL8169_WRITE_GMII_REG,0x09,0x273a |
stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0002 |
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x90D0 |
stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0000 |
jmp .exit |
.not_4: |
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_02 |
je @f |
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_03 |
jne .not_2_or_3 |
@@: |
stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0001 |
stdcall RTL8169_WRITE_GMII_REG, 0x15, 0x1000 |
stdcall RTL8169_WRITE_GMII_REG, 0x18, 0x65C7 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0000 |
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0x00A1 |
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0x0008 |
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x1020 |
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0x1000 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0800 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0000 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x7000 |
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xFF41 |
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDE60 |
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x0140 |
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0x0077 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x7800 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x7000 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xA000 |
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xDF01 |
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDF20 |
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0xFF95 |
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0xFA00 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xA800 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xA000 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xB000 |
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xFF41 |
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDE20 |
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x0140 |
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0x00BB |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xB800 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xB000 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xF000 |
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xDF01 |
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDF20 |
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0xFF95 |
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0xBF00 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xF800 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xF000 |
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0000 |
stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0000 |
stdcall RTL8169_WRITE_GMII_REG, 0x0B, 0x0000 |
jmp .exit |
.not_2_or_3: |
; DBG_PRINT("tpc->mcfg=%d. Discard hw PHY config.\n", tpc->mcfg); |
; DEBUGF 1,"K : tpc.mcfg=%d, discard hw PHY config\n",[rtl8169_tpc.mcfg] |
.exit: |
ret |
endp |
;proc pci_write_config_byte |
; ret |
;endp |
proc RTL8169_WRITE_GMII_REG,RegAddr:byte,value:dword |
;;; DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value] |
movzx eax, [RegAddr] |
shl eax, 16 |
or eax, [value] |
or eax, 0x80000000 |
RTL_W32 RTL8169_REG_PHYAR,eax |
stdcall udelay, 1 ;;;1000 |
mov ecx, 2000 |
; Check if the RTL8169 has completed writing to the specified MII register |
@@: |
RTL_R32 RTL8169_REG_PHYAR |
test eax, 0x80000000 |
jz .exit |
stdcall udelay, 1 ;;;100 |
loop @b |
.exit: |
ret |
endp |
proc RTL8169_READ_GMII_REG,RegAddr:byte |
;;; DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2 |
push ecx |
movzx eax, [RegAddr] |
shl eax, 16 |
; or eax,0x0 |
RTL_W32 RTL8169_REG_PHYAR,eax |
stdcall udelay, 1 ;;;1000 |
mov ecx, 2000 |
; Check if the RTL8169 has completed retrieving data from the specified MII register |
@@: |
RTL_R32 RTL8169_REG_PHYAR |
test eax, 0x80000000 |
jnz .exit |
stdcall udelay, 1 ;;;100 |
loop @b |
or eax, -1 |
pop ecx |
ret |
.exit: |
RTL_R32 RTL8169_REG_PHYAR |
and eax, 0xFFFF |
pop ecx |
ret |
endp |
proc rtl8169_set_rx_mode |
; DEBUGF 1,"K : rtl8169_set_rx_mode\n" |
; IFF_ALLMULTI |
; Too many to filter perfectly -- accept all multicasts |
RTL_R32 RTL8169_REG_RxConfig |
mov ecx, [rtl8169_tpc.chipset] |
and eax, [rtl_chip_info + ecx * 8 + 4]; RxConfigMask |
or eax, rtl8169_rx_config or (RTL8169_RXM_AcceptBroadcast or RTL8169_RXM_AcceptMulticast or RTL8169_RXM_AcceptMyPhys) |
RTL_W32 RTL8169_REG_RxConfig,eax |
; Multicast hash filter |
RTL_W32 RTL8169_REG_MAR0 + 0,0xffffffff |
RTL_W32 RTL8169_REG_MAR0 + 4,0xffffffff |
ret |
endp |
proc rtl8169_init_ring |
; DEBUGF 1,"K : rtl8169_init_ring\n" |
xor eax, eax |
mov [rtl8169_tpc.cur_rx], eax |
mov [rtl8169_tpc.cur_tx], eax |
mov edi, [rtl8169_tpc.TxDescArray] |
mov ecx, (NUM_TX_DESC * sizeof.rtl8169_TxDesc) / 4 |
cld |
rep stosd |
mov edi, [rtl8169_tpc.RxDescArray] |
mov ecx, (NUM_RX_DESC * sizeof.rtl8169_RxDesc) / 4 |
rep stosd |
mov edi, rtl8169_tpc.Tx_skbuff |
mov eax, rtl8169_txb |
mov ecx, NUM_TX_DESC |
@@: |
stosd |
inc eax ; add eax,RX_BUF_SIZE ??? |
loop @b |
;!!! for (i = 0; i < NUM_RX_DESC; i++) { |
;!!! if (i == (NUM_RX_DESC - 1)) |
;!!! tpc->RxDescArray[i].status = (OWNbit | EORbit) | RX_BUF_SIZE; |
;!!! else |
;!!! tpc->RxDescArray[i].status = OWNbit | RX_BUF_SIZE; |
;!!! tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; |
;!!! tpc->RxDescArray[i].buf_addr = virt_to_bus(tpc->RxBufferRing[i]); |
;!!! } |
mov esi, rtl8169_tpc.RxBufferRing |
mov edi, [rtl8169_tpc.RxDescArray] |
mov eax, rtl8169_rxb |
mov ecx, NUM_RX_DESC |
@@: |
mov [esi], eax |
mov [edi+rtl8169_RxDesc.buf_addr], eax |
sub [edi+rtl8169_RxDesc.buf_addr], OS_BASE ; shurf 28.09.2008 |
mov [edi+rtl8169_RxDesc.status], RTL8169_DSB_OWNbit or RX_BUF_SIZE |
add esi, 4 |
add edi, sizeof.rtl8169_RxDesc |
add eax, RX_BUF_SIZE |
loop @b |
or [edi - sizeof.rtl8169_RxDesc + rtl8169_RxDesc.status], RTL8169_DSB_EORbit |
ret |
endp |
proc rtl8169_hw_start |
; DEBUGF 1,"K : rtl8169_hw_start\n" |
; Soft reset the chip |
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset |
; Check that the chip has finished the reset |
mov ecx, 1000 |
@@: |
RTL_R8 RTL8169_REG_ChipCmd |
and al, RTL8169_CMD_Reset |
jz @f |
stdcall udelay, 10 |
loop @b |
@@: |
RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Unlock |
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_TxEnb or RTL8169_CMD_RxEnb |
RTL_W8 RTL8169_REG_ETThReg,ETTh |
; For gigabit rtl8169 |
RTL_W16 RTL8169_REG_RxMaxSize,RxPacketMaxSize |
; Set Rx Config register |
RTL_R32 RTL8169_REG_RxConfig |
mov ecx, [rtl8169_tpc.chipset] |
and eax, [rtl_chip_info + ecx * 8 + 4]; RxConfigMask |
or eax, rtl8169_rx_config |
RTL_W32 RTL8169_REG_RxConfig,eax |
; Set DMA burst size and Interframe Gap Time |
RTL_W32 RTL8169_REG_TxConfig,(TX_DMA_BURST shl RTL8169_TXC_DMAShift) or (InterFrameGap shl RTL8169_TXC_InterFrameGapShift) |
RTL_R16 RTL8169_REG_CPlusCmd |
RTL_W16 RTL8169_REG_CPlusCmd,ax |
RTL_R16 RTL8169_REG_CPlusCmd |
or ax, 1 shl 3 |
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_02 |
jne @f |
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_03 |
jne @f |
or ax, 1 shl 14 |
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n" |
jmp .set |
@@:;DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3\n" |
.set: |
RTL_W16 RTL8169_REG_CPlusCmd,ax |
; RTL_W16 0xE2,0x1517 |
; RTL_W16 0xE2,0x152a |
; RTL_W16 0xE2,0x282a |
RTL_W16 0xE2,0x0000 |
MOV [rtl8169_tpc.cur_rx],0 |
push eax ; shurf 28.09.2008 |
mov eax, [rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 |
sub eax, OS_BASE ; shurf 28.09.2008 |
RTL_W32 RTL8169_REG_TxDescStartAddr,eax ;[rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 |
mov eax, [rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 |
sub eax, OS_BASE ; shurf 28.09.2008 |
RTL_W32 RTL8169_REG_RxDescStartAddr,eax ;[rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 |
pop eax ; shurf 28.09.2008 |
RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Lock |
stdcall udelay, 10 |
RTL_W32 RTL8169_REG_RxMissed,0 |
call rtl8169_set_rx_mode |
; no early-rx interrupts |
RTL_R16 RTL8169_REG_MultiIntr |
and ax, 0xF000 |
RTL_W16 RTL8169_REG_MultiIntr,ax |
RTL_W16 RTL8169_REG_IntrMask,0 ; rtl8169_intr_mask |
ret |
endp |
proc udelay,msec:dword |
push esi |
mov esi, [msec] |
call delay_ms |
pop esi |
ret |
endp |
;*************************************************************************** |
; Function |
; rtl8169_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
proc rtl8169_probe |
; DEBUGF 1,"K : rtl8169_probe: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 |
call rtl8169_init_board |
mov ecx, MAC_ADDR_LEN |
mov edx, [rtl8169_tpc.mmio_addr] |
add edx, RTL8169_REG_MAC0 |
xor ebx, ebx |
; Get MAC address. FIXME: read EEPROM |
@@: |
RTL_R8 dx |
mov [node_addr+ebx], al |
inc edx |
inc ebx |
loop @b |
; DEBUGF 1,"K : rtl8169_probe: MAC = %x-%x-%x-%x-%x-%x\n",[node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2 |
; Config PHY |
stdcall rtl8169_hw_PHY_config |
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" |
RTL_W8 0x82,0x01 |
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_03 |
jae @f |
; DEBUGF 1,"K : Set PCI Latency=0x40\n" |
; stdcall pci_write_config_byte,PCI_LATENCY_TIMER,0x40 |
@@: |
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_02 |
jne @f |
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" |
RTL_W8 0x82,0x01 |
; DEBUGF 1,"K : Set PHY Reg 0x0bh = 0x00h\n" |
stdcall RTL8169_WRITE_GMII_REG, 0x0b, 0x0000 ; w 0x0b 15 0 0 |
@@: |
; if TBI is not enabled |
RTL_R8 RTL8169_REG_PHYstatus |
test al, RTL8169_PHYS_TBI_Enable |
jz .tbi_dis |
stdcall RTL8169_READ_GMII_REG, RTL8169_PHY_AUTO_NEGO_REG |
; enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged |
and eax, 0x0C1F |
or eax, RTL8169_PHY_Cap_10_Half or RTL8169_PHY_Cap_10_Full or RTL8169_PHY_Cap_100_Half or RTL8169_PHY_Cap_100_Full |
stdcall RTL8169_WRITE_GMII_REG, RTL8169_PHY_AUTO_NEGO_REG, eax |
; enable 1000 Full Mode |
stdcall RTL8169_WRITE_GMII_REG, RTL8169_PHY_1000_CTRL_REG, RTL8169_PHY_Cap_1000_Full or RTL8169_PHY_Cap_1000_Half; rtl8168 |
; Enable auto-negotiation and restart auto-nigotiation |
stdcall RTL8169_WRITE_GMII_REG, RTL8169_PHY_CTRL_REG, RTL8169_PHY_Enable_Auto_Nego or RTL8169_PHY_Restart_Auto_Nego |
stdcall udelay, 100 |
mov ecx, 10000 |
; wait for auto-negotiation process |
@@: |
dec ecx |
jz @f |
stdcall RTL8169_READ_GMII_REG, RTL8169_PHY_STAT_REG |
stdcall udelay, 100 |
test eax, RTL8169_PHY_Auto_Neco_Comp |
jz @b |
RTL_R8 RTL8169_REG_PHYstatus |
jmp @f |
.tbi_dis: |
stdcall udelay, 100 |
@@: |
call rtl8169_reset |
ret |
endp |
;*************************************************************************** |
; Function |
; rt8169_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
proc rtl8169_reset |
; DEBUGF 1,"K : rtl8169_reset: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 |
mov [rtl8169_tpc.TxDescArrays], rtl8169_tx_ring |
; Tx Desscriptor needs 256 bytes alignment |
mov [rtl8169_tpc.TxDescArray], rtl8169_tx_ring |
mov [rtl8169_tpc.RxDescArrays], rtl8169_rx_ring |
; Rx Desscriptor needs 256 bytes alignment |
mov [rtl8169_tpc.RxDescArray], rtl8169_rx_ring |
call rtl8169_init_ring |
call rtl8169_hw_start |
; Construct a perfect filter frame with the mac address as first match |
; and broadcast for all others |
mov edi, rtl8169_txb |
or al, -1 |
mov ecx, 192 |
cld |
rep stosb |
mov esi, node_addr |
mov edi, rtl8169_txb |
movsd |
movsw |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
endp |
;*************************************************************************** |
; Function |
; rtl8169_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; d - edi - Pointer to 48 bit destination address |
; t - bx - Type of packet |
; s - ecx - size of packet |
; p - esi - pointer to packet data |
; Destroyed registers |
; eax, edx, esi, edi |
; |
;*************************************************************************** |
proc rtl8169_transmit |
; DEBUGF 1,"K : rtl8169_transmit\n" ;: 0x%x : 0x%x 0x%x 0x%x 0x%x\n",[io_addr]:8,edi,bx,ecx,esi |
push ecx edx esi |
mov eax, MAX_ETH_FRAME_SIZE |
mul [rtl8169_tpc.cur_tx] |
mov esi, edi |
; point to the current txb incase multiple tx_rings are used |
mov edi, [rtl8169_tpc.Tx_skbuff + eax * 4] |
mov eax, edi |
cld |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi, node_addr |
movsd |
movsw |
; copy packet type |
mov [edi], bx |
add edi, 2 |
; copy the packet data |
pop esi edx ecx |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
push ecx |
and ecx, 3 |
rep movsb |
;!!! s += ETH_HLEN; |
;!!! s &= 0x0FFF; |
;!!! while (s < ETH_ZLEN) |
;!!! ptxb[s++] = '\0'; |
mov edi, eax |
pop ecx |
push eax |
add ecx, ETH_HLEN |
and ecx, 0x0FFF |
xor al, al |
add edi, ecx |
@@: |
cmp ecx, ETH_ZLEN |
jae @f |
stosb |
inc ecx |
jmp @b |
@@: |
pop eax |
mov ebx, eax |
mov eax, sizeof.rtl8169_TxDesc |
mul [rtl8169_tpc.cur_tx] |
add eax, [rtl8169_tpc.TxDescArray] |
xchg eax, ebx |
mov [ebx + rtl8169_TxDesc.buf_addr], eax |
sub [ebx + rtl8169_TxDesc.buf_addr], OS_BASE ; shurf 28.09.2008 |
mov eax, ecx |
cmp eax, ETH_ZLEN |
jae @f |
mov eax, ETH_ZLEN |
@@: |
or eax, RTL8169_DSB_OWNbit or RTL8169_DSB_FSbit or RTL8169_DSB_LSbit |
cmp [rtl8169_tpc.cur_tx], NUM_TX_DESC - 1 |
jne @f |
or eax, RTL8169_DSB_EORbit |
@@: |
mov [ebx + rtl8169_TxDesc.status], eax |
RTL_W8 RTL8169_REG_TxPoll,0x40 ; set polling bit |
inc [rtl8169_tpc.cur_tx] |
and [rtl8169_tpc.cur_tx], NUM_TX_DESC - 1 |
;!!! to = currticks() + TX_TIMEOUT; |
;!!! while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ |
mov ecx, TX_TIMEOUT / 10 |
@@: |
test [ebx + rtl8169_TxDesc.status], RTL8169_DSB_OWNbit |
jnz @f |
stdcall udelay, 10 |
loop @b |
; DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n" |
@@: |
ret |
endp |
;*************************************************************************** |
; Function |
; rtl8169_poll |
; |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Destroyed register(s) |
; eax, edx, ecx |
; |
;*************************************************************************** |
proc rtl8169_poll |
; DEBUGF 1,"K : rtl8169_poll\n" ;: 0x%x : none\n",[io_addr]:8 |
mov word[eth_rx_data_len], 0 |
mov eax, sizeof.rtl8169_RxDesc |
mul [rtl8169_tpc.cur_rx] |
add eax, [rtl8169_tpc.RxDescArray] |
mov ebx, eax |
; DEBUGF 1,"K : rtl8169_RxDesc.status = 0x%x\n",[ebx + rtl8169_RxDesc.status] |
test [ebx + rtl8169_RxDesc.status], RTL8169_DSB_OWNbit; 0x80000600 |
jnz .exit |
; DEBUGF 1,"K : rtl8169_tpc.cur_rx = %u\n",[rtl8169_tpc.cur_rx] |
; h/w no longer present (hotplug?) or major error, bail |
RTL_R16 RTL8169_REG_IntrStatus |
; DEBUGF 1,"K : IntrStatus = 0x%x\n",ax |
cmp ax, 0xFFFF |
je .exit |
push eax |
and ax, not (RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK) |
RTL_W16 RTL8169_REG_IntrStatus,ax |
mov eax, [ebx + rtl8169_RxDesc.status] |
; DEBUGF 1,"K : RxDesc.status = 0x%x\n",eax |
test eax, RTL8169_SD_RxRES |
jnz .else |
and eax, 0x00001FFF |
; jz .exit.pop |
add eax, -4 |
mov [eth_rx_data_len], ax |
; DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax |
push eax |
mov ecx, eax |
shr ecx, 2 |
mov eax, [rtl8169_tpc.cur_rx] |
mov edx, [rtl8169_tpc.RxBufferRing + eax * 4] |
mov esi, edx |
mov edi, Ether_buffer |
cld |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
mov eax, RTL8169_DSB_OWNbit or RX_BUF_SIZE |
cmp [rtl8169_tpc.cur_rx], NUM_RX_DESC - 1 |
jne @f |
or eax, RTL8169_DSB_EORbit |
@@: |
mov [ebx + rtl8169_RxDesc.status], eax |
mov [ebx + rtl8169_RxDesc.buf_addr], edx |
sub [ebx + rtl8169_RxDesc.buf_addr], OS_BASE ; shurf 28.09.2008 |
jmp @f |
.else: |
; DEBUGF 1,"K : rtl8169_poll: Rx Error\n" |
; FIXME: shouldn't I reset the status on an error |
@@: |
inc [rtl8169_tpc.cur_rx] |
and [rtl8169_tpc.cur_rx], NUM_RX_DESC - 1 |
.exit.pop: |
pop eax |
and ax, RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK |
RTL_W16 RTL8169_REG_IntrStatus,ax |
.exit: |
ret |
endp |
proc rtl8169_cable |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/drivers/sis900.inc |
---|
1,1158 → 1,1166 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; SIS900.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.4 26 April 2004 ;; |
;; ;; |
;; This driver is based on the SIS900 driver from ;; |
;; the etherboot 5.0.6 project. The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2004 Jason Delozier, ;; |
;; cordata51@hotmail.com ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; Updates: ;; |
;; Revision Look up table and SIS635 Mac Address by Jarek Pelczar ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************** |
; Interface |
; SIS900_reset |
; SIS900_probe |
; SIS900_poll |
; SIS900_transmit |
; |
;******************************************************************** |
;******************************************************************** |
; Comments: |
; Known to work with the following SIS900 ethernet cards: |
; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x91 |
; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x90 |
; |
; If your card is not listed, try it and let me know if it |
; functions properly and it will be aded to the list. If not |
; we may be able to add support for it. |
; |
; How To Use: |
; Add the following lines to Ethernet.inc in their appropriate locations |
; |
; include "Sis900.INC" |
; dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, |
; SIS900_transmit |
; dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, |
; SIS900_transmit ;untested |
; |
; ToDo: |
; - Enable MII interface for reading speed |
; and duplex settings. |
; |
; - Update Poll routine to support packet fragmentation. |
; |
; - Add additional support for other sis900 based cards |
; |
;******************************************************************** |
; comment the next line out if you don't want debug info printed |
; on the debug board. This option adds a lot of bytes to the driver |
; so it's worth to comment it out. |
; SIS900_DEBUG equ 1 |
;* buffers and descriptors |
cur_rx db 0 |
NUM_RX_DESC equ 4 ;* Number of RX descriptors * |
NUM_TX_DESC equ 1 ;* Number of TX descriptors * |
RX_BUFF_SZ equ 1520 ;* Buffer size for each Rx buffer * |
TX_BUFF_SZ equ 1516 ;* Buffer size for each Tx buffer * |
uglobal |
align 4 |
txd: times (3 * NUM_TX_DESC) dd 0 |
rxd: times (3 * NUM_RX_DESC) dd 0 |
endg |
txb equ eth_data_start |
rxb equ txb + (NUM_TX_DESC * TX_BUFF_SZ) |
SIS900_ETH_ALEN equ 6 ;* Size of Ethernet address * |
SIS900_ETH_HLEN equ 14 ;* Size of ethernet header * |
SIS900_ETH_ZLEN equ 60 ;* Minimum packet length * |
SIS900_DSIZE equ 0x00000fff |
SIS900_CRC_SIZE equ 4 |
SIS900_RFADDR_shift equ 16 |
;SIS900 Symbolic offsets to registers. |
SIS900_cr equ 0x0 ; Command Register |
SIS900_cfg equ 0x4 ; Configuration Register |
SIS900_mear equ 0x8 ; EEPROM Access Register |
SIS900_ptscr equ 0xc ; PCI Test Control Register |
SIS900_isr equ 0x10 ; Interrupt Status Register |
SIS900_imr equ 0x14 ; Interrupt Mask Register |
SIS900_ier equ 0x18 ; Interrupt Enable Register |
SIS900_epar equ 0x18 ; Enhanced PHY Access Register |
SIS900_txdp equ 0x20 ; Transmit Descriptor Pointer Register |
SIS900_txcfg equ 0x24 ; Transmit Configuration Register |
SIS900_rxdp equ 0x30 ; Receive Descriptor Pointer Register |
SIS900_rxcfg equ 0x34 ; Receive Configuration Register |
SIS900_flctrl equ 0x38 ; Flow Control Register |
SIS900_rxlen equ 0x3c ; Receive Packet Length Register |
SIS900_rfcr equ 0x48 ; Receive Filter Control Register |
SIS900_rfdr equ 0x4C ; Receive Filter Data Register |
SIS900_pmctrl equ 0xB0 ; Power Management Control Register |
SIS900_pmer equ 0xB4 ; Power Management Wake-up Event Register |
;SIS900 Command Register Bits |
SIS900_RELOAD equ 0x00000400 |
SIS900_ACCESSMODE equ 0x00000200 |
SIS900_RESET equ 0x00000100 |
SIS900_SWI equ 0x00000080 |
SIS900_RxRESET equ 0x00000020 |
SIS900_TxRESET equ 0x00000010 |
SIS900_RxDIS equ 0x00000008 |
SIS900_RxENA equ 0x00000004 |
SIS900_TxDIS equ 0x00000002 |
SIS900_TxENA equ 0x00000001 |
;SIS900 Configuration Register Bits |
SIS900_DESCRFMT equ 0x00000100 ; 7016 specific |
SIS900_REQALG equ 0x00000080 |
SIS900_SB equ 0x00000040 |
SIS900_POW equ 0x00000020 |
SIS900_EXD equ 0x00000010 |
SIS900_PESEL equ 0x00000008 |
SIS900_LPM equ 0x00000004 |
SIS900_BEM equ 0x00000001 |
SIS900_RND_CNT equ 0x00000400 |
SIS900_FAIR_BACKOFF equ 0x00000200 |
SIS900_EDB_MASTER_EN equ 0x00002000 |
;SIS900 Eeprom Access Reigster Bits |
SIS900_MDC equ 0x00000040 |
SIS900_MDDIR equ 0x00000020 |
SIS900_MDIO equ 0x00000010 ; 7016 specific |
SIS900_EECS equ 0x00000008 |
SIS900_EECLK equ 0x00000004 |
SIS900_EEDO equ 0x00000002 |
SIS900_EEDI equ 0x00000001 |
;SIS900 TX Configuration Register Bits |
SIS900_ATP equ 0x10000000 ;Automatic Transmit Padding |
SIS900_MLB equ 0x20000000 ;Mac Loopback Enable |
SIS900_HBI equ 0x40000000 ;HeartBeat Ignore (Req for full-dup) |
SIS900_CSI equ 0x80000000 ;CarrierSenseIgnore (Req for full-du |
;SIS900 RX Configuration Register Bits |
SIS900_AJAB equ 0x08000000 ; |
SIS900_ATX equ 0x10000000 ;Accept Transmit Packets |
SIS900_ARP equ 0x40000000 ;accept runt packets (<64bytes) |
SIS900_AEP equ 0x80000000 ;accept error packets |
;SIS900 Interrupt Reigster Bits |
SIS900_WKEVT equ 0x10000000 |
SIS900_TxPAUSEEND equ 0x08000000 |
SIS900_TxPAUSE equ 0x04000000 |
SIS900_TxRCMP equ 0x02000000 |
SIS900_RxRCMP equ 0x01000000 |
SIS900_DPERR equ 0x00800000 |
SIS900_SSERR equ 0x00400000 |
SIS900_RMABT equ 0x00200000 |
SIS900_RTABT equ 0x00100000 |
SIS900_RxSOVR equ 0x00010000 |
SIS900_HIBERR equ 0x00008000 |
SIS900_SWINT equ 0x00001000 |
SIS900_MIBINT equ 0x00000800 |
SIS900_TxURN equ 0x00000400 |
SIS900_TxIDLE equ 0x00000200 |
SIS900_TxERR equ 0x00000100 |
SIS900_TxDESC equ 0x00000080 |
SIS900_TxOK equ 0x00000040 |
SIS900_RxORN equ 0x00000020 |
SIS900_RxIDLE equ 0x00000010 |
SIS900_RxEARLY equ 0x00000008 |
SIS900_RxERR equ 0x00000004 |
SIS900_RxDESC equ 0x00000002 |
SIS900_RxOK equ 0x00000001 |
;SIS900 Interrupt Enable Reigster Bits |
SIS900_IE equ 0x00000001 |
;SIS900 Revision ID |
SIS900B_900_REV equ 0x03 |
SIS630A_900_REV equ 0x80 |
SIS630E_900_REV equ 0x81 |
SIS630S_900_REV equ 0x82 |
SIS630EA1_900_REV equ 0x83 |
SIS630ET_900_REV equ 0x84 |
SIS635A_900_REV equ 0x90 |
SIS900_960_REV equ 0x91 |
;SIS900 Receive Filter Control Register Bits |
SIS900_RFEN equ 0x80000000 |
SIS900_RFAAB equ 0x40000000 |
SIS900_RFAAM equ 0x20000000 |
SIS900_RFAAP equ 0x10000000 |
SIS900_RFPromiscuous equ 0x70000000 |
;SIS900 Reveive Filter Data Mask |
SIS900_RFDAT equ 0x0000FFFF |
;SIS900 Eeprom Address |
SIS900_EEPROMSignature equ 0x00 |
SIS900_EEPROMVendorID equ 0x02 |
SIS900_EEPROMDeviceID equ 0x03 |
SIS900_EEPROMMACAddr equ 0x08 |
SIS900_EEPROMChecksum equ 0x0b |
;The EEPROM commands include the alway-set leading bit. |
;SIS900 Eeprom Command |
SIS900_EEread equ 0x0180 |
SIS900_EEwrite equ 0x0140 |
SIS900_EEerase equ 0x01C0 |
SIS900_EEwriteEnable equ 0x0130 |
SIS900_EEwriteDisable equ 0x0100 |
SIS900_EEeraseAll equ 0x0120 |
SIS900_EEwriteAll equ 0x0110 |
SIS900_EEaddrMask equ 0x013F |
SIS900_EEcmdShift equ 16 |
;For SiS962 or SiS963, request the eeprom software access |
SIS900_EEREQ equ 0x00000400 |
SIS900_EEDONE equ 0x00000200 |
SIS900_EEGNT equ 0x00000100 |
;General Varibles |
SIS900_pci_revision: db 0 |
SIS900_Status dd 0x03000000 |
sis900_specific_table: |
; dd SIS630A_900_REV,Get_Mac_SIS630A_900_REV,0 |
; dd SIS630E_900_REV,Get_Mac_SIS630E_900_REV,0 |
dd SIS630S_900_REV,Get_Mac_SIS635_900_REV,0 |
dd SIS630EA1_900_REV,Get_Mac_SIS635_900_REV,0 |
dd SIS630ET_900_REV,Get_Mac_SIS635_900_REV,0;SIS630ET_900_REV_SpecialFN |
dd SIS635A_900_REV,Get_Mac_SIS635_900_REV,0 |
dd SIS900_960_REV,SIS960_get_mac_addr,0 |
dd SIS900B_900_REV,SIS900_get_mac_addr,0 |
dd 0,0,0,0 ; end of list |
sis900_get_mac_func: dd 0 |
sis900_special_func: dd 0 |
sis900_table_entries: db 8 |
;*************************************************************************** |
; Function |
; SIS900_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
;not done - still need to probe mii transcievers |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Str_Unsupported db 'Sorry your card is unsupported ',13,10,0 |
end if |
SIS900_probe: |
;******Wake Up Chip******* |
mov al, 4 |
mov bh, [pci_dev] |
mov ecx, 0 |
mov ah, [pci_bus] |
mov bl, 0x40 |
call pci_write_reg |
;*******Set some PCI Settings********* |
call SIS900_adjust_pci_device |
;*****Get Card Revision****** |
mov al, 1 ;one byte to read |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, 0x08 ;Revision Register |
call pci_read_reg |
mov [SIS900_pci_revision], al ;save the revision for later use |
;****** Look up through the sis900_specific_table |
mov esi,sis900_specific_table |
.probe_loop: |
cmp dword [esi],0 ; Check if we reached end of the list |
je .probe_loop_failed |
cmp al,[esi] ; Check if revision is OK |
je .probe_loop_ok |
add esi,12 ; Advance to next entry |
jmp .probe_loop |
.probe_loop_failed: |
jmp SIS900_Probe_Unsupported |
;*********Find Get Mac Function********* |
.probe_loop_ok: |
mov eax,[esi+4] ; Get pointer to "get MAC" function |
mov [sis900_get_mac_func],eax |
mov eax,[esi+8] ; Get pointer to special initialization fn |
mov [sis900_special_func],eax |
;******** Get MAC ******** |
call dword [sis900_get_mac_func] |
;******** Call special initialization fn if requested ******** |
cmp dword [sis900_special_func],0 |
je .no_special_init |
call dword [sis900_special_func] |
.no_special_init: |
;******** Set table entries ******** |
mov al,[SIS900_pci_revision] |
cmp al,SIS635A_900_REV |
jae .ent16 |
cmp al,SIS900B_900_REV |
je .ent16 |
jmp .ent8 |
.ent16: |
mov byte [sis900_table_entries],16 |
.ent8: |
;*******Probe for mii transceiver******* |
;TODO!!********************* |
;*******Initialize Device******* |
call sis900_init |
ret |
SIS900_Probe_Unsupported: |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Str_Unsupported |
call sys_msg_board_str |
end if |
ret |
;*************************************************************************** |
; Function: sis900_init |
; |
; Description: resets the ethernet controller chip and various |
; data structures required for sending and receiving packets. |
; |
; Arguments: |
; |
; returns: none |
;not done |
;*************************************************************************** |
sis900_init: |
call SIS900_reset ;Done |
call SIS900_init_rxfilter ;Done |
call SIS900_init_txd ;Done |
call SIS900_init_rxd ;Done |
call SIS900_set_rx_mode ;done |
call SIS900_set_tx_mode |
;call SIS900_check_mode |
ret |
;*************************************************************************** |
; Function |
; SIS900_reset |
; Description |
; disables interrupts and soft resets the controller chip |
; |
;done+ |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Reset_Failed db 'Reset Failed ',0 |
end if |
SIS900_reset: |
;******Disable Interrupts and reset Receive Filter******* |
mov ebp, [io_addr] ; base address |
xor eax, eax ; 0 to initialize |
lea edx,[ebp+SIS900_ier] |
out dx, eax ; Write 0 to location |
lea edx,[ebp+SIS900_imr] |
out dx, eax ; Write 0 to location |
lea edx,[ebp+SIS900_rfcr] |
out dx, eax ; Write 0 to location |
;*******Reset Card*********************************************** |
lea edx,[ebp+SIS900_cr] |
in eax, dx ; Get current Command Register |
or eax, SIS900_RESET ; set flags |
or eax, SIS900_RxRESET ; |
or eax, SIS900_TxRESET ; |
out dx, eax ; Write new Command Register |
;*******Wait Loop************************************************ |
lea edx,[ebp+SIS900_isr] |
mov ecx, [SIS900_Status] ; Status we would like to see from card |
mov ebx, 2001 ; only loop 1000 times |
SIS900_Wait: |
dec ebx ; 1 less loop |
jz SIS900_DoneWait_e ; 1000 times yet? |
in eax, dx ; move interrup status to eax |
and eax, ecx |
xor ecx, eax |
jz SIS900_DoneWait |
jmp SIS900_Wait |
SIS900_DoneWait_e: |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Reset_Failed |
call sys_msg_board_str |
end if |
SIS900_DoneWait: |
;*******Set Configuration Register depending on Card Revision******** |
lea edx,[ebp+SIS900_cfg] |
mov eax, SIS900_PESEL ; Configuration Register Bit |
mov bl, [SIS900_pci_revision] ; card revision |
mov cl, SIS635A_900_REV ; Check card revision |
cmp bl, cl |
je SIS900_RevMatch |
mov cl, SIS900B_900_REV ; Check card revision |
cmp bl, cl |
je SIS900_RevMatch |
out dx, eax ; no revision match |
jmp SIS900_Reset_Complete |
SIS900_RevMatch: ; Revision match |
or eax, SIS900_RND_CNT ; Configuration Register Bit |
out dx, eax |
SIS900_Reset_Complete: |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
;*************************************************************************** |
; Function: sis_init_rxfilter |
; |
; Description: sets receive filter address to our MAC address |
; |
; Arguments: |
; |
; returns: |
;done+ |
;*************************************************************************** |
SIS900_init_rxfilter: |
;****Get Receive Filter Control Register ******** |
mov ebp, [io_addr] ; base address |
lea edx,[ebp+SIS900_rfcr] |
in eax, dx ; get register |
push eax |
;****disable packet filtering before setting filter******* |
mov eax, SIS900_RFEN ;move receive filter enable flag |
not eax ;1s complement |
pop ebx ;and with our saved register |
and eax, ebx ;disable receiver |
push ebx ;save filter for another use |
out dx, eax ;set receive disabled |
;********load MAC addr to filter data register********* |
xor ecx, ecx |
SIS900_RXINT_Mac_Write: |
;high word of eax tells card which mac byte to write |
mov eax, ecx |
lea edx,[ebp+SIS900_rfcr] |
shl eax, 16 ; |
out dx, eax ; |
lea edx,[ebp+SIS900_rfdr] |
mov ax, word [node_addr+ecx*2] ; Get Mac ID word |
out dx, ax ; Send Mac ID |
inc cl ; send next word |
cmp cl, 3 ; more to send? |
jne SIS900_RXINT_Mac_Write |
;********enable packet filitering ***** |
pop eax ;old register value |
lea edx,[ebp+SIS900_rfcr] |
or eax, SIS900_RFEN ;enable filtering |
out dx, eax ;set register |
ret |
;*************************************************************************** |
;* |
;* Function: sis_init_txd |
;* |
;* Description: initializes the Tx descriptor |
;* |
;* Arguments: |
;* |
;* returns: |
;*done |
;*************************************************************************** |
SIS900_init_txd: |
;********** initialize TX descriptor ************** |
mov [txd], dword 0 ;put link to next descriptor in link field |
mov [txd+4],dword 0 ;clear status field |
mov [txd+8], dword txb - OS_BASE ;save address to buffer ptr field |
;*************** load Transmit Descriptor Register *************** |
mov dx, [io_addr] ; base address |
add dx, SIS900_txdp ; TX Descriptor Pointer |
mov eax, txd - OS_BASE ; First Descriptor |
out dx, eax ; move the pointer |
ret |
;*************************************************************************** |
;* Function: sis_init_rxd |
;* |
;* Description: initializes the Rx descriptor ring |
;* |
;* Arguments: |
;* |
;* Returns: |
;*done |
;*************************************************************************** |
SIS900_init_rxd: |
xor ecx,ecx |
mov [cur_rx], cl ;Set cuurent rx discriptor to 0 |
;******** init RX descriptors ******** |
SIS900_init_rxd_Loop: |
mov eax, ecx ;current descriptor |
imul eax, 12 ; |
mov ebx, ecx ;determine next link descriptor |
inc ebx ; |
cmp ebx, NUM_RX_DESC ; |
jne SIS900_init_rxd_Loop_0 ; |
xor ebx, ebx ; |
SIS900_init_rxd_Loop_0: ; |
imul ebx, 12 ; |
add ebx, rxd - OS_BASE ; |
mov [rxd+eax], ebx ;save link to next descriptor |
mov [rxd+eax+4],dword RX_BUFF_SZ ;status bits init to buf size |
mov ebx, ecx ;find where the buf is located |
imul ebx,RX_BUFF_SZ ; |
add ebx, rxb - OS_BASE ; |
mov [rxd+eax+8], ebx ;save buffer pointer |
inc ecx ;next descriptor |
cmp ecx, NUM_RX_DESC ; |
jne SIS900_init_rxd_Loop ; |
;********* load Receive Descriptor Register with address of first |
; descriptor********* |
mov dx, [io_addr] |
add dx, SIS900_rxdp |
mov eax, rxd - OS_BASE |
out dx, eax |
ret |
;*************************************************************************** |
;* Function: sis900_set_tx_mode |
;* |
;* Description: |
;* sets the transmit mode to allow for full duplex |
;* |
;* |
;* Arguments: |
;* |
;* Returns: |
;* |
;* Comments: |
;* If you are having problems transmitting packet try changing the |
;* Max DMA Burst, Possible settings are as follows: |
;* 0x00000000 = 512 bytes |
;* 0x00100000 = 4 bytes |
;* 0x00200000 = 8 bytes |
;* 0x00300000 = 16 bytes |
;* 0x00400000 = 32 bytes |
;* 0x00500000 = 64 bytes |
;* 0x00600000 = 128 bytes |
;* 0x00700000 = 256 bytes |
;*************************************************************************** |
SIS900_set_tx_mode: |
mov ebp,[io_addr] |
lea edx,[ebp+SIS900_cr] |
in eax, dx ; Get current Command Register |
or eax, SIS900_TxENA ;Enable Receive |
out dx, eax |
lea edx,[ebp+SIS900_txcfg]; Transmit config Register offset |
mov eax, SIS900_ATP ;allow automatic padding |
or eax, SIS900_HBI ;allow heartbeat ignore |
or eax, SIS900_CSI ;allow carrier sense ignore |
or eax, 0x00600000 ;Max DMA Burst |
or eax, 0x00000100 ;TX Fill Threshold |
or eax, 0x00000020 ;TX Drain Threshold |
out dx, eax |
ret |
;*************************************************************************** |
;* Function: sis900_set_rx_mode |
;* |
;* Description: |
;* sets the receive mode to accept all broadcast packets and packets |
;* with our MAC address, and reject all multicast packets. Also allows |
;* full-duplex |
;* |
;* Arguments: |
;* |
;* Returns: |
;* |
;* Comments: |
;* If you are having problems receiving packet try changing the |
;* Max DMA Burst, Possible settings are as follows: |
;* 0x00000000 = 512 bytes |
;* 0x00100000 = 4 bytes |
;* 0x00200000 = 8 bytes |
;* 0x00300000 = 16 bytes |
;* 0x00400000 = 32 bytes |
;* 0x00500000 = 64 bytes |
;* 0x00600000 = 128 bytes |
;* 0x00700000 = 256 bytes |
;*************************************************************************** |
SIS900_mc_filter: times 16 dw 0 |
SIS900_set_rx_mode: |
mov ebp,[io_addr] |
;**************update Multicast Hash Table in Receive Filter |
mov ebx, 0xffff |
xor cl, cl |
SIS900_set_rx_mode_Loop: |
mov eax, ecx |
shl eax, 1 |
mov [SIS900_mc_filter+eax], bx |
lea edx,[ebp+SIS900_rfcr] ; Receive Filter Control Reg offset |
mov eax, 4 ;determine table entry |
add al, cl |
shl eax, 16 |
out dx, eax ;tell card which entry to modify |
lea edx,[ebp+SIS900_rfdr] ; Receive Filter Control Reg offset |
mov eax, ebx ;entry value |
out dx, ax ;write value to table in card |
inc cl ;next entry |
cmp cl,[sis900_table_entries] ; |
jl SIS900_set_rx_mode_Loop |
;*******Set Receive Filter Control Register************* |
lea edx,[ebp+SIS900_rfcr] ; Receive Filter Control Register offset |
mov eax, SIS900_RFAAB ;accecpt all broadcast packets |
or eax, SIS900_RFAAM ;accept all multicast packets |
or eax, SIS900_RFAAP ;Accept all packets |
or eax, SIS900_RFEN ;enable receiver filter |
out dx, eax |
;******Enable Receiver************ |
lea edx,[ebp+SIS900_cr] ; Command Register offset |
in eax, dx ; Get current Command Register |
or eax, SIS900_RxENA ;Enable Receive |
out dx, eax |
;*********Set |
lea edx,[ebp+SIS900_rxcfg] ; Receive Config Register offset |
mov eax, SIS900_ATX ;Accept Transmit Packets |
; (Req for full-duplex and PMD Loopback) |
or eax, 0x00600000 ;Max DMA Burst |
or eax, 0x00000002 ;RX Drain Threshold, 8X8 bytes or 64bytes |
out dx, eax ; |
ret |
;*************************************************************************** |
; * SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model |
; * @pci_dev: the sis900 pci device |
; * @net_dev: the net device to get address for |
; * |
; * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM |
; * is shared by |
; * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first |
; * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access |
; * by LAN, otherwise is not. After MAC address is read from EEPROM, send |
; * EEDONE signal to refuse EEPROM access by LAN. |
; * The EEPROM map of SiS962 or SiS963 is different to SiS900. |
; * The signature field in SiS962 or SiS963 spec is meaningless. |
; * MAC address is read into @net_dev->dev_addr. |
; *done |
;* |
;* Return 0 is EAX = failure |
;*Done+ |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Str_GetMac_Start db 'Attempting to get SIS900 Mac ID: ',13,10,0 |
SIS900_Debug_Str_GetMac_Failed db 'Access to EEprom Failed',13,10,0 |
SIS900_Debug_Str_GetMac_Address db 'Your Mac ID is: ',0 |
SIS900_Debug_Str_GetMac_Address2 db 'Your SIS96x Mac ID is: ',0 |
end if |
SIS960_get_mac_addr: |
mov ebp,[io_addr] |
;**********Send Request for eeprom access********************* |
lea edx,[ebp+SIS900_mear] ; Eeprom access register |
mov eax, SIS900_EEREQ ; Request access to eeprom |
out dx, eax ; Send request |
xor ebx,ebx ; |
;******Loop 4000 times and if access not granted error out***** |
SIS96X_Get_Mac_Wait: |
in eax, dx ;get eeprom status |
and eax, SIS900_EEGNT ;see if eeprom access granted flag is set |
jnz SIS900_Got_EEP_Access ;if it is, go access the eeprom |
inc ebx ;else keep waiting |
cmp ebx, 4000 ;have we tried 4000 times yet? |
jl SIS96X_Get_Mac_Wait ;if not ask again |
xor eax, eax ;return zero in eax indicating failure |
;*******Debug ********************** |
if defined SIS900_DEBUG |
mov esi,SIS900_Debug_Str_GetMac_Failed |
call sys_msg_board_str |
end if |
jmp SIS960_get_mac_addr_done |
;**********EEprom access granted, read MAC from card************* |
SIS900_Got_EEP_Access: |
; zero based so 3-16 bit reads will take place |
mov ecx, 2 |
SIS96x_mac_read_loop: |
mov eax, SIS900_EEPROMMACAddr ;Base Mac Address |
add eax, ecx ;Current Mac Byte Offset |
push ecx |
call sis900_read_eeprom ;try to read 16 bits |
pop ecx |
mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID varible |
dec ecx ;one less word to read |
jns SIS96x_mac_read_loop ;if more read more |
mov eax, 1 ;return non-zero indicating success |
;*******Debug Print MAC ID to debug window********************** |
if defined SIS900_DEBUG |
mov esi,SIS900_Debug_Str_GetMac_Address2 |
call sys_msg_board_str |
mov edx, node_addr |
call Create_Mac_String |
end if |
;**********Tell EEPROM We are Done Accessing It********************* |
SIS960_get_mac_addr_done: |
lea edx,[ebp+SIS900_mear] ; Eeprom access register |
mov eax, SIS900_EEDONE ;tell eeprom we are done |
out dx,eax |
ret |
;*************************************************************************** |
;* sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model |
;* @pci_dev: the sis900 pci device |
;* @net_dev: the net device to get address for |
;* |
;* Older SiS900 and friends, use EEPROM to store MAC address. |
;* MAC address is read from read_eeprom() into @net_dev->dev_addr. |
;* done/untested |
;*************************************************************************** |
SIS900_get_mac_addr: |
;*******Debug ********************** |
if defined SIS900_DEBUG |
mov esi,SIS900_Debug_Str_GetMac_Start |
call sys_msg_board_str |
end if |
;******** check to see if we have sane EEPROM ******* |
mov eax, SIS900_EEPROMSignature ;Base Eeprom Signature |
call sis900_read_eeprom ;try to read 16 bits |
cmp ax, 0xffff |
je SIS900_Bad_Eeprom |
cmp ax, 0 |
je SIS900_Bad_Eeprom |
;**************Read MacID************** |
; zero based so 3-16 bit reads will take place |
mov ecx, 2 |
SIS900_mac_read_loop: |
mov eax, SIS900_EEPROMMACAddr ;Base Mac Address |
add eax, ecx ;Current Mac Byte Offset |
push ecx |
call sis900_read_eeprom ;try to read 16 bits |
pop ecx |
mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID storage |
dec ecx ;one less word to read |
jns SIS900_mac_read_loop ;if more read more |
mov eax, 1 ;return non-zero indicating success |
;*******Debug Print MAC ID to debug window********************** |
if defined SIS900_DEBUG |
mov esi,SIS900_Debug_Str_GetMac_Address |
call sys_msg_board_str |
mov edx, node_addr |
call Create_Mac_String |
end if |
ret |
SIS900_Bad_Eeprom: |
xor eax, eax |
;*******Debug ********************** |
if defined SIS900_DEBUG |
mov esi,SIS900_Debug_Str_GetMac_Failed |
call sys_msg_board_str |
end if |
ret |
;*************************************************************************** |
;* Get_Mac_SIS635_900_REV: - Get MAC address for model 635 |
;* |
;* |
;*************************************************************************** |
Get_Mac_SIS635_900_REV: |
if defined SIS900_DEBUG |
mov esi,SIS900_Debug_Str_GetMac_Start |
call sys_msg_board_str |
end if |
mov ebp,[io_addr] |
lea edx,[ebp+SIS900_rfcr] |
in eax,dx |
mov edi,eax ; EDI=rfcrSave |
lea edx,[ebp+SIS900_cr] |
or eax,SIS900_RELOAD |
out dx,eax |
xor eax,eax |
out dx,eax |
; Disable packet filtering before setting filter |
lea edx,[ebp+SIS900_rfcr] |
mov eax,edi |
and edi,not SIS900_RFEN |
out dx,eax |
; Load MAC to filter data register |
xor ecx,ecx |
mov esi,node_addr |
.get_mac_loop: |
lea edx,[ebp+SIS900_rfcr] |
mov eax,ecx |
shl eax,SIS900_RFADDR_shift |
out dx,eax |
lea edx,[ebp+SIS900_rfdr] |
in eax,dx |
mov [esi],ax |
add esi,2 |
inc ecx |
cmp ecx,3 |
jne .get_mac_loop |
; Enable packet filtering |
;lea edx,[ebp+SIS900_rfcr] |
;mov eax,edi |
;or eax,SIS900_RFEN |
;out dx, eax |
;*******Debug Print MAC ID to debug window********************** |
if defined SIS900_DEBUG |
mov esi,SIS900_Debug_Str_GetMac_Address |
call sys_msg_board_str |
mov edx, node_addr |
call Create_Mac_String |
end if |
ret |
;*************************************************************************** |
;* Function: sis900_read_eeprom |
;* |
;* Description: reads and returns a given location from EEPROM |
;* |
;* Arguments: eax - location: requested EEPROM location |
;* |
;* Returns: eax : contents of requested EEPROM location |
;* |
; Read Serial EEPROM through EEPROM Access Register, Note that location is |
; in word (16 bits) unit */ |
;done+ |
;*************************************************************************** |
sis900_read_eeprom: |
push esi |
push edx |
push ecx |
push ebx |
mov ebp,[io_addr] |
mov ebx, eax ;location of Mac byte to read |
or ebx, SIS900_EEread ; |
lea edx,[ebp+SIS900_mear] ; Eeprom access register |
xor eax, eax ; start send |
out dx,eax |
call SIS900_Eeprom_Delay_1 |
mov eax, SIS900_EECLK |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
;************ Shift the read command (9) bits out. ********* |
mov cl, 8 ; |
sis900_read_eeprom_Send: |
mov eax, 1 |
shl eax, cl |
and eax, ebx |
jz SIS900_Read_Eeprom_8 |
mov eax, 9 |
jmp SIS900_Read_Eeprom_9 |
SIS900_Read_Eeprom_8: |
mov eax, 8 |
SIS900_Read_Eeprom_9: |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
or eax, SIS900_EECLK |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
cmp cl, 0 |
je sis900_read_eeprom_Send_Done |
dec cl |
jmp sis900_read_eeprom_Send |
;********************* |
sis900_read_eeprom_Send_Done: |
mov eax, SIS900_EECS ; |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
;********** Read 16-bits of data in *************** |
mov cx, 16 ;16 bits to read |
sis900_read_eeprom_Send2: |
mov eax, SIS900_EECS |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
or eax, SIS900_EECLK |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
in eax, dx |
shl ebx, 1 |
and eax, SIS900_EEDO |
jz SIS900_Read_Eeprom_0 |
or ebx, 1 |
SIS900_Read_Eeprom_0: |
dec cx |
jnz sis900_read_eeprom_Send2 |
;************** Terminate the EEPROM access. ************** |
xor eax, eax |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
mov eax, SIS900_EECLK |
out dx, eax |
mov eax, ebx |
and eax, 0x0000ffff ;return only 16 bits |
pop ebx |
pop ecx |
pop edx |
pop esi |
ret |
;*************************************************************************** |
; Function |
; SIS900_Eeprom_Delay_1 |
; Description |
; |
; |
; |
; |
;*************************************************************************** |
SIS900_Eeprom_Delay_1: |
push eax |
in eax, dx |
pop eax |
ret |
;*************************************************************************** |
; Function |
; SIS900_poll |
; Description |
; polls card to see if there is a packet waiting |
; |
; Currently only supports one descriptor per packet, if packet is fragmented |
; between multiple descriptors you will lose part of the packet |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Pull_Packet_good db 'Good Packet Waiting: ',13,10,0 |
SIS900_Debug_Pull_Bad_Packet_Status db 'Bad Packet Waiting: Status',13,10,0 |
SIS900_Debug_Pull_Bad_Packet_Size db 'Bad Packet Waiting: Size',13,10,0 |
end if |
SIS900_poll: |
;**************Get Status ************** |
xor eax, eax ;get RX_Status |
mov [eth_rx_data_len], ax |
mov al, [cur_rx] ;find current discriptor |
imul eax, 12 ; |
mov ecx, [rxd+eax+4] ; get receive status |
;**************Check Status ************** |
mov ebx, ecx ;move status |
;Check RX_Status to see if packet is waiting |
and ebx, 0x80000000 |
jnz SIS900_poll_IS_packet |
ret |
;**********There is a packet waiting check it for errors************** |
SIS900_poll_IS_packet: |
mov ebx, ecx ;move status |
and ebx, 0x67C0000 ;see if there are any errors |
jnz SIS900_Poll_Error_Status |
;**************Check size of packet************* |
and ecx, SIS900_DSIZE ;get packet size minus CRC |
cmp cx, SIS900_CRC_SIZE |
;make sure packet contains data |
jle SIS900_Poll_Error_Size |
;*******Copy Good Packet to receive buffer****** |
sub cx, SIS900_CRC_SIZE ;dont want crc |
mov word [eth_rx_data_len], cx ;save size of packet |
;**********Continue copying packet**************** |
push ecx |
; first copy dword-wise, divide size by 4 |
shr ecx, 2 |
mov esi, [rxd+eax+8] ; set source |
add esi, OS_BASE ; get linear address |
mov edi, Ether_buffer ; set destination |
cld ; clear direction |
rep movsd ; copy the dwords |
pop ecx |
and ecx, 3 ; |
rep movsb |
;********Debug, tell user we have a good packet************* |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Pull_Packet_good |
call sys_msg_board_str |
end if |
jmp SIS900_Poll_Cnt ; |
;*************Error occured let user know through debug window*********** |
SIS900_Poll_Error_Status: |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Pull_Bad_Packet_Status |
call sys_msg_board_str |
end if |
jmp SIS900_Poll_Cnt |
SIS900_Poll_Error_Size: |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Pull_Bad_Packet_Size |
call sys_msg_board_str |
end if |
;*************Increment to next available descriptor************** |
SIS900_Poll_Cnt: |
;Reset status, allow ethernet card access to descriptor |
mov ecx, RX_BUFF_SZ |
mov [rxd+eax+4], ecx ; |
inc [cur_rx] ;get next descriptor |
and [cur_rx],3 ;only 4 descriptors 0-3 |
;******Enable Receiver************ |
mov ebp, [io_addr] ; Base Address |
lea edx,[ebp+SIS900_cr] ; Command Register offset |
in eax, dx ; Get current Command Register |
or eax, SIS900_RxENA ;Enable Receive |
out dx, eax |
ret |
;*************************************************************************** |
; Function |
; SIS900_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
; |
; only one transmit descriptor is used |
; |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Transmit_Packet db 'Transmitting Packet: ',13,10,0 |
SIS900_Debug_Transmit_Packet_Err db 'Transmitting Packet Error: ',13,10,0 |
end if |
str1 db 'Transmitting packet:',13,10,0 |
str2 db ' ',0 |
SIS900_transmit: |
mov ebp, [io_addr] ; Base Address |
;******** Stop the transmitter ******** |
lea edx,[ebp+SIS900_cr] ; Command Register offset |
in eax, dx ; Get current Command Register |
or eax, SIS900_TxDIS ; Disable Transmitter |
out dx, eax |
;*******load Transmit Descriptor Register ******* |
lea edx,[ebp+SIS900_txdp] |
mov eax, txd - OS_BASE |
out dx, eax |
;******* copy packet to descriptor******* |
push esi |
mov esi, edi ;copy destination addess |
mov edi, txb |
cld |
movsd |
movsw |
mov esi, node_addr ;copy my mac address |
movsd |
movsw |
mov [edi], bx ;copy packet type |
add edi, 2 |
pop esi ;restore pointer to source of packet |
push ecx ;save packet size |
shr ecx, 2 ;divide by 4, size in bytes send in dwords |
rep movsd ;copy data to decriptor |
pop ecx ;restore packet size |
push ecx ;save packet size |
and ecx, 3 ;last three bytes if not a multiple of 4 |
rep movsb |
;**************set length tag************** |
pop ecx ;restore packet size |
add ecx, SIS900_ETH_HLEN ;add header to length |
and ecx, SIS900_DSIZE ; |
;**************pad to minimum packet size **************not needed |
;cmp ecx, SIS900_ETH_ZLEN |
;jge SIS900_transmit_Size_Ok |
;push ecx |
;mov ebx, SIS900_ETH_ZLEN |
;sub ebx, ecx |
;mov ecx, ebx |
;rep movsb |
;pop ecx |
SIS900_transmit_Size_Ok: |
mov [txd+4], dword 0x80000000 ;card owns descriptor |
or [txd+4], ecx ;set size of packet |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Transmit_Packet |
call sys_msg_board_str |
end if |
;***************restart the transmitter ******** |
lea edx,[ebp+SIS900_cr] |
in eax, dx ; Get current Command Register |
or eax, SIS900_TxENA ; Enable Transmitter |
out dx, eax |
;****make sure packet transmitted successfully**** |
; mov esi,10 |
; call delay_ms |
mov eax, [txd+4] |
and eax, 0x6200000 |
jz SIS900_transmit_OK |
;**************Tell user there was an error through debug window |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Transmit_Packet_Err |
call sys_msg_board_str |
end if |
SIS900_transmit_OK: |
;******** Disable interrupts by clearing the interrupt mask. ******** |
lea edx,[ebp+SIS900_imr] ; Interupt Mask Register |
xor eax, eax |
out dx,eax |
ret |
;*************************************************************************** |
;* Function: Create_Mac_String |
;* |
;* Description: Converts the 48 bit value to a string for display |
;* |
;* String Format: XX:XX:XX:XX:XX:XX |
;* |
;* Arguments: node_addr is location of 48 bit MAC ID |
;* |
;* Returns: Prints string to general debug window |
;* |
;* |
;done |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Char_String db '0','1','2','3','4','5','6','7','8','9' |
db 'A','B','C','D','E','F' |
Mac_str_build: times 20 db 0 |
Create_Mac_String: |
pusha |
xor ecx, ecx |
Create_Mac_String_loop: |
mov al,byte [edx+ecx];[node_addr+ecx] |
push eax |
shr eax, 4 |
and eax, 0x0f |
mov bl, byte [SIS900_Char_String+eax] |
mov [Mac_str_build+ecx*3], bl |
pop eax |
and eax, 0x0f |
mov bl, byte [SIS900_Char_String+eax] |
mov [Mac_str_build+1+ecx*3], bl |
cmp ecx, 5 |
je Create_Mac_String_done |
mov bl, ':' |
mov [Mac_str_build+2+ecx*3], bl |
inc ecx |
jmp Create_Mac_String_loop |
Create_Mac_String_done: ;Insert CR and Zero Terminate |
mov [Mac_str_build+2+ecx*3],byte 13 |
mov [Mac_str_build+3+ecx*3],byte 10 |
mov [Mac_str_build+4+ecx*3],byte 0 |
mov esi, Mac_str_build |
call sys_msg_board_str ;Print String to message board |
popa |
ret |
end if |
;*************************************************************************** |
;* Set device to be a busmaster in case BIOS neglected to do so. |
;* Also adjust PCI latency timer to a reasonable value, 64. |
;*************************************************************************** |
SIS900_adjust_pci_device: |
;*******Get current setting************************ |
mov al, 2 ;read a word |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, 0x04 ;from command Register |
call pci_read_reg |
;******see if its already set as bus master******** |
mov bx, ax |
and bx,5 |
cmp bx,5 |
je SIS900_adjust_pci_device_Latency |
;******Make card a bus master******* |
mov cx, ax ;value to write |
mov bh, [pci_dev] |
mov al, 2 ;write a word |
or cx,5 |
mov ah, [pci_bus] |
mov bl, 0x04 ;to command register |
call pci_write_reg |
;******Check latency setting*********** |
SIS900_adjust_pci_device_Latency: |
;*******Get current latency setting************************ |
mov al, 1 ;read a byte |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, 0x0D ;from Lantency Timer Register |
call pci_read_reg |
;******see if its aat least 64 clocks******** |
cmp ax,64 |
jge SIS900_adjust_pci_device_Done |
;******Set latency to 32 clocks******* |
mov cx, 64 ;value to write |
mov bh, [pci_dev] |
mov al, 1 ;write a byte |
mov ah, [pci_bus] |
mov bl, 0x0D ;to Lantency Timer Register |
call pci_write_reg |
;******Check latency setting*********** |
SIS900_adjust_pci_device_Done: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; SIS900.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.4 26 April 2004 ;; |
;; ;; |
;; This driver is based on the SIS900 driver from ;; |
;; the etherboot 5.0.6 project. The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2004 Jason Delozier, ;; |
;; cordata51@hotmail.com ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; Updates: ;; |
;; Revision Look up table and SIS635 Mac Address by Jarek Pelczar ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************** |
; Interface |
; SIS900_reset |
; SIS900_probe |
; SIS900_poll |
; SIS900_transmit |
; |
;******************************************************************** |
;******************************************************************** |
; Comments: |
; Known to work with the following SIS900 ethernet cards: |
; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x91 |
; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x90 |
; |
; If your card is not listed, try it and let me know if it |
; functions properly and it will be aded to the list. If not |
; we may be able to add support for it. |
; |
; How To Use: |
; Add the following lines to Ethernet.inc in their appropriate locations |
; |
; include "Sis900.INC" |
; dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, |
; SIS900_transmit |
; dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, |
; SIS900_transmit ;untested |
; |
; ToDo: |
; - Enable MII interface for reading speed |
; and duplex settings. |
; |
; - Update Poll routine to support packet fragmentation. |
; |
; - Add additional support for other sis900 based cards |
; |
;******************************************************************** |
; comment the next line out if you don't want debug info printed |
; on the debug board. This option adds a lot of bytes to the driver |
; so it's worth to comment it out. |
; SIS900_DEBUG equ 1 |
;* buffers and descriptors |
cur_rx db 0 |
NUM_RX_DESC equ 4 ;* Number of RX descriptors * |
NUM_TX_DESC equ 1 ;* Number of TX descriptors * |
RX_BUFF_SZ equ 1520 ;* Buffer size for each Rx buffer * |
TX_BUFF_SZ equ 1516 ;* Buffer size for each Tx buffer * |
uglobal |
align 4 |
txd: |
times (3 * NUM_TX_DESC) dd 0 |
rxd: |
times (3 * NUM_RX_DESC) dd 0 |
endg |
txb equ eth_data_start |
rxb equ txb + (NUM_TX_DESC * TX_BUFF_SZ) |
SIS900_ETH_ALEN equ 6 ;* Size of Ethernet address * |
SIS900_ETH_HLEN equ 14 ;* Size of ethernet header * |
SIS900_ETH_ZLEN equ 60 ;* Minimum packet length * |
SIS900_DSIZE equ 0x00000fff |
SIS900_CRC_SIZE equ 4 |
SIS900_RFADDR_shift equ 16 |
;SIS900 Symbolic offsets to registers. |
SIS900_cr equ 0x0 ; Command Register |
SIS900_cfg equ 0x4 ; Configuration Register |
SIS900_mear equ 0x8 ; EEPROM Access Register |
SIS900_ptscr equ 0xc ; PCI Test Control Register |
SIS900_isr equ 0x10 ; Interrupt Status Register |
SIS900_imr equ 0x14 ; Interrupt Mask Register |
SIS900_ier equ 0x18 ; Interrupt Enable Register |
SIS900_epar equ 0x18 ; Enhanced PHY Access Register |
SIS900_txdp equ 0x20 ; Transmit Descriptor Pointer Register |
SIS900_txcfg equ 0x24 ; Transmit Configuration Register |
SIS900_rxdp equ 0x30 ; Receive Descriptor Pointer Register |
SIS900_rxcfg equ 0x34 ; Receive Configuration Register |
SIS900_flctrl equ 0x38 ; Flow Control Register |
SIS900_rxlen equ 0x3c ; Receive Packet Length Register |
SIS900_rfcr equ 0x48 ; Receive Filter Control Register |
SIS900_rfdr equ 0x4C ; Receive Filter Data Register |
SIS900_pmctrl equ 0xB0 ; Power Management Control Register |
SIS900_pmer equ 0xB4 ; Power Management Wake-up Event Register |
;SIS900 Command Register Bits |
SIS900_RELOAD equ 0x00000400 |
SIS900_ACCESSMODE equ 0x00000200 |
SIS900_RESET equ 0x00000100 |
SIS900_SWI equ 0x00000080 |
SIS900_RxRESET equ 0x00000020 |
SIS900_TxRESET equ 0x00000010 |
SIS900_RxDIS equ 0x00000008 |
SIS900_RxENA equ 0x00000004 |
SIS900_TxDIS equ 0x00000002 |
SIS900_TxENA equ 0x00000001 |
;SIS900 Configuration Register Bits |
SIS900_DESCRFMT equ 0x00000100 ; 7016 specific |
SIS900_REQALG equ 0x00000080 |
SIS900_SB equ 0x00000040 |
SIS900_POW equ 0x00000020 |
SIS900_EXD equ 0x00000010 |
SIS900_PESEL equ 0x00000008 |
SIS900_LPM equ 0x00000004 |
SIS900_BEM equ 0x00000001 |
SIS900_RND_CNT equ 0x00000400 |
SIS900_FAIR_BACKOFF equ 0x00000200 |
SIS900_EDB_MASTER_EN equ 0x00002000 |
;SIS900 Eeprom Access Reigster Bits |
SIS900_MDC equ 0x00000040 |
SIS900_MDDIR equ 0x00000020 |
SIS900_MDIO equ 0x00000010 ; 7016 specific |
SIS900_EECS equ 0x00000008 |
SIS900_EECLK equ 0x00000004 |
SIS900_EEDO equ 0x00000002 |
SIS900_EEDI equ 0x00000001 |
;SIS900 TX Configuration Register Bits |
SIS900_ATP equ 0x10000000 ;Automatic Transmit Padding |
SIS900_MLB equ 0x20000000 ;Mac Loopback Enable |
SIS900_HBI equ 0x40000000 ;HeartBeat Ignore (Req for full-dup) |
SIS900_CSI equ 0x80000000 ;CarrierSenseIgnore (Req for full-du |
;SIS900 RX Configuration Register Bits |
SIS900_AJAB equ 0x08000000 ; |
SIS900_ATX equ 0x10000000 ;Accept Transmit Packets |
SIS900_ARP equ 0x40000000 ;accept runt packets (<64bytes) |
SIS900_AEP equ 0x80000000 ;accept error packets |
;SIS900 Interrupt Reigster Bits |
SIS900_WKEVT equ 0x10000000 |
SIS900_TxPAUSEEND equ 0x08000000 |
SIS900_TxPAUSE equ 0x04000000 |
SIS900_TxRCMP equ 0x02000000 |
SIS900_RxRCMP equ 0x01000000 |
SIS900_DPERR equ 0x00800000 |
SIS900_SSERR equ 0x00400000 |
SIS900_RMABT equ 0x00200000 |
SIS900_RTABT equ 0x00100000 |
SIS900_RxSOVR equ 0x00010000 |
SIS900_HIBERR equ 0x00008000 |
SIS900_SWINT equ 0x00001000 |
SIS900_MIBINT equ 0x00000800 |
SIS900_TxURN equ 0x00000400 |
SIS900_TxIDLE equ 0x00000200 |
SIS900_TxERR equ 0x00000100 |
SIS900_TxDESC equ 0x00000080 |
SIS900_TxOK equ 0x00000040 |
SIS900_RxORN equ 0x00000020 |
SIS900_RxIDLE equ 0x00000010 |
SIS900_RxEARLY equ 0x00000008 |
SIS900_RxERR equ 0x00000004 |
SIS900_RxDESC equ 0x00000002 |
SIS900_RxOK equ 0x00000001 |
;SIS900 Interrupt Enable Reigster Bits |
SIS900_IE equ 0x00000001 |
;SIS900 Revision ID |
SIS900B_900_REV equ 0x03 |
SIS630A_900_REV equ 0x80 |
SIS630E_900_REV equ 0x81 |
SIS630S_900_REV equ 0x82 |
SIS630EA1_900_REV equ 0x83 |
SIS630ET_900_REV equ 0x84 |
SIS635A_900_REV equ 0x90 |
SIS900_960_REV equ 0x91 |
;SIS900 Receive Filter Control Register Bits |
SIS900_RFEN equ 0x80000000 |
SIS900_RFAAB equ 0x40000000 |
SIS900_RFAAM equ 0x20000000 |
SIS900_RFAAP equ 0x10000000 |
SIS900_RFPromiscuous equ 0x70000000 |
;SIS900 Reveive Filter Data Mask |
SIS900_RFDAT equ 0x0000FFFF |
;SIS900 Eeprom Address |
SIS900_EEPROMSignature equ 0x00 |
SIS900_EEPROMVendorID equ 0x02 |
SIS900_EEPROMDeviceID equ 0x03 |
SIS900_EEPROMMACAddr equ 0x08 |
SIS900_EEPROMChecksum equ 0x0b |
;The EEPROM commands include the alway-set leading bit. |
;SIS900 Eeprom Command |
SIS900_EEread equ 0x0180 |
SIS900_EEwrite equ 0x0140 |
SIS900_EEerase equ 0x01C0 |
SIS900_EEwriteEnable equ 0x0130 |
SIS900_EEwriteDisable equ 0x0100 |
SIS900_EEeraseAll equ 0x0120 |
SIS900_EEwriteAll equ 0x0110 |
SIS900_EEaddrMask equ 0x013F |
SIS900_EEcmdShift equ 16 |
;For SiS962 or SiS963, request the eeprom software access |
SIS900_EEREQ equ 0x00000400 |
SIS900_EEDONE equ 0x00000200 |
SIS900_EEGNT equ 0x00000100 |
;General Varibles |
SIS900_pci_revision: |
db 0 |
SIS900_Status dd 0x03000000 |
sis900_specific_table: |
; dd SIS630A_900_REV,Get_Mac_SIS630A_900_REV,0 |
; dd SIS630E_900_REV,Get_Mac_SIS630E_900_REV,0 |
dd SIS630S_900_REV,Get_Mac_SIS635_900_REV,0 |
dd SIS630EA1_900_REV,Get_Mac_SIS635_900_REV,0 |
dd SIS630ET_900_REV,Get_Mac_SIS635_900_REV,0;SIS630ET_900_REV_SpecialFN |
dd SIS635A_900_REV,Get_Mac_SIS635_900_REV,0 |
dd SIS900_960_REV,SIS960_get_mac_addr,0 |
dd SIS900B_900_REV,SIS900_get_mac_addr,0 |
dd 0,0,0,0 ; end of list |
sis900_get_mac_func: |
dd 0 |
sis900_special_func: |
dd 0 |
sis900_table_entries: |
db 8 |
;*************************************************************************** |
; Function |
; SIS900_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
;not done - still need to probe mii transcievers |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Str_Unsupported db 'Sorry your card is unsupported ',13,10,0 |
end if |
SIS900_probe: |
;******Wake Up Chip******* |
mov al, 4 |
mov bh, [pci_dev] |
mov ecx, 0 |
mov ah, [pci_bus] |
mov bl, 0x40 |
call pci_write_reg |
;*******Set some PCI Settings********* |
call SIS900_adjust_pci_device |
;*****Get Card Revision****** |
mov al, 1 ;one byte to read |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, 0x08 ;Revision Register |
call pci_read_reg |
mov [SIS900_pci_revision], al;save the revision for later use |
;****** Look up through the sis900_specific_table |
mov esi, sis900_specific_table |
.probe_loop: |
cmp dword [esi], 0 ; Check if we reached end of the list |
je .probe_loop_failed |
cmp al, [esi] ; Check if revision is OK |
je .probe_loop_ok |
add esi, 12 ; Advance to next entry |
jmp .probe_loop |
.probe_loop_failed: |
jmp SIS900_Probe_Unsupported |
;*********Find Get Mac Function********* |
.probe_loop_ok: |
mov eax, [esi+4] ; Get pointer to "get MAC" function |
mov [sis900_get_mac_func], eax |
mov eax, [esi+8] ; Get pointer to special initialization fn |
mov [sis900_special_func], eax |
;******** Get MAC ******** |
call dword [sis900_get_mac_func] |
;******** Call special initialization fn if requested ******** |
cmp dword [sis900_special_func], 0 |
je .no_special_init |
call dword [sis900_special_func] |
.no_special_init: |
;******** Set table entries ******** |
mov al, [SIS900_pci_revision] |
cmp al, SIS635A_900_REV |
jae .ent16 |
cmp al, SIS900B_900_REV |
je .ent16 |
jmp .ent8 |
.ent16: |
mov byte [sis900_table_entries], 16 |
.ent8: |
;*******Probe for mii transceiver******* |
;TODO!!********************* |
;*******Initialize Device******* |
call sis900_init |
ret |
SIS900_Probe_Unsupported: |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Str_Unsupported |
call sys_msg_board_str |
end if |
ret |
;*************************************************************************** |
; Function: sis900_init |
; |
; Description: resets the ethernet controller chip and various |
; data structures required for sending and receiving packets. |
; |
; Arguments: |
; |
; returns: none |
;not done |
;*************************************************************************** |
sis900_init: |
call SIS900_reset ;Done |
call SIS900_init_rxfilter;Done |
call SIS900_init_txd;Done |
call SIS900_init_rxd ;Done |
call SIS900_set_rx_mode;done |
call SIS900_set_tx_mode |
;call SIS900_check_mode |
ret |
;*************************************************************************** |
; Function |
; SIS900_reset |
; Description |
; disables interrupts and soft resets the controller chip |
; |
;done+ |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Reset_Failed db 'Reset Failed ',0 |
end if |
SIS900_reset: |
;******Disable Interrupts and reset Receive Filter******* |
mov ebp, [io_addr] ; base address |
xor eax, eax ; 0 to initialize |
lea edx, [ebp+SIS900_ier] |
out dx, eax ; Write 0 to location |
lea edx, [ebp+SIS900_imr] |
out dx, eax ; Write 0 to location |
lea edx, [ebp+SIS900_rfcr] |
out dx, eax ; Write 0 to location |
;*******Reset Card*********************************************** |
lea edx, [ebp+SIS900_cr] |
in eax, dx ; Get current Command Register |
or eax, SIS900_RESET ; set flags |
or eax, SIS900_RxRESET ; |
or eax, SIS900_TxRESET ; |
out dx, eax ; Write new Command Register |
;*******Wait Loop************************************************ |
lea edx, [ebp+SIS900_isr] |
mov ecx, [SIS900_Status]; Status we would like to see from card |
mov ebx, 2001 ; only loop 1000 times |
SIS900_Wait: |
dec ebx ; 1 less loop |
jz SIS900_DoneWait_e ; 1000 times yet? |
in eax, dx ; move interrup status to eax |
and eax, ecx |
xor ecx, eax |
jz SIS900_DoneWait |
jmp SIS900_Wait |
SIS900_DoneWait_e: |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Reset_Failed |
call sys_msg_board_str |
end if |
SIS900_DoneWait: |
;*******Set Configuration Register depending on Card Revision******** |
lea edx, [ebp+SIS900_cfg] |
mov eax, SIS900_PESEL ; Configuration Register Bit |
mov bl, [SIS900_pci_revision]; card revision |
mov cl, SIS635A_900_REV ; Check card revision |
cmp bl, cl |
je SIS900_RevMatch |
mov cl, SIS900B_900_REV ; Check card revision |
cmp bl, cl |
je SIS900_RevMatch |
out dx, eax ; no revision match |
jmp SIS900_Reset_Complete |
SIS900_RevMatch: ; Revision match |
or eax, SIS900_RND_CNT ; Configuration Register Bit |
out dx, eax |
SIS900_Reset_Complete: |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
;*************************************************************************** |
; Function: sis_init_rxfilter |
; |
; Description: sets receive filter address to our MAC address |
; |
; Arguments: |
; |
; returns: |
;done+ |
;*************************************************************************** |
SIS900_init_rxfilter: |
;****Get Receive Filter Control Register ******** |
mov ebp, [io_addr] ; base address |
lea edx, [ebp+SIS900_rfcr] |
in eax, dx ; get register |
push eax |
;****disable packet filtering before setting filter******* |
mov eax, SIS900_RFEN;move receive filter enable flag |
not eax ;1s complement |
pop ebx ;and with our saved register |
and eax, ebx ;disable receiver |
push ebx ;save filter for another use |
out dx, eax ;set receive disabled |
;********load MAC addr to filter data register********* |
xor ecx, ecx |
SIS900_RXINT_Mac_Write: |
;high word of eax tells card which mac byte to write |
mov eax, ecx |
lea edx, [ebp+SIS900_rfcr] |
shl eax, 16 ; |
out dx, eax ; |
lea edx, [ebp+SIS900_rfdr] |
mov ax, word [node_addr+ecx*2]; Get Mac ID word |
out dx, ax ; Send Mac ID |
inc cl ; send next word |
cmp cl, 3 ; more to send? |
jne SIS900_RXINT_Mac_Write |
;********enable packet filitering ***** |
pop eax ;old register value |
lea edx, [ebp+SIS900_rfcr] |
or eax, SIS900_RFEN;enable filtering |
out dx, eax ;set register |
ret |
;*************************************************************************** |
;* |
;* Function: sis_init_txd |
;* |
;* Description: initializes the Tx descriptor |
;* |
;* Arguments: |
;* |
;* returns: |
;*done |
;*************************************************************************** |
SIS900_init_txd: |
;********** initialize TX descriptor ************** |
mov [txd], dword 0 ;put link to next descriptor in link field |
mov [txd+4], dword 0;clear status field |
mov [txd+8], dword txb - OS_BASE;save address to buffer ptr field |
;*************** load Transmit Descriptor Register *************** |
mov dx, [io_addr] ; base address |
add dx, SIS900_txdp ; TX Descriptor Pointer |
mov eax, txd - OS_BASE ; First Descriptor |
out dx, eax ; move the pointer |
ret |
;*************************************************************************** |
;* Function: sis_init_rxd |
;* |
;* Description: initializes the Rx descriptor ring |
;* |
;* Arguments: |
;* |
;* Returns: |
;*done |
;*************************************************************************** |
SIS900_init_rxd: |
xor ecx, ecx |
mov [cur_rx], cl ;Set cuurent rx discriptor to 0 |
;******** init RX descriptors ******** |
SIS900_init_rxd_Loop: |
mov eax, ecx ;current descriptor |
imul eax, 12 ; |
mov ebx, ecx ;determine next link descriptor |
inc ebx ; |
cmp ebx, NUM_RX_DESC ; |
jne SIS900_init_rxd_Loop_0 ; |
xor ebx, ebx ; |
SIS900_init_rxd_Loop_0: ; |
imul ebx, 12 ; |
add ebx, rxd - OS_BASE ; |
mov [rxd+eax], ebx ;save link to next descriptor |
mov [rxd+eax+4], dword RX_BUFF_SZ ;status bits init to buf size |
mov ebx, ecx ;find where the buf is located |
imul ebx, RX_BUFF_SZ ; |
add ebx, rxb - OS_BASE ; |
mov [rxd+eax+8], ebx ;save buffer pointer |
inc ecx ;next descriptor |
cmp ecx, NUM_RX_DESC ; |
jne SIS900_init_rxd_Loop ; |
;********* load Receive Descriptor Register with address of first |
; descriptor********* |
mov dx, [io_addr] |
add dx, SIS900_rxdp |
mov eax, rxd - OS_BASE |
out dx, eax |
ret |
;*************************************************************************** |
;* Function: sis900_set_tx_mode |
;* |
;* Description: |
;* sets the transmit mode to allow for full duplex |
;* |
;* |
;* Arguments: |
;* |
;* Returns: |
;* |
;* Comments: |
;* If you are having problems transmitting packet try changing the |
;* Max DMA Burst, Possible settings are as follows: |
;* 0x00000000 = 512 bytes |
;* 0x00100000 = 4 bytes |
;* 0x00200000 = 8 bytes |
;* 0x00300000 = 16 bytes |
;* 0x00400000 = 32 bytes |
;* 0x00500000 = 64 bytes |
;* 0x00600000 = 128 bytes |
;* 0x00700000 = 256 bytes |
;*************************************************************************** |
SIS900_set_tx_mode: |
mov ebp, [io_addr] |
lea edx, [ebp+SIS900_cr] |
in eax, dx ; Get current Command Register |
or eax, SIS900_TxENA;Enable Receive |
out dx, eax |
lea edx, [ebp+SIS900_txcfg]; Transmit config Register offset |
mov eax, SIS900_ATP ;allow automatic padding |
or eax, SIS900_HBI ;allow heartbeat ignore |
or eax, SIS900_CSI ;allow carrier sense ignore |
or eax, 0x00600000 ;Max DMA Burst |
or eax, 0x00000100 ;TX Fill Threshold |
or eax, 0x00000020 ;TX Drain Threshold |
out dx, eax |
ret |
;*************************************************************************** |
;* Function: sis900_set_rx_mode |
;* |
;* Description: |
;* sets the receive mode to accept all broadcast packets and packets |
;* with our MAC address, and reject all multicast packets. Also allows |
;* full-duplex |
;* |
;* Arguments: |
;* |
;* Returns: |
;* |
;* Comments: |
;* If you are having problems receiving packet try changing the |
;* Max DMA Burst, Possible settings are as follows: |
;* 0x00000000 = 512 bytes |
;* 0x00100000 = 4 bytes |
;* 0x00200000 = 8 bytes |
;* 0x00300000 = 16 bytes |
;* 0x00400000 = 32 bytes |
;* 0x00500000 = 64 bytes |
;* 0x00600000 = 128 bytes |
;* 0x00700000 = 256 bytes |
;*************************************************************************** |
SIS900_mc_filter: |
times 16 dw 0 |
SIS900_set_rx_mode: |
mov ebp, [io_addr] |
;**************update Multicast Hash Table in Receive Filter |
mov ebx, 0xffff |
xor cl, cl |
SIS900_set_rx_mode_Loop: |
mov eax, ecx |
shl eax, 1 |
mov [SIS900_mc_filter+eax], bx |
lea edx, [ebp+SIS900_rfcr] ; Receive Filter Control Reg offset |
mov eax, 4 ;determine table entry |
add al, cl |
shl eax, 16 |
out dx, eax ;tell card which entry to modify |
lea edx, [ebp+SIS900_rfdr] ; Receive Filter Control Reg offset |
mov eax, ebx ;entry value |
out dx, ax ;write value to table in card |
inc cl ;next entry |
cmp cl, [sis900_table_entries]; |
jl SIS900_set_rx_mode_Loop |
;*******Set Receive Filter Control Register************* |
lea edx, [ebp+SIS900_rfcr] ; Receive Filter Control Register offset |
mov eax, SIS900_RFAAB ;accecpt all broadcast packets |
or eax, SIS900_RFAAM ;accept all multicast packets |
or eax, SIS900_RFAAP ;Accept all packets |
or eax, SIS900_RFEN ;enable receiver filter |
out dx, eax |
;******Enable Receiver************ |
lea edx, [ebp+SIS900_cr]; Command Register offset |
in eax, dx ; Get current Command Register |
or eax, SIS900_RxENA;Enable Receive |
out dx, eax |
;*********Set |
lea edx, [ebp+SIS900_rxcfg] ; Receive Config Register offset |
mov eax, SIS900_ATX ;Accept Transmit Packets |
; (Req for full-duplex and PMD Loopback) |
or eax, 0x00600000 ;Max DMA Burst |
or eax, 0x00000002 ;RX Drain Threshold, 8X8 bytes or 64bytes |
out dx, eax ; |
ret |
;*************************************************************************** |
; * SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model |
; * @pci_dev: the sis900 pci device |
; * @net_dev: the net device to get address for |
; * |
; * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM |
; * is shared by |
; * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first |
; * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access |
; * by LAN, otherwise is not. After MAC address is read from EEPROM, send |
; * EEDONE signal to refuse EEPROM access by LAN. |
; * The EEPROM map of SiS962 or SiS963 is different to SiS900. |
; * The signature field in SiS962 or SiS963 spec is meaningless. |
; * MAC address is read into @net_dev->dev_addr. |
; *done |
;* |
;* Return 0 is EAX = failure |
;*Done+ |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Str_GetMac_Start db 'Attempting to get SIS900 Mac ID: ',13,10,0 |
SIS900_Debug_Str_GetMac_Failed db 'Access to EEprom Failed',13,10,0 |
SIS900_Debug_Str_GetMac_Address db 'Your Mac ID is: ',0 |
SIS900_Debug_Str_GetMac_Address2 db 'Your SIS96x Mac ID is: ',0 |
end if |
SIS960_get_mac_addr: |
mov ebp, [io_addr] |
;**********Send Request for eeprom access********************* |
lea edx, [ebp+SIS900_mear] ; Eeprom access register |
mov eax, SIS900_EEREQ ; Request access to eeprom |
out dx, eax ; Send request |
xor ebx, ebx ; |
;******Loop 4000 times and if access not granted error out***** |
SIS96X_Get_Mac_Wait: |
in eax, dx ;get eeprom status |
and eax, SIS900_EEGNT ;see if eeprom access granted flag is set |
jnz SIS900_Got_EEP_Access ;if it is, go access the eeprom |
inc ebx ;else keep waiting |
cmp ebx, 4000 ;have we tried 4000 times yet? |
jl SIS96X_Get_Mac_Wait ;if not ask again |
xor eax, eax ;return zero in eax indicating failure |
;*******Debug ********************** |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Str_GetMac_Failed |
call sys_msg_board_str |
end if |
jmp SIS960_get_mac_addr_done |
;**********EEprom access granted, read MAC from card************* |
SIS900_Got_EEP_Access: |
; zero based so 3-16 bit reads will take place |
mov ecx, 2 |
SIS96x_mac_read_loop: |
mov eax, SIS900_EEPROMMACAddr;Base Mac Address |
add eax, ecx ;Current Mac Byte Offset |
push ecx |
call sis900_read_eeprom ;try to read 16 bits |
pop ecx |
mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID varible |
dec ecx ;one less word to read |
jns SIS96x_mac_read_loop ;if more read more |
mov eax, 1 ;return non-zero indicating success |
;*******Debug Print MAC ID to debug window********************** |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Str_GetMac_Address2 |
call sys_msg_board_str |
mov edx, node_addr |
call Create_Mac_String |
end if |
;**********Tell EEPROM We are Done Accessing It********************* |
SIS960_get_mac_addr_done: |
lea edx, [ebp+SIS900_mear] ; Eeprom access register |
mov eax, SIS900_EEDONE ;tell eeprom we are done |
out dx, eax |
ret |
;*************************************************************************** |
;* sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model |
;* @pci_dev: the sis900 pci device |
;* @net_dev: the net device to get address for |
;* |
;* Older SiS900 and friends, use EEPROM to store MAC address. |
;* MAC address is read from read_eeprom() into @net_dev->dev_addr. |
;* done/untested |
;*************************************************************************** |
SIS900_get_mac_addr: |
;*******Debug ********************** |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Str_GetMac_Start |
call sys_msg_board_str |
end if |
;******** check to see if we have sane EEPROM ******* |
mov eax, SIS900_EEPROMSignature;Base Eeprom Signature |
call sis900_read_eeprom ;try to read 16 bits |
cmp ax, 0xffff |
je SIS900_Bad_Eeprom |
cmp ax, 0 |
je SIS900_Bad_Eeprom |
;**************Read MacID************** |
; zero based so 3-16 bit reads will take place |
mov ecx, 2 |
SIS900_mac_read_loop: |
mov eax, SIS900_EEPROMMACAddr;Base Mac Address |
add eax, ecx ;Current Mac Byte Offset |
push ecx |
call sis900_read_eeprom ;try to read 16 bits |
pop ecx |
mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID storage |
dec ecx ;one less word to read |
jns SIS900_mac_read_loop ;if more read more |
mov eax, 1 ;return non-zero indicating success |
;*******Debug Print MAC ID to debug window********************** |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Str_GetMac_Address |
call sys_msg_board_str |
mov edx, node_addr |
call Create_Mac_String |
end if |
ret |
SIS900_Bad_Eeprom: |
xor eax, eax |
;*******Debug ********************** |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Str_GetMac_Failed |
call sys_msg_board_str |
end if |
ret |
;*************************************************************************** |
;* Get_Mac_SIS635_900_REV: - Get MAC address for model 635 |
;* |
;* |
;*************************************************************************** |
Get_Mac_SIS635_900_REV: |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Str_GetMac_Start |
call sys_msg_board_str |
end if |
mov ebp, [io_addr] |
lea edx, [ebp+SIS900_rfcr] |
in eax, dx |
mov edi, eax; EDI=rfcrSave |
lea edx, [ebp+SIS900_cr] |
or eax, SIS900_RELOAD |
out dx, eax |
xor eax, eax |
out dx, eax |
; Disable packet filtering before setting filter |
lea edx, [ebp+SIS900_rfcr] |
mov eax, edi |
and edi, not SIS900_RFEN |
out dx, eax |
; Load MAC to filter data register |
xor ecx, ecx |
mov esi, node_addr |
.get_mac_loop: |
lea edx, [ebp+SIS900_rfcr] |
mov eax, ecx |
shl eax, SIS900_RFADDR_shift |
out dx, eax |
lea edx, [ebp+SIS900_rfdr] |
in eax, dx |
mov [esi], ax |
add esi, 2 |
inc ecx |
cmp ecx, 3 |
jne .get_mac_loop |
; Enable packet filtering |
;lea edx,[ebp+SIS900_rfcr] |
;mov eax,edi |
;or eax,SIS900_RFEN |
;out dx, eax |
;*******Debug Print MAC ID to debug window********************** |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Str_GetMac_Address |
call sys_msg_board_str |
mov edx, node_addr |
call Create_Mac_String |
end if |
ret |
;*************************************************************************** |
;* Function: sis900_read_eeprom |
;* |
;* Description: reads and returns a given location from EEPROM |
;* |
;* Arguments: eax - location: requested EEPROM location |
;* |
;* Returns: eax : contents of requested EEPROM location |
;* |
; Read Serial EEPROM through EEPROM Access Register, Note that location is |
; in word (16 bits) unit */ |
;done+ |
;*************************************************************************** |
sis900_read_eeprom: |
push esi |
push edx |
push ecx |
push ebx |
mov ebp, [io_addr] |
mov ebx, eax ;location of Mac byte to read |
or ebx, SIS900_EEread ; |
lea edx, [ebp+SIS900_mear]; Eeprom access register |
xor eax, eax ; start send |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
mov eax, SIS900_EECLK |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
;************ Shift the read command (9) bits out. ********* |
mov cl, 8 ; |
sis900_read_eeprom_Send: |
mov eax, 1 |
shl eax, cl |
and eax, ebx |
jz SIS900_Read_Eeprom_8 |
mov eax, 9 |
jmp SIS900_Read_Eeprom_9 |
SIS900_Read_Eeprom_8: |
mov eax, 8 |
SIS900_Read_Eeprom_9: |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
or eax, SIS900_EECLK |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
cmp cl, 0 |
je sis900_read_eeprom_Send_Done |
dec cl |
jmp sis900_read_eeprom_Send |
;********************* |
sis900_read_eeprom_Send_Done: |
mov eax, SIS900_EECS ; |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
;********** Read 16-bits of data in *************** |
mov cx, 16 ;16 bits to read |
sis900_read_eeprom_Send2: |
mov eax, SIS900_EECS |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
or eax, SIS900_EECLK |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
in eax, dx |
shl ebx, 1 |
and eax, SIS900_EEDO |
jz SIS900_Read_Eeprom_0 |
or ebx, 1 |
SIS900_Read_Eeprom_0: |
dec cx |
jnz sis900_read_eeprom_Send2 |
;************** Terminate the EEPROM access. ************** |
xor eax, eax |
out dx, eax |
call SIS900_Eeprom_Delay_1 |
mov eax, SIS900_EECLK |
out dx, eax |
mov eax, ebx |
and eax, 0x0000ffff ;return only 16 bits |
pop ebx |
pop ecx |
pop edx |
pop esi |
ret |
;*************************************************************************** |
; Function |
; SIS900_Eeprom_Delay_1 |
; Description |
; |
; |
; |
; |
;*************************************************************************** |
SIS900_Eeprom_Delay_1: |
push eax |
in eax, dx |
pop eax |
ret |
;*************************************************************************** |
; Function |
; SIS900_poll |
; Description |
; polls card to see if there is a packet waiting |
; |
; Currently only supports one descriptor per packet, if packet is fragmented |
; between multiple descriptors you will lose part of the packet |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Pull_Packet_good db 'Good Packet Waiting: ',13,10,0 |
SIS900_Debug_Pull_Bad_Packet_Status db 'Bad Packet Waiting: Status',13,10,0 |
SIS900_Debug_Pull_Bad_Packet_Size db 'Bad Packet Waiting: Size',13,10,0 |
end if |
SIS900_poll: |
;**************Get Status ************** |
xor eax, eax ;get RX_Status |
mov [eth_rx_data_len], ax |
mov al, [cur_rx] ;find current discriptor |
imul eax, 12 ; |
mov ecx, [rxd+eax+4] ; get receive status |
;**************Check Status ************** |
mov ebx, ecx ;move status |
;Check RX_Status to see if packet is waiting |
and ebx, 0x80000000 |
jnz SIS900_poll_IS_packet |
ret |
;**********There is a packet waiting check it for errors************** |
SIS900_poll_IS_packet: |
mov ebx, ecx ;move status |
and ebx, 0x67C0000 ;see if there are any errors |
jnz SIS900_Poll_Error_Status |
;**************Check size of packet************* |
and ecx, SIS900_DSIZE ;get packet size minus CRC |
cmp cx, SIS900_CRC_SIZE |
;make sure packet contains data |
jle SIS900_Poll_Error_Size |
;*******Copy Good Packet to receive buffer****** |
sub cx, SIS900_CRC_SIZE ;dont want crc |
mov word [eth_rx_data_len], cx ;save size of packet |
;**********Continue copying packet**************** |
push ecx |
; first copy dword-wise, divide size by 4 |
shr ecx, 2 |
mov esi, [rxd+eax+8] ; set source |
add esi, OS_BASE ; get linear address |
mov edi, Ether_buffer ; set destination |
cld ; clear direction |
rep movsd ; copy the dwords |
pop ecx |
and ecx, 3 ; |
rep movsb |
;********Debug, tell user we have a good packet************* |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Pull_Packet_good |
call sys_msg_board_str |
end if |
jmp SIS900_Poll_Cnt ; |
;*************Error occured let user know through debug window*********** |
SIS900_Poll_Error_Status: |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Pull_Bad_Packet_Status |
call sys_msg_board_str |
end if |
jmp SIS900_Poll_Cnt |
SIS900_Poll_Error_Size: |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Pull_Bad_Packet_Size |
call sys_msg_board_str |
end if |
;*************Increment to next available descriptor************** |
SIS900_Poll_Cnt: |
;Reset status, allow ethernet card access to descriptor |
mov ecx, RX_BUFF_SZ |
mov [rxd+eax+4], ecx ; |
inc [cur_rx] ;get next descriptor |
and [cur_rx], 3 ;only 4 descriptors 0-3 |
;******Enable Receiver************ |
mov ebp, [io_addr] ; Base Address |
lea edx, [ebp+SIS900_cr]; Command Register offset |
in eax, dx ; Get current Command Register |
or eax, SIS900_RxENA;Enable Receive |
out dx, eax |
ret |
;*************************************************************************** |
; Function |
; SIS900_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
; |
; only one transmit descriptor is used |
; |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Debug_Transmit_Packet db 'Transmitting Packet: ',13,10,0 |
SIS900_Debug_Transmit_Packet_Err db 'Transmitting Packet Error: ',13,10,0 |
end if |
str1 db 'Transmitting packet:',13,10,0 |
str2 db ' ',0 |
SIS900_transmit: |
mov ebp, [io_addr] ; Base Address |
;******** Stop the transmitter ******** |
lea edx, [ebp+SIS900_cr]; Command Register offset |
in eax, dx ; Get current Command Register |
or eax, SIS900_TxDIS; Disable Transmitter |
out dx, eax |
;*******load Transmit Descriptor Register ******* |
lea edx, [ebp+SIS900_txdp] |
mov eax, txd - OS_BASE |
out dx, eax |
;******* copy packet to descriptor******* |
push esi |
mov esi, edi ;copy destination addess |
mov edi, txb |
cld |
movsd |
movsw |
mov esi, node_addr;copy my mac address |
movsd |
movsw |
mov [edi], bx ;copy packet type |
add edi, 2 |
pop esi ;restore pointer to source of packet |
push ecx ;save packet size |
shr ecx, 2 ;divide by 4, size in bytes send in dwords |
rep movsd ;copy data to decriptor |
pop ecx ;restore packet size |
push ecx ;save packet size |
and ecx, 3 ;last three bytes if not a multiple of 4 |
rep movsb |
;**************set length tag************** |
pop ecx ;restore packet size |
add ecx, SIS900_ETH_HLEN;add header to length |
and ecx, SIS900_DSIZE; |
;**************pad to minimum packet size **************not needed |
;cmp ecx, SIS900_ETH_ZLEN |
;jge SIS900_transmit_Size_Ok |
;push ecx |
;mov ebx, SIS900_ETH_ZLEN |
;sub ebx, ecx |
;mov ecx, ebx |
;rep movsb |
;pop ecx |
SIS900_transmit_Size_Ok: |
mov [txd+4], dword 0x80000000 ;card owns descriptor |
or [txd+4], ecx ;set size of packet |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Transmit_Packet |
call sys_msg_board_str |
end if |
;***************restart the transmitter ******** |
lea edx, [ebp+SIS900_cr] |
in eax, dx ; Get current Command Register |
or eax, SIS900_TxENA; Enable Transmitter |
out dx, eax |
;****make sure packet transmitted successfully**** |
; mov esi,10 |
; call delay_ms |
mov eax, [txd+4] |
and eax, 0x6200000 |
jz SIS900_transmit_OK |
;**************Tell user there was an error through debug window |
if defined SIS900_DEBUG |
mov esi, SIS900_Debug_Transmit_Packet_Err |
call sys_msg_board_str |
end if |
SIS900_transmit_OK: |
;******** Disable interrupts by clearing the interrupt mask. ******** |
lea edx, [ebp+SIS900_imr] ; Interupt Mask Register |
xor eax, eax |
out dx, eax |
ret |
;*************************************************************************** |
;* Function: Create_Mac_String |
;* |
;* Description: Converts the 48 bit value to a string for display |
;* |
;* String Format: XX:XX:XX:XX:XX:XX |
;* |
;* Arguments: node_addr is location of 48 bit MAC ID |
;* |
;* Returns: Prints string to general debug window |
;* |
;* |
;done |
;*************************************************************************** |
if defined SIS900_DEBUG |
SIS900_Char_String db '0','1','2','3','4','5','6','7','8','9' |
db 'A','B','C','D','E','F' |
Mac_str_build: |
times 20 db 0 |
Create_Mac_String: |
pusha |
xor ecx, ecx |
Create_Mac_String_loop: |
mov al, byte [edx+ecx];[node_addr+ecx] |
push eax |
shr eax, 4 |
and eax, 0x0f |
mov bl, byte [SIS900_Char_String+eax] |
mov [Mac_str_build+ecx*3], bl |
pop eax |
and eax, 0x0f |
mov bl, byte [SIS900_Char_String+eax] |
mov [Mac_str_build+1+ecx*3], bl |
cmp ecx, 5 |
je Create_Mac_String_done |
mov bl, ':' |
mov [Mac_str_build+2+ecx*3], bl |
inc ecx |
jmp Create_Mac_String_loop |
Create_Mac_String_done: ;Insert CR and Zero Terminate |
mov [Mac_str_build+2+ecx*3], byte 13 |
mov [Mac_str_build+3+ecx*3], byte 10 |
mov [Mac_str_build+4+ecx*3], byte 0 |
mov esi, Mac_str_build |
call sys_msg_board_str ;Print String to message board |
popa |
ret |
end if |
;*************************************************************************** |
;* Set device to be a busmaster in case BIOS neglected to do so. |
;* Also adjust PCI latency timer to a reasonable value, 64. |
;*************************************************************************** |
SIS900_adjust_pci_device: |
;*******Get current setting************************ |
mov al, 2 ;read a word |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, 0x04 ;from command Register |
call pci_read_reg |
;******see if its already set as bus master******** |
mov bx, ax |
and bx, 5 |
cmp bx, 5 |
je SIS900_adjust_pci_device_Latency |
;******Make card a bus master******* |
mov cx, ax ;value to write |
mov bh, [pci_dev] |
mov al, 2 ;write a word |
or cx, 5 |
mov ah, [pci_bus] |
mov bl, 0x04 ;to command register |
call pci_write_reg |
;******Check latency setting*********** |
SIS900_adjust_pci_device_Latency: |
;*******Get current latency setting************************ |
mov al, 1 ;read a byte |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, 0x0D ;from Lantency Timer Register |
call pci_read_reg |
;******see if its aat least 64 clocks******** |
cmp ax, 64 |
jge SIS900_adjust_pci_device_Done |
;******Set latency to 32 clocks******* |
mov cx, 64 ;value to write |
mov bh, [pci_dev] |
mov al, 1 ;write a byte |
mov ah, [pci_bus] |
mov bl, 0x0D ;to Lantency Timer Register |
call pci_write_reg |
;******Check latency setting*********** |
SIS900_adjust_pci_device_Done: |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/ethernet.inc |
---|
1,506 → 1,524 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ETHERNET.INC ;; |
;; ;; |
;; Ethernet network layer for Menuet OS ;; |
;; ;; |
;; This file contains the following: ;; |
;; PCI bus scanning for valid devices ;; |
;; Table of supported ethernet drivers ;; |
;; Code to identify and activate a supported driver ;; |
;; ARP handler ;; |
;; Driver interface to the IP layer ;; |
;; Gateway support ;; |
;; ;; |
;; Individual driver files are included here ;; |
;; ;; |
;; The PCI bus scanning code was ported from the etherboot ;; |
;; 5.0.6 project. The copyright statement for that code is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2002 Mike Hibbett ;; |
;; mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************** |
; Interface |
; ethernet_driver called by stack_handler in stack.inc |
; eth_probe called by app_stack_handler in stack.inc |
; |
;******************************************************************** |
ETHER_IP equ 0x0008 ; Reversed from 0800 for intel |
ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel |
ETHER_RARP equ 0x3580 |
struc ETH_FRAME |
{ .DstMAC dp ? ;destination MAC-address [6 bytes] |
.SrcMAC dp ? ;source MAC-address [6 bytes] |
.Type dw ? ;type of the upper-layer protocol [2 bytes] |
.Data db ? ;data [46-1500 bytes] |
} |
virtual at Ether_buffer |
ETH_FRAME ETH_FRAME |
end virtual |
; Some useful information on data structures |
; Ethernet Packet - ARP Request example |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
; |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Dest H/W Address | |
; | ( 14 byte header ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | Source H/W Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Protocol - ARP 08 06 | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | H/W Type 00 01 | Protocol Type 08 00 | |
; | ( ARP Request packet ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | HLen 0x06 | PLen 0x04 | OpCode 00 01 | |
; | ( 0001 for request, 0002 for reply ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Source Hardware Address ( MAC Address ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | Source IP Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | Destination Hardware Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Destination IP Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; Include individual drivers source files at this point. |
; If you create a new driver, include it below. |
include "drivers/rtl8029.inc" |
include "drivers/i8255x.inc" |
include "drivers/rtl8139.inc" |
include "drivers/3c59x.inc" |
include "drivers/sis900.inc" |
include "drivers/pcnet32.inc" |
include "drivers/rtl8169.inc" |
include "drivers/forcedeth.inc" |
include "drivers/r6040.inc" |
; PCICards |
; ======== |
; PCI vendor and hardware types for hardware supported by the above drivers |
; If you add a driver, ensure you update this datastructure, otherwise the |
; card will not be probed. |
; Each driver is defined by 4 double words. These are |
; PCIVendorDevice probeFunction ResetFunction PollFunction transmitFunction |
; The last entry must be kept at all zeros, to indicate the end of the list |
; As a PCI driver may support more than one hardware implementation, there may |
; be several lines which refer to the same functions. |
; The first driver found on the PCI bus will be the one used. |
PCICARDS_ENTRY_SIZE equ 24 ; Size of each PCICARDS entry |
iglobal |
PCICards: |
dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit, 0 |
;dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x813810ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x12111113, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x13601500, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x13604033, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x13001186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x13401186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xab0613d1, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xa1171259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xa11e1259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xab0614ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xab0714ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x123411db, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x91301432, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x101202ac, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x0106018a, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x1211126c, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x81391743, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x8139021b, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x816810ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x816910ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x011616ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x43001186, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x816710ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 |
dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 |
dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 |
dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 |
dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 |
dd 0x006610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; nVidia Corporation nForce2 Ethernet Controller |
dd 0x01c310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x00D610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x008610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x008c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x00e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x00df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x005610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x005710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x003710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x003810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x026810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x026910de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x037210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x037310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x03e510de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x03e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x03ee10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x03ef10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x045010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x045110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x045210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x045310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x054c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x054d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x054e10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x054f10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x07dc10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x07dd10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x07de10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x07df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x076010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; MCP77 Ethernet Controller |
dd 0x076110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x076210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x076310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0ab010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0ab110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0ab210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0ab310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0d7d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x604017F3, r6040_probe, r6040_reset, r6040_poll, r6040_transmit, 0 |
rb PCICARDS_ENTRY_SIZE ; end of list marker, do not remove |
endg |
uglobal |
;Net-stack's interface's settings |
node_addr: db 0,0,0,0,0,0 |
gateway_ip: dd 0 |
dns_ip: dd 0 |
eth_rx_data_len: dw 0 |
eth_status: dd 0 |
io_addr: dd 0 |
hdrtype: db 0 |
vendor_device: dd 0 |
pci_data: dd 0 |
pci_dev: dd 0 |
pci_bus: dd 0 |
; These will hold pointers to the selected driver functions |
drvr_probe: dd 0 |
drvr_reset: dd 0 |
drvr_poll: dd 0 |
drvr_transmit: dd 0 |
drvr_cable: dd 0 |
endg |
iglobal |
broadcast_add: db 0xff,0xff,0xff,0xff,0xff,0xff |
subnet_mask: dd 0x00ffffff ; 255.255.255.0 |
endg |
include "arp.inc" ;arp-protocol functions |
include "pci.inc" ;PCI bus access functions |
;*************************************************************************** |
; Function |
; eth_tx |
; |
; Description |
; Looks at the NET1OUT_QUEUE for data to send. |
; Stores that destination IP in a location used by the tx routine |
; Looks up the MAC address in the ARP table; stores that where |
; the tx routine can get it |
; Get the length of the data. Store that where the tx routine wants it |
; Call tx |
; Places buffer on empty queue when the tx routine finished |
; |
;*************************************************************************** |
proc eth_tx stdcall uses ebx esi edi |
local MACAddress dp ? ;allocate 6 bytes in the stack |
; Look for a buffer to tx |
mov eax, NET1OUT_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit ; Exit if no buffer available |
push eax ;save buffer number |
; convert buffer pointer eax to the absolute address |
imul eax, IPBUFFSIZE |
add eax, IPbuffs |
; Extract the destination IP |
; find the destination IP in the ARP table, get MAC |
; store this MAC in 'MACAddress' |
mov ebx, eax ; Save buffer address |
mov edx, [ebx + 16] ; get destination address |
; If the destination address is 255.255.255.255, |
; set the MACAddress to all ones ( broadcast ) |
cld |
mov esi, broadcast_add |
lea edi, [MACAddress] |
movsd |
movsw |
cmp edx, 0xffffffff |
je .send ; If it is broadcast, just send |
lea eax, [MACAddress] ;cause this is local variable |
stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, edx, eax ;opcode,IP,MAC_ptr - Get the MAC address. |
cmp eax, ARP_VALID_MAPPING |
je .send |
; No valid entry. Has the request been sent, but timed out? |
cmp eax, ARP_RESPONSE_TIMEOUT |
je .freebuf |
.wait_response: ;we wait arp-response |
; Re-queue the packet, and exit |
pop ebx |
mov eax, NET1OUT_QUEUE |
call queue ; Get the buffer back |
jmp .exit |
.send: ;if ARP_VALID_MAPPING then send the packet |
lea edi, [MACAddress] ; Pointer to 48 bit destination address |
movzx ecx, word[ebx+2] ; Size of IP packet to send |
xchg ch, cl ; because mirror byte-order |
mov esi, ebx ; Pointer to packet data |
mov bx, ETHER_IP ; Type of packet |
push ebp |
call dword [drvr_transmit] ; Call the drivers transmit function |
pop ebp |
; OK, we have sent a packet, so increment the count |
inc dword [ip_tx_count] |
; And finally, return the buffer to the free queue |
.freebuf: |
pop eax |
call freeBuff |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; ether_IP_handler |
; |
; Description |
; Called when an IP ethernet packet is received on the ethernet |
; Header + Data is in Ether_buffer[] |
; We just need to get a buffer from the 'free' queue, and |
; store the packet in it, then insert the packet number into the |
; IPRX queue. |
; If no queue entry is available, the packet is silently discarded |
; All registers may be destroyed |
; |
;*************************************************************************** |
;uglobal |
; ether_IP_handler_cnt dd ? |
;endg |
ether_IP_handler: |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je eiph00x |
; convert buffer pointer eax to the absolute address |
push eax |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov edi, eax |
; get a pointer to the start of the DATA |
mov esi, ETH_FRAME.Data |
; Now store it all away |
mov ecx, IPBUFFSIZE / 4 ; Copy all of the available |
; data across - worse case |
cld |
rep movsd |
; inc [ether_IP_handler_cnt] |
; DEBUGF 1, "K : ether_IP_handler (%u)\n", [ether_IP_handler_cnt] |
; And finally, place the buffer in the IPRX queue |
pop ebx |
mov eax, IPIN_QUEUE |
call queue |
eiph00x: |
ret |
;*************************************************************************** |
; Function |
; eth_probe |
; Description |
; Searches for an ethernet card. If found, the card is enabled and |
; the ethernet -> IP link established |
; |
; This function scans the PCI bus looking for a supported device. |
; ISA bus is currently not supported. |
; |
; eax is 0 if no hardware found |
;*************************************************************************** |
eth_probe: |
; Find a card on the PCI bus, and get it's address |
call scan_bus ; Find the ethernet cards PIC address |
xor eax, eax |
cmp [io_addr], eax |
je ep_00x ; Return 0 in eax if no cards found |
call dword [drvr_probe] ; Call the drivers probe function |
mov eax, [io_addr] ; return a non zero value |
ep_00x: |
ret |
;*************************************************************************** |
; Function |
; ethernet_driver |
; |
; Description |
; The ethernet RX and TX handler |
; This is a kernel function, called by stack_handler |
; |
;*************************************************************************** |
ethernet_driver: |
; Do nothing if the driver is inactive |
cmp [ethernet_active], byte 0 |
je eth_exit |
call eth_rx |
call eth_tx |
eth_exit: |
ret |
;*************************************************************************** |
; Function |
; eth_rx |
; |
; Description |
; Polls the ethernet card for received data. Extracts if present |
; Depending on the Protocol within the packet: |
; ARP : Pass to ARP_handler. This may result in an ARP reply |
; being tx'ed |
; IP : Store in an IP buffer |
; |
;*************************************************************************** |
eth_rx: |
xor ax, ax |
mov [eth_rx_data_len], ax |
call dword [drvr_poll] ; Call the drivers poll function |
mov ax, [eth_rx_data_len] |
cmp ax, 0 |
je .exit |
; Check the protocol. Call appropriate handler |
mov ax, [ETH_FRAME.Type] ; The address of the protocol word |
cmp ax, ETHER_IP |
je .is_ip ; It's IP |
cmp ax, ETHER_ARP |
je .is_arp ; It is ARP |
DEBUGF 1,"K : eth_rx - dumped (%u)\n", ax |
inc [dumped_rx_count] |
jmp .exit ; If not IP or ARP, ignore |
.is_ip: |
; DEBUGF 1,"K : eth_rx - IP packet\n" |
inc dword [ip_rx_count] |
call ether_IP_handler |
jmp .exit |
.is_arp: |
; DEBUGF 1,"K : eth_rx - ARP packet\n" |
; At this point, the packet is still in the Ether_buffer |
call arp_handler |
.exit: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ETHERNET.INC ;; |
;; ;; |
;; Ethernet network layer for Menuet OS ;; |
;; ;; |
;; This file contains the following: ;; |
;; PCI bus scanning for valid devices ;; |
;; Table of supported ethernet drivers ;; |
;; Code to identify and activate a supported driver ;; |
;; ARP handler ;; |
;; Driver interface to the IP layer ;; |
;; Gateway support ;; |
;; ;; |
;; Individual driver files are included here ;; |
;; ;; |
;; The PCI bus scanning code was ported from the etherboot ;; |
;; 5.0.6 project. The copyright statement for that code is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2002 Mike Hibbett ;; |
;; mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************** |
; Interface |
; ethernet_driver called by stack_handler in stack.inc |
; eth_probe called by app_stack_handler in stack.inc |
; |
;******************************************************************** |
ETHER_IP equ 0x0008 ; Reversed from 0800 for intel |
ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel |
ETHER_RARP equ 0x3580 |
struc ETH_FRAME |
{ .DstMAC dp ? ;destination MAC-address [6 bytes] |
.SrcMAC dp ? ;source MAC-address [6 bytes] |
.Type dw ? ;type of the upper-layer protocol [2 bytes] |
.Data db ? ;data [46-1500 bytes] |
} |
virtual at Ether_buffer |
ETH_FRAME ETH_FRAME |
end virtual |
; Some useful information on data structures |
; Ethernet Packet - ARP Request example |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
; |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Dest H/W Address | |
; | ( 14 byte header ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | Source H/W Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Protocol - ARP 08 06 | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | H/W Type 00 01 | Protocol Type 08 00 | |
; | ( ARP Request packet ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | HLen 0x06 | PLen 0x04 | OpCode 00 01 | |
; | ( 0001 for request, 0002 for reply ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Source Hardware Address ( MAC Address ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | Source IP Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | Destination Hardware Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Destination IP Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; Include individual drivers source files at this point. |
; If you create a new driver, include it below. |
include "drivers/rtl8029.inc" |
include "drivers/i8255x.inc" |
include "drivers/rtl8139.inc" |
include "drivers/3c59x.inc" |
include "drivers/sis900.inc" |
include "drivers/pcnet32.inc" |
include "drivers/rtl8169.inc" |
include "drivers/forcedeth.inc" |
include "drivers/r6040.inc" |
; PCICards |
; ======== |
; PCI vendor and hardware types for hardware supported by the above drivers |
; If you add a driver, ensure you update this datastructure, otherwise the |
; card will not be probed. |
; Each driver is defined by 4 double words. These are |
; PCIVendorDevice probeFunction ResetFunction PollFunction transmitFunction |
; The last entry must be kept at all zeros, to indicate the end of the list |
; As a PCI driver may support more than one hardware implementation, there may |
; be several lines which refer to the same functions. |
; The first driver found on the PCI bus will be the one used. |
PCICARDS_ENTRY_SIZE equ 24 ; Size of each PCICARDS entry |
iglobal |
PCICards: |
dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit, 0 |
;dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x813810ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x12111113, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x13601500, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x13604033, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x13001186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x13401186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xab0613d1, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xa1171259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xa11e1259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xab0614ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0xab0714ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x123411db, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x91301432, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x101202ac, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x0106018a, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x1211126c, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x81391743, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
;dd 0x8139021b, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x816810ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x816910ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x011616ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x43001186, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x816710ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 |
dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 |
dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 |
dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 |
dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 |
dd 0x006610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; nVidia Corporation nForce2 Ethernet Controller |
dd 0x01c310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x00D610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x008610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x008c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x00e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x00df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x005610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x005710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x003710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x003810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x026810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x026910de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x037210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x037310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x03e510de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x03e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x03ee10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x03ef10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x045010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x045110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x045210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x045310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x054c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x054d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x054e10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x054f10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x07dc10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x07dd10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x07de10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x07df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x076010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; MCP77 Ethernet Controller |
dd 0x076110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x076210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x076310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0ab010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0ab110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0ab210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0ab310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x0d7d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested |
dd 0x604017F3, r6040_probe, r6040_reset, r6040_poll, r6040_transmit, 0 |
rb PCICARDS_ENTRY_SIZE ; end of list marker, do not remove |
endg |
uglobal |
;Net-stack's interface's settings |
node_addr: |
db 0,0,0,0,0,0 |
gateway_ip: |
dd 0 |
dns_ip: |
dd 0 |
eth_rx_data_len: |
dw 0 |
eth_status: |
dd 0 |
io_addr: |
dd 0 |
hdrtype: |
db 0 |
vendor_device: |
dd 0 |
pci_data: |
dd 0 |
pci_dev: |
dd 0 |
pci_bus: |
dd 0 |
; These will hold pointers to the selected driver functions |
drvr_probe: |
dd 0 |
drvr_reset: |
dd 0 |
drvr_poll: |
dd 0 |
drvr_transmit: |
dd 0 |
drvr_cable: |
dd 0 |
endg |
iglobal |
broadcast_add: |
db 0xff,0xff,0xff,0xff,0xff,0xff |
subnet_mask: |
dd 0x00ffffff ; 255.255.255.0 |
endg |
include "arp.inc" ;arp-protocol functions |
include "pci.inc" ;PCI bus access functions |
;*************************************************************************** |
; Function |
; eth_tx |
; |
; Description |
; Looks at the NET1OUT_QUEUE for data to send. |
; Stores that destination IP in a location used by the tx routine |
; Looks up the MAC address in the ARP table; stores that where |
; the tx routine can get it |
; Get the length of the data. Store that where the tx routine wants it |
; Call tx |
; Places buffer on empty queue when the tx routine finished |
; |
;*************************************************************************** |
proc eth_tx stdcall uses ebx esi edi |
local MACAddress dp ? ;allocate 6 bytes in the stack |
; Look for a buffer to tx |
mov eax, NET1OUT_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit ; Exit if no buffer available |
push eax;save buffer number |
; convert buffer pointer eax to the absolute address |
imul eax, IPBUFFSIZE |
add eax, IPbuffs |
; Extract the destination IP |
; find the destination IP in the ARP table, get MAC |
; store this MAC in 'MACAddress' |
mov ebx, eax ; Save buffer address |
mov edx, [ebx + 16] ; get destination address |
; If the destination address is 255.255.255.255, |
; set the MACAddress to all ones ( broadcast ) |
cld |
mov esi, broadcast_add |
lea edi, [MACAddress] |
movsd |
movsw |
cmp edx, 0xffffffff |
je .send ; If it is broadcast, just send |
lea eax, [MACAddress];cause this is local variable |
stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, edx, eax;opcode,IP,MAC_ptr - Get the MAC address. |
cmp eax, ARP_VALID_MAPPING |
je .send |
; No valid entry. Has the request been sent, but timed out? |
cmp eax, ARP_RESPONSE_TIMEOUT |
je .freebuf |
.wait_response: ;we wait arp-response |
; Re-queue the packet, and exit |
pop ebx |
mov eax, NET1OUT_QUEUE |
call queue ; Get the buffer back |
jmp .exit |
.send: ;if ARP_VALID_MAPPING then send the packet |
lea edi, [MACAddress] ; Pointer to 48 bit destination address |
movzx ecx, word[ebx+2] ; Size of IP packet to send |
xchg ch, cl ; because mirror byte-order |
mov esi, ebx ; Pointer to packet data |
mov bx, ETHER_IP ; Type of packet |
push ebp |
call dword [drvr_transmit]; Call the drivers transmit function |
pop ebp |
; OK, we have sent a packet, so increment the count |
inc dword [ip_tx_count] |
; And finally, return the buffer to the free queue |
.freebuf: |
pop eax |
call freeBuff |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; ether_IP_handler |
; |
; Description |
; Called when an IP ethernet packet is received on the ethernet |
; Header + Data is in Ether_buffer[] |
; We just need to get a buffer from the 'free' queue, and |
; store the packet in it, then insert the packet number into the |
; IPRX queue. |
; If no queue entry is available, the packet is silently discarded |
; All registers may be destroyed |
; |
;*************************************************************************** |
;uglobal |
; ether_IP_handler_cnt dd ? |
;endg |
ether_IP_handler: |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je eiph00x |
; convert buffer pointer eax to the absolute address |
push eax |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov edi, eax |
; get a pointer to the start of the DATA |
mov esi, ETH_FRAME.Data |
; Now store it all away |
mov ecx, IPBUFFSIZE / 4 ; Copy all of the available |
; data across - worse case |
cld |
rep movsd |
; inc [ether_IP_handler_cnt] |
; DEBUGF 1, "K : ether_IP_handler (%u)\n", [ether_IP_handler_cnt] |
; And finally, place the buffer in the IPRX queue |
pop ebx |
mov eax, IPIN_QUEUE |
call queue |
eiph00x: |
ret |
;*************************************************************************** |
; Function |
; eth_probe |
; Description |
; Searches for an ethernet card. If found, the card is enabled and |
; the ethernet -> IP link established |
; |
; This function scans the PCI bus looking for a supported device. |
; ISA bus is currently not supported. |
; |
; eax is 0 if no hardware found |
;*************************************************************************** |
eth_probe: |
; Find a card on the PCI bus, and get it's address |
call scan_bus ; Find the ethernet cards PIC address |
xor eax, eax |
cmp [io_addr], eax |
je ep_00x ; Return 0 in eax if no cards found |
call dword [drvr_probe] ; Call the drivers probe function |
mov eax, [io_addr] ; return a non zero value |
ep_00x: |
ret |
;*************************************************************************** |
; Function |
; ethernet_driver |
; |
; Description |
; The ethernet RX and TX handler |
; This is a kernel function, called by stack_handler |
; |
;*************************************************************************** |
ethernet_driver: |
; Do nothing if the driver is inactive |
cmp [ethernet_active], byte 0 |
je eth_exit |
call eth_rx |
call eth_tx |
eth_exit: |
ret |
;*************************************************************************** |
; Function |
; eth_rx |
; |
; Description |
; Polls the ethernet card for received data. Extracts if present |
; Depending on the Protocol within the packet: |
; ARP : Pass to ARP_handler. This may result in an ARP reply |
; being tx'ed |
; IP : Store in an IP buffer |
; |
;*************************************************************************** |
eth_rx: |
xor ax, ax |
mov [eth_rx_data_len], ax |
call dword [drvr_poll] ; Call the drivers poll function |
mov ax, [eth_rx_data_len] |
cmp ax, 0 |
je .exit |
; Check the protocol. Call appropriate handler |
mov ax, [ETH_FRAME.Type]; The address of the protocol word |
cmp ax, ETHER_IP |
je .is_ip ; It's IP |
cmp ax, ETHER_ARP |
je .is_arp ; It is ARP |
DEBUGF 1,"K : eth_rx - dumped (%u)\n", ax |
inc [dumped_rx_count] |
jmp .exit ; If not IP or ARP, ignore |
.is_ip: |
; DEBUGF 1,"K : eth_rx - IP packet\n" |
inc dword [ip_rx_count] |
call ether_IP_handler |
jmp .exit |
.is_arp: |
; DEBUGF 1,"K : eth_rx - ARP packet\n" |
; At this point, the packet is still in the Ether_buffer |
call arp_handler |
.exit: |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/eth_drv/pci.inc |
---|
1,351 → 1,351 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;*************************************************************************** |
; |
; PCI CODE FOLLOWS |
; |
; the following functions provide access to the PCI interface. |
; These functions are used by scan_bus, and also some ethernet drivers |
; |
;*************************************************************************** |
; PCI Bus defines |
PCI_HEADER_TYPE equ 0x0e ;8 bit |
PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit |
PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits |
PCI_BASE_ADDRESS_SPACE_IO equ 0x01 |
PCI_VENDOR_ID equ 0x00 ;16 bit |
PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC |
;*************************************************************************** |
; Function |
; config_cmd |
; |
; Description |
; creates a command dword for use with the PCI bus |
; bus # in ebx |
; devfn in ecx |
; where in edx |
; |
; command dword returned in eax |
; Only eax destroyed |
;*************************************************************************** |
config_cmd: |
push ecx |
mov eax, ebx |
shl eax, 16 |
or eax, 0x80000000 |
shl ecx, 8 |
or eax, ecx |
pop ecx |
or eax, edx |
and eax, 0xFFFFFFFC |
ret |
;*************************************************************************** |
; Function |
; pcibios_read_config_byte |
; |
; Description |
; reads a byte from the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; byte returned in al ( rest of eax zero ) |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_read_config_byte: |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
xor eax, eax |
and dx, 0x03 |
add dx, 0xCFC |
; and dx, 0xFFC |
in al, dx |
ret |
;*************************************************************************** |
; Function |
; pcibios_read_config_word |
; |
; Description |
; reads a word from the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; word returned in ax ( rest of eax zero ) |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_read_config_word: |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
xor eax, eax |
and dx, 0x02 |
add dx, 0xCFC |
; and dx, 0xFFC |
in ax, dx |
ret |
;*************************************************************************** |
; Function |
; pcibios_read_config_dword |
; |
; Description |
; reads a dword from the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; dword returned in eax |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_read_config_dword: |
push edx |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
xor eax, eax |
mov dx, 0xCFC |
in eax, dx |
pop edx |
ret |
;*************************************************************************** |
; Function |
; pcibios_write_config_byte |
; |
; Description |
; write a byte in al to the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_write_config_byte: |
push ax |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
pop ax |
and dx, 0x03 |
add dx, 0xCFC |
out dx, al |
ret |
;*************************************************************************** |
; Function |
; pcibios_write_config_word |
; |
; Description |
; write a word in ax to the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_write_config_word: |
push ax |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
pop ax |
and dx, 0x02 |
add dx, 0xCFC |
out dx, ax |
ret |
;*************************************************************************** |
; Function |
; delay_us |
; |
; Description |
; delays for 30 to 60 us |
; |
; I would prefer this routine to be able to delay for |
; a selectable number of microseconds, but this works for now. |
; |
; If you know a better way to do 2us delay, pleae tell me! |
;*************************************************************************** |
delay_us: |
push eax |
push ecx |
mov ecx,2 |
in al,0x61 |
and al,0x10 |
mov ah,al |
cld |
dcnt1: |
in al,0x61 |
and al,0x10 |
cmp al,ah |
jz dcnt1 |
mov ah,al |
loop dcnt1 |
pop ecx |
pop eax |
ret |
;*************************************************************************** |
; Function |
; scan_bus |
; |
; Description |
; Scans the PCI bus for a supported device |
; If a supported device is found, the drvr_ variables are initialised |
; to that drivers functions ( as defined in the PCICards table) |
; |
; io_addr holds card I/O space. 32 bit, but only LS 16 bits valid |
; pci_data holds the PCI vendor + device code |
; pci_dev holds PCI bus dev # |
; pci_bus holds PCI bus # |
; |
; io_addr will be zero if no card found |
; |
;*************************************************************************** |
scan_bus: |
xor eax, eax |
mov [hdrtype], al |
mov [pci_data], eax |
xor ebx, ebx ; ebx = bus# 0 .. 255 |
sb_bus_loop: |
xor ecx, ecx ; ecx = devfn# 0 .. 254 ( not 255? ) |
sb_devf_loop: |
mov eax, ecx |
and eax, 0x07 |
cmp eax, 0 |
jne sb_001 |
mov edx, PCI_HEADER_TYPE |
call pcibios_read_config_byte |
mov [hdrtype], al |
jmp sb_002 |
sb_001: |
mov al, [hdrtype] |
and al, 0x80 |
cmp al, 0x80 |
jne sb_inc_devf |
sb_002: |
mov edx, PCI_VENDOR_ID |
call pcibios_read_config_dword |
mov [vendor_device], eax |
cmp eax, 0xffffffff |
je sb_empty |
cmp eax, 0 |
jne sb_check_vendor |
sb_empty: |
mov [hdrtype], byte 0 |
jmp sb_inc_devf |
sb_check_vendor: |
; iterate though PCICards until end or match found |
mov esi, PCICards |
sb_check: |
cmp [esi], dword 0 |
je sb_inc_devf ; Quit if at last entry |
cmp eax, [esi] |
je sb_got_card |
add esi, PCICARDS_ENTRY_SIZE |
jmp sb_check |
sb_got_card: |
; indicate that we have found the card |
mov [pci_data], eax |
mov [pci_dev], ecx |
mov [pci_bus], ebx |
; Define the driver functions |
push eax |
mov eax, [esi+4] |
mov [drvr_probe], eax |
mov eax, [esi+8] |
mov [drvr_reset], eax |
mov eax, [esi+12] |
mov [drvr_poll], eax |
mov eax, [esi+16] |
mov [drvr_transmit], eax |
mov eax, [esi+20] |
mov [drvr_cable], eax |
pop eax |
mov edx, PCI_BASE_ADDRESS_0 |
sb_reg_check: |
call pcibios_read_config_dword |
mov [io_addr], eax |
and eax, PCI_BASE_ADDRESS_IO_MASK |
cmp eax, 0 |
je sb_inc_reg |
mov eax, [io_addr] |
and eax, PCI_BASE_ADDRESS_SPACE_IO |
cmp eax, 0 |
je sb_inc_reg |
mov eax, [io_addr] |
and eax, PCI_BASE_ADDRESS_IO_MASK |
mov [io_addr], eax |
sb_exit1: |
ret |
sb_inc_reg: |
add edx, 4 |
cmp edx, PCI_BASE_ADDRESS_5 |
jbe sb_reg_check |
sb_inc_devf: |
inc ecx |
cmp ecx, 255 |
jb sb_devf_loop |
inc ebx |
cmp ebx, 256 |
jb sb_bus_loop |
; We get here if we didn't find our card |
; set io_addr to 0 as an indication |
xor eax, eax |
mov [io_addr], eax |
sb_exit2: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;*************************************************************************** |
; |
; PCI CODE FOLLOWS |
; |
; the following functions provide access to the PCI interface. |
; These functions are used by scan_bus, and also some ethernet drivers |
; |
;*************************************************************************** |
; PCI Bus defines |
PCI_HEADER_TYPE equ 0x0e ;8 bit |
PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit |
PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits |
PCI_BASE_ADDRESS_SPACE_IO equ 0x01 |
PCI_VENDOR_ID equ 0x00 ;16 bit |
PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC |
;*************************************************************************** |
; Function |
; config_cmd |
; |
; Description |
; creates a command dword for use with the PCI bus |
; bus # in ebx |
; devfn in ecx |
; where in edx |
; |
; command dword returned in eax |
; Only eax destroyed |
;*************************************************************************** |
config_cmd: |
push ecx |
mov eax, ebx |
shl eax, 16 |
or eax, 0x80000000 |
shl ecx, 8 |
or eax, ecx |
pop ecx |
or eax, edx |
and eax, 0xFFFFFFFC |
ret |
;*************************************************************************** |
; Function |
; pcibios_read_config_byte |
; |
; Description |
; reads a byte from the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; byte returned in al ( rest of eax zero ) |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_read_config_byte: |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
xor eax, eax |
and dx, 0x03 |
add dx, 0xCFC |
; and dx, 0xFFC |
in al, dx |
ret |
;*************************************************************************** |
; Function |
; pcibios_read_config_word |
; |
; Description |
; reads a word from the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; word returned in ax ( rest of eax zero ) |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_read_config_word: |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
xor eax, eax |
and dx, 0x02 |
add dx, 0xCFC |
; and dx, 0xFFC |
in ax, dx |
ret |
;*************************************************************************** |
; Function |
; pcibios_read_config_dword |
; |
; Description |
; reads a dword from the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; dword returned in eax |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_read_config_dword: |
push edx |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
xor eax, eax |
mov dx, 0xCFC |
in eax, dx |
pop edx |
ret |
;*************************************************************************** |
; Function |
; pcibios_write_config_byte |
; |
; Description |
; write a byte in al to the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_write_config_byte: |
push ax |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
pop ax |
and dx, 0x03 |
add dx, 0xCFC |
out dx, al |
ret |
;*************************************************************************** |
; Function |
; pcibios_write_config_word |
; |
; Description |
; write a word in ax to the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_write_config_word: |
push ax |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
pop ax |
and dx, 0x02 |
add dx, 0xCFC |
out dx, ax |
ret |
;*************************************************************************** |
; Function |
; delay_us |
; |
; Description |
; delays for 30 to 60 us |
; |
; I would prefer this routine to be able to delay for |
; a selectable number of microseconds, but this works for now. |
; |
; If you know a better way to do 2us delay, pleae tell me! |
;*************************************************************************** |
delay_us: |
push eax |
push ecx |
mov ecx, 2 |
in al, 0x61 |
and al, 0x10 |
mov ah, al |
cld |
dcnt1: |
in al, 0x61 |
and al, 0x10 |
cmp al, ah |
jz dcnt1 |
mov ah, al |
loop dcnt1 |
pop ecx |
pop eax |
ret |
;*************************************************************************** |
; Function |
; scan_bus |
; |
; Description |
; Scans the PCI bus for a supported device |
; If a supported device is found, the drvr_ variables are initialised |
; to that drivers functions ( as defined in the PCICards table) |
; |
; io_addr holds card I/O space. 32 bit, but only LS 16 bits valid |
; pci_data holds the PCI vendor + device code |
; pci_dev holds PCI bus dev # |
; pci_bus holds PCI bus # |
; |
; io_addr will be zero if no card found |
; |
;*************************************************************************** |
scan_bus: |
xor eax, eax |
mov [hdrtype], al |
mov [pci_data], eax |
xor ebx, ebx ; ebx = bus# 0 .. 255 |
sb_bus_loop: |
xor ecx, ecx ; ecx = devfn# 0 .. 254 ( not 255? ) |
sb_devf_loop: |
mov eax, ecx |
and eax, 0x07 |
cmp eax, 0 |
jne sb_001 |
mov edx, PCI_HEADER_TYPE |
call pcibios_read_config_byte |
mov [hdrtype], al |
jmp sb_002 |
sb_001: |
mov al, [hdrtype] |
and al, 0x80 |
cmp al, 0x80 |
jne sb_inc_devf |
sb_002: |
mov edx, PCI_VENDOR_ID |
call pcibios_read_config_dword |
mov [vendor_device], eax |
cmp eax, 0xffffffff |
je sb_empty |
cmp eax, 0 |
jne sb_check_vendor |
sb_empty: |
mov [hdrtype], byte 0 |
jmp sb_inc_devf |
sb_check_vendor: |
; iterate though PCICards until end or match found |
mov esi, PCICards |
sb_check: |
cmp [esi], dword 0 |
je sb_inc_devf ; Quit if at last entry |
cmp eax, [esi] |
je sb_got_card |
add esi, PCICARDS_ENTRY_SIZE |
jmp sb_check |
sb_got_card: |
; indicate that we have found the card |
mov [pci_data], eax |
mov [pci_dev], ecx |
mov [pci_bus], ebx |
; Define the driver functions |
push eax |
mov eax, [esi+4] |
mov [drvr_probe], eax |
mov eax, [esi+8] |
mov [drvr_reset], eax |
mov eax, [esi+12] |
mov [drvr_poll], eax |
mov eax, [esi+16] |
mov [drvr_transmit], eax |
mov eax, [esi+20] |
mov [drvr_cable], eax |
pop eax |
mov edx, PCI_BASE_ADDRESS_0 |
sb_reg_check: |
call pcibios_read_config_dword |
mov [io_addr], eax |
and eax, PCI_BASE_ADDRESS_IO_MASK |
cmp eax, 0 |
je sb_inc_reg |
mov eax, [io_addr] |
and eax, PCI_BASE_ADDRESS_SPACE_IO |
cmp eax, 0 |
je sb_inc_reg |
mov eax, [io_addr] |
and eax, PCI_BASE_ADDRESS_IO_MASK |
mov [io_addr], eax |
sb_exit1: |
ret |
sb_inc_reg: |
add edx, 4 |
cmp edx, PCI_BASE_ADDRESS_5 |
jbe sb_reg_check |
sb_inc_devf: |
inc ecx |
cmp ecx, 255 |
jb sb_devf_loop |
inc ebx |
cmp ebx, 256 |
jb sb_bus_loop |
; We get here if we didn't find our card |
; set io_addr to 0 as an indication |
xor eax, eax |
mov [io_addr], eax |
sb_exit2: |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/icmp.inc |
---|
1,193 → 1,193 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ICMP.INC ;; |
;; ;; |
;; Internet Control Message Protocol ( RFC 792 ) ;; |
;; ;; |
;; Last revision: 11.11.2006 ;; |
;; ;; |
;; This file contains the following: ;; |
;; icmp_rx - processes ICMP-packets received by the IP layer ;; |
;; ;; |
;; Changes history: ;; |
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; |
;; 11.11.2006 - [Johnny_B] and [smb] ;; |
;; ;; |
;; Current status: ;; |
;; This implemetation of ICMP proto supports message of ECHO type. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
struc ICMP_PACKET |
{ .Type db ? ;+00 |
.Code db ? ;+01 |
.Checksum dw ? ;+02 |
.Identifier dw ? ;+04 |
.SequenceNumber dw ? ;+06 |
.Data db ? ;+08 |
} |
virtual at 0 |
ICMP_PACKET ICMP_PACKET |
end virtual |
; Example: |
; ECHO message format |
; |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Type | Code | Checksum | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Identifier | Sequence Number | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Data ... |
; +-+-+-+-+- |
; |
; |
; ICMP types & codes, RFC 792 and FreeBSD's ICMP sources |
; |
ICMP_ECHOREPLY equ 0 ; echo reply message |
ICMP_UNREACH equ 3 |
ICMP_UNREACH_NET equ 0 ; bad net |
ICMP_UNREACH_HOST equ 1 ; bad host |
ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol |
ICMP_UNREACH_PORT equ 3 ; bad port |
ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop |
ICMP_UNREACH_SRCFAIL equ 5 ; src route failed |
ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net |
ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host |
ICMP_UNREACH_ISOLATED equ 8 ; src host isolated |
ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access |
ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto |
ICMP_UNREACH_TOSNET equ 11 ; bad tos for net |
ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host |
ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib |
ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio. |
ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff |
ICMP_SOURCEQUENCH equ 4 ; packet lost, slow down |
ICMP_REDIRECT equ 5 ; shorter route, codes: |
ICMP_REDIRECT_NET equ 0 ; for network |
ICMP_REDIRECT_HOST equ 1 ; for host |
ICMP_REDIRECT_TOSNET equ 2 ; for tos and net |
ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host |
ICMP_ALTHOSTADDR equ 6 ; alternate host address |
ICMP_ECHO equ 8 ; echo service |
ICMP_ROUTERADVERT equ 9 ; router advertisement |
ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement |
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing |
ICMP_ROUTERSOLICIT equ 10 ; router solicitation |
ICMP_TIMXCEED equ 11 ; time exceeded, code: |
ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit |
ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass |
ICMP_PARAMPROB equ 12 ; ip header bad |
ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr |
ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent |
ICMP_PARAMPROB_LENGTH equ 2 ; bad length |
ICMP_TSTAMP equ 13 ; timestamp request |
ICMP_TSTAMPREPLY equ 14 ; timestamp reply |
ICMP_IREQ equ 15 ; information request |
ICMP_IREQREPLY equ 16 ; information reply |
ICMP_MASKREQ equ 17 ; address mask request |
ICMP_MASKREPLY equ 18 ; address mask reply |
ICMP_TRACEROUTE equ 30 ; traceroute |
ICMP_DATACONVERR equ 31 ; data conversion error |
ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect |
ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you |
ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here |
ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req |
ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply |
ICMP_SKIP equ 39 ; SKIP |
ICMP_PHOTURIS equ 40 ; Photuris |
ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index |
ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed |
ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed |
;*************************************************************************** |
; Function |
; icmp_rx [by Johnny_B] |
; |
; Description |
; ICMP protocol handler |
; This is a kernel function, called by ip_rx |
; |
; IN: |
; buffer_number - # of IP-buffer. This buffer must be reused or marked as empty afterwards |
; IPPacketBase - IP_PACKET base address |
; IPHeaderLength - Header length of IP_PACKET |
; |
; OUT: |
; EAX=not defined |
; |
; All used registers will be saved |
; |
;*************************************************************************** |
proc icmp_rx stdcall uses ebx esi edi,\ |
buffer_number:DWORD,IPPacketBase:DWORD,IPHeaderLength:DWORD |
mov esi,[IPPacketBase] ;esi=IP_PACKET base address |
mov edi, esi |
add edi,[IPHeaderLength] ;edi=ICMP_PACKET base address |
cmp byte[edi + ICMP_PACKET.Type], ICMP_ECHO ; Is this an echo request? discard if not |
jz .icmp_echo |
mov eax, [buffer_number] |
call freeBuff |
jmp .exit |
.icmp_echo: |
; swap the source and destination addresses |
mov ecx, [esi + IP_PACKET.DestinationAddress] |
mov ebx, [esi + IP_PACKET.SourceAddress] |
mov [esi + IP_PACKET.DestinationAddress], ebx |
mov [esi + IP_PACKET.SourceAddress], ecx |
; recalculate the IP header checksum |
mov eax,[IPHeaderLength] |
stdcall checksum_jb,esi,eax ;buf_ptr,buf_size |
mov byte[esi + IP_PACKET.HeaderChecksum], ah |
mov byte[esi + IP_PACKET.HeaderChecksum + 1], al ; ?? correct byte order? |
mov byte[edi + ICMP_PACKET.Type], ICMP_ECHOREPLY ; change the request to a response |
mov word[edi + ICMP_PACKET.Checksum], 0 ; clear ICMP checksum prior to re-calc |
; Calculate the length of the ICMP data ( IP payload) |
xor eax, eax |
mov ah, byte[esi + IP_PACKET.TotalLength] |
mov al, byte[esi + IP_PACKET.TotalLength + 1] |
sub ax, word[IPHeaderLength] ;ax=ICMP-packet length |
stdcall checksum_jb,edi,eax ;buf_ptr,buf_size |
mov byte[edi + ICMP_PACKET.Checksum], ah |
mov byte[edi + ICMP_PACKET.Checksum + 1], al |
; Queue packet for transmission |
mov ebx, [buffer_number] |
mov eax, NET1OUT_QUEUE |
call queue |
.exit: |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ICMP.INC ;; |
;; ;; |
;; Internet Control Message Protocol ( RFC 792 ) ;; |
;; ;; |
;; Last revision: 11.11.2006 ;; |
;; ;; |
;; This file contains the following: ;; |
;; icmp_rx - processes ICMP-packets received by the IP layer ;; |
;; ;; |
;; Changes history: ;; |
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; |
;; 11.11.2006 - [Johnny_B] and [smb] ;; |
;; ;; |
;; Current status: ;; |
;; This implemetation of ICMP proto supports message of ECHO type. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
struc ICMP_PACKET |
{ .Type db ? ;+00 |
.Code db ? ;+01 |
.Checksum dw ? ;+02 |
.Identifier dw ? ;+04 |
.SequenceNumber dw ? ;+06 |
.Data db ? ;+08 |
} |
virtual at 0 |
ICMP_PACKET ICMP_PACKET |
end virtual |
; Example: |
; ECHO message format |
; |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Type | Code | Checksum | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Identifier | Sequence Number | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Data ... |
; +-+-+-+-+- |
; |
; |
; ICMP types & codes, RFC 792 and FreeBSD's ICMP sources |
; |
ICMP_ECHOREPLY equ 0 ; echo reply message |
ICMP_UNREACH equ 3 |
ICMP_UNREACH_NET equ 0 ; bad net |
ICMP_UNREACH_HOST equ 1 ; bad host |
ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol |
ICMP_UNREACH_PORT equ 3 ; bad port |
ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop |
ICMP_UNREACH_SRCFAIL equ 5 ; src route failed |
ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net |
ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host |
ICMP_UNREACH_ISOLATED equ 8 ; src host isolated |
ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access |
ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto |
ICMP_UNREACH_TOSNET equ 11 ; bad tos for net |
ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host |
ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib |
ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio. |
ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff |
ICMP_SOURCEQUENCH equ 4 ; packet lost, slow down |
ICMP_REDIRECT equ 5 ; shorter route, codes: |
ICMP_REDIRECT_NET equ 0 ; for network |
ICMP_REDIRECT_HOST equ 1 ; for host |
ICMP_REDIRECT_TOSNET equ 2 ; for tos and net |
ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host |
ICMP_ALTHOSTADDR equ 6 ; alternate host address |
ICMP_ECHO equ 8 ; echo service |
ICMP_ROUTERADVERT equ 9 ; router advertisement |
ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement |
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing |
ICMP_ROUTERSOLICIT equ 10 ; router solicitation |
ICMP_TIMXCEED equ 11 ; time exceeded, code: |
ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit |
ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass |
ICMP_PARAMPROB equ 12 ; ip header bad |
ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr |
ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent |
ICMP_PARAMPROB_LENGTH equ 2 ; bad length |
ICMP_TSTAMP equ 13 ; timestamp request |
ICMP_TSTAMPREPLY equ 14 ; timestamp reply |
ICMP_IREQ equ 15 ; information request |
ICMP_IREQREPLY equ 16 ; information reply |
ICMP_MASKREQ equ 17 ; address mask request |
ICMP_MASKREPLY equ 18 ; address mask reply |
ICMP_TRACEROUTE equ 30 ; traceroute |
ICMP_DATACONVERR equ 31 ; data conversion error |
ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect |
ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you |
ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here |
ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req |
ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply |
ICMP_SKIP equ 39 ; SKIP |
ICMP_PHOTURIS equ 40 ; Photuris |
ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index |
ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed |
ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed |
;*************************************************************************** |
; Function |
; icmp_rx [by Johnny_B] |
; |
; Description |
; ICMP protocol handler |
; This is a kernel function, called by ip_rx |
; |
; IN: |
; buffer_number - # of IP-buffer. This buffer must be reused or marked as empty afterwards |
; IPPacketBase - IP_PACKET base address |
; IPHeaderLength - Header length of IP_PACKET |
; |
; OUT: |
; EAX=not defined |
; |
; All used registers will be saved |
; |
;*************************************************************************** |
proc icmp_rx stdcall uses ebx esi edi,\ |
buffer_number:DWORD,IPPacketBase:DWORD,IPHeaderLength:DWORD |
mov esi, [IPPacketBase];esi=IP_PACKET base address |
mov edi, esi |
add edi, [IPHeaderLength];edi=ICMP_PACKET base address |
cmp byte[edi + ICMP_PACKET.Type], ICMP_ECHO; Is this an echo request? discard if not |
jz .icmp_echo |
mov eax, [buffer_number] |
call freeBuff |
jmp .exit |
.icmp_echo: |
; swap the source and destination addresses |
mov ecx, [esi + IP_PACKET.DestinationAddress] |
mov ebx, [esi + IP_PACKET.SourceAddress] |
mov [esi + IP_PACKET.DestinationAddress], ebx |
mov [esi + IP_PACKET.SourceAddress], ecx |
; recalculate the IP header checksum |
mov eax, [IPHeaderLength] |
stdcall checksum_jb, esi, eax;buf_ptr,buf_size |
mov byte[esi + IP_PACKET.HeaderChecksum], ah |
mov byte[esi + IP_PACKET.HeaderChecksum + 1], al ; ?? correct byte order? |
mov byte[edi + ICMP_PACKET.Type], ICMP_ECHOREPLY; change the request to a response |
mov word[edi + ICMP_PACKET.Checksum], 0; clear ICMP checksum prior to re-calc |
; Calculate the length of the ICMP data ( IP payload) |
xor eax, eax |
mov ah, byte[esi + IP_PACKET.TotalLength] |
mov al, byte[esi + IP_PACKET.TotalLength + 1] |
sub ax, word[IPHeaderLength];ax=ICMP-packet length |
stdcall checksum_jb, edi, eax;buf_ptr,buf_size |
mov byte[edi + ICMP_PACKET.Checksum], ah |
mov byte[edi + ICMP_PACKET.Checksum + 1], al |
; Queue packet for transmission |
mov ebx, [buffer_number] |
mov eax, NET1OUT_QUEUE |
call queue |
.exit: |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/ip.inc |
---|
1,244 → 1,244 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; IP.INC ;; |
;; ;; |
;; IP Processes for Menuet OS TCP/IP stack ;; |
;; ;; |
;; Version 0.3 29 August 2002 ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; IP underlying protocols numbers |
PROTOCOL_ICMP equ 1 |
PROTOCOL_TCP equ 6 |
PROTOCOL_UDP equ 17 |
struc IP_PACKET |
{ .VersionAndIHL db ? ;+00 - Version[0-3 bits] and IHL(header length)[4-7 bits] |
.TypeOfService db ? ;+01 |
.TotalLength dw ? ;+02 |
.Identification dw ? ;+04 |
.FlagsAndFragmentOffset dw ? ;+06 - Flags[0-2] and FragmentOffset[3-15] |
.TimeToLive db ? ;+08 |
.Protocol db ? ;+09 |
.HeaderChecksum dw ? ;+10 |
.SourceAddress dd ? ;+12 |
.DestinationAddress dd ? ;+16 |
.DataOrOptional dd ? ;+20 |
} |
virtual at 0 |
IP_PACKET IP_PACKET |
end virtual |
;******************************************************************* |
; Interface |
; |
; ip_rx processes all packets received by the network layer |
; It calls the appropriate protocol handler |
; |
; |
; |
;******************************************************************* |
; |
; IP Packet after reception - Normal IP packet format |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 |
; |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;0 |Version| IHL |Type of Service| Total Length | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;4 | Identification |Flags| Fragment Offset | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;8 | Time to Live | Protocol | Header Checksum | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;12 | Source Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;16 | Destination Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;20 | Data | |
; +-+-+-.......... -+ |
; |
; |
; [smb] attention! according to RFC 791 IP packet may have 'options' sections, |
; so we can't simply think, that data have offset 20. We must calculate offset from |
; IHL field |
; |
macro GET_IHL reg, header_addr |
{ |
movzx reg, byte [header_addr] |
; we need 4-7 bits, so.... |
and reg, 0x0000000F |
; IHL keeps number of octets, so we need to << 2 'reg' |
shl reg, 2 |
} |
include "tcp.inc" |
include "udp.inc" |
include "icmp.inc" |
;*************************************************************************** |
; Function |
; ip_rx |
; |
; Description |
; This is a kernel function, called by stack_handler |
; Processes all IP-packets received by the network layer |
; It calls the appropriate protocol handler |
; |
;*************************************************************************** |
proc ip_rx stdcall |
local buffer_number dd ? |
; Look for a buffer to tx |
mov eax, IPIN_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit ; Exit if no buffer available |
mov [buffer_number], eax ;save buffer number |
; convert buffer pointer eax to the absolute address |
imul eax, IPBUFFSIZE |
add eax, IPbuffs |
mov ebx, eax ; ebx=pointer to IP_PACKET |
; DEBUGF 1, "K : ip_rx - proto: %u\n", [ebx + IP_PACKET.Protocol]:1 |
; Validate the IP checksum |
mov dx, word[ebx + IP_PACKET.HeaderChecksum] |
xchg dh,dl ; Get the checksum in intel format |
mov [ebx + IP_PACKET.HeaderChecksum], 0 ; clear checksum field - need to when |
; recalculating checksum |
; this needs two data pointers and two size #. |
; 2nd pointer can be of length 0 |
GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx |
stdcall checksum_jb, ebx, ecx ;buf_ptr, buf_size |
cmp dx, ax |
; DEBUGF 1, "K : ip_rx - checksums: %x - %x\n", dx, ax |
jnz .dump.1 ;if CHECKSUM isn't valid then dump packet |
mov edx, ebx ; EDX (IP-BUFFER POINTER) WILL BE USED FOR *_rx HANDLERS BELOW!!! |
; DEBUGF 1, "K : ip_rx - dest: %x - %x\n", [ebx + IP_PACKET.DestinationAddress], [stack_ip] |
; Validate the IP address, if it isn't broadcast |
mov eax, [stack_ip] |
cmp dword[ebx + IP_PACKET.DestinationAddress], eax |
je @f |
; If the IP address is 255.255.255.255, accept it |
; - it is a broadcast packet, which we need for dhcp |
mov eax, [ebx + IP_PACKET.DestinationAddress] |
cmp eax, 0xffffffff |
je @f |
mov ecx, [stack_ip] |
and eax, [subnet_mask] |
and ecx, [subnet_mask] |
cmp eax, ecx |
jne .dump.2 |
mov eax, [ebx + IP_PACKET.DestinationAddress] |
or eax, [subnet_mask] |
cmp eax, 0xffffffff |
jne .dump.2 |
@@: |
mov al, [ebx + IP_PACKET.VersionAndIHL] |
and al, 0x0f ;get IHL(header length) |
cmp al, 0x05 ;if IHL!= 5*4(20 bytes) |
; DEBUGF 1, "K : ip_rx - ihl: %x - 05\n", al |
jnz .dump.3 ;then dump it |
; DEBUGF 1, "K : ip_rx - ttl: %x - 00\n", [ebx + IP_PACKET.TimeToLive]:2 |
cmp [ebx + IP_PACKET.TimeToLive], 0 |
je .dump.4 ;if TTL==0 then dump it |
mov ax, [ebx + IP_PACKET.FlagsAndFragmentOffset] |
and ax, 0xFFBF ;get flags |
; DEBUGF 1, "K : ip_rx - flags: %x - 0000\n", ax |
cmp ax, 0 ;if some flags was set then we dump this packet |
jnz .dump.5 ;the flags should be used for fragmented packets |
; Check the protocol, and call the appropriate handler |
; Each handler will re-use or free the queue buffer as appropriate |
mov al, [ebx + IP_PACKET.Protocol] |
cmp al , PROTOCOL_TCP |
jne .not_tcp |
; DEBUGF 1,"K : ip_rx - TCP packet\n" |
mov eax, dword[buffer_number] |
call tcp_rx |
jmp .exit |
.not_tcp: |
cmp al, PROTOCOL_UDP |
jne .not_udp |
; DEBUGF 1,"K : ip_rx - UDP packet\n" |
mov eax, dword[buffer_number] |
call udp_rx |
jmp .exit |
.not_udp: |
cmp al, PROTOCOL_ICMP |
jne .dump.6 ;protocol ain't supported |
; DEBUGF 1,"K : ip_rx - ICMP packet\n" |
;GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx |
mov eax, dword[buffer_number] |
stdcall icmp_rx,eax,ebx,ecx ;buffer_number,IPPacketBase,IPHeaderLength |
jmp .exit |
.dump.1: |
DEBUGF 1, "K : ip_rx - dumped (checksum: 0x%x-0x%x)\n", dx, ax |
jmp .dump.x |
.dump.2: |
DEBUGF 1, "K : ip_rx - dumped (ip: %u.%u.%u.%u)\n", [ebx + IP_PACKET.DestinationAddress + 0]:1, [ebx + IP_PACKET.DestinationAddress + 1]:1, [ebx + IP_PACKET.DestinationAddress + 2]:1, [ebx + IP_PACKET.DestinationAddress + 3]:1 |
jmp .dump.x |
.dump.3: |
DEBUGF 1, "K : ip_rx - dumped (ihl: %u)\n", al |
jmp .dump.x |
.dump.4: |
DEBUGF 1, "K : ip_rx - dumped (ttl: %u)\n", [ebx + IP_PACKET.TimeToLive] |
jmp .dump.x |
.dump.5: |
DEBUGF 1, "K : ip_rx - dumped (flags: 0x%x)\n", ax |
jmp .dump.x |
.dump.6: |
DEBUGF 1, "K : ip_rx - dumped (proto: %u)\n", [ebx + IP_PACKET.Protocol]:1 |
.dump.x: |
inc dword[dumped_rx_count] |
mov eax, [buffer_number] |
call freeBuff |
.exit: |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; IP.INC ;; |
;; ;; |
;; IP Processes for Menuet OS TCP/IP stack ;; |
;; ;; |
;; Version 0.3 29 August 2002 ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; IP underlying protocols numbers |
PROTOCOL_ICMP equ 1 |
PROTOCOL_TCP equ 6 |
PROTOCOL_UDP equ 17 |
struc IP_PACKET |
{ .VersionAndIHL db ? ;+00 - Version[0-3 bits] and IHL(header length)[4-7 bits] |
.TypeOfService db ? ;+01 |
.TotalLength dw ? ;+02 |
.Identification dw ? ;+04 |
.FlagsAndFragmentOffset dw ? ;+06 - Flags[0-2] and FragmentOffset[3-15] |
.TimeToLive db ? ;+08 |
.Protocol db ? ;+09 |
.HeaderChecksum dw ? ;+10 |
.SourceAddress dd ? ;+12 |
.DestinationAddress dd ? ;+16 |
.DataOrOptional dd ? ;+20 |
} |
virtual at 0 |
IP_PACKET IP_PACKET |
end virtual |
;******************************************************************* |
; Interface |
; |
; ip_rx processes all packets received by the network layer |
; It calls the appropriate protocol handler |
; |
; |
; |
;******************************************************************* |
; |
; IP Packet after reception - Normal IP packet format |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 |
; |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;0 |Version| IHL |Type of Service| Total Length | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;4 | Identification |Flags| Fragment Offset | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;8 | Time to Live | Protocol | Header Checksum | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;12 | Source Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;16 | Destination Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;20 | Data | |
; +-+-+-.......... -+ |
; |
; |
; [smb] attention! according to RFC 791 IP packet may have 'options' sections, |
; so we can't simply think, that data have offset 20. We must calculate offset from |
; IHL field |
; |
macro GET_IHL reg, header_addr |
{ |
movzx reg, byte [header_addr] |
; we need 4-7 bits, so.... |
and reg, 0x0000000F |
; IHL keeps number of octets, so we need to << 2 'reg' |
shl reg, 2 |
} |
include "tcp.inc" |
include "udp.inc" |
include "icmp.inc" |
;*************************************************************************** |
; Function |
; ip_rx |
; |
; Description |
; This is a kernel function, called by stack_handler |
; Processes all IP-packets received by the network layer |
; It calls the appropriate protocol handler |
; |
;*************************************************************************** |
proc ip_rx stdcall |
local buffer_number dd ? |
; Look for a buffer to tx |
mov eax, IPIN_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit ; Exit if no buffer available |
mov [buffer_number], eax;save buffer number |
; convert buffer pointer eax to the absolute address |
imul eax, IPBUFFSIZE |
add eax, IPbuffs |
mov ebx, eax; ebx=pointer to IP_PACKET |
; DEBUGF 1, "K : ip_rx - proto: %u\n", [ebx + IP_PACKET.Protocol]:1 |
; Validate the IP checksum |
mov dx, word[ebx + IP_PACKET.HeaderChecksum] |
xchg dh, dl ; Get the checksum in intel format |
mov [ebx + IP_PACKET.HeaderChecksum], 0; clear checksum field - need to when |
; recalculating checksum |
; this needs two data pointers and two size #. |
; 2nd pointer can be of length 0 |
GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx |
stdcall checksum_jb, ebx, ecx;buf_ptr, buf_size |
cmp dx, ax |
; DEBUGF 1, "K : ip_rx - checksums: %x - %x\n", dx, ax |
jnz .dump.1;if CHECKSUM isn't valid then dump packet |
mov edx, ebx; EDX (IP-BUFFER POINTER) WILL BE USED FOR *_rx HANDLERS BELOW!!! |
; DEBUGF 1, "K : ip_rx - dest: %x - %x\n", [ebx + IP_PACKET.DestinationAddress], [stack_ip] |
; Validate the IP address, if it isn't broadcast |
mov eax, [stack_ip] |
cmp dword[ebx + IP_PACKET.DestinationAddress], eax |
je @f |
; If the IP address is 255.255.255.255, accept it |
; - it is a broadcast packet, which we need for dhcp |
mov eax, [ebx + IP_PACKET.DestinationAddress] |
cmp eax, 0xffffffff |
je @f |
mov ecx, [stack_ip] |
and eax, [subnet_mask] |
and ecx, [subnet_mask] |
cmp eax, ecx |
jne .dump.2 |
mov eax, [ebx + IP_PACKET.DestinationAddress] |
or eax, [subnet_mask] |
cmp eax, 0xffffffff |
jne .dump.2 |
@@: |
mov al, [ebx + IP_PACKET.VersionAndIHL] |
and al, 0x0f;get IHL(header length) |
cmp al, 0x05;if IHL!= 5*4(20 bytes) |
; DEBUGF 1, "K : ip_rx - ihl: %x - 05\n", al |
jnz .dump.3 ;then dump it |
; DEBUGF 1, "K : ip_rx - ttl: %x - 00\n", [ebx + IP_PACKET.TimeToLive]:2 |
cmp [ebx + IP_PACKET.TimeToLive], 0 |
je .dump.4 ;if TTL==0 then dump it |
mov ax, [ebx + IP_PACKET.FlagsAndFragmentOffset] |
and ax, 0xFFBF;get flags |
; DEBUGF 1, "K : ip_rx - flags: %x - 0000\n", ax |
cmp ax, 0 ;if some flags was set then we dump this packet |
jnz .dump.5 ;the flags should be used for fragmented packets |
; Check the protocol, and call the appropriate handler |
; Each handler will re-use or free the queue buffer as appropriate |
mov al, [ebx + IP_PACKET.Protocol] |
cmp al , PROTOCOL_TCP |
jne .not_tcp |
; DEBUGF 1,"K : ip_rx - TCP packet\n" |
mov eax, dword[buffer_number] |
call tcp_rx |
jmp .exit |
.not_tcp: |
cmp al, PROTOCOL_UDP |
jne .not_udp |
; DEBUGF 1,"K : ip_rx - UDP packet\n" |
mov eax, dword[buffer_number] |
call udp_rx |
jmp .exit |
.not_udp: |
cmp al, PROTOCOL_ICMP |
jne .dump.6 ;protocol ain't supported |
; DEBUGF 1,"K : ip_rx - ICMP packet\n" |
;GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx |
mov eax, dword[buffer_number] |
stdcall icmp_rx, eax, ebx, ecx;buffer_number,IPPacketBase,IPHeaderLength |
jmp .exit |
.dump.1: |
DEBUGF 1, "K : ip_rx - dumped (checksum: 0x%x-0x%x)\n", dx, ax |
jmp .dump.x |
.dump.2: |
DEBUGF 1, "K : ip_rx - dumped (ip: %u.%u.%u.%u)\n", [ebx + IP_PACKET.DestinationAddress + 0]:1, [ebx + IP_PACKET.DestinationAddress + 1]:1, [ebx + IP_PACKET.DestinationAddress + 2]:1, [ebx + IP_PACKET.DestinationAddress + 3]:1 |
jmp .dump.x |
.dump.3: |
DEBUGF 1, "K : ip_rx - dumped (ihl: %u)\n", al |
jmp .dump.x |
.dump.4: |
DEBUGF 1, "K : ip_rx - dumped (ttl: %u)\n", [ebx + IP_PACKET.TimeToLive] |
jmp .dump.x |
.dump.5: |
DEBUGF 1, "K : ip_rx - dumped (flags: 0x%x)\n", ax |
jmp .dump.x |
.dump.6: |
DEBUGF 1, "K : ip_rx - dumped (proto: %u)\n", [ebx + IP_PACKET.Protocol]:1 |
.dump.x: |
inc dword[dumped_rx_count] |
mov eax, [buffer_number] |
call freeBuff |
.exit: |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/queue.inc |
---|
1,229 → 1,229 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; QUEUE.INC ;; |
;; ;; |
;; Buffer queue management for Menuet OS TCP/IP Stack ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************* |
; Interface |
; |
; queueInit Configures the queues to empty |
; dequeue Removes a buffer pointer from a queue |
; queue Inserts a buffer pointer into a queue |
; freeBuff Adds the buffer pointer to the list of free buffers |
; queueSize Returns the number of entries in a queue |
; |
; The various defines for queue names can be found in stack.inc |
; |
;******************************************************************* |
;*************************************************************************** |
; Function |
; freeBuff |
; |
; Description |
; Adds a buffer number to the beginning of the free list. |
; buffer number in eax ( ms word zeroed ) |
; all other registers preserved |
; This always works, so no error returned |
;*************************************************************************** |
;uglobal |
; freeBuff_cnt dd ? |
;endg |
freeBuff: |
; inc [freeBuff_cnt] |
; DEBUGF 1, "K : freeBuff (%u)\n", [freeBuff_cnt] |
push ebx |
push ecx |
mov ebx, queues + EMPTY_QUEUE * 2 |
cli ; Ensure that another process does not interfer |
mov cx, [ebx] |
mov [ebx], ax |
mov [queueList + eax * 2], cx |
sti |
pop ecx |
pop ebx |
ret |
;*************************************************************************** |
; Function |
; queueSize |
; |
; Description |
; Counts the number of entries in a queue |
; queue number in ebx ( ms word zeroed ) |
; Queue size returned in eax |
; This always works, so no error returned |
;*************************************************************************** |
queueSize: |
xor eax, eax |
shl ebx, 1 |
add ebx, queues |
movzx ecx, word [ebx] |
cmp cx, NO_BUFFER |
je qs_exit |
qs_001: |
inc eax |
shl ecx, 1 |
add ecx, queueList |
movzx ecx, word [ecx] |
cmp cx, NO_BUFFER |
je qs_exit |
jmp qs_001 |
qs_exit: |
ret |
;*************************************************************************** |
; Function |
; queue |
; |
; Description |
; Adds a buffer number to the *end* of a queue |
; This is quite quick because these queues will be short |
; queue number in eax ( ms word zeroed ) |
; buffer number in ebx ( ms word zeroed ) |
; all other registers preserved |
; This always works, so no error returned |
;*************************************************************************** |
;uglobal |
; queue_cnt dd ? |
;endg |
queue: |
; inc [queue_cnt] |
; DEBUGF 1, "K : queue (%u)\n", [queue_cnt] |
push ebx |
shl ebx, 1 |
add ebx, queueList ; eax now holds address of queue entry |
mov [ebx], word NO_BUFFER ; This buffer will be the last |
cli |
shl eax, 1 |
add eax, queues ; eax now holds address of queue |
movzx ebx, word [eax] |
cmp bx, NO_BUFFER |
jne qu_001 |
pop ebx |
; The list is empty, so add this to the head |
mov [eax], bx |
jmp qu_exit |
qu_001: |
; Find the last entry |
shl ebx, 1 |
add ebx, queueList |
mov eax, ebx |
movzx ebx, word [ebx] |
cmp bx, NO_BUFFER |
jne qu_001 |
mov ebx, eax |
pop eax |
mov [ebx], ax |
qu_exit: |
sti |
ret |
;*************************************************************************** |
; Function |
; dequeue |
; |
; Description |
; removes a buffer number from the head of a queue |
; This is fast, as it unlinks the first entry in the list |
; queue number in eax ( ms word zeroed ) |
; buffer number returned in eax ( ms word zeroed ) |
; all other registers preserved |
; |
;*************************************************************************** |
;uglobal |
; dequeue_cnt dd ? |
;endg |
dequeue: |
push ebx |
shl eax, 1 |
add eax, queues ; eax now holds address of queue |
mov ebx, eax |
cli |
movzx eax, word [eax] |
cmp ax, NO_BUFFER |
je dq_exit |
; inc [dequeue_cnt] |
; DEBUGF 1, "K : dequeue (%u)\n", [dequeue_cnt] |
push eax |
shl eax, 1 |
add eax, queueList ; eax now holds address of queue entry |
mov ax, [eax] |
mov [ebx], ax |
pop eax |
dq_exit: |
sti |
pop ebx |
ret |
;*************************************************************************** |
; Function |
; queueInit |
; |
; Description |
; Initialises the queues to empty, and creates the free queue |
; list. |
; |
;*************************************************************************** |
queueInit: |
mov esi, queues |
mov ecx, NUMQUEUES |
mov ax, NO_BUFFER |
qi001: |
mov [esi], ax |
inc esi |
inc esi |
loop qi001 |
mov esi, queues + ( 2 * EMPTY_QUEUE ) |
; Initialise empty queue list |
xor ax, ax |
mov [esi], ax |
mov ecx, NUMQUEUEENTRIES - 1 |
mov esi, queueList |
qi002: |
inc ax |
mov [esi], ax |
inc esi |
inc esi |
loop qi002 |
mov ax, NO_BUFFER |
mov [esi], ax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; QUEUE.INC ;; |
;; ;; |
;; Buffer queue management for Menuet OS TCP/IP Stack ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************* |
; Interface |
; |
; queueInit Configures the queues to empty |
; dequeue Removes a buffer pointer from a queue |
; queue Inserts a buffer pointer into a queue |
; freeBuff Adds the buffer pointer to the list of free buffers |
; queueSize Returns the number of entries in a queue |
; |
; The various defines for queue names can be found in stack.inc |
; |
;******************************************************************* |
;*************************************************************************** |
; Function |
; freeBuff |
; |
; Description |
; Adds a buffer number to the beginning of the free list. |
; buffer number in eax ( ms word zeroed ) |
; all other registers preserved |
; This always works, so no error returned |
;*************************************************************************** |
;uglobal |
; freeBuff_cnt dd ? |
;endg |
freeBuff: |
; inc [freeBuff_cnt] |
; DEBUGF 1, "K : freeBuff (%u)\n", [freeBuff_cnt] |
push ebx |
push ecx |
mov ebx, queues + EMPTY_QUEUE * 2 |
cli ; Ensure that another process does not interfer |
mov cx, [ebx] |
mov [ebx], ax |
mov [queueList + eax * 2], cx |
sti |
pop ecx |
pop ebx |
ret |
;*************************************************************************** |
; Function |
; queueSize |
; |
; Description |
; Counts the number of entries in a queue |
; queue number in ebx ( ms word zeroed ) |
; Queue size returned in eax |
; This always works, so no error returned |
;*************************************************************************** |
queueSize: |
xor eax, eax |
shl ebx, 1 |
add ebx, queues |
movzx ecx, word [ebx] |
cmp cx, NO_BUFFER |
je qs_exit |
qs_001: |
inc eax |
shl ecx, 1 |
add ecx, queueList |
movzx ecx, word [ecx] |
cmp cx, NO_BUFFER |
je qs_exit |
jmp qs_001 |
qs_exit: |
ret |
;*************************************************************************** |
; Function |
; queue |
; |
; Description |
; Adds a buffer number to the *end* of a queue |
; This is quite quick because these queues will be short |
; queue number in eax ( ms word zeroed ) |
; buffer number in ebx ( ms word zeroed ) |
; all other registers preserved |
; This always works, so no error returned |
;*************************************************************************** |
;uglobal |
; queue_cnt dd ? |
;endg |
queue: |
; inc [queue_cnt] |
; DEBUGF 1, "K : queue (%u)\n", [queue_cnt] |
push ebx |
shl ebx, 1 |
add ebx, queueList ; eax now holds address of queue entry |
mov [ebx], word NO_BUFFER; This buffer will be the last |
cli |
shl eax, 1 |
add eax, queues ; eax now holds address of queue |
movzx ebx, word [eax] |
cmp bx, NO_BUFFER |
jne qu_001 |
pop ebx |
; The list is empty, so add this to the head |
mov [eax], bx |
jmp qu_exit |
qu_001: |
; Find the last entry |
shl ebx, 1 |
add ebx, queueList |
mov eax, ebx |
movzx ebx, word [ebx] |
cmp bx, NO_BUFFER |
jne qu_001 |
mov ebx, eax |
pop eax |
mov [ebx], ax |
qu_exit: |
sti |
ret |
;*************************************************************************** |
; Function |
; dequeue |
; |
; Description |
; removes a buffer number from the head of a queue |
; This is fast, as it unlinks the first entry in the list |
; queue number in eax ( ms word zeroed ) |
; buffer number returned in eax ( ms word zeroed ) |
; all other registers preserved |
; |
;*************************************************************************** |
;uglobal |
; dequeue_cnt dd ? |
;endg |
dequeue: |
push ebx |
shl eax, 1 |
add eax, queues ; eax now holds address of queue |
mov ebx, eax |
cli |
movzx eax, word [eax] |
cmp ax, NO_BUFFER |
je dq_exit |
; inc [dequeue_cnt] |
; DEBUGF 1, "K : dequeue (%u)\n", [dequeue_cnt] |
push eax |
shl eax, 1 |
add eax, queueList ; eax now holds address of queue entry |
mov ax, [eax] |
mov [ebx], ax |
pop eax |
dq_exit: |
sti |
pop ebx |
ret |
;*************************************************************************** |
; Function |
; queueInit |
; |
; Description |
; Initialises the queues to empty, and creates the free queue |
; list. |
; |
;*************************************************************************** |
queueInit: |
mov esi, queues |
mov ecx, NUMQUEUES |
mov ax, NO_BUFFER |
qi001: |
mov [esi], ax |
inc esi |
inc esi |
loop qi001 |
mov esi, queues + ( 2 * EMPTY_QUEUE ) |
; Initialise empty queue list |
xor ax, ax |
mov [esi], ax |
mov ecx, NUMQUEUEENTRIES - 1 |
mov esi, queueList |
qi002: |
inc ax |
mov [esi], ax |
inc esi |
inc esi |
loop qi002 |
mov ax, NO_BUFFER |
mov [esi], ax |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/socket.inc |
---|
1,1124 → 1,1129 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; SOCKET.INC ;; |
;; ;; |
;; Sockets constants, structures and functions ;; |
;; ;; |
;; This file contains the following: ;; |
;; is_localport_unused ;; |
;; get_free_socket ;; |
;; socket_open ;; |
;; socket_open_tcp ;; |
;; socket_close ;; |
;; socket_close_tcp ;; |
;; socket_poll ;; |
;; socket_status ;; |
;; socket_read ;; |
;; socket_write ;; |
;; socket_write_tcp ;; |
;; ;; |
;; ;; |
;; Changes history: ;; |
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; |
;; 11.11.2006 - [Johnny_B] and [smb] ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; socket data structure |
struct SOCKET |
.PrevPtr dd ? ; pointer to previous socket in list |
.NextPtr dd ? ; pointer to next socket in list |
.Number dd ? ; socket number (unique within single process) |
.PID dd ? ; application process id |
.LocalIP dd ? ; local IP address |
.LocalPort dw ? ; local port |
.RemoteIP dd ? ; remote IP address |
.RemotePort dw ? ; remote port |
.OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) |
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) |
.rxDataCount dd ? ; rx data count |
.TCBState dd ? ; TCB state |
.TCBTimer dd ? ; TCB timer (seconds) |
.ISS dd ? ; initial send sequence |
.IRS dd ? ; initial receive sequence |
.SND_UNA dd ? ; sequence number of unack'ed sent packets |
.SND_NXT dd ? ; bext send sequence number to use |
.SND_WND dd ? ; send window |
.RCV_NXT dd ? ; next receive sequence number to use |
.RCV_WND dd ? ; receive window |
.SEG_LEN dd ? ; segment length |
.SEG_WND dd ? ; segment window |
.wndsizeTimer dd ? ; window size timer |
.lock MUTEX ; lock mutex |
.rxData dd ? ; receive data buffer here |
ends |
; TCP opening modes |
SOCKET_PASSIVE = 0 |
SOCKET_ACTIVE = 1 |
; socket types |
SOCK_STREAM = 1 |
SOCK_DGRAM = 2 |
; pointer to bitmap of free ports (1=free, 0=used) |
uglobal |
align 4 |
network_free_ports dd ? |
endg |
iglobal |
align 4 |
network_free_hint dd 1024/8 |
endg |
;; Allocate memory for socket data and put new socket into the list |
; Newly created socket is initialized with calling PID and number and |
; put into beginning of list (which is a fastest way). |
; |
; @return socket structure address in EAX |
;; |
proc net_socket_alloc stdcall uses ebx ecx edx edi |
stdcall kernel_alloc, SOCKETBUFFSIZE |
DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax |
; check if we can allocate needed amount of memory |
or eax, eax |
jz .exit |
; zero-initialize allocated memory |
push eax |
mov edi, eax |
mov ecx, SOCKETBUFFSIZE / 4 |
cld |
xor eax, eax |
rep stosd |
pop eax |
mov ebx, eax |
lea ecx, [eax+SOCKET.lock] |
call mutex_init |
mov eax, ebx |
; add socket to the list by changing pointers |
mov ebx, net_sockets |
push [ebx + SOCKET.NextPtr] |
mov [ebx + SOCKET.NextPtr], eax |
mov [eax + SOCKET.PrevPtr], ebx |
pop ebx |
mov [eax + SOCKET.NextPtr], ebx |
or ebx, ebx |
jz @f |
mov [ebx + SOCKET.PrevPtr], eax |
@@: ; set socket owner PID to the one of calling process |
mov ebx, [TASK_BASE] |
mov ebx, [ebx + TASKDATA.pid] |
mov [eax + SOCKET.PID], ebx |
; find first free socket number and use it |
;mov edx, ebx |
mov ebx, net_sockets |
xor ecx, ecx |
.next_socket_number: |
inc ecx |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .last_socket_number |
cmp [ebx + SOCKET.Number], ecx |
jne .next_socket |
;cmp [ebx + SOCKET.PID], edx |
;jne .next_socket |
mov ebx, net_sockets |
jmp .next_socket_number |
.last_socket_number: |
mov [eax + SOCKET.Number], ecx |
.exit: |
ret |
endp |
;; Free socket data memory and pop socket off the list |
; |
; @param sockAddr is a socket structure address |
;; |
proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD |
mov eax, [sockAddr] |
DEBUGF 1, "K : net_socket_free (0x%x)\n", eax |
; check if we got something similar to socket structure address |
or eax, eax |
jz .error |
; make sure sockAddr is one of the socket addresses in the list |
mov ebx, net_sockets |
;mov ecx, [TASK_BASE] |
;mov ecx, [ecx + TASKDATA.pid] |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .error |
cmp ebx, eax |
jne .next_socket |
;cmp [ebx + SOCKET.PID], ecx |
;jne .next_socket |
; okay, we found the correct one |
; mark local port as unused |
movzx ebx, [eax + SOCKET.LocalPort] |
push eax |
mov eax, [network_free_ports] |
xchg bl, bh |
lock bts [eax], ebx |
pop eax |
; remove it from the list first, changing pointers |
mov ebx, [eax + SOCKET.NextPtr] |
mov eax, [eax + SOCKET.PrevPtr] |
mov [eax + SOCKET.NextPtr], ebx |
or ebx, ebx |
jz @f |
mov [ebx + SOCKET.PrevPtr], eax |
@@: ; and finally free the memory structure used |
stdcall kernel_free, [sockAddr] |
ret |
.error: |
DEBUGF 1, "K : failed\n" |
ret |
endp |
;; Get socket structure address by its number |
; Scan through sockets list to find the socket with specified number. |
; This proc uses SOCKET.PID indirectly to check if socket is owned by |
; calling process. |
; |
; @param sockNum is a socket number |
; @return socket structure address or 0 (not found) in EAX |
;; |
proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD |
mov eax, [sockNum] |
; check if we got something similar to socket number |
or eax, eax |
jz .error |
; scan through sockets list |
mov ebx, net_sockets |
;mov ecx, [TASK_BASE] |
;mov ecx, [ecx + TASKDATA.pid] |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .error |
cmp [ebx + SOCKET.Number], eax |
jne .next_socket |
;cmp [ebx + SOCKET.PID], ecx |
;jne .next_socket |
; okay, we found the correct one |
mov eax, ebx |
ret |
.error: |
xor eax, eax |
ret |
endp |
;; Get socket number by its structure address |
; Scan through sockets list to find the socket with specified address. |
; This proc uses SOCKET.PID indirectly to check if socket is owned by |
; calling process. |
; |
; @param sockAddr is a socket structure address |
; @return socket number (SOCKET.Number) or 0 (not found) in EAX |
;; |
proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD |
mov eax, [sockAddr] |
; check if we got something similar to socket structure address |
or eax, eax |
jz .error |
; scan through sockets list |
mov ebx, net_sockets |
;mov ecx, [TASK_BASE] |
;mov ecx, [ecx + TASKDATA.pid] |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .error |
cmp ebx, eax |
jne .next_socket |
;cmp [ebx + SOCKET.PID], ecx |
;jne .next_socket |
; okay, we found the correct one |
mov eax, [ebx + SOCKET.Number] |
ret |
.error: |
xor eax, eax |
ret |
endp |
;; [53.9] Check if local port is used by any socket in the system. |
; Scan through sockets list, checking SOCKET.LocalPort. |
; Useful when you want a to generate a unique local port number. |
; This proc doesn't guarantee that after calling it and trying to use |
; the port reported being free in calls to socket_open/socket_open_tcp it'll |
; still be free or otherwise it'll still be used if reported being in use. |
; |
; @param BX is a port number |
; @return 1 (port is free) or 0 (port is in use) in EAX |
;; |
proc is_localport_unused stdcall |
movzx ebx, bx |
mov eax, [network_free_ports] |
bt [eax], ebx |
setc al |
movzx eax, al |
ret |
endp |
;====================================== |
set_local_port: |
;-------------------------------------- |
;? Set local port in socket structure. |
;-------------------------------------- |
;> eax -> struct SOCKET |
;> bx = local port, or 0 if the kernel must select it itself |
;-------------------------------------- |
;< CF set on error / cleared on success |
;< [eax+SOCKET.LocalPort] filled on success |
;====================================== |
; 0. Prepare: save registers, make eax point to ports table, expand port to ebx. |
push eax ecx |
mov eax, [network_free_ports] |
movzx ebx, bx |
; 1. Test, whether the kernel should choose port itself. If no, proceed to 5. |
test ebx, ebx |
jnz .given |
; 2. Yes, it should. Set ecx = limit of table, eax = start value |
lea ecx, [eax+0x10000/8] |
add eax, [network_free_hint] |
; 3. First scan loop: from free hint to end of table. |
.scan1: |
; 3a. For each dword, find bit set to 1 |
bsf ebx, [eax] |
jz .next1 |
; 3b. If such bit has been found, atomically test again and clear it. |
lock btr [eax], ebx |
; 3c. If the bit was still set (usual case), we have found and reserved one port. |
; Proceed to 6. |
jc .found |
; 3d. Otherwise, someone has reserved it between bsf and btr, so retry search. |
jmp .scan1 |
.next1: |
; 3e. All bits are cleared, so advance to next dword. |
add eax, 4 |
; 3f. Check limit and continue loop. |
cmp eax, ecx |
jb .scan1 |
; 4. Second scan loop: from port 1024 (start of non-system ports) to free hint. |
mov eax, [network_free_ports] |
mov ecx, eax |
add ecx, [network_free_hint] |
add eax, 1024/8 |
; 4a. Test whether there is something to scan. |
cmp eax, ecx |
jae .fail |
; 4b. Enter the loop, the process is same as for 3. |
.scan2: |
bsf ebx, [eax] |
jz .next2 |
lock btr [eax], ebx |
jc .found |
jmp .scan2 |
.next2: |
add eax, 4 |
cmp eax, ecx |
jb .scan2 |
; 4c. None found. Fail. |
.fail: |
pop ecx eax |
stc |
ret |
; 5. No, the kernel should reserve selected port. |
.given: |
; 5a. Atomically test old value and clear bit. |
lock btr [eax], ebx |
; 5b. If the bit was set, reservation is successful. Proceed to 8. |
jc .set |
; 5c. Otherwise, fail. |
jmp .fail |
.found: |
; 6. We have found the bit set to 1, convert the position to port number. |
sub eax, [network_free_ports] |
lea ebx, [ebx+eax*8] |
; 7. Update free hint. |
add eax, 4 |
cmp eax, 65536/8 |
jb @f |
mov eax, 1024/8 |
@@: |
mov [network_free_hint], eax |
.set: |
; 8. Restore eax, set SOCKET.LocalPort and return. |
pop ecx eax |
xchg bl, bh ; Intel -> network byte order |
mov [eax + SOCKET.LocalPort], bx |
clc |
ret |
;; [53.0] Open DGRAM socket (connectionless, unreliable) |
; |
; @param BX is local port number |
; @param CX is remote port number |
; @param EDX is remote IP address |
; @return socket number or -1 (error) in EAX |
;; |
proc socket_open stdcall |
call net_socket_alloc |
or eax, eax |
jz .error |
DEBUGF 1, "K : socket_open (0x%x)\n", eax |
push eax |
call set_local_port |
jc .error.free |
xchg ch, cl |
mov [eax + SOCKET.RemotePort], cx |
mov ebx, [stack_ip] |
mov [eax + SOCKET.LocalIP], ebx |
mov [eax + SOCKET.RemoteIP], edx |
;pop eax ; Get the socket number back, so we can return it |
stdcall net_socket_addr_to_num |
ret |
.error.free: |
stdcall net_socket_free;, eax |
.error: |
DEBUGF 1, "K : socket_open (fail)\n" |
or eax, -1 |
ret |
endp |
;; [53.5] Open STREAM socket (connection-based, sequenced, reliable, two-way) |
; |
; @param BX is local port number |
; @param CX is remote port number |
; @param EDX is remote IP address |
; @param ESI is open mode (SOCKET_ACTIVE, SOCKET_PASSIVE) |
; @return socket number or -1 (error) in EAX |
;; |
proc socket_open_tcp stdcall |
local sockAddr dd ? |
cmp esi, SOCKET_PASSIVE |
jne .skip_port_check |
push ebx |
mov eax, ebx |
xchg al, ah |
mov ebx, net_sockets |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .last_socket |
cmp [ebx + SOCKET.TCBState], TCB_LISTEN |
jne .next_socket |
cmp [ebx + SOCKET.LocalPort], ax |
jne .next_socket |
xchg al, ah |
DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx |
pop ebx |
jmp .error |
.last_socket: |
pop ebx |
.skip_port_check: |
call net_socket_alloc |
or eax, eax |
jz .error |
DEBUGF 1, "K : socket_open_tcp (0x%x)\n", eax |
mov [sockAddr], eax |
; TODO - check this works! |
;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. |
call set_local_port |
jc .error.free |
xchg ch, cl |
mov [eax + SOCKET.RemotePort], cx |
mov [eax + SOCKET.OrigRemotePort], cx |
mov ebx, [stack_ip] |
mov [eax + SOCKET.LocalIP], ebx |
mov [eax + SOCKET.RemoteIP], edx |
mov [eax + SOCKET.OrigRemoteIP], edx |
mov ebx, TCB_LISTEN |
cmp esi, SOCKET_PASSIVE |
je @f |
mov ebx, TCB_SYN_SENT |
@@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB |
cmp ebx, TCB_LISTEN |
je .exit |
; Now, if we are in active mode, then we have to send a SYN to the specified remote port |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push eax |
mov bl, TH_SYN |
xor ecx, ecx |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
mov esi, [sockAddr] |
; increment SND.NXT in socket |
add esi, SOCKET.SND_NXT |
call inc_inet_esi |
.exit: |
; Get the socket number back, so we can return it |
stdcall net_socket_addr_to_num, [sockAddr] |
ret |
.error.free: |
stdcall net_socket_free, eax |
.error: |
DEBUGF 1, "K : socket_open_tcp (fail)\n" |
or eax, -1 |
ret |
endp |
;; [53.1] Close DGRAM socket |
; |
; @param EBX is socket number |
; @return 0 (closed successfully) or -1 (error) in EAX |
;; |
proc socket_close stdcall |
DEBUGF 1, "K : socket_close (0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
stdcall net_socket_free, eax |
xor eax, eax |
ret |
.error: |
DEBUGF 1, "K : socket_close (fail)\n" |
or eax, -1 |
ret |
endp |
;; [53.8] Close STREAM socket |
; Closing TCP sockets takes time, so when you get successful return code |
; from this function doesn't always mean that socket is actually closed. |
; |
; @param EBX is socket number |
; @return 0 (closed successfully) or -1 (error) in EAX |
;; |
proc socket_close_tcp stdcall |
local sockAddr dd ? |
DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx |
; first, remove any resend entries |
pusha |
mov esi, resendQ |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .last_resendq ; None left |
cmp [esi + 4], ebx |
je @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: mov dword[esi + 4], 0 |
inc ecx |
add esi, 8 |
jmp .next_resendq |
.last_resendq: |
popa |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov ebx, eax |
mov [sockAddr], eax |
cmp [ebx + SOCKET.TCBState], TCB_LISTEN |
je .destroy_tcb |
cmp [ebx + SOCKET.TCBState], TCB_SYN_SENT |
je .destroy_tcb |
cmp [ebx + SOCKET.TCBState], TCB_CLOSED |
je .destroy_tcb |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .error |
push eax |
mov bl, TH_FIN+TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov ebx, [sockAddr] |
; increament SND.NXT in socket |
lea esi, [ebx + SOCKET.SND_NXT] |
call inc_inet_esi |
; Get the socket state |
mov eax, [ebx + SOCKET.TCBState] |
cmp eax, TCB_SYN_RECEIVED |
je .fin_wait_1 |
cmp eax, TCB_ESTABLISHED |
je .fin_wait_1 |
; assume CLOSE WAIT |
; Send a fin, then enter last-ack state |
mov [ebx + SOCKET.TCBState], TCB_LAST_ACK |
jmp .send |
.fin_wait_1: |
; Send a fin, then enter finwait2 state |
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 |
.send: |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
jmp .exit |
.destroy_tcb: |
; Clear the socket variables |
stdcall net_socket_free, ebx |
.exit: |
xor eax, eax |
ret |
.error: |
DEBUGF 1, "K : socket_close_tcp (fail)\n" |
or eax, -1 |
ret |
endp |
;; [53.2] Poll socket |
; |
; @param EBX is socket number |
; @return count or bytes in rx buffer or 0 (error) in EAX |
;; |
proc socket_poll stdcall |
; DEBUGF 1, "socket_poll(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov eax, [eax + SOCKET.rxDataCount] |
ret |
.error: |
xor eax, eax |
ret |
endp |
;; [53.6] Get socket TCB state |
; |
; @param EBX is socket number |
; @return socket TCB state or 0 (error) in EAX |
;; |
proc socket_status stdcall |
;; DEBUGF 1, "socket_status(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov eax, [eax + SOCKET.TCBState] |
ret |
.error: |
xor eax, eax |
ret |
endp |
;; [53.3] Get one byte from rx buffer |
; This function can return 0 in two cases: if there's one byte read and |
; non left, and if an error occured. Behavior should be changed and function |
; shouldn't be used for now. Consider using [53.11] instead. |
; |
; @param EBX is socket number |
; @return number of bytes left in rx buffer or 0 (error) in EAX |
; @return byte read in BL |
;; |
proc socket_read stdcall |
; DEBUGF 1, "socket_read(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov ebx, eax |
lea ecx, [eax + SOCKET.lock] |
call mutex_lock |
mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes |
test eax, eax |
jz .error_release |
dec eax |
mov esi, ebx ; esi is address of socket |
mov [ebx + SOCKET.rxDataCount], eax ; store new count |
movzx eax, byte[ebx + SOCKET.rxData] ; get the byte |
mov ecx, SOCKETBUFFSIZE - SOCKET.rxData - 1 |
lea edi, [esi + SOCKET.rxData] |
lea esi, [edi + 1] |
cld |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
lea ecx, [ebx + SOCKET.lock] |
mov ebx, eax |
call mutex_unlock |
mov eax, ebx |
ret |
.error_release: |
lea ecx, [ebx + SOCKET.lock] |
call mutex_unlock |
.error: |
xor ebx, ebx |
xor eax, eax |
ret |
endp |
;; [53.11] Get specified number of bytes from rx buffer |
; Number of bytes in rx buffer can be less than requested size. In this case, |
; only available number of bytes is read. |
; This function can return 0 in two cases: if there's no data to read, and if |
; an error occured. Behavior should be changed. |
; |
; @param EBX is socket number |
; @param ECX is pointer to application buffer |
; @param EDX is application buffer size (number of bytes to read) |
; @return number of bytes read or 0 (error) in EAX |
;; |
proc socket_read_packet stdcall |
; DEBUGF 1, "socket_read_packet(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx ; get real socket address |
or eax, eax |
jz .error |
mov ebx, eax |
push ecx edx |
lea ecx, [eax + SOCKET.lock] |
call mutex_lock |
pop edx ecx |
mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes |
test eax, eax ; if count of bytes is zero.. |
jz .exit ; exit function (eax will be zero) |
test edx, edx ; if buffer size is zero, copy all data |
jz .copy_all_bytes |
cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data |
jge .copy_all_bytes |
sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy) |
mov [ebx + SOCKET.rxDataCount], eax ; |
push eax |
mov eax, edx ; number of bytes we want to copy must be in eax |
call .start_copy ; copy to the application |
mov esi, ebx ; now we're going to copy the remaining bytes to the beginning |
add esi, SOCKET.rxData ; we dont need to copy the header |
mov edi, esi ; edi is where we're going to copy to |
add esi, edx ; esi is from where we copy |
pop ecx ; count of bytes we have left |
push ecx ; push it again so we can re-use it later |
shr ecx, 2 ; divide eax by 4 |
cld |
rep movsd ; copy all full dwords |
pop ecx |
and ecx, 3 |
rep movsb ; copy remaining bytes |
.exit: |
lea ecx, [ebx + SOCKET.lock] |
mov ebx,eax |
call mutex_unlock |
mov eax,ebx |
ret ; at last, exit |
.error: |
xor eax, eax |
ret |
.copy_all_bytes: |
xor esi, esi |
mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero) |
call .start_copy |
lea ecx, [ebx + SOCKET.lock] |
mov ebx,eax |
call mutex_unlock |
mov eax,ebx |
ret |
.start_copy: |
mov edi, ecx |
mov esi, ebx |
add esi, SOCKET.rxData ; we dont need to copy the header |
mov ecx, eax ; eax is count of bytes |
push ecx |
shr ecx, 2 ; divide eax by 4 |
cld ; copy all full dwords |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb ; copy the rest bytes |
retn ; exit, or go back to shift remaining bytes if any |
endp |
;; [53.4] Send data through DGRAM socket |
; |
; @param EBX is socket number |
; @param ECX is application data size (number of bytes to send) |
; @param EDX is pointer to application data buffer |
; @return 0 (sent successfully) or -1 (error) in EAX |
;; |
proc socket_write stdcall |
; DEBUGF 1, "socket_write(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx ; get real socket address |
or eax, eax |
jz .error |
mov ebx, eax |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .error |
; Save the queue entry number |
push eax |
; save the pointers to the data buffer & size |
push edx |
push ecx |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov edx, eax |
; So, ebx holds the socket ptr, edx holds the IPbuffer ptr |
; Fill in the IP header (some data is in the socket descriptor) |
mov eax, [ebx + SOCKET.LocalIP] |
mov [edx + IP_PACKET.SourceAddress], eax |
mov eax, [ebx + SOCKET.RemoteIP] |
mov [edx + IP_PACKET.DestinationAddress], eax |
mov [edx + IP_PACKET.VersionAndIHL], 0x45 |
mov [edx + IP_PACKET.TypeOfService], 0 |
pop eax ; Get the UDP data length |
push eax |
add eax, 20 + 8 ; add IP header and UDP header lengths |
xchg al, ah |
mov [edx + IP_PACKET.TotalLength], ax |
xor eax, eax |
mov [edx + IP_PACKET.Identification], ax |
mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 |
mov [edx + IP_PACKET.TimeToLive], 0x20 |
mov [edx + IP_PACKET.Protocol], PROTOCOL_UDP |
; Checksum left unfilled |
mov [edx + IP_PACKET.HeaderChecksum], ax |
; Fill in the UDP header (some data is in the socket descriptor) |
mov ax, [ebx + SOCKET.LocalPort] |
mov [edx + 20 + UDP_PACKET.SourcePort], ax |
mov ax, [ebx + SOCKET.RemotePort] |
mov [edx + 20 + UDP_PACKET.DestinationPort], ax |
pop eax |
push eax |
add eax, 8 |
xchg al, ah |
mov [edx + 20 + UDP_PACKET.Length], ax |
; Checksum left unfilled |
xor eax, eax |
mov [edx + 20 + UDP_PACKET.Checksum], ax |
pop ecx ; count of bytes to send |
mov ebx, ecx ; need the length later |
pop eax ; get callers ptr to data to send |
; Get the address of the callers data |
mov edi, [TASK_BASE] |
add edi, TASKDATA.mem_start |
add eax, [edi] |
mov esi, eax |
mov edi, edx |
add edi, 28 |
cld |
rep movsb ; copy the data across |
; we have edx as IPbuffer ptr. |
; Fill in the UDP checksum |
; First, fill in pseudoheader |
mov eax, [edx + IP_PACKET.SourceAddress] |
mov [pseudoHeader], eax |
mov eax, [edx + IP_PACKET.DestinationAddress] |
mov [pseudoHeader + 4], eax |
mov word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0 ; 0 + protocol |
add ebx, 8 |
mov eax, ebx |
xchg al, ah |
mov [pseudoHeader + 10], ax |
mov eax, pseudoHeader |
mov [checkAdd1], eax |
mov [checkSize1], word 12 |
mov eax, edx |
add eax, 20 |
mov [checkAdd2], eax |
mov eax, ebx |
mov [checkSize2], ax ; was eax!! mjh 8/7/02 |
call checksum |
; store it in the UDP checksum ( in the correct order! ) |
mov ax, [checkResult] |
; If the UDP checksum computes to 0, we must make it 0xffff |
; (0 is reserved for 'not used') |
test ax, ax |
jnz @f |
mov ax, 0xffff |
@@: xchg al, ah |
mov [edx + 20 + UDP_PACKET.Checksum], ax |
; Fill in the IP header checksum |
GET_IHL ecx,edx ; get IP-Header length |
stdcall checksum_jb,edx,ecx ; buf_ptr, buf_size |
xchg al, ah |
mov [edx + IP_PACKET.HeaderChecksum], ax |
; Check destination IP address. |
; If it is the local host IP, route it back to IP_RX |
pop ebx |
mov eax, NET1OUT_QUEUE |
mov ecx, [edx + SOCKET.RemoteIP] |
mov edx, [stack_ip] |
cmp edx, ecx |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
call queue |
xor eax, eax |
ret |
.error: |
or eax, -1 |
ret |
endp |
;; [53.7] Send data through STREAM socket |
; |
; @param EBX is socket number |
; @param ECX is application data size (number of bytes to send) |
; @param EDX is pointer to application data buffer |
; @return 0 (sent successfully) or -1 (error) in EAX |
;; |
proc socket_write_tcp stdcall |
local sockAddr dd ? |
; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov ebx, eax |
mov [sockAddr], ebx |
; If the sockets window timer is nonzero, do not queue packet |
cmp [ebx + SOCKET.wndsizeTimer], 0 |
jne .error |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .error |
push eax |
; Get the address of the callers data |
mov edi, [TASK_BASE] |
add edi, TASKDATA.mem_start |
add edx, [edi] |
mov esi, edx |
pop eax |
push eax |
push ecx |
mov bl, TH_ACK |
stdcall build_tcp_packet, [sockAddr] |
pop ecx |
; Check destination IP address. |
; If it is the local host IP, route it back to IP_RX |
pop ebx |
push ecx |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
pop ecx |
push ebx ; save ipbuffer number |
call queue |
mov esi, [sockAddr] |
; increament SND.NXT in socket |
; Amount to increment by is in ecx |
add esi, SOCKET.SND_NXT |
call add_inet_esi |
pop ebx |
; Copy the IP buffer to a resend queue |
; If there isn't one, dont worry about it for now |
mov esi, resendQ |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .exit ; None found |
cmp dword[esi + 4], 0 |
je @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: push ebx |
; OK, we have a buffer descriptor ptr in esi. |
; resend entry # in ecx |
; Populate it |
; socket # |
; retries count |
; retry time |
; fill IP buffer associated with this descriptor |
stdcall net_socket_addr_to_num, [sockAddr] |
mov [esi + 4], eax |
mov byte[esi + 1], TCP_RETRIES |
mov word[esi + 2], TCP_TIMEOUT |
inc ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
mov edi, resendBuffer - IPBUFFSIZE |
@@: add edi, IPBUFFSIZE |
loop @b |
; we have dest buffer location in edi |
pop eax |
; convert source buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov esi, eax |
; do copy |
mov ecx, IPBUFFSIZE |
cld |
rep movsb |
.exit: |
xor eax, eax |
ret |
.error: |
or eax, -1 |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; SOCKET.INC ;; |
;; ;; |
;; Sockets constants, structures and functions ;; |
;; ;; |
;; This file contains the following: ;; |
;; is_localport_unused ;; |
;; get_free_socket ;; |
;; socket_open ;; |
;; socket_open_tcp ;; |
;; socket_close ;; |
;; socket_close_tcp ;; |
;; socket_poll ;; |
;; socket_status ;; |
;; socket_read ;; |
;; socket_write ;; |
;; socket_write_tcp ;; |
;; ;; |
;; ;; |
;; Changes history: ;; |
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; |
;; 11.11.2006 - [Johnny_B] and [smb] ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; socket data structure |
struct SOCKET |
.PrevPtr dd ? ; pointer to previous socket in list |
.NextPtr dd ? ; pointer to next socket in list |
.Number dd ? ; socket number (unique within single process) |
.PID dd ? ; application process id |
.LocalIP dd ? ; local IP address |
.LocalPort dw ? ; local port |
.RemoteIP dd ? ; remote IP address |
.RemotePort dw ? ; remote port |
.OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) |
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) |
.rxDataCount dd ? ; rx data count |
.TCBState dd ? ; TCB state |
.TCBTimer dd ? ; TCB timer (seconds) |
.ISS dd ? ; initial send sequence |
.IRS dd ? ; initial receive sequence |
.SND_UNA dd ? ; sequence number of unack'ed sent packets |
.SND_NXT dd ? ; bext send sequence number to use |
.SND_WND dd ? ; send window |
.RCV_NXT dd ? ; next receive sequence number to use |
.RCV_WND dd ? ; receive window |
.SEG_LEN dd ? ; segment length |
.SEG_WND dd ? ; segment window |
.wndsizeTimer dd ? ; window size timer |
.lock MUTEX ; lock mutex |
.rxData dd ? ; receive data buffer here |
ends |
; TCP opening modes |
SOCKET_PASSIVE = 0 |
SOCKET_ACTIVE = 1 |
; socket types |
SOCK_STREAM = 1 |
SOCK_DGRAM = 2 |
; pointer to bitmap of free ports (1=free, 0=used) |
uglobal |
align 4 |
network_free_ports dd ? |
endg |
iglobal |
align 4 |
network_free_hint dd 1024/8 |
endg |
;; Allocate memory for socket data and put new socket into the list |
; Newly created socket is initialized with calling PID and number and |
; put into beginning of list (which is a fastest way). |
; |
; @return socket structure address in EAX |
;; |
proc net_socket_alloc stdcall uses ebx ecx edx edi |
stdcall kernel_alloc, SOCKETBUFFSIZE |
DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax |
; check if we can allocate needed amount of memory |
or eax, eax |
jz .exit |
; zero-initialize allocated memory |
push eax |
mov edi, eax |
mov ecx, SOCKETBUFFSIZE / 4 |
cld |
xor eax, eax |
rep stosd |
pop eax |
mov ebx, eax |
lea ecx, [eax+SOCKET.lock] |
call mutex_init |
mov eax, ebx |
; add socket to the list by changing pointers |
mov ebx, net_sockets |
push [ebx + SOCKET.NextPtr] |
mov [ebx + SOCKET.NextPtr], eax |
mov [eax + SOCKET.PrevPtr], ebx |
pop ebx |
mov [eax + SOCKET.NextPtr], ebx |
or ebx, ebx |
jz @f |
mov [ebx + SOCKET.PrevPtr], eax |
@@: ; set socket owner PID to the one of calling process |
mov ebx, [TASK_BASE] |
mov ebx, [ebx + TASKDATA.pid] |
mov [eax + SOCKET.PID], ebx |
; find first free socket number and use it |
;mov edx, ebx |
mov ebx, net_sockets |
xor ecx, ecx |
.next_socket_number: |
inc ecx |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .last_socket_number |
cmp [ebx + SOCKET.Number], ecx |
jne .next_socket |
;cmp [ebx + SOCKET.PID], edx |
;jne .next_socket |
mov ebx, net_sockets |
jmp .next_socket_number |
.last_socket_number: |
mov [eax + SOCKET.Number], ecx |
.exit: |
ret |
endp |
;; Free socket data memory and pop socket off the list |
; |
; @param sockAddr is a socket structure address |
;; |
proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD |
mov eax, [sockAddr] |
DEBUGF 1, "K : net_socket_free (0x%x)\n", eax |
; check if we got something similar to socket structure address |
or eax, eax |
jz .error |
; make sure sockAddr is one of the socket addresses in the list |
mov ebx, net_sockets |
;mov ecx, [TASK_BASE] |
;mov ecx, [ecx + TASKDATA.pid] |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .error |
cmp ebx, eax |
jne .next_socket |
;cmp [ebx + SOCKET.PID], ecx |
;jne .next_socket |
; okay, we found the correct one |
; mark local port as unused |
movzx ebx, [eax + SOCKET.LocalPort] |
push eax |
mov eax, [network_free_ports] |
xchg bl, bh |
lock bts [eax], ebx |
pop eax |
; remove it from the list first, changing pointers |
mov ebx, [eax + SOCKET.NextPtr] |
mov eax, [eax + SOCKET.PrevPtr] |
mov [eax + SOCKET.NextPtr], ebx |
or ebx, ebx |
jz @f |
mov [ebx + SOCKET.PrevPtr], eax |
@@: ; and finally free the memory structure used |
stdcall kernel_free, [sockAddr] |
ret |
.error: |
DEBUGF 1, "K : failed\n" |
ret |
endp |
;; Get socket structure address by its number |
; Scan through sockets list to find the socket with specified number. |
; This proc uses SOCKET.PID indirectly to check if socket is owned by |
; calling process. |
; |
; @param sockNum is a socket number |
; @return socket structure address or 0 (not found) in EAX |
;; |
proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD |
mov eax, [sockNum] |
; check if we got something similar to socket number |
or eax, eax |
jz .error |
; scan through sockets list |
mov ebx, net_sockets |
;mov ecx, [TASK_BASE] |
;mov ecx, [ecx + TASKDATA.pid] |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .error |
cmp [ebx + SOCKET.Number], eax |
jne .next_socket |
;cmp [ebx + SOCKET.PID], ecx |
;jne .next_socket |
; okay, we found the correct one |
mov eax, ebx |
ret |
.error: |
xor eax, eax |
ret |
endp |
;; Get socket number by its structure address |
; Scan through sockets list to find the socket with specified address. |
; This proc uses SOCKET.PID indirectly to check if socket is owned by |
; calling process. |
; |
; @param sockAddr is a socket structure address |
; @return socket number (SOCKET.Number) or 0 (not found) in EAX |
;; |
proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD |
mov eax, [sockAddr] |
; check if we got something similar to socket structure address |
or eax, eax |
jz .error |
; scan through sockets list |
mov ebx, net_sockets |
;mov ecx, [TASK_BASE] |
;mov ecx, [ecx + TASKDATA.pid] |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .error |
cmp ebx, eax |
jne .next_socket |
;cmp [ebx + SOCKET.PID], ecx |
;jne .next_socket |
; okay, we found the correct one |
mov eax, [ebx + SOCKET.Number] |
ret |
.error: |
xor eax, eax |
ret |
endp |
;; [53.9] Check if local port is used by any socket in the system. |
; Scan through sockets list, checking SOCKET.LocalPort. |
; Useful when you want a to generate a unique local port number. |
; This proc doesn't guarantee that after calling it and trying to use |
; the port reported being free in calls to socket_open/socket_open_tcp it'll |
; still be free or otherwise it'll still be used if reported being in use. |
; |
; @param BX is a port number |
; @return 1 (port is free) or 0 (port is in use) in EAX |
;; |
proc is_localport_unused stdcall |
movzx ebx, bx |
mov eax, [network_free_ports] |
bt [eax], ebx |
setc al |
movzx eax, al |
ret |
endp |
;====================================== |
set_local_port: |
;-------------------------------------- |
;? Set local port in socket structure. |
;-------------------------------------- |
;> eax -> struct SOCKET |
;> bx = local port, or 0 if the kernel must select it itself |
;-------------------------------------- |
;< CF set on error / cleared on success |
;< [eax+SOCKET.LocalPort] filled on success |
;====================================== |
; 0. Prepare: save registers, make eax point to ports table, expand port to ebx. |
push eax ecx |
mov eax, [network_free_ports] |
movzx ebx, bx |
; 1. Test, whether the kernel should choose port itself. If no, proceed to 5. |
test ebx, ebx |
jnz .given |
; 2. Yes, it should. Set ecx = limit of table, eax = start value |
lea ecx, [eax+0x10000/8] |
add eax, [network_free_hint] |
; 3. First scan loop: from free hint to end of table. |
.scan1: |
; 3a. For each dword, find bit set to 1 |
bsf ebx, [eax] |
jz .next1 |
; 3b. If such bit has been found, atomically test again and clear it. |
lock btr [eax], ebx |
; 3c. If the bit was still set (usual case), we have found and reserved one port. |
; Proceed to 6. |
jc .found |
; 3d. Otherwise, someone has reserved it between bsf and btr, so retry search. |
jmp .scan1 |
.next1: |
; 3e. All bits are cleared, so advance to next dword. |
add eax, 4 |
; 3f. Check limit and continue loop. |
cmp eax, ecx |
jb .scan1 |
; 4. Second scan loop: from port 1024 (start of non-system ports) to free hint. |
mov eax, [network_free_ports] |
mov ecx, eax |
add ecx, [network_free_hint] |
add eax, 1024/8 |
; 4a. Test whether there is something to scan. |
cmp eax, ecx |
jae .fail |
; 4b. Enter the loop, the process is same as for 3. |
.scan2: |
bsf ebx, [eax] |
jz .next2 |
lock btr [eax], ebx |
jc .found |
jmp .scan2 |
.next2: |
add eax, 4 |
cmp eax, ecx |
jb .scan2 |
; 4c. None found. Fail. |
.fail: |
pop ecx eax |
stc |
ret |
; 5. No, the kernel should reserve selected port. |
.given: |
; 5a. Atomically test old value and clear bit. |
lock btr [eax], ebx |
; 5b. If the bit was set, reservation is successful. Proceed to 8. |
jc .set |
; 5c. Otherwise, fail. |
jmp .fail |
.found: |
; 6. We have found the bit set to 1, convert the position to port number. |
sub eax, [network_free_ports] |
lea ebx, [ebx+eax*8] |
; 7. Update free hint. |
add eax, 4 |
cmp eax, 65536/8 |
jb @f |
mov eax, 1024/8 |
@@: |
mov [network_free_hint], eax |
.set: |
; 8. Restore eax, set SOCKET.LocalPort and return. |
pop ecx eax |
xchg bl, bh ; Intel -> network byte order |
mov [eax + SOCKET.LocalPort], bx |
clc |
ret |
;; [53.0] Open DGRAM socket (connectionless, unreliable) |
; |
; @param BX is local port number |
; @param CX is remote port number |
; @param EDX is remote IP address |
; @return socket number or -1 (error) in EAX |
;; |
proc socket_open stdcall |
call net_socket_alloc |
or eax, eax |
jz .error |
DEBUGF 1, "K : socket_open (0x%x)\n", eax |
push eax |
call set_local_port |
jc .error.free |
xchg ch, cl |
mov [eax + SOCKET.RemotePort], cx |
mov ebx, [stack_ip] |
mov [eax + SOCKET.LocalIP], ebx |
mov [eax + SOCKET.RemoteIP], edx |
;pop eax ; Get the socket number back, so we can return it |
stdcall net_socket_addr_to_num |
ret |
.error.free: |
stdcall net_socket_free;, eax |
.error: |
DEBUGF 1, "K : socket_open (fail)\n" |
or eax, -1 |
ret |
endp |
;; [53.5] Open STREAM socket (connection-based, sequenced, reliable, two-way) |
; |
; @param BX is local port number |
; @param CX is remote port number |
; @param EDX is remote IP address |
; @param ESI is open mode (SOCKET_ACTIVE, SOCKET_PASSIVE) |
; @return socket number or -1 (error) in EAX |
;; |
proc socket_open_tcp stdcall |
local sockAddr dd ? |
cmp esi, SOCKET_PASSIVE |
jne .skip_port_check |
push ebx |
mov eax, ebx |
xchg al, ah |
mov ebx, net_sockets |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .last_socket |
cmp [ebx + SOCKET.TCBState], TCB_LISTEN |
jne .next_socket |
cmp [ebx + SOCKET.LocalPort], ax |
jne .next_socket |
xchg al, ah |
DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx |
pop ebx |
jmp .error |
.last_socket: |
pop ebx |
.skip_port_check: |
call net_socket_alloc |
or eax, eax |
jz .error |
DEBUGF 1, "K : socket_open_tcp (0x%x)\n", eax |
mov [sockAddr], eax |
; TODO - check this works! |
;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. |
call set_local_port |
jc .error.free |
xchg ch, cl |
mov [eax + SOCKET.RemotePort], cx |
mov [eax + SOCKET.OrigRemotePort], cx |
mov ebx, [stack_ip] |
mov [eax + SOCKET.LocalIP], ebx |
mov [eax + SOCKET.RemoteIP], edx |
mov [eax + SOCKET.OrigRemoteIP], edx |
mov ebx, TCB_LISTEN |
cmp esi, SOCKET_PASSIVE |
je @f |
mov ebx, TCB_SYN_SENT |
@@: |
mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB |
cmp ebx, TCB_LISTEN |
je .exit |
; Now, if we are in active mode, then we have to send a SYN to the specified remote port |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push eax |
mov bl, TH_SYN |
xor ecx, ecx |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
mov esi, [sockAddr] |
; increment SND.NXT in socket |
add esi, SOCKET.SND_NXT |
call inc_inet_esi |
.exit: |
; Get the socket number back, so we can return it |
stdcall net_socket_addr_to_num, [sockAddr] |
ret |
.error.free: |
stdcall net_socket_free, eax |
.error: |
DEBUGF 1, "K : socket_open_tcp (fail)\n" |
or eax, -1 |
ret |
endp |
;; [53.1] Close DGRAM socket |
; |
; @param EBX is socket number |
; @return 0 (closed successfully) or -1 (error) in EAX |
;; |
proc socket_close stdcall |
DEBUGF 1, "K : socket_close (0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
stdcall net_socket_free, eax |
xor eax, eax |
ret |
.error: |
DEBUGF 1, "K : socket_close (fail)\n" |
or eax, -1 |
ret |
endp |
;; [53.8] Close STREAM socket |
; Closing TCP sockets takes time, so when you get successful return code |
; from this function doesn't always mean that socket is actually closed. |
; |
; @param EBX is socket number |
; @return 0 (closed successfully) or -1 (error) in EAX |
;; |
proc socket_close_tcp stdcall |
local sockAddr dd ? |
DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx |
; first, remove any resend entries |
pusha |
mov esi, resendQ |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .last_resendq ; None left |
cmp [esi + 4], ebx |
je @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: |
mov dword[esi + 4], 0 |
inc ecx |
add esi, 8 |
jmp .next_resendq |
.last_resendq: |
popa |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov ebx, eax |
mov [sockAddr], eax |
cmp [ebx + SOCKET.TCBState], TCB_LISTEN |
je .destroy_tcb |
cmp [ebx + SOCKET.TCBState], TCB_SYN_SENT |
je .destroy_tcb |
cmp [ebx + SOCKET.TCBState], TCB_CLOSED |
je .destroy_tcb |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .error |
push eax |
mov bl, TH_FIN+TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov ebx, [sockAddr] |
; increament SND.NXT in socket |
lea esi, [ebx + SOCKET.SND_NXT] |
call inc_inet_esi |
; Get the socket state |
mov eax, [ebx + SOCKET.TCBState] |
cmp eax, TCB_SYN_RECEIVED |
je .fin_wait_1 |
cmp eax, TCB_ESTABLISHED |
je .fin_wait_1 |
; assume CLOSE WAIT |
; Send a fin, then enter last-ack state |
mov [ebx + SOCKET.TCBState], TCB_LAST_ACK |
jmp .send |
.fin_wait_1: |
; Send a fin, then enter finwait2 state |
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 |
.send: |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
jmp .exit |
.destroy_tcb: |
; Clear the socket variables |
stdcall net_socket_free, ebx |
.exit: |
xor eax, eax |
ret |
.error: |
DEBUGF 1, "K : socket_close_tcp (fail)\n" |
or eax, -1 |
ret |
endp |
;; [53.2] Poll socket |
; |
; @param EBX is socket number |
; @return count or bytes in rx buffer or 0 (error) in EAX |
;; |
proc socket_poll stdcall |
; DEBUGF 1, "socket_poll(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov eax, [eax + SOCKET.rxDataCount] |
ret |
.error: |
xor eax, eax |
ret |
endp |
;; [53.6] Get socket TCB state |
; |
; @param EBX is socket number |
; @return socket TCB state or 0 (error) in EAX |
;; |
proc socket_status stdcall |
;; DEBUGF 1, "socket_status(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov eax, [eax + SOCKET.TCBState] |
ret |
.error: |
xor eax, eax |
ret |
endp |
;; [53.3] Get one byte from rx buffer |
; This function can return 0 in two cases: if there's one byte read and |
; non left, and if an error occured. Behavior should be changed and function |
; shouldn't be used for now. Consider using [53.11] instead. |
; |
; @param EBX is socket number |
; @return number of bytes left in rx buffer or 0 (error) in EAX |
; @return byte read in BL |
;; |
proc socket_read stdcall |
; DEBUGF 1, "socket_read(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov ebx, eax |
lea ecx, [eax + SOCKET.lock] |
call mutex_lock |
mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes |
test eax, eax |
jz .error_release |
dec eax |
mov esi, ebx ; esi is address of socket |
mov [ebx + SOCKET.rxDataCount], eax ; store new count |
movzx eax, byte[ebx + SOCKET.rxData] ; get the byte |
mov ecx, SOCKETBUFFSIZE - SOCKET.rxData - 1 |
lea edi, [esi + SOCKET.rxData] |
lea esi, [edi + 1] |
cld |
push ecx |
shr ecx, 2 |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
lea ecx, [ebx + SOCKET.lock] |
mov ebx, eax |
call mutex_unlock |
mov eax, ebx |
ret |
.error_release: |
lea ecx, [ebx + SOCKET.lock] |
call mutex_unlock |
.error: |
xor ebx, ebx |
xor eax, eax |
ret |
endp |
;; [53.11] Get specified number of bytes from rx buffer |
; Number of bytes in rx buffer can be less than requested size. In this case, |
; only available number of bytes is read. |
; This function can return 0 in two cases: if there's no data to read, and if |
; an error occured. Behavior should be changed. |
; |
; @param EBX is socket number |
; @param ECX is pointer to application buffer |
; @param EDX is application buffer size (number of bytes to read) |
; @return number of bytes read or 0 (error) in EAX |
;; |
proc socket_read_packet stdcall |
; DEBUGF 1, "socket_read_packet(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx ; get real socket address |
or eax, eax |
jz .error |
mov ebx, eax |
push ecx edx |
lea ecx, [eax + SOCKET.lock] |
call mutex_lock |
pop edx ecx |
mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes |
test eax, eax ; if count of bytes is zero.. |
jz .exit ; exit function (eax will be zero) |
test edx, edx ; if buffer size is zero, copy all data |
jz .copy_all_bytes |
cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data |
jge .copy_all_bytes |
sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy) |
mov [ebx + SOCKET.rxDataCount], eax ; |
push eax |
mov eax, edx ; number of bytes we want to copy must be in eax |
call .start_copy ; copy to the application |
mov esi, ebx ; now we're going to copy the remaining bytes to the beginning |
add esi, SOCKET.rxData ; we dont need to copy the header |
mov edi, esi ; edi is where we're going to copy to |
add esi, edx ; esi is from where we copy |
pop ecx ; count of bytes we have left |
push ecx ; push it again so we can re-use it later |
shr ecx, 2 ; divide eax by 4 |
cld |
rep movsd ; copy all full dwords |
pop ecx |
and ecx, 3 |
rep movsb ; copy remaining bytes |
.exit: |
lea ecx, [ebx + SOCKET.lock] |
mov ebx, eax |
call mutex_unlock |
mov eax, ebx |
ret ; at last, exit |
.error: |
xor eax, eax |
ret |
.copy_all_bytes: |
xor esi, esi |
mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero) |
call .start_copy |
lea ecx, [ebx + SOCKET.lock] |
mov ebx, eax |
call mutex_unlock |
mov eax, ebx |
ret |
.start_copy: |
mov edi, ecx |
mov esi, ebx |
add esi, SOCKET.rxData ; we dont need to copy the header |
mov ecx, eax ; eax is count of bytes |
push ecx |
shr ecx, 2 ; divide eax by 4 |
cld ; copy all full dwords |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb ; copy the rest bytes |
retn ; exit, or go back to shift remaining bytes if any |
endp |
;; [53.4] Send data through DGRAM socket |
; |
; @param EBX is socket number |
; @param ECX is application data size (number of bytes to send) |
; @param EDX is pointer to application data buffer |
; @return 0 (sent successfully) or -1 (error) in EAX |
;; |
proc socket_write stdcall |
; DEBUGF 1, "socket_write(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx ; get real socket address |
or eax, eax |
jz .error |
mov ebx, eax |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .error |
; Save the queue entry number |
push eax |
; save the pointers to the data buffer & size |
push edx |
push ecx |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov edx, eax |
; So, ebx holds the socket ptr, edx holds the IPbuffer ptr |
; Fill in the IP header (some data is in the socket descriptor) |
mov eax, [ebx + SOCKET.LocalIP] |
mov [edx + IP_PACKET.SourceAddress], eax |
mov eax, [ebx + SOCKET.RemoteIP] |
mov [edx + IP_PACKET.DestinationAddress], eax |
mov [edx + IP_PACKET.VersionAndIHL], 0x45 |
mov [edx + IP_PACKET.TypeOfService], 0 |
pop eax ; Get the UDP data length |
push eax |
add eax, 20 + 8 ; add IP header and UDP header lengths |
xchg al, ah |
mov [edx + IP_PACKET.TotalLength], ax |
xor eax, eax |
mov [edx + IP_PACKET.Identification], ax |
mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 |
mov [edx + IP_PACKET.TimeToLive], 0x20 |
mov [edx + IP_PACKET.Protocol], PROTOCOL_UDP |
; Checksum left unfilled |
mov [edx + IP_PACKET.HeaderChecksum], ax |
; Fill in the UDP header (some data is in the socket descriptor) |
mov ax, [ebx + SOCKET.LocalPort] |
mov [edx + 20 + UDP_PACKET.SourcePort], ax |
mov ax, [ebx + SOCKET.RemotePort] |
mov [edx + 20 + UDP_PACKET.DestinationPort], ax |
pop eax |
push eax |
add eax, 8 |
xchg al, ah |
mov [edx + 20 + UDP_PACKET.Length], ax |
; Checksum left unfilled |
xor eax, eax |
mov [edx + 20 + UDP_PACKET.Checksum], ax |
pop ecx ; count of bytes to send |
mov ebx, ecx ; need the length later |
pop eax ; get callers ptr to data to send |
; Get the address of the callers data |
mov edi, [TASK_BASE] |
add edi, TASKDATA.mem_start |
add eax, [edi] |
mov esi, eax |
mov edi, edx |
add edi, 28 |
cld |
rep movsb ; copy the data across |
; we have edx as IPbuffer ptr. |
; Fill in the UDP checksum |
; First, fill in pseudoheader |
mov eax, [edx + IP_PACKET.SourceAddress] |
mov [pseudoHeader], eax |
mov eax, [edx + IP_PACKET.DestinationAddress] |
mov [pseudoHeader + 4], eax |
mov word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0 ; 0 + protocol |
add ebx, 8 |
mov eax, ebx |
xchg al, ah |
mov [pseudoHeader + 10], ax |
mov eax, pseudoHeader |
mov [checkAdd1], eax |
mov [checkSize1], word 12 |
mov eax, edx |
add eax, 20 |
mov [checkAdd2], eax |
mov eax, ebx |
mov [checkSize2], ax ; was eax!! mjh 8/7/02 |
call checksum |
; store it in the UDP checksum ( in the correct order! ) |
mov ax, [checkResult] |
; If the UDP checksum computes to 0, we must make it 0xffff |
; (0 is reserved for 'not used') |
test ax, ax |
jnz @f |
mov ax, 0xffff |
@@: |
xchg al, ah |
mov [edx + 20 + UDP_PACKET.Checksum], ax |
; Fill in the IP header checksum |
GET_IHL ecx,edx ; get IP-Header length |
stdcall checksum_jb, edx, ecx; buf_ptr, buf_size |
xchg al, ah |
mov [edx + IP_PACKET.HeaderChecksum], ax |
; Check destination IP address. |
; If it is the local host IP, route it back to IP_RX |
pop ebx |
mov eax, NET1OUT_QUEUE |
mov ecx, [edx + SOCKET.RemoteIP] |
mov edx, [stack_ip] |
cmp edx, ecx |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
call queue |
xor eax, eax |
ret |
.error: |
or eax, -1 |
ret |
endp |
;; [53.7] Send data through STREAM socket |
; |
; @param EBX is socket number |
; @param ECX is application data size (number of bytes to send) |
; @param EDX is pointer to application data buffer |
; @return 0 (sent successfully) or -1 (error) in EAX |
;; |
proc socket_write_tcp stdcall |
local sockAddr dd ? |
; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
mov ebx, eax |
mov [sockAddr], ebx |
; If the sockets window timer is nonzero, do not queue packet |
cmp [ebx + SOCKET.wndsizeTimer], 0 |
jne .error |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .error |
push eax |
; Get the address of the callers data |
mov edi, [TASK_BASE] |
add edi, TASKDATA.mem_start |
add edx, [edi] |
mov esi, edx |
pop eax |
push eax |
push ecx |
mov bl, TH_ACK |
stdcall build_tcp_packet, [sockAddr] |
pop ecx |
; Check destination IP address. |
; If it is the local host IP, route it back to IP_RX |
pop ebx |
push ecx |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
pop ecx |
push ebx ; save ipbuffer number |
call queue |
mov esi, [sockAddr] |
; increament SND.NXT in socket |
; Amount to increment by is in ecx |
add esi, SOCKET.SND_NXT |
call add_inet_esi |
pop ebx |
; Copy the IP buffer to a resend queue |
; If there isn't one, dont worry about it for now |
mov esi, resendQ |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .exit ; None found |
cmp dword[esi + 4], 0 |
je @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: |
push ebx |
; OK, we have a buffer descriptor ptr in esi. |
; resend entry # in ecx |
; Populate it |
; socket # |
; retries count |
; retry time |
; fill IP buffer associated with this descriptor |
stdcall net_socket_addr_to_num, [sockAddr] |
mov [esi + 4], eax |
mov byte[esi + 1], TCP_RETRIES |
mov word[esi + 2], TCP_TIMEOUT |
inc ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
mov edi, resendBuffer - IPBUFFSIZE |
@@: |
add edi, IPBUFFSIZE |
loop @b |
; we have dest buffer location in edi |
pop eax |
; convert source buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov esi, eax |
; do copy |
mov ecx, IPBUFFSIZE |
cld |
rep movsb |
.exit: |
xor eax, eax |
ret |
.error: |
or eax, -1 |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/stack.inc |
---|
1,908 → 1,912 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; STACK.INC ;; |
;; ;; |
;; TCP/IP stack for Menuet OS ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; Version 0.7 ;; |
;; Added a timer per socket to allow delays when rx window ;; |
;; gets below 1KB ;; |
;; ;; |
;;10.01.2007 Bugfix for checksum function from Paolo Franchetti ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************* |
; Interface |
; The interfaces defined in ETHERNET.INC plus: |
; stack_init |
; stack_handler |
; app_stack_handler |
; app_socket_handler |
; checksum |
; |
;******************************************************************* |
uglobal |
StackCounters: |
dumped_rx_count dd 0 |
arp_tx_count: dd 0 |
arp_rx_count: dd 0 |
ip_rx_count: dd 0 |
ip_tx_count: dd 0 |
endg |
; socket buffers |
SOCKETBUFFSIZE equ 4096 ; state + config + buffer. |
SOCKETHEADERSIZE equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data |
;NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 |
; IPBUFF status values |
BUFF_EMPTY equ 0 |
BUFF_RX_FULL equ 1 |
BUFF_ALLOCATED equ 2 |
BUFF_TX_FULL equ 3 |
NUM_IPBUFFERS equ 20 ; buffers allocated for TX/RX |
NUMQUEUES equ 4 |
EMPTY_QUEUE equ 0 |
IPIN_QUEUE equ 1 |
IPOUT_QUEUE equ 2 |
NET1OUT_QUEUE equ 3 |
NO_BUFFER equ 0xFFFF |
IPBUFFSIZE equ 1500 ; MTU of an ethernet packet |
NUMQUEUEENTRIES equ NUM_IPBUFFERS |
NUMRESENDENTRIES equ 18 ; Buffers for TCP resend packets |
; These are the 0x40 function codes for application access to the stack |
STACK_DRIVER_STATUS equ 52 |
SOCKET_INTERFACE equ 53 |
; 128KB allocated for the stack and network driver buffers and other |
; data requirements |
;stack_data_start equ 0x700000 |
;eth_data_start equ 0x700000 |
;stack_data equ 0x704000 |
;stack_data_end equ 0x71ffff |
; 32 bit word |
stack_config equ stack_data |
; 32 bit word - IP Address in network format |
stack_ip equ stack_data + 4 |
; 1 byte. 0 == inactive, 1 = active |
ethernet_active equ stack_data + 9 |
; TODO :: empty memory area |
; Address of selected socket |
;sktAddr equ stack_data + 32 |
; Parameter to checksum routine - data ptr |
checkAdd1 equ stack_data + 36 |
; Parameter to checksum routine - 2nd data ptr |
checkAdd2 equ stack_data + 40 |
; Parameter to checksum routine - data size |
checkSize1 equ stack_data + 44 |
; Parameter to checksum routine - 2nd data size |
checkSize2 equ stack_data + 46 |
; result of checksum routine |
checkResult equ stack_data + 48 |
; holds the TCP/UDP pseudo header. SA|DA|0|prot|UDP len| |
pseudoHeader equ stack_data + 50 |
; receive and transmit IP buffer allocation |
;sockets equ stack_data + 62 |
Next_free2 equ stack_data + 62;Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) |
; 1560 byte buffer for rx / tx ethernet packets |
Ether_buffer equ Next_free2 |
Next_free3 equ Ether_buffer + 1518 |
last_1sTick equ Next_free3 |
IPbuffs equ Next_free3 + 1 |
queues equ IPbuffs + ( NUM_IPBUFFERS * IPBUFFSIZE ) |
queueList equ queues + (2 * NUMQUEUES) |
last_1hsTick equ queueList + ( 2 * NUMQUEUEENTRIES ) |
;resendQ equ queueList + ( 2 * NUMQUEUEENTRIES ) |
;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP |
; equ resendBuffer + ( IPBUFFSIZE * NUMRESENDENTRIES ) |
;resendQ equ 0x770000 |
;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP ; XTODO: validate size |
resendBuffer equ resendQ + ( 8 * NUMRESENDENTRIES ) ; for TCP |
uglobal |
net_sockets rd 2 |
endg |
; simple macro for memory set operation |
macro _memset_dw adr,value,amount |
{ |
mov edi, adr |
mov ecx, amount |
if value = 0 |
xor eax, eax |
else |
mov eax, value |
end if |
cld |
rep stosd |
} |
; Below, the main network layer source code is included |
; |
include "queue.inc" |
include "eth_drv/ethernet.inc" |
include "ip.inc" |
include "socket.inc" |
;*************************************************************************** |
; Function |
; stack_init |
; |
; Description |
; Clear all allocated memory to zero. This ensures that |
; on startup, the stack is inactive, and consumes no resources |
; This is a kernel function, called prior to the OS main loop |
; in set_variables |
; |
;*************************************************************************** |
stack_init: |
; Init two address spaces with default values |
_memset_dw stack_data_start, 0, 0x20000/4 |
_memset_dw resendQ, 0, NUMRESENDENTRIES * 2 |
mov [net_sockets], 0 |
mov [net_sockets + 4], 0 |
; Queries initialization |
call queueInit |
; The following block sets up the 1s timer |
mov al, 0x0 |
out 0x70, al |
in al, 0x71 |
mov [last_1sTick], al |
ret |
;*************************************************************************** |
; Function |
; stack_handler |
; |
; Description |
; The kernel loop routine for the stack |
; This is a kernel function, called in the main loop |
; |
;*************************************************************************** |
align 4 |
stack_handler: |
call ethernet_driver |
call ip_rx |
; Test for 10ms tick, call tcp timer |
mov eax, [timer_ticks] ;[0xfdf0] |
cmp eax, [last_1hsTick] |
je sh_001 |
mov [last_1hsTick], eax |
call tcp_tx_handler |
sh_001: |
; Test for 1 second event, call 1s timer functions |
mov al, 0x0 ;second |
out 0x70, al |
in al, 0x71 |
cmp al, [last_1sTick] |
je sh_exit |
mov [last_1sTick], al |
stdcall arp_table_manager, ARP_TABLE_TIMER, 0, 0 |
call tcp_tcb_handler |
sh_exit: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; Checksum [by Johnny_B] |
;; IN: |
;; buf_ptr=POINTER to buffer |
;; buf_size=SIZE of buffer |
;; OUT: |
;; AX=16-bit checksum |
;; Saves all used registers |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
proc checksum_jb stdcall uses ebx esi ecx,\ |
buf_ptr:DWORD, buf_size:DWORD |
xor eax, eax |
xor ebx, ebx ;accumulator |
mov esi, dword[buf_ptr] |
mov ecx, dword[buf_size] |
shr ecx, 1 ; ecx=ecx/2 |
jnc @f ; if CF==0 then size is even number |
mov bh, byte[esi + ecx*2] |
@@: |
cld |
.loop: |
lodsw ;eax=word[esi],esi=esi+2 |
xchg ah,al ;cause must be a net byte-order |
add ebx, eax |
loop .loop |
mov eax, ebx |
shr eax, 16 |
add ax, bx |
not ax |
ret |
endp |
;*************************************************************************** |
; Function |
; checksum |
; |
; Description |
; checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult |
; Dont break anything; Most registers are used by the caller |
; This code is derived from the 'C' source, cksum.c, in the book |
; Internetworking with TCP/IP Volume II by D.E. Comer |
; |
;*************************************************************************** |
checksum: |
pusha |
mov eax, [checkAdd1] |
xor edx, edx ; edx is the accumulative checksum |
xor ebx, ebx |
mov cx, [checkSize1] |
shr cx, 1 |
jz cs1_1 |
cs1: |
mov bh, [eax] |
mov bl, [eax + 1] |
add eax, 2 |
add edx, ebx |
loopw cs1 |
cs1_1: |
and word [checkSize1], 0x01 |
jz cs_test2 |
mov bh, [eax] |
xor bl, bl |
add edx, ebx |
cs_test2: |
mov cx, [checkSize2] |
cmp cx, 0 |
jz cs_exit ; Finished if no 2nd buffer |
mov eax, [checkAdd2] |
shr cx, 1 |
jz cs2_1 |
cs2: |
mov bh, [eax] |
mov bl, [eax + 1] |
add eax, 2 |
add edx, ebx |
loopw cs2 |
cs2_1: |
and word [checkSize2], 0x01 |
jz cs_exit |
mov bh, [eax] |
xor bl, bl |
add edx, ebx |
cs_exit: |
mov ebx, edx |
shr ebx, 16 |
and edx, 0xffff |
add edx, ebx |
mov eax, edx |
shr eax, 16 |
add edx, eax |
not dx |
mov [checkResult], dx |
popa |
ret |
;*************************************************************************** |
; Function |
; app_stack_handler |
; |
; Description |
; This is an application service, called by int 0x40, function 52 |
; It provides application access to the network interface layer |
; |
;*************************************************************************** |
iglobal |
align 4 |
f52call: |
dd app_stack_handler.00 |
dd app_stack_handler.01 |
dd app_stack_handler.02 |
dd app_stack_handler.03 |
dd app_stack_handler.fail ;04 |
dd app_stack_handler.fail ;05 |
dd stack_insert_packet ;app_stack_handler.06 |
dd app_stack_handler.fail ;07 |
dd stack_get_packet ;app_stack_handler.08 |
dd app_stack_handler.09 |
dd app_stack_handler.10 |
dd app_stack_handler.11 |
dd app_stack_handler.12 |
dd app_stack_handler.13 |
dd app_stack_handler.14 |
dd app_stack_handler.15 |
endg |
app_stack_handler: |
;in ebx,ecx |
;out eax |
cmp ebx,15 |
ja .fail ;if more than 15 then exit |
jmp dword [f52call+ebx*4] |
.00: |
; Read the configuration word |
mov eax, [stack_config] |
ret |
.01: |
; read the IP address |
mov eax, [stack_ip] |
ret |
.02: |
; write the configuration word |
mov [stack_config], ecx |
; <Slip shouldn't be active anyway - thats an operational issue.> |
; If ethernet now enabled, probe for the card, reset it and empty |
; the packet buffer |
; If all successfull, enable the card. |
; If ethernet now disabled, set it as disabled. Should really |
; empty the tcpip data area too. |
; ethernet interface is '3' in ls 7 bits |
and cl, 0x7f |
cmp cl, 3 |
je ash_eth_enable |
; Ethernet isn't enabled, so make sure that the card is disabled |
mov [ethernet_active], byte 0 |
ret |
.03: |
; write the IP Address |
mov [stack_ip], ecx |
ret |
;old functions was deleted |
;.06: |
; Insert an IP packet into the stacks received packet queue |
; call stack_insert_packet |
; ret |
; Test for any packets queued for transmission over the network |
;.08: |
; call stack_get_packet |
; Extract a packet queued for transmission by the network |
; ret |
.09: |
; read the gateway IP address |
mov eax, [gateway_ip] |
ret |
.10: |
; read the subnet mask |
mov eax, [subnet_mask] |
ret |
.11: |
; write the gateway IP Address |
mov [gateway_ip], ecx |
ret |
.12: |
; write the subnet mask |
mov [subnet_mask], ecx |
ret |
.13: |
; read the dns |
mov eax, [dns_ip] |
ret |
.14: |
; write the dns IP Address |
mov [dns_ip], ecx |
ret |
.15: |
;<added by Frank Sommer> |
; in ecx we need 4 to read the last 2 bytes |
; or we need 0 to read the first 4 bytes |
cmp ecx,4 |
ja .param_error |
; read MAC, returned (in mirrored byte order) in eax |
mov eax, [node_addr + ecx] |
ret |
.param_error: |
or eax, -1 ; params not accepted |
ret |
.16: |
; 0 -> arp_probe |
; 1 -> arp_announce |
; 2 -> arp_responce (not supported yet) |
test ecx,ecx |
je a_probe |
dec ebx |
jz a_ann ; arp announce |
.fail: |
or eax, -1 |
ret |
; cmp ebx,2 |
; jne a_resp ; arp response |
; arp probe, sender IP must be set to 0.0.0.0, target IP is set to address being probed |
; ecx: pointer to target MAC, MAC should set to 0 by application |
; edx: target IP |
a_probe: |
push dword [stack_ip] |
mov edx, [stack_ip] |
and [stack_ip], dword 0 |
mov esi, ecx ; pointer to target MAC address |
call arp_request |
pop dword [stack_ip] |
ret |
; arp announce, sender IP must be set to target IP |
; ecx: pointer to target MAC |
a_ann: |
mov edx, [stack_ip] |
mov esi, ecx ; pointer to target MAC address |
call arp_request |
ret |
.17: |
;</added by Frank Sommer> |
; modified by [smb] |
;<added by Johnny_B> |
; ARPTable manager interface |
;see "proc arp_table_manager" for more details |
stdcall arp_table_manager,ecx,edx,esi ;Opcode,Index,Extra |
ret |
;</added by Johnny_B> |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
ash_eth_enable: |
; Probe for the card. This will reset it and enable the interface |
; if found |
call eth_probe |
test eax,eax |
jz ash_eth_done ; Abort if no hardware found |
mov [ethernet_active], byte 1 |
ash_eth_done: |
ret |
;*************************************************************************** |
; Function |
; app_socket_handler |
; |
; Description |
; This is an application service, called by int 0x40, function 53 |
; It provides application access to stack socket services |
; such as opening sockets |
; |
;*************************************************************************** |
iglobal |
align 4 |
f53call: |
dd socket_open ;00 |
dd socket_close ;01 |
dd socket_poll ;02 |
dd socket_read ;03 |
dd socket_write ;04 |
dd socket_open_tcp ;05 |
dd socket_status ;06 |
dd socket_write_tcp ;07 |
dd socket_close_tcp ;08 |
dd is_localport_unused ;09 |
dd app_socket_handler.10 |
dd socket_read_packet ;11 |
endg |
app_socket_handler: |
;in ebx,ecx,edx,wsi |
;out eax |
cmp eax,255 |
je stack_internal_status |
cmp eax,11 |
ja .fail ;if more than 15 then exit |
jmp dword [f53call+eax*4] |
.10: |
mov eax,dword[drvr_cable] |
test eax,eax |
jnz @f ; if function is not implented, return -1 |
or al,-1 |
ret |
@@: |
jmp dword[drvr_cable] |
.fail: |
or eax,-1 |
ret |
uglobal |
ARPTmp: |
times 14 db 0 |
endg |
;*************************************************************************** |
; Function |
; stack_internal_status |
; |
; Description |
; Returns information about the internal status of the stack |
; This is only useful for debugging |
; It works with the ethernet driver |
; sub function in ebx |
; return requested data in eax |
; |
;*************************************************************************** |
; This sub function allows access to debugging information on the stack |
; ecx holds the request: |
; 100 : return length of empty queue |
; 101 : return length of IPOUT QUEUE |
; 102 : return length of IPIN QUEUE |
; 103 : return length of NET1OUT QUEUE |
; 200 : return # of ARP entries |
; 201 : return size of ARP table ( max # entries ) |
; 202 : select ARP table entry # |
; 203 : return IP of selected table entry |
; 204 : return High 4 bytes of MAC address of selected table entry |
; 205 : return low 2 bytes of MAC address of selected table entry |
; 206 : return status word of selected table entry |
; 207 : return Time to live of selected table entry |
; 2 : return number of IP packets received |
; 3 : return number of packets transmitted |
; 4 : return number of received packets dumped |
; 5 : return number of arp packets received |
; 6 : return status of packet driver |
; ( 0 == not active, FFFFFFFF = successful ) |
stack_internal_status: |
cmp ebx, 100 |
jnz notsis100 |
; 100 : return length of EMPTY QUEUE |
mov ebx, EMPTY_QUEUE |
call queueSize |
ret |
notsis100: |
cmp ebx, 101 |
jnz notsis101 |
; 101 : return length of IPOUT QUEUE |
mov ebx, IPOUT_QUEUE |
call queueSize |
ret |
notsis101: |
cmp ebx, 102 |
jnz notsis102 |
; 102 : return length of IPIN QUEUE |
mov ebx, IPIN_QUEUE |
call queueSize |
ret |
notsis102: |
cmp ebx, 103 |
jnz notsis103 |
; 103 : return length of NET1OUT QUEUE |
mov ebx, NET1OUT_QUEUE |
call queueSize |
ret |
notsis103: |
cmp ebx, 200 |
jnz notsis200 |
; 200 : return num entries in arp table |
movzx eax, byte [NumARP] |
ret |
notsis200: |
cmp ebx, 201 |
jnz notsis201 |
; 201 : return arp table size |
mov eax, 20 ; ARP_TABLE_SIZE |
ret |
notsis201: |
cmp ebx, 202 |
jnz notsis202 |
; 202 - read the requested table entry |
; into a temporary buffer |
; ecx holds the entry number |
mov eax, ecx |
mov ecx, 14 ; ARP_ENTRY_SIZE |
mul ecx |
mov ecx, [eax + ARPTable] |
mov [ARPTmp], ecx |
mov ecx, [eax + ARPTable+4] |
mov [ARPTmp+4], ecx |
mov ecx, [eax + ARPTable+8] |
mov [ARPTmp+8], ecx |
mov cx, [eax + ARPTable+12] |
mov [ARPTmp+12], cx |
ret |
notsis202: |
cmp ebx, 203 |
jnz notsis203 |
; 203 - return IP address |
mov eax, [ARPTmp] |
ret |
notsis203: |
cmp ebx, 204 |
jnz notsis204 |
; 204 - return MAC high dword |
mov eax, [ARPTmp+4] |
ret |
notsis204: |
cmp ebx, 205 |
jnz notsis205 |
; 205 - return MAC ls word |
movzx eax, word [ARPTmp+8] |
ret |
notsis205: |
cmp ebx, 206 |
jnz notsis206 |
; 206 - return status word |
movzx eax, word [ARPTmp+10] |
ret |
notsis206: |
cmp ebx, 207 |
jnz notsis207 |
; 207 - return ttl word |
movzx eax, word [ARPTmp+12] |
ret |
notsis207: |
cmp ebx, 2 |
jnz notsis2 |
; 2 : return number of IP packets received |
mov eax, [ip_rx_count] |
ret |
notsis2: |
cmp ebx, 3 |
jnz notsis3 |
; 3 : return number of packets transmitted |
mov eax, [ip_tx_count] |
ret |
notsis3: |
cmp ebx, 4 |
jnz notsis4 |
; 4 : return number of received packets dumped |
mov eax, [dumped_rx_count] |
ret |
notsis4: |
cmp ebx, 5 |
jnz notsis5 |
; 5 : return number of arp packets received |
mov eax, [arp_rx_count] |
ret |
notsis5: |
cmp ebx, 6 |
jnz notsis6 |
; 6 : return status of packet driver |
; ( 0 == not active, FFFFFFFF = successful ) |
mov eax, [eth_status] |
ret |
notsis6: |
xor eax, eax |
ret |
;*************************************************************************** |
; Function |
; stack_get_packet |
; |
; Description |
; extracts an IP packet from the NET1 output queue |
; and sends the data to the calling process |
; pointer to data in edx |
; returns number of bytes read in eax |
; |
;*************************************************************************** |
stack_get_packet: |
; Look for a buffer to tx |
mov eax, NET1OUT_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je sgp_non_exit ; Exit if no buffer available |
push eax ; Save buffer number for freeing at end |
push edx |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
pop edx |
push eax ; save address of IP data |
; Get the address of the callers data |
mov edi,[TASK_BASE] |
add edi,TASKDATA.mem_start |
add edx,[edi] |
mov edi, edx |
pop eax |
mov ecx, 1500 ; should get the actual number of bytes to write |
mov esi, eax |
cld |
rep movsb ; copy the data across |
; And finally, return the buffer to the free queue |
pop eax |
call freeBuff |
mov eax, 1500 |
ret |
sgp_non_exit: |
xor eax, eax |
ret |
;*************************************************************************** |
; Function |
; stack_insert_packet |
; |
; Description |
; writes an IP packet into the stacks receive queue |
; # of bytes to write in ecx |
; pointer to data in edx |
; returns 0 in eax ok, -1 == failed |
; |
;*************************************************************************** |
stack_insert_packet: |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je sip_err_exit |
push eax |
; save the pointers to the data buffer & size |
push edx |
push ecx |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov edx, eax |
; So, edx holds the IPbuffer ptr |
pop ecx ; count of bytes to send |
mov ebx, ecx ; need the length later |
pop eax ; get callers ptr to data to send |
; Get the address of the callers data |
mov edi,[TASK_BASE] |
add edi,TASKDATA.mem_start |
add eax,[edi] |
mov esi, eax |
mov edi, edx |
cld |
rep movsb ; copy the data across |
pop ebx |
mov eax, IPIN_QUEUE |
call queue |
inc dword [ip_rx_count] |
mov eax, 0 |
ret |
sip_err_exit: |
mov eax, 0xFFFFFFFF |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; STACK.INC ;; |
;; ;; |
;; TCP/IP stack for Menuet OS ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; Version 0.7 ;; |
;; Added a timer per socket to allow delays when rx window ;; |
;; gets below 1KB ;; |
;; ;; |
;;10.01.2007 Bugfix for checksum function from Paolo Franchetti ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************* |
; Interface |
; The interfaces defined in ETHERNET.INC plus: |
; stack_init |
; stack_handler |
; app_stack_handler |
; app_socket_handler |
; checksum |
; |
;******************************************************************* |
uglobal |
StackCounters: |
dumped_rx_count dd 0 |
arp_tx_count: |
dd 0 |
arp_rx_count: |
dd 0 |
ip_rx_count: |
dd 0 |
ip_tx_count: |
dd 0 |
endg |
; socket buffers |
SOCKETBUFFSIZE equ 4096 ; state + config + buffer. |
SOCKETHEADERSIZE equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data |
;NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 |
; IPBUFF status values |
BUFF_EMPTY equ 0 |
BUFF_RX_FULL equ 1 |
BUFF_ALLOCATED equ 2 |
BUFF_TX_FULL equ 3 |
NUM_IPBUFFERS equ 20 ; buffers allocated for TX/RX |
NUMQUEUES equ 4 |
EMPTY_QUEUE equ 0 |
IPIN_QUEUE equ 1 |
IPOUT_QUEUE equ 2 |
NET1OUT_QUEUE equ 3 |
NO_BUFFER equ 0xFFFF |
IPBUFFSIZE equ 1500 ; MTU of an ethernet packet |
NUMQUEUEENTRIES equ NUM_IPBUFFERS |
NUMRESENDENTRIES equ 18 ; Buffers for TCP resend packets |
; These are the 0x40 function codes for application access to the stack |
STACK_DRIVER_STATUS equ 52 |
SOCKET_INTERFACE equ 53 |
; 128KB allocated for the stack and network driver buffers and other |
; data requirements |
;stack_data_start equ 0x700000 |
;eth_data_start equ 0x700000 |
;stack_data equ 0x704000 |
;stack_data_end equ 0x71ffff |
; 32 bit word |
stack_config equ stack_data |
; 32 bit word - IP Address in network format |
stack_ip equ stack_data + 4 |
; 1 byte. 0 == inactive, 1 = active |
ethernet_active equ stack_data + 9 |
; TODO :: empty memory area |
; Address of selected socket |
;sktAddr equ stack_data + 32 |
; Parameter to checksum routine - data ptr |
checkAdd1 equ stack_data + 36 |
; Parameter to checksum routine - 2nd data ptr |
checkAdd2 equ stack_data + 40 |
; Parameter to checksum routine - data size |
checkSize1 equ stack_data + 44 |
; Parameter to checksum routine - 2nd data size |
checkSize2 equ stack_data + 46 |
; result of checksum routine |
checkResult equ stack_data + 48 |
; holds the TCP/UDP pseudo header. SA|DA|0|prot|UDP len| |
pseudoHeader equ stack_data + 50 |
; receive and transmit IP buffer allocation |
;sockets equ stack_data + 62 |
Next_free2 equ stack_data + 62;Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) |
; 1560 byte buffer for rx / tx ethernet packets |
Ether_buffer equ Next_free2 |
Next_free3 equ Ether_buffer + 1518 |
last_1sTick equ Next_free3 |
IPbuffs equ Next_free3 + 1 |
queues equ IPbuffs + ( NUM_IPBUFFERS * IPBUFFSIZE ) |
queueList equ queues + (2 * NUMQUEUES) |
last_1hsTick equ queueList + ( 2 * NUMQUEUEENTRIES ) |
;resendQ equ queueList + ( 2 * NUMQUEUEENTRIES ) |
;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP |
; equ resendBuffer + ( IPBUFFSIZE * NUMRESENDENTRIES ) |
;resendQ equ 0x770000 |
;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP ; XTODO: validate size |
resendBuffer equ resendQ + ( 8 * NUMRESENDENTRIES ) ; for TCP |
uglobal |
net_sockets rd 2 |
endg |
; simple macro for memory set operation |
macro _memset_dw adr,value,amount |
{ |
mov edi, adr |
mov ecx, amount |
if value = 0 |
xor eax, eax |
else |
mov eax, value |
end if |
cld |
rep stosd |
} |
; Below, the main network layer source code is included |
; |
include "queue.inc" |
include "eth_drv/ethernet.inc" |
include "ip.inc" |
include "socket.inc" |
;*************************************************************************** |
; Function |
; stack_init |
; |
; Description |
; Clear all allocated memory to zero. This ensures that |
; on startup, the stack is inactive, and consumes no resources |
; This is a kernel function, called prior to the OS main loop |
; in set_variables |
; |
;*************************************************************************** |
stack_init: |
; Init two address spaces with default values |
_memset_dw stack_data_start, 0, 0x20000/4 |
_memset_dw resendQ, 0, NUMRESENDENTRIES * 2 |
mov [net_sockets], 0 |
mov [net_sockets + 4], 0 |
; Queries initialization |
call queueInit |
; The following block sets up the 1s timer |
mov al, 0x0 |
out 0x70, al |
in al, 0x71 |
mov [last_1sTick], al |
ret |
;*************************************************************************** |
; Function |
; stack_handler |
; |
; Description |
; The kernel loop routine for the stack |
; This is a kernel function, called in the main loop |
; |
;*************************************************************************** |
align 4 |
stack_handler: |
call ethernet_driver |
call ip_rx |
; Test for 10ms tick, call tcp timer |
mov eax, [timer_ticks];[0xfdf0] |
cmp eax, [last_1hsTick] |
je sh_001 |
mov [last_1hsTick], eax |
call tcp_tx_handler |
sh_001: |
; Test for 1 second event, call 1s timer functions |
mov al, 0x0;second |
out 0x70, al |
in al, 0x71 |
cmp al, [last_1sTick] |
je sh_exit |
mov [last_1sTick], al |
stdcall arp_table_manager, ARP_TABLE_TIMER, 0, 0 |
call tcp_tcb_handler |
sh_exit: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; Checksum [by Johnny_B] |
;; IN: |
;; buf_ptr=POINTER to buffer |
;; buf_size=SIZE of buffer |
;; OUT: |
;; AX=16-bit checksum |
;; Saves all used registers |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
proc checksum_jb stdcall uses ebx esi ecx,\ |
buf_ptr:DWORD, buf_size:DWORD |
xor eax, eax |
xor ebx, ebx;accumulator |
mov esi, dword[buf_ptr] |
mov ecx, dword[buf_size] |
shr ecx, 1; ecx=ecx/2 |
jnc @f ; if CF==0 then size is even number |
mov bh, byte[esi + ecx*2] |
@@: |
cld |
.loop: |
lodsw ;eax=word[esi],esi=esi+2 |
xchg ah, al;cause must be a net byte-order |
add ebx, eax |
loop .loop |
mov eax, ebx |
shr eax, 16 |
add ax, bx |
not ax |
ret |
endp |
;*************************************************************************** |
; Function |
; checksum |
; |
; Description |
; checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult |
; Dont break anything; Most registers are used by the caller |
; This code is derived from the 'C' source, cksum.c, in the book |
; Internetworking with TCP/IP Volume II by D.E. Comer |
; |
;*************************************************************************** |
checksum: |
pusha |
mov eax, [checkAdd1] |
xor edx, edx ; edx is the accumulative checksum |
xor ebx, ebx |
mov cx, [checkSize1] |
shr cx, 1 |
jz cs1_1 |
cs1: |
mov bh, [eax] |
mov bl, [eax + 1] |
add eax, 2 |
add edx, ebx |
loopw cs1 |
cs1_1: |
and word [checkSize1], 0x01 |
jz cs_test2 |
mov bh, [eax] |
xor bl, bl |
add edx, ebx |
cs_test2: |
mov cx, [checkSize2] |
cmp cx, 0 |
jz cs_exit ; Finished if no 2nd buffer |
mov eax, [checkAdd2] |
shr cx, 1 |
jz cs2_1 |
cs2: |
mov bh, [eax] |
mov bl, [eax + 1] |
add eax, 2 |
add edx, ebx |
loopw cs2 |
cs2_1: |
and word [checkSize2], 0x01 |
jz cs_exit |
mov bh, [eax] |
xor bl, bl |
add edx, ebx |
cs_exit: |
mov ebx, edx |
shr ebx, 16 |
and edx, 0xffff |
add edx, ebx |
mov eax, edx |
shr eax, 16 |
add edx, eax |
not dx |
mov [checkResult], dx |
popa |
ret |
;*************************************************************************** |
; Function |
; app_stack_handler |
; |
; Description |
; This is an application service, called by int 0x40, function 52 |
; It provides application access to the network interface layer |
; |
;*************************************************************************** |
iglobal |
align 4 |
f52call: |
dd app_stack_handler.00 |
dd app_stack_handler.01 |
dd app_stack_handler.02 |
dd app_stack_handler.03 |
dd app_stack_handler.fail ;04 |
dd app_stack_handler.fail ;05 |
dd stack_insert_packet ;app_stack_handler.06 |
dd app_stack_handler.fail ;07 |
dd stack_get_packet ;app_stack_handler.08 |
dd app_stack_handler.09 |
dd app_stack_handler.10 |
dd app_stack_handler.11 |
dd app_stack_handler.12 |
dd app_stack_handler.13 |
dd app_stack_handler.14 |
dd app_stack_handler.15 |
endg |
app_stack_handler: |
;in ebx,ecx |
;out eax |
cmp ebx, 15 |
ja .fail ;if more than 15 then exit |
jmp dword [f52call+ebx*4] |
.00: |
; Read the configuration word |
mov eax, [stack_config] |
ret |
.01: |
; read the IP address |
mov eax, [stack_ip] |
ret |
.02: |
; write the configuration word |
mov [stack_config], ecx |
; <Slip shouldn't be active anyway - thats an operational issue.> |
; If ethernet now enabled, probe for the card, reset it and empty |
; the packet buffer |
; If all successfull, enable the card. |
; If ethernet now disabled, set it as disabled. Should really |
; empty the tcpip data area too. |
; ethernet interface is '3' in ls 7 bits |
and cl, 0x7f |
cmp cl, 3 |
je ash_eth_enable |
; Ethernet isn't enabled, so make sure that the card is disabled |
mov [ethernet_active], byte 0 |
ret |
.03: |
; write the IP Address |
mov [stack_ip], ecx |
ret |
;old functions was deleted |
;.06: |
; Insert an IP packet into the stacks received packet queue |
; call stack_insert_packet |
; ret |
; Test for any packets queued for transmission over the network |
;.08: |
; call stack_get_packet |
; Extract a packet queued for transmission by the network |
; ret |
.09: |
; read the gateway IP address |
mov eax, [gateway_ip] |
ret |
.10: |
; read the subnet mask |
mov eax, [subnet_mask] |
ret |
.11: |
; write the gateway IP Address |
mov [gateway_ip], ecx |
ret |
.12: |
; write the subnet mask |
mov [subnet_mask], ecx |
ret |
.13: |
; read the dns |
mov eax, [dns_ip] |
ret |
.14: |
; write the dns IP Address |
mov [dns_ip], ecx |
ret |
.15: |
;<added by Frank Sommer> |
; in ecx we need 4 to read the last 2 bytes |
; or we need 0 to read the first 4 bytes |
cmp ecx, 4 |
ja .param_error |
; read MAC, returned (in mirrored byte order) in eax |
mov eax, [node_addr + ecx] |
ret |
.param_error: |
or eax, -1 ; params not accepted |
ret |
.16: |
; 0 -> arp_probe |
; 1 -> arp_announce |
; 2 -> arp_responce (not supported yet) |
test ecx, ecx |
je a_probe |
dec ebx |
jz a_ann ; arp announce |
.fail: |
or eax, -1 |
ret |
; cmp ebx,2 |
; jne a_resp ; arp response |
; arp probe, sender IP must be set to 0.0.0.0, target IP is set to address being probed |
; ecx: pointer to target MAC, MAC should set to 0 by application |
; edx: target IP |
a_probe: |
push dword [stack_ip] |
mov edx, [stack_ip] |
and [stack_ip], dword 0 |
mov esi, ecx ; pointer to target MAC address |
call arp_request |
pop dword [stack_ip] |
ret |
; arp announce, sender IP must be set to target IP |
; ecx: pointer to target MAC |
a_ann: |
mov edx, [stack_ip] |
mov esi, ecx ; pointer to target MAC address |
call arp_request |
ret |
.17: |
;</added by Frank Sommer> |
; modified by [smb] |
;<added by Johnny_B> |
; ARPTable manager interface |
;see "proc arp_table_manager" for more details |
stdcall arp_table_manager, ecx, edx, esi;Opcode,Index,Extra |
ret |
;</added by Johnny_B> |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
ash_eth_enable: |
; Probe for the card. This will reset it and enable the interface |
; if found |
call eth_probe |
test eax, eax |
jz ash_eth_done ; Abort if no hardware found |
mov [ethernet_active], byte 1 |
ash_eth_done: |
ret |
;*************************************************************************** |
; Function |
; app_socket_handler |
; |
; Description |
; This is an application service, called by int 0x40, function 53 |
; It provides application access to stack socket services |
; such as opening sockets |
; |
;*************************************************************************** |
iglobal |
align 4 |
f53call: |
dd socket_open ;00 |
dd socket_close ;01 |
dd socket_poll ;02 |
dd socket_read ;03 |
dd socket_write ;04 |
dd socket_open_tcp ;05 |
dd socket_status ;06 |
dd socket_write_tcp ;07 |
dd socket_close_tcp ;08 |
dd is_localport_unused ;09 |
dd app_socket_handler.10 |
dd socket_read_packet ;11 |
endg |
app_socket_handler: |
;in ebx,ecx,edx,wsi |
;out eax |
cmp eax, 255 |
je stack_internal_status |
cmp eax, 11 |
ja .fail ;if more than 15 then exit |
jmp dword [f53call+eax*4] |
.10: |
mov eax, dword[drvr_cable] |
test eax, eax |
jnz @f ; if function is not implented, return -1 |
or al, -1 |
ret |
@@: |
jmp dword[drvr_cable] |
.fail: |
or eax, -1 |
ret |
uglobal |
ARPTmp: |
times 14 db 0 |
endg |
;*************************************************************************** |
; Function |
; stack_internal_status |
; |
; Description |
; Returns information about the internal status of the stack |
; This is only useful for debugging |
; It works with the ethernet driver |
; sub function in ebx |
; return requested data in eax |
; |
;*************************************************************************** |
; This sub function allows access to debugging information on the stack |
; ecx holds the request: |
; 100 : return length of empty queue |
; 101 : return length of IPOUT QUEUE |
; 102 : return length of IPIN QUEUE |
; 103 : return length of NET1OUT QUEUE |
; 200 : return # of ARP entries |
; 201 : return size of ARP table ( max # entries ) |
; 202 : select ARP table entry # |
; 203 : return IP of selected table entry |
; 204 : return High 4 bytes of MAC address of selected table entry |
; 205 : return low 2 bytes of MAC address of selected table entry |
; 206 : return status word of selected table entry |
; 207 : return Time to live of selected table entry |
; 2 : return number of IP packets received |
; 3 : return number of packets transmitted |
; 4 : return number of received packets dumped |
; 5 : return number of arp packets received |
; 6 : return status of packet driver |
; ( 0 == not active, FFFFFFFF = successful ) |
stack_internal_status: |
cmp ebx, 100 |
jnz notsis100 |
; 100 : return length of EMPTY QUEUE |
mov ebx, EMPTY_QUEUE |
call queueSize |
ret |
notsis100: |
cmp ebx, 101 |
jnz notsis101 |
; 101 : return length of IPOUT QUEUE |
mov ebx, IPOUT_QUEUE |
call queueSize |
ret |
notsis101: |
cmp ebx, 102 |
jnz notsis102 |
; 102 : return length of IPIN QUEUE |
mov ebx, IPIN_QUEUE |
call queueSize |
ret |
notsis102: |
cmp ebx, 103 |
jnz notsis103 |
; 103 : return length of NET1OUT QUEUE |
mov ebx, NET1OUT_QUEUE |
call queueSize |
ret |
notsis103: |
cmp ebx, 200 |
jnz notsis200 |
; 200 : return num entries in arp table |
movzx eax, byte [NumARP] |
ret |
notsis200: |
cmp ebx, 201 |
jnz notsis201 |
; 201 : return arp table size |
mov eax, 20; ARP_TABLE_SIZE |
ret |
notsis201: |
cmp ebx, 202 |
jnz notsis202 |
; 202 - read the requested table entry |
; into a temporary buffer |
; ecx holds the entry number |
mov eax, ecx |
mov ecx, 14; ARP_ENTRY_SIZE |
mul ecx |
mov ecx, [eax + ARPTable] |
mov [ARPTmp], ecx |
mov ecx, [eax + ARPTable+4] |
mov [ARPTmp+4], ecx |
mov ecx, [eax + ARPTable+8] |
mov [ARPTmp+8], ecx |
mov cx, [eax + ARPTable+12] |
mov [ARPTmp+12], cx |
ret |
notsis202: |
cmp ebx, 203 |
jnz notsis203 |
; 203 - return IP address |
mov eax, [ARPTmp] |
ret |
notsis203: |
cmp ebx, 204 |
jnz notsis204 |
; 204 - return MAC high dword |
mov eax, [ARPTmp+4] |
ret |
notsis204: |
cmp ebx, 205 |
jnz notsis205 |
; 205 - return MAC ls word |
movzx eax, word [ARPTmp+8] |
ret |
notsis205: |
cmp ebx, 206 |
jnz notsis206 |
; 206 - return status word |
movzx eax, word [ARPTmp+10] |
ret |
notsis206: |
cmp ebx, 207 |
jnz notsis207 |
; 207 - return ttl word |
movzx eax, word [ARPTmp+12] |
ret |
notsis207: |
cmp ebx, 2 |
jnz notsis2 |
; 2 : return number of IP packets received |
mov eax, [ip_rx_count] |
ret |
notsis2: |
cmp ebx, 3 |
jnz notsis3 |
; 3 : return number of packets transmitted |
mov eax, [ip_tx_count] |
ret |
notsis3: |
cmp ebx, 4 |
jnz notsis4 |
; 4 : return number of received packets dumped |
mov eax, [dumped_rx_count] |
ret |
notsis4: |
cmp ebx, 5 |
jnz notsis5 |
; 5 : return number of arp packets received |
mov eax, [arp_rx_count] |
ret |
notsis5: |
cmp ebx, 6 |
jnz notsis6 |
; 6 : return status of packet driver |
; ( 0 == not active, FFFFFFFF = successful ) |
mov eax, [eth_status] |
ret |
notsis6: |
xor eax, eax |
ret |
;*************************************************************************** |
; Function |
; stack_get_packet |
; |
; Description |
; extracts an IP packet from the NET1 output queue |
; and sends the data to the calling process |
; pointer to data in edx |
; returns number of bytes read in eax |
; |
;*************************************************************************** |
stack_get_packet: |
; Look for a buffer to tx |
mov eax, NET1OUT_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je sgp_non_exit ; Exit if no buffer available |
push eax ; Save buffer number for freeing at end |
push edx |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
pop edx |
push eax ; save address of IP data |
; Get the address of the callers data |
mov edi, [TASK_BASE] |
add edi, TASKDATA.mem_start |
add edx, [edi] |
mov edi, edx |
pop eax |
mov ecx, 1500 ; should get the actual number of bytes to write |
mov esi, eax |
cld |
rep movsb ; copy the data across |
; And finally, return the buffer to the free queue |
pop eax |
call freeBuff |
mov eax, 1500 |
ret |
sgp_non_exit: |
xor eax, eax |
ret |
;*************************************************************************** |
; Function |
; stack_insert_packet |
; |
; Description |
; writes an IP packet into the stacks receive queue |
; # of bytes to write in ecx |
; pointer to data in edx |
; returns 0 in eax ok, -1 == failed |
; |
;*************************************************************************** |
stack_insert_packet: |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je sip_err_exit |
push eax |
; save the pointers to the data buffer & size |
push edx |
push ecx |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov edx, eax |
; So, edx holds the IPbuffer ptr |
pop ecx ; count of bytes to send |
mov ebx, ecx ; need the length later |
pop eax ; get callers ptr to data to send |
; Get the address of the callers data |
mov edi, [TASK_BASE] |
add edi, TASKDATA.mem_start |
add eax, [edi] |
mov esi, eax |
mov edi, edx |
cld |
rep movsb ; copy the data across |
pop ebx |
mov eax, IPIN_QUEUE |
call queue |
inc dword [ip_rx_count] |
mov eax, 0 |
ret |
sip_err_exit: |
mov eax, 0xFFFFFFFF |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/tcp.inc |
---|
1,1172 → 1,1176 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; TCP.INC ;; |
;; ;; |
;; TCP Processes for Menuet OS TCP/IP stack ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; v0.6 : Added reset handling in the established state ;; |
;; Added a timer per socket to allow delays when ;; |
;; rx window gets below 1KB ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; TCP TCB states |
TCB_LISTEN equ 1 |
TCB_SYN_SENT equ 2 |
TCB_SYN_RECEIVED equ 3 |
TCB_ESTABLISHED equ 4 |
TCB_FIN_WAIT_1 equ 5 |
TCB_FIN_WAIT_2 equ 6 |
TCB_CLOSE_WAIT equ 7 |
TCB_CLOSING equ 8 |
TCB_LAST_ACK equ 9 |
TCB_TIMED_WAIT equ 10 |
TCB_CLOSED equ 11 |
TH_FIN = 0x01 |
TH_SYN = 0x02 |
TH_RST = 0x04 |
TH_PUSH = 0x08 |
TH_ACK = 0x10 |
TH_URG = 0x20 |
TWOMSL equ 10 ; # of secs to wait before closing socket |
TCP_RETRIES equ 5 ; Number of times to resend a packet |
TCP_TIMEOUT equ 20 ; resend if not replied to in x hs |
;******************************************************************* |
; Interface |
; |
; tcp_tx_handler Handles the TCP transmit queue |
; tcp_rx The protocol handler for received data |
; buildTCPPacket fills in the packet headers and data |
; tcpStateMachine Main state machine for received TCP packets |
; tcp_tcb_handler 1s timer, to erase tcb's in TIME_WAIT state |
; |
;******************************************************************* |
; TCP Payload ( Data field in IP datagram ) |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;20 | Source Port | Destination Port | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;24 | Sequence Number | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;28 | Acknowledgment Number | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;32 | Data | |U|A|P|R|S|F| | |
; | Offset| Reserved |R|C|S|S|Y|I| Window | |
; | | |G|K|H|T|N|N| | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;36 | Checksum | Urgent Pointer | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;40 | Options | Padding | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | data |
struc TCP_PACKET |
{ .SourcePort dw ? ;+00 |
.DestinationPort dw ? ;+02 |
.SequenceNumber dd ? ;+04 |
.AckNumber dd ? ;+08 |
.DataOffset db ? ;+12 - DataOffset[0-3 bits] and Reserved[4-7] |
.Flags db ? ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN |
.Window dw ? ;+14 |
.Checksum dw ? ;+16 |
.UrgentPointer dw ? ;+18 |
.Options rb 3 ;+20 |
.Padding db ? ;+23 |
.Data db ? ;+24 |
} |
virtual at 0 |
TCP_PACKET TCP_PACKET |
end virtual |
;*************************************************************************** |
; Function |
; tcp_tcb_handler |
; |
; Description |
; Handles sockets in the timewait state, closing them |
; when the TCB timer expires |
; |
;*************************************************************************** |
proc tcp_tcb_handler stdcall uses ebx |
; scan through all the sockets, decrementing active timers |
mov ebx, net_sockets |
cmp [ebx + SOCKET.NextPtr], 0 |
je .exit |
;DEBUGF 1, "K : sockets:\n" |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .exit |
;DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] |
cmp [ebx + SOCKET.TCBTimer], 0 |
jne .decrement_tcb |
cmp [ebx + SOCKET.wndsizeTimer], 0 |
jne .decrement_wnd |
jmp .next_socket |
.decrement_tcb: |
; decrement it, delete socket if TCB timer = 0 & socket in timewait state |
dec [ebx + SOCKET.TCBTimer] |
jnz .next_socket |
cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
jne .next_socket |
push [ebx + SOCKET.PrevPtr] |
stdcall net_socket_free, ebx |
pop ebx |
jmp .next_socket |
.decrement_wnd: |
; TODO - prove it works! |
dec [ebx + SOCKET.wndsizeTimer] |
jmp .next_socket |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; tcp_tx_handler |
; |
; Description |
; Handles queued TCP data |
; This is a kernel function, called by stack_handler |
; |
;*************************************************************************** |
proc tcp_tx_handler stdcall |
; decrement all resend buffers timers. If they |
; expire, queue them for sending, and restart the timer. |
; If the retries counter reach 0, delete the entry |
mov esi, resendQ |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .exit ; None left |
cmp dword[esi + 4], 0 |
jne @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: ; we have one. decrement it's timer by 1 |
dec word[esi + 2] |
jz @f |
inc ecx |
add esi, 8 |
jmp .next_resendq ; Timer not zero, so move on |
@@: |
xor ebx, ebx |
; restart timer, and decrement retries |
; After the first resend, back of on next, by a factor of 5 |
mov [esi + 2], word TCP_TIMEOUT * 5 |
dec byte[esi + 1] |
jnz @f |
; retries now 0, so delete from queue |
xchg [esi + 4], ebx |
@@: ; resend packet |
pushad |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
jne .tth004z |
; TODO - try again in 10ms. |
test ebx, ebx |
jnz @f |
mov [esi + 4], ebx |
@@: ; Mark it to expire in 10ms - 1 tick |
mov byte[esi + 1], 1 |
mov word[esi + 2], 1 |
jmp .tth005 |
.tth004z: |
; we have a buffer # in ax |
push eax ecx |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
; we have the buffer address in eax |
mov edi, eax |
pop ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
imul esi, ecx, IPBUFFSIZE |
add esi, resendBuffer |
; we have resend buffer location in esi |
mov ecx, IPBUFFSIZE |
; copy data across |
push edi |
cld |
rep movsb |
pop edi |
; queue packet |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
cmp edx, [edi + IP_PACKET.DestinationAddress] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
pop ebx |
call queue |
.tth005: |
popad |
inc ecx |
add esi, 8 |
jmp .next_resendq |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; tcp_rx |
; |
; Description |
; TCP protocol handler |
; This is a kernel function, called by ip_rx |
; IP buffer address given in edx |
; IP buffer number in eax |
; Free up (or re-use) IP buffer when finished |
; |
;*************************************************************************** |
proc tcp_rx stdcall uses ebx |
; The process is as follows. |
; Look for a socket with matching remote IP, remote port, local port |
; if not found, then |
; look for remote IP + local port match ( where sockets remote port = 0) |
; if not found, then |
; look for a socket where local socket port == IP packets remote port |
; where sockets remote port, remote IP = 0 |
; discard if not found |
; Call sockets tcbStateMachine, with pointer to packet. |
; the state machine will not delete the packet, so do that here. |
push eax |
; Look for a socket where |
; IP Packet TCP Destination Port = local Port |
; IP Packet SA = Remote IP |
; IP Packet TCP Source Port = remote Port |
mov ebx, net_sockets |
.next_socket.1: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .next_socket.1.exit |
; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr |
cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr |
jne .next_socket.1 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] |
mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr |
cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
jne .next_socket.1 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 |
mov ax, [edx + 20 + TCP_PACKET.SourcePort] ; get the source port from the TCP hdr |
cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port |
jne .next_socket.1 ; different - try next socket |
; We have a complete match - use this socket |
jmp .change_state |
.next_socket.1.exit: |
; If we got here, there was no match |
; Look for a socket where |
; IP Packet TCP Destination Port = local Port |
; IP Packet SA = Remote IP |
; socket remote Port = 0 |
mov ebx, net_sockets |
.next_socket.2: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .next_socket.2.exit |
; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr |
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
jne .next_socket.2 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] |
mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr |
cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
jne .next_socket.2 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
jne .next_socket.2 ; different - try next socket |
; We have a complete match - use this socket |
jmp .change_state |
.next_socket.2.exit: |
; If we got here, there was no match |
; Look for a socket where |
; IP Packet TCP Destination Port = local Port |
; socket Remote IP = 0 |
; socket remote Port = 0 |
mov ebx, net_sockets |
.next_socket.3: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .next_socket.3.exit |
; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get destination port from the TCP hdr |
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
jne .next_socket.3 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP] |
cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0 |
jne .next_socket.3 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
jne .next_socket.3 ; different - try next socket |
; We have a complete match - use this socket |
jmp .change_state |
.next_socket.3.exit: |
; If we got here, we need to reject the packet |
DEBUGF 1, "K : tcp_rx - dumped\n" |
DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [edx + IP_PACKET.SourceAddress], [edx + 20 + TCP_PACKET.SourcePort]:4, [edx + 20 + TCP_PACKET.Flags]:2 |
inc [dumped_rx_count] |
jmp .exit |
.change_state: |
; We have a valid socket/TCB, so call the TCB State Machine for that skt. |
; socket is pointed to by ebx |
; IP packet is pointed to by edx |
; IP buffer number is on stack ( it will be popped at the end) |
stdcall tcpStateMachine, ebx |
.exit: |
pop eax |
call freeBuff |
ret |
endp |
;*************************************************************************** |
; Function |
; buildTCPPacket |
; |
; Description |
; builds an IP Packet with TCP data fully populated for transmission |
; You may destroy any and all registers |
; TCP control flags specified in bl |
; This TCB is in [sktAddr] |
; User data pointed to by esi |
; Data length in ecx |
; Transmit buffer number in eax |
; |
;*************************************************************************** |
proc build_tcp_packet stdcall, sockAddr:DWORD |
push ecx ; Save data length |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov edx, eax |
mov [edx + 20 + TCP_PACKET.Flags], bl ; TCP flags |
mov ebx, [sockAddr] |
; So, ebx holds the socket ptr, edx holds the IPbuffer ptr |
; Fill in the IP header ( some data is in the socket descriptor) |
mov eax, [ebx + SOCKET.LocalIP] |
mov [edx + IP_PACKET.SourceAddress], eax |
mov eax, [ebx + SOCKET.RemoteIP] |
mov [edx + IP_PACKET.DestinationAddress], eax |
mov [edx + IP_PACKET.VersionAndIHL], 0x45 |
mov [edx + IP_PACKET.TypeOfService], 0 |
pop eax ; Get the TCP data length |
push eax |
add eax, 20 + 20 ; add IP header and TCP header lengths |
rol ax, 8 |
mov [edx + IP_PACKET.TotalLength], ax |
mov [edx + IP_PACKET.Identification], 0 |
mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 |
mov [edx + IP_PACKET.TimeToLive], 0x20 |
mov [edx + IP_PACKET.Protocol], PROTOCOL_TCP |
; Checksum left unfilled |
mov [edx + IP_PACKET.HeaderChecksum], 0 |
; Fill in the TCP header (some data is in the socket descriptor) |
mov ax, [ebx + SOCKET.LocalPort] |
mov [edx + 20 + TCP_PACKET.SourcePort], ax ; Local Port |
mov ax, [ebx + SOCKET.RemotePort] |
mov [edx + 20 + TCP_PACKET.DestinationPort], ax ; desitination Port |
; Checksum left unfilled |
mov [edx + 20 + TCP_PACKET.Checksum], 0 |
; sequence number |
mov eax, [ebx + SOCKET.SND_NXT] |
mov [edx + 20 + TCP_PACKET.SequenceNumber], eax |
; ack number |
mov eax, [ebx + SOCKET.RCV_NXT] |
mov [edx + 20 + TCP_PACKET.AckNumber], eax |
; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) |
; 768 bytes seems better |
mov [edx + 20 + TCP_PACKET.Window], 0x0003 |
; Urgent pointer (0) |
mov [edx + 20 + TCP_PACKET.UrgentPointer], 0 |
; data offset ( 0x50 ) |
mov [edx + 20 + TCP_PACKET.DataOffset], 0x50 |
pop ecx ; count of bytes to send |
mov ebx, ecx ; need the length later |
cmp ebx, 0 |
jz @f |
mov edi, edx |
add edi, 40 |
cld |
rep movsb ; copy the data across |
@@: ; we have edx as IPbuffer ptr. |
; Fill in the TCP checksum |
; First, fill in pseudoheader |
mov eax, [edx + IP_PACKET.SourceAddress] |
mov [pseudoHeader], eax |
mov eax, [edx + IP_PACKET.DestinationAddress] |
mov [pseudoHeader + 4], eax |
mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 |
add ebx, 20 |
mov [pseudoHeader + 10], bh |
mov [pseudoHeader + 11], bl |
mov eax, pseudoHeader |
mov [checkAdd1], eax |
mov word[checkSize1], 12 |
mov eax, edx |
add eax, 20 |
mov [checkAdd2], eax |
mov eax, ebx |
mov [checkSize2], ax |
call checksum |
; store it in the TCP checksum ( in the correct order! ) |
mov ax, [checkResult] |
rol ax, 8 |
mov [edx + 20 + TCP_PACKET.Checksum], ax |
; Fill in the IP header checksum |
GET_IHL eax, edx ; get IP-Header length |
stdcall checksum_jb, edx, eax ; buf_ptr, buf_size |
rol ax, 8 |
mov [edx + IP_PACKET.HeaderChecksum], ax |
ret |
endp |
; Increments the 32 bit value pointed to by esi in internet order |
proc inc_inet_esi stdcall |
push eax |
mov eax, [esi] |
bswap eax |
inc eax |
bswap eax |
mov [esi], eax |
pop eax |
ret |
endp |
; Increments the 32 bit value pointed to by esi in internet order |
; by the value in ecx |
proc add_inet_esi stdcall |
push eax |
mov eax, [esi] |
bswap eax |
add eax, ecx |
bswap eax |
mov [esi], eax |
pop eax |
ret |
endp |
iglobal |
TCBStateHandler dd \ |
stateTCB_LISTEN, \ |
stateTCB_SYN_SENT, \ |
stateTCB_SYN_RECEIVED, \ |
stateTCB_ESTABLISHED, \ |
stateTCB_FIN_WAIT_1, \ |
stateTCB_FIN_WAIT_2, \ |
stateTCB_CLOSE_WAIT, \ |
stateTCB_CLOSING, \ |
stateTCB_LAST_ACK, \ |
stateTCB_TIME_WAIT, \ |
stateTCB_CLOSED |
endg |
;*************************************************************************** |
; Function |
; tcpStateMachine |
; |
; Description |
; TCP state machine |
; This is a kernel function, called by tcp_rx |
; |
; IP buffer address given in edx |
; Socket/TCB address in ebx |
; |
; The IP buffer will be released by the caller |
;*************************************************************************** |
proc tcpStateMachine stdcall, sockAddr:DWORD |
; as a packet has been received, update the TCB timer |
mov [ebx + SOCKET.TCBTimer], TWOMSL |
; If the received packet has an ACK bit set, |
; remove any packets in the resend queue that this |
; received packet acknowledges |
pushad |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .call_handler ; No ACK, so no data yet |
; get skt number in eax |
stdcall net_socket_addr_to_num, ebx |
; The ack number is in [edx + 28], inet format |
; skt in eax |
mov esi, resendQ |
xor ecx, ecx |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .call_handler ; None left |
cmp [esi + 4], eax |
je @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: ; Can we delete this buffer? |
; If yes, goto @@. No, goto .next_resendq |
; Get packet data address |
push ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
imul edi, ecx, IPBUFFSIZE |
add edi, resendBuffer |
; we have dest buffer location in edi. incoming packet in edx. |
; Get this packets sequence number |
; preserve al, ecx, esi, edx |
mov ecx, [edi + 20 + TCP_PACKET.SequenceNumber] |
bswap ecx |
movzx ebx, word[edi + 2] |
xchg bl, bh |
sub ebx, 40 |
add ecx, ebx ; ecx is now seq# of last byte +1, intel format |
; get recievd ack #, in intel format |
mov ebx, [edx + 20 + TCP_PACKET.AckNumber] |
bswap ebx |
cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que |
; DANGER! need to handle case that we have just |
; passed the 2**32, and wrapped round! |
pop ecx |
jae @f ; if rx > old, delete old |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: mov dword[esi + 4], 0 |
inc ecx |
add esi, 8 |
jmp .next_resendq |
.call_handler: |
popad |
; Call handler for given TCB state |
mov eax, [ebx + SOCKET.TCBState] |
cmp eax, TCB_LISTEN |
jb .exit |
cmp eax, TCB_CLOSED |
ja .exit |
stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; signal_network_event |
; |
; Description |
; Signals about network event to socket owner |
; This is a kernel function, called from TCP handler |
; |
; Socket/TCB address in ebx |
;*************************************************************************** |
proc signal_network_event |
push ecx esi eax |
mov eax, [ebx + SOCKET.PID] |
mov ecx, 1 |
mov esi, TASK_DATA + TASKDATA.pid |
.next_pid: |
cmp [esi], eax |
je .found_pid |
inc ecx |
add esi, 0x20 |
cmp ecx, [TASK_COUNT] |
jbe .next_pid |
.found_pid: |
shl ecx, 8 |
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event |
pop eax esi ecx |
ret |
endp |
proc stateTCB_LISTEN stdcall, sockAddr:DWORD |
; In this case, we are expecting a SYN packet |
; For now, if the packet is a SYN, process it, and send a response |
; If not, ignore it |
; Look at control flags |
test [edx + 20 + TCP_PACKET.Flags], TH_SYN |
jz .exit |
; We have a SYN. update the socket with this IP packets details, |
; And send a response |
mov eax, [edx + IP_PACKET.SourceAddress] |
mov [ebx + SOCKET.RemoteIP], eax |
mov ax, [edx + 20 + TCP_PACKET.SourcePort] |
mov [ebx + SOCKET.RemotePort], ax |
mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
mov [ebx + SOCKET.IRS], eax |
mov [ebx + SOCKET.RCV_NXT], eax |
lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi ; RCV.NXT |
mov eax, [ebx + SOCKET.ISS] |
mov [ebx + SOCKET.SND_NXT], eax |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push ebx |
push eax |
mov bl, TH_SYN + TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
pop ebx |
mov esi, [sockAddr] |
mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED |
call signal_network_event |
; increment SND.NXT in socket |
add esi, SOCKET.SND_NXT |
call inc_inet_esi |
.exit: |
ret |
endp |
proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD |
; We are awaiting an ACK to our SYN, with a SYM |
; Look at control flags - expecting an ACK |
mov al, [edx + 20 + TCP_PACKET.Flags] |
and al, TH_SYN + TH_ACK |
cmp al, TH_SYN + TH_ACK |
je .syn_ack |
test al, TH_SYN |
jz .exit |
mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED |
push TH_SYN + TH_ACK |
jmp .send |
.syn_ack: |
mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
push TH_ACK |
.send: |
call signal_network_event |
; Store the recv.nxt field |
mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
; Update our recv.nxt field |
mov [ebx + SOCKET.RCV_NXT], eax |
lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi |
; Send an ACK |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
pop ebx |
je .exit |
push eax |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
.exit: |
ret |
endp |
proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD |
; In this case, we are expecting an ACK packet |
; For now, if the packet is an ACK, process it, |
; If not, ignore it |
test [edx + 20 + TCP_PACKET.Flags], TH_RST |
jz .check_ack |
push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP] |
pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort] |
mov [ebx + SOCKET.TCBState], TCB_LISTEN |
jmp .signal |
.check_ack: |
; Look at control flags - expecting an ACK |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .exit |
mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
.signal: |
call signal_network_event |
.exit: |
ret |
endp |
proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD |
; Here we are expecting data, or a request to close |
; OR both... |
; Ignore all packets with sequnce number other than next expected |
; recv.nxt is in dword [edx+24], in inet format |
; recv seq is in [sktAddr]+56, in inet format |
; just do a comparision |
mov eax, [ebx + SOCKET.RCV_NXT] |
cmp eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
jne .exit |
; Did we receive a FIN or RST? |
test [edx + 20 + TCP_PACKET.Flags], TH_FIN+TH_RST |
jz .check_ack |
; It was a fin or reset. |
; Remove resend entries from the queue - I dont want to send any more data |
pushad |
; get skt # |
stdcall net_socket_addr_to_num, ebx |
mov esi, resendQ |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .last_resendq ; None left |
cmp [esi + 4], eax |
je @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: mov dword[esi + 4], 0 |
inc ecx |
add esi, 8 |
jmp .next_resendq |
.last_resendq: |
popad |
@@: ; Send an ACK to that fin, and enter closewait state |
mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
test [edx + 20 + TCP_PACKET.Flags], TH_RST |
je @f |
mov [ebx + SOCKET.TCBState], TCB_CLOSED |
@@: |
call signal_network_event |
lea esi, [ebx + SOCKET.RCV_NXT] |
mov eax, [esi] ; save original |
call inc_inet_esi |
;; jmp ste_ack - NO, there may be data |
.check_ack: |
; Check that we received an ACK |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .exit |
; TODO - done, I think! |
; First, look at the incoming window. If this is less than or equal to 1024, |
; Set the socket window timer to 1. This will stop an additional packets being queued. |
; ** I may need to tweak this value, since I do not know how many packets are already queued |
mov cx, [edx + 20 + TCP_PACKET.Window] |
xchg cl, ch |
cmp cx, 1024 |
ja @f |
mov [ebx + SOCKET.wndsizeTimer], 1 |
@@: ; OK, here is the deal |
; Read the data bytes, store in socket buffer |
movzx ecx, [edx + IP_PACKET.TotalLength] |
xchg cl, ch |
sub ecx, 40 ; Discard 40 bytes of header |
ja .data ; Read data, if any |
; If we had received a fin, we need to ACK it. |
cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
je .ack |
jmp .exit |
.data: |
push ecx |
push ecx edx |
lea ecx, [ebx+SOCKET.lock] |
call mutex_lock |
pop edx ecx |
push ebx |
mov eax, [ebx + SOCKET.rxDataCount] |
add eax, ecx |
cmp eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE |
ja .overflow |
mov [ebx + SOCKET.rxDataCount], eax ; increment the count of bytes in buffer |
; point to the location to store the data |
lea edi, [ebx + eax + SOCKETHEADERSIZE] |
sub edi, ecx |
add edx, 40 ; edx now points to the data |
mov esi, edx |
cld |
rep movsb ; copy the data across |
lea ecx,[ebx + SOCKET.lock] |
call mutex_unlock |
; flag an event to the application |
pop ebx |
call signal_network_event |
pop ecx |
; Update our recv.nxt field |
lea esi, [ebx + SOCKET.RCV_NXT] |
call add_inet_esi |
.ack: |
; Send an ACK |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push eax |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
.exit: |
ret |
.overflow: |
; no place in buffer |
; so simply restore stack and exit |
lea ecx, [ebx + SOCKET.lock] |
call mutex_unlock |
pop eax ecx |
ret |
endp |
proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD |
; We can either receive an ACK of a fin, or a fin |
mov al, [edx + 20 + TCP_PACKET.Flags] |
and al, TH_FIN + TH_ACK |
cmp al, TH_ACK |
jne @f |
; It was an ACK |
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2 |
jmp .exit |
@@: mov [ebx + SOCKET.TCBState], TCB_CLOSING |
cmp al, TH_FIN |
je @f |
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
@@: lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push eax |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
.exit: |
ret |
endp |
proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD |
test [edx + 20 + TCP_PACKET.Flags], TH_FIN |
jz .exit |
; Change state, as we have a fin |
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push eax |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
.exit: |
ret |
endp |
proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD |
; Intentionally left empty |
; socket_close_tcp handles this |
ret |
endp |
proc stateTCB_CLOSING stdcall, sockAddr:DWORD |
; We can either receive an ACK of a fin, or a fin |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .exit |
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
.exit: |
ret |
endp |
proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD |
; Look at control flags - expecting an ACK |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .exit |
; delete the socket |
stdcall net_socket_free, ebx |
.exit: |
ret |
endp |
proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD |
ret |
endp |
proc stateTCB_CLOSED stdcall, sockAddr:DWORD |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; TCP.INC ;; |
;; ;; |
;; TCP Processes for Menuet OS TCP/IP stack ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; v0.6 : Added reset handling in the established state ;; |
;; Added a timer per socket to allow delays when ;; |
;; rx window gets below 1KB ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; TCP TCB states |
TCB_LISTEN equ 1 |
TCB_SYN_SENT equ 2 |
TCB_SYN_RECEIVED equ 3 |
TCB_ESTABLISHED equ 4 |
TCB_FIN_WAIT_1 equ 5 |
TCB_FIN_WAIT_2 equ 6 |
TCB_CLOSE_WAIT equ 7 |
TCB_CLOSING equ 8 |
TCB_LAST_ACK equ 9 |
TCB_TIMED_WAIT equ 10 |
TCB_CLOSED equ 11 |
TH_FIN = 0x01 |
TH_SYN = 0x02 |
TH_RST = 0x04 |
TH_PUSH = 0x08 |
TH_ACK = 0x10 |
TH_URG = 0x20 |
TWOMSL equ 10 ; # of secs to wait before closing socket |
TCP_RETRIES equ 5 ; Number of times to resend a packet |
TCP_TIMEOUT equ 20 ; resend if not replied to in x hs |
;******************************************************************* |
; Interface |
; |
; tcp_tx_handler Handles the TCP transmit queue |
; tcp_rx The protocol handler for received data |
; buildTCPPacket fills in the packet headers and data |
; tcpStateMachine Main state machine for received TCP packets |
; tcp_tcb_handler 1s timer, to erase tcb's in TIME_WAIT state |
; |
;******************************************************************* |
; TCP Payload ( Data field in IP datagram ) |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;20 | Source Port | Destination Port | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;24 | Sequence Number | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;28 | Acknowledgment Number | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;32 | Data | |U|A|P|R|S|F| | |
; | Offset| Reserved |R|C|S|S|Y|I| Window | |
; | | |G|K|H|T|N|N| | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;36 | Checksum | Urgent Pointer | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;40 | Options | Padding | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | data |
struc TCP_PACKET |
{ .SourcePort dw ? ;+00 |
.DestinationPort dw ? ;+02 |
.SequenceNumber dd ? ;+04 |
.AckNumber dd ? ;+08 |
.DataOffset db ? ;+12 - DataOffset[0-3 bits] and Reserved[4-7] |
.Flags db ? ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN |
.Window dw ? ;+14 |
.Checksum dw ? ;+16 |
.UrgentPointer dw ? ;+18 |
.Options rb 3 ;+20 |
.Padding db ? ;+23 |
.Data db ? ;+24 |
} |
virtual at 0 |
TCP_PACKET TCP_PACKET |
end virtual |
;*************************************************************************** |
; Function |
; tcp_tcb_handler |
; |
; Description |
; Handles sockets in the timewait state, closing them |
; when the TCB timer expires |
; |
;*************************************************************************** |
proc tcp_tcb_handler stdcall uses ebx |
; scan through all the sockets, decrementing active timers |
mov ebx, net_sockets |
cmp [ebx + SOCKET.NextPtr], 0 |
je .exit |
;DEBUGF 1, "K : sockets:\n" |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .exit |
;DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] |
cmp [ebx + SOCKET.TCBTimer], 0 |
jne .decrement_tcb |
cmp [ebx + SOCKET.wndsizeTimer], 0 |
jne .decrement_wnd |
jmp .next_socket |
.decrement_tcb: |
; decrement it, delete socket if TCB timer = 0 & socket in timewait state |
dec [ebx + SOCKET.TCBTimer] |
jnz .next_socket |
cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
jne .next_socket |
push [ebx + SOCKET.PrevPtr] |
stdcall net_socket_free, ebx |
pop ebx |
jmp .next_socket |
.decrement_wnd: |
; TODO - prove it works! |
dec [ebx + SOCKET.wndsizeTimer] |
jmp .next_socket |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; tcp_tx_handler |
; |
; Description |
; Handles queued TCP data |
; This is a kernel function, called by stack_handler |
; |
;*************************************************************************** |
proc tcp_tx_handler stdcall |
; decrement all resend buffers timers. If they |
; expire, queue them for sending, and restart the timer. |
; If the retries counter reach 0, delete the entry |
mov esi, resendQ |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .exit ; None left |
cmp dword[esi + 4], 0 |
jne @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: ; we have one. decrement it's timer by 1 |
dec word[esi + 2] |
jz @f |
inc ecx |
add esi, 8 |
jmp .next_resendq ; Timer not zero, so move on |
@@: |
xor ebx, ebx |
; restart timer, and decrement retries |
; After the first resend, back of on next, by a factor of 5 |
mov [esi + 2], word TCP_TIMEOUT * 5 |
dec byte[esi + 1] |
jnz @f |
; retries now 0, so delete from queue |
xchg [esi + 4], ebx |
@@: ; resend packet |
pushad |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
jne .tth004z |
; TODO - try again in 10ms. |
test ebx, ebx |
jnz @f |
mov [esi + 4], ebx |
@@: ; Mark it to expire in 10ms - 1 tick |
mov byte[esi + 1], 1 |
mov word[esi + 2], 1 |
jmp .tth005 |
.tth004z: |
; we have a buffer # in ax |
push eax ecx |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
; we have the buffer address in eax |
mov edi, eax |
pop ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
imul esi, ecx, IPBUFFSIZE |
add esi, resendBuffer |
; we have resend buffer location in esi |
mov ecx, IPBUFFSIZE |
; copy data across |
push edi |
cld |
rep movsb |
pop edi |
; queue packet |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
cmp edx, [edi + IP_PACKET.DestinationAddress] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
pop ebx |
call queue |
.tth005: |
popad |
inc ecx |
add esi, 8 |
jmp .next_resendq |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; tcp_rx |
; |
; Description |
; TCP protocol handler |
; This is a kernel function, called by ip_rx |
; IP buffer address given in edx |
; IP buffer number in eax |
; Free up (or re-use) IP buffer when finished |
; |
;*************************************************************************** |
proc tcp_rx stdcall uses ebx |
; The process is as follows. |
; Look for a socket with matching remote IP, remote port, local port |
; if not found, then |
; look for remote IP + local port match ( where sockets remote port = 0) |
; if not found, then |
; look for a socket where local socket port == IP packets remote port |
; where sockets remote port, remote IP = 0 |
; discard if not found |
; Call sockets tcbStateMachine, with pointer to packet. |
; the state machine will not delete the packet, so do that here. |
push eax |
; Look for a socket where |
; IP Packet TCP Destination Port = local Port |
; IP Packet SA = Remote IP |
; IP Packet TCP Source Port = remote Port |
mov ebx, net_sockets |
.next_socket.1: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .next_socket.1.exit |
; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr |
cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr |
jne .next_socket.1 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] |
mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr |
cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
jne .next_socket.1 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 |
mov ax, [edx + 20 + TCP_PACKET.SourcePort] ; get the source port from the TCP hdr |
cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port |
jne .next_socket.1 ; different - try next socket |
; We have a complete match - use this socket |
jmp .change_state |
.next_socket.1.exit: |
; If we got here, there was no match |
; Look for a socket where |
; IP Packet TCP Destination Port = local Port |
; IP Packet SA = Remote IP |
; socket remote Port = 0 |
mov ebx, net_sockets |
.next_socket.2: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .next_socket.2.exit |
; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr |
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
jne .next_socket.2 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] |
mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr |
cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
jne .next_socket.2 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
jne .next_socket.2 ; different - try next socket |
; We have a complete match - use this socket |
jmp .change_state |
.next_socket.2.exit: |
; If we got here, there was no match |
; Look for a socket where |
; IP Packet TCP Destination Port = local Port |
; socket Remote IP = 0 |
; socket remote Port = 0 |
mov ebx, net_sockets |
.next_socket.3: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .next_socket.3.exit |
; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get destination port from the TCP hdr |
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
jne .next_socket.3 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP] |
cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0 |
jne .next_socket.3 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
jne .next_socket.3 ; different - try next socket |
; We have a complete match - use this socket |
jmp .change_state |
.next_socket.3.exit: |
; If we got here, we need to reject the packet |
DEBUGF 1, "K : tcp_rx - dumped\n" |
DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [edx + IP_PACKET.SourceAddress], [edx + 20 + TCP_PACKET.SourcePort]:4, [edx + 20 + TCP_PACKET.Flags]:2 |
inc [dumped_rx_count] |
jmp .exit |
.change_state: |
; We have a valid socket/TCB, so call the TCB State Machine for that skt. |
; socket is pointed to by ebx |
; IP packet is pointed to by edx |
; IP buffer number is on stack ( it will be popped at the end) |
stdcall tcpStateMachine, ebx |
.exit: |
pop eax |
call freeBuff |
ret |
endp |
;*************************************************************************** |
; Function |
; buildTCPPacket |
; |
; Description |
; builds an IP Packet with TCP data fully populated for transmission |
; You may destroy any and all registers |
; TCP control flags specified in bl |
; This TCB is in [sktAddr] |
; User data pointed to by esi |
; Data length in ecx |
; Transmit buffer number in eax |
; |
;*************************************************************************** |
proc build_tcp_packet stdcall, sockAddr:DWORD |
push ecx ; Save data length |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov edx, eax |
mov [edx + 20 + TCP_PACKET.Flags], bl ; TCP flags |
mov ebx, [sockAddr] |
; So, ebx holds the socket ptr, edx holds the IPbuffer ptr |
; Fill in the IP header ( some data is in the socket descriptor) |
mov eax, [ebx + SOCKET.LocalIP] |
mov [edx + IP_PACKET.SourceAddress], eax |
mov eax, [ebx + SOCKET.RemoteIP] |
mov [edx + IP_PACKET.DestinationAddress], eax |
mov [edx + IP_PACKET.VersionAndIHL], 0x45 |
mov [edx + IP_PACKET.TypeOfService], 0 |
pop eax ; Get the TCP data length |
push eax |
add eax, 20 + 20 ; add IP header and TCP header lengths |
rol ax, 8 |
mov [edx + IP_PACKET.TotalLength], ax |
mov [edx + IP_PACKET.Identification], 0 |
mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 |
mov [edx + IP_PACKET.TimeToLive], 0x20 |
mov [edx + IP_PACKET.Protocol], PROTOCOL_TCP |
; Checksum left unfilled |
mov [edx + IP_PACKET.HeaderChecksum], 0 |
; Fill in the TCP header (some data is in the socket descriptor) |
mov ax, [ebx + SOCKET.LocalPort] |
mov [edx + 20 + TCP_PACKET.SourcePort], ax ; Local Port |
mov ax, [ebx + SOCKET.RemotePort] |
mov [edx + 20 + TCP_PACKET.DestinationPort], ax ; desitination Port |
; Checksum left unfilled |
mov [edx + 20 + TCP_PACKET.Checksum], 0 |
; sequence number |
mov eax, [ebx + SOCKET.SND_NXT] |
mov [edx + 20 + TCP_PACKET.SequenceNumber], eax |
; ack number |
mov eax, [ebx + SOCKET.RCV_NXT] |
mov [edx + 20 + TCP_PACKET.AckNumber], eax |
; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) |
; 768 bytes seems better |
mov [edx + 20 + TCP_PACKET.Window], 0x0003 |
; Urgent pointer (0) |
mov [edx + 20 + TCP_PACKET.UrgentPointer], 0 |
; data offset ( 0x50 ) |
mov [edx + 20 + TCP_PACKET.DataOffset], 0x50 |
pop ecx ; count of bytes to send |
mov ebx, ecx ; need the length later |
cmp ebx, 0 |
jz @f |
mov edi, edx |
add edi, 40 |
cld |
rep movsb ; copy the data across |
@@: ; we have edx as IPbuffer ptr. |
; Fill in the TCP checksum |
; First, fill in pseudoheader |
mov eax, [edx + IP_PACKET.SourceAddress] |
mov [pseudoHeader], eax |
mov eax, [edx + IP_PACKET.DestinationAddress] |
mov [pseudoHeader + 4], eax |
mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 |
add ebx, 20 |
mov [pseudoHeader + 10], bh |
mov [pseudoHeader + 11], bl |
mov eax, pseudoHeader |
mov [checkAdd1], eax |
mov word[checkSize1], 12 |
mov eax, edx |
add eax, 20 |
mov [checkAdd2], eax |
mov eax, ebx |
mov [checkSize2], ax |
call checksum |
; store it in the TCP checksum ( in the correct order! ) |
mov ax, [checkResult] |
rol ax, 8 |
mov [edx + 20 + TCP_PACKET.Checksum], ax |
; Fill in the IP header checksum |
GET_IHL eax, edx ; get IP-Header length |
stdcall checksum_jb, edx, eax ; buf_ptr, buf_size |
rol ax, 8 |
mov [edx + IP_PACKET.HeaderChecksum], ax |
ret |
endp |
; Increments the 32 bit value pointed to by esi in internet order |
proc inc_inet_esi stdcall |
push eax |
mov eax, [esi] |
bswap eax |
inc eax |
bswap eax |
mov [esi], eax |
pop eax |
ret |
endp |
; Increments the 32 bit value pointed to by esi in internet order |
; by the value in ecx |
proc add_inet_esi stdcall |
push eax |
mov eax, [esi] |
bswap eax |
add eax, ecx |
bswap eax |
mov [esi], eax |
pop eax |
ret |
endp |
iglobal |
TCBStateHandler dd \ |
stateTCB_LISTEN, \ |
stateTCB_SYN_SENT, \ |
stateTCB_SYN_RECEIVED, \ |
stateTCB_ESTABLISHED, \ |
stateTCB_FIN_WAIT_1, \ |
stateTCB_FIN_WAIT_2, \ |
stateTCB_CLOSE_WAIT, \ |
stateTCB_CLOSING, \ |
stateTCB_LAST_ACK, \ |
stateTCB_TIME_WAIT, \ |
stateTCB_CLOSED |
endg |
;*************************************************************************** |
; Function |
; tcpStateMachine |
; |
; Description |
; TCP state machine |
; This is a kernel function, called by tcp_rx |
; |
; IP buffer address given in edx |
; Socket/TCB address in ebx |
; |
; The IP buffer will be released by the caller |
;*************************************************************************** |
proc tcpStateMachine stdcall, sockAddr:DWORD |
; as a packet has been received, update the TCB timer |
mov [ebx + SOCKET.TCBTimer], TWOMSL |
; If the received packet has an ACK bit set, |
; remove any packets in the resend queue that this |
; received packet acknowledges |
pushad |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .call_handler ; No ACK, so no data yet |
; get skt number in eax |
stdcall net_socket_addr_to_num, ebx |
; The ack number is in [edx + 28], inet format |
; skt in eax |
mov esi, resendQ |
xor ecx, ecx |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .call_handler ; None left |
cmp [esi + 4], eax |
je @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: ; Can we delete this buffer? |
; If yes, goto @@. No, goto .next_resendq |
; Get packet data address |
push ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
imul edi, ecx, IPBUFFSIZE |
add edi, resendBuffer |
; we have dest buffer location in edi. incoming packet in edx. |
; Get this packets sequence number |
; preserve al, ecx, esi, edx |
mov ecx, [edi + 20 + TCP_PACKET.SequenceNumber] |
bswap ecx |
movzx ebx, word[edi + 2] |
xchg bl, bh |
sub ebx, 40 |
add ecx, ebx ; ecx is now seq# of last byte +1, intel format |
; get recievd ack #, in intel format |
mov ebx, [edx + 20 + TCP_PACKET.AckNumber] |
bswap ebx |
cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que |
; DANGER! need to handle case that we have just |
; passed the 2**32, and wrapped round! |
pop ecx |
jae @f ; if rx > old, delete old |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: |
mov dword[esi + 4], 0 |
inc ecx |
add esi, 8 |
jmp .next_resendq |
.call_handler: |
popad |
; Call handler for given TCB state |
mov eax, [ebx + SOCKET.TCBState] |
cmp eax, TCB_LISTEN |
jb .exit |
cmp eax, TCB_CLOSED |
ja .exit |
stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; signal_network_event |
; |
; Description |
; Signals about network event to socket owner |
; This is a kernel function, called from TCP handler |
; |
; Socket/TCB address in ebx |
;*************************************************************************** |
proc signal_network_event |
push ecx esi eax |
mov eax, [ebx + SOCKET.PID] |
mov ecx, 1 |
mov esi, TASK_DATA + TASKDATA.pid |
.next_pid: |
cmp [esi], eax |
je .found_pid |
inc ecx |
add esi, 0x20 |
cmp ecx, [TASK_COUNT] |
jbe .next_pid |
.found_pid: |
shl ecx, 8 |
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event |
pop eax esi ecx |
ret |
endp |
proc stateTCB_LISTEN stdcall, sockAddr:DWORD |
; In this case, we are expecting a SYN packet |
; For now, if the packet is a SYN, process it, and send a response |
; If not, ignore it |
; Look at control flags |
test [edx + 20 + TCP_PACKET.Flags], TH_SYN |
jz .exit |
; We have a SYN. update the socket with this IP packets details, |
; And send a response |
mov eax, [edx + IP_PACKET.SourceAddress] |
mov [ebx + SOCKET.RemoteIP], eax |
mov ax, [edx + 20 + TCP_PACKET.SourcePort] |
mov [ebx + SOCKET.RemotePort], ax |
mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
mov [ebx + SOCKET.IRS], eax |
mov [ebx + SOCKET.RCV_NXT], eax |
lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi ; RCV.NXT |
mov eax, [ebx + SOCKET.ISS] |
mov [ebx + SOCKET.SND_NXT], eax |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push ebx |
push eax |
mov bl, TH_SYN + TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
pop ebx |
mov esi, [sockAddr] |
mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED |
call signal_network_event |
; increment SND.NXT in socket |
add esi, SOCKET.SND_NXT |
call inc_inet_esi |
.exit: |
ret |
endp |
proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD |
; We are awaiting an ACK to our SYN, with a SYM |
; Look at control flags - expecting an ACK |
mov al, [edx + 20 + TCP_PACKET.Flags] |
and al, TH_SYN + TH_ACK |
cmp al, TH_SYN + TH_ACK |
je .syn_ack |
test al, TH_SYN |
jz .exit |
mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED |
push TH_SYN + TH_ACK |
jmp .send |
.syn_ack: |
mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
push TH_ACK |
.send: |
call signal_network_event |
; Store the recv.nxt field |
mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
; Update our recv.nxt field |
mov [ebx + SOCKET.RCV_NXT], eax |
lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi |
; Send an ACK |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
pop ebx |
je .exit |
push eax |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
.exit: |
ret |
endp |
proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD |
; In this case, we are expecting an ACK packet |
; For now, if the packet is an ACK, process it, |
; If not, ignore it |
test [edx + 20 + TCP_PACKET.Flags], TH_RST |
jz .check_ack |
push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP] |
pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort] |
mov [ebx + SOCKET.TCBState], TCB_LISTEN |
jmp .signal |
.check_ack: |
; Look at control flags - expecting an ACK |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .exit |
mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
.signal: |
call signal_network_event |
.exit: |
ret |
endp |
proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD |
; Here we are expecting data, or a request to close |
; OR both... |
; Ignore all packets with sequnce number other than next expected |
; recv.nxt is in dword [edx+24], in inet format |
; recv seq is in [sktAddr]+56, in inet format |
; just do a comparision |
mov eax, [ebx + SOCKET.RCV_NXT] |
cmp eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
jne .exit |
; Did we receive a FIN or RST? |
test [edx + 20 + TCP_PACKET.Flags], TH_FIN+TH_RST |
jz .check_ack |
; It was a fin or reset. |
; Remove resend entries from the queue - I dont want to send any more data |
pushad |
; get skt # |
stdcall net_socket_addr_to_num, ebx |
mov esi, resendQ |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .last_resendq ; None left |
cmp [esi + 4], eax |
je @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
@@: |
mov dword[esi + 4], 0 |
inc ecx |
add esi, 8 |
jmp .next_resendq |
.last_resendq: |
popad |
@@: ; Send an ACK to that fin, and enter closewait state |
mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
test [edx + 20 + TCP_PACKET.Flags], TH_RST |
je @f |
mov [ebx + SOCKET.TCBState], TCB_CLOSED |
@@: |
call signal_network_event |
lea esi, [ebx + SOCKET.RCV_NXT] |
mov eax, [esi] ; save original |
call inc_inet_esi |
;; jmp ste_ack - NO, there may be data |
.check_ack: |
; Check that we received an ACK |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .exit |
; TODO - done, I think! |
; First, look at the incoming window. If this is less than or equal to 1024, |
; Set the socket window timer to 1. This will stop an additional packets being queued. |
; ** I may need to tweak this value, since I do not know how many packets are already queued |
mov cx, [edx + 20 + TCP_PACKET.Window] |
xchg cl, ch |
cmp cx, 1024 |
ja @f |
mov [ebx + SOCKET.wndsizeTimer], 1 |
@@: ; OK, here is the deal |
; Read the data bytes, store in socket buffer |
movzx ecx, [edx + IP_PACKET.TotalLength] |
xchg cl, ch |
sub ecx, 40 ; Discard 40 bytes of header |
ja .data ; Read data, if any |
; If we had received a fin, we need to ACK it. |
cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
je .ack |
jmp .exit |
.data: |
push ecx |
push ecx edx |
lea ecx, [ebx+SOCKET.lock] |
call mutex_lock |
pop edx ecx |
push ebx |
mov eax, [ebx + SOCKET.rxDataCount] |
add eax, ecx |
cmp eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE |
ja .overflow |
mov [ebx + SOCKET.rxDataCount], eax ; increment the count of bytes in buffer |
; point to the location to store the data |
lea edi, [ebx + eax + SOCKETHEADERSIZE] |
sub edi, ecx |
add edx, 40 ; edx now points to the data |
mov esi, edx |
cld |
rep movsb ; copy the data across |
lea ecx, [ebx + SOCKET.lock] |
call mutex_unlock |
; flag an event to the application |
pop ebx |
call signal_network_event |
pop ecx |
; Update our recv.nxt field |
lea esi, [ebx + SOCKET.RCV_NXT] |
call add_inet_esi |
.ack: |
; Send an ACK |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push eax |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
.exit: |
ret |
.overflow: |
; no place in buffer |
; so simply restore stack and exit |
lea ecx, [ebx + SOCKET.lock] |
call mutex_unlock |
pop eax ecx |
ret |
endp |
proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD |
; We can either receive an ACK of a fin, or a fin |
mov al, [edx + 20 + TCP_PACKET.Flags] |
and al, TH_FIN + TH_ACK |
cmp al, TH_ACK |
jne @f |
; It was an ACK |
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2 |
jmp .exit |
@@: |
mov [ebx + SOCKET.TCBState], TCB_CLOSING |
cmp al, TH_FIN |
je @f |
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
@@: |
lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push eax |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
.exit: |
ret |
endp |
proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD |
test [edx + 20 + TCP_PACKET.Flags], TH_FIN |
jz .exit |
; Change state, as we have a fin |
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
push eax |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
.exit: |
ret |
endp |
proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD |
; Intentionally left empty |
; socket_close_tcp handles this |
ret |
endp |
proc stateTCB_CLOSING stdcall, sockAddr:DWORD |
; We can either receive an ACK of a fin, or a fin |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .exit |
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
.exit: |
ret |
endp |
proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD |
; Look at control flags - expecting an ACK |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .exit |
; delete the socket |
stdcall net_socket_free, ebx |
.exit: |
ret |
endp |
proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD |
ret |
endp |
proc stateTCB_CLOSED stdcall, sockAddr:DWORD |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/network/udp.inc |
---|
1,155 → 1,155 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; UDP.INC ;; |
;; ;; |
;; UDP Processes for Menuet OS TCP/IP stack ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************* |
; Interface |
; |
; udp_rx Handles received IP packets with the UDP protocol |
; |
;******************************************************************* |
; |
; UDP Payload ( Data field in IP datagram ) |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
; |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Source Port | Destination Port | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Length ( UDP Header + Data ) | Checksum | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | UDP Data | |
; +-+-+-.......... -+ |
; |
struc UDP_PACKET |
{ .SourcePort dw ? ;+00 |
.DestinationPort dw ? ;+02 |
.Length dw ? ;+04 - Length of (UDP Header + Data) |
.Checksum dw ? ;+06 |
.Data db ? ;+08 |
} |
virtual at 0 |
UDP_PACKET UDP_PACKET |
end virtual |
;*************************************************************************** |
; Function |
; udp_rx [by Johnny_B] |
; |
; Description |
; UDP protocol handler |
; This is a kernel function, called by ip_rx |
; IP buffer address given in edx |
; IP buffer number in eax |
; Free up (or re-use) IP buffer when finished |
; |
;*************************************************************************** |
proc udp_rx stdcall |
push eax |
; First validate the header & checksum. Discard buffer if error |
; Look for a socket where |
; IP Packet UDP Destination Port = local Port |
; IP Packet SA = Remote IP |
mov ax, [edx + 20 + UDP_PACKET.DestinationPort] ; get the local port from |
; the IP packet's UDP header |
mov ebx, net_sockets |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .exit ; No match, so exit |
cmp [ebx + SOCKET.LocalPort], ax ; ax will hold the 'wrong' value, |
; but the comparision is correct |
jne .next_socket ; Return back if no match |
; For dhcp, we must allow any remote server to respond. |
; I will accept the first incoming response to be the one |
; I bind to, if the socket is opened with a destination IP address of |
; 255.255.255.255 |
cmp [ebx + SOCKET.RemoteIP], 0xffffffff |
je @f |
mov eax, [edx + IP_PACKET.SourceAddress] ; get the Source address from the IP packet |
cmp [ebx + SOCKET.RemoteIP], eax |
jne .exit ; Quit if the source IP is not valid |
@@: ; OK - we have a valid UDP packet for this socket. |
; First, update the sockets remote port number with the incoming msg |
; - it will have changed |
; from the original ( 69 normally ) to allow further connects |
mov ax, [edx + 20 + UDP_PACKET.SourcePort] ; get the UDP source port |
; ( was 69, now new ) |
mov [ebx + SOCKET.RemotePort], ax |
; Now, copy data to socket. We have socket address as [eax + sockets]. |
; We have IP packet in edx |
; get # of bytes in ecx |
movzx ecx, [edx + IP_PACKET.TotalLength] ; total length of IP packet. Subtract |
xchg cl, ch ; 20 + 8 gives data length |
sub ecx, 28 |
mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer |
add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer |
; ecx has count, edx points to data |
add edx, 28 ; edx now points to the data |
lea edi, [ebx + eax + SOCKETHEADERSIZE] |
mov esi, edx |
cld |
rep movsb ; copy the data across |
; flag an event to the application |
mov eax, [ebx + SOCKET.PID] ; get socket owner PID |
mov ecx, 1 |
mov esi, TASK_DATA + TASKDATA.pid |
.next_pid: |
cmp [esi], eax |
je .found_pid |
inc ecx |
add esi, 0x20 |
cmp ecx, [TASK_COUNT] |
jbe .next_pid |
jmp .exit |
.found_pid: |
shl ecx, 8 |
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event |
mov [check_idle_semaphore], 200 |
.exit: |
pop eax |
call freeBuff ; Discard the packet |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; UDP.INC ;; |
;; ;; |
;; UDP Processes for Menuet OS TCP/IP stack ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;******************************************************************* |
; Interface |
; |
; udp_rx Handles received IP packets with the UDP protocol |
; |
;******************************************************************* |
; |
; UDP Payload ( Data field in IP datagram ) |
; |
; 0 1 2 3 |
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
; |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Source Port | Destination Port | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Length ( UDP Header + Data ) | Checksum | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | UDP Data | |
; +-+-+-.......... -+ |
; |
struc UDP_PACKET |
{ .SourcePort dw ? ;+00 |
.DestinationPort dw ? ;+02 |
.Length dw ? ;+04 - Length of (UDP Header + Data) |
.Checksum dw ? ;+06 |
.Data db ? ;+08 |
} |
virtual at 0 |
UDP_PACKET UDP_PACKET |
end virtual |
;*************************************************************************** |
; Function |
; udp_rx [by Johnny_B] |
; |
; Description |
; UDP protocol handler |
; This is a kernel function, called by ip_rx |
; IP buffer address given in edx |
; IP buffer number in eax |
; Free up (or re-use) IP buffer when finished |
; |
;*************************************************************************** |
proc udp_rx stdcall |
push eax |
; First validate the header & checksum. Discard buffer if error |
; Look for a socket where |
; IP Packet UDP Destination Port = local Port |
; IP Packet SA = Remote IP |
mov ax, [edx + 20 + UDP_PACKET.DestinationPort] ; get the local port from |
; the IP packet's UDP header |
mov ebx, net_sockets |
.next_socket: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .exit ; No match, so exit |
cmp [ebx + SOCKET.LocalPort], ax ; ax will hold the 'wrong' value, |
; but the comparision is correct |
jne .next_socket ; Return back if no match |
; For dhcp, we must allow any remote server to respond. |
; I will accept the first incoming response to be the one |
; I bind to, if the socket is opened with a destination IP address of |
; 255.255.255.255 |
cmp [ebx + SOCKET.RemoteIP], 0xffffffff |
je @f |
mov eax, [edx + IP_PACKET.SourceAddress] ; get the Source address from the IP packet |
cmp [ebx + SOCKET.RemoteIP], eax |
jne .exit ; Quit if the source IP is not valid |
@@: ; OK - we have a valid UDP packet for this socket. |
; First, update the sockets remote port number with the incoming msg |
; - it will have changed |
; from the original ( 69 normally ) to allow further connects |
mov ax, [edx + 20 + UDP_PACKET.SourcePort] ; get the UDP source port |
; ( was 69, now new ) |
mov [ebx + SOCKET.RemotePort], ax |
; Now, copy data to socket. We have socket address as [eax + sockets]. |
; We have IP packet in edx |
; get # of bytes in ecx |
movzx ecx, [edx + IP_PACKET.TotalLength] ; total length of IP packet. Subtract |
xchg cl, ch ; 20 + 8 gives data length |
sub ecx, 28 |
mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer |
add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer |
; ecx has count, edx points to data |
add edx, 28 ; edx now points to the data |
lea edi, [ebx + eax + SOCKETHEADERSIZE] |
mov esi, edx |
cld |
rep movsb ; copy the data across |
; flag an event to the application |
mov eax, [ebx + SOCKET.PID] ; get socket owner PID |
mov ecx, 1 |
mov esi, TASK_DATA + TASKDATA.pid |
.next_pid: |
cmp [esi], eax |
je .found_pid |
inc ecx |
add esi, 0x20 |
cmp ecx, [TASK_COUNT] |
jbe .next_pid |
jmp .exit |
.found_pid: |
shl ecx, 8 |
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event |
mov [check_idle_semaphore], 200 |
.exit: |
pop eax |
call freeBuff ; Discard the packet |
ret |
endp |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/proc32.inc |
---|
1,271 → 1,271 |
$Revision$ |
; Macroinstructions for defining and calling procedures |
macro stdcall proc,[arg] ; directly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call proc } |
macro invoke proc,[arg] ; indirectly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call [proc] } |
macro ccall proc,[arg] ; directly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call proc |
if size@ccall |
add esp,size@ccall |
end if } |
macro cinvoke proc,[arg] ; indirectly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call [proc] |
if size@ccall |
add esp,size@ccall |
end if } |
macro proc [args] ; define procedure |
{ common |
match name params, args> |
\{ define@proc name,<params \} } |
prologue@proc equ prologuedef |
macro prologuedef procname,flag,parmbytes,localbytes,reglist |
{ if parmbytes | localbytes |
push ebp |
mov ebp,esp |
if localbytes |
sub esp,localbytes |
end if |
end if |
irps reg, reglist \{ push reg \} } |
epilogue@proc equ epiloguedef |
macro epiloguedef procname,flag,parmbytes,localbytes,reglist |
{ irps reg, reglist \{ reverse pop reg \} |
if parmbytes | localbytes |
leave |
end if |
if (flag and 10000b) | (parmbytes=0) |
retn |
else |
retn parmbytes |
end if } |
macro define@proc name,statement |
{ local params,flag,regs,parmbytes,localbytes,current |
if used name |
name: |
match =stdcall args, statement \{ params equ args |
flag = 11b \} |
match =stdcall, statement \{ params equ |
flag = 11b \} |
match =c args, statement \{ params equ args |
flag = 10001b \} |
match =c, statement \{ params equ |
flag = 10001b \} |
match =params, params \{ params equ statement |
flag = 0 \} |
virtual at ebp+8 |
match =uses reglist=,args, params \{ regs equ reglist |
params equ args \} |
match =regs =uses reglist, regs params \{ regs equ reglist |
params equ \} |
match =regs, regs \{ regs equ \} |
match =,args, params \{ defargs@proc args \} |
match =args@proc args, args@proc params \{ defargs@proc args \} |
parmbytes = $ - (ebp+8) |
end virtual |
name # % = parmbytes/4 |
all@vars equ |
current = 0 |
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \} |
macro locals |
\{ virtual at ebp-localbytes+current |
macro label . \\{ deflocal@proc .,:, \\} |
struc db [val] \\{ \common deflocal@proc .,db,val \\} |
struc dw [val] \\{ \common deflocal@proc .,dw,val \\} |
struc dp [val] \\{ \common deflocal@proc .,dp,val \\} |
struc dd [val] \\{ \common deflocal@proc .,dd,val \\} |
struc dt [val] \\{ \common deflocal@proc .,dt,val \\} |
struc dq [val] \\{ \common deflocal@proc .,dq,val \\} |
struc rb cnt \\{ deflocal@proc .,rb cnt, \\} |
struc rw cnt \\{ deflocal@proc .,rw cnt, \\} |
struc rp cnt \\{ deflocal@proc .,rp cnt, \\} |
struc rd cnt \\{ deflocal@proc .,rd cnt, \\} |
struc rt cnt \\{ deflocal@proc .,rt cnt, \\} |
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} |
macro endl |
\{ purge label |
restruc db,dw,dp,dd,dt,dq |
restruc rb,rw,rp,rd,rt,rq |
restruc byte,word,dword,pword,tword,qword |
current = $-(ebp-localbytes) |
end virtual \} |
macro ret operand |
\{ match any, operand \\{ retn operand \\} |
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> |
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} |
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 |
end if \} } |
macro defargs@proc [arg] |
{ common |
if ~ arg eq |
forward |
local ..arg,current@arg |
match argname:type, arg |
\{ current@arg equ argname |
label ..arg type |
argname equ ..arg |
if dqword eq type |
dd ?,?,?,? |
else if tbyte eq type |
dd ?,?,? |
else if qword eq type | pword eq type |
dd ?,? |
else |
dd ? |
end if \} |
match =current@arg,current@arg |
\{ current@arg equ arg |
arg equ ..arg |
..arg dd ? \} |
common |
args@proc equ current@arg |
forward |
restore current@arg |
common |
end if } |
macro deflocal@proc name,def,[val] |
{ common |
match vars, all@vars \{ all@vars equ all@vars, \} |
all@vars equ all@vars name |
forward |
local ..var,..tmp |
..var def val |
match =?, val \{ ..tmp equ \} |
match any =dup (=?), val \{ ..tmp equ \} |
match tmp : value, ..tmp : val |
\{ tmp: end virtual |
initlocal@proc ..var,def value |
virtual at tmp\} |
common |
match first rest, ..var, \{ name equ first \} } |
macro initlocal@proc name,def |
{ virtual at name |
def |
size@initlocal = $ - name |
end virtual |
position@initlocal = 0 |
while size@initlocal > position@initlocal |
virtual at name |
def |
if size@initlocal - position@initlocal < 2 |
current@initlocal = 1 |
load byte@initlocal byte from name+position@initlocal |
else if size@initlocal - position@initlocal < 4 |
current@initlocal = 2 |
load word@initlocal word from name+position@initlocal |
else |
current@initlocal = 4 |
load dword@initlocal dword from name+position@initlocal |
end if |
end virtual |
if current@initlocal = 1 |
mov byte [name+position@initlocal],byte@initlocal |
else if current@initlocal = 2 |
mov word [name+position@initlocal],word@initlocal |
else |
mov dword [name+position@initlocal],dword@initlocal |
end if |
position@initlocal = position@initlocal + current@initlocal |
end while } |
macro endp |
{ purge ret,locals,endl |
finish@proc |
purge finish@proc |
restore regs@proc |
match all,args@proc \{ restore all \} |
restore args@proc |
match all,all@vars \{ restore all \} } |
macro local [var] |
{ common |
locals |
forward done@local equ |
match varname[count]:vartype, var |
\{ match =BYTE, vartype \\{ varname rb count |
restore done@local \\} |
match =WORD, vartype \\{ varname rw count |
restore done@local \\} |
match =DWORD, vartype \\{ varname rd count |
restore done@local \\} |
match =PWORD, vartype \\{ varname rp count |
restore done@local \\} |
match =QWORD, vartype \\{ varname rq count |
restore done@local \\} |
match =TBYTE, vartype \\{ varname rt count |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
rq count+count |
restore done@local \\} |
match , done@local \\{ virtual |
varname vartype |
end virtual |
rb count*sizeof.\#vartype |
restore done@local \\} \} |
match :varname:vartype, done@local:var |
\{ match =BYTE, vartype \\{ varname db ? |
restore done@local \\} |
match =WORD, vartype \\{ varname dw ? |
restore done@local \\} |
match =DWORD, vartype \\{ varname dd ? |
restore done@local \\} |
match =PWORD, vartype \\{ varname dp ? |
restore done@local \\} |
match =QWORD, vartype \\{ varname dq ? |
restore done@local \\} |
match =TBYTE, vartype \\{ varname dt ? |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
dq ?,? |
restore done@local \\} |
match , done@local \\{ varname vartype |
restore done@local \\} \} |
match ,done@local |
\{ var |
restore done@local \} |
common |
endl } |
$Revision$ |
; Macroinstructions for defining and calling procedures |
macro stdcall proc,[arg] ; directly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call proc } |
macro invoke proc,[arg] ; indirectly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call [proc] } |
macro ccall proc,[arg] ; directly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call proc |
if size@ccall |
add esp, size@ccall |
end if } |
macro cinvoke proc,[arg] ; indirectly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call [proc] |
if size@ccall |
add esp, size@ccall |
end if } |
macro proc [args] ; define procedure |
{ common |
match name params, args> |
\{ define@proc name,<params \} } |
prologue@proc equ prologuedef |
macro prologuedef procname,flag,parmbytes,localbytes,reglist |
{ if parmbytes | localbytes |
push ebp |
mov ebp, esp |
if localbytes |
sub esp, localbytes |
end if |
end if |
irps reg, reglist \{ push reg \} } |
epilogue@proc equ epiloguedef |
macro epiloguedef procname,flag,parmbytes,localbytes,reglist |
{ irps reg, reglist \{ reverse pop reg \} |
if parmbytes | localbytes |
leave |
end if |
if (flag and 10000b) | (parmbytes=0) |
retn |
else |
retn parmbytes |
end if } |
macro define@proc name,statement |
{ local params,flag,regs,parmbytes,localbytes,current |
if used name |
name: |
match =stdcall args, statement \{ params equ args |
flag = 11b \} |
match =stdcall, statement \{ params equ |
flag = 11b \} |
match =c args, statement \{ params equ args |
flag = 10001b \} |
match =c, statement \{ params equ |
flag = 10001b \} |
match =params, params \{ params equ statement |
flag = 0 \} |
virtual at ebp+8 |
match =uses reglist=,args, params \{ regs equ reglist |
params equ args \} |
match =regs =uses reglist, regs params \{ regs equ reglist |
params equ \} |
match =regs, regs \{ regs equ \} |
match =,args, params \{ defargs@proc args \} |
match =args@proc args, args@proc params \{ defargs@proc args \} |
parmbytes = $ - (ebp+8) |
end virtual |
name # % = parmbytes/4 |
all@vars equ |
current = 0 |
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \} |
macro locals |
\{ virtual at ebp-localbytes+current |
macro label . \\{ deflocal@proc .,:, \\} |
struc db [val] \\{ \common deflocal@proc .,db,val \\} |
struc dw [val] \\{ \common deflocal@proc .,dw,val \\} |
struc dp [val] \\{ \common deflocal@proc .,dp,val \\} |
struc dd [val] \\{ \common deflocal@proc .,dd,val \\} |
struc dt [val] \\{ \common deflocal@proc .,dt,val \\} |
struc dq [val] \\{ \common deflocal@proc .,dq,val \\} |
struc rb cnt \\{ deflocal@proc .,rb cnt, \\} |
struc rw cnt \\{ deflocal@proc .,rw cnt, \\} |
struc rp cnt \\{ deflocal@proc .,rp cnt, \\} |
struc rd cnt \\{ deflocal@proc .,rd cnt, \\} |
struc rt cnt \\{ deflocal@proc .,rt cnt, \\} |
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} |
macro endl |
\{ purge label |
restruc db,dw,dp,dd,dt,dq |
restruc rb,rw,rp,rd,rt,rq |
restruc byte,word,dword,pword,tword,qword |
current = $-(ebp-localbytes) |
end virtual \} |
macro ret operand |
\{ match any, operand \\{ retn operand \\} |
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> |
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} |
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 |
end if \} } |
macro defargs@proc [arg] |
{ common |
if ~ arg eq |
forward |
local ..arg,current@arg |
match argname:type, arg |
\{ current@arg equ argname |
label ..arg type |
argname equ ..arg |
if dqword eq type |
dd ?,?,?,? |
else if tbyte eq type |
dd ?,?,? |
else if qword eq type | pword eq type |
dd ?,? |
else |
dd ? |
end if \} |
match =current@arg,current@arg |
\{ current@arg equ arg |
arg equ ..arg |
..arg dd ? \} |
common |
args@proc equ current@arg |
forward |
restore current@arg |
common |
end if } |
macro deflocal@proc name,def,[val] |
{ common |
match vars, all@vars \{ all@vars equ all@vars, \} |
all@vars equ all@vars name |
forward |
local ..var,..tmp |
..var def val |
match =?, val \{ ..tmp equ \} |
match any =dup (=?), val \{ ..tmp equ \} |
match tmp : value, ..tmp : val |
\{ tmp: end virtual |
initlocal@proc ..var,def value |
virtual at tmp\} |
common |
match first rest, ..var, \{ name equ first \} } |
macro initlocal@proc name,def |
{ virtual at name |
def |
size@initlocal = $ - name |
end virtual |
position@initlocal = 0 |
while size@initlocal > position@initlocal |
virtual at name |
def |
if size@initlocal - position@initlocal < 2 |
current@initlocal = 1 |
load byte@initlocal byte from name+position@initlocal |
else if size@initlocal - position@initlocal < 4 |
current@initlocal = 2 |
load word@initlocal word from name+position@initlocal |
else |
current@initlocal = 4 |
load dword@initlocal dword from name+position@initlocal |
end if |
end virtual |
if current@initlocal = 1 |
mov byte [name+position@initlocal], byte@initlocal |
else if current@initlocal = 2 |
mov word [name+position@initlocal], word@initlocal |
else |
mov dword [name+position@initlocal], dword@initlocal |
end if |
position@initlocal = position@initlocal + current@initlocal |
end while } |
macro endp |
{ purge ret,locals,endl |
finish@proc |
purge finish@proc |
restore regs@proc |
match all,args@proc \{ restore all \} |
restore args@proc |
match all,all@vars \{ restore all \} } |
macro local [var] |
{ common |
locals |
forward done@local equ |
match varname[count]:vartype, var |
\{ match =BYTE, vartype \\{ varname rb count |
restore done@local \\} |
match =WORD, vartype \\{ varname rw count |
restore done@local \\} |
match =DWORD, vartype \\{ varname rd count |
restore done@local \\} |
match =PWORD, vartype \\{ varname rp count |
restore done@local \\} |
match =QWORD, vartype \\{ varname rq count |
restore done@local \\} |
match =TBYTE, vartype \\{ varname rt count |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
rq count+count |
restore done@local \\} |
match , done@local \\{ virtual |
varname vartype |
end virtual |
rb count*sizeof.\#vartype |
restore done@local \\} \} |
match :varname:vartype, done@local:var |
\{ match =BYTE, vartype \\{ varname db ? |
restore done@local \\} |
match =WORD, vartype \\{ varname dw ? |
restore done@local \\} |
match =DWORD, vartype \\{ varname dd ? |
restore done@local \\} |
match =PWORD, vartype \\{ varname dp ? |
restore done@local \\} |
match =QWORD, vartype \\{ varname dq ? |
restore done@local \\} |
match =TBYTE, vartype \\{ varname dt ? |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
dq ?,? |
restore done@local \\} |
match , done@local \\{ varname vartype |
restore done@local \\} \} |
match ,done@local |
\{ var |
restore done@local \} |
common |
endl } |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot/after_win/fat.inc |
---|
1,509 → 1,509 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
load_file_fat: |
mov eax, [bp + root_clus - dat] |
mov [bp + cur_obj - dat], root_string |
push es |
push bx |
push cx |
.parse_dir_loop: |
; convert name to FAT name |
push [bp + cur_obj - dat] |
push ax |
mov [bp + cur_obj - dat], si |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
mov di, fat_filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
.nameloop: |
lodsb |
test al, al |
jz .namedone |
cmp al, '/' |
jz .namedone |
cmp al, '.' |
jz .namedot |
dec cx |
js .badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp .nameloop |
.namedot: |
inc bx |
jp .badname |
add di, cx |
mov cl, 3 |
jmp .nameloop |
.badname: |
mov si, badname_msg |
jmp find_error_si |
.namedone: |
; scan directory |
pop ax ; eax = cluster of directory |
; high word of eax is preserved by operations above |
push ds |
push si |
; read a folder sector-by-sector and scan |
; first, try to use the cache |
push ss |
pop ds |
mov bx, -2 |
mov cx, [bp + rootcache_size - dat] |
cmp [bp + root_clus - dat], eax |
jz .lookcache_root |
mov di, foldcache_mark |
xor bx, bx |
mov cx, [bp + cachelimit - dat] |
@@: |
lea si, [di+bx] |
mov edx, dword [foldcache_clus+si-foldcache_mark+bx] |
cmp edx, eax |
jz .cacheok |
test edx, edx |
jz .cacheadd ; the cache has place for new entry |
inc bx |
inc bx |
dec cx |
js @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov bx, -2 |
mov dx, [bp + cachelimit - dat] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
.cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
lea si, [di+bx] |
mov dword [foldcache_clus+si-foldcache_mark+bx], eax |
.cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [bp + cachelimit - dat] |
add di, di |
.cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns .cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
.lookcache_root: |
; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder |
;mov dx, bx |
;shl dx, 8 |
;add dx, 0x9200 |
lea dx, [bx + 0x92] |
xchg dl, dh |
mov ds, dx |
mov si, fat_filename ; ss:si -> filename in FAT style |
call fat_scan_for_filename |
jz .lookup_done |
; cache miss, read folder data from disk |
; we are reading parent directory, it can result in disk read errors; restore [cur_obj] |
mov di, sp |
mov bx, [bp + cur_obj - dat] |
xchg bx, [ss:di+4] |
mov [bp + cur_obj - dat], bx |
mov bx, cx |
add bx, 0xF |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
.folder_next_cluster: |
; internal loop: scan sectors in cluster |
movzx ecx, byte [ss:0x320D] ; BPB_SecPerClus |
push eax |
; FAT12/16 root - special handling |
test eax, eax |
jnz .folder_notroot |
mov cx, [ss:0x3211] ; BPB_RootEntCnt |
mov dx, cx |
add cx, 0xF |
rcr cx, 1 |
shr cx, 3 |
mov eax, [bp + root_start - dat] |
jmp .folder_next_sector |
.folder_notroot: |
mul ecx |
add eax, [bp + data_start - dat] |
.folder_next_sector: |
sub dx, 0x10 |
; skip first bx sectors |
dec bx |
jns .folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
call read |
jc ..found_disk_error |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
pusha |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
cmp di, 0x90 |
jz .update_rootcache_size |
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache |
jmp .updated_cachesize |
.update_rootcache_size: |
mov cl, 0x10 |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
add [bp + rootcache_size - dat], cx |
.updated_cachesize: |
popa |
@@: |
push es |
mov cl, 0x10 ; ch=0 at this point |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
call fat_scan_for_filename |
pop es |
pop cx |
jz .lookup_done_pop |
.folder_skip_sector: |
inc eax |
loop .folder_next_sector |
pop eax ; eax = current cluster |
test eax, eax |
jz @f |
call [bp + get_next_cluster_ptr - dat] |
jc .folder_next_cluster |
@@: |
stc |
push eax |
.lookup_done_pop: |
pop eax |
.lookup_done: |
pop si |
; CF=1 <=> failed |
jnc .found |
pop ds |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.found: |
mov eax, [di+20-2] |
mov edx, [di+28] |
mov ax, [di+26] ; get cluster |
test byte [di+11], 10h ; directory? |
pop ds |
pop [bp + cur_obj - dat] ; forget old [cur_obj] |
jz .regular_file |
cmp byte [si-1], 0 |
jnz .parse_dir_loop |
..directory_error: |
mov si, directory_string |
jmp find_error_si |
.regular_file: |
cmp byte [si-1], 0 |
jz @f |
..notdir_error: |
mov si, notdir_string |
jmp find_error_si |
@@: |
; ok, we have found a regular file and the caller requested it |
; parse FAT chunk |
push ss |
pop es |
push ss |
pop ds |
mov di, 0x4005 |
mov byte [di-5], 1 ; non-resident attribute |
mov dword [di-4], 1 |
stosd |
pop cx |
push cx |
.parsefat: |
call [bp + get_next_cluster_ptr - dat] |
jnc .done |
mov esi, [di-8] |
add esi, [di-4] |
cmp eax, esi |
jz .contc |
mov dword [di], 1 |
scasd |
stosd |
jmp @f |
.contc: |
inc dword [di-8] |
@@: |
sub cl, [0x320D] |
sbb ch, 0 |
ja .parsefat |
.done: |
xor eax, eax |
stosd |
mov si, 0x4000 |
load_file_common_end: |
xor ecx, ecx |
pop cx |
pop bx |
pop es |
mov [bp + filesize - dat], edx |
mov [bp + sectors_read - dat], ecx |
add edx, 0x1FF |
shr edx, 9 |
mov [bp + filesize_sectors - dat], edx |
cmp edx, ecx |
seta al |
mov ah, 0 |
push ax |
call read_file_chunk |
continue_load_common_end: |
mov [bp + cur_chunk_ptr - dat], si |
pop bx |
mov ax, word [bp + filesize - dat] |
mov dx, word [bp + filesize+2 - dat] |
jnc @f |
mov bl, 3 ; read error |
@@: |
ret |
continue_load_file: |
; es:bx -> buffer for output, ecx = cx = number of sectors |
mov si, [bp + cur_chunk_ptr - dat] |
push ecx |
add ecx, [bp + sectors_read - dat] |
mov [bp + sectors_read - dat], ecx |
cmp [bp + filesize_sectors - dat], ecx |
pop ecx |
seta al |
mov ah, 0 |
push ax |
push continue_load_common_end |
push ss |
pop ds |
cmp [bp + cur_chunk_resident - dat], ah |
jnz .nonresident |
.resident: |
mov ax, word [bp + num_sectors - dat] |
jmp read_file_chunk.resident.continue |
.nonresident: |
mov eax, [bp + cur_cluster - dat] |
mov edx, [bp + num_sectors - dat] |
add eax, [bp + cur_delta - dat] |
jmp read_file_chunk.nonresident.continue |
fat_scan_for_filename: |
; in: ss:si -> 11-bytes FAT name |
; in: ds:0 -> part of directory data |
; in: cx = number of entries |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
push ds |
pop es |
xor di, di |
push cx |
jcxz .noent |
.loop: |
cmp byte [di], 0 |
jz .notfound |
test byte [di+11], 8 ; volume label? |
jnz .cont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmps byte [ss:si], byte [es:di] |
popa |
jz .done |
.cont: |
add di, 0x20 |
loop .loop |
.noent: |
inc cx ; clear ZF flag |
.notfound: |
stc |
.done: |
pop cx |
ret |
fat12_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
push si |
push ds |
push 0x6000 |
pop ds |
mov si, ax |
shr si, 1 |
add si, ax |
test al, 1 |
lodsw |
jz @f |
shr ax, 4 |
@@: |
and ax, 0xFFF |
cmp ax, 0xFF7 |
pop ds si |
ret |
fat16_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
; each sector contains 200h bytes = 100h FAT entries |
; so ah = # of sector, al = offset in sector |
push si |
mov si, ax |
shr si, 8 |
; calculate segment for this sector of FAT table |
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) |
; segment = 6000 + 20*si, offset = 0 |
push es |
push si |
shl si, 5 |
add si, 0x6000 |
mov es, si |
pop si |
cmp byte [ss:0x3400+si], 0 ; sector already loaded? |
jnz .noread |
; load corresponding sector, try all FATs if disk read error detected |
pusha |
movzx di, byte [ss:0x3210] ; BPB_NumFATs |
xor bx, bx |
mov ax, [ss:0x320E] ; BPB_RsvdSecCnt |
xor dx, dx |
add ax, si |
adc dx, bx |
@@: |
push es |
push dx ax |
pop eax |
mov cx, 1 ; read 1 sector |
call read |
pop es |
jnc @f |
add ax, [ss:0x3216] ; BPB_FATSz16 |
adc dx, bx |
dec di |
jnz @b |
..found_disk_error: |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
popa |
.noread: |
mov si, ax |
and si, 0xFF |
add si, si |
mov ax, [es:si] |
pop es |
cmp ax, 0xFFF7 |
pop si |
ret |
fat32_get_next_cluster: |
; in: eax = cluster |
; out: if there is next cluster: CF=1, eax = next cluster |
; out: if there is no next cluster: CF=0 |
push di |
push ax |
shr eax, 7 |
; eax = FAT sector number; look in cache |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
jnc .noread |
; read FAT, try all FATs if disk read error detected |
push es |
pushad |
movzx edx, word [ss:0x320E] ; BPB_RsvdSecCnt |
add eax, edx |
movzx si, byte [ss:0x3210] ; BPB_NumFATs |
@@: |
lea cx, [di - 0x3400 + (0x6000 shr (9-3))] |
shl cx, 9-3 |
mov es, cx |
xor bx, bx |
mov cx, 1 |
call read |
jnc @f |
add eax, [ss:0x3224] ; BPB_FATSz32 |
dec si |
jnz @b |
jmp ..found_disk_error |
@@: |
popad |
pop es |
.noread: |
; get requested item |
lea ax, [di - 0x3400 + (0x6000 shr (9-3))] |
pop di |
and di, 0x7F |
shl di, 2 |
shl ax, 9-3 |
push ds |
mov ds, ax |
and byte [di+3], 0x0F |
mov eax, [di] |
pop ds |
pop di |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
ret |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
load_file_fat: |
mov eax, [bp + root_clus - dat] |
mov [bp + cur_obj - dat], root_string |
push es |
push bx |
push cx |
.parse_dir_loop: |
; convert name to FAT name |
push [bp + cur_obj - dat] |
push ax |
mov [bp + cur_obj - dat], si |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
mov di, fat_filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
.nameloop: |
lodsb |
test al, al |
jz .namedone |
cmp al, '/' |
jz .namedone |
cmp al, '.' |
jz .namedot |
dec cx |
js .badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp .nameloop |
.namedot: |
inc bx |
jp .badname |
add di, cx |
mov cl, 3 |
jmp .nameloop |
.badname: |
mov si, badname_msg |
jmp find_error_si |
.namedone: |
; scan directory |
pop ax ; eax = cluster of directory |
; high word of eax is preserved by operations above |
push ds |
push si |
; read a folder sector-by-sector and scan |
; first, try to use the cache |
push ss |
pop ds |
mov bx, -2 |
mov cx, [bp + rootcache_size - dat] |
cmp [bp + root_clus - dat], eax |
jz .lookcache_root |
mov di, foldcache_mark |
xor bx, bx |
mov cx, [bp + cachelimit - dat] |
@@: |
lea si, [di+bx] |
mov edx, dword [foldcache_clus+si-foldcache_mark+bx] |
cmp edx, eax |
jz .cacheok |
test edx, edx |
jz .cacheadd ; the cache has place for new entry |
inc bx |
inc bx |
dec cx |
js @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov bx, -2 |
mov dx, [bp + cachelimit - dat] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
.cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
lea si, [di+bx] |
mov dword [foldcache_clus+si-foldcache_mark+bx], eax |
.cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [bp + cachelimit - dat] |
add di, di |
.cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns .cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
.lookcache_root: |
; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder |
;mov dx, bx |
;shl dx, 8 |
;add dx, 0x9200 |
lea dx, [bx + 0x92] |
xchg dl, dh |
mov ds, dx |
mov si, fat_filename ; ss:si -> filename in FAT style |
call fat_scan_for_filename |
jz .lookup_done |
; cache miss, read folder data from disk |
; we are reading parent directory, it can result in disk read errors; restore [cur_obj] |
mov di, sp |
mov bx, [bp + cur_obj - dat] |
xchg bx, [ss:di+4] |
mov [bp + cur_obj - dat], bx |
mov bx, cx |
add bx, 0xF |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
.folder_next_cluster: |
; internal loop: scan sectors in cluster |
movzx ecx, byte [ss:0x320D] ; BPB_SecPerClus |
push eax |
; FAT12/16 root - special handling |
test eax, eax |
jnz .folder_notroot |
mov cx, [ss:0x3211] ; BPB_RootEntCnt |
mov dx, cx |
add cx, 0xF |
rcr cx, 1 |
shr cx, 3 |
mov eax, [bp + root_start - dat] |
jmp .folder_next_sector |
.folder_notroot: |
mul ecx |
add eax, [bp + data_start - dat] |
.folder_next_sector: |
sub dx, 0x10 |
; skip first bx sectors |
dec bx |
jns .folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
call read |
jc ..found_disk_error |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
pusha |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
cmp di, 0x90 |
jz .update_rootcache_size |
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache |
jmp .updated_cachesize |
.update_rootcache_size: |
mov cl, 0x10 |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
add [bp + rootcache_size - dat], cx |
.updated_cachesize: |
popa |
@@: |
push es |
mov cl, 0x10 ; ch=0 at this point |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
call fat_scan_for_filename |
pop es |
pop cx |
jz .lookup_done_pop |
.folder_skip_sector: |
inc eax |
loop .folder_next_sector |
pop eax ; eax = current cluster |
test eax, eax |
jz @f |
call [bp + get_next_cluster_ptr - dat] |
jc .folder_next_cluster |
@@: |
stc |
push eax |
.lookup_done_pop: |
pop eax |
.lookup_done: |
pop si |
; CF=1 <=> failed |
jnc .found |
pop ds |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.found: |
mov eax, [di+20-2] |
mov edx, [di+28] |
mov ax, [di+26] ; get cluster |
test byte [di+11], 10h ; directory? |
pop ds |
pop [bp + cur_obj - dat] ; forget old [cur_obj] |
jz .regular_file |
cmp byte [si-1], 0 |
jnz .parse_dir_loop |
..directory_error: |
mov si, directory_string |
jmp find_error_si |
.regular_file: |
cmp byte [si-1], 0 |
jz @f |
..notdir_error: |
mov si, notdir_string |
jmp find_error_si |
@@: |
; ok, we have found a regular file and the caller requested it |
; parse FAT chunk |
push ss |
pop es |
push ss |
pop ds |
mov di, 0x4005 |
mov byte [di-5], 1 ; non-resident attribute |
mov dword [di-4], 1 |
stosd |
pop cx |
push cx |
.parsefat: |
call [bp + get_next_cluster_ptr - dat] |
jnc .done |
mov esi, [di-8] |
add esi, [di-4] |
cmp eax, esi |
jz .contc |
mov dword [di], 1 |
scasd |
stosd |
jmp @f |
.contc: |
inc dword [di-8] |
@@: |
sub cl, [0x320D] |
sbb ch, 0 |
ja .parsefat |
.done: |
xor eax, eax |
stosd |
mov si, 0x4000 |
load_file_common_end: |
xor ecx, ecx |
pop cx |
pop bx |
pop es |
mov [bp + filesize - dat], edx |
mov [bp + sectors_read - dat], ecx |
add edx, 0x1FF |
shr edx, 9 |
mov [bp + filesize_sectors - dat], edx |
cmp edx, ecx |
seta al |
mov ah, 0 |
push ax |
call read_file_chunk |
continue_load_common_end: |
mov [bp + cur_chunk_ptr - dat], si |
pop bx |
mov ax, word [bp + filesize - dat] |
mov dx, word [bp + filesize+2 - dat] |
jnc @f |
mov bl, 3 ; read error |
@@: |
ret |
continue_load_file: |
; es:bx -> buffer for output, ecx = cx = number of sectors |
mov si, [bp + cur_chunk_ptr - dat] |
push ecx |
add ecx, [bp + sectors_read - dat] |
mov [bp + sectors_read - dat], ecx |
cmp [bp + filesize_sectors - dat], ecx |
pop ecx |
seta al |
mov ah, 0 |
push ax |
push continue_load_common_end |
push ss |
pop ds |
cmp [bp + cur_chunk_resident - dat], ah |
jnz .nonresident |
.resident: |
mov ax, word [bp + num_sectors - dat] |
jmp read_file_chunk.resident.continue |
.nonresident: |
mov eax, [bp + cur_cluster - dat] |
mov edx, [bp + num_sectors - dat] |
add eax, [bp + cur_delta - dat] |
jmp read_file_chunk.nonresident.continue |
fat_scan_for_filename: |
; in: ss:si -> 11-bytes FAT name |
; in: ds:0 -> part of directory data |
; in: cx = number of entries |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
push ds |
pop es |
xor di, di |
push cx |
jcxz .noent |
.loop: |
cmp byte [di], 0 |
jz .notfound |
test byte [di+11], 8 ; volume label? |
jnz .cont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmps byte [ss:si], byte [es:di] |
popa |
jz .done |
.cont: |
add di, 0x20 |
loop .loop |
.noent: |
inc cx ; clear ZF flag |
.notfound: |
stc |
.done: |
pop cx |
ret |
fat12_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
push si |
push ds |
push 0x6000 |
pop ds |
mov si, ax |
shr si, 1 |
add si, ax |
test al, 1 |
lodsw |
jz @f |
shr ax, 4 |
@@: |
and ax, 0xFFF |
cmp ax, 0xFF7 |
pop ds si |
ret |
fat16_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
; each sector contains 200h bytes = 100h FAT entries |
; so ah = # of sector, al = offset in sector |
push si |
mov si, ax |
shr si, 8 |
; calculate segment for this sector of FAT table |
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) |
; segment = 6000 + 20*si, offset = 0 |
push es |
push si |
shl si, 5 |
add si, 0x6000 |
mov es, si |
pop si |
cmp byte [ss:0x3400+si], 0 ; sector already loaded? |
jnz .noread |
; load corresponding sector, try all FATs if disk read error detected |
pusha |
movzx di, byte [ss:0x3210] ; BPB_NumFATs |
xor bx, bx |
mov ax, [ss:0x320E] ; BPB_RsvdSecCnt |
xor dx, dx |
add ax, si |
adc dx, bx |
@@: |
push es |
push dx ax |
pop eax |
mov cx, 1 ; read 1 sector |
call read |
pop es |
jnc @f |
add ax, [ss:0x3216] ; BPB_FATSz16 |
adc dx, bx |
dec di |
jnz @b |
..found_disk_error: |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
popa |
.noread: |
mov si, ax |
and si, 0xFF |
add si, si |
mov ax, [es:si] |
pop es |
cmp ax, 0xFFF7 |
pop si |
ret |
fat32_get_next_cluster: |
; in: eax = cluster |
; out: if there is next cluster: CF=1, eax = next cluster |
; out: if there is no next cluster: CF=0 |
push di |
push ax |
shr eax, 7 |
; eax = FAT sector number; look in cache |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
jnc .noread |
; read FAT, try all FATs if disk read error detected |
push es |
pushad |
movzx edx, word [ss:0x320E] ; BPB_RsvdSecCnt |
add eax, edx |
movzx si, byte [ss:0x3210] ; BPB_NumFATs |
@@: |
lea cx, [di - 0x3400 + (0x6000 shr (9-3))] |
shl cx, 9-3 |
mov es, cx |
xor bx, bx |
mov cx, 1 |
call read |
jnc @f |
add eax, [ss:0x3224] ; BPB_FATSz32 |
dec si |
jnz @b |
jmp ..found_disk_error |
@@: |
popad |
pop es |
.noread: |
; get requested item |
lea ax, [di - 0x3400 + (0x6000 shr (9-3))] |
pop di |
and di, 0x7F |
shl di, 2 |
shl ax, 9-3 |
push ds |
mov ds, ax |
and byte [di+3], 0x0F |
mov eax, [di] |
pop ds |
pop di |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot/after_win/kordldr.win.asm |
---|
1,921 → 1,924 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond |
; It is used when main bootloader is Windows loader. |
; this code is loaded: |
; NT/2k/XP: by ntldr to 0D00:0000 |
; 9x: by io.sys from config.sys to xxxx:0100 |
; Vista: by bootmgr to 0000:7C00 |
format binary |
use16 |
; in any case, we relocate this code to 0000:0600 |
org 0x600 |
; entry point for 9x and Vista booting |
call @f |
db 'NTFS' |
@@: |
pop si |
sub si, 3 |
cmp si, 100h |
jnz boot_vista |
mov si, load_question + 100h - 600h |
call out_string |
; mov si, answer + 100h - 0600h ; already is |
xxy: mov ah, 0 |
int 16h |
or al, 20h |
mov [si], al |
cmp al, 'y' |
jz xxz |
cmp al, 'n' |
jnz xxy |
; continue load Windows |
; call out_string |
; ret |
out_string: |
push bx |
@@: |
lodsb |
test al, al |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
pop bx |
ret |
xxz: |
; boot KordOS |
call out_string |
; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers, |
; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached |
xor di, di |
mov ds, di |
mov word [di+4], new01handler + 100h - 600h |
mov [di+6], cs |
pushf |
pop ax |
or ah, 1 |
push ax |
popf |
; we cannot issue INT 19h directly, because INT command clears TF |
; int 19h ; don't issue it directly, because INT command clears TF |
; so instead we use direct call |
; pushf ; there will be no IRET |
call far [di + 19h*4] |
xxt: |
xor di, di |
mov ds, di |
cmp word [di + 8*4+2], 0F000h |
jz @f |
les bx, [di + 8*4] |
mov eax, [es:bx+1] |
mov [di + 8*4], eax |
@@: |
mov si, 100h |
boot_vista: |
; relocate cs:si -> 0000:0600 |
push cs |
pop ds |
xor ax, ax |
mov es, ax |
mov di, 0x600 |
mov cx, 2000h/2 |
rep movsw |
jmp 0:real_entry |
load_question db 'Load KordOS? [y/n]: ',0 |
answer db ? |
db 13,10,0 |
new01handler: |
; [sp]=ip, [sp+2]=cs, [sp+4]=flags |
push bp |
mov bp, sp |
push ds |
lds bp, [bp+2] |
cmp word [ds:bp], 19cdh |
jz xxt |
pop ds |
pop bp |
iret |
; read from hard disk |
; in: eax = absolute sector |
; cx = number of sectors |
; es:bx -> buffer |
; out: CF=1 if error |
read: |
pushad |
add eax, [bp + partition_start - dat] |
cmp [bp + use_lba - dat], 0 |
jz .chs |
; LBA read |
push ds |
.lbado: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp + boot_drive - dat] |
mov ah, 42h |
int 13h |
jc .disk_error_lba |
add sp, 10h ; restore stack |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz .lbado |
pop ds |
popad |
ret |
.disk_error_lba: |
add sp, 14h |
pop ds |
popad |
stc |
ret |
.chs: |
pusha |
pop edi ; loword(edi) = di, hiword(edi) = si |
push bx |
; eax / (SectorsPerTrack) -> eax, remainder bx |
movzx esi, [bp + sectors - dat] |
xor edx, edx |
div esi |
mov bx, dx ; bx = sector-1 |
; eax -> dx:ax |
push eax |
pop ax |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp + heads - dat] |
; number of sectors: read no more than to end of track |
sub si, bx |
cmp cx, si |
jbe @f |
mov cx, si |
@@: |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector |
; convert to int13 format |
movzx edi, cx |
mov dh, dl |
mov dl, [bp + boot_drive - dat] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
add sp, 12 |
popad |
stc |
ret |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push edi |
popa |
add eax, edi |
sub cx, di |
jnz .chs |
popad |
ret |
disk_error2 db 'Fatal: cannot read partitions info: ' |
disk_error_msg db 'disk read error',0 |
disk_params_msg db 'Fatal: cannot get drive parameters',0 |
start_msg db 2,' KordOS bootloader',13,10,0 |
part_msg db 'looking at partition ' |
part_char db '0' ; will be incremented before writing message |
db ' ... ',0 |
errfs_msg db 'unknown filesystem',13,10,0 |
fatxx_msg db 'FATxx' |
newline db 13,10,0 |
ntfs_msg db 'NTFS',13,10,0 |
error_msg db 'Error' |
colon db ': ',0 |
root_string db '\',0 |
nomem_msg db 'No memory',0 |
filesys_string db '(filesystem)',0 |
directory_string db 'is a directory',0 |
notdir_string db 'not a directory',0 |
; entry point for NT/2k/XP booting |
; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256 |
repeat 600h + 256h - $ |
db 1 ; any data can be here; 1 in ASCII is a nice face :) |
end repeat |
; cs=es=0D00, ds=07C0, ss=0 |
; esi=edi=ebp=0, esp=7C00 |
xor si, si |
jmp boot_vista |
real_entry: |
; ax = 0 |
mov ds, ax |
mov es, ax |
; our stack is 4 Kb: memory range 2000-3000 |
mov ss, ax |
mov sp, 3000h |
mov bp, dat |
sti ; just for case |
; say hi to user |
mov si, start_msg |
call out_string |
; we are booting from hard disk identified by [boot_drive] |
mov dl, [bp + boot_drive - dat] |
; is LBA supported? |
mov [bp + use_lba - dat], 0 |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
jc .no_lba |
cmp bx, 0AA55h |
jnz .no_lba |
test cl, 1 |
jz .no_lba |
inc [bp + use_lba - dat] |
jmp disk_params_ok |
.no_lba: |
; get drive geometry |
mov ah, 8 |
mov dl, [bp + boot_drive - dat] |
int 13h |
jnc @f |
mov si, disk_params_msg |
call out_string |
jmp $ |
@@: |
movzx ax, dh |
inc ax |
mov [bp + heads - dat], ax |
and cx, 3Fh |
mov [bp + sectors - dat], cx |
disk_params_ok: |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 94000h / 1024 |
jc nomem |
shr ax, 3 |
mov [bp + cachelimit - dat], ax ; size of cache - 1 |
; scan all partitions |
new_partition_ex: |
xor eax, eax ; read first sector of current disk area |
mov [bp + extended_part_cur - dat], eax ; no extended partition yet |
mov [bp + cur_partition_ofs - dat], 31BEh ; start from first partition |
push es |
mov cx, 1 |
mov bx, 3000h |
call read |
pop es |
jnc new_partition |
mov si, disk_error2 |
call out_string |
jmp $ |
new_partition: |
mov bx, [bp + cur_partition_ofs - dat] |
mov al, [bx+4] ; partition type |
test al, al |
jz next_partition |
cmp al, 5 |
jz @f |
cmp al, 0xF |
jnz not_extended |
@@: |
; extended partition |
mov eax, [bx+8] ; partition start |
add eax, [bp + extended_part_start - dat] |
mov [bp + extended_part_cur - dat], eax |
next_partition: |
add [bp + cur_partition_ofs - dat], 10h |
cmp [bp + cur_partition_ofs - dat], 31FEh |
jb new_partition |
mov eax, [bp + extended_part_cur - dat] |
test eax, eax |
jz partitions_done |
cmp [bp + extended_part_start - dat], 0 |
jnz @f |
mov [bp + extended_part_start - dat], eax |
@@: |
mov [bp + extended_parent - dat], eax |
mov [bp + partition_start - dat], eax |
jmp new_partition_ex |
partitions_done: |
mov si, total_kaput |
call out_string |
jmp $ |
not_extended: |
mov eax, [bx+8] |
add eax, [bp + extended_parent - dat] |
mov [bp + partition_start - dat], eax |
; try to load from current partition |
; inform user |
mov si, part_msg |
inc [si + part_char - part_msg] |
call out_string |
; read bootsector |
xor eax, eax |
mov [bp + cur_obj - dat], filesys_string |
push es |
mov cx, 1 |
mov bx, 3200h |
call read |
pop es |
mov si, disk_error_msg |
jc find_error_si |
movzx si, byte [bx+13] |
mov word [bp + sect_per_clust - dat], si |
test si, si |
jz unknown_fs |
lea ax, [si-1] |
test si, ax |
jnz unknown_fs |
; determine file system |
; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h) |
cmp word [bx+11], 0x200 |
jnz unknown_fs |
; is it NTFS? |
cmp dword [bx+3], 'NTFS' |
jnz not_ntfs |
cmp byte [bx+16], bl |
jz ntfs |
not_ntfs: |
; is it FAT? FAT12/FAT16/FAT32? |
; get count of sectors to dword in cx:si |
mov si, [bx+19] |
xor cx, cx |
test si, si |
jnz @f |
mov si, [bx+32] |
mov cx, [bx+34] |
@@: |
xor eax, eax |
; subtract size of system area |
sub si, [bx+14] ; BPB_ResvdSecCnt |
sbb cx, ax |
mov ax, [bx+17] ; BPB_RootEntCnt |
add ax, 0xF |
rcr ax, 1 |
shr ax, 3 |
sub si, ax |
sbb cx, 0 |
push cx |
push si |
mov ax, word [bx+22] |
test ax, ax |
jnz @f |
mov eax, [bx+36] |
@@: |
movzx ecx, byte [bx+16] |
imul ecx, eax |
pop eax |
sub eax, ecx |
; now eax = count of sectors in the data region |
xor edx, edx |
div [bp + sect_per_clust - dat] |
; now eax = count of clusters in the data region |
mov si, fatxx_msg |
cmp eax, 0xFFF5 |
jae test_fat32 |
; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38 |
cmp byte [bx+38], 0x29 |
jnz not_fat |
cmp ax, 0xFF5 |
jae fat16 |
fat12: |
mov [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster |
mov di, cx ; BPB_NumFATs |
mov ax, '12' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
movzx ecx, word [bx+22] ; BPB_FATSz16 |
; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes) |
.fatloop: |
; if first copy is not readable, try to switch to other copies |
push 0x6000 |
pop es |
xor bx, bx |
movzx eax, word [0x320E] ; BPB_RsvdSecCnt |
push cx |
cmp cx, 12 |
jb @f |
mov cx, 12 |
@@: |
call read |
pop cx |
jnc fat1x_common |
add eax, ecx ; switch to next copy of FAT |
dec di |
jnz .fatloop |
mov si, disk_error_msg |
jmp find_error_si |
fat16: |
mov [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster |
mov ax, '16' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT16: init FAT cache - no sectors loaded |
mov di, 0x3400 |
xor ax, ax |
mov cx, 0x100/2 |
rep stosw |
fat1x_common: |
mov bx, 0x3200 |
movzx eax, word [bx+22] ; BPB_FATSz16 |
xor esi, esi ; no root cluster |
jmp fat_common |
test_fat32: |
; FAT32 bootsector has it at the offset +66 |
cmp byte [bx+66], 0x29 |
jnz not_fat |
mov [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster |
mov ax, '32' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT32 - init cache for FAT table: no sectors loaded |
lea si, [bp + cache1head - dat] |
mov [si], si ; no sectors in cache: |
mov [si+2], si ; 'prev' & 'next' links point to self |
mov [bp + cache1end - dat], 3400h ; first free item = 3400h |
mov [bp + cache1limit - dat], 3C00h |
mov eax, [bx+36] ; BPB_FATSz32 |
mov esi, [bx+44] ; BPB_RootClus |
jmp fat_common |
not_fat: |
unknown_fs: |
mov si, errfs_msg |
call out_string |
jmp next_partition |
fat_common: |
push ss |
pop es |
movzx edx, byte [bx+16] ; BPB_NumFATs |
mul edx |
mov [bp + root_start - dat], eax ; this is for FAT1x |
; eax = total size of all FAT tables, in sectors |
movzx ecx, word [bx+17] ; BPB_RootEntCnt |
add ecx, 0xF |
shr ecx, 4 |
add eax, ecx |
mov cx, word [bx+14] ; BPB_RsvdSecCnt |
add [bp + root_start - dat], ecx ; this is for FAT1x |
add eax, ecx |
; cluster 2 begins from sector eax |
movzx ebx, byte [bx+13] ; BPB_SecPerClus |
sub eax, ebx |
sub eax, ebx |
mov [bp + data_start - dat], eax |
; no clusters in folders cache |
mov di, foldcache_clus - 2 |
xor ax, ax |
mov cx, 7*8/2 + 1 |
rep stosw |
mov [bp + root_clus - dat], esi |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_fat |
load_secondary: |
push 0x1000 |
pop es |
xor bx, bx |
mov si, kernel_name |
mov cx, 0x30000 / 0x200 |
call [bp + load_file_ptr - dat] |
; say error if needed |
mov si, error_too_big |
dec bx |
js @f |
jz find_error_si |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
; fill loader information and jump to secondary loader |
mov al, 'h' ; boot device: hard drive |
mov ah, [bp + boot_drive - dat] |
sub ah, 80h ; boot device: identifier |
pop bx ; restore file system ID ('12'/'16'/'32'/'nt') |
mov si, callback |
jmp 1000h:0000h |
nomem: |
mov si, nomem_msg |
call out_string |
jmp $ |
ntfs: |
push 'nt' ; save for secondary loader |
mov si, ntfs_msg |
call out_string |
xor eax, eax |
mov [bp + data_start - dat], eax |
mov ecx, [bx+40h] ; frs_size |
cmp cl, al |
jg .1 |
neg cl |
inc ax |
shl eax, cl |
jmp .2 |
.1: |
mov eax, ecx |
shl eax, 9 |
.2: |
mov [bp + frs_size - dat], ax |
; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different |
; (at least with standard tools) |
; we allow extra size, but no more than 0x1000 bytes = 4 Kb |
mov si, invalid_volume_msg |
cmp eax, 0x1000 |
ja find_error_si |
; must be multiple of sector size |
test ax, 0x1FF |
jnz find_error_si |
shr ax, 9 |
xchg cx, ax |
; initialize cache - no data loaded |
lea si, [bp + cache1head - dat] |
mov [si], si |
mov [si+2], si |
mov word [si+4], 3400h ; first free item = 3400h |
mov word [si+6], 3400h + 8*8 ; 8 items in this cache |
; read first MFT record - description of MFT itself |
mov [bp + cur_obj - dat], mft_string |
mov eax, [bx+30h] ; mft_cluster |
mul [bp + sect_per_clust - dat] |
push 0x8000 |
pop es |
xor bx, bx |
push es |
call read |
pop ds |
call restore_usa |
; scan for unnamed $DATA attribute |
mov [bp + freeattr - dat], 4000h |
mov ax, 80h |
call load_attr |
push ss |
pop ds |
mov si, nodata_string |
jc find_error_si |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_ntfs |
jmp load_secondary |
find_error_si: |
push si |
find_error_sp: |
cmp [bp + in_callback - dat], 0 |
jnz error_in_callback |
push ss |
pop ds |
push ss |
pop es |
mov si, error_msg |
call out_string |
mov si, [bp + cur_obj - dat] |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
mov si, colon |
call out_string |
pop si |
call out_string |
mov si, newline |
call out_string |
mov sp, 0x3000 |
jmp next_partition |
error_in_callback: |
; return status: file not found, except for read errors |
mov bx, 2 |
cmp si, disk_error_msg |
jnz @f |
inc bx |
@@: |
mov ax, 0xFFFF |
mov dx, ax |
mov sp, 3000h - 6 |
ret |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 3000h |
mov bp, dat |
mov [bp + in_callback - dat], 1 |
push dx |
push cx |
; set ds:si -> ASCIIZ name |
lea si, [di+6] |
; set cx = limit in sectors; 4Kb = 8 sectors |
movzx ecx, word [di+4] |
shl cx, 3 |
; set es:bx = pointer to buffer |
les bx, [di] |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call [bp + load_file_ptr - dat] |
callback_ret_succ: |
clc |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
read_file_chunk.resident: |
; auxiliary label for read_file_chunk procedure |
mov di, bx |
lodsw |
read_file_chunk.resident.continue: |
mov dx, ax |
add dx, 0x1FF |
shr dx, 9 |
cmp dx, cx |
jbe @f |
mov ax, cx |
shl ax, 9 |
@@: |
xchg ax, cx |
rep movsb |
xchg ax, cx |
clc ; no disk error if no disk requests |
mov word [bp + num_sectors - dat], ax |
ret |
read_file_chunk: |
; in: ds:si -> file chunk |
; in: es:bx -> buffer for output |
; in: ecx = maximum number of sectors to read (high word must be 0) |
; out: CF=1 <=> disk read error |
lodsb |
mov [bp + cur_chunk_resident - dat], al |
test al, al |
jz .resident |
; normal case: load (non-resident) attribute from disk |
.read_block: |
lodsd |
xchg eax, edx |
test edx, edx |
jz .ret |
lodsd |
; eax = start cluster, edx = number of clusters, cx = limit in sectors |
imul eax, [bp + sect_per_clust - dat] |
add eax, [bp + data_start - dat] |
mov [bp + cur_cluster - dat], eax |
imul edx, [bp + sect_per_clust - dat] |
mov [bp + num_sectors - dat], edx |
and [bp + cur_delta - dat], 0 |
.nonresident.continue: |
cmp edx, ecx |
jb @f |
mov edx, ecx |
@@: |
test dx, dx |
jz .read_block |
add [bp + cur_delta - dat], edx |
sub [bp + num_sectors - dat], edx |
sub ecx, edx |
push cx |
mov cx, dx |
call read |
pop cx |
jc .ret |
test cx, cx |
jnz .read_block |
.ret: |
ret |
cache_lookup: |
; in: eax = value to look, si = pointer to cache structure |
; out: di->cache entry; CF=1 <=> the value was not found |
push ds bx |
push ss |
pop ds |
mov di, [si+2] |
.look: |
cmp di, si |
jz .not_in_cache |
cmp eax, [di+4] |
jz .in_cache |
mov di, [di+2] |
jmp .look |
.not_in_cache: |
; cache miss |
; cache is full? |
mov di, [si+4] |
cmp di, [si+6] |
jnz .cache_not_full |
; yes, delete the oldest entry |
mov di, [si] |
mov bx, [di] |
mov [si], bx |
push word [di+2] |
pop word [bx+2] |
jmp .cache_append |
.cache_not_full: |
; no, allocate new item |
add word [si+4], 8 |
.cache_append: |
mov [di+4], eax |
stc |
jmp @f |
.in_cache: |
; delete this sector from the list |
push si |
mov si, [di] |
mov bx, [di+2] |
mov [si+2], bx |
mov [bx], si |
pop si |
@@: |
; add new sector to the end of list |
mov bx, di |
xchg bx, [si+2] |
push word [bx] |
pop word [di] |
mov [bx], di |
mov [di+2], bx |
pop bx ds |
ret |
include 'fat.inc' |
include 'ntfs.inc' |
total_kaput db 13,10,'Fatal error: cannot load the secondary loader',0 |
error_too_big db 'file is too big',0 |
nodata_string db '$DATA ' |
error_not_found db 'not found',0 |
noindex_string db '$INDEX_ROOT not found',0 |
badname_msg db 'bad name for FAT',0 |
invalid_volume_msg db 'invalid volume',0 |
mft_string db '$MFT',0 |
fragmented_string db 'too fragmented file',0 |
invalid_read_request_string db 'cannot read attribute',0 |
kernel_name db 'kord/loader',0 |
align 4 |
dat: |
extended_part_start dd 0 ; start sector for main extended partition |
extended_part_cur dd ? ; start sector for current extended child |
extended_parent dd 0 ; start sector for current extended parent |
partition_start dd 0 ; start sector for current logical disk |
cur_partition_ofs dw ? ; offset in MBR data for current partition |
sect_per_clust dd 0 |
; change this variable if you want to boot from other physical drive |
boot_drive db 80h |
in_callback db 0 |
; uninitialized data |
use_lba db ? |
cur_chunk_resident db ? |
align 2 |
heads dw ? |
sectors dw ? |
cache1head rw 2 |
cache1end dw ? |
cache1limit dw ? |
data_start dd ? |
cachelimit dw ? |
load_file_ptr dw ? |
cur_obj dw ? |
missing_slash dw ? |
root_clus dd ? |
root_start dd ? |
get_next_cluster_ptr dw ? |
frs_size dw ? |
freeattr dw ? |
index_root dw ? |
index_alloc dw ? |
cur_index_seg dw ? |
cur_index_cache dw ? |
filesize dd ? |
filesize_sectors dd ? |
cur_cluster dd ? |
cur_delta dd ? |
num_sectors dd ? |
sectors_read dd ? |
cur_chunk_ptr dw ? |
rootcache_size dw ? ; must be immediately before foldcache_clus |
if $-dat >= 0x80 |
warning: unoptimal data displacement! |
end if |
foldcache_clus rd 7 |
foldcache_mark rw 7 |
foldcache_size rw 7 |
fat_filename rb 11 |
if $ > 2000h |
error: file is too big |
end if |
; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long |
repeat 0x2600 - $ |
db 2 ; any data can be here; 2 is another nice face in ASCII :) |
end repeat |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond |
; It is used when main bootloader is Windows loader. |
; this code is loaded: |
; NT/2k/XP: by ntldr to 0D00:0000 |
; 9x: by io.sys from config.sys to xxxx:0100 |
; Vista: by bootmgr to 0000:7C00 |
format binary |
use16 |
; in any case, we relocate this code to 0000:0600 |
org 0x600 |
; entry point for 9x and Vista booting |
call @f |
db 'NTFS' |
@@: |
pop si |
sub si, 3 |
cmp si, 100h |
jnz boot_vista |
mov si, load_question + 100h - 600h |
call out_string |
; mov si, answer + 100h - 0600h ; already is |
xxy: |
mov ah, 0 |
int 16h |
or al, 20h |
mov [si], al |
cmp al, 'y' |
jz xxz |
cmp al, 'n' |
jnz xxy |
; continue load Windows |
; call out_string |
; ret |
out_string: |
push bx |
@@: |
lodsb |
test al, al |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
pop bx |
ret |
xxz: |
; boot KordOS |
call out_string |
; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers, |
; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached |
xor di, di |
mov ds, di |
mov word [di+4], new01handler + 100h - 600h |
mov [di+6], cs |
pushf |
pop ax |
or ah, 1 |
push ax |
popf |
; we cannot issue INT 19h directly, because INT command clears TF |
; int 19h ; don't issue it directly, because INT command clears TF |
; so instead we use direct call |
; pushf ; there will be no IRET |
call far [di + 19h*4] |
xxt: |
xor di, di |
mov ds, di |
cmp word [di + 8*4+2], 0F000h |
jz @f |
les bx, [di + 8*4] |
mov eax, [es:bx+1] |
mov [di + 8*4], eax |
@@: |
mov si, 100h |
boot_vista: |
; relocate cs:si -> 0000:0600 |
push cs |
pop ds |
xor ax, ax |
mov es, ax |
mov di, 0x600 |
mov cx, 2000h/2 |
rep movsw |
jmp 0:real_entry |
load_question db 'Load KordOS? [y/n]: ',0 |
answer db ? |
db 13,10,0 |
new01handler: |
; [sp]=ip, [sp+2]=cs, [sp+4]=flags |
push bp |
mov bp, sp |
push ds |
lds bp, [bp+2] |
cmp word [ds:bp], 19cdh |
jz xxt |
pop ds |
pop bp |
iret |
; read from hard disk |
; in: eax = absolute sector |
; cx = number of sectors |
; es:bx -> buffer |
; out: CF=1 if error |
read: |
pushad |
add eax, [bp + partition_start - dat] |
cmp [bp + use_lba - dat], 0 |
jz .chs |
; LBA read |
push ds |
.lbado: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp + boot_drive - dat] |
mov ah, 42h |
int 13h |
jc .disk_error_lba |
add sp, 10h ; restore stack |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz .lbado |
pop ds |
popad |
ret |
.disk_error_lba: |
add sp, 14h |
pop ds |
popad |
stc |
ret |
.chs: |
pusha |
pop edi ; loword(edi) = di, hiword(edi) = si |
push bx |
; eax / (SectorsPerTrack) -> eax, remainder bx |
movzx esi, [bp + sectors - dat] |
xor edx, edx |
div esi |
mov bx, dx ; bx = sector-1 |
; eax -> dx:ax |
push eax |
pop ax |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp + heads - dat] |
; number of sectors: read no more than to end of track |
sub si, bx |
cmp cx, si |
jbe @f |
mov cx, si |
@@: |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector |
; convert to int13 format |
movzx edi, cx |
mov dh, dl |
mov dl, [bp + boot_drive - dat] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
add sp, 12 |
popad |
stc |
ret |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push edi |
popa |
add eax, edi |
sub cx, di |
jnz .chs |
popad |
ret |
disk_error2 db 'Fatal: cannot read partitions info: ' |
disk_error_msg db 'disk read error',0 |
disk_params_msg db 'Fatal: cannot get drive parameters',0 |
start_msg db 2,' KordOS bootloader',13,10,0 |
part_msg db 'looking at partition ' |
part_char db '0' ; will be incremented before writing message |
db ' ... ',0 |
errfs_msg db 'unknown filesystem',13,10,0 |
fatxx_msg db 'FATxx' |
newline db 13,10,0 |
ntfs_msg db 'NTFS',13,10,0 |
error_msg db 'Error' |
colon db ': ',0 |
root_string db '\',0 |
nomem_msg db 'No memory',0 |
filesys_string db '(filesystem)',0 |
directory_string db 'is a directory',0 |
notdir_string db 'not a directory',0 |
; entry point for NT/2k/XP booting |
; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256 |
repeat 600h + 256h - $ |
db 1 ; any data can be here; 1 in ASCII is a nice face :) |
end repeat |
; cs=es=0D00, ds=07C0, ss=0 |
; esi=edi=ebp=0, esp=7C00 |
xor si, si |
jmp boot_vista |
real_entry: |
; ax = 0 |
mov ds, ax |
mov es, ax |
; our stack is 4 Kb: memory range 2000-3000 |
mov ss, ax |
mov sp, 3000h |
mov bp, dat |
sti ; just for case |
; say hi to user |
mov si, start_msg |
call out_string |
; we are booting from hard disk identified by [boot_drive] |
mov dl, [bp + boot_drive - dat] |
; is LBA supported? |
mov [bp + use_lba - dat], 0 |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
jc .no_lba |
cmp bx, 0AA55h |
jnz .no_lba |
test cl, 1 |
jz .no_lba |
inc [bp + use_lba - dat] |
jmp disk_params_ok |
.no_lba: |
; get drive geometry |
mov ah, 8 |
mov dl, [bp + boot_drive - dat] |
int 13h |
jnc @f |
mov si, disk_params_msg |
call out_string |
jmp $ |
@@: |
movzx ax, dh |
inc ax |
mov [bp + heads - dat], ax |
and cx, 3Fh |
mov [bp + sectors - dat], cx |
disk_params_ok: |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 94000h / 1024 |
jc nomem |
shr ax, 3 |
mov [bp + cachelimit - dat], ax ; size of cache - 1 |
; scan all partitions |
new_partition_ex: |
xor eax, eax ; read first sector of current disk area |
mov [bp + extended_part_cur - dat], eax ; no extended partition yet |
mov [bp + cur_partition_ofs - dat], 31BEh ; start from first partition |
push es |
mov cx, 1 |
mov bx, 3000h |
call read |
pop es |
jnc new_partition |
mov si, disk_error2 |
call out_string |
jmp $ |
new_partition: |
mov bx, [bp + cur_partition_ofs - dat] |
mov al, [bx+4] ; partition type |
test al, al |
jz next_partition |
cmp al, 5 |
jz @f |
cmp al, 0xF |
jnz not_extended |
@@: |
; extended partition |
mov eax, [bx+8] ; partition start |
add eax, [bp + extended_part_start - dat] |
mov [bp + extended_part_cur - dat], eax |
next_partition: |
add [bp + cur_partition_ofs - dat], 10h |
cmp [bp + cur_partition_ofs - dat], 31FEh |
jb new_partition |
mov eax, [bp + extended_part_cur - dat] |
test eax, eax |
jz partitions_done |
cmp [bp + extended_part_start - dat], 0 |
jnz @f |
mov [bp + extended_part_start - dat], eax |
@@: |
mov [bp + extended_parent - dat], eax |
mov [bp + partition_start - dat], eax |
jmp new_partition_ex |
partitions_done: |
mov si, total_kaput |
call out_string |
jmp $ |
not_extended: |
mov eax, [bx+8] |
add eax, [bp + extended_parent - dat] |
mov [bp + partition_start - dat], eax |
; try to load from current partition |
; inform user |
mov si, part_msg |
inc [si + part_char - part_msg] |
call out_string |
; read bootsector |
xor eax, eax |
mov [bp + cur_obj - dat], filesys_string |
push es |
mov cx, 1 |
mov bx, 3200h |
call read |
pop es |
mov si, disk_error_msg |
jc find_error_si |
movzx si, byte [bx+13] |
mov word [bp + sect_per_clust - dat], si |
test si, si |
jz unknown_fs |
lea ax, [si-1] |
test si, ax |
jnz unknown_fs |
; determine file system |
; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h) |
cmp word [bx+11], 0x200 |
jnz unknown_fs |
; is it NTFS? |
cmp dword [bx+3], 'NTFS' |
jnz not_ntfs |
cmp byte [bx+16], bl |
jz ntfs |
not_ntfs: |
; is it FAT? FAT12/FAT16/FAT32? |
; get count of sectors to dword in cx:si |
mov si, [bx+19] |
xor cx, cx |
test si, si |
jnz @f |
mov si, [bx+32] |
mov cx, [bx+34] |
@@: |
xor eax, eax |
; subtract size of system area |
sub si, [bx+14] ; BPB_ResvdSecCnt |
sbb cx, ax |
mov ax, [bx+17] ; BPB_RootEntCnt |
add ax, 0xF |
rcr ax, 1 |
shr ax, 3 |
sub si, ax |
sbb cx, 0 |
push cx |
push si |
mov ax, word [bx+22] |
test ax, ax |
jnz @f |
mov eax, [bx+36] |
@@: |
movzx ecx, byte [bx+16] |
imul ecx, eax |
pop eax |
sub eax, ecx |
; now eax = count of sectors in the data region |
xor edx, edx |
div [bp + sect_per_clust - dat] |
; now eax = count of clusters in the data region |
mov si, fatxx_msg |
cmp eax, 0xFFF5 |
jae test_fat32 |
; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38 |
cmp byte [bx+38], 0x29 |
jnz not_fat |
cmp ax, 0xFF5 |
jae fat16 |
fat12: |
mov [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster |
mov di, cx ; BPB_NumFATs |
mov ax, '12' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
movzx ecx, word [bx+22] ; BPB_FATSz16 |
; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes) |
.fatloop: |
; if first copy is not readable, try to switch to other copies |
push 0x6000 |
pop es |
xor bx, bx |
movzx eax, word [0x320E] ; BPB_RsvdSecCnt |
push cx |
cmp cx, 12 |
jb @f |
mov cx, 12 |
@@: |
call read |
pop cx |
jnc fat1x_common |
add eax, ecx ; switch to next copy of FAT |
dec di |
jnz .fatloop |
mov si, disk_error_msg |
jmp find_error_si |
fat16: |
mov [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster |
mov ax, '16' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT16: init FAT cache - no sectors loaded |
mov di, 0x3400 |
xor ax, ax |
mov cx, 0x100/2 |
rep stosw |
fat1x_common: |
mov bx, 0x3200 |
movzx eax, word [bx+22] ; BPB_FATSz16 |
xor esi, esi ; no root cluster |
jmp fat_common |
test_fat32: |
; FAT32 bootsector has it at the offset +66 |
cmp byte [bx+66], 0x29 |
jnz not_fat |
mov [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster |
mov ax, '32' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT32 - init cache for FAT table: no sectors loaded |
lea si, [bp + cache1head - dat] |
mov [si], si ; no sectors in cache: |
mov [si+2], si ; 'prev' & 'next' links point to self |
mov [bp + cache1end - dat], 3400h ; first free item = 3400h |
mov [bp + cache1limit - dat], 3C00h |
mov eax, [bx+36] ; BPB_FATSz32 |
mov esi, [bx+44] ; BPB_RootClus |
jmp fat_common |
not_fat: |
unknown_fs: |
mov si, errfs_msg |
call out_string |
jmp next_partition |
fat_common: |
push ss |
pop es |
movzx edx, byte [bx+16] ; BPB_NumFATs |
mul edx |
mov [bp + root_start - dat], eax ; this is for FAT1x |
; eax = total size of all FAT tables, in sectors |
movzx ecx, word [bx+17] ; BPB_RootEntCnt |
add ecx, 0xF |
shr ecx, 4 |
add eax, ecx |
mov cx, word [bx+14] ; BPB_RsvdSecCnt |
add [bp + root_start - dat], ecx ; this is for FAT1x |
add eax, ecx |
; cluster 2 begins from sector eax |
movzx ebx, byte [bx+13] ; BPB_SecPerClus |
sub eax, ebx |
sub eax, ebx |
mov [bp + data_start - dat], eax |
; no clusters in folders cache |
mov di, foldcache_clus - 2 |
xor ax, ax |
mov cx, 7*8/2 + 1 |
rep stosw |
mov [bp + root_clus - dat], esi |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_fat |
load_secondary: |
push 0x1000 |
pop es |
xor bx, bx |
mov si, kernel_name |
mov cx, 0x30000 / 0x200 |
call [bp + load_file_ptr - dat] |
; say error if needed |
mov si, error_too_big |
dec bx |
js @f |
jz find_error_si |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
; fill loader information and jump to secondary loader |
mov al, 'h' ; boot device: hard drive |
mov ah, [bp + boot_drive - dat] |
sub ah, 80h ; boot device: identifier |
pop bx ; restore file system ID ('12'/'16'/'32'/'nt') |
mov si, callback |
jmp 1000h:0000h |
nomem: |
mov si, nomem_msg |
call out_string |
jmp $ |
ntfs: |
push 'nt' ; save for secondary loader |
mov si, ntfs_msg |
call out_string |
xor eax, eax |
mov [bp + data_start - dat], eax |
mov ecx, [bx+40h] ; frs_size |
cmp cl, al |
jg .1 |
neg cl |
inc ax |
shl eax, cl |
jmp .2 |
.1: |
mov eax, ecx |
shl eax, 9 |
.2: |
mov [bp + frs_size - dat], ax |
; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different |
; (at least with standard tools) |
; we allow extra size, but no more than 0x1000 bytes = 4 Kb |
mov si, invalid_volume_msg |
cmp eax, 0x1000 |
ja find_error_si |
; must be multiple of sector size |
test ax, 0x1FF |
jnz find_error_si |
shr ax, 9 |
xchg cx, ax |
; initialize cache - no data loaded |
lea si, [bp + cache1head - dat] |
mov [si], si |
mov [si+2], si |
mov word [si+4], 3400h ; first free item = 3400h |
mov word [si+6], 3400h + 8*8 ; 8 items in this cache |
; read first MFT record - description of MFT itself |
mov [bp + cur_obj - dat], mft_string |
mov eax, [bx+30h] ; mft_cluster |
mul [bp + sect_per_clust - dat] |
push 0x8000 |
pop es |
xor bx, bx |
push es |
call read |
pop ds |
call restore_usa |
; scan for unnamed $DATA attribute |
mov [bp + freeattr - dat], 4000h |
mov ax, 80h |
call load_attr |
push ss |
pop ds |
mov si, nodata_string |
jc find_error_si |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_ntfs |
jmp load_secondary |
find_error_si: |
push si |
find_error_sp: |
cmp [bp + in_callback - dat], 0 |
jnz error_in_callback |
push ss |
pop ds |
push ss |
pop es |
mov si, error_msg |
call out_string |
mov si, [bp + cur_obj - dat] |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
mov si, colon |
call out_string |
pop si |
call out_string |
mov si, newline |
call out_string |
mov sp, 0x3000 |
jmp next_partition |
error_in_callback: |
; return status: file not found, except for read errors |
mov bx, 2 |
cmp si, disk_error_msg |
jnz @f |
inc bx |
@@: |
mov ax, 0xFFFF |
mov dx, ax |
mov sp, 3000h - 6 |
ret |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 3000h |
mov bp, dat |
mov [bp + in_callback - dat], 1 |
push dx |
push cx |
; set ds:si -> ASCIIZ name |
lea si, [di+6] |
; set cx = limit in sectors; 4Kb = 8 sectors |
movzx ecx, word [di+4] |
shl cx, 3 |
; set es:bx = pointer to buffer |
les bx, [di] |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call [bp + load_file_ptr - dat] |
callback_ret_succ: |
clc |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
read_file_chunk.resident: |
; auxiliary label for read_file_chunk procedure |
mov di, bx |
lodsw |
read_file_chunk.resident.continue: |
mov dx, ax |
add dx, 0x1FF |
shr dx, 9 |
cmp dx, cx |
jbe @f |
mov ax, cx |
shl ax, 9 |
@@: |
xchg ax, cx |
rep movsb |
xchg ax, cx |
clc ; no disk error if no disk requests |
mov word [bp + num_sectors - dat], ax |
ret |
read_file_chunk: |
; in: ds:si -> file chunk |
; in: es:bx -> buffer for output |
; in: ecx = maximum number of sectors to read (high word must be 0) |
; out: CF=1 <=> disk read error |
lodsb |
mov [bp + cur_chunk_resident - dat], al |
test al, al |
jz .resident |
; normal case: load (non-resident) attribute from disk |
.read_block: |
lodsd |
xchg eax, edx |
test edx, edx |
jz .ret |
lodsd |
; eax = start cluster, edx = number of clusters, cx = limit in sectors |
imul eax, [bp + sect_per_clust - dat] |
add eax, [bp + data_start - dat] |
mov [bp + cur_cluster - dat], eax |
imul edx, [bp + sect_per_clust - dat] |
mov [bp + num_sectors - dat], edx |
and [bp + cur_delta - dat], 0 |
.nonresident.continue: |
cmp edx, ecx |
jb @f |
mov edx, ecx |
@@: |
test dx, dx |
jz .read_block |
add [bp + cur_delta - dat], edx |
sub [bp + num_sectors - dat], edx |
sub ecx, edx |
push cx |
mov cx, dx |
call read |
pop cx |
jc .ret |
test cx, cx |
jnz .read_block |
.ret: |
ret |
cache_lookup: |
; in: eax = value to look, si = pointer to cache structure |
; out: di->cache entry; CF=1 <=> the value was not found |
push ds bx |
push ss |
pop ds |
mov di, [si+2] |
.look: |
cmp di, si |
jz .not_in_cache |
cmp eax, [di+4] |
jz .in_cache |
mov di, [di+2] |
jmp .look |
.not_in_cache: |
; cache miss |
; cache is full? |
mov di, [si+4] |
cmp di, [si+6] |
jnz .cache_not_full |
; yes, delete the oldest entry |
mov di, [si] |
mov bx, [di] |
mov [si], bx |
push word [di+2] |
pop word [bx+2] |
jmp .cache_append |
.cache_not_full: |
; no, allocate new item |
add word [si+4], 8 |
.cache_append: |
mov [di+4], eax |
stc |
jmp @f |
.in_cache: |
; delete this sector from the list |
push si |
mov si, [di] |
mov bx, [di+2] |
mov [si+2], bx |
mov [bx], si |
pop si |
@@: |
; add new sector to the end of list |
mov bx, di |
xchg bx, [si+2] |
push word [bx] |
pop word [di] |
mov [bx], di |
mov [di+2], bx |
pop bx ds |
ret |
include 'fat.inc' |
include 'ntfs.inc' |
total_kaput db 13,10,'Fatal error: cannot load the secondary loader',0 |
error_too_big db 'file is too big',0 |
nodata_string db '$DATA ' |
error_not_found db 'not found',0 |
noindex_string db '$INDEX_ROOT not found',0 |
badname_msg db 'bad name for FAT',0 |
invalid_volume_msg db 'invalid volume',0 |
mft_string db '$MFT',0 |
fragmented_string db 'too fragmented file',0 |
invalid_read_request_string db 'cannot read attribute',0 |
kernel_name db 'kord/loader',0 |
align 4 |
dat: |
extended_part_start dd 0 ; start sector for main extended partition |
extended_part_cur dd ? ; start sector for current extended child |
extended_parent dd 0 ; start sector for current extended parent |
partition_start dd 0 ; start sector for current logical disk |
cur_partition_ofs dw ? ; offset in MBR data for current partition |
sect_per_clust dd 0 |
; change this variable if you want to boot from other physical drive |
boot_drive db 80h |
in_callback db 0 |
; uninitialized data |
use_lba db ? |
cur_chunk_resident db ? |
align 2 |
heads dw ? |
sectors dw ? |
cache1head rw 2 |
cache1end dw ? |
cache1limit dw ? |
data_start dd ? |
cachelimit dw ? |
load_file_ptr dw ? |
cur_obj dw ? |
missing_slash dw ? |
root_clus dd ? |
root_start dd ? |
get_next_cluster_ptr dw ? |
frs_size dw ? |
freeattr dw ? |
index_root dw ? |
index_alloc dw ? |
cur_index_seg dw ? |
cur_index_cache dw ? |
filesize dd ? |
filesize_sectors dd ? |
cur_cluster dd ? |
cur_delta dd ? |
num_sectors dd ? |
sectors_read dd ? |
cur_chunk_ptr dw ? |
rootcache_size dw ? ; must be immediately before foldcache_clus |
if $-dat >= 0x80 |
warning: |
unoptimal data displacement! |
end if |
foldcache_clus rd 7 |
foldcache_mark rw 7 |
foldcache_size rw 7 |
fat_filename rb 11 |
if $ > 2000h |
error: |
file is too big |
end if |
; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long |
repeat 0x2600 - $ |
db 2 ; any data can be here; 2 is another nice face in ASCII :) |
end repeat |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot/after_win/ntfs.inc |
---|
1,587 → 1,587 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
restore_usa: |
; Update Sequence Array restore |
; in: ds:bx -> USA-protected structure |
push bx |
lea di, [bx+1feh] |
mov cx, [bx+6] |
add bx, [bx+4] |
dec cx |
@@: |
mov ax, [bx+2] |
mov [di], ax |
inc bx |
inc bx |
add di, 200h |
loop @b |
pop bx |
ret |
find_attr: |
; in: ds:di->file record, ax=attribute |
; out: ds:di->attribute or di=0 if not found |
add di, [di+14h] |
.1: |
; attributes' codes are formally dwords, but all of them fit in word |
cmp word [di], -1 |
jz .notfound |
cmp word [di], ax |
jnz .continue |
; for $DATA attribute, scan only unnamed |
cmp ax, 80h |
jnz .found |
cmp byte [di+9], 0 |
jz .found |
.continue: |
add di, [di+4] |
jmp .1 |
.notfound: |
xor di, di |
.found: |
ret |
process_mcb_nonres: |
; in: ds:si->attribute, es:di->buffer |
; out: es:di->buffer end |
pushad |
pop di |
add si, [si+20h] |
xor ebx, ebx |
.loop: |
lodsb |
test al, al |
jz .done |
push invalid_read_request_string |
movzx cx, al |
shr cx, 4 |
jz find_error_sp |
xchg ax, dx |
and dx, 0Fh |
jz find_error_sp |
add si, cx |
add si, dx |
pop ax |
push si |
dec si |
movsx eax, byte [si] |
dec cx |
jz .l1e |
.l1: |
dec si |
shl eax, 8 |
mov al, [si] |
loop .l1 |
.l1e: |
xchg ebp, eax |
dec si |
movsx eax, byte [si] |
mov cx, dx |
dec cx |
jz .l2e |
.l2: |
dec si |
shl eax, 8 |
mov al, byte [si] |
loop .l2 |
.l2e: |
pop si |
add ebx, ebp |
; eax=length, ebx=disk block |
stosd |
mov eax, ebx |
stosd |
cmp di, 0x8000 - 12 |
jbe .loop |
..attr_overflow: |
mov si, fragmented_string |
jmp find_error_si |
.done: |
xor ax, ax |
stosw |
stosw |
push di |
popad |
ret |
load_attr: |
; in: ax=attribute, ds:bx->base record |
; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, |
; edx=size of attribute in bytes |
; out: if not found: CF=1 |
mov di, [bp + freeattr - dat] |
push ss |
pop es |
mov byte [es:di], 1 |
inc di |
cmp di, 0x8000 - 12 |
ja ..attr_overflow |
or edx, -1 ; file size is not known yet |
; scan for attribute |
push di |
mov di, bx |
add di, [di+14h] |
@@: |
call find_attr.1 |
test di, di |
jz .notfound1 |
cmp byte [di+8], 0 |
jnz .nonresident |
mov si, di |
pop di |
push ds |
jmp .resident |
.aux_resident: |
mov ax, ds |
mov si, di |
pop di ds bx ds edx |
push ss |
pop es |
push ds |
mov ds, ax |
; resident attribute |
.resident: |
dec di |
mov al, 0 |
stosb |
mov ax, [si+10h] |
stosw |
push di |
add di, ax |
cmp di, 0x8000 - 12 |
pop di |
ja ..attr_overflow |
movzx edx, ax ; length of attribute |
xchg ax, cx |
add si, [si+14h] |
rep movsb |
mov [bp + freeattr - dat], di |
pop ds |
ret |
.nonresident: |
; nonresident attribute |
cmp dword [di+10h], 0 |
jnz @b |
; read start of data |
mov si, di |
mov edx, [di+30h] ; size of attribute |
pop di |
call process_mcb_nonres |
sub di, 4 |
push di |
.notfound1: |
pop di |
push edx |
; $ATTRIBUTE_LIST is always in base file record |
cmp ax, 20h |
jz .nofragmented |
; try to load $ATTRIBUTE_LIST = 20h |
push ax |
mov ax, 20h |
push [bp + freeattr - dat] |
mov [bp + freeattr - dat], di |
push di |
call load_attr |
pop di |
pop [bp + freeattr - dat] |
pop ax |
jc .nofragmented |
push ds bx |
pusha |
mov si, di |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
popa |
push ss |
pop es |
xor bx, bx |
.1: |
cmp [bx], ax |
jnz .continue1 |
; only unnamed $DATA attributes! |
cmp ax, 80h |
jnz @f |
cmp byte [bx+6], 0 |
jnz .continue1 |
@@: |
cmp dword [bx+10h], 0 |
jz .continue1 |
cmp dword [bx+8], 0 |
jnz @f |
dec di |
cmp di, [bp + freeattr - dat] |
lea di, [di+1] |
jnz .continue1 |
@@: |
push ds di |
push ax |
mov eax, [bx+10h] |
mov ecx, [bx+8] |
call read_file_record |
pop ax |
mov di, [14h] |
.2: |
call find_attr.1 |
cmp byte [di+8], 0 |
jz .aux_resident |
cmp dword [di+10h], ecx |
jnz .2 |
mov si, di |
mov di, sp |
cmp dword [ss:di+8], -1 |
jnz @f |
push dword [si+30h] ; size of attribute |
pop dword [ss:di+8] |
@@: |
pop di |
call process_mcb_nonres |
sub di, 4 |
pop ds |
.continue1: |
add bx, [bx+4] |
cmp bx, dx |
jb .1 |
pop bx ds |
.nofragmented: |
pop edx |
dec di |
cmp di, [bp + freeattr - dat] |
jnz @f |
stc |
ret |
@@: |
inc di |
xor ax, ax |
stosw |
stosw |
mov [bp + freeattr - dat], di |
ret |
read_file_record: |
; in: eax = index of record |
; out: ds:0 -> record |
; find place in cache |
push di |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
pushf |
sub di, 3400h |
shl di, 10-3 |
add di, 0x6000 |
mov ds, di |
popf |
pop di |
jnc .noread |
; read file record <eax> to ds:0 |
pushad |
push ds |
push es |
movzx ecx, [bp + frs_size - dat] |
shr cx, 9 |
mul ecx |
push ds |
pop es |
push ss |
pop ds |
mov si, 0x4000 |
xor bx, bx |
push [bp + cur_obj - dat] |
mov [bp + cur_obj - dat], mft_string |
push es |
call read_attr |
; initialize cache for $INDEX_ALLOCATION for this record |
pop si |
push si |
sub si, 0x6000 |
mov ax, si |
shr si, 10-3 |
shr ax, 2 |
add si, 3480h |
add ax, 3500h |
mov [si], si |
mov [si+2], si |
mov [si+4], ax |
pop ds |
call restore_usa |
pop [bp + cur_obj - dat] |
pop es |
pop ds |
popad |
.noread: |
ret |
read_attr: |
; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute |
push invalid_read_request_string |
cmp byte [si], 0 |
jnz .nonresident |
cmp eax, 10000h shr 9 |
jae find_error_sp |
shl ax, 9 |
shl cx, 9 |
cmp ax, [si+2] |
jae find_error_sp |
cmp cx, [si+2] |
ja find_error_sp |
add si, 3 |
add si, ax |
mov di, bx |
rep movsb |
pop ax |
ret |
.nonresident: |
inc si |
.loop: |
mov edx, dword [si] |
add si, 8 |
test edx, edx |
jz find_error_sp |
imul edx, [bp + sect_per_clust - dat] |
sub eax, edx |
jnc .loop |
add eax, edx |
sub edx, eax |
push cx |
cmp ecx, edx |
jb @f |
mov cx, dx |
@@: |
push bx |
mov ebx, [si-4] |
imul ebx, [bp + sect_per_clust - dat] |
add eax, ebx |
pop bx |
call read |
jc ..found_disk_error |
mov dx, cx |
pop cx |
xor eax, eax |
sub cx, dx |
jnz .loop |
pop ax |
ret |
load_file_ntfs: |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
push es bx cx |
mov eax, 5 ; root cluster |
mov [bp + cur_obj - dat], root_string |
.parse_dir_loop: |
push ds si |
call read_file_record |
; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP |
mov ax, [bp + freeattr - dat] |
mov [bp + index_root - dat], ax |
mov ax, 90h ; $INDEX_ROOT |
xor bx, bx |
call load_attr |
mov si, noindex_string |
jc find_error_si |
mov ax, [bp + freeattr - dat] |
mov [bp + index_alloc - dat], ax |
mov ax, 0A0h ; $INDEX_ALLOCATION |
call load_attr |
jnc @f |
mov [bp + index_alloc - dat], bx |
@@: |
push ds |
; search for entry |
mov si, [bp + index_root - dat] |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
mov si, invalid_read_request_string |
cmp word [bx+10], 0 |
jnz find_error_si |
; calculate number of items in cache |
mov di, [bx+8] ; subnode_size |
mov ax, 0x4000 |
sub ax, word [bp + frs_size - dat] |
cwd |
div di |
test ax, ax |
jz find_error_si |
mov si, invalid_volume_msg |
test di, 0x1FF |
jnz find_error_si |
pop cx |
mov [bp + cur_index_seg - dat], cx |
shl ax, 3 |
sub cx, 6000h |
mov si, cx |
shr cx, 2 |
shr si, 10-3 |
add cx, ax |
add si, 3480h |
mov [bp + cur_index_cache - dat], si |
add cx, 3500h |
mov [ss:si+6], cx |
mov dx, di |
add bx, 10h |
.scan_record: |
add bx, [bx] |
.scan: |
test byte [bx+0Ch], 2 |
jnz .look_child |
movzx cx, byte [bx+50h] ; namelen |
lea di, [bx+52h] ; name |
push ds |
pop es |
pop si ds |
push ds si |
xor ax, ax |
.1: |
lodsb |
cmp al, '/' |
jnz @f |
mov al, 0 |
@@: |
cmp al, 'A' |
jb .nocapital |
cmp al, 'Z' |
ja .nocapital |
or al, 20h |
.nocapital: |
cmp al, 'a' |
jb .notletter |
cmp al, 'z' |
ja .notletter |
or byte [es:di], 20h |
.notletter: |
scasw |
loopz .1 |
jb .look_child |
ja @f |
cmp byte [si], 0 |
jz .file_found |
cmp byte [si], '/' |
jz .file_found |
@@: |
push es |
pop ds |
add bx, [bx+8] |
jmp .scan |
.look_child: |
push es |
pop ds |
test byte [bx+0Ch], 1 |
jz .not_found |
mov si, [bp + index_alloc - dat] |
test si, si |
jz .not_found |
add bx, [bx+8] |
mov eax, [bx-8] |
mov es, [bp + cur_index_seg - dat] |
push si |
mov si, [bp + cur_index_cache - dat] |
call cache_lookup |
pop si |
pushf |
mov bx, di |
mov bh, 0 |
shr bx, 3 |
imul bx, dx |
add bx, [bp + frs_size - dat] |
popf |
jnc .noread |
push es |
push dx |
push ss |
pop ds |
movzx ecx, dx |
shr cx, 9 |
mul [bp + sect_per_clust - dat] |
call read_attr |
pop dx |
pop es |
push es |
pop ds |
call restore_usa |
.noread: |
push es |
pop ds |
add bx, 18h |
jmp .scan_record |
.not_found: |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.file_found: |
pop [bp + cur_obj - dat] |
pop cx |
mov ax, [bp + index_root - dat] |
mov [bp + freeattr - dat], ax |
mov eax, [es:bx] |
test byte [es:bx+48h+3], 10h |
jz .regular_file |
cmp byte [si], 0 |
jz ..directory_error |
inc si |
jmp .parse_dir_loop |
.regular_file: |
cmp byte [si], 0 |
jnz ..notdir_error |
; read entry |
call read_file_record |
xor bx, bx |
mov ax, 80h |
call load_attr |
mov si, nodata_string |
jc find_error_si |
mov si, [bp + index_root - dat] |
mov [bp + freeattr - dat], si |
push ss |
pop ds |
jmp load_file_common_end |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
restore_usa: |
; Update Sequence Array restore |
; in: ds:bx -> USA-protected structure |
push bx |
lea di, [bx+1feh] |
mov cx, [bx+6] |
add bx, [bx+4] |
dec cx |
@@: |
mov ax, [bx+2] |
mov [di], ax |
inc bx |
inc bx |
add di, 200h |
loop @b |
pop bx |
ret |
find_attr: |
; in: ds:di->file record, ax=attribute |
; out: ds:di->attribute or di=0 if not found |
add di, [di+14h] |
.1: |
; attributes' codes are formally dwords, but all of them fit in word |
cmp word [di], -1 |
jz .notfound |
cmp word [di], ax |
jnz .continue |
; for $DATA attribute, scan only unnamed |
cmp ax, 80h |
jnz .found |
cmp byte [di+9], 0 |
jz .found |
.continue: |
add di, [di+4] |
jmp .1 |
.notfound: |
xor di, di |
.found: |
ret |
process_mcb_nonres: |
; in: ds:si->attribute, es:di->buffer |
; out: es:di->buffer end |
pushad |
pop di |
add si, [si+20h] |
xor ebx, ebx |
.loop: |
lodsb |
test al, al |
jz .done |
push invalid_read_request_string |
movzx cx, al |
shr cx, 4 |
jz find_error_sp |
xchg ax, dx |
and dx, 0Fh |
jz find_error_sp |
add si, cx |
add si, dx |
pop ax |
push si |
dec si |
movsx eax, byte [si] |
dec cx |
jz .l1e |
.l1: |
dec si |
shl eax, 8 |
mov al, [si] |
loop .l1 |
.l1e: |
xchg ebp, eax |
dec si |
movsx eax, byte [si] |
mov cx, dx |
dec cx |
jz .l2e |
.l2: |
dec si |
shl eax, 8 |
mov al, byte [si] |
loop .l2 |
.l2e: |
pop si |
add ebx, ebp |
; eax=length, ebx=disk block |
stosd |
mov eax, ebx |
stosd |
cmp di, 0x8000 - 12 |
jbe .loop |
..attr_overflow: |
mov si, fragmented_string |
jmp find_error_si |
.done: |
xor ax, ax |
stosw |
stosw |
push di |
popad |
ret |
load_attr: |
; in: ax=attribute, ds:bx->base record |
; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, |
; edx=size of attribute in bytes |
; out: if not found: CF=1 |
mov di, [bp + freeattr - dat] |
push ss |
pop es |
mov byte [es:di], 1 |
inc di |
cmp di, 0x8000 - 12 |
ja ..attr_overflow |
or edx, -1 ; file size is not known yet |
; scan for attribute |
push di |
mov di, bx |
add di, [di+14h] |
@@: |
call find_attr.1 |
test di, di |
jz .notfound1 |
cmp byte [di+8], 0 |
jnz .nonresident |
mov si, di |
pop di |
push ds |
jmp .resident |
.aux_resident: |
mov ax, ds |
mov si, di |
pop di ds bx ds edx |
push ss |
pop es |
push ds |
mov ds, ax |
; resident attribute |
.resident: |
dec di |
mov al, 0 |
stosb |
mov ax, [si+10h] |
stosw |
push di |
add di, ax |
cmp di, 0x8000 - 12 |
pop di |
ja ..attr_overflow |
movzx edx, ax ; length of attribute |
xchg ax, cx |
add si, [si+14h] |
rep movsb |
mov [bp + freeattr - dat], di |
pop ds |
ret |
.nonresident: |
; nonresident attribute |
cmp dword [di+10h], 0 |
jnz @b |
; read start of data |
mov si, di |
mov edx, [di+30h] ; size of attribute |
pop di |
call process_mcb_nonres |
sub di, 4 |
push di |
.notfound1: |
pop di |
push edx |
; $ATTRIBUTE_LIST is always in base file record |
cmp ax, 20h |
jz .nofragmented |
; try to load $ATTRIBUTE_LIST = 20h |
push ax |
mov ax, 20h |
push [bp + freeattr - dat] |
mov [bp + freeattr - dat], di |
push di |
call load_attr |
pop di |
pop [bp + freeattr - dat] |
pop ax |
jc .nofragmented |
push ds bx |
pusha |
mov si, di |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
popa |
push ss |
pop es |
xor bx, bx |
.1: |
cmp [bx], ax |
jnz .continue1 |
; only unnamed $DATA attributes! |
cmp ax, 80h |
jnz @f |
cmp byte [bx+6], 0 |
jnz .continue1 |
@@: |
cmp dword [bx+10h], 0 |
jz .continue1 |
cmp dword [bx+8], 0 |
jnz @f |
dec di |
cmp di, [bp + freeattr - dat] |
lea di, [di+1] |
jnz .continue1 |
@@: |
push ds di |
push ax |
mov eax, [bx+10h] |
mov ecx, [bx+8] |
call read_file_record |
pop ax |
mov di, [14h] |
.2: |
call find_attr.1 |
cmp byte [di+8], 0 |
jz .aux_resident |
cmp dword [di+10h], ecx |
jnz .2 |
mov si, di |
mov di, sp |
cmp dword [ss:di+8], -1 |
jnz @f |
push dword [si+30h] ; size of attribute |
pop dword [ss:di+8] |
@@: |
pop di |
call process_mcb_nonres |
sub di, 4 |
pop ds |
.continue1: |
add bx, [bx+4] |
cmp bx, dx |
jb .1 |
pop bx ds |
.nofragmented: |
pop edx |
dec di |
cmp di, [bp + freeattr - dat] |
jnz @f |
stc |
ret |
@@: |
inc di |
xor ax, ax |
stosw |
stosw |
mov [bp + freeattr - dat], di |
ret |
read_file_record: |
; in: eax = index of record |
; out: ds:0 -> record |
; find place in cache |
push di |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
pushf |
sub di, 3400h |
shl di, 10-3 |
add di, 0x6000 |
mov ds, di |
popf |
pop di |
jnc .noread |
; read file record <eax> to ds:0 |
pushad |
push ds |
push es |
movzx ecx, [bp + frs_size - dat] |
shr cx, 9 |
mul ecx |
push ds |
pop es |
push ss |
pop ds |
mov si, 0x4000 |
xor bx, bx |
push [bp + cur_obj - dat] |
mov [bp + cur_obj - dat], mft_string |
push es |
call read_attr |
; initialize cache for $INDEX_ALLOCATION for this record |
pop si |
push si |
sub si, 0x6000 |
mov ax, si |
shr si, 10-3 |
shr ax, 2 |
add si, 3480h |
add ax, 3500h |
mov [si], si |
mov [si+2], si |
mov [si+4], ax |
pop ds |
call restore_usa |
pop [bp + cur_obj - dat] |
pop es |
pop ds |
popad |
.noread: |
ret |
read_attr: |
; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute |
push invalid_read_request_string |
cmp byte [si], 0 |
jnz .nonresident |
cmp eax, 10000h shr 9 |
jae find_error_sp |
shl ax, 9 |
shl cx, 9 |
cmp ax, [si+2] |
jae find_error_sp |
cmp cx, [si+2] |
ja find_error_sp |
add si, 3 |
add si, ax |
mov di, bx |
rep movsb |
pop ax |
ret |
.nonresident: |
inc si |
.loop: |
mov edx, dword [si] |
add si, 8 |
test edx, edx |
jz find_error_sp |
imul edx, [bp + sect_per_clust - dat] |
sub eax, edx |
jnc .loop |
add eax, edx |
sub edx, eax |
push cx |
cmp ecx, edx |
jb @f |
mov cx, dx |
@@: |
push bx |
mov ebx, [si-4] |
imul ebx, [bp + sect_per_clust - dat] |
add eax, ebx |
pop bx |
call read |
jc ..found_disk_error |
mov dx, cx |
pop cx |
xor eax, eax |
sub cx, dx |
jnz .loop |
pop ax |
ret |
load_file_ntfs: |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
push es bx cx |
mov eax, 5 ; root cluster |
mov [bp + cur_obj - dat], root_string |
.parse_dir_loop: |
push ds si |
call read_file_record |
; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP |
mov ax, [bp + freeattr - dat] |
mov [bp + index_root - dat], ax |
mov ax, 90h ; $INDEX_ROOT |
xor bx, bx |
call load_attr |
mov si, noindex_string |
jc find_error_si |
mov ax, [bp + freeattr - dat] |
mov [bp + index_alloc - dat], ax |
mov ax, 0A0h ; $INDEX_ALLOCATION |
call load_attr |
jnc @f |
mov [bp + index_alloc - dat], bx |
@@: |
push ds |
; search for entry |
mov si, [bp + index_root - dat] |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
mov si, invalid_read_request_string |
cmp word [bx+10], 0 |
jnz find_error_si |
; calculate number of items in cache |
mov di, [bx+8] ; subnode_size |
mov ax, 0x4000 |
sub ax, word [bp + frs_size - dat] |
cwd |
div di |
test ax, ax |
jz find_error_si |
mov si, invalid_volume_msg |
test di, 0x1FF |
jnz find_error_si |
pop cx |
mov [bp + cur_index_seg - dat], cx |
shl ax, 3 |
sub cx, 6000h |
mov si, cx |
shr cx, 2 |
shr si, 10-3 |
add cx, ax |
add si, 3480h |
mov [bp + cur_index_cache - dat], si |
add cx, 3500h |
mov [ss:si+6], cx |
mov dx, di |
add bx, 10h |
.scan_record: |
add bx, [bx] |
.scan: |
test byte [bx+0Ch], 2 |
jnz .look_child |
movzx cx, byte [bx+50h] ; namelen |
lea di, [bx+52h] ; name |
push ds |
pop es |
pop si ds |
push ds si |
xor ax, ax |
.1: |
lodsb |
cmp al, '/' |
jnz @f |
mov al, 0 |
@@: |
cmp al, 'A' |
jb .nocapital |
cmp al, 'Z' |
ja .nocapital |
or al, 20h |
.nocapital: |
cmp al, 'a' |
jb .notletter |
cmp al, 'z' |
ja .notletter |
or byte [es:di], 20h |
.notletter: |
scasw |
loopz .1 |
jb .look_child |
ja @f |
cmp byte [si], 0 |
jz .file_found |
cmp byte [si], '/' |
jz .file_found |
@@: |
push es |
pop ds |
add bx, [bx+8] |
jmp .scan |
.look_child: |
push es |
pop ds |
test byte [bx+0Ch], 1 |
jz .not_found |
mov si, [bp + index_alloc - dat] |
test si, si |
jz .not_found |
add bx, [bx+8] |
mov eax, [bx-8] |
mov es, [bp + cur_index_seg - dat] |
push si |
mov si, [bp + cur_index_cache - dat] |
call cache_lookup |
pop si |
pushf |
mov bx, di |
mov bh, 0 |
shr bx, 3 |
imul bx, dx |
add bx, [bp + frs_size - dat] |
popf |
jnc .noread |
push es |
push dx |
push ss |
pop ds |
movzx ecx, dx |
shr cx, 9 |
mul [bp + sect_per_clust - dat] |
call read_attr |
pop dx |
pop es |
push es |
pop ds |
call restore_usa |
.noread: |
push es |
pop ds |
add bx, 18h |
jmp .scan_record |
.not_found: |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.file_found: |
pop [bp + cur_obj - dat] |
pop cx |
mov ax, [bp + index_root - dat] |
mov [bp + freeattr - dat], ax |
mov eax, [es:bx] |
test byte [es:bx+48h+3], 10h |
jz .regular_file |
cmp byte [si], 0 |
jz ..directory_error |
inc si |
jmp .parse_dir_loop |
.regular_file: |
cmp byte [si], 0 |
jnz ..notdir_error |
; read entry |
call read_file_record |
xor bx, bx |
mov ax, 80h |
call load_attr |
mov si, nodata_string |
jc find_error_si |
mov si, [bp + index_root - dat] |
mov [bp + freeattr - dat], si |
push ss |
pop ds |
jmp load_file_common_end |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot/cdfs/bootsect.asm |
---|
1,1024 → 1,1024 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
jmp far 0:real_start |
; special text |
org $+0x7C00 |
real_start: |
; initialize |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov es, ax |
cld |
sti |
mov [bootdrive], dl |
; check LBA support |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cl, 1 |
jz err_ |
; get file system information |
; scan for Primary Volume Descriptor |
db 66h |
push 10h-1 |
pop eax |
pvd_scan_loop: |
mov cx, 1 |
inc eax |
mov bx, 0x1000 |
call read_sectors |
jnc @f |
fatal_read_err: |
mov si, aReadError |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
@@: |
push ds |
pop es |
cmp word [bx+1], 'CD' |
jnz pvd_scan_loop |
cmp word [bx+3], '00' |
jnz pvd_scan_loop |
cmp byte [bx+5], '1' |
jnz pvd_scan_loop |
; we have found ISO9660 descriptor, look for type |
cmp byte [bx], 1 ; Primary Volume Descriptor? |
jz pvd_found |
cmp byte [bx], 0xFF ; Volume Descriptor Set Terminator? |
jnz pvd_scan_loop |
; Volume Descriptor Set Terminator reached, no PVD found - fatal error |
mov si, no_pvd |
jmp err_ |
pvd_found: |
add bx, 80h |
mov ax, [bx] |
mov [lb_size], ax |
; calculate number of logical blocks in one sector |
mov ax, 800h |
cwd |
div word [bx] |
mov [lb_per_sec], ax |
; get location of root directory |
mov di, root_location |
movzx eax, byte [bx+1Dh] |
add eax, [bx+1Eh] |
stosd |
; get memory size |
int 12h |
mov si, nomem_str |
cmp ax, 71000h / 400h |
jb err_ |
shr ax, 1 |
sub ax, 60000h / 800h |
mov [size_rest], ax |
mov [free_ptr], 60000h / 800h |
; load path table |
; if size > 62K => it's very strange, avoid using it |
; if size > (size of cache)/2 => avoid using it too |
mov ecx, [bx+4] |
cmp ecx, 0x10000 - 0x800 |
ja nopathtable |
shr ax, 1 |
cmp ax, 0x20 |
jae @f |
shl ax, 11 |
cmp cx, ax |
ja nopathtable |
@@: |
; size is ok, try to load it |
mov [pathtable_size], cx |
mov eax, [bx+12] |
xor edx, edx |
div dword [lb_per_sec] |
imul dx, [bx] |
mov [pathtable_start], dx |
add cx, dx |
call cx_to_sectors |
xor bx, bx |
push 6000h |
pop es |
call read_sectors |
jc nopathtable |
; path table has been loaded |
inc [use_path_table] |
sub [size_rest], cx |
add [free_ptr], cx |
nopathtable: |
; init cache |
mov ax, [size_rest] |
mov [cache_size], ax |
mov ax, [free_ptr] |
mov [cache_start], ax |
; load secondary loader |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
jnz noloader |
; set registers for secondary loader |
mov ah, [bootdrive] |
mov al, 'c' |
mov bx, 'is' |
mov si, callback |
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 |
noloader: |
mov si, aKernelNotFound |
jmp err_ |
read_sectors: |
; es:bx = pointer to data |
; eax = first sector |
; cx = number of sectors |
pushad |
push ds |
do_read_sectors: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
db 66h |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [cs:bootdrive] |
mov ah, 42h |
int 13h |
jc diskreaderr |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 7 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz do_read_sectors |
pop ds |
popad |
ret |
diskreaderr: |
add sp, 10h + 2*2 |
pop ds |
popad |
stc |
out_string.ret: |
ret |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz .ret |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aNoLBA db 'The drive does not support LBA!',0 |
aReadError db 'Read error',0 |
no_pvd db 'Primary Volume Descriptor not found!',0 |
nomem_str db 'No memory',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
load_file: |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
; parse path to the file |
lea si, [di+6] |
mov eax, [cs:root_location] |
cmp [cs:use_path_table], 0 |
jz parse_dir |
; scan for path in path table |
push di |
push 6000h |
pop es |
mov di, [cs:pathtable_start] ; es:di = pointer to current entry in path table |
mov dx, 1 ; dx = number of current entry in path table, start from 1 |
mov cx, [cs:pathtable_size] |
pathtable_newparent: |
mov bx, dx ; bx = number of current parent in path table: root = 1 |
scan_path_table_e: |
call is_last_component |
jnc path_table_scanned |
scan_path_table_i: |
cmp word [es:di+6], bx |
jb .next |
ja path_table_notfound |
call test_filename1 |
jc .next |
@@: |
lodsb |
cmp al, '/' |
jnz @b |
jmp pathtable_newparent |
.next: |
; go to next entry |
inc dx |
movzx ax, byte [es:di] |
add ax, 8+1 |
and al, not 1 |
add di, ax |
sub cx, ax |
ja scan_path_table_i |
path_table_notfound: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 2 ; file not found |
ret |
path_table_scanned: |
movzx eax, byte [es:di+1] |
add eax, [es:di+2] |
pop di |
parse_dir: |
; eax = logical block, ds:di -> information structure, ds:si -> file name |
; was the folder already read? |
push di ds |
push cs |
pop ds |
mov [cur_desc_end], 2000h |
mov bx, cachelist |
.scan1: |
mov bx, [bx+2] |
cmp bx, cachelist |
jz .notfound |
cmp [bx+4], eax |
jnz .scan1 |
.found: |
; yes; delete this item from the list (the following code will append this item to the tail) |
mov di, [bx] |
push word [bx+2] |
pop word [di+2] |
mov di, [bx+2] |
push word [bx] |
pop word [di] |
mov di, bx |
jmp .scan |
.notfound: |
; no; load first sector of the folder to get its size |
push eax |
push si |
mov si, 1 |
call load_phys_sector_for_lb_force |
mov bx, si |
pop si |
pop eax |
jnc @f |
; read error - return |
.readerr: |
pop ds |
.readerr2: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 3 |
ret |
@@: |
; first item of the folder describes the folder itself |
; do not cache too big folders: size < 64K and size <= (total cache size)/2 |
cmp word [bx+12], 0 |
jnz .nocache |
mov cx, [cache_size] ; cx = cache size in sectors |
shr cx, 1 ; cx = (cache size)/2 |
cmp cx, 0x20 |
jae @f |
shl cx, 11 |
cmp [bx+10], cx |
ja .nocache |
@@: |
; we want to cache this folder; get space for it |
mov cx, [bx+10] |
call cx_to_sectors |
jnz .yescache |
.nocache: |
push dword [bx+10] |
pop dword [cur_nocache_len] |
call lb_to_sector |
push ds |
pop es |
pop ds |
.nocache_loop: |
push eax |
mov dx, 1800h |
call scan_for_filename_in_sector |
mov cx, dx |
pop eax |
jnc .j_scandone |
sub cx, bx |
sub word [es:cur_nocache_len], cx |
sbb word [es:cur_nocache_len+2], 0 |
jb .j_scandone |
ja @f |
cmp word [es:cur_nocache_len], 0 |
jz .j_scandone |
@@: |
mov cx, 1 |
inc eax |
push es |
mov bx, 1000h |
call read_sectors |
pop es |
jc .readerr2 |
jmp .nocache_loop |
.j_scandone: |
jmp .scandone |
.yescache: |
push bx |
mov bx, [cachelist.head] |
.freeloop: |
cmp cx, [size_rest] |
jbe .sizeok |
@@: |
; if we are here: there is not enough free space, so we must delete old folders' data |
; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2). |
; one loop iteration: delete data of one folder |
pusha |
mov dx, [bx+10] |
mov es, dx ; es = segment of folder data to be deleted |
xor di, di |
mov ax, [bx+8] |
add ax, 0x7FF |
rcr ax, 1 |
shr ax, 10 |
push ax |
shl ax, 11-4 ; get number of paragraphs in folder data to be deleted |
mov cx, [cache_size] |
add cx, [cache_start] |
push ds |
push ax |
add ax, dx |
mov ds, ax |
pop ax |
shl cx, 11-4 |
sub cx, dx ; cx = number of paragraphs to be moved |
push si |
xor si, si |
; move cx paragraphs from ds:si to es:di to get free space in the end of cache |
@@: |
sub cx, 1000h |
jbe @f |
push cx |
mov cx, 8000h |
rep movsw |
mov cx, ds |
add cx, 1000h |
mov ds, cx |
mov cx, es |
add cx, 1000h |
mov es, cx |
pop cx |
jmp @b |
@@: |
add cx, 1000h |
shl cx, 3 |
rep movsw |
pop si |
pop ds |
; correct positions in cache for existing items |
mov cx, 80h |
mov di, 8400h |
.correct: |
cmp [di+10], dx |
jbe @f |
sub [di+10], ax |
@@: |
add di, 12 |
loop .correct |
; some additional space is free now |
pop ax |
add [size_rest], ax |
sub [free_ptr], ax |
; add cache item to the list of free items |
mov dx, [bx] |
mov ax, [free_cache_item] |
mov [bx], ax |
mov [free_cache_item], bx |
mov bx, dx |
; current iteration done |
popa |
jmp .freeloop |
.sizeok: |
mov [cachelist.head], bx |
mov word [bx+2], cachelist |
; allocate new item in cache |
mov di, [free_cache_item] |
test di, di |
jz .nofree |
push word [di] |
pop [free_cache_item] |
jmp @f |
.nofree: |
mov di, [last_cache_item] |
add [last_cache_item], 12 |
@@: |
pop bx |
push si di |
; mov [di+4], eax ; start of folder |
scasd |
stosd |
push ax |
mov ax, [free_ptr] |
shl ax, 11-4 |
mov [di+10-8], ax |
mov es, ax |
pop ax |
add [free_ptr], cx |
sub [size_rest], cx |
; read folder data |
; first sector is already in memory, 0000:bx |
pusha |
mov cx, [bx+10] |
mov [di+8-8], cx ; folder size in bytes |
mov si, bx |
xor di, di |
mov cx, 0x1800 |
sub cx, si |
rep movsb |
pop ax |
push di |
popa |
; read rest of folder |
mov esi, dword [lb_per_sec] |
add eax, esi |
dec si |
not si |
and ax, si |
mov si, word [bx+10] |
mov bx, di |
pop di |
sub si, bx |
jbe @f |
mov [cur_limit], esi |
call read_many_bytes |
pop si |
jnc .scan |
jmp .readerr |
@@: |
pop si |
.scan: |
; now we have required cache item; append it to the end of list |
mov bx, [cachelist.tail] |
mov [cachelist.tail], di |
mov [di+2], bx |
mov word [di], cachelist |
mov [bx], di |
; scan for given filename |
mov es, [di+10] |
mov dx, [di+8] |
pop ds |
xor bx, bx |
call scan_for_filename_in_sector |
.scandone: |
push cs |
pop es |
mov bx, 2000h |
cmp bx, [es:cur_desc_end] |
jnz filefound |
j_notfound: |
jmp path_table_notfound |
filefound: |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
@@: |
mov cl, [es:bx+8] |
test al, al |
jz @f |
; parse next component of file name |
test cl, 2 ; directory? |
jz j_notfound |
mov eax, [es:bx] |
pop di |
jmp parse_dir |
@@: |
test cl, 2 ; directory? |
jnz j_notfound ; do not allow read directories as regular files |
; ok, now load the file |
pop di |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; esi = limit in 4K blocks |
shl esi, 12 ; esi = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, 2000h |
loadloop: |
and [cur_start], 0 |
.loadnew: |
mov esi, [cur_limit] |
mov eax, [cur_start] |
add esi, eax |
mov [overflow], 1 |
sub esi, [di+4] |
jb @f |
xor esi, esi |
dec [overflow] |
@@: |
add esi, [di+4] ; esi = number of bytes to read |
mov [cur_start], esi |
sub esi, eax |
jz .loadcontinue |
xor edx, edx |
div dword [lb_size] ; eax = number of logical blocks to skip, |
mov [first_byte], dx; [first_byte] = number of bytes to skip in 1st block |
cmp byte [di+10], 0 |
jnz .interleaved |
add eax, [di] |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
jc .readerr3 |
.loadcontinue: |
mov [cur_chunk], di |
add di, 11 |
cmp di, [cur_desc_end] |
jae @f |
cmp [cur_limit], 0 |
jnz loadloop |
@@: |
mov bx, [overflow] |
.calclen: |
; calculate length of file |
xor ax, ax |
xor dx, dx |
mov di, 2000h |
@@: |
add ax, [di+4] |
adc dx, [di+6] |
add di, 11 |
cmp di, [cur_desc_end] |
jb @b |
ret |
.interleaved: |
mov [cur_unit_limit], esi |
push esi |
; skip first blocks |
movzx ecx, byte [di+9] ; Unit Size |
movzx esi, byte [di+10] ; Interleave Gap |
add si, cx |
mov edx, [di] |
@@: |
sub eax, ecx |
jb @f |
add edx, esi |
jmp @b |
@@: |
add ecx, eax ; ecx = number of logical blocks to skip |
lea eax, [ecx+edx] ; eax = first logical block |
pop esi |
.interleaved_loop: |
; get number of bytes in current file unit |
push eax |
movzx eax, byte [di+9] |
sub ax, cx |
imul eax, dword [lb_size] |
cmp eax, esi |
ja .i2 |
.i1: |
xchg esi, eax |
.i2: |
pop eax |
sub [cur_unit_limit], esi |
push eax |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
pop eax |
jnc @f |
.readerr3: |
mov bx, 3 |
jmp .calclen |
@@: |
mov esi, [cur_unit_limit] |
test esi, esi |
jz .loadcontinue |
movzx ecx, byte [di+9] ; add Unit Size |
add cl, byte [di+10] ; add Interleave Gap |
adc ch, 0 |
add eax, ecx |
xor cx, cx |
mov [first_byte], cx |
jmp .interleaved_loop |
cx_to_sectors: |
add cx, 7FFh |
rcr cx, 1 |
shr cx, 10 |
ret |
is_last_component: |
; in: ds:si -> name |
; out: CF set <=> current component is not last (=> folder) |
push si |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
stc |
@@: |
pop si |
ret |
test_filename1: |
; in: ds:si -> filename, es:di -> path table item |
; out: CF set <=> no match |
pusha |
mov cl, [es:di] |
add di, 8 |
jmp test_filename2.start |
test_filename2: |
; in: ds:si -> filename, es:bx -> directory item |
; out: CF set <=> no match |
pusha |
mov cl, [es:bx+32] |
lea di, [bx+33] |
.start: |
mov ch, 0 |
@@: |
lodsb |
test al, al |
jz .test1 |
cmp al, '/' |
jz .test1 |
call toupper |
mov ah, al |
mov al, [es:di] |
call toupper |
inc di |
cmp al, ah |
loopz @b |
jnz .next1 |
; if we have reached this point: current name is done |
lodsb |
test al, al |
jz .ret |
cmp al, '/' |
jz .ret |
; if we have reached this point: current name is done, but input name continues |
; so they do not match |
jmp .next1 |
.test1: |
; if we have reached this point: input name is done, but current name continues |
; "filename.ext;version" in ISO-9660 represents file "filename.ext" |
; "filename." and "filename.;version" are also possible for "filename" |
cmp byte [es:di], '.' |
jnz @f |
inc di |
dec cx |
jz .ret |
@@: |
cmp byte [es:di], ';' |
jnz .next1 |
jmp .ret |
.next1: |
stc |
.ret: |
popa |
ret |
toupper: |
; in: al=symbol |
; out: al=symbol in uppercase |
cmp al, 'a' |
jb .ret |
cmp al, 'z' |
ja .ret |
sub al, 'a'-'A' |
.ret: |
ret |
scan_for_filename_in_sector: |
; in: ds:si->filename, es:bx->folder data, dx=limit |
; out: CF=0 if found |
push bx |
.loope: |
push bx |
.loop: |
cmp bx, dx |
jae .notfound |
cmp byte [es:bx], 0 |
jz .loopd |
test byte [es:bx+25], 4 ; ignore files with Associated bit |
jnz .next |
call test_filename2 |
jc .next |
push ds es di |
push es |
pop ds |
push cs |
pop es |
mov di, [es:cur_desc_end] |
movzx eax, byte [bx+1] |
add eax, [bx+2] |
stosd ; first logical block |
mov eax, [bx+10] |
stosd ; length |
mov al, [bx+25] |
stosb ; flags |
mov ax, [bx+26] |
stosw ; File Unit size, Interleave Gap size |
mov [es:cur_desc_end], di |
cmp di, 3000h |
pop di es ds |
jae .done |
test byte [es:bx+25], 80h |
jz .done |
.next: |
add bl, [es:bx] |
adc bh, 0 |
jmp .loop |
.loopd: |
mov ax, bx |
pop bx |
@@: |
add bx, [cs:lb_size] |
jz .done2 |
cmp bx, ax |
jb @b |
jmp .loope |
.notfound: |
stc |
.done: |
pop bx |
.done2: |
pop bx |
ret |
lb_to_sector: |
xor edx, edx |
div dword [lb_per_sec] |
ret |
load_phys_sector_for_lb_force: |
; in: eax = logical block, ds=0 |
; in: si=0 - accept 0 logical blocks, otherwise force read at least 1 |
; out: 0000:1000 = physical sector data; si -> logical block |
; out: eax = next physical sector |
; out: CF=1 if read error |
; destroys cx |
; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector |
call lb_to_sector |
or si, dx |
jnz @f |
mov si, 1800h |
jmp .done |
@@: |
mov si, 1000h |
imul dx, [lb_size] |
add si, dx |
mov cx, 1 |
push es bx |
push ds |
pop es |
mov bx, 1000h |
call read_sectors |
pop bx es |
inc eax |
.done: |
ret |
normalize: |
; in: es:bx = far pointer |
; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10) |
push ax bx |
mov ax, es |
shr bx, 4 |
add ax, bx |
mov es, ax |
pop bx ax |
and bx, 0x0F |
ret |
read_many_bytes: |
and [first_byte], 0 |
read_many_bytes.with_first: |
; read esi bytes from logical block dx:ax to buffer es:bx |
; out: CF=1 <=> disk error |
push di |
; load first physical sector |
push bx si |
mov si, [first_byte] |
call load_phys_sector_for_lb_force |
jnc @f |
pop si bx |
.ret: |
pop di |
ret |
@@: |
add si, [first_byte] |
mov ecx, 1800h |
sub cx, si |
mov ebx, esi |
pop bx |
sub ebx, ecx |
jnc @f |
add cx, bx |
xor ebx, ebx |
@@: |
pop di |
sub [cur_limit], ecx |
rep movsb |
mov esi, ebx |
mov bx, di |
call normalize |
; load other physical sectors |
; read esi bytes from physical sector eax to buffer es:bx |
test esi, esi |
jz .ret |
push esi |
add esi, 0x7FF |
and si, not 0x7FF |
cmp esi, [cur_limit] |
jbe .okplace |
.noplace: |
sub esi, 800h |
.okplace: |
shr esi, 11 ; si = number of sectors |
mov cx, si |
jz @f |
call read_sectors |
@@: |
pop esi |
jc .ret |
movzx ecx, cx |
add eax, ecx |
shl ecx, 11 |
sub [cur_limit], ecx |
sub esi, ecx |
jc .big |
jz .nopost |
push bx es |
push ds |
pop es |
mov bx, 1000h |
mov cx, 1 |
call read_sectors |
pop es di |
jc .ret2 |
mov cx, si |
mov si, 1000h |
sub word [cur_limit], cx |
sbb word [cur_limit+2], 0 |
rep movsb |
mov bx, di |
call normalize |
.nopost: |
clc |
.ret2: |
pop di |
ret |
.big: |
mov ax, es |
sub ax, 80h |
mov es, ax |
add bx, 800h |
add bx, si |
call normalize |
sub [cur_limit], esi |
jmp .nopost |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only function 1 is defined for now |
dec ax |
jz callback_readfile |
dec ax |
jz callback_continueread |
stc ; unsupported function |
retf |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
clc ; function is supported |
retf |
callback_continueread: |
; function 2: continue to read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; si = limit in 4K blocks |
shl esi, 12 ; bp:si = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, [cur_chunk] |
call loadloop.loadnew |
clc ; function is supported |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kord/loader',0 |
aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 |
align 2 |
cachelist: |
.head dw cachelist |
.tail dw cachelist |
free_cache_item dw 0 |
last_cache_item dw 0x8400 |
use_path_table db 0 |
bootdrive db ? |
align 2 |
lb_size dw ? ; Logical Block size in bytes |
dw 0 ; to allow access dword [lb_size] |
lb_per_sec dw ? ; Logical Blocks per physical sector |
dw 0 ; to allow access dword [lb_per_sec] |
free_ptr dw ? ; first free block in cache (cache block = sector = 0x800 bytes) |
size_rest dw ? ; free space in cache (in blocks) |
cache_size dw ? |
cache_start dw ? |
pathtable_size dw ? |
pathtable_start dw ? |
root_location dd ? |
cur_desc_end dw ? |
cur_nocache_len dd ? |
cur_limit dd ? |
cur_unit_limit dd ? |
overflow dw ? |
cur_chunk dw ? |
first_byte dw ? |
cur_start dd ? |
;times 83FEh-$ db 0 |
db 43h |
; just to make file 2048 bytes long :) |
db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' |
dw 0xAA55 ; this is not required for CD, but to be consistent... |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
jmp far 0:real_start |
; special text |
org $+0x7C00 |
real_start: |
; initialize |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov es, ax |
cld |
sti |
mov [bootdrive], dl |
; check LBA support |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cl, 1 |
jz err_ |
; get file system information |
; scan for Primary Volume Descriptor |
db 66h |
push 10h-1 |
pop eax |
pvd_scan_loop: |
mov cx, 1 |
inc eax |
mov bx, 0x1000 |
call read_sectors |
jnc @f |
fatal_read_err: |
mov si, aReadError |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
@@: |
push ds |
pop es |
cmp word [bx+1], 'CD' |
jnz pvd_scan_loop |
cmp word [bx+3], '00' |
jnz pvd_scan_loop |
cmp byte [bx+5], '1' |
jnz pvd_scan_loop |
; we have found ISO9660 descriptor, look for type |
cmp byte [bx], 1 ; Primary Volume Descriptor? |
jz pvd_found |
cmp byte [bx], 0xFF ; Volume Descriptor Set Terminator? |
jnz pvd_scan_loop |
; Volume Descriptor Set Terminator reached, no PVD found - fatal error |
mov si, no_pvd |
jmp err_ |
pvd_found: |
add bx, 80h |
mov ax, [bx] |
mov [lb_size], ax |
; calculate number of logical blocks in one sector |
mov ax, 800h |
cwd |
div word [bx] |
mov [lb_per_sec], ax |
; get location of root directory |
mov di, root_location |
movzx eax, byte [bx+1Dh] |
add eax, [bx+1Eh] |
stosd |
; get memory size |
int 12h |
mov si, nomem_str |
cmp ax, 71000h / 400h |
jb err_ |
shr ax, 1 |
sub ax, 60000h / 800h |
mov [size_rest], ax |
mov [free_ptr], 60000h / 800h |
; load path table |
; if size > 62K => it's very strange, avoid using it |
; if size > (size of cache)/2 => avoid using it too |
mov ecx, [bx+4] |
cmp ecx, 0x10000 - 0x800 |
ja nopathtable |
shr ax, 1 |
cmp ax, 0x20 |
jae @f |
shl ax, 11 |
cmp cx, ax |
ja nopathtable |
@@: |
; size is ok, try to load it |
mov [pathtable_size], cx |
mov eax, [bx+12] |
xor edx, edx |
div dword [lb_per_sec] |
imul dx, [bx] |
mov [pathtable_start], dx |
add cx, dx |
call cx_to_sectors |
xor bx, bx |
push 6000h |
pop es |
call read_sectors |
jc nopathtable |
; path table has been loaded |
inc [use_path_table] |
sub [size_rest], cx |
add [free_ptr], cx |
nopathtable: |
; init cache |
mov ax, [size_rest] |
mov [cache_size], ax |
mov ax, [free_ptr] |
mov [cache_start], ax |
; load secondary loader |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
jnz noloader |
; set registers for secondary loader |
mov ah, [bootdrive] |
mov al, 'c' |
mov bx, 'is' |
mov si, callback |
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 |
noloader: |
mov si, aKernelNotFound |
jmp err_ |
read_sectors: |
; es:bx = pointer to data |
; eax = first sector |
; cx = number of sectors |
pushad |
push ds |
do_read_sectors: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
db 66h |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [cs:bootdrive] |
mov ah, 42h |
int 13h |
jc diskreaderr |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 7 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz do_read_sectors |
pop ds |
popad |
ret |
diskreaderr: |
add sp, 10h + 2*2 |
pop ds |
popad |
stc |
out_string.ret: |
ret |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz .ret |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aNoLBA db 'The drive does not support LBA!',0 |
aReadError db 'Read error',0 |
no_pvd db 'Primary Volume Descriptor not found!',0 |
nomem_str db 'No memory',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
load_file: |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
; parse path to the file |
lea si, [di+6] |
mov eax, [cs:root_location] |
cmp [cs:use_path_table], 0 |
jz parse_dir |
; scan for path in path table |
push di |
push 6000h |
pop es |
mov di, [cs:pathtable_start] ; es:di = pointer to current entry in path table |
mov dx, 1 ; dx = number of current entry in path table, start from 1 |
mov cx, [cs:pathtable_size] |
pathtable_newparent: |
mov bx, dx ; bx = number of current parent in path table: root = 1 |
scan_path_table_e: |
call is_last_component |
jnc path_table_scanned |
scan_path_table_i: |
cmp word [es:di+6], bx |
jb .next |
ja path_table_notfound |
call test_filename1 |
jc .next |
@@: |
lodsb |
cmp al, '/' |
jnz @b |
jmp pathtable_newparent |
.next: |
; go to next entry |
inc dx |
movzx ax, byte [es:di] |
add ax, 8+1 |
and al, not 1 |
add di, ax |
sub cx, ax |
ja scan_path_table_i |
path_table_notfound: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 2 ; file not found |
ret |
path_table_scanned: |
movzx eax, byte [es:di+1] |
add eax, [es:di+2] |
pop di |
parse_dir: |
; eax = logical block, ds:di -> information structure, ds:si -> file name |
; was the folder already read? |
push di ds |
push cs |
pop ds |
mov [cur_desc_end], 2000h |
mov bx, cachelist |
.scan1: |
mov bx, [bx+2] |
cmp bx, cachelist |
jz .notfound |
cmp [bx+4], eax |
jnz .scan1 |
.found: |
; yes; delete this item from the list (the following code will append this item to the tail) |
mov di, [bx] |
push word [bx+2] |
pop word [di+2] |
mov di, [bx+2] |
push word [bx] |
pop word [di] |
mov di, bx |
jmp .scan |
.notfound: |
; no; load first sector of the folder to get its size |
push eax |
push si |
mov si, 1 |
call load_phys_sector_for_lb_force |
mov bx, si |
pop si |
pop eax |
jnc @f |
; read error - return |
.readerr: |
pop ds |
.readerr2: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 3 |
ret |
@@: |
; first item of the folder describes the folder itself |
; do not cache too big folders: size < 64K and size <= (total cache size)/2 |
cmp word [bx+12], 0 |
jnz .nocache |
mov cx, [cache_size] ; cx = cache size in sectors |
shr cx, 1 ; cx = (cache size)/2 |
cmp cx, 0x20 |
jae @f |
shl cx, 11 |
cmp [bx+10], cx |
ja .nocache |
@@: |
; we want to cache this folder; get space for it |
mov cx, [bx+10] |
call cx_to_sectors |
jnz .yescache |
.nocache: |
push dword [bx+10] |
pop dword [cur_nocache_len] |
call lb_to_sector |
push ds |
pop es |
pop ds |
.nocache_loop: |
push eax |
mov dx, 1800h |
call scan_for_filename_in_sector |
mov cx, dx |
pop eax |
jnc .j_scandone |
sub cx, bx |
sub word [es:cur_nocache_len], cx |
sbb word [es:cur_nocache_len+2], 0 |
jb .j_scandone |
ja @f |
cmp word [es:cur_nocache_len], 0 |
jz .j_scandone |
@@: |
mov cx, 1 |
inc eax |
push es |
mov bx, 1000h |
call read_sectors |
pop es |
jc .readerr2 |
jmp .nocache_loop |
.j_scandone: |
jmp .scandone |
.yescache: |
push bx |
mov bx, [cachelist.head] |
.freeloop: |
cmp cx, [size_rest] |
jbe .sizeok |
@@: |
; if we are here: there is not enough free space, so we must delete old folders' data |
; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2). |
; one loop iteration: delete data of one folder |
pusha |
mov dx, [bx+10] |
mov es, dx ; es = segment of folder data to be deleted |
xor di, di |
mov ax, [bx+8] |
add ax, 0x7FF |
rcr ax, 1 |
shr ax, 10 |
push ax |
shl ax, 11-4 ; get number of paragraphs in folder data to be deleted |
mov cx, [cache_size] |
add cx, [cache_start] |
push ds |
push ax |
add ax, dx |
mov ds, ax |
pop ax |
shl cx, 11-4 |
sub cx, dx ; cx = number of paragraphs to be moved |
push si |
xor si, si |
; move cx paragraphs from ds:si to es:di to get free space in the end of cache |
@@: |
sub cx, 1000h |
jbe @f |
push cx |
mov cx, 8000h |
rep movsw |
mov cx, ds |
add cx, 1000h |
mov ds, cx |
mov cx, es |
add cx, 1000h |
mov es, cx |
pop cx |
jmp @b |
@@: |
add cx, 1000h |
shl cx, 3 |
rep movsw |
pop si |
pop ds |
; correct positions in cache for existing items |
mov cx, 80h |
mov di, 8400h |
.correct: |
cmp [di+10], dx |
jbe @f |
sub [di+10], ax |
@@: |
add di, 12 |
loop .correct |
; some additional space is free now |
pop ax |
add [size_rest], ax |
sub [free_ptr], ax |
; add cache item to the list of free items |
mov dx, [bx] |
mov ax, [free_cache_item] |
mov [bx], ax |
mov [free_cache_item], bx |
mov bx, dx |
; current iteration done |
popa |
jmp .freeloop |
.sizeok: |
mov [cachelist.head], bx |
mov word [bx+2], cachelist |
; allocate new item in cache |
mov di, [free_cache_item] |
test di, di |
jz .nofree |
push word [di] |
pop [free_cache_item] |
jmp @f |
.nofree: |
mov di, [last_cache_item] |
add [last_cache_item], 12 |
@@: |
pop bx |
push si di |
; mov [di+4], eax ; start of folder |
scasd |
stosd |
push ax |
mov ax, [free_ptr] |
shl ax, 11-4 |
mov [di+10-8], ax |
mov es, ax |
pop ax |
add [free_ptr], cx |
sub [size_rest], cx |
; read folder data |
; first sector is already in memory, 0000:bx |
pusha |
mov cx, [bx+10] |
mov [di+8-8], cx ; folder size in bytes |
mov si, bx |
xor di, di |
mov cx, 0x1800 |
sub cx, si |
rep movsb |
pop ax |
push di |
popa |
; read rest of folder |
mov esi, dword [lb_per_sec] |
add eax, esi |
dec si |
not si |
and ax, si |
mov si, word [bx+10] |
mov bx, di |
pop di |
sub si, bx |
jbe @f |
mov [cur_limit], esi |
call read_many_bytes |
pop si |
jnc .scan |
jmp .readerr |
@@: |
pop si |
.scan: |
; now we have required cache item; append it to the end of list |
mov bx, [cachelist.tail] |
mov [cachelist.tail], di |
mov [di+2], bx |
mov word [di], cachelist |
mov [bx], di |
; scan for given filename |
mov es, [di+10] |
mov dx, [di+8] |
pop ds |
xor bx, bx |
call scan_for_filename_in_sector |
.scandone: |
push cs |
pop es |
mov bx, 2000h |
cmp bx, [es:cur_desc_end] |
jnz filefound |
j_notfound: |
jmp path_table_notfound |
filefound: |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
@@: |
mov cl, [es:bx+8] |
test al, al |
jz @f |
; parse next component of file name |
test cl, 2 ; directory? |
jz j_notfound |
mov eax, [es:bx] |
pop di |
jmp parse_dir |
@@: |
test cl, 2 ; directory? |
jnz j_notfound ; do not allow read directories as regular files |
; ok, now load the file |
pop di |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; esi = limit in 4K blocks |
shl esi, 12 ; esi = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, 2000h |
loadloop: |
and [cur_start], 0 |
.loadnew: |
mov esi, [cur_limit] |
mov eax, [cur_start] |
add esi, eax |
mov [overflow], 1 |
sub esi, [di+4] |
jb @f |
xor esi, esi |
dec [overflow] |
@@: |
add esi, [di+4] ; esi = number of bytes to read |
mov [cur_start], esi |
sub esi, eax |
jz .loadcontinue |
xor edx, edx |
div dword [lb_size] ; eax = number of logical blocks to skip, |
mov [first_byte], dx; [first_byte] = number of bytes to skip in 1st block |
cmp byte [di+10], 0 |
jnz .interleaved |
add eax, [di] |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
jc .readerr3 |
.loadcontinue: |
mov [cur_chunk], di |
add di, 11 |
cmp di, [cur_desc_end] |
jae @f |
cmp [cur_limit], 0 |
jnz loadloop |
@@: |
mov bx, [overflow] |
.calclen: |
; calculate length of file |
xor ax, ax |
xor dx, dx |
mov di, 2000h |
@@: |
add ax, [di+4] |
adc dx, [di+6] |
add di, 11 |
cmp di, [cur_desc_end] |
jb @b |
ret |
.interleaved: |
mov [cur_unit_limit], esi |
push esi |
; skip first blocks |
movzx ecx, byte [di+9] ; Unit Size |
movzx esi, byte [di+10] ; Interleave Gap |
add si, cx |
mov edx, [di] |
@@: |
sub eax, ecx |
jb @f |
add edx, esi |
jmp @b |
@@: |
add ecx, eax ; ecx = number of logical blocks to skip |
lea eax, [ecx+edx] ; eax = first logical block |
pop esi |
.interleaved_loop: |
; get number of bytes in current file unit |
push eax |
movzx eax, byte [di+9] |
sub ax, cx |
imul eax, dword [lb_size] |
cmp eax, esi |
ja .i2 |
.i1: |
xchg esi, eax |
.i2: |
pop eax |
sub [cur_unit_limit], esi |
push eax |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
pop eax |
jnc @f |
.readerr3: |
mov bx, 3 |
jmp .calclen |
@@: |
mov esi, [cur_unit_limit] |
test esi, esi |
jz .loadcontinue |
movzx ecx, byte [di+9] ; add Unit Size |
add cl, byte [di+10] ; add Interleave Gap |
adc ch, 0 |
add eax, ecx |
xor cx, cx |
mov [first_byte], cx |
jmp .interleaved_loop |
cx_to_sectors: |
add cx, 7FFh |
rcr cx, 1 |
shr cx, 10 |
ret |
is_last_component: |
; in: ds:si -> name |
; out: CF set <=> current component is not last (=> folder) |
push si |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
stc |
@@: |
pop si |
ret |
test_filename1: |
; in: ds:si -> filename, es:di -> path table item |
; out: CF set <=> no match |
pusha |
mov cl, [es:di] |
add di, 8 |
jmp test_filename2.start |
test_filename2: |
; in: ds:si -> filename, es:bx -> directory item |
; out: CF set <=> no match |
pusha |
mov cl, [es:bx+32] |
lea di, [bx+33] |
.start: |
mov ch, 0 |
@@: |
lodsb |
test al, al |
jz .test1 |
cmp al, '/' |
jz .test1 |
call toupper |
mov ah, al |
mov al, [es:di] |
call toupper |
inc di |
cmp al, ah |
loopz @b |
jnz .next1 |
; if we have reached this point: current name is done |
lodsb |
test al, al |
jz .ret |
cmp al, '/' |
jz .ret |
; if we have reached this point: current name is done, but input name continues |
; so they do not match |
jmp .next1 |
.test1: |
; if we have reached this point: input name is done, but current name continues |
; "filename.ext;version" in ISO-9660 represents file "filename.ext" |
; "filename." and "filename.;version" are also possible for "filename" |
cmp byte [es:di], '.' |
jnz @f |
inc di |
dec cx |
jz .ret |
@@: |
cmp byte [es:di], ';' |
jnz .next1 |
jmp .ret |
.next1: |
stc |
.ret: |
popa |
ret |
toupper: |
; in: al=symbol |
; out: al=symbol in uppercase |
cmp al, 'a' |
jb .ret |
cmp al, 'z' |
ja .ret |
sub al, 'a'-'A' |
.ret: |
ret |
scan_for_filename_in_sector: |
; in: ds:si->filename, es:bx->folder data, dx=limit |
; out: CF=0 if found |
push bx |
.loope: |
push bx |
.loop: |
cmp bx, dx |
jae .notfound |
cmp byte [es:bx], 0 |
jz .loopd |
test byte [es:bx+25], 4 ; ignore files with Associated bit |
jnz .next |
call test_filename2 |
jc .next |
push ds es di |
push es |
pop ds |
push cs |
pop es |
mov di, [es:cur_desc_end] |
movzx eax, byte [bx+1] |
add eax, [bx+2] |
stosd ; first logical block |
mov eax, [bx+10] |
stosd ; length |
mov al, [bx+25] |
stosb ; flags |
mov ax, [bx+26] |
stosw ; File Unit size, Interleave Gap size |
mov [es:cur_desc_end], di |
cmp di, 3000h |
pop di es ds |
jae .done |
test byte [es:bx+25], 80h |
jz .done |
.next: |
add bl, [es:bx] |
adc bh, 0 |
jmp .loop |
.loopd: |
mov ax, bx |
pop bx |
@@: |
add bx, [cs:lb_size] |
jz .done2 |
cmp bx, ax |
jb @b |
jmp .loope |
.notfound: |
stc |
.done: |
pop bx |
.done2: |
pop bx |
ret |
lb_to_sector: |
xor edx, edx |
div dword [lb_per_sec] |
ret |
load_phys_sector_for_lb_force: |
; in: eax = logical block, ds=0 |
; in: si=0 - accept 0 logical blocks, otherwise force read at least 1 |
; out: 0000:1000 = physical sector data; si -> logical block |
; out: eax = next physical sector |
; out: CF=1 if read error |
; destroys cx |
; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector |
call lb_to_sector |
or si, dx |
jnz @f |
mov si, 1800h |
jmp .done |
@@: |
mov si, 1000h |
imul dx, [lb_size] |
add si, dx |
mov cx, 1 |
push es bx |
push ds |
pop es |
mov bx, 1000h |
call read_sectors |
pop bx es |
inc eax |
.done: |
ret |
normalize: |
; in: es:bx = far pointer |
; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10) |
push ax bx |
mov ax, es |
shr bx, 4 |
add ax, bx |
mov es, ax |
pop bx ax |
and bx, 0x0F |
ret |
read_many_bytes: |
and [first_byte], 0 |
read_many_bytes.with_first: |
; read esi bytes from logical block dx:ax to buffer es:bx |
; out: CF=1 <=> disk error |
push di |
; load first physical sector |
push bx si |
mov si, [first_byte] |
call load_phys_sector_for_lb_force |
jnc @f |
pop si bx |
.ret: |
pop di |
ret |
@@: |
add si, [first_byte] |
mov ecx, 1800h |
sub cx, si |
mov ebx, esi |
pop bx |
sub ebx, ecx |
jnc @f |
add cx, bx |
xor ebx, ebx |
@@: |
pop di |
sub [cur_limit], ecx |
rep movsb |
mov esi, ebx |
mov bx, di |
call normalize |
; load other physical sectors |
; read esi bytes from physical sector eax to buffer es:bx |
test esi, esi |
jz .ret |
push esi |
add esi, 0x7FF |
and si, not 0x7FF |
cmp esi, [cur_limit] |
jbe .okplace |
.noplace: |
sub esi, 800h |
.okplace: |
shr esi, 11 ; si = number of sectors |
mov cx, si |
jz @f |
call read_sectors |
@@: |
pop esi |
jc .ret |
movzx ecx, cx |
add eax, ecx |
shl ecx, 11 |
sub [cur_limit], ecx |
sub esi, ecx |
jc .big |
jz .nopost |
push bx es |
push ds |
pop es |
mov bx, 1000h |
mov cx, 1 |
call read_sectors |
pop es di |
jc .ret2 |
mov cx, si |
mov si, 1000h |
sub word [cur_limit], cx |
sbb word [cur_limit+2], 0 |
rep movsb |
mov bx, di |
call normalize |
.nopost: |
clc |
.ret2: |
pop di |
ret |
.big: |
mov ax, es |
sub ax, 80h |
mov es, ax |
add bx, 800h |
add bx, si |
call normalize |
sub [cur_limit], esi |
jmp .nopost |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only function 1 is defined for now |
dec ax |
jz callback_readfile |
dec ax |
jz callback_continueread |
stc ; unsupported function |
retf |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
clc ; function is supported |
retf |
callback_continueread: |
; function 2: continue to read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; si = limit in 4K blocks |
shl esi, 12 ; bp:si = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, [cur_chunk] |
call loadloop.loadnew |
clc ; function is supported |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kord/loader',0 |
aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 |
align 2 |
cachelist: |
.head dw cachelist |
.tail dw cachelist |
free_cache_item dw 0 |
last_cache_item dw 0x8400 |
use_path_table db 0 |
bootdrive db ? |
align 2 |
lb_size dw ? ; Logical Block size in bytes |
dw 0 ; to allow access dword [lb_size] |
lb_per_sec dw ? ; Logical Blocks per physical sector |
dw 0 ; to allow access dword [lb_per_sec] |
free_ptr dw ? ; first free block in cache (cache block = sector = 0x800 bytes) |
size_rest dw ? ; free space in cache (in blocks) |
cache_size dw ? |
cache_start dw ? |
pathtable_size dw ? |
pathtable_start dw ? |
root_location dd ? |
cur_desc_end dw ? |
cur_nocache_len dd ? |
cur_limit dd ? |
cur_unit_limit dd ? |
overflow dw ? |
cur_chunk dw ? |
first_byte dw ? |
cur_start dd ? |
;times 83FEh-$ db 0 |
db 43h |
; just to make file 2048 bytes long :) |
db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' |
dw 0xAA55 ; this is not required for CD, but to be consistent... |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot/fat1x/bootsect.asm |
---|
1,392 → 1,392 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
use_lba = 0 |
org 0x7C00 |
jmp start |
nop |
; FAT parameters, BPB |
; note: they can be changed at install, replaced with real values |
; these settings are for most typical 1.44M floppies |
db 'KOLIBRI ' ; BS_OEMName, ignored |
dw 200h ; BPB_BytsPerSec |
BPB_SecsPerClus db 1 |
BPB_RsvdSecCnt dw 1 |
BPB_NumFATs db 2 |
BPB_RootEntCnt dw 0xE0 |
dw 2880 ; BPB_TotSec16 |
db 0xF0 ; BPB_Media |
BPB_FATSz16 dw 9 |
BPB_SecPerTrk dw 18 |
BPB_NumHeads dw 2 |
BPB_HiddSec dd 0 |
dd 0 ; BPB_TotSec32 |
BS_DrvNum db 0 |
db 0 ; BS_Reserved1 |
db ')' ; BS_BootSig |
dd 12344321h ; BS_VolID |
filename: |
db 'KORD.OS ' ; BS_VolLab |
db 'FAT12 ' ; BS_FilSysType |
; Used memory map: |
; 8000:0000 - current directory |
; 9000:0000 - root directory data [cached] |
start: |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov bp, sp |
cld |
sti |
mov [bp+BS_DrvNum-0x7C00], dl |
if use_lba |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cx, 1 |
jz err_ |
else |
mov ah, 8 |
int 13h |
jc @f ; on error, assume that BPB geometry is valid |
mov al, dh |
mov ah, 0 |
inc ax |
mov [bp+BPB_NumHeads-0x7C00], ax |
and cx, 3Fh |
mov [bp+BPB_SecPerTrk-0x7C00], cx |
@@: |
end if |
; get FAT parameters |
xor bx, bx |
mov al, [bp+BPB_NumFATs-0x7C00] |
mov ah, 0 |
mul [bp+BPB_FATSz16-0x7C00] |
add ax, [bp+BPB_RsvdSecCnt-0x7C00] |
adc dx, bx |
push dx |
push ax ; root directory start = dword [bp-4] |
mov cx, [bp+BPB_RootEntCnt-0x7C00] |
add cx, 0xF |
rcr cx, 1 |
shr cx, 3 ; cx = size of root directory in sectors |
add ax, cx |
adc dx, bx |
push dx |
push ax ; data start = dword [bp-8] |
; load start of root directory (no more than 0x2000 bytes = 0x10 sectors) |
cmp cx, 0x10 |
jb @f |
mov cx, 0x10 |
@@: |
mov ax, [bp-4] |
mov dx, [bp-2] |
push 0x9000 |
pop es |
call read_sectors |
add word [bp-4], cx ; dword [bp-4] = start of non-cached root data |
adc word [bp-2], bx |
; load kordldr.f12 |
mov si, main_loader |
call lookup_in_root_dir |
jc noloader |
test byte [es:di+11], 10h ; directory? |
jz kordldr_ok |
noloader: |
mov si, aLoaderNotFound |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
kordldr_ok: |
mov ax, [es:di+26] ; get file cluster |
mov bx, 0x7E00 |
xor cx, cx |
mov es, cx |
sub ax, 2 |
jc noloader |
push bx ; save return address: bx = 7E00 |
mov cl, [bp+BPB_SecsPerClus-0x7C00] |
mul cx |
; fall through - 'ret' in read_sectors will return to 7E00 |
read_sectors2: |
; same as read_sectors, but dx:ax is relative to start of data |
add ax, [bp-8] |
adc dx, [bp-6] |
read_sectors: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; dx:ax = first sector |
; cx = number of sectors |
pusha |
add ax, word [bp+BPB_HiddSec-0x7C00] |
adc dx, word [bp+BPB_HiddSec+2-0x7C00] |
if use_lba |
push ds |
do_read_sectors: |
push ax |
push cx |
push dx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push dx |
push ax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp+BS_DrvNum-0x7C00] |
mov ah, 42h |
int 13h |
mov si, aReadError |
jc err_ |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
mov si, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop dx |
pop cx |
pop ax |
add ax, si |
adc dx, 0 |
sub cx, si |
jnz do_read_sectors |
pop ds |
popa |
ret |
else |
do_read_sectors: |
pusha |
pop di |
push bx |
; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx |
mov si, ax |
xchg ax, dx |
xor dx, dx |
div [bp+BPB_SecPerTrk-0x7C00] |
push ax |
mov ax, si |
div [bp+BPB_SecPerTrk-0x7C00] |
mov bx, dx ; bx=sector-1 |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp+BPB_NumHeads-0x7C00] |
; number of sectors: read no more than to end of track |
push bx |
sub bx, [bp+BPB_SecPerTrk-0x7C00] |
neg bx |
cmp cx, bx |
jbe @f |
mov cx, bx |
@@: |
pop bx |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format |
mov di, cx |
mov dh, dl |
mov dl, [bp+BS_DrvNum-0x7C00] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
mov si, aReadError |
jmp err_ |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push di |
popa |
add ax, di |
adc dx, 0 |
sub cx, di |
jnz do_read_sectors |
popa |
ret |
end if |
scan_for_filename: |
; in: ds:si -> 11-bytes FAT name |
; in: es:0 -> part of directory data |
; in: cx = number of entries |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
xor di, di |
push cx |
sloop: |
cmp byte [es:di], 0 |
jz snotfound |
test byte [es:di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmpsb |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
inc cx ; clear ZF flag |
snotfound: |
stc |
sdone: |
pop cx |
lrdret: |
ret |
lookup_in_root_dir: |
; ss:bp = 0:7C00 |
; in: ds:si -> 11-bytes FAT name |
; out: if found: CF=0, es:di -> directory entry |
; out: if not found: CF=1 |
mov cx, [bp+BPB_RootEntCnt-0x7C00] |
push cx |
; first, look in root directory cache |
push 0x9000 |
pop es |
test ch, ch |
jz @f |
mov cx, 0x100 |
@@: |
mov ax, [bp-4] |
mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory |
lrdloop: |
call scan_for_filename |
pop bx |
jz lrdret |
sub bx, cx |
mov cx, bx |
stc |
jz lrdret |
; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries |
push cx |
cmp ch, 0x8 |
jb @f |
mov cx, 0x800 |
@@: |
push 0x8000 |
pop es |
push cx |
push es |
xor bx, bx |
add cx, 0xF |
shr cx, 4 |
call read_sectors |
pop es |
add ax, cx |
adc dx, bx |
pop cx |
jmp lrdloop |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz lrdret |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aReadError db 'Read error',0 |
if use_lba |
aNoLBA db 'The drive does not support LBA!',0 |
end if |
aLoaderNotFound db 'Loader not found',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
main_loader db 'KORDLDR F1X' |
if use_lba |
db 0 ; make bootsector 512 bytes in length |
end if |
; bootsector signature |
dw 0xAA55 |
; display offsets of all procedures used by kordldr.f12.asm |
macro show [procedure] |
{ |
bits = 16 |
display `procedure,' = ' |
repeat bits/4 |
d = '0' + procedure shr (bits - %*4) and 0Fh |
if d > '9' |
d = d + 'A'-'9'-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
use_lba = 0 |
org 0x7C00 |
jmp start |
nop |
; FAT parameters, BPB |
; note: they can be changed at install, replaced with real values |
; these settings are for most typical 1.44M floppies |
db 'KOLIBRI ' ; BS_OEMName, ignored |
dw 200h ; BPB_BytsPerSec |
BPB_SecsPerClus db 1 |
BPB_RsvdSecCnt dw 1 |
BPB_NumFATs db 2 |
BPB_RootEntCnt dw 0xE0 |
dw 2880 ; BPB_TotSec16 |
db 0xF0 ; BPB_Media |
BPB_FATSz16 dw 9 |
BPB_SecPerTrk dw 18 |
BPB_NumHeads dw 2 |
BPB_HiddSec dd 0 |
dd 0 ; BPB_TotSec32 |
BS_DrvNum db 0 |
db 0 ; BS_Reserved1 |
db ')' ; BS_BootSig |
dd 12344321h ; BS_VolID |
filename: |
db 'KORD.OS ' ; BS_VolLab |
db 'FAT12 ' ; BS_FilSysType |
; Used memory map: |
; 8000:0000 - current directory |
; 9000:0000 - root directory data [cached] |
start: |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov bp, sp |
cld |
sti |
mov [bp+BS_DrvNum-0x7C00], dl |
if use_lba |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cx, 1 |
jz err_ |
else |
mov ah, 8 |
int 13h |
jc @f ; on error, assume that BPB geometry is valid |
mov al, dh |
mov ah, 0 |
inc ax |
mov [bp+BPB_NumHeads-0x7C00], ax |
and cx, 3Fh |
mov [bp+BPB_SecPerTrk-0x7C00], cx |
@@: |
end if |
; get FAT parameters |
xor bx, bx |
mov al, [bp+BPB_NumFATs-0x7C00] |
mov ah, 0 |
mul [bp+BPB_FATSz16-0x7C00] |
add ax, [bp+BPB_RsvdSecCnt-0x7C00] |
adc dx, bx |
push dx |
push ax ; root directory start = dword [bp-4] |
mov cx, [bp+BPB_RootEntCnt-0x7C00] |
add cx, 0xF |
rcr cx, 1 |
shr cx, 3 ; cx = size of root directory in sectors |
add ax, cx |
adc dx, bx |
push dx |
push ax ; data start = dword [bp-8] |
; load start of root directory (no more than 0x2000 bytes = 0x10 sectors) |
cmp cx, 0x10 |
jb @f |
mov cx, 0x10 |
@@: |
mov ax, [bp-4] |
mov dx, [bp-2] |
push 0x9000 |
pop es |
call read_sectors |
add word [bp-4], cx ; dword [bp-4] = start of non-cached root data |
adc word [bp-2], bx |
; load kordldr.f12 |
mov si, main_loader |
call lookup_in_root_dir |
jc noloader |
test byte [es:di+11], 10h ; directory? |
jz kordldr_ok |
noloader: |
mov si, aLoaderNotFound |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
kordldr_ok: |
mov ax, [es:di+26] ; get file cluster |
mov bx, 0x7E00 |
xor cx, cx |
mov es, cx |
sub ax, 2 |
jc noloader |
push bx ; save return address: bx = 7E00 |
mov cl, [bp+BPB_SecsPerClus-0x7C00] |
mul cx |
; fall through - 'ret' in read_sectors will return to 7E00 |
read_sectors2: |
; same as read_sectors, but dx:ax is relative to start of data |
add ax, [bp-8] |
adc dx, [bp-6] |
read_sectors: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; dx:ax = first sector |
; cx = number of sectors |
pusha |
add ax, word [bp+BPB_HiddSec-0x7C00] |
adc dx, word [bp+BPB_HiddSec+2-0x7C00] |
if use_lba |
push ds |
do_read_sectors: |
push ax |
push cx |
push dx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push dx |
push ax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp+BS_DrvNum-0x7C00] |
mov ah, 42h |
int 13h |
mov si, aReadError |
jc err_ |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
mov si, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop dx |
pop cx |
pop ax |
add ax, si |
adc dx, 0 |
sub cx, si |
jnz do_read_sectors |
pop ds |
popa |
ret |
else |
do_read_sectors: |
pusha |
pop di |
push bx |
; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx |
mov si, ax |
xchg ax, dx |
xor dx, dx |
div [bp+BPB_SecPerTrk-0x7C00] |
push ax |
mov ax, si |
div [bp+BPB_SecPerTrk-0x7C00] |
mov bx, dx ; bx=sector-1 |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp+BPB_NumHeads-0x7C00] |
; number of sectors: read no more than to end of track |
push bx |
sub bx, [bp+BPB_SecPerTrk-0x7C00] |
neg bx |
cmp cx, bx |
jbe @f |
mov cx, bx |
@@: |
pop bx |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format |
mov di, cx |
mov dh, dl |
mov dl, [bp+BS_DrvNum-0x7C00] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
mov si, aReadError |
jmp err_ |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push di |
popa |
add ax, di |
adc dx, 0 |
sub cx, di |
jnz do_read_sectors |
popa |
ret |
end if |
scan_for_filename: |
; in: ds:si -> 11-bytes FAT name |
; in: es:0 -> part of directory data |
; in: cx = number of entries |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
xor di, di |
push cx |
sloop: |
cmp byte [es:di], 0 |
jz snotfound |
test byte [es:di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmpsb |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
inc cx ; clear ZF flag |
snotfound: |
stc |
sdone: |
pop cx |
lrdret: |
ret |
lookup_in_root_dir: |
; ss:bp = 0:7C00 |
; in: ds:si -> 11-bytes FAT name |
; out: if found: CF=0, es:di -> directory entry |
; out: if not found: CF=1 |
mov cx, [bp+BPB_RootEntCnt-0x7C00] |
push cx |
; first, look in root directory cache |
push 0x9000 |
pop es |
test ch, ch |
jz @f |
mov cx, 0x100 |
@@: |
mov ax, [bp-4] |
mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory |
lrdloop: |
call scan_for_filename |
pop bx |
jz lrdret |
sub bx, cx |
mov cx, bx |
stc |
jz lrdret |
; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries |
push cx |
cmp ch, 0x8 |
jb @f |
mov cx, 0x800 |
@@: |
push 0x8000 |
pop es |
push cx |
push es |
xor bx, bx |
add cx, 0xF |
shr cx, 4 |
call read_sectors |
pop es |
add ax, cx |
adc dx, bx |
pop cx |
jmp lrdloop |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz lrdret |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aReadError db 'Read error',0 |
if use_lba |
aNoLBA db 'The drive does not support LBA!',0 |
end if |
aLoaderNotFound db 'Loader not found',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
main_loader db 'KORDLDR F1X' |
if use_lba |
db 0 ; make bootsector 512 bytes in length |
end if |
; bootsector signature |
dw 0xAA55 |
; display offsets of all procedures used by kordldr.f12.asm |
macro show [procedure] |
{ |
bits = 16 |
display `procedure,' = ' |
repeat bits/4 |
d = '0' + procedure shr (bits - %*4) and 0Fh |
if d > '9' |
d = d + 'A'-'9'-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot/fat1x/kordldr.f1x.asm |
---|
1,667 → 1,668 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
org 0x7E00 |
; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here |
; ss:bp = 0:7C00 |
virtual at bp |
rb 3 ; BS_jmpBoot |
rb 8 ; BS_OEMName, ignored |
dw ? ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
BPB_TotSec16 dw ? |
db ? ; BPB_Media |
BPB_FATSz16 dw ? |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
BPB_TotSec32 dd ? |
BS_DrvNum db ? |
fat_type db ? ; this is BS_Reserved1, |
; we use it to save FS type: 0=FAT12, 1=FAT16 |
db ? ; BS_BootSig |
num_sectors dd ? ; BS_VolID |
; rb 11 ; BS_VolLab |
; rb 3 ; BS_FilSysType, first 3 bytes |
read_sectors dw ? |
read_sectors2 dw ? |
lookup_in_root_dir dw ? |
scan_for_filename dw ? |
err_ dw ? |
noloader dw ? |
cachelimit dw ? |
filesize: ; will be used to save file size |
rb 5 ; BS_FilSysType, last 5 bytes |
; following variables are located in the place of starting code; |
; starting code is no more used at this point |
sect_per_clus dw ? |
cur_cluster dw ? |
next_cluster dw ? |
flags dw ? |
cur_delta dd ? |
end virtual |
; procedures from boot sector |
; LBA version |
lba_read_sectors = 7CE2h |
lba_read_sectors2 = 7CDCh |
lba_lookup_in_root_dir = 7D4Fh |
lba_scan_for_filename = 7D2Dh |
lba_err = 7CB5h |
lba_noloader = 7CB2h |
; CHS version |
chs_read_sectors = 7CDEh |
chs_read_sectors2 = 7CD8h |
chs_lookup_in_root_dir = 7D70h |
chs_scan_for_filename = 7D4Eh |
chs_err = 7CB1h |
chs_noloader = 7CAEh |
push ax cx ; save our position on disk |
push ss |
pop es |
; determine version of bootsector (LBA vs CHS) |
; mov [read_sectors], chs_read_sectors |
; mov [read_sectors2], chs_read_sectors2 |
; mov [lookup_in_root_dir], chs_lookup_in_root_dir |
; mov [scan_for_filename], chs_scan_for_filename |
; mov [err], chs_err |
; mov [noloader], chs_noloader |
lea di, [read_sectors] |
mov si, chs_proc_addresses |
mov cx, 6*2 |
cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di' |
jz @f |
add si, cx |
; mov [read_sectors], lba_read_sectors |
; mov [read_sectors2], lba_read_sectors2 |
; mov [lookup_in_root_dir], lba_lookup_in_root_dir |
; mov [scan_for_filename], lba_scan_for_filename |
; mov [err], lba_err |
; mov [noloader], lba_noloader |
@@: |
rep movsb |
mov cl, [BPB_SecsPerClus] |
mov [sect_per_clus], cx |
xor bx, bx |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 94000h / 1024 |
jae @f |
nomem: |
mov si, nomem_str |
jmp [err_] |
@@: |
shr ax, 3 |
mov [cachelimit], ax ; size of cache - 1 |
; get type of file system - FAT12 or FAT16? |
; calculate number of clusters |
mov ax, [BPB_TotSec16] |
xor dx, dx |
test ax, ax |
jnz @f |
mov ax, word [BPB_TotSec32] |
mov dx, word [BPB_TotSec32+2] |
@@: |
sub ax, [bp-8] ; dword [bp-8] = first data sector |
sbb dx, [bp-6] |
jb j_noloader |
div [sect_per_clus] |
; ax = number of clusters |
; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes |
mov [fat_type], ch |
cmp ax, 0xFF5 |
jb init_fat12 |
inc [fat_type] |
init_fat16: |
; no sectors loaded |
mov di, 0x8200 |
xor ax, ax |
mov cx, 0x100/2 |
rep stosw |
jmp init_fat_done |
init_fat12: |
; read FAT |
push 0x6000 |
pop es |
mov ax, [BPB_RsvdSecCnt] |
mov cx, [BPB_FATSz16] |
cmp cx, 12 |
jb @f |
mov cx, 12 |
@@: |
xor dx, dx |
call [read_sectors] |
init_fat_done: |
; if cluster = sector, we need to read second part of our file |
; (bootsector loads only first cluster of kordldr.f1x) |
pop cx ax ; restore our position on disk |
cmp cx, 1 |
ja kordldr_full |
sub ax, [bp-8] |
inc ax |
inc ax ; ax = first cluster of kordldr.f12 |
call get_next_cluster |
jc @f |
j_noloader: |
jmp [noloader] |
@@: |
dec ax |
dec ax |
push 0x800 |
pop es |
call [read_sectors2] |
kordldr_full: |
; ...continue loading... |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
mov bx, [err_] |
jz @f |
mov si, aKernelNotFound |
jmp bx |
@@: |
; for subsequent calls to callback function, hook error handler |
; mov byte [bx], 0xE9 ; 'jmp' opcode |
; mov ax, hooked_err - 3 |
; sub ax, bx |
; mov word [bx+1], ax |
; push hooked_err / ret |
mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8) |
mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8) |
; set registers for secondary loader |
mov ah, [BS_DrvNum] |
mov al, 'f' |
test ah, ah |
jns @f |
sub ah, 80h |
mov al, 'h' |
@@: |
mov bx, '12' |
cmp [fat_type], 0 |
jz @f |
mov bh, '6' |
@@: |
mov si, callback ; ds:si = far pointer to callback procedure |
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 |
nomem_str db 'No memory',0 |
chs_proc_addresses: |
dw chs_read_sectors |
dw chs_read_sectors2 |
dw chs_lookup_in_root_dir |
dw chs_scan_for_filename |
dw chs_err |
dw chs_noloader |
lba_proc_addresses: |
dw lba_read_sectors |
dw lba_read_sectors2 |
dw lba_lookup_in_root_dir |
dw lba_scan_for_filename |
dw lba_err |
dw lba_noloader |
get_next_cluster: |
; in: ax = cluster |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
push si |
cmp [fat_type], 0 |
jnz gnc16 |
; for FAT12 |
push ds |
push 0x6000 |
pop ds |
mov si, ax |
shr si, 1 |
add si, ax |
test al, 1 |
lodsw |
jz @f |
shr ax, 4 |
@@: |
and ax, 0xFFF |
cmp ax, 0xFF7 |
pop ds si |
ret |
; for FAT16 |
gnc16: |
; each sector contains 200h bytes = 100h FAT entries |
; so ah = # of sector, al = offset in sector |
mov si, ax |
mov ah, 0 |
shr si, 8 |
; calculate segment for this sector of FAT table |
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) |
; segment = 6000 + 20*si, offset = 0 |
push es |
push si |
shl si, 5 |
add si, 0x6000 |
mov es, si |
pop si |
cmp byte [ss:0x8200+si], ah ; sector already loaded? |
jnz @f |
; load corresponding sector |
pusha |
push es |
xor bx, bx |
mov ax, [BPB_RsvdSecCnt] |
xor dx, dx |
add ax, si |
adc dx, bx |
mov cx, 1 ; read 1 sector |
call [read_sectors] |
pop es |
popa |
@@: |
mov si, ax |
add si, si |
; mov ax, [es:si] |
lods word [es:si] |
pop es |
cmp ax, 0xFFF7 |
pop si |
ret |
if $ > 0x8000 |
error 'get_next_cluster must fit in first sector of kordldr.f1x!' |
end if |
load_file: |
; in: ss:bp = 0:7C00 |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
xor ax, ax ; start from root directory |
mov dx, -1 |
mov word [filesize], dx |
mov word [filesize+2], dx ; initialize file size with invalid value |
lea si, [di+6] |
parse_dir_loop: |
; convert name to FAT name |
push di |
push ax |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
mov di, filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
nameloop: |
lodsb |
test al, al |
jz namedone |
cmp al, '/' |
jz namedone |
cmp al, '.' |
jz namedot |
dec cx |
js badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp nameloop |
namedot: |
inc bx |
jp badname |
add di, cx |
mov cl, 3 |
jmp nameloop |
badname: ; do not make direct js/jp to notfound_pop: |
; this generates long forms of conditional jumps and results in longer code |
jmp notfound_pop |
namedone: |
; scan directory |
pop ax ; ax = cluster of directory or 0 for root |
push ds |
push si |
push es |
pop ds |
mov si, filename ; ds:si -> filename in FAT style |
test ax, ax |
jnz lookup_in_notroot_dir |
; for root directory, use the subroutine from bootsector |
call [lookup_in_root_dir] |
jmp lookup_done |
lookup_in_notroot_dir: |
; for other directories, read a folder sector-by-sector and scan |
; first, try to use the cache |
push ds |
push cs |
pop ds |
mov bx, [cachelimit] |
add bx, bx |
mov di, foldcache_mark |
@@: |
mov dx, [foldcache_clus+di-foldcache_mark+bx] |
cmp dx, ax |
jz cacheok |
test dx, dx |
jz cacheadd ; the cache has place for new entry |
dec bx |
dec bx |
jns @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov dx, [cachelimit] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
mov [foldcache_clus+di-foldcache_mark+bx], ax |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [cachelimit] |
add di, di |
cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
pop ds |
; mov dx, bx |
; shl dx, 8 ; dx = (position in cache)*0x2000/0x10 |
; add dx, 0x9200 |
lea dx, [bx+0x92] |
xchg dl, dh |
mov es, dx |
jcxz not_in_cache |
call [scan_for_filename] |
jz lookup_done |
not_in_cache: |
; cache miss, read folder data from disk |
mov bx, cx |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
folder_next_cluster: |
; internal loop: scan sectors in cluster |
mov cx, [sect_per_clus] |
push ax |
dec ax |
dec ax |
mul cx |
add ax, [bp-8] |
adc dx, [bp-6] ; dx:ax = absolute sector |
folder_next_sector: |
; skip first bx sectors |
dec bx |
jns folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
call [read_sectors] |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
push si di |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache |
pop di si |
@@: |
push es |
push 0x8000 |
pop es |
push cs |
pop ds |
mov cx, 0x10 |
call [scan_for_filename] |
pop es |
pop cx |
jz lookup_done_pop |
folder_skip_sector: |
inc ax |
jnz @f |
inc dx |
@@: |
loop folder_next_sector |
pop ax ; ax = current cluster |
call get_next_cluster |
jc folder_next_cluster |
stc |
push ax |
lookup_done_pop: |
pop ax |
lookup_done: |
pop si |
pop ds |
; CF=1 <=> failed |
jnc found |
notfound: |
pop di |
mov bx, 2 ; file not found |
mov ax, 0xFFFF |
mov dx, ax ; invalid file size |
ret |
notfound_pop: |
pop ax |
jmp notfound |
found: |
mov ax, [es:di+26] ; get cluster |
test byte [es:di+11], 10h ; directory? |
jz regular_file |
cmp byte [si-1], 0 |
jz notfound ; don't read directories as a regular files |
; ok, we have found a directory and the caller requested a file into it |
pop di |
jmp parse_dir_loop ; restart with new cluster in ax |
regular_file: |
cmp byte [si-1], 0 |
jnz notfound ; file does not contain another files |
; ok, we have found a regular file and the caller requested it |
; save file size |
mov dx, [es:di+28] |
mov [filesize], dx |
mov dx, [es:di+30] |
mov [filesize+2], dx |
pop di |
mov si, [di+4] |
shl si, 3 |
push si ; [ds:di+4] = limit in 4K blocks |
les bx, [di] ; es:bx -> buffer |
clusloop: |
; ax = first cluster, top of stack contains limit in sectors |
mov si, ax ; remember current cluster |
xor cx, cx ; cx will contain number of consecutive clusters |
mov word [cur_delta], cx |
mov word [cur_delta+2], cx |
mov di, ax |
clusfind: |
inc di |
inc cx |
call get_next_cluster |
jnc clusread |
cmp ax, di |
jz clusfind |
stc |
clusread: |
pop di ; limit in sectors |
push ax ; save next cluster |
pushf ; save flags |
; read cx clusters, starting from si |
; calculate number of sectors |
xchg ax, cx |
mul [sect_per_clus] |
; dx:ax = number of sectors; compare with limit |
mov word [num_sectors], ax |
mov word [num_sectors+2], dx |
jmp @f |
continue_load_file: |
les bx, [di] ; es:bx -> buffer |
mov di, [di+4] ; ds:di = limit in 4K blocks |
shl di, 3 ; now di = limit in sectors |
mov ax, word [num_sectors] |
mov dx, word [num_sectors+2] |
mov si, [cur_cluster] |
push [next_cluster] |
push [flags] |
or ax, dx |
jz nextclus |
@@: |
test dx, dx |
jnz clusdecrease |
push dx ; limit was not exceeded |
cmp ax, di |
jbe @f |
pop ax |
clusdecrease: |
push 1 ; limit was exceeded |
mov ax, di |
@@: |
sub di, ax ; calculate new limit |
sub word [num_sectors], ax |
sbb word [num_sectors+2], 0 |
; calculate starting sector |
xchg ax, cx |
lea ax, [si-2] |
mul [sect_per_clus] |
add ax, word [cur_delta] |
adc dx, word [cur_delta+2] |
add word [cur_delta], cx |
adc word [cur_delta+2], 0 |
; read |
call [read_sectors2] |
pop dx |
; next cluster? |
nextclus: |
popf |
pop ax |
mov [cur_cluster], si |
mov [next_cluster], ax |
pushf |
pop [flags] |
jnc @f ; no next cluster => return |
mov dl, 1 ; dh=0 in any case |
test di, di |
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded |
push di |
jmp clusloop ; all is ok, continue |
hooked_err: |
mov sp, 7C00h-12-2 ; restore stack |
mov dx, 3 ; return: read error |
@@: |
mov bx, dx |
mov ax, [filesize] |
mov dx, [filesize+2] |
ret |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 7C00h-8 |
mov bp, 7C00h |
push dx |
push cx |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
; function 2: continue loading file |
; can be called only after function 1 returned value bx=1 (only part of file was loaded) |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
callback_ret_succ: |
clc ; function is supported |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kord/loader',0 |
aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 |
foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache |
foldcache_mark rw 7 |
foldcache_size rw 7 |
filename rb 11 |
if $ > 0x8200 |
error: table overwritten |
end if |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
org 0x7E00 |
; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here |
; ss:bp = 0:7C00 |
virtual at bp |
rb 3 ; BS_jmpBoot |
rb 8 ; BS_OEMName, ignored |
dw ? ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
BPB_TotSec16 dw ? |
db ? ; BPB_Media |
BPB_FATSz16 dw ? |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
BPB_TotSec32 dd ? |
BS_DrvNum db ? |
fat_type db ? ; this is BS_Reserved1, |
; we use it to save FS type: 0=FAT12, 1=FAT16 |
db ? ; BS_BootSig |
num_sectors dd ? ; BS_VolID |
; rb 11 ; BS_VolLab |
; rb 3 ; BS_FilSysType, first 3 bytes |
read_sectors dw ? |
read_sectors2 dw ? |
lookup_in_root_dir dw ? |
scan_for_filename dw ? |
err_ dw ? |
noloader dw ? |
cachelimit dw ? |
filesize: ; will be used to save file size |
rb 5 ; BS_FilSysType, last 5 bytes |
; following variables are located in the place of starting code; |
; starting code is no more used at this point |
sect_per_clus dw ? |
cur_cluster dw ? |
next_cluster dw ? |
flags dw ? |
cur_delta dd ? |
end virtual |
; procedures from boot sector |
; LBA version |
lba_read_sectors = 7CE2h |
lba_read_sectors2 = 7CDCh |
lba_lookup_in_root_dir = 7D4Fh |
lba_scan_for_filename = 7D2Dh |
lba_err = 7CB5h |
lba_noloader = 7CB2h |
; CHS version |
chs_read_sectors = 7CDEh |
chs_read_sectors2 = 7CD8h |
chs_lookup_in_root_dir = 7D70h |
chs_scan_for_filename = 7D4Eh |
chs_err = 7CB1h |
chs_noloader = 7CAEh |
push ax cx ; save our position on disk |
push ss |
pop es |
; determine version of bootsector (LBA vs CHS) |
; mov [read_sectors], chs_read_sectors |
; mov [read_sectors2], chs_read_sectors2 |
; mov [lookup_in_root_dir], chs_lookup_in_root_dir |
; mov [scan_for_filename], chs_scan_for_filename |
; mov [err], chs_err |
; mov [noloader], chs_noloader |
lea di, [read_sectors] |
mov si, chs_proc_addresses |
mov cx, 6*2 |
cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di' |
jz @f |
add si, cx |
; mov [read_sectors], lba_read_sectors |
; mov [read_sectors2], lba_read_sectors2 |
; mov [lookup_in_root_dir], lba_lookup_in_root_dir |
; mov [scan_for_filename], lba_scan_for_filename |
; mov [err], lba_err |
; mov [noloader], lba_noloader |
@@: |
rep movsb |
mov cl, [BPB_SecsPerClus] |
mov [sect_per_clus], cx |
xor bx, bx |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 94000h / 1024 |
jae @f |
nomem: |
mov si, nomem_str |
jmp [err_] |
@@: |
shr ax, 3 |
mov [cachelimit], ax ; size of cache - 1 |
; get type of file system - FAT12 or FAT16? |
; calculate number of clusters |
mov ax, [BPB_TotSec16] |
xor dx, dx |
test ax, ax |
jnz @f |
mov ax, word [BPB_TotSec32] |
mov dx, word [BPB_TotSec32+2] |
@@: |
sub ax, [bp-8] ; dword [bp-8] = first data sector |
sbb dx, [bp-6] |
jb j_noloader |
div [sect_per_clus] |
; ax = number of clusters |
; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes |
mov [fat_type], ch |
cmp ax, 0xFF5 |
jb init_fat12 |
inc [fat_type] |
init_fat16: |
; no sectors loaded |
mov di, 0x8200 |
xor ax, ax |
mov cx, 0x100/2 |
rep stosw |
jmp init_fat_done |
init_fat12: |
; read FAT |
push 0x6000 |
pop es |
mov ax, [BPB_RsvdSecCnt] |
mov cx, [BPB_FATSz16] |
cmp cx, 12 |
jb @f |
mov cx, 12 |
@@: |
xor dx, dx |
call [read_sectors] |
init_fat_done: |
; if cluster = sector, we need to read second part of our file |
; (bootsector loads only first cluster of kordldr.f1x) |
pop cx ax ; restore our position on disk |
cmp cx, 1 |
ja kordldr_full |
sub ax, [bp-8] |
inc ax |
inc ax ; ax = first cluster of kordldr.f12 |
call get_next_cluster |
jc @f |
j_noloader: |
jmp [noloader] |
@@: |
dec ax |
dec ax |
push 0x800 |
pop es |
call [read_sectors2] |
kordldr_full: |
; ...continue loading... |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
mov bx, [err_] |
jz @f |
mov si, aKernelNotFound |
jmp bx |
@@: |
; for subsequent calls to callback function, hook error handler |
; mov byte [bx], 0xE9 ; 'jmp' opcode |
; mov ax, hooked_err - 3 |
; sub ax, bx |
; mov word [bx+1], ax |
; push hooked_err / ret |
mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8) |
mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8) |
; set registers for secondary loader |
mov ah, [BS_DrvNum] |
mov al, 'f' |
test ah, ah |
jns @f |
sub ah, 80h |
mov al, 'h' |
@@: |
mov bx, '12' |
cmp [fat_type], 0 |
jz @f |
mov bh, '6' |
@@: |
mov si, callback ; ds:si = far pointer to callback procedure |
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 |
nomem_str db 'No memory',0 |
chs_proc_addresses: |
dw chs_read_sectors |
dw chs_read_sectors2 |
dw chs_lookup_in_root_dir |
dw chs_scan_for_filename |
dw chs_err |
dw chs_noloader |
lba_proc_addresses: |
dw lba_read_sectors |
dw lba_read_sectors2 |
dw lba_lookup_in_root_dir |
dw lba_scan_for_filename |
dw lba_err |
dw lba_noloader |
get_next_cluster: |
; in: ax = cluster |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
push si |
cmp [fat_type], 0 |
jnz gnc16 |
; for FAT12 |
push ds |
push 0x6000 |
pop ds |
mov si, ax |
shr si, 1 |
add si, ax |
test al, 1 |
lodsw |
jz @f |
shr ax, 4 |
@@: |
and ax, 0xFFF |
cmp ax, 0xFF7 |
pop ds si |
ret |
; for FAT16 |
gnc16: |
; each sector contains 200h bytes = 100h FAT entries |
; so ah = # of sector, al = offset in sector |
mov si, ax |
mov ah, 0 |
shr si, 8 |
; calculate segment for this sector of FAT table |
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) |
; segment = 6000 + 20*si, offset = 0 |
push es |
push si |
shl si, 5 |
add si, 0x6000 |
mov es, si |
pop si |
cmp byte [ss:0x8200+si], ah ; sector already loaded? |
jnz @f |
; load corresponding sector |
pusha |
push es |
xor bx, bx |
mov ax, [BPB_RsvdSecCnt] |
xor dx, dx |
add ax, si |
adc dx, bx |
mov cx, 1 ; read 1 sector |
call [read_sectors] |
pop es |
popa |
@@: |
mov si, ax |
add si, si |
; mov ax, [es:si] |
lods word [es:si] |
pop es |
cmp ax, 0xFFF7 |
pop si |
ret |
if $ > 0x8000 |
error 'get_next_cluster must fit in first sector of kordldr.f1x!' |
end if |
load_file: |
; in: ss:bp = 0:7C00 |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
xor ax, ax ; start from root directory |
mov dx, -1 |
mov word [filesize], dx |
mov word [filesize+2], dx ; initialize file size with invalid value |
lea si, [di+6] |
parse_dir_loop: |
; convert name to FAT name |
push di |
push ax |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
mov di, filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
nameloop: |
lodsb |
test al, al |
jz namedone |
cmp al, '/' |
jz namedone |
cmp al, '.' |
jz namedot |
dec cx |
js badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp nameloop |
namedot: |
inc bx |
jp badname |
add di, cx |
mov cl, 3 |
jmp nameloop |
badname: ; do not make direct js/jp to notfound_pop: |
; this generates long forms of conditional jumps and results in longer code |
jmp notfound_pop |
namedone: |
; scan directory |
pop ax ; ax = cluster of directory or 0 for root |
push ds |
push si |
push es |
pop ds |
mov si, filename ; ds:si -> filename in FAT style |
test ax, ax |
jnz lookup_in_notroot_dir |
; for root directory, use the subroutine from bootsector |
call [lookup_in_root_dir] |
jmp lookup_done |
lookup_in_notroot_dir: |
; for other directories, read a folder sector-by-sector and scan |
; first, try to use the cache |
push ds |
push cs |
pop ds |
mov bx, [cachelimit] |
add bx, bx |
mov di, foldcache_mark |
@@: |
mov dx, [foldcache_clus+di-foldcache_mark+bx] |
cmp dx, ax |
jz cacheok |
test dx, dx |
jz cacheadd ; the cache has place for new entry |
dec bx |
dec bx |
jns @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov dx, [cachelimit] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
mov [foldcache_clus+di-foldcache_mark+bx], ax |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [cachelimit] |
add di, di |
cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
pop ds |
; mov dx, bx |
; shl dx, 8 ; dx = (position in cache)*0x2000/0x10 |
; add dx, 0x9200 |
lea dx, [bx+0x92] |
xchg dl, dh |
mov es, dx |
jcxz not_in_cache |
call [scan_for_filename] |
jz lookup_done |
not_in_cache: |
; cache miss, read folder data from disk |
mov bx, cx |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
folder_next_cluster: |
; internal loop: scan sectors in cluster |
mov cx, [sect_per_clus] |
push ax |
dec ax |
dec ax |
mul cx |
add ax, [bp-8] |
adc dx, [bp-6] ; dx:ax = absolute sector |
folder_next_sector: |
; skip first bx sectors |
dec bx |
jns folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
call [read_sectors] |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
push si di |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache |
pop di si |
@@: |
push es |
push 0x8000 |
pop es |
push cs |
pop ds |
mov cx, 0x10 |
call [scan_for_filename] |
pop es |
pop cx |
jz lookup_done_pop |
folder_skip_sector: |
inc ax |
jnz @f |
inc dx |
@@: |
loop folder_next_sector |
pop ax ; ax = current cluster |
call get_next_cluster |
jc folder_next_cluster |
stc |
push ax |
lookup_done_pop: |
pop ax |
lookup_done: |
pop si |
pop ds |
; CF=1 <=> failed |
jnc found |
notfound: |
pop di |
mov bx, 2 ; file not found |
mov ax, 0xFFFF |
mov dx, ax ; invalid file size |
ret |
notfound_pop: |
pop ax |
jmp notfound |
found: |
mov ax, [es:di+26] ; get cluster |
test byte [es:di+11], 10h ; directory? |
jz regular_file |
cmp byte [si-1], 0 |
jz notfound ; don't read directories as a regular files |
; ok, we have found a directory and the caller requested a file into it |
pop di |
jmp parse_dir_loop ; restart with new cluster in ax |
regular_file: |
cmp byte [si-1], 0 |
jnz notfound ; file does not contain another files |
; ok, we have found a regular file and the caller requested it |
; save file size |
mov dx, [es:di+28] |
mov [filesize], dx |
mov dx, [es:di+30] |
mov [filesize+2], dx |
pop di |
mov si, [di+4] |
shl si, 3 |
push si ; [ds:di+4] = limit in 4K blocks |
les bx, [di] ; es:bx -> buffer |
clusloop: |
; ax = first cluster, top of stack contains limit in sectors |
mov si, ax ; remember current cluster |
xor cx, cx ; cx will contain number of consecutive clusters |
mov word [cur_delta], cx |
mov word [cur_delta+2], cx |
mov di, ax |
clusfind: |
inc di |
inc cx |
call get_next_cluster |
jnc clusread |
cmp ax, di |
jz clusfind |
stc |
clusread: |
pop di ; limit in sectors |
push ax ; save next cluster |
pushf ; save flags |
; read cx clusters, starting from si |
; calculate number of sectors |
xchg ax, cx |
mul [sect_per_clus] |
; dx:ax = number of sectors; compare with limit |
mov word [num_sectors], ax |
mov word [num_sectors+2], dx |
jmp @f |
continue_load_file: |
les bx, [di] ; es:bx -> buffer |
mov di, [di+4] ; ds:di = limit in 4K blocks |
shl di, 3 ; now di = limit in sectors |
mov ax, word [num_sectors] |
mov dx, word [num_sectors+2] |
mov si, [cur_cluster] |
push [next_cluster] |
push [flags] |
or ax, dx |
jz nextclus |
@@: |
test dx, dx |
jnz clusdecrease |
push dx ; limit was not exceeded |
cmp ax, di |
jbe @f |
pop ax |
clusdecrease: |
push 1 ; limit was exceeded |
mov ax, di |
@@: |
sub di, ax ; calculate new limit |
sub word [num_sectors], ax |
sbb word [num_sectors+2], 0 |
; calculate starting sector |
xchg ax, cx |
lea ax, [si-2] |
mul [sect_per_clus] |
add ax, word [cur_delta] |
adc dx, word [cur_delta+2] |
add word [cur_delta], cx |
adc word [cur_delta+2], 0 |
; read |
call [read_sectors2] |
pop dx |
; next cluster? |
nextclus: |
popf |
pop ax |
mov [cur_cluster], si |
mov [next_cluster], ax |
pushf |
pop [flags] |
jnc @f ; no next cluster => return |
mov dl, 1 ; dh=0 in any case |
test di, di |
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded |
push di |
jmp clusloop ; all is ok, continue |
hooked_err: |
mov sp, 7C00h-12-2 ; restore stack |
mov dx, 3 ; return: read error |
@@: |
mov bx, dx |
mov ax, [filesize] |
mov dx, [filesize+2] |
ret |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 7C00h-8 |
mov bp, 7C00h |
push dx |
push cx |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
; function 2: continue loading file |
; can be called only after function 1 returned value bx=1 (only part of file was loaded) |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
callback_ret_succ: |
clc ; function is supported |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kord/loader',0 |
aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 |
foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache |
foldcache_mark rw 7 |
foldcache_size rw 7 |
filename rb 11 |
if $ > 0x8200 |
error: |
table overwritten |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot/fat32/bootsect.asm |
---|
1,358 → 1,358 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
use_lba = 0 |
org 0x7C00 |
jmp start |
nop |
; FAT parameters, BPB |
; they must be changed at install, replaced with real values |
rb 8 ; BS_OEMName, ignored |
dw 200h ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
dw ? ; BPB_TotSec16 |
db ? ; BPB_Media |
dw ? ; BPB_FATSz16 = 0 for FAT32 |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
dd ? ; BPB_TotSec32 |
BPB_FATSz32 dd ? |
BPB_ExtFlags dw ? |
dw ? ; BPB_FSVer |
BPB_RootClus dd ? |
dw ? ; BPB_FSInfo |
BPB_BkBootSec dw ? |
rb 12 ; BPB_Reserved |
BS_DrvNum db ? |
db ? ; BS_Reserved1 |
db ? ; BS_BootSig |
dd ? ; BS_VolID |
rb 11 ; BS_VolLab |
rb 8 ; |
curseg dw 0x8000 |
start: |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov bp, sp |
cld |
sti |
push dx ; byte [bp-2] = boot drive |
if use_lba |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cl, 1 |
jz err_ |
else |
mov ah, 8 |
int 13h |
jc @f |
movzx ax, dh |
inc ax |
mov [bp+BPB_NumHeads-0x7C00], ax |
and cx, 3Fh |
mov [bp+BPB_SecPerTrk-0x7C00], cx |
@@: |
end if |
; get FAT parameters |
xor bx, bx |
movzx eax, [bp+BPB_NumFATs-0x7C00] |
mul [bp+BPB_FATSz32-0x7C00] |
movzx ecx, [bp+BPB_RsvdSecCnt-0x7C00] |
push ecx ; FAT start = dword [bp-6] |
add eax, ecx |
push eax ; data start = dword [bp-10] |
;push dword -1 ; dword [bp-14] = current sector for FAT cache |
db 66h |
push -1 ; dword [bp-14] = current sector for FAT cache |
mov eax, [bp+BPB_RootClus-0x7C00] |
mov si, main_loader |
call lookup_in_dir |
jnc kordldr_ok |
noloader: |
mov si, aLoaderNotFound |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
kordldr_ok: |
mov eax, [es:di+20-2] ; hiword(eax) = hiword(cluster) |
mov ax, [es:di+26] ; loword(eax) = loword(cluster) |
mov es, bx ; es = 0 |
mov bx, 0x7E00 |
push bx ; save return address: bx = 7E00 |
; fall through - 'ret' in read_cluster will return to 7E00 |
read_cluster: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; eax = cluster |
sub eax, 2 |
movzx ecx, [bp+BPB_SecsPerClus-0x7C00] |
mul ecx |
read_sectors2: |
; same as read_sectors32, but eax is relative to start of data |
add eax, [bp-10] |
read_sectors32: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; eax = first sector |
; cx = number of sectors |
; some high words of 32-bit registers are destroyed! |
pusha |
add eax, [bp+BPB_HiddSec-0x7C00] |
if use_lba |
push ds |
do_read_sectors: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp-2] |
mov ah, 42h |
int 13h |
mov si, aReadError |
jc err_ |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz do_read_sectors |
pop ds |
popa |
ret |
else |
do_read_sectors: |
pusha |
pop edi ; loword(edi) = di, hiword(edi) = si |
push bx |
; eax / (SectorsPerTrack) -> eax, remainder bx |
movzx esi, [bp+BPB_SecPerTrk-0x7C00] |
xor edx, edx |
div esi |
mov bx, dx ; bx=sector-1 |
; eax -> dx:ax |
push eax |
pop ax |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp+BPB_NumHeads-0x7C00] |
; number of sectors: read no more than to end of track |
sub si, bx |
cmp cx, si |
jbe @f |
mov cx, si |
@@: |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format |
movzx edi, cx |
mov dh, dl |
mov dl, [bp-2] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
mov si, aReadError |
jmp err_ |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push edi |
popa |
add eax, edi |
sub cx, di |
jnz do_read_sectors |
popa |
ret |
end if |
lookup_in_dir: |
; in: ds:si -> 11-bytes FAT name |
; in: eax = cluster |
; in: bx = 0 |
; out: if found: CF=0, es:di -> directory entry |
; out: if not found: CF=1 |
; push 0x8000 |
; pop es |
; read current cluster: first cluster goes to 8000:0000, others - to 8200:0000 |
mov es, [bp-7C00h + curseg] |
push es |
push eax |
call read_cluster |
mov ax, es |
cmp ah, 82h |
jb @f |
mov ax, 8200h |
@@: |
mov [bp-7C00h + curseg], ax |
pop eax |
pop es |
; scan for filename |
shl cx, 4 |
xor di, di |
sloop: |
cmp byte [es:di], bl |
jz snotfound |
test byte [es:di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmpsb |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
; next cluster |
push 0x6000 |
pop es |
push es ax |
shr eax, 7 |
cmp eax, [bp-14] |
mov [bp-14], eax |
jz @f |
add eax, [bp-6] |
mov cx, 1 |
call read_sectors32 |
@@: |
pop di es |
and di, 0x7F |
shl di, 2 |
and byte [es:di+3], 0x0F |
mov eax, [es:di] |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
jb lookup_in_dir |
snotfound: |
stc |
sdone: |
ret |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz sdone |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aReadError db 'Read error',0 |
if use_lba |
aNoLBA db 'The drive does not support LBA!',0 |
end if |
aLoaderNotFound db 'Loader not found',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
main_loader db 'KORDLDR F32' |
db 56h |
; just to make file 512 bytes long :) |
db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' |
; bootsector signature |
dw 0xAA55 |
; display offsets of all procedures used by kordldr.f12.asm |
macro show [procedure] |
{ |
bits = 16 |
display `procedure,' = ' |
repeat bits/4 |
d = '0' + procedure shr (bits - %*4) and 0Fh |
if d > '9' |
d = d + 'A'-'9'-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
show read_sectors32, read_sectors2, err_, noloader |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
use_lba = 0 |
org 0x7C00 |
jmp start |
nop |
; FAT parameters, BPB |
; they must be changed at install, replaced with real values |
rb 8 ; BS_OEMName, ignored |
dw 200h ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
dw ? ; BPB_TotSec16 |
db ? ; BPB_Media |
dw ? ; BPB_FATSz16 = 0 for FAT32 |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
dd ? ; BPB_TotSec32 |
BPB_FATSz32 dd ? |
BPB_ExtFlags dw ? |
dw ? ; BPB_FSVer |
BPB_RootClus dd ? |
dw ? ; BPB_FSInfo |
BPB_BkBootSec dw ? |
rb 12 ; BPB_Reserved |
BS_DrvNum db ? |
db ? ; BS_Reserved1 |
db ? ; BS_BootSig |
dd ? ; BS_VolID |
rb 11 ; BS_VolLab |
rb 8 ; |
curseg dw 0x8000 |
start: |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov bp, sp |
cld |
sti |
push dx ; byte [bp-2] = boot drive |
if use_lba |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cl, 1 |
jz err_ |
else |
mov ah, 8 |
int 13h |
jc @f |
movzx ax, dh |
inc ax |
mov [bp+BPB_NumHeads-0x7C00], ax |
and cx, 3Fh |
mov [bp+BPB_SecPerTrk-0x7C00], cx |
@@: |
end if |
; get FAT parameters |
xor bx, bx |
movzx eax, [bp+BPB_NumFATs-0x7C00] |
mul [bp+BPB_FATSz32-0x7C00] |
movzx ecx, [bp+BPB_RsvdSecCnt-0x7C00] |
push ecx ; FAT start = dword [bp-6] |
add eax, ecx |
push eax ; data start = dword [bp-10] |
;push dword -1 ; dword [bp-14] = current sector for FAT cache |
db 66h |
push -1 ; dword [bp-14] = current sector for FAT cache |
mov eax, [bp+BPB_RootClus-0x7C00] |
mov si, main_loader |
call lookup_in_dir |
jnc kordldr_ok |
noloader: |
mov si, aLoaderNotFound |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
kordldr_ok: |
mov eax, [es:di+20-2] ; hiword(eax) = hiword(cluster) |
mov ax, [es:di+26] ; loword(eax) = loword(cluster) |
mov es, bx ; es = 0 |
mov bx, 0x7E00 |
push bx ; save return address: bx = 7E00 |
; fall through - 'ret' in read_cluster will return to 7E00 |
read_cluster: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; eax = cluster |
sub eax, 2 |
movzx ecx, [bp+BPB_SecsPerClus-0x7C00] |
mul ecx |
read_sectors2: |
; same as read_sectors32, but eax is relative to start of data |
add eax, [bp-10] |
read_sectors32: |
; ss:bp = 0:7C00 |
; es:bx = pointer to data |
; eax = first sector |
; cx = number of sectors |
; some high words of 32-bit registers are destroyed! |
pusha |
add eax, [bp+BPB_HiddSec-0x7C00] |
if use_lba |
push ds |
do_read_sectors: |
push ax |
push cx |
cmp cx, 0x7F |
jbe @f |
mov cx, 0x7F |
@@: |
; create disk address packet on the stack |
; dq starting LBA |
push 0 |
push 0 |
push eax |
; dd buffer |
push es |
push bx |
; dw number of blocks to transfer (no more than 0x7F) |
push cx |
; dw packet size in bytes |
push 10h |
; issue BIOS call |
push ss |
pop ds |
mov si, sp |
mov dl, [bp-2] |
mov ah, 42h |
int 13h |
mov si, aReadError |
jc err_ |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 5 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz do_read_sectors |
pop ds |
popa |
ret |
else |
do_read_sectors: |
pusha |
pop edi ; loword(edi) = di, hiword(edi) = si |
push bx |
; eax / (SectorsPerTrack) -> eax, remainder bx |
movzx esi, [bp+BPB_SecPerTrk-0x7C00] |
xor edx, edx |
div esi |
mov bx, dx ; bx=sector-1 |
; eax -> dx:ax |
push eax |
pop ax |
pop dx |
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx |
div [bp+BPB_NumHeads-0x7C00] |
; number of sectors: read no more than to end of track |
sub si, bx |
cmp cx, si |
jbe @f |
mov cx, si |
@@: |
inc bx |
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format |
movzx edi, cx |
mov dh, dl |
mov dl, [bp-2] |
shl ah, 6 |
mov ch, al |
mov al, cl |
mov cl, bl |
or cl, ah |
pop bx |
mov si, 3 |
mov ah, 2 |
@@: |
push ax |
int 13h |
jnc @f |
xor ax, ax |
int 13h ; reset drive |
pop ax |
dec si |
jnz @b |
mov si, aReadError |
jmp err_ |
@@: |
pop ax |
mov ax, es |
mov cx, di |
shl cx, 5 |
add ax, cx |
mov es, ax |
push edi |
popa |
add eax, edi |
sub cx, di |
jnz do_read_sectors |
popa |
ret |
end if |
lookup_in_dir: |
; in: ds:si -> 11-bytes FAT name |
; in: eax = cluster |
; in: bx = 0 |
; out: if found: CF=0, es:di -> directory entry |
; out: if not found: CF=1 |
; push 0x8000 |
; pop es |
; read current cluster: first cluster goes to 8000:0000, others - to 8200:0000 |
mov es, [bp-7C00h + curseg] |
push es |
push eax |
call read_cluster |
mov ax, es |
cmp ah, 82h |
jb @f |
mov ax, 8200h |
@@: |
mov [bp-7C00h + curseg], ax |
pop eax |
pop es |
; scan for filename |
shl cx, 4 |
xor di, di |
sloop: |
cmp byte [es:di], bl |
jz snotfound |
test byte [es:di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmpsb |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
; next cluster |
push 0x6000 |
pop es |
push es ax |
shr eax, 7 |
cmp eax, [bp-14] |
mov [bp-14], eax |
jz @f |
add eax, [bp-6] |
mov cx, 1 |
call read_sectors32 |
@@: |
pop di es |
and di, 0x7F |
shl di, 2 |
and byte [es:di+3], 0x0F |
mov eax, [es:di] |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
jb lookup_in_dir |
snotfound: |
stc |
sdone: |
ret |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz sdone |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aReadError db 'Read error',0 |
if use_lba |
aNoLBA db 'The drive does not support LBA!',0 |
end if |
aLoaderNotFound db 'Loader not found',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
main_loader db 'KORDLDR F32' |
db 56h |
; just to make file 512 bytes long :) |
db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' |
; bootsector signature |
dw 0xAA55 |
; display offsets of all procedures used by kordldr.f12.asm |
macro show [procedure] |
{ |
bits = 16 |
display `procedure,' = ' |
repeat bits/4 |
d = '0' + procedure shr (bits - %*4) and 0Fh |
if d > '9' |
d = d + 'A'-'9'-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
show read_sectors32, read_sectors2, err_, noloader |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot/fat32/kordldr.f32.asm |
---|
1,672 → 1,672 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
org 0x7E00 |
; the KordOS FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here |
; ss:bp = 0:7C00 |
; ds = 0 |
virtual at bp |
rb 3 ; BS_jmpBoot |
rb 8 ; BS_OEMName, ignored |
dw ? ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
dw ? ; BPB_TotSec16 |
db ? ; BPB_Media |
dw ? ; BPB_FATSz16 = 0 for FAT32 |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
dd ? ; BPB_TotSec32 |
BPB_FATSz32 dd ? |
BPB_ExtFlags dw ? |
dw ? ; BPB_FSVer |
BPB_RootClus dd ? |
filesize: |
dw ? ; BPB_FSInfo |
dw ? ; BPB_BkBootSec |
rb 12 ; BPB_Reserved |
BS_DrvNum db ? |
db ? ; BS_Reserved1 |
db ? ; BS_BootSig |
dd ? ; BS_VolID |
; rb 11 ; BS_VolLab |
; rb 5 ; BS_FilSysType, first 5 bytes |
read_sectors32 dw ? |
read_sectors2 dw ? |
err_ dw ? |
noloader dw ? |
cachelimit dw ? |
fatcachehead rw 2 |
fatcacheend dw ? |
rb 3 ; BS_FilSysType, last 3 bytes |
curseg dw ? |
num_sectors dd ? |
cur_cluster dd ? |
next_cluster dd ? |
flags dw ? |
cur_delta dd ? |
end virtual |
; procedures from boot sector |
; LBA version |
lba_read_sectors2 = 7CD6h |
lba_err = 7CAAh |
lba_noloader = 7CA7h ; = lba_err - 3 |
; CHS version |
chs_read_sectors2 = 7CD2h |
chs_err = 7CA6h |
chs_noloader = 7CA3h ; = chs_err - 3 |
push eax cx ; save our position on disk |
; determine version of bootsector (LBA vs CHS) |
mov [read_sectors2], chs_read_sectors2 |
mov bx, chs_err |
mov [err_], bx |
; mov [noloader], chs_noloader |
cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version |
jz @f |
add [read_sectors2], lba_read_sectors2 - chs_read_sectors2 |
add [err_], lba_err - chs_err |
; mov [noloader], lba_noloader |
@@: |
xor bx, bx |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 92000h / 1024 |
jae @f |
nomem: |
mov si, nomem_str |
jmp [err_] |
@@: |
shr ax, 3 |
mov [cachelimit], ax ; size of cache - 1 |
mov es, bx |
; no folders in cache yet |
mov di, foldcache_clus |
mov cx, 8*4/2 + 1 |
xor ax, ax |
rep stosw |
; bootsector code caches one FAT sector, [bp-14], in 6000:0000 |
; initialize our (more advanced) FAT caching from this |
mov di, 8400h |
mov cx, di |
lea si, [fatcachehead] |
mov [si], si ; no sectors in cache: |
mov [si+2], si ; 'prev' & 'next' links point to self |
mov [fatcacheend], di ; first free item = 8400h |
stosw ; 'next cached sector' link |
stosw ; 'prev cached sector' link |
mov eax, [bp-14] |
stosd ; first sector number in cache |
test eax, eax |
js @f |
mov [si], cx ; 'first cached sector' link = 8400h |
mov [si+2], cx ; 'next cached sector' link = 8400h |
mov [fatcacheend], di ; first free item = 8406h |
@@: |
; if cluster = sector, we need to read second part of our file |
; (bootsector loads only first cluster of kordldr.f32) |
pop cx eax ; restore our position on disk |
cmp cx, 1 |
ja kordldr_full |
sub eax, [bp-10] |
inc eax |
inc eax ; eax = first cluster of kordldr.f32 |
call get_next_cluster |
jc @f |
; jmp [noloader] |
mov ax, [err_] |
sub ax, 3 |
jmp ax |
@@: |
dec eax |
dec eax |
push 0x800 |
pop es |
call [read_sectors2] |
kordldr_full: |
; bootsector code has read some data of root directory to 8000:0000 |
; initialize our folder caching from this |
mov eax, [BPB_RootClus] |
mov [foldcache_clus], eax |
mov cx, [curseg] |
mov ax, 8000h |
sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes) |
shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes) |
mov [foldcache_size], cx |
shl cx, 4 |
push ds |
mov ds, ax |
push 0x9000 |
pop es |
xor si, si |
xor di, di |
rep movsw |
pop ds |
; ...continue loading... |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
mov bx, [err_] |
jz @f |
mov si, aKernelNotFound |
jmp bx |
@@: |
; for subsequent calls to callback function, hook error handler |
; push hooked_err / ret |
mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24) |
; set registers for secondary loader |
mov ah, [bp-2] ; drive id |
mov al, 'f' |
btr ax, 15 |
jnc @f |
mov al, 'h' |
@@: |
mov bx, '32' |
mov si, callback |
jmp far [si+secondary_loader_info-callback] |
nomem_str db 'No memory',0 |
cluster2sector: |
sub eax, 2 |
clustersz2sectorsz: |
movzx ecx, [BPB_SecsPerClus] |
mul ecx |
ret |
get_next_cluster: |
; in: eax = cluster |
; out: if there is next cluster: CF=1, eax = next cluster |
; out: if there is no next cluster: CF=0 |
push di bx |
push ds |
push ss |
pop ds |
push ax |
shr eax, 7 |
; eax = FAT sector number; look in cache |
mov di, 8400h |
.cache_lookup: |
cmp di, [fatcacheend] |
jae .not_in_cache |
scasd |
scasd |
jnz .cache_lookup |
.in_cache: |
sub di, 8 |
; delete this sector from the list |
push si |
mov si, [di] |
mov bx, [di+2] |
mov [si+2], bx |
mov [bx], si |
pop si |
jmp @f |
.not_in_cache: |
; cache miss |
; cache is full? |
mov di, [fatcacheend] |
cmp di, 8C00h |
jnz .cache_not_full |
; yes, delete the oldest entry |
mov di, [fatcachehead] |
mov bx, [di] |
mov [fatcachehead], bx |
push word [di+2] |
pop word [bx+2] |
jmp .cache_append |
.cache_not_full: |
; no, allocate new sector |
add [fatcacheend], 8 |
.cache_append: |
; read FAT |
mov [di+4], eax |
push es |
pushad |
lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))] ; +0x10000 - for FASM |
shl cx, 9-3 |
mov es, cx |
xor bx, bx |
mov cx, 1 |
add eax, [bp-6] ; FAT start |
sub eax, [bp-10] |
call [read_sectors2] |
popad |
pop es |
@@: |
; add new sector to the end of list |
mov bx, di |
xchg bx, [fatcachehead+2] |
push word [bx] |
pop word [di] |
mov [bx], di |
mov [di+2], bx |
; get requested item |
lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))] |
pop di |
and di, 0x7F |
shl di, 2 |
shl ax, 9-3 |
mov ds, ax |
and byte [di+3], 0x0F |
mov eax, [di] |
pop ds |
pop bx di |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
ret |
if $ > 0x8000 |
error 'get_next_cluster must fit in first sector of kordldr.f32!' |
end if |
load_file: |
; in: ss:bp = 0:7C00 |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
mov eax, [BPB_RootClus] ; start from root directory |
or dword [filesize], -1 ; initialize file size with invalid value |
lea si, [di+6] |
parse_dir_loop: |
; convert name to FAT name |
push di |
push ax |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
filename equ bp |
mov di, filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
nameloop: |
lodsb |
test al, al |
jz namedone |
cmp al, '/' |
jz namedone |
cmp al, '.' |
jz namedot |
dec cx |
js badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp nameloop |
namedot: |
inc bx |
jp badname |
add di, cx |
mov cl, 3 |
jmp nameloop |
badname: ; do not make direct js/jp to notfound_pop: |
; this generates long forms of conditional jumps and results in longer code |
jmp notfound_pop |
namedone: |
; scan directory |
pop ax ; eax = cluster of directory |
; high word of eax is preserved by operations above |
push ds |
push si |
; read a folder sector-by-sector and scan |
; first, try to use the cache |
push ss |
pop ds |
mov di, foldcache_mark |
xor bx, bx |
mov cx, [cachelimit] |
@@: |
lea si, [di+bx] |
mov edx, dword [foldcache_clus+si-foldcache_mark+bx] |
cmp edx, eax |
jz cacheok |
test edx, edx |
jz cacheadd ; the cache has place for new entry |
inc bx |
inc bx |
dec cx |
jns @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov bx, -2 |
mov dx, [cachelimit] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
lea si, [di+bx] |
cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
mov dword [foldcache_clus+si-foldcache_mark+bx], eax |
cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [cachelimit] |
add di, di |
cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
;mov dx, bx |
;shl dx, 8 ; dx = (position in cache)*0x2000/0x10 |
;add dx, 0x9000 |
lea dx, [bx + 0x90] |
xchg dl, dh |
mov ds, dx |
mov si, filename ; ss:si -> filename in FAT style |
call scan_for_filename |
jz lookup_done |
; cache miss, read folder data from disk |
mov bx, cx |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
folder_next_cluster: |
; internal loop: scan sectors in cluster |
push eax |
call cluster2sector |
folder_next_sector: |
; skip first bx sectors |
dec bx |
jns folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
push eax |
call [read_sectors2] |
pop eax |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
pusha |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache |
popa |
@@: |
push es |
mov cl, 0x10 ; ch=0 at this point |
call scan_for_filename |
pop es |
pop cx |
jz lookup_done_pop |
folder_skip_sector: |
inc eax |
loop folder_next_sector |
pop eax ; eax = current cluster |
call get_next_cluster |
jc folder_next_cluster |
stc |
push eax |
lookup_done_pop: |
pop eax |
lookup_done: |
pop si |
; CF=1 <=> failed |
jnc found |
pop ds |
notfound: |
pop di |
notfound2: |
mov bx, 2 ; file not found |
mov ax, 0xFFFF |
mov dx, ax ; invalid file size |
ret |
notfound_pop: |
pop ax |
jmp notfound |
found: |
mov eax, [di+20-2] |
mov edx, [di+28] |
mov ax, [di+26] ; get cluster |
test byte [di+11], 10h ; directory? |
pop ds |
pop di |
jz regular_file |
cmp byte [si-1], 0 |
jz notfound2 ; don't read directories as regular files |
; ok, we have found a directory and the caller requested a file into it |
jmp parse_dir_loop ; restart with new cluster in ax |
regular_file: |
cmp byte [si-1], 0 |
jnz notfound2 ; file does not contain another files |
; ok, we have found a regular file and the caller requested it |
; save file size |
mov [filesize], edx |
mov si, [di+4] ; [ds:di+4] = limit in 4K blocks |
shl si, 3 |
push si |
les bx, [di] ; es:bx -> buffer |
clusloop: |
; eax = first cluster, top of stack contains limit in sectors |
mov esi, eax ; remember current cluster |
xor ecx, ecx ; ecx will contain number of consecutive clusters |
mov [cur_delta], ecx |
mov edi, eax |
clusfind: |
inc edi |
inc ecx |
call get_next_cluster |
jnc clusread |
cmp eax, edi |
jz clusfind |
stc |
clusread: |
pop di ; limit in sectors |
movzx edi, di |
push eax ; save next cluster |
pushf ; save flags |
; read cx clusters, starting from si |
; calculate number of sectors |
xchg eax, ecx |
call clustersz2sectorsz |
mov [num_sectors], eax |
jmp @f |
continue_load_file: |
les bx, [di] ; es:bx -> buffer |
movzx edi, word [di+4] ; di = limit in 4K blocks |
shl di, 3 ; now di = limit in sectors |
mov eax, [num_sectors] |
mov esi, [cur_cluster] |
push [next_cluster] |
push [flags] |
test eax, eax |
jz nextclus |
@@: |
; eax = number of sectors; compare with limit |
cmp eax, edi |
seta dl |
push dx ; limit was exceeded? |
jbe @f |
mov eax, edi |
@@: |
sub di, ax ; calculate new limit |
sub [num_sectors], eax |
mov [cur_cluster], esi |
; calculate starting sector |
push ax |
xchg eax, esi |
call cluster2sector |
pop cx |
add eax, [cur_delta] |
add [cur_delta], ecx |
; read |
call [read_sectors2] |
pop dx |
; next cluster? |
nextclus: |
popf |
pop eax |
mov [next_cluster], eax |
pushf |
pop [flags] |
jnc @f ; no next cluster => return |
mov dl, 1 ; dh=0 in any case |
test di, di |
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded |
push di |
jmp clusloop ; all is ok, continue |
hooked_err: |
mov sp, 7C00h-14-2 ; restore stack |
mov dx, 3 ; return: read error |
@@: |
mov bx, dx |
mov ax, [filesize] |
mov dx, [filesize+2] |
ret |
scan_for_filename: |
; in: ss:si -> 11-bytes FAT name |
; in: ds:0 -> part of directory data |
; in: cx = number of entries |
; in: bh = 0 |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
push ds |
pop es |
xor di, di |
push cx |
jcxz snoent |
sloop: |
cmp byte [di], bh |
jz snotfound |
test byte [di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmps byte [ss:si], byte [es:di] |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
snoent: |
inc cx ; clear ZF flag |
snotfound: |
stc |
sdone: |
pop cx |
lrdret: |
ret |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 7C00h-10 |
mov bp, 7C00h |
push dx |
push cx |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
; function 2: continue loading file |
; can be called only after function 1 returned value bx=1 (only part of file was loaded) |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
callback_ret_succ: |
clc ; function is supported |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kord/loader',0 |
aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 |
;if $ > 0x8200 |
;error 'total size of kordldr.f32 must not exceed 1024 bytes!' |
;end if |
;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache |
;foldcache_mark dw 0 |
; rw 7 |
;foldcache_size rw 8 |
foldcache_clus rd 8 |
foldcache_mark rw 8 |
foldcache_size rw 8 |
; Copyright (c) 2008-2009, diamond |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
org 0x7E00 |
; the KordOS FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here |
; ss:bp = 0:7C00 |
; ds = 0 |
virtual at bp |
rb 3 ; BS_jmpBoot |
rb 8 ; BS_OEMName, ignored |
dw ? ; BPB_BytsPerSec |
BPB_SecsPerClus db ? |
BPB_RsvdSecCnt dw ? |
BPB_NumFATs db ? |
BPB_RootEntCnt dw ? |
dw ? ; BPB_TotSec16 |
db ? ; BPB_Media |
dw ? ; BPB_FATSz16 = 0 for FAT32 |
BPB_SecPerTrk dw ? |
BPB_NumHeads dw ? |
BPB_HiddSec dd ? |
dd ? ; BPB_TotSec32 |
BPB_FATSz32 dd ? |
BPB_ExtFlags dw ? |
dw ? ; BPB_FSVer |
BPB_RootClus dd ? |
filesize: |
dw ? ; BPB_FSInfo |
dw ? ; BPB_BkBootSec |
rb 12 ; BPB_Reserved |
BS_DrvNum db ? |
db ? ; BS_Reserved1 |
db ? ; BS_BootSig |
dd ? ; BS_VolID |
; rb 11 ; BS_VolLab |
; rb 5 ; BS_FilSysType, first 5 bytes |
read_sectors32 dw ? |
read_sectors2 dw ? |
err_ dw ? |
noloader dw ? |
cachelimit dw ? |
fatcachehead rw 2 |
fatcacheend dw ? |
rb 3 ; BS_FilSysType, last 3 bytes |
curseg dw ? |
num_sectors dd ? |
cur_cluster dd ? |
next_cluster dd ? |
flags dw ? |
cur_delta dd ? |
end virtual |
; procedures from boot sector |
; LBA version |
lba_read_sectors2 = 7CD6h |
lba_err = 7CAAh |
lba_noloader = 7CA7h ; = lba_err - 3 |
; CHS version |
chs_read_sectors2 = 7CD2h |
chs_err = 7CA6h |
chs_noloader = 7CA3h ; = chs_err - 3 |
push eax cx ; save our position on disk |
; determine version of bootsector (LBA vs CHS) |
mov [read_sectors2], chs_read_sectors2 |
mov bx, chs_err |
mov [err_], bx |
; mov [noloader], chs_noloader |
cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version |
jz @f |
add [read_sectors2], lba_read_sectors2 - chs_read_sectors2 |
add [err_], lba_err - chs_err |
; mov [noloader], lba_noloader |
@@: |
xor bx, bx |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 92000h / 1024 |
jae @f |
nomem: |
mov si, nomem_str |
jmp [err_] |
@@: |
shr ax, 3 |
mov [cachelimit], ax ; size of cache - 1 |
mov es, bx |
; no folders in cache yet |
mov di, foldcache_clus |
mov cx, 8*4/2 + 1 |
xor ax, ax |
rep stosw |
; bootsector code caches one FAT sector, [bp-14], in 6000:0000 |
; initialize our (more advanced) FAT caching from this |
mov di, 8400h |
mov cx, di |
lea si, [fatcachehead] |
mov [si], si ; no sectors in cache: |
mov [si+2], si ; 'prev' & 'next' links point to self |
mov [fatcacheend], di ; first free item = 8400h |
stosw ; 'next cached sector' link |
stosw ; 'prev cached sector' link |
mov eax, [bp-14] |
stosd ; first sector number in cache |
test eax, eax |
js @f |
mov [si], cx ; 'first cached sector' link = 8400h |
mov [si+2], cx ; 'next cached sector' link = 8400h |
mov [fatcacheend], di ; first free item = 8406h |
@@: |
; if cluster = sector, we need to read second part of our file |
; (bootsector loads only first cluster of kordldr.f32) |
pop cx eax ; restore our position on disk |
cmp cx, 1 |
ja kordldr_full |
sub eax, [bp-10] |
inc eax |
inc eax ; eax = first cluster of kordldr.f32 |
call get_next_cluster |
jc @f |
; jmp [noloader] |
mov ax, [err_] |
sub ax, 3 |
jmp ax |
@@: |
dec eax |
dec eax |
push 0x800 |
pop es |
call [read_sectors2] |
kordldr_full: |
; bootsector code has read some data of root directory to 8000:0000 |
; initialize our folder caching from this |
mov eax, [BPB_RootClus] |
mov [foldcache_clus], eax |
mov cx, [curseg] |
mov ax, 8000h |
sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes) |
shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes) |
mov [foldcache_size], cx |
shl cx, 4 |
push ds |
mov ds, ax |
push 0x9000 |
pop es |
xor si, si |
xor di, di |
rep movsw |
pop ds |
; ...continue loading... |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
mov bx, [err_] |
jz @f |
mov si, aKernelNotFound |
jmp bx |
@@: |
; for subsequent calls to callback function, hook error handler |
; push hooked_err / ret |
mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24) |
; set registers for secondary loader |
mov ah, [bp-2] ; drive id |
mov al, 'f' |
btr ax, 15 |
jnc @f |
mov al, 'h' |
@@: |
mov bx, '32' |
mov si, callback |
jmp far [si+secondary_loader_info-callback] |
nomem_str db 'No memory',0 |
cluster2sector: |
sub eax, 2 |
clustersz2sectorsz: |
movzx ecx, [BPB_SecsPerClus] |
mul ecx |
ret |
get_next_cluster: |
; in: eax = cluster |
; out: if there is next cluster: CF=1, eax = next cluster |
; out: if there is no next cluster: CF=0 |
push di bx |
push ds |
push ss |
pop ds |
push ax |
shr eax, 7 |
; eax = FAT sector number; look in cache |
mov di, 8400h |
.cache_lookup: |
cmp di, [fatcacheend] |
jae .not_in_cache |
scasd |
scasd |
jnz .cache_lookup |
.in_cache: |
sub di, 8 |
; delete this sector from the list |
push si |
mov si, [di] |
mov bx, [di+2] |
mov [si+2], bx |
mov [bx], si |
pop si |
jmp @f |
.not_in_cache: |
; cache miss |
; cache is full? |
mov di, [fatcacheend] |
cmp di, 8C00h |
jnz .cache_not_full |
; yes, delete the oldest entry |
mov di, [fatcachehead] |
mov bx, [di] |
mov [fatcachehead], bx |
push word [di+2] |
pop word [bx+2] |
jmp .cache_append |
.cache_not_full: |
; no, allocate new sector |
add [fatcacheend], 8 |
.cache_append: |
; read FAT |
mov [di+4], eax |
push es |
pushad |
lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))] ; +0x10000 - for FASM |
shl cx, 9-3 |
mov es, cx |
xor bx, bx |
mov cx, 1 |
add eax, [bp-6] ; FAT start |
sub eax, [bp-10] |
call [read_sectors2] |
popad |
pop es |
@@: |
; add new sector to the end of list |
mov bx, di |
xchg bx, [fatcachehead+2] |
push word [bx] |
pop word [di] |
mov [bx], di |
mov [di+2], bx |
; get requested item |
lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))] |
pop di |
and di, 0x7F |
shl di, 2 |
shl ax, 9-3 |
mov ds, ax |
and byte [di+3], 0x0F |
mov eax, [di] |
pop ds |
pop bx di |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
ret |
if $ > 0x8000 |
error 'get_next_cluster must fit in first sector of kordldr.f32!' |
end if |
load_file: |
; in: ss:bp = 0:7C00 |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
mov eax, [BPB_RootClus] ; start from root directory |
or dword [filesize], -1 ; initialize file size with invalid value |
lea si, [di+6] |
parse_dir_loop: |
; convert name to FAT name |
push di |
push ax |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
filename equ bp |
mov di, filename |
push di |
mov cx, 8+3 |
mov al, ' ' |
rep stosb |
pop di |
mov cl, 8 ; 8 symbols per name |
mov bl, 1 |
nameloop: |
lodsb |
test al, al |
jz namedone |
cmp al, '/' |
jz namedone |
cmp al, '.' |
jz namedot |
dec cx |
js badname |
cmp al, 'a' |
jb @f |
cmp al, 'z' |
ja @f |
sub al, 'a'-'A' |
@@: |
stosb |
jmp nameloop |
namedot: |
inc bx |
jp badname |
add di, cx |
mov cl, 3 |
jmp nameloop |
badname: ; do not make direct js/jp to notfound_pop: |
; this generates long forms of conditional jumps and results in longer code |
jmp notfound_pop |
namedone: |
; scan directory |
pop ax ; eax = cluster of directory |
; high word of eax is preserved by operations above |
push ds |
push si |
; read a folder sector-by-sector and scan |
; first, try to use the cache |
push ss |
pop ds |
mov di, foldcache_mark |
xor bx, bx |
mov cx, [cachelimit] |
@@: |
lea si, [di+bx] |
mov edx, dword [foldcache_clus+si-foldcache_mark+bx] |
cmp edx, eax |
jz cacheok |
test edx, edx |
jz cacheadd ; the cache has place for new entry |
inc bx |
inc bx |
dec cx |
jns @b |
; the folder is not present in the cache, so add it |
; the cache is full; find the oldest entry and replace it with the new one |
mov bx, -2 |
mov dx, [cachelimit] |
@@: |
inc bx |
inc bx |
cmp word [di+bx], dx ; marks have values 0 through [cachelimit] |
jnz @b |
lea si, [di+bx] |
cacheadd: |
or word [di+bx], 0xFFFF ; very big value, it will be changed soon |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
mov dword [foldcache_clus+si-foldcache_mark+bx], eax |
cacheok: |
; update cache marks |
mov dx, [di+bx] |
mov cx, [foldcache_size+di-foldcache_mark+bx] |
mov di, [cachelimit] |
add di, di |
cacheupdate: |
cmp [foldcache_mark+di], dx |
adc [foldcache_mark+di], 0 |
dec di |
dec di |
jns cacheupdate |
and [foldcache_mark+bx], 0 |
; done, bx contains (position in cache)*2 |
;mov dx, bx |
;shl dx, 8 ; dx = (position in cache)*0x2000/0x10 |
;add dx, 0x9000 |
lea dx, [bx + 0x90] |
xchg dl, dh |
mov ds, dx |
mov si, filename ; ss:si -> filename in FAT style |
call scan_for_filename |
jz lookup_done |
; cache miss, read folder data from disk |
mov bx, cx |
shr bx, 4 |
shl cx, 5 |
mov di, cx ; es:di -> free space in cache entry |
; external loop: scan clusters |
folder_next_cluster: |
; internal loop: scan sectors in cluster |
push eax |
call cluster2sector |
folder_next_sector: |
; skip first bx sectors |
dec bx |
jns folder_skip_sector |
push cx |
push es di |
push 0x8000 |
pop es |
xor bx, bx |
mov cx, 1 |
push es |
push eax |
call [read_sectors2] |
pop eax |
; copy data to the cache... |
pop ds |
pop di es |
cmp di, 0x2000 ; ...if there is free space, of course |
jae @f |
pusha |
mov cx, 0x100 |
xor si, si |
rep movsw |
mov di, es |
shr di, 8 |
add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache |
popa |
@@: |
push es |
mov cl, 0x10 ; ch=0 at this point |
call scan_for_filename |
pop es |
pop cx |
jz lookup_done_pop |
folder_skip_sector: |
inc eax |
loop folder_next_sector |
pop eax ; eax = current cluster |
call get_next_cluster |
jc folder_next_cluster |
stc |
push eax |
lookup_done_pop: |
pop eax |
lookup_done: |
pop si |
; CF=1 <=> failed |
jnc found |
pop ds |
notfound: |
pop di |
notfound2: |
mov bx, 2 ; file not found |
mov ax, 0xFFFF |
mov dx, ax ; invalid file size |
ret |
notfound_pop: |
pop ax |
jmp notfound |
found: |
mov eax, [di+20-2] |
mov edx, [di+28] |
mov ax, [di+26] ; get cluster |
test byte [di+11], 10h ; directory? |
pop ds |
pop di |
jz regular_file |
cmp byte [si-1], 0 |
jz notfound2 ; don't read directories as regular files |
; ok, we have found a directory and the caller requested a file into it |
jmp parse_dir_loop ; restart with new cluster in ax |
regular_file: |
cmp byte [si-1], 0 |
jnz notfound2 ; file does not contain another files |
; ok, we have found a regular file and the caller requested it |
; save file size |
mov [filesize], edx |
mov si, [di+4] ; [ds:di+4] = limit in 4K blocks |
shl si, 3 |
push si |
les bx, [di] ; es:bx -> buffer |
clusloop: |
; eax = first cluster, top of stack contains limit in sectors |
mov esi, eax ; remember current cluster |
xor ecx, ecx ; ecx will contain number of consecutive clusters |
mov [cur_delta], ecx |
mov edi, eax |
clusfind: |
inc edi |
inc ecx |
call get_next_cluster |
jnc clusread |
cmp eax, edi |
jz clusfind |
stc |
clusread: |
pop di ; limit in sectors |
movzx edi, di |
push eax ; save next cluster |
pushf ; save flags |
; read cx clusters, starting from si |
; calculate number of sectors |
xchg eax, ecx |
call clustersz2sectorsz |
mov [num_sectors], eax |
jmp @f |
continue_load_file: |
les bx, [di] ; es:bx -> buffer |
movzx edi, word [di+4] ; di = limit in 4K blocks |
shl di, 3 ; now di = limit in sectors |
mov eax, [num_sectors] |
mov esi, [cur_cluster] |
push [next_cluster] |
push [flags] |
test eax, eax |
jz nextclus |
@@: |
; eax = number of sectors; compare with limit |
cmp eax, edi |
seta dl |
push dx ; limit was exceeded? |
jbe @f |
mov eax, edi |
@@: |
sub di, ax ; calculate new limit |
sub [num_sectors], eax |
mov [cur_cluster], esi |
; calculate starting sector |
push ax |
xchg eax, esi |
call cluster2sector |
pop cx |
add eax, [cur_delta] |
add [cur_delta], ecx |
; read |
call [read_sectors2] |
pop dx |
; next cluster? |
nextclus: |
popf |
pop eax |
mov [next_cluster], eax |
pushf |
pop [flags] |
jnc @f ; no next cluster => return |
mov dl, 1 ; dh=0 in any case |
test di, di |
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded |
push di |
jmp clusloop ; all is ok, continue |
hooked_err: |
mov sp, 7C00h-14-2 ; restore stack |
mov dx, 3 ; return: read error |
@@: |
mov bx, dx |
mov ax, [filesize] |
mov dx, [filesize+2] |
ret |
scan_for_filename: |
; in: ss:si -> 11-bytes FAT name |
; in: ds:0 -> part of directory data |
; in: cx = number of entries |
; in: bh = 0 |
; out: if found: CF=0, ZF=1, es:di -> directory entry |
; out: if not found, but continue required: CF=1 and ZF=0 |
; out: if not found and zero item reached: CF=1 and ZF=1 |
push ds |
pop es |
xor di, di |
push cx |
jcxz snoent |
sloop: |
cmp byte [di], bh |
jz snotfound |
test byte [di+11], 8 ; volume label? |
jnz scont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmps byte [ss:si], byte [es:di] |
popa |
jz sdone |
scont: |
add di, 0x20 |
loop sloop |
snoent: |
inc cx ; clear ZF flag |
snotfound: |
stc |
sdone: |
pop cx |
lrdret: |
ret |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only functions 1 and 2 are defined for now |
; save caller's stack |
mov dx, ss |
mov cx, sp |
; set our stack (required because we need ss=0) |
xor si, si |
mov ss, si |
mov sp, 7C00h-10 |
mov bp, 7C00h |
push dx |
push cx |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
; function 2: continue loading file |
; can be called only after function 1 returned value bx=1 (only part of file was loaded) |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
call continue_load_file |
jmp callback_ret_succ |
callback_readfile: |
; function 1: read file |
; in: ds:di -> information structure |
; dw:dw address |
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) |
; ASCIIZ name |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error |
; out: dx:ax = file size (0xFFFFFFFF if file was not found) |
call load_file |
callback_ret_succ: |
clc ; function is supported |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kord/loader',0 |
aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 |
;if $ > 0x8200 |
;error 'total size of kordldr.f32 must not exceed 1024 bytes!' |
;end if |
;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache |
;foldcache_mark dw 0 |
; rw 7 |
;foldcache_size rw 8 |
foldcache_clus rd 8 |
foldcache_mark rw 8 |
foldcache_size rw 8 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot/mkfloppy.inc |
---|
1,90 → 1,91 |
; --------------------------------------------------------------------------- |
; mkfloppy.inc |
; --------------------------------------------------------------------------- |
; Created by Phantom-84 |
; --------------------------------------------------------------------------- |
FA_RO equ 01h |
FA_HID equ 02h |
FA_SYS equ 04h |
FA_VOL equ 08h |
FA_DIR equ 10h |
FA_ARC equ 20h |
DSTAMP equ 28C1h |
TSTAMP equ 6000h |
root_size=0 |
macro reset id |
{ |
local count, cur, disp, val, var |
times 511-($+511) mod 512 db 0 |
if id#_size>0 |
count=(id#_size+511)/512 |
cur=id#_base/512-(33-2) |
repeat count |
if %=count |
val=0FFFh |
else |
val=cur+1 |
end if |
if cur and 1 |
val=val shl 4 |
end if |
disp=(cur*3)/2 |
load var word from 512+disp |
var=var or val |
store word var at 512+disp |
store word var at 10*512+disp |
cur=cur+1 |
end repeat |
end if |
} |
macro dent id, name, attr |
{ |
@@ db name |
times @b+11-$ db 32 |
db attr |
dw 0, TSTAMP, DSTAMP, DSTAMP, 0, TSTAMP, DSTAMP |
if id#_size=0 |
dw 0 |
else |
dw id#_base/512-(33-2) |
end if |
if (attr) and FA_DIR |
dd 0 |
else |
dd id#_size |
end if |
} |
macro orgdir id, parentid |
{ |
id#_base: |
dent id, ".", FA_DIR |
dent parentid, "..", FA_DIR |
} |
macro findir id |
{ |
id#_size=$-id#_base |
reset id |
} |
macro stod id, parentid |
{ |
orgdir id, parentid |
id |
findir id |
} |
macro stof id, name |
{ |
id#_base: file name |
id#_size=$-id#_base |
reset id |
} |
defdir fix macro |
; --------------------------------------------------------------------------- |
; mkfloppy.inc |
; --------------------------------------------------------------------------- |
; Created by Phantom-84 |
; --------------------------------------------------------------------------- |
FA_RO equ 01h |
FA_HID equ 02h |
FA_SYS equ 04h |
FA_VOL equ 08h |
FA_DIR equ 10h |
FA_ARC equ 20h |
DSTAMP equ 28C1h |
TSTAMP equ 6000h |
root_size=0 |
macro reset id |
{ |
local count, cur, disp, val, var |
times 511-($+511) mod 512 db 0 |
if id#_size>0 |
count=(id#_size+511)/512 |
cur=id#_base/512-(33-2) |
repeat count |
if %=count |
val=0FFFh |
else |
val=cur+1 |
end if |
if cur and 1 |
val=val shl 4 |
end if |
disp=(cur*3)/2 |
load var word from 512+disp |
var=var or val |
store word var at 512+disp |
store word var at 10*512+disp |
cur=cur+1 |
end repeat |
end if |
} |
macro dent id, name, attr |
{ |
@@ db name |
times @b+11-$ db 32 |
db attr |
dw 0, TSTAMP, DSTAMP, DSTAMP, 0, TSTAMP, DSTAMP |
if id#_size=0 |
dw 0 |
else |
dw id#_base/512-(33-2) |
end if |
if (attr) and FA_DIR |
dd 0 |
else |
dd id#_size |
end if |
} |
macro orgdir id, parentid |
{ |
id#_base: |
dent id, ".", FA_DIR |
dent parentid, "..", FA_DIR |
} |
macro findir id |
{ |
id#_size=$-id#_base |
reset id |
} |
macro stod id, parentid |
{ |
orgdir id, parentid |
id |
findir id |
} |
macro stof id, name |
{ |
id#_base: |
file name |
id#_size=$-id#_base |
reset id |
} |
defdir fix macro |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/boot_st.inc |
---|
1,68 → 1,68 |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
version db 'Secondary Loader v 0.010',0 |
version_end: |
select_section db 'Select section:' |
select_section_end: |
section_description db 'Section description:' |
section_description_end: |
soft_mes db 'Soft (c) 2008-2009' |
soft_mes_end: |
badprocessor db '>Fatal - CPU 586+ required.',0 |
error_ini_f1 db '>Error: cannot load ini file, buffer is full',0 |
error_ini_f2 db '>Error: ini file not found',0 |
error_ini_f3 db '>Error: cannot read ini file',0 |
error_ini_nf db '>Error: unrecognized error when loading ini file',0 |
not_found_sec_loader db '>Not found section [loader]',0 |
not_found_def_sect db '>Not found value default in section [loader]',0 |
default_eq_loader db '>Error in section [loader] parametr default=loader',0 |
found_equal_default db '>Found equal parametr default will be use first value',0 |
found_equal_timeout db '>Found equal parametr timeout will be use first value',0 |
set_default_timeout_val db '>Section timeout has incorrect value, will be use default value',0 |
error_ini_common db ">I will use predefined settings and try to boot. Let's hope for the best..." |
db 13,10,"Press any key to continue...",0 |
load_ini db '>Ini file loaded successfully',0 |
parse_ini_end db '>End parsing ini file',0 |
point_to_default_sec_not_found db '>Point to default section is not found in ini file',0 |
incorect_section_define db ">Incorect section define not found ']'",0 |
default_section_name db '"Section unname"' |
start_msg db "Press any key to change default section, press [Enter] to continue booting" |
start_msg_e: |
time_msg db "or wait 4 seconds before default continuation" |
time_msg_e: |
time_str db "seconds before default continuation" |
time_str_e: |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
version db 'Secondary Loader v 0.010',0 |
version_end: |
select_section db 'Select section:' |
select_section_end: |
section_description db 'Section description:' |
section_description_end: |
soft_mes db 'Soft (c) 2008-2009' |
soft_mes_end: |
badprocessor db '>Fatal - CPU 586+ required.',0 |
error_ini_f1 db '>Error: cannot load ini file, buffer is full',0 |
error_ini_f2 db '>Error: ini file not found',0 |
error_ini_f3 db '>Error: cannot read ini file',0 |
error_ini_nf db '>Error: unrecognized error when loading ini file',0 |
not_found_sec_loader db '>Not found section [loader]',0 |
not_found_def_sect db '>Not found value default in section [loader]',0 |
default_eq_loader db '>Error in section [loader] parametr default=loader',0 |
found_equal_default db '>Found equal parametr default will be use first value',0 |
found_equal_timeout db '>Found equal parametr timeout will be use first value',0 |
set_default_timeout_val db '>Section timeout has incorrect value, will be use default value',0 |
error_ini_common db ">I will use predefined settings and try to boot. Let's hope for the best..." |
db 13,10,"Press any key to continue...",0 |
load_ini db '>Ini file loaded successfully',0 |
parse_ini_end db '>End parsing ini file',0 |
point_to_default_sec_not_found db '>Point to default section is not found in ini file',0 |
incorect_section_define db ">Incorect section define not found ']'",0 |
default_section_name db '"Section unname"' |
start_msg db "Press any key to change default section, press [Enter] to continue booting" |
start_msg_e: |
time_msg db "or wait 4 seconds before default continuation" |
time_msg_e: |
time_str db "seconds before default continuation" |
time_str_e: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/debug_msg.inc |
---|
1,77 → 1,77 |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;Òóò îïðåäåëåíû âñå ñîîáùåíèÿ, êîòîðûå íóæíû â ïðîöåññå îòëàäêè, è ñîâñåì íå íóæíû â ðàáî÷åé êîïèè ïðîãðàììû. |
If DEBUG |
cseg_msg db ' - Adress of code segment',0 |
stack_msg db 'Set stack & segments is have completed',0 |
show_string db 'Have loaded size:' |
show_decode db ' ',0 |
show_db1 db ' -Message debug1',0 |
show_db2 db ' -Message debug2',0 |
lm_l_found db '[loader] is found',0 |
lm_lf_timeout db 'timeout is found',0 |
lm_lf_default db 'name default is found and end parsing section',0 |
lm_lf_section db 'found section [',0 |
lm_lf_default_f db 'found default parametr',0 |
lm_l_end db 'section [loader] is end',0 |
show_all_sect db 'SHOW ALL Sections',0 |
no_show_only_w db 'Not show sections - only work on default sect',0 |
_not_found db '[ not found',0 |
_found_1 db '[] found',0 |
_found_2 db '[ found',0 |
say_hello db 'Hello $)',0 |
ramdiskFS_st db 'Start use_RamdiskFS macros',0 |
free_memory_msg db ' -Kb availability system free memory',0 |
RamdiskSize_msg db ' -Kb equal RamdiskSize',0 |
RamdiskSector_msg db ' -byts RamdiskSector',0 |
RamdiskCluster_msg db ' -RamdiskCluster',0 |
RamdiskFile_msg db ' -size RamdiskFile',0 |
fat_create_msg db ' -first create fat table, point to next block',0 |
BPB_msg db ' -in byte, why we get data from move BPB struct',0 |
firstDataSect_msg db ' -first data sector, offset to data in sectors',0 |
size_root_dir_msg db ' -size root dir in sectrors',0 |
DataClasters_msg db ' -size data in Clasters',0 |
first_entry_in_fat db ' -data segment in FIRST entry FAT',0 |
check_root_fat_ db ' : --------------',0 |
check_name_fat_msg_y db 'Name is present that is BAD',0 |
check_name_fat_msg_n db 'Name is not present that is GOOD',0 |
name_of_seg_get_64 db ' -name of seg where we get 64 Kb of data',0 |
convertion_file_name_msg_y db '->Destination name of file is GOOD',0 |
convertion_file_name_msg_n db '->Destination name of file is BAD',0 |
alarm_msg db '%%%%%%%% WARNING: MISS THE FILE %%%%%%%%%%%',0 |
start_making_FAT12_msg db '>>>>>> Begin make a RAMDISK and FS after 1 Mb <<<<<<<',0 |
make_fat12_RFS_msg db '-Make FAT12 Ram FS',0 |
get_type_FS_msg db '-End make RamDisk',0 |
seg_where_get_data db ' - Segment where we get data for move up file',0 |
return_code_af_move db ' -return code after 0x87 int 0x15, move block',0 |
return_code_af_fat_m db ' -return code after 0x87 int 0x15, move fat struc',0 |
end if |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;Òóò îïðåäåëåíû âñå ñîîáùåíèÿ, êîòîðûå íóæíû â ïðîöåññå îòëàäêè, è ñîâñåì íå íóæíû â ðàáî÷åé êîïèè ïðîãðàììû. |
If DEBUG |
cseg_msg db ' - Adress of code segment',0 |
stack_msg db 'Set stack & segments is have completed',0 |
show_string db 'Have loaded size:' |
show_decode db ' ',0 |
show_db1 db ' -Message debug1',0 |
show_db2 db ' -Message debug2',0 |
lm_l_found db '[loader] is found',0 |
lm_lf_timeout db 'timeout is found',0 |
lm_lf_default db 'name default is found and end parsing section',0 |
lm_lf_section db 'found section [',0 |
lm_lf_default_f db 'found default parametr',0 |
lm_l_end db 'section [loader] is end',0 |
show_all_sect db 'SHOW ALL Sections',0 |
no_show_only_w db 'Not show sections - only work on default sect',0 |
_not_found db '[ not found',0 |
_found_1 db '[] found',0 |
_found_2 db '[ found',0 |
say_hello db 'Hello $)',0 |
ramdiskFS_st db 'Start use_RamdiskFS macros',0 |
free_memory_msg db ' -Kb availability system free memory',0 |
RamdiskSize_msg db ' -Kb equal RamdiskSize',0 |
RamdiskSector_msg db ' -byts RamdiskSector',0 |
RamdiskCluster_msg db ' -RamdiskCluster',0 |
RamdiskFile_msg db ' -size RamdiskFile',0 |
fat_create_msg db ' -first create fat table, point to next block',0 |
BPB_msg db ' -in byte, why we get data from move BPB struct',0 |
firstDataSect_msg db ' -first data sector, offset to data in sectors',0 |
size_root_dir_msg db ' -size root dir in sectrors',0 |
DataClasters_msg db ' -size data in Clasters',0 |
first_entry_in_fat db ' -data segment in FIRST entry FAT',0 |
check_root_fat_ db ' : --------------',0 |
check_name_fat_msg_y db 'Name is present that is BAD',0 |
check_name_fat_msg_n db 'Name is not present that is GOOD',0 |
name_of_seg_get_64 db ' -name of seg where we get 64 Kb of data',0 |
convertion_file_name_msg_y db '->Destination name of file is GOOD',0 |
convertion_file_name_msg_n db '->Destination name of file is BAD',0 |
alarm_msg db '%%%%%%%% WARNING: MISS THE FILE %%%%%%%%%%%',0 |
start_making_FAT12_msg db '>>>>>> Begin make a RAMDISK and FS after 1 Mb <<<<<<<',0 |
make_fat12_RFS_msg db '-Make FAT12 Ram FS',0 |
get_type_FS_msg db '-End make RamDisk',0 |
seg_where_get_data db ' - Segment where we get data for move up file',0 |
return_code_af_move db ' -return code after 0x87 int 0x15, move block',0 |
return_code_af_fat_m db ' -return code after 0x87 int 0x15, move fat struc',0 |
end if |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/booteng.inc |
---|
1,98 → 1,98 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; booteng.asm the module for Secondary Loader ;; |
;; ;; |
;; KolibriOS 16-bit loader module, ;; |
;; based on bootcode for KolibriOS ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
d80x25_bottom: |
db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY ' |
db 'NO WARRANTY ',186 |
db 186,' See file COPYING for details ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
vervesa db "Version of Vesa: Vesa x.x",13,10,0 |
novesa db "Display: EGA/CGA",13,10,0 |
s_vesa db "Version of VESA: " |
.ver db "?.?",13,10,0 |
gr_mode db "Select a videomode: ",13,10,0 |
vrrmprint db "Apply VRR? (picture frequency greater than 60Hz" |
db " only for transfers:",13,10 |
db 186," 1024*768->800*600 and 800*600->640*480) [1-yes,2-no]:",0 |
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 |
bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-use preloaded ram-image from kernel restart;" |
db 13,10,186," " |
db "4-create blank image]: ",0 |
probetext db 13,10,13,10,186," Use standart graphics mode? [1-yes, " |
db "2-probe bios (Vesa 3.0)]: ",0 |
prnotfnd db "Fatal - Videomode not found.",0 |
not386 db "Fatal - CPU 386+ required.",0 |
btns db "Fatal - Can't determine color depth.",0 |
fatalsel db "Fatal - Graphics mode not supported by hardware.",0 |
pres_key db "Press any key to choose a new videomode.",0 |
badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0 |
memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Loading diskette: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Press [abc] 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 |
current_cfg_msg db "Current settings:",13,10,0 |
curvideo_msg db " [a] Videomode: ",0 |
mode0 db "320x200, EGA/CGA 256 colors",13,10,0 |
mode9 db "640x480, VGA 16 colors",13,10,0 |
usebd_msg db " [b] Add disks visible by BIOS:",0 |
on_msg db " on",13,10,0 |
off_msg db " off",13,10,0 |
;readonly_msg db " only for reading",13,10,0 |
vrrm_msg db " [c] Use VRR:",0 |
preboot_device_msg db " [d] Floppy image: ",0 |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "real floppy",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "use already loaded image",13,10,0 |
pdm4 db "create blank image",13,10,0 |
loading_msg db "Loading KolibriOS...",0 |
save_quest db "Remember current settings? [y/n]: ",0 |
loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0 |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0 |
remark1 db "Default values were selected to match most of configurations, but not all.",0 |
remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 |
remark3 db "If the system does not boot, try to disable the item [b].",0 |
remarks dw remark1, remark2, remark3 |
num_remarks = 3 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; booteng.asm the module for Secondary Loader ;; |
;; ;; |
;; KolibriOS 16-bit loader module, ;; |
;; based on bootcode for KolibriOS ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
d80x25_bottom: |
db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY ' |
db 'NO WARRANTY ',186 |
db 186,' See file COPYING for details ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
msg_apm db " APM x.x ", 0 |
vervesa db "Version of Vesa: Vesa x.x",13,10,0 |
novesa db "Display: EGA/CGA",13,10,0 |
s_vesa db "Version of VESA: " |
.ver db "?.?",13,10,0 |
gr_mode db "Select a videomode: ",13,10,0 |
vrrmprint db "Apply VRR? (picture frequency greater than 60Hz" |
db " only for transfers:",13,10 |
db 186," 1024*768->800*600 and 800*600->640*480) [1-yes,2-no]:",0 |
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 |
bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-use preloaded ram-image from kernel restart;" |
db 13,10,186," " |
db "4-create blank image]: ",0 |
probetext db 13,10,13,10,186," Use standart graphics mode? [1-yes, " |
db "2-probe bios (Vesa 3.0)]: ",0 |
prnotfnd db "Fatal - Videomode not found.",0 |
not386 db "Fatal - CPU 386+ required.",0 |
btns db "Fatal - Can't determine color depth.",0 |
fatalsel db "Fatal - Graphics mode not supported by hardware.",0 |
pres_key db "Press any key to choose a new videomode.",0 |
badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0 |
memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Loading diskette: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Press [abc] 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 |
current_cfg_msg db "Current settings:",13,10,0 |
curvideo_msg db " [a] Videomode: ",0 |
mode0 db "320x200, EGA/CGA 256 colors",13,10,0 |
mode9 db "640x480, VGA 16 colors",13,10,0 |
usebd_msg db " [b] Add disks visible by BIOS:",0 |
on_msg db " on",13,10,0 |
off_msg db " off",13,10,0 |
;readonly_msg db " only for reading",13,10,0 |
vrrm_msg db " [c] Use VRR:",0 |
preboot_device_msg db " [d] Floppy image: ",0 |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "real floppy",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "use already loaded image",13,10,0 |
pdm4 db "create blank image",13,10,0 |
loading_msg db "Loading KolibriOS...",0 |
save_quest db "Remember current settings? [y/n]: ",0 |
loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0 |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0 |
remark1 db "Default values were selected to match most of configurations, but not all.",0 |
remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 |
remark3 db "If the system does not boot, try to disable the item [b].",0 |
remarks dw remark1, remark2, remark3 |
num_remarks = 3 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootet.inc |
---|
1,119 → 1,119 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; kolibri_ldm.asm the module for Secondary Loader ;; |
;; ;; |
;; KolibriOS 16-bit loader module, ;; |
;; based on bootcode for KolibriOS ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
d80x25_bottom: |
db 186,' KolibriOS based on MenuetOS and comes with ABSOLUTELY ' |
db 'NO WARRANTY ',186 |
db 186,' See file COPYING for details ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
novesa db "Ekraan: EGA/CGA",13,10,0 |
vervesa db "Vesa versioon: Vesa x.x",13,10,0 |
vervesa_off=20 |
msg_apm db " APM x.x ", 0 |
gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " |
db "[3] 1024x768, [4] 1280x1024",13,10 |
db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " |
db "[7] 1024x768, [8] 1280x1024",13,10 |
db 186," EGA/CGA 256 värvi: [9] 320x200, " |
db "VGA 16 värvi: [0] 640x480",13,10 |
db 186," Vali reziim: ",0 |
bt24 db "Bitti pikseli kohta: 24",13,10,0 |
bt32 db "Bitti pikseli kohta: 32",13,10,0 |
vrrmprint db "Kinnita VRR? (ekraani sagedus suurem kui 60Hz" |
db " ainult:",13,10 |
db 186," 1024*768->800*600 ja 800*600->640*480) [1-jah,2-ei]:",0 |
;askmouse db " Hiir:" |
; db " [1] PS/2 (USB), [2] Com1, [3] Com2." |
; db " Vali port [1-3]: ",0 |
;no_com1 db 13,10,186, " No COM1 mouse",0 |
;no_com2 db 13,10,186, " No COM2 mouse",0 |
;ask_dma db "Use DMA for HDD access? [1-yes, 2-only for reading, 3-no]: ",0 |
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 |
;gr_direct db 186," Use direct LFB writing? " |
; db "[1-yes/2-no] ? ",0 |
;mem_model db 13,10,186," Motherboard memory [1-16 Mb / 2-32 Mb / " |
; db "3-64Mb / 4-128 Mb / 5-256 Mb] ? ",0 |
;bootlog db 13,10,186," After bootlog display [1-continue/2-pause] ? ",0 |
bdev db "Paigalda mäluketas [1-diskett; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-kasuta eellaaditud mäluketast kerneli restardist;" |
db 13,10,186," " |
db "4-loo tühi pilt]: ",0 |
probetext db 13,10,13,10,186," Kasuta standartset graafika reziimi? [1-jah, " |
db "2-leia biosist (Vesa 3.0)]: ",0 |
;memokz256 db 13,10,186," RAM 256 Mb",0 |
;memokz128 db 13,10,186," RAM 128 Mb",0 |
;memokz64 db 13,10,186," RAM 64 Mb",0 |
;memokz32 db 13,10,186," RAM 32 Mb",0 |
;memokz16 db 13,10,186," RAM 16 Mb",0 |
prnotfnd db "Fataalne - Videoreziimi ei leitud.",0 |
;modena db "Fataalne - VBE 0x112+ on vajalik.",0 |
not386 db "Fataalne - CPU 386+ on vajalik.",0 |
btns db "Fataalne - Ei suuda värvisügavust määratleda.",0 |
fatalsel db "Fataalne - Graafilist reziimi riistvara ei toeta.",0 |
badsect db 13,10,186," Fataalne - Vigane sektor. Asenda diskett.",0 |
memmovefailed db 13,10,186," Fataalne - Int 0x15 liigutamine ebaõnnestus.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Loen disketti: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Vajuta [abcd] seadete muutmiseks, vajuta [Enter] laadimise jätkamiseks",13,10,0 |
time_msg db " või oota " |
time_str db " 5 sekundit" |
db " automaatseks jätkamiseks",13,10,0 |
current_cfg_msg db "Praegused seaded:",13,10,0 |
curvideo_msg db " [a] Videoreziim: ",0 |
mode1 db "640x480",0 |
mode2 db "800x600",0 |
mode3 db "1024x768",0 |
mode4 db "1280x1024",0 |
modes_msg dw mode4,mode1,mode2,mode3 |
modevesa20 db " koos LFB",0 |
modevesa12 db ", VESA 1.2 Bnk",0 |
mode9 db "320x200, EGA/CGA 256 värvi",0 |
mode10 db "640x480, VGA 16 värvi",0 |
probeno_msg db " (standard reziim)",0 |
probeok_msg db " (kontrolli ebastandardseid reziime)",0 |
;dma_msg db " [b] Kasuta DMA'd HDD juurdepääsuks:",0 |
usebd_msg db " [b] Add disks visible by BIOS:",0 |
on_msg db " sees",13,10,0 |
off_msg db " väljas",13,10,0 |
;readonly_msg db " ainult lugemiseks",13,10,0 |
vrrm_msg db " [c] Kasuta VRR:",0 |
preboot_device_msg db " [d] Disketi kujutis: ",0 |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "reaalne diskett",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "kasuta juba laaditud kujutist",13,10,0 |
pdm4 db "loo tühi pilt",13,10,0 |
loading_msg db "Laadin KolibriOS...",0 |
save_quest db "Jäta meelde praegused seaded? [y/n]: ",0 |
loader_block_error db "Alglaaduri andmed vigased, ei saa jätkata. Peatatud.",0 |
remark1 db "Default values were selected to match most of configurations, but not all.",0 |
remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 |
remark3 db "If the system does not boot, try to disable the item [b].",0 |
remarks dw remark1, remark2, remark3 |
num_remarks = 3 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; kolibri_ldm.asm the module for Secondary Loader ;; |
;; ;; |
;; KolibriOS 16-bit loader module, ;; |
;; based on bootcode for KolibriOS ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
d80x25_bottom: |
db 186,' KolibriOS based on MenuetOS and comes with ABSOLUTELY ' |
db 'NO WARRANTY ',186 |
db 186,' See file COPYING for details ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
novesa db "Ekraan: EGA/CGA",13,10,0 |
vervesa db "Vesa versioon: Vesa x.x",13,10,0 |
vervesa_off=20 |
msg_apm db " APM x.x ", 0 |
gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " |
db "[3] 1024x768, [4] 1280x1024",13,10 |
db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " |
db "[7] 1024x768, [8] 1280x1024",13,10 |
db 186," EGA/CGA 256 värvi: [9] 320x200, " |
db "VGA 16 värvi: [0] 640x480",13,10 |
db 186," Vali reziim: ",0 |
bt24 db "Bitti pikseli kohta: 24",13,10,0 |
bt32 db "Bitti pikseli kohta: 32",13,10,0 |
vrrmprint db "Kinnita VRR? (ekraani sagedus suurem kui 60Hz" |
db " ainult:",13,10 |
db 186," 1024*768->800*600 ja 800*600->640*480) [1-jah,2-ei]:",0 |
;askmouse db " Hiir:" |
; db " [1] PS/2 (USB), [2] Com1, [3] Com2." |
; db " Vali port [1-3]: ",0 |
;no_com1 db 13,10,186, " No COM1 mouse",0 |
;no_com2 db 13,10,186, " No COM2 mouse",0 |
;ask_dma db "Use DMA for HDD access? [1-yes, 2-only for reading, 3-no]: ",0 |
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 |
;gr_direct db 186," Use direct LFB writing? " |
; db "[1-yes/2-no] ? ",0 |
;mem_model db 13,10,186," Motherboard memory [1-16 Mb / 2-32 Mb / " |
; db "3-64Mb / 4-128 Mb / 5-256 Mb] ? ",0 |
;bootlog db 13,10,186," After bootlog display [1-continue/2-pause] ? ",0 |
bdev db "Paigalda mäluketas [1-diskett; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-kasuta eellaaditud mäluketast kerneli restardist;" |
db 13,10,186," " |
db "4-loo tühi pilt]: ",0 |
probetext db 13,10,13,10,186," Kasuta standartset graafika reziimi? [1-jah, " |
db "2-leia biosist (Vesa 3.0)]: ",0 |
;memokz256 db 13,10,186," RAM 256 Mb",0 |
;memokz128 db 13,10,186," RAM 128 Mb",0 |
;memokz64 db 13,10,186," RAM 64 Mb",0 |
;memokz32 db 13,10,186," RAM 32 Mb",0 |
;memokz16 db 13,10,186," RAM 16 Mb",0 |
prnotfnd db "Fataalne - Videoreziimi ei leitud.",0 |
;modena db "Fataalne - VBE 0x112+ on vajalik.",0 |
not386 db "Fataalne - CPU 386+ on vajalik.",0 |
btns db "Fataalne - Ei suuda värvisügavust määratleda.",0 |
fatalsel db "Fataalne - Graafilist reziimi riistvara ei toeta.",0 |
badsect db 13,10,186," Fataalne - Vigane sektor. Asenda diskett.",0 |
memmovefailed db 13,10,186," Fataalne - Int 0x15 liigutamine ebaõnnestus.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Loen disketti: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Vajuta [abcd] seadete muutmiseks, vajuta [Enter] laadimise jätkamiseks",13,10,0 |
time_msg db " või oota " |
time_str db " 5 sekundit" |
db " automaatseks jätkamiseks",13,10,0 |
current_cfg_msg db "Praegused seaded:",13,10,0 |
curvideo_msg db " [a] Videoreziim: ",0 |
mode1 db "640x480",0 |
mode2 db "800x600",0 |
mode3 db "1024x768",0 |
mode4 db "1280x1024",0 |
modes_msg dw mode4,mode1,mode2,mode3 |
modevesa20 db " koos LFB",0 |
modevesa12 db ", VESA 1.2 Bnk",0 |
mode9 db "320x200, EGA/CGA 256 värvi",0 |
mode10 db "640x480, VGA 16 värvi",0 |
probeno_msg db " (standard reziim)",0 |
probeok_msg db " (kontrolli ebastandardseid reziime)",0 |
;dma_msg db " [b] Kasuta DMA'd HDD juurdepääsuks:",0 |
usebd_msg db " [b] Add disks visible by BIOS:",0 |
on_msg db " sees",13,10,0 |
off_msg db " väljas",13,10,0 |
;readonly_msg db " ainult lugemiseks",13,10,0 |
vrrm_msg db " [c] Kasuta VRR:",0 |
preboot_device_msg db " [d] Disketi kujutis: ",0 |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "reaalne diskett",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "kasuta juba laaditud kujutist",13,10,0 |
pdm4 db "loo tühi pilt",13,10,0 |
loading_msg db "Laadin KolibriOS...",0 |
save_quest db "Jäta meelde praegused seaded? [y/n]: ",0 |
loader_block_error db "Alglaaduri andmed vigased, ei saa jätkata. Peatatud.",0 |
remark1 db "Default values were selected to match most of configurations, but not all.",0 |
remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 |
remark3 db "If the system does not boot, try to disable the item [b].",0 |
remarks dw remark1, remark2, remark3 |
num_remarks = 3 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootge.inc |
---|
1,118 → 1,118 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
d80x25_bottom: |
; db 186,' KolibriOS based on MenuetOS and comes with ABSOLUTELY ' |
; db 'NO WARRANTY ',186 |
; db 186,' See file COPYING for details ' |
; db ' ',186 |
db 186,' KolibriOS basiert auf MenuetOS und wird ohne jegliche ' |
db ' Garantie vertrieben ',186 |
db 186,' Details stehen in der Datei COPYING ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
novesa db "Anzeige: EGA/CGA ",13,10,0 |
vervesa db "Vesa-Version: Vesa ",13,10,0 |
vervesa_off=22 |
msg_apm db " APM x.x ", 0 |
gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " |
db "[3] 1024x768, [4] 1280x1024",13,10 |
db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " |
db "[7] 1024x768, [8] 1280x1024",13,10 |
db 186," EGA/CGA 256 Farben: [9] 320x200, " |
db "VGA 16 Farben: [0] 640x480",13,10 |
db 186," Waehle Modus: ",0 |
bt24 db "Bits Per Pixel: 24",13,10,0 |
bt32 db "Bits Per Pixel: 32",13,10,0 |
vrrmprint db "VRR verwenden? (Monitorfrequenz groesser als 60Hz" |
db " only for transfers:",13,10 |
db 186," 1024*768->800*600 und 800*600->640*480) [1-ja,2-nein]:",0 |
;askmouse db " Maus angeschlossen an:" |
; db " [1] PS/2 (USB), [2] Com1, [3] Com2." |
; db " Waehle Port [1-3]: ",0 |
;no_com1 db 13,10,186, " Keine COM1 Maus",0 |
;no_com2 db 13,10,186, " Keine COM2 Maus",0 |
;ask_dma db "Nutze DMA zum HDD Zugriff? [1-ja, 2-allein fur Lesen, 3-nein]: ",0 |
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 |
;gr_direct db 186," Benutze direct LFB? " |
; db "[1-ja/2-nein] ? ",0 |
;mem_model db 13,10,186," Hauptspeicher [1-16 Mb / 2-32 Mb / " |
; db "3-64Mb / 4-128 Mb / 5-256 Mb] ? ",0 |
;bootlog db 13,10,186," After bootlog display [1-continue/2-pause] ? ",0 |
bdev db "Lade die Ramdisk von [1-Diskette; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-benutze ein bereits geladenes Kernel image;" |
db 13,10,186," " |
db "4-create blank image]: ",0 |
probetext db 13,10,13,10,186," Nutze Standardgrafikmodi? [1-ja, " |
db "2-BIOS Test (Vesa 3.0)]: ",0 |
;memokz256 db 13,10,186," RAM 256 Mb",0 |
;memokz128 db 13,10,186," RAM 128 Mb",0 |
;memokz64 db 13,10,186," RAM 64 Mb",0 |
;memokz32 db 13,10,186," RAM 32 Mb",0 |
;memokz16 db 13,10,186," RAM 16 Mb",0 |
prnotfnd db "Fatal - Videomodus nicht gefunden.",0 |
;modena db "Fatal - VBE 0x112+ required.",0 |
not386 db "Fatal - CPU 386+ benoetigt.",0 |
btns db "Fatal - konnte Farbtiefe nicht erkennen.",0 |
fatalsel db "Fatal - Grafikmodus nicht unterstuetzt.",0 |
badsect db 13,10,186," Fatal - Sektorfehler, Andere Diskette neutzen.",0 |
memmovefailed db 13,10,186," Fatal - Int 0x15 Fehler.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Lade Diskette: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Druecke [abcd], um die Einstellungen zu aendern , druecke [Enter] zum starten",13,10,0 |
time_msg db " oder warte " |
time_str db " 5 Sekunden" |
db " bis zum automatischen Start",13,10,0 |
current_cfg_msg db "Aktuelle Einstellungen:",13,10,0 |
curvideo_msg db " [a] Videomodus: ",0 |
mode1 db "640x480",0 |
mode2 db "800x600",0 |
mode3 db "1024x768",0 |
mode4 db "1280x1024",0 |
modes_msg dw mode4,mode1,mode2,mode3 |
modevesa20 db " mit LFB",0 |
modevesa12 db ", VESA 1.2 Bnk",0 |
mode9 db "320x200, EGA/CGA 256 colors",0 |
mode10 db "640x480, VGA 16 colors",0 |
probeno_msg db " (Standard Modus)",0 |
probeok_msg db " (teste nicht-standard Modi)",0 |
;dma_msg db " [b] Nutze DMA zum HDD Aufschreiben:",0 |
usebd_msg db " [b] Add disks visible by BIOS:",0 |
on_msg db " an",13,10,0 |
off_msg db " aus",13,10,0 |
;readonly_msg db " fur Lesen",13,10,0 |
vrrm_msg db " [c] Nutze VRR:",0 |
preboot_device_msg db " [d] Diskettenimage: ",0 |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "Echte Diskette",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "Nutze bereits geladenes Image",13,10,0 |
pdm4 db "create blank image",13,10,0 |
loading_msg db "Lade KolibriOS...",0 |
save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0 |
loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0 |
remark1 db "Default values were selected to match most of configurations, but not all.",0 |
remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 |
remark3 db "If the system does not boot, try to disable the item [b].",0 |
remarks dw remark1, remark2, remark3 |
num_remarks = 3 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
d80x25_bottom: |
; db 186,' KolibriOS based on MenuetOS and comes with ABSOLUTELY ' |
; db 'NO WARRANTY ',186 |
; db 186,' See file COPYING for details ' |
; db ' ',186 |
db 186,' KolibriOS basiert auf MenuetOS und wird ohne jegliche ' |
db ' Garantie vertrieben ',186 |
db 186,' Details stehen in der Datei COPYING ' |
db ' ',186 |
line_full_bottom |
d80x25_bottom_num = 3 |
novesa db "Anzeige: EGA/CGA ",13,10,0 |
vervesa db "Vesa-Version: Vesa ",13,10,0 |
vervesa_off=22 |
msg_apm db " APM x.x ", 0 |
gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " |
db "[3] 1024x768, [4] 1280x1024",13,10 |
db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " |
db "[7] 1024x768, [8] 1280x1024",13,10 |
db 186," EGA/CGA 256 Farben: [9] 320x200, " |
db "VGA 16 Farben: [0] 640x480",13,10 |
db 186," Waehle Modus: ",0 |
bt24 db "Bits Per Pixel: 24",13,10,0 |
bt32 db "Bits Per Pixel: 32",13,10,0 |
vrrmprint db "VRR verwenden? (Monitorfrequenz groesser als 60Hz" |
db " only for transfers:",13,10 |
db 186," 1024*768->800*600 und 800*600->640*480) [1-ja,2-nein]:",0 |
;askmouse db " Maus angeschlossen an:" |
; db " [1] PS/2 (USB), [2] Com1, [3] Com2." |
; db " Waehle Port [1-3]: ",0 |
;no_com1 db 13,10,186, " Keine COM1 Maus",0 |
;no_com2 db 13,10,186, " Keine COM2 Maus",0 |
;ask_dma db "Nutze DMA zum HDD Zugriff? [1-ja, 2-allein fur Lesen, 3-nein]: ",0 |
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 |
;gr_direct db 186," Benutze direct LFB? " |
; db "[1-ja/2-nein] ? ",0 |
;mem_model db 13,10,186," Hauptspeicher [1-16 Mb / 2-32 Mb / " |
; db "3-64Mb / 4-128 Mb / 5-256 Mb] ? ",0 |
;bootlog db 13,10,186," After bootlog display [1-continue/2-pause] ? ",0 |
bdev db "Lade die Ramdisk von [1-Diskette; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-benutze ein bereits geladenes Kernel image;" |
db 13,10,186," " |
db "4-create blank image]: ",0 |
probetext db 13,10,13,10,186," Nutze Standardgrafikmodi? [1-ja, " |
db "2-BIOS Test (Vesa 3.0)]: ",0 |
;memokz256 db 13,10,186," RAM 256 Mb",0 |
;memokz128 db 13,10,186," RAM 128 Mb",0 |
;memokz64 db 13,10,186," RAM 64 Mb",0 |
;memokz32 db 13,10,186," RAM 32 Mb",0 |
;memokz16 db 13,10,186," RAM 16 Mb",0 |
prnotfnd db "Fatal - Videomodus nicht gefunden.",0 |
;modena db "Fatal - VBE 0x112+ required.",0 |
not386 db "Fatal - CPU 386+ benoetigt.",0 |
btns db "Fatal - konnte Farbtiefe nicht erkennen.",0 |
fatalsel db "Fatal - Grafikmodus nicht unterstuetzt.",0 |
badsect db 13,10,186," Fatal - Sektorfehler, Andere Diskette neutzen.",0 |
memmovefailed db 13,10,186," Fatal - Int 0x15 Fehler.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db "Lade Diskette: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 ; 0=floppy, 1=hd |
start_msg db "Druecke [abcd], um die Einstellungen zu aendern , druecke [Enter] zum starten",13,10,0 |
time_msg db " oder warte " |
time_str db " 5 Sekunden" |
db " bis zum automatischen Start",13,10,0 |
current_cfg_msg db "Aktuelle Einstellungen:",13,10,0 |
curvideo_msg db " [a] Videomodus: ",0 |
mode1 db "640x480",0 |
mode2 db "800x600",0 |
mode3 db "1024x768",0 |
mode4 db "1280x1024",0 |
modes_msg dw mode4,mode1,mode2,mode3 |
modevesa20 db " mit LFB",0 |
modevesa12 db ", VESA 1.2 Bnk",0 |
mode9 db "320x200, EGA/CGA 256 colors",0 |
mode10 db "640x480, VGA 16 colors",0 |
probeno_msg db " (Standard Modus)",0 |
probeok_msg db " (teste nicht-standard Modi)",0 |
;dma_msg db " [b] Nutze DMA zum HDD Aufschreiben:",0 |
usebd_msg db " [b] Add disks visible by BIOS:",0 |
on_msg db " an",13,10,0 |
off_msg db " aus",13,10,0 |
;readonly_msg db " fur Lesen",13,10,0 |
vrrm_msg db " [c] Nutze VRR:",0 |
preboot_device_msg db " [d] Diskettenimage: ",0 |
preboot_device_msgs dw 0,pdm1,pdm2,pdm3 |
pdm1 db "Echte Diskette",13,10,0 |
pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
pdm3 db "Nutze bereits geladenes Image",13,10,0 |
pdm4 db "create blank image",13,10,0 |
loading_msg db "Lade KolibriOS...",0 |
save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0 |
loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0 |
remark1 db "Default values were selected to match most of configurations, but not all.",0 |
remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 |
remark3 db "If the system does not boot, try to disable the item [b].",0 |
remarks dw remark1, remark2, remark3 |
num_remarks = 3 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootru.inc |
---|
1,87 → 1,87 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;================================================================= |
; |
; BOOT DATA |
; |
;================================================================= |
d80x25_bottom: |
db 186,' Kolibri OS ®á®¢ Menuet OS ¨ ¥ ¯à¥¤®áâ ¢«ï¥â ' |
db '¨ª ª¨å £ àa⨩. ',186 |
db 186,' ®¤à®¡¥¥ ᬮâà¨â¥ ¢ ä ©«¥ COPYING.TXT ' |
db ' ',186 |
line_full_bottom |
msg_apm db " APM x.x ", 0 |
novesa db "¨¤¥®ª àâ : EGA/CGA",13,10,0 |
s_vesa db "¥àá¨ï VESA: " |
.ver db "?.?",13,10,0 |
gr_mode db "ë¡¥à¨â¥ ¢¨¤¥®à¥¦¨¬: ",13,10,0 |
vrrmprint db "ᯮ«ì§®¢ âì VRR? (ç áâ®â ª ¤à®¢ ¢ëè¥ 60 æ" |
db " ⮫쪮 ¤«ï ¯¥à¥å®¤®¢:",13,10 |
db 186," 1024*768>800*600 ¨ 800*600>640*480) [1-¤ , 2-¥â]: ",0 |
;ask_dma db "ᯮ«ì§®¢ âì DMA ¤«ï ¤®áâ㯠ª HDD? [1-¤ , 2-⮫쪮 ç⥨¥, 3-¥â]: ",0 |
ask_bd db "®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS ¢ ०¨¬¥ V86? [1-¤ , 2-¥â]: ",0 |
bdev db " £à㧨âì ®¡à § ¨§ [1-¤¨áª¥â ; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-¨á¯®«ì§®¢ âì 㦥 § £àã¦¥ë© ®¡à §;" |
db 13,10,186," " |
db "4-ᮧ¤ âì ç¨áâë© ®¡à §]: ",0 |
prnotfnd db "訡ª - ¨¤¥®à¥¦¨¬ ¥ ©¤¥.",0 |
not386 db "訡ª - ॡã¥âáï ¯à®æ¥áá®à 386+.",0 |
fatalsel db "訡ª - ë¡à ë© ¢¨¤¥®à¥¦¨¬ ¥ ¯®¤¤¥à¦¨¢ ¥âáï.",0 |
pres_key db " ¦¨¬¨â¥ «î¡ãî ª« ¢¨èã, ¤«ï ¯¥à¥å®¤ ¢ ¢ë¡®à ०¨¬®¢.",0 |
badsect db 13,10,186," 訡ª - ¨áª¥â ¯®¢à¥¦¤¥ . ®¯à®¡ã©â¥ ¤àã£ãî.",0 |
memmovefailed db 13,10,186," 訡ª - Int 0x15 move failed.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db " £à㧪 ¤¨áª¥âë: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 |
start_msg db " ¦¬¨â¥ [abc] ¤«ï ¨§¬¥¥¨ï áâ஥ª, [Enter] ¤«ï ¯à®¤®«¦¥¨ï § £à㧪¨",13,10,0 |
time_msg db " ¨«¨ ¯®¤®¦¤¨â¥ " |
time_str db " 5 ᥪ㭤 " |
db " ¤® ¢â®¬ â¨ç¥áª®£® ¯à®¤®«¦¥¨ï",13,10,0 |
current_cfg_msg db "¥ªã騥 áâனª¨:",13,10,0 |
curvideo_msg db " [a] ¨¤¥®à¥¦¨¬: ",0 |
mode0 db "320x200, EGA/CGA 256 梥⮢",13,10,0 |
mode9 db "640x480, VGA 16 梥⮢",13,10,0 |
usebd_msg db " [b] ®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS:",0 |
on_msg db " ¢ª«",13,10,0 |
off_msg db " ¢ëª«",13,10,0 |
readonly_msg db " ⮫쪮 ç⥨¥",13,10,0 |
vrrm_msg db " [c] ᯮ«ì§®¢ ¨¥ VRR:",0 |
;preboot_device_msg db " [d] ¡à § ¤¨áª¥âë: ",0 |
;preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4 |
;pdm1 db " áâ®ïé ï ¤¨áª¥â ",13,10,0 |
;pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
;pdm3 db "¨á¯®«ì§®¢ âì 㦥 § £àã¦¥ë© ®¡à §",13,10,0 |
;pdm4 db "ᮧ¤ âì ç¨áâë© ®¡à §",13,10,0 |
loading_msg db "¤ñâ § £à㧪 KolibriOS...",0 |
save_quest db " ¯®¬¨âì ⥪ã騥 áâனª¨? [y/n]: ",0 |
loader_block_error db "訡ª ¢ ¤ ëå ç «ì®£® § £àã§ç¨ª , ¯à®¤®«¦¥¨¥ ¥¢®§¬®¦®.",0 |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 梥⮢ ³ ³ ',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 梥⮢ ³ ³ ',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³ ',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ',13,10,0 |
remark1 db " ç¥¨ï ¯® 㬮«ç ¨î ¢ë¡à ë ¤«ï 㤮¡á⢠¡®«ìè¨á⢠, ® ¥ ¢á¥å.",0 |
remark2 db " ᫨ ã á LCD-¬®¨â®à, ®âª«îç¨â¥ VRR ¢ ¯ãªâ¥ [c] - ® ¬ ¥ 㦥.",0 |
remark3 db " ᫨ ã á ¥ £à㧨âáï á¨á⥬ , ¯®¯à®¡ã©â¥ ®âª«îç¨âì ¯ãªâ [b].",0 |
remarks dw remark1, remark2, remark3 |
num_remarks = 3 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;================================================================= |
; |
; BOOT DATA |
; |
;================================================================= |
d80x25_bottom: |
db 186,' Kolibri OS ®á®¢ Menuet OS ¨ ¥ ¯à¥¤®áâ ¢«ï¥â ' |
db '¨ª ª¨å £ àa⨩. ',186 |
db 186,' ®¤à®¡¥¥ ᬮâà¨â¥ ¢ ä ©«¥ COPYING.TXT ' |
db ' ',186 |
line_full_bottom |
msg_apm db " APM x.x ", 0 |
novesa db "¨¤¥®ª àâ : EGA/CGA",13,10,0 |
s_vesa db "¥àá¨ï VESA: " |
.ver db "?.?",13,10,0 |
gr_mode db "ë¡¥à¨â¥ ¢¨¤¥®à¥¦¨¬: ",13,10,0 |
vrrmprint db "ᯮ«ì§®¢ âì VRR? (ç áâ®â ª ¤à®¢ ¢ëè¥ 60 æ" |
db " ⮫쪮 ¤«ï ¯¥à¥å®¤®¢:",13,10 |
db 186," 1024*768>800*600 ¨ 800*600>640*480) [1-¤ , 2-¥â]: ",0 |
;ask_dma db "ᯮ«ì§®¢ âì DMA ¤«ï ¤®áâ㯠ª HDD? [1-¤ , 2-⮫쪮 ç⥨¥, 3-¥â]: ",0 |
ask_bd db "®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS ¢ ०¨¬¥ V86? [1-¤ , 2-¥â]: ",0 |
bdev db " £à㧨âì ®¡à § ¨§ [1-¤¨áª¥â ; 2-C:\kolibri.img (FAT32);" |
db 13,10,186," " |
db "3-¨á¯®«ì§®¢ âì 㦥 § £àã¦¥ë© ®¡à §;" |
db 13,10,186," " |
db "4-ᮧ¤ âì ç¨áâë© ®¡à §]: ",0 |
prnotfnd db "訡ª - ¨¤¥®à¥¦¨¬ ¥ ©¤¥.",0 |
not386 db "訡ª - ॡã¥âáï ¯à®æ¥áá®à 386+.",0 |
fatalsel db "訡ª - ë¡à ë© ¢¨¤¥®à¥¦¨¬ ¥ ¯®¤¤¥à¦¨¢ ¥âáï.",0 |
pres_key db " ¦¨¬¨â¥ «î¡ãî ª« ¢¨èã, ¤«ï ¯¥à¥å®¤ ¢ ¢ë¡®à ०¨¬®¢.",0 |
badsect db 13,10,186," 訡ª - ¨áª¥â ¯®¢à¥¦¤¥ . ®¯à®¡ã©â¥ ¤àã£ãî.",0 |
memmovefailed db 13,10,186," 訡ª - Int 0x15 move failed.",0 |
okt db " ... OK" |
linef db 13,10,0 |
diskload db " £à㧪 ¤¨áª¥âë: 00 %",8,8,8,8,0 |
pros db "00" |
backspace2 db 8,8,0 |
boot_dev db 0 |
start_msg db " ¦¬¨â¥ [abc] ¤«ï ¨§¬¥¥¨ï áâ஥ª, [Enter] ¤«ï ¯à®¤®«¦¥¨ï § £à㧪¨",13,10,0 |
time_msg db " ¨«¨ ¯®¤®¦¤¨â¥ " |
time_str db " 5 ᥪ㭤 " |
db " ¤® ¢â®¬ â¨ç¥áª®£® ¯à®¤®«¦¥¨ï",13,10,0 |
current_cfg_msg db "¥ªã騥 áâனª¨:",13,10,0 |
curvideo_msg db " [a] ¨¤¥®à¥¦¨¬: ",0 |
mode0 db "320x200, EGA/CGA 256 梥⮢",13,10,0 |
mode9 db "640x480, VGA 16 梥⮢",13,10,0 |
usebd_msg db " [b] ®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS:",0 |
on_msg db " ¢ª«",13,10,0 |
off_msg db " ¢ëª«",13,10,0 |
readonly_msg db " ⮫쪮 ç⥨¥",13,10,0 |
vrrm_msg db " [c] ᯮ«ì§®¢ ¨¥ VRR:",0 |
;preboot_device_msg db " [d] ¡à § ¤¨áª¥âë: ",0 |
;preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4 |
;pdm1 db " áâ®ïé ï ¤¨áª¥â ",13,10,0 |
;pdm2 db "C:\kolibri.img (FAT32)",13,10,0 |
;pdm3 db "¨á¯®«ì§®¢ âì 㦥 § £àã¦¥ë© ®¡à §",13,10,0 |
;pdm4 db "ᮧ¤ âì ç¨áâë© ®¡à §",13,10,0 |
loading_msg db "¤ñâ § £à㧪 KolibriOS...",0 |
save_quest db " ¯®¬¨âì ⥪ã騥 áâனª¨? [y/n]: ",0 |
loader_block_error db "訡ª ¢ ¤ ëå ç «ì®£® § £àã§ç¨ª , ¯à®¤®«¦¥¨¥ ¥¢®§¬®¦®.",0 |
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ',13,10,0 |
_r1 db 186,' ³ 320x200 EGA/CGA 256 梥⮢ ³ ³ ',13,10,0 |
_r2 db 186,' ³ 640x480 VGA 16 梥⮢ ³ ³ ',13,10,0 |
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³ ',13,10,0 |
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ',13,10,0 |
remark1 db " ç¥¨ï ¯® 㬮«ç ¨î ¢ë¡à ë ¤«ï 㤮¡á⢠¡®«ìè¨á⢠, ® ¥ ¢á¥å.",0 |
remark2 db " ᫨ ã á LCD-¬®¨â®à, ®âª«îç¨â¥ VRR ¢ ¯ãªâ¥ [c] - ® ¬ ¥ 㦥.",0 |
remark3 db " ᫨ ã á ¥ £à㧨âáï á¨á⥬ , ¯®¯à®¡ã©â¥ ®âª«îç¨âì ¯ãªâ [b].",0 |
remarks dw remark1, remark2, remark3 |
num_remarks = 3 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootstr.inc |
---|
1,55 → 1,56 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; boot data: common strings (for all languages) |
macro line_full_top { |
db 201 |
times 78 db 205 |
db 187 |
} |
macro line_full_bottom { |
db 200 |
times 78 db 205 |
db 188 |
} |
macro line_half { |
db 186,' ' |
times 76 db 0xc4 |
db ' ',186 |
} |
macro line_space { |
db 186 |
times 78 db 32 |
db 186 |
} |
d80x25_top: |
line_full_top |
cur_line_pos = 75 |
; store byte ' ' at d80x25_top+cur_line_pos+1 |
; store byte ' ' at d80x25_top+cur_line_pos |
; store dword ' SVN' at d80x25_top+cur_line_pos-4 |
space_msg: line_space |
;verstr: |
; line_space |
; version string |
; db 186,32 |
; repeat 78 |
; load a byte from version+%-1 |
; if a = 13 |
; break |
; end if |
; db a |
; end repeat |
; repeat 78 - ($-verstr) |
; db ' ' |
; end repeat |
; db 32,186 |
; line_half |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; boot data: common strings (for all languages) |
macro line_full_top { |
db 201 |
times 78 db 205 |
db 187 |
} |
macro line_full_bottom { |
db 200 |
times 78 db 205 |
db 188 |
} |
macro line_half { |
db 186,' ' |
times 76 db 0xc4 |
db ' ',186 |
} |
macro line_space { |
db 186 |
times 78 db 32 |
db 186 |
} |
d80x25_top: |
line_full_top |
cur_line_pos = 75 |
; store byte ' ' at d80x25_top+cur_line_pos+1 |
; store byte ' ' at d80x25_top+cur_line_pos |
; store dword ' SVN' at d80x25_top+cur_line_pos-4 |
space_msg: |
line_space |
;verstr: |
; line_space |
; version string |
; db 186,32 |
; repeat 78 |
; load a byte from version+%-1 |
; if a = 13 |
; break |
; end if |
; db a |
; end repeat |
; repeat 78 - ($-verstr) |
; db ' ' |
; end repeat |
; db 32,186 |
; line_half |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootvesa.inc |
---|
1,754 → 1,762 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
struc VBE_VGAInfo { |
.VESASignature dd ? ; char |
.VESAVersion dw ? ; short |
.OemStringPtr dd ? ; char * |
.Capabilities dd ? ; ulong |
.VideoModePtr dd ? ; ulong |
.TotalMemory dw ? ; short |
; VBE 2.0+ |
.OemSoftwareRev db ? ; short |
.OemVendorNamePtr dw ? ; char * |
.OemProductNamePtr dw ? ; char * |
.OemProductRevPtr dw ? ; char * |
.reserved rb 222 ; char |
.OemData rb 256 ; char |
} |
struc VBE_ModeInfo { |
.ModeAttributes dw ? ; short |
.WinAAttributes db ? ; char |
.WinBAttributes db ? ; char |
.WinGranularity dw ? ; short |
.WinSize dw ? ; short |
.WinASegment dw ? ; ushort |
.WinBSegment dw ? ; ushort |
.WinFuncPtr dd ? ; void * |
.BytesPerScanLine dw ? ; short |
.XRes dw ? ; short |
.YRes dw ? ; short |
.XCharSize db ? ; char |
.YCharSize db ? ; char |
.NumberOfPlanes db ? ; char |
.BitsPerPixel db ? ; char |
.NumberOfBanks db ? ; char |
.MemoryModel db ? ; char |
.BankSize db ? ; char |
.NumberOfImagePages db ? ; char |
.res1 db ? ; char |
.RedMaskSize db ? ; char |
.RedFieldPosition db ? ; char |
.GreenMaskSize db ? ; char |
.GreenFieldPosition db ? ; char |
.BlueMaskSize db ? ; char |
.BlueFieldPosition db ? ; char |
.RsvedMaskSize db ? ; char |
.RsvedFieldPosition db ? ; char |
.DirectColorModeInfo db ? ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE |
; VBE 2.0+ |
.PhysBasePtr dd ? ; ulong |
.OffScreenMemOffset dd ? ; ulong |
.OffScreenMemSize dw ? ; short |
; VBE 3.0+ |
.LinbytesPerScanLine dw ? ; short |
.BankNumberOfImagePages db ? ; char |
.LinNumberOfImagePages db ? ; char |
.LinRedMaskSize db ? ; char |
.LinRedFieldPosition db ? ; char |
.LingreenMaskSize db ? ; char |
.LinGreenFieldPosition db ? ; char |
.LinBlueMaskSize db ? ; char |
.LinBlueFieldPosition db ? ; char |
.LinRsvdMaskSize db ? ; char |
.LinRsvdFieldPosition db ? ; char |
.MaxPixelClock dd ? ; ulong |
.res2 rb 190 ; char |
} |
virtual at $A000 |
vi VBE_VGAInfo |
mi VBE_ModeInfo |
modes_table: |
end virtual |
cursor_pos dw 0 ;âðåìåííîå õðàíåíèå êóðñîðà. |
home_cursor dw 0 ;current shows rows a table |
end_cursor dw 0 ;end of position current shows rows a table |
scroll_start dw 0 ;start position of scroll bar |
scroll_end dw 0 ;end position of scroll bar |
long_v_table equ 9 ;long of visible video table |
size_of_step equ 10 |
scroll_area_size equ (long_v_table-2) |
int2str: |
dec bl |
jz @f |
xor edx,edx |
div ecx |
push edx |
call int2str |
pop eax |
@@: or al,0x30 |
mov [ds:di],al |
inc di |
ret |
int2strnz: |
cmp eax,ecx |
jb @f |
xor edx,edx |
div ecx |
push edx |
call int2strnz |
pop eax |
@@: or al,0x30 |
mov [es:di],al |
inc di |
ret |
;------------------------------------------------------- |
;Write message about incorrect v_mode and write message about jmp on swith v_mode |
v_mode_error: |
_setcursor 19,2 |
mov si, fatalsel |
call printplain |
_setcursor 20,2 |
mov si,pres_key |
call printplain |
xor eax,eax |
int 16h |
jmp cfgmanager.d |
;------------------------------------------------------- |
; |
;------------------------------------------------------- |
print_vesa_info: |
_setcursor 5,2 |
mov [es:vi.VESASignature],'VBE2' |
mov ax,0x4F00 |
mov di,vi ;0xa000 |
int 0x10 |
or ah,ah |
jz @f |
mov [es:vi.VESASignature],'VESA' |
mov ax,$4F00 |
mov di,vi |
int 0x10 |
or ah,ah |
jnz .exit |
@@: |
cmp [es:vi.VESASignature],'VESA' |
jne .exit |
cmp [es:vi.VESAVersion],0x0100 |
jb .exit |
jmp .vesaok2 |
.exit: |
mov si,novesa |
call printplain |
ret |
.vesaok2: |
mov ax,[es:vi.VESAVersion] |
add ax,'00' |
mov [s_vesa.ver], ah |
mov [s_vesa.ver+2], al |
mov si,s_vesa |
call printplain |
_setcursor 4,2 |
mov si,word[es:vi.OemStringPtr] |
mov di,si |
push ds |
mov ds,word[es:vi.OemStringPtr+2] |
call printplain |
pop ds |
ret |
;----------------------------------------------------------------------------- |
calc_vmodes_table: |
pushad |
; push 0 |
; pop es |
lfs si, [es:vi.VideoModePtr] |
mov bx,modes_table |
;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢ |
mov word [es:bx],640 |
mov word [es:bx+2],480 |
mov word [es:bx+6],0x13 |
mov word [es:bx+10],640 |
mov word [es:bx+12],480 |
mov word [es:bx+16],0x12 |
add bx,20 |
.next_mode: |
mov cx,word [fs:si] ; mode number |
cmp cx,-1 |
je .modes_ok.2 |
mov ax,0x4F01 |
mov di,mi |
int 0x10 |
or ah,ah |
jnz .modes_ok.2;vesa_info.exit |
test [es:mi.ModeAttributes],00000001b ;videomode support ? |
jz @f |
test [es:mi.ModeAttributes],00010000b ;picture ? |
jz @f |
test [es:mi.ModeAttributes],10000000b ;LFB ? |
jz @f |
cmp [es:mi.BitsPerPixel], 24 ;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 |
; mov [es:mi.BitsPerPixel],15 |
.l0: |
cmp [es:mi.XRes],640 |
jb @f |
cmp [es:mi.YRes],480 |
jb @f |
; cmp [es:mi.BitsPerPixel],8 |
; jb @f |
mov ax,[es:mi.XRes] |
mov [es:bx+0],ax ; +0[2] : resolution X |
mov ax,[es:mi.YRes] |
mov [es:bx+2],ax ; +2[2] : resolution Y |
mov ax,[es:mi.ModeAttributes] |
mov [es:bx+4],ax ; +4[2] : attributes |
cmp [s_vesa.ver],'2' |
jb .lp1 |
or cx,0x4000 ; use LFB |
.lp1: mov [es:bx+6],cx ; +6 : mode number |
movzx ax,byte [es:mi.BitsPerPixel] |
mov word [es:bx+8],ax ; +8 : bits per pixel |
add bx,size_of_step ; size of record |
@@: |
add si,2 |
jmp .next_mode |
.modes_ok.2: |
mov word[es:bx],-1 ;end video table |
mov word[end_cursor],bx ;save end cursor position |
;;;;;;;;;;;;;;;;;; |
;Sort array |
; mov si,modes_table |
;.new_mode: |
; mov ax,word [es:si] |
; cmp ax,-1 |
; je .exxit |
; add ax,word [es:si+2] |
; add ax,word [es:si+8] |
; mov bp,si |
;.again: |
; add bp,12 |
; mov bx,word [es:bp] |
; cmp bx,-1 |
; je .exit |
; add bx,word [es:bp+2] |
; add bx,word [es:bp+8] |
; |
; cmp ax,bx |
; ja .loops |
; jmp .again |
;.loops: |
; push dword [es:si] |
; push dword [es:si+4] |
; push dword [es:si+8] |
; push dword [es:bp] |
; push dword [es:bp+4] |
; push dword [es:bp+8] |
; |
; pop dword [es:si+8] |
; pop dword [es:si+4] |
; pop dword [es:si] |
; pop dword [es:bp+8] |
; pop dword [es:bp+4] |
; pop dword [es:bp] |
; jmp .new_mode |
; |
;.exit: add si,12 |
; jmp .new_mode |
;.exxit: |
popad |
ret |
;----------------------------------------------------------------------------- |
draw_current_vmode: |
push 0 |
pop es |
mov si,word [cursor_pos] |
cmp word [es:si+6],0x12 |
je .no_vesa_0x12 |
cmp word [es:si+6],0x13 |
je .no_vesa_0x13 |
mov di,loader_block_error |
movzx eax,word[es:si+0] |
mov ecx,10 |
call int2strnz |
mov byte[es:di],'x' |
inc di |
movzx eax,word[es:si+2] |
call int2strnz |
mov byte[es:di],'x' |
inc di |
movzx eax,word[es:si+8] |
call int2strnz |
mov dword[es:di],0x00000d0a |
mov si,loader_block_error |
push ds |
push es |
pop ds |
call printplain |
pop ds |
ret |
.no_vesa_0x13: |
mov si,mode0 |
jmp .print |
.no_vesa_0x12: |
mov si,mode9 |
.print: |
call printplain |
ret |
;----------------------------------------------------------------------------- |
check_first_parm: |
mov si,word [preboot_graph] |
test si,si |
jnz .no_zero ;if no zero |
.zerro: |
; mov ax,modes_table |
; mov word [cursor_pos],ax |
; 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 ax,1024 |
mov bx,768 |
mov si,modes_table |
call .loops |
test ax,ax |
jz .ok_found_mode |
mov ax,800 |
mov bx,600 |
mov si,modes_table |
call .loops |
test ax,ax |
jz .ok_found_mode |
mov ax,640 |
mov bx,480 |
mov si,modes_table |
call .loops |
test ax,ax |
jz .ok_found_mode |
mov si,modes_table |
jmp .ok_found_mode |
.no_zero: |
mov bp,word [number_vm] |
cmp bp,word [es:si+6] |
jz .ok_found_mode |
mov ax,word [x_save] |
mov bx,word [y_save] |
mov si,modes_table |
call .loops |
test ax,ax |
jz .ok_found_mode |
mov si,modes_table |
; cmp ax,modes_table |
; jb .zerro ;check on correct if bellow |
; cmp ax,word [end_cursor] |
; ja .zerro ;check on correct if anymore |
.ok_found_mode: |
mov word [home_cursor],si |
; mov word [cursor_pos],si |
mov word [preboot_graph],si |
mov ax,si |
mov ecx,long_v_table |
.loop: add ax,size_of_step |
cmp ax,word [end_cursor] |
jae .next_step |
loop .loop |
.next_step: |
sub ax,size_of_step*long_v_table |
cmp ax,modes_table |
jae @f |
mov ax,modes_table |
@@: |
mov word [home_cursor],ax |
mov si,[preboot_graph] |
mov word [cursor_pos],si |
push word [es:si] |
pop word [x_save] |
push word [es:si+2] |
pop word [y_save] |
push word [es:si+6] |
pop word [number_vm] |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.loops: |
cmp ax,word [es:si] |
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 |
.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 |
;----------------------------------------------------------------------------- |
;default_vmode: |
;----------------------------------------------------------------------------- |
draw_vmodes_table: |
_setcursor 9, 2 |
mov si,gr_mode |
call printplain |
mov si,_st |
call printplain |
push word [cursor_pos] |
pop ax |
push word [home_cursor] |
pop si |
mov cx,si |
cmp ax,si |
je .ok |
jb .low |
add cx,size_of_step*long_v_table |
cmp ax,cx |
jb .ok |
sub cx,size_of_step*long_v_table |
add cx,size_of_step |
cmp cx,word[end_cursor] |
jae .ok |
add si,size_of_step |
push si |
pop word [home_cursor] |
jmp .ok |
.low: sub cx,size_of_step |
cmp cx,modes_table |
jb .ok |
push cx |
push cx |
pop word [home_cursor] |
pop si |
.ok: |
; calculate scroll position |
push si |
mov ax, [end_cursor] |
sub ax, modes_table |
mov bx, size_of_step |
cwd |
div bx |
mov si, ax ; si = size of list |
mov ax, [home_cursor] |
sub ax, modes_table |
cwd |
div bx |
mov di, ax |
mov ax, scroll_area_size*long_v_table |
cwd |
div si |
test ax, ax |
jnz @f |
inc ax |
@@: |
cmp al, scroll_area_size |
jb @f |
mov al, scroll_area_size |
@@: |
mov cx, ax |
; cx = scroll height |
; calculate scroll pos |
xor bx, bx ; initialize scroll pos |
sub al, scroll_area_size+1 |
neg al |
sub si, long_v_table-1 |
jbe @f |
mul di |
div si |
mov bx, ax |
@@: |
inc bx |
imul ax, bx, size_of_step |
add ax, [home_cursor] |
mov [scroll_start], ax |
imul cx, size_of_step |
add ax, cx |
mov [scroll_end], ax |
pop si |
mov bp,long_v_table ;show rows |
.@@_next_bit: |
;clear cursor |
mov ax,' ' |
mov word[ds:_r1+21],ax |
mov word[ds:_r1+50],ax |
mov word[ds:_r2+21],ax |
mov word[ds:_r2+45],ax |
mov word[ds:_rs+21],ax |
mov word[ds:_rs+46],ax |
; draw string |
cmp word [es:si+6],0x12 |
je .show_0x12 |
cmp word [es:si+6],0x13 |
je .show_0x13 |
movzx eax,word[es:si] |
cmp ax,-1 |
je .@@_end |
mov di,_rs+23 |
mov ecx,10 |
mov bl,4 |
call int2str |
movzx eax,word[es:si+2] |
inc di |
mov bl,4 |
call int2str |
movzx eax,word[es:si+8] |
inc di |
mov bl,2 |
call int2str |
cmp si, word [cursor_pos] |
jne .next |
;draw cursor |
mov word[ds:_rs+21],'>>' |
mov word[ds:_rs+46],'<<' |
.next: |
push si |
mov si,_rs |
.@@_sh: |
; add to the string pseudographics for scrollbar |
pop bx |
push bx |
mov byte [si+53], ' ' |
cmp bx, [scroll_start] |
jb @f |
cmp bx, [scroll_end] |
jae @f |
mov byte [si+53], 0xDB ; filled bar |
@@: |
push bx |
add bx, size_of_step |
cmp bx, [end_cursor] |
jnz @f |
mov byte [si+53], 31 ; 'down arrow' symbol |
@@: |
sub bx, [home_cursor] |
cmp bx, size_of_step*long_v_table |
jnz @f |
mov byte [si+53], 31 ; 'down arrow' symbol |
@@: |
pop bx |
cmp bx, [home_cursor] |
jnz @f |
mov byte [si+53], 30 ; 'up arrow' symbol |
@@: |
call printplain |
pop si |
add si,size_of_step |
dec bp |
jnz .@@_next_bit |
.@@_end: |
mov si,_bt |
call printplain |
ret |
.show_0x13: |
push si |
cmp si, word [cursor_pos] |
jne @f |
mov word[ds:_r1+21],'>>' |
mov word[ds:_r1+50],'<<' |
@@: |
mov si,_r1 |
jmp .@@_sh |
.show_0x12: |
push si |
cmp si, word [cursor_pos] |
jne @f |
mov word[ds:_r2+21],'>>' |
mov word[ds:_r2+45],'<<' |
@@: |
mov si,_r2 |
jmp .@@_sh |
;----------------------------------------------------------------------------- |
;Clear arrea of current video page (0xb800) |
clear_vmodes_table: |
pusha |
; draw frames |
push es |
push 0xb800 |
pop es |
mov di,1444 |
xor ax,ax |
mov ah, 1*16+15 |
mov cx,70 |
mov bp,12 |
.loop_start: |
rep stosw |
mov cx,70 |
add di,20 |
dec bp |
jns .loop_start |
pop es |
popa |
ret |
;----------------------------------------------------------------------------- |
set_vmode: |
push 0 ;0;x1000 |
pop es |
mov si,word [preboot_graph] ;[preboot_graph] |
mov cx,word [es:si+6] ; number of mode |
mov ax,word [es:si+0] ; resolution X |
mov bx,word [es:si+2] ; resolution Y |
mov word [es:0x900A],ax ; resolution X |
mov word [es:0x900C],bx ; resolution Y |
mov word [es:0x9008],cx ; number of mode |
cmp cx,0x12 |
je .mode0x12_0x13 |
cmp cx,0x13 |
je .mode0x12_0x13 |
cmp byte [s_vesa.ver],'2' |
jb .vesa12 |
; VESA 2 and Vesa 3 |
mov ax,0x4f01 |
and cx,0xfff |
mov di,mi;0xa000 |
int 0x10 |
; LFB |
mov eax,[es:mi.PhysBasePtr];di+0x28] |
mov [es:0x9018],eax |
; ---- vbe voodoo |
BytesPerLine equ 0x10 |
mov ax, [es:di+BytesPerLine] |
mov [es:0x9001], ax |
; BPP |
cmp [es:mi.BitsPerPixel],16 |
jne .l0 |
cmp [es:mi.GreenMaskSize],5 |
jne .l0 |
mov [es:mi.BitsPerPixel],15 |
.l0: |
mov al, byte [es:di+0x19] |
mov [es:0x9000], al |
jmp .exit |
.mode0x12_0x13: |
mov byte [es:0x9000], 32 |
or dword [es:0x9018], 0xFFFFFFFF; 0x800000 |
; VESA 1.2 PM BANK SWITCH ADDRESS |
.vesa12: |
mov ax,0x4f0A |
xor bx,bx |
int 0x10 |
xor eax,eax |
xor ebx,ebx |
mov ax,es |
shl eax,4 |
mov bx,di |
add eax,ebx |
movzx ebx,word[es:di] |
add eax,ebx |
push 0x0000 |
pop es |
mov [es:0x9014],eax |
.exit: |
ret |
; mov dword[es:0x9018],0x000A0000 |
; ret |
;============================================================================= |
;============================================================================= |
;============================================================================= |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
struc VBE_VGAInfo { |
.VESASignature dd ? ; char |
.VESAVersion dw ? ; short |
.OemStringPtr dd ? ; char * |
.Capabilities dd ? ; ulong |
.VideoModePtr dd ? ; ulong |
.TotalMemory dw ? ; short |
; VBE 2.0+ |
.OemSoftwareRev db ? ; short |
.OemVendorNamePtr dw ? ; char * |
.OemProductNamePtr dw ? ; char * |
.OemProductRevPtr dw ? ; char * |
.reserved rb 222 ; char |
.OemData rb 256 ; char |
} |
struc VBE_ModeInfo { |
.ModeAttributes dw ? ; short |
.WinAAttributes db ? ; char |
.WinBAttributes db ? ; char |
.WinGranularity dw ? ; short |
.WinSize dw ? ; short |
.WinASegment dw ? ; ushort |
.WinBSegment dw ? ; ushort |
.WinFuncPtr dd ? ; void * |
.BytesPerScanLine dw ? ; short |
.XRes dw ? ; short |
.YRes dw ? ; short |
.XCharSize db ? ; char |
.YCharSize db ? ; char |
.NumberOfPlanes db ? ; char |
.BitsPerPixel db ? ; char |
.NumberOfBanks db ? ; char |
.MemoryModel db ? ; char |
.BankSize db ? ; char |
.NumberOfImagePages db ? ; char |
.res1 db ? ; char |
.RedMaskSize db ? ; char |
.RedFieldPosition db ? ; char |
.GreenMaskSize db ? ; char |
.GreenFieldPosition db ? ; char |
.BlueMaskSize db ? ; char |
.BlueFieldPosition db ? ; char |
.RsvedMaskSize db ? ; char |
.RsvedFieldPosition db ? ; char |
.DirectColorModeInfo db ? ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE |
; VBE 2.0+ |
.PhysBasePtr dd ? ; ulong |
.OffScreenMemOffset dd ? ; ulong |
.OffScreenMemSize dw ? ; short |
; VBE 3.0+ |
.LinbytesPerScanLine dw ? ; short |
.BankNumberOfImagePages db ? ; char |
.LinNumberOfImagePages db ? ; char |
.LinRedMaskSize db ? ; char |
.LinRedFieldPosition db ? ; char |
.LingreenMaskSize db ? ; char |
.LinGreenFieldPosition db ? ; char |
.LinBlueMaskSize db ? ; char |
.LinBlueFieldPosition db ? ; char |
.LinRsvdMaskSize db ? ; char |
.LinRsvdFieldPosition db ? ; char |
.MaxPixelClock dd ? ; ulong |
.res2 rb 190 ; char |
} |
virtual at $A000 |
vi VBE_VGAInfo |
mi VBE_ModeInfo |
modes_table: |
end virtual |
cursor_pos dw 0 ;âðåìåííîå õðàíåíèå êóðñîðà. |
home_cursor dw 0 ;current shows rows a table |
end_cursor dw 0 ;end of position current shows rows a table |
scroll_start dw 0 ;start position of scroll bar |
scroll_end dw 0 ;end position of scroll bar |
long_v_table equ 9 ;long of visible video table |
size_of_step equ 10 |
scroll_area_size equ (long_v_table-2) |
int2str: |
dec bl |
jz @f |
xor edx, edx |
div ecx |
push edx |
call int2str |
pop eax |
@@: |
or al, 0x30 |
mov [ds:di], al |
inc di |
ret |
int2strnz: |
cmp eax, ecx |
jb @f |
xor edx, edx |
div ecx |
push edx |
call int2strnz |
pop eax |
@@: |
or al, 0x30 |
mov [es:di], al |
inc di |
ret |
;------------------------------------------------------- |
;Write message about incorrect v_mode and write message about jmp on swith v_mode |
v_mode_error: |
_setcursor 19,2 |
mov si, fatalsel |
call printplain |
_setcursor 20,2 |
mov si, pres_key |
call printplain |
xor eax, eax |
int 16h |
jmp cfgmanager.d |
;------------------------------------------------------- |
; |
;------------------------------------------------------- |
print_vesa_info: |
_setcursor 5,2 |
mov [es:vi.VESASignature], 'VBE2' |
mov ax, 0x4F00 |
mov di, vi ;0xa000 |
int 0x10 |
or ah, ah |
jz @f |
mov [es:vi.VESASignature], 'VESA' |
mov ax, $4F00 |
mov di, vi |
int 0x10 |
or ah, ah |
jnz .exit |
@@: |
cmp [es:vi.VESASignature], 'VESA' |
jne .exit |
cmp [es:vi.VESAVersion], 0x0100 |
jb .exit |
jmp .vesaok2 |
.exit: |
mov si, novesa |
call printplain |
ret |
.vesaok2: |
mov ax, [es:vi.VESAVersion] |
add ax, '00' |
mov [s_vesa.ver], ah |
mov [s_vesa.ver+2], al |
mov si, s_vesa |
call printplain |
_setcursor 4,2 |
mov si, word[es:vi.OemStringPtr] |
mov di, si |
push ds |
mov ds, word[es:vi.OemStringPtr+2] |
call printplain |
pop ds |
ret |
;----------------------------------------------------------------------------- |
calc_vmodes_table: |
pushad |
; push 0 |
; pop es |
lfs si, [es:vi.VideoModePtr] |
mov bx, modes_table |
;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢ |
mov word [es:bx], 640 |
mov word [es:bx+2], 480 |
mov word [es:bx+6], 0x13 |
mov word [es:bx+10], 640 |
mov word [es:bx+12], 480 |
mov word [es:bx+16], 0x12 |
add bx, 20 |
.next_mode: |
mov cx, word [fs:si]; mode number |
cmp cx, -1 |
je .modes_ok.2 |
mov ax, 0x4F01 |
mov di, mi |
int 0x10 |
or ah, ah |
jnz .modes_ok.2;vesa_info.exit |
test [es:mi.ModeAttributes], 00000001b ;videomode support ? |
jz @f |
test [es:mi.ModeAttributes], 00010000b ;picture ? |
jz @f |
test [es:mi.ModeAttributes], 10000000b ;LFB ? |
jz @f |
cmp [es:mi.BitsPerPixel], 24 ;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 |
; mov [es:mi.BitsPerPixel],15 |
.l0: |
cmp [es:mi.XRes], 640 |
jb @f |
cmp [es:mi.YRes], 480 |
jb @f |
; cmp [es:mi.BitsPerPixel],8 |
; jb @f |
mov ax, [es:mi.XRes] |
mov [es:bx+0], ax ; +0[2] : resolution X |
mov ax, [es:mi.YRes] |
mov [es:bx+2], ax ; +2[2] : resolution Y |
mov ax, [es:mi.ModeAttributes] |
mov [es:bx+4], ax ; +4[2] : attributes |
cmp [s_vesa.ver], '2' |
jb .lp1 |
or cx, 0x4000 ; use LFB |
.lp1: |
mov [es:bx+6], cx ; +6 : mode number |
movzx ax, byte [es:mi.BitsPerPixel] |
mov word [es:bx+8], ax ; +8 : bits per pixel |
add bx, size_of_step ; size of record |
@@: |
add si, 2 |
jmp .next_mode |
.modes_ok.2: |
mov word[es:bx], -1 ;end video table |
mov word[end_cursor], bx ;save end cursor position |
;;;;;;;;;;;;;;;;;; |
;Sort array |
; mov si,modes_table |
;.new_mode: |
; mov ax,word [es:si] |
; cmp ax,-1 |
; je .exxit |
; add ax,word [es:si+2] |
; add ax,word [es:si+8] |
; mov bp,si |
;.again: |
; add bp,12 |
; mov bx,word [es:bp] |
; cmp bx,-1 |
; je .exit |
; add bx,word [es:bp+2] |
; add bx,word [es:bp+8] |
; |
; cmp ax,bx |
; ja .loops |
; jmp .again |
;.loops: |
; push dword [es:si] |
; push dword [es:si+4] |
; push dword [es:si+8] |
; push dword [es:bp] |
; push dword [es:bp+4] |
; push dword [es:bp+8] |
; |
; pop dword [es:si+8] |
; pop dword [es:si+4] |
; pop dword [es:si] |
; pop dword [es:bp+8] |
; pop dword [es:bp+4] |
; pop dword [es:bp] |
; jmp .new_mode |
; |
;.exit: add si,12 |
; jmp .new_mode |
;.exxit: |
popad |
ret |
;----------------------------------------------------------------------------- |
draw_current_vmode: |
push 0 |
pop es |
mov si, word [cursor_pos] |
cmp word [es:si+6], 0x12 |
je .no_vesa_0x12 |
cmp word [es:si+6], 0x13 |
je .no_vesa_0x13 |
mov di, loader_block_error |
movzx eax, word[es:si+0] |
mov ecx, 10 |
call int2strnz |
mov byte[es:di], 'x' |
inc di |
movzx eax, word[es:si+2] |
call int2strnz |
mov byte[es:di], 'x' |
inc di |
movzx eax, word[es:si+8] |
call int2strnz |
mov dword[es:di], 0x00000d0a |
mov si, loader_block_error |
push ds |
push es |
pop ds |
call printplain |
pop ds |
ret |
.no_vesa_0x13: |
mov si, mode0 |
jmp .print |
.no_vesa_0x12: |
mov si, mode9 |
.print: |
call printplain |
ret |
;----------------------------------------------------------------------------- |
check_first_parm: |
mov si, word [preboot_graph] |
test si, si |
jnz .no_zero ;if no zero |
.zerro: |
; mov ax,modes_table |
; mov word [cursor_pos],ax |
; 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 ax, 1024 |
mov bx, 768 |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
mov ax, 800 |
mov bx, 600 |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
mov ax, 640 |
mov bx, 480 |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
mov si, modes_table |
jmp .ok_found_mode |
.no_zero: |
mov bp, word [number_vm] |
cmp bp, word [es:si+6] |
jz .ok_found_mode |
mov ax, word [x_save] |
mov bx, word [y_save] |
mov si, modes_table |
call .loops |
test ax, ax |
jz .ok_found_mode |
mov si, modes_table |
; cmp ax,modes_table |
; jb .zerro ;check on correct if bellow |
; cmp ax,word [end_cursor] |
; ja .zerro ;check on correct if anymore |
.ok_found_mode: |
mov word [home_cursor], si |
; mov word [cursor_pos],si |
mov word [preboot_graph], si |
mov ax, si |
mov ecx, long_v_table |
.loop: |
add ax, size_of_step |
cmp ax, word [end_cursor] |
jae .next_step |
loop .loop |
.next_step: |
sub ax, size_of_step*long_v_table |
cmp ax, modes_table |
jae @f |
mov ax, modes_table |
@@: |
mov word [home_cursor], ax |
mov si, [preboot_graph] |
mov word [cursor_pos], si |
push word [es:si] |
pop word [x_save] |
push word [es:si+2] |
pop word [y_save] |
push word [es:si+6] |
pop word [number_vm] |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.loops: |
cmp ax, word [es:si] |
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 |
.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 |
;----------------------------------------------------------------------------- |
;default_vmode: |
;----------------------------------------------------------------------------- |
draw_vmodes_table: |
_setcursor 9, 2 |
mov si, gr_mode |
call printplain |
mov si, _st |
call printplain |
push word [cursor_pos] |
pop ax |
push word [home_cursor] |
pop si |
mov cx, si |
cmp ax, si |
je .ok |
jb .low |
add cx, size_of_step*long_v_table |
cmp ax, cx |
jb .ok |
sub cx, size_of_step*long_v_table |
add cx, size_of_step |
cmp cx, word[end_cursor] |
jae .ok |
add si, size_of_step |
push si |
pop word [home_cursor] |
jmp .ok |
.low: |
sub cx, size_of_step |
cmp cx, modes_table |
jb .ok |
push cx |
push cx |
pop word [home_cursor] |
pop si |
.ok: |
; calculate scroll position |
push si |
mov ax, [end_cursor] |
sub ax, modes_table |
mov bx, size_of_step |
cwd |
div bx |
mov si, ax ; si = size of list |
mov ax, [home_cursor] |
sub ax, modes_table |
cwd |
div bx |
mov di, ax |
mov ax, scroll_area_size*long_v_table |
cwd |
div si |
test ax, ax |
jnz @f |
inc ax |
@@: |
cmp al, scroll_area_size |
jb @f |
mov al, scroll_area_size |
@@: |
mov cx, ax |
; cx = scroll height |
; calculate scroll pos |
xor bx, bx ; initialize scroll pos |
sub al, scroll_area_size+1 |
neg al |
sub si, long_v_table-1 |
jbe @f |
mul di |
div si |
mov bx, ax |
@@: |
inc bx |
imul ax, bx, size_of_step |
add ax, [home_cursor] |
mov [scroll_start], ax |
imul cx, size_of_step |
add ax, cx |
mov [scroll_end], ax |
pop si |
mov bp, long_v_table ;show rows |
.@@_next_bit: |
;clear cursor |
mov ax, ' ' |
mov word[ds:_r1+21], ax |
mov word[ds:_r1+50], ax |
mov word[ds:_r2+21], ax |
mov word[ds:_r2+45], ax |
mov word[ds:_rs+21], ax |
mov word[ds:_rs+46], ax |
; draw string |
cmp word [es:si+6], 0x12 |
je .show_0x12 |
cmp word [es:si+6], 0x13 |
je .show_0x13 |
movzx eax, word[es:si] |
cmp ax, -1 |
je .@@_end |
mov di, _rs+23 |
mov ecx, 10 |
mov bl, 4 |
call int2str |
movzx eax, word[es:si+2] |
inc di |
mov bl, 4 |
call int2str |
movzx eax, word[es:si+8] |
inc di |
mov bl, 2 |
call int2str |
cmp si, word [cursor_pos] |
jne .next |
;draw cursor |
mov word[ds:_rs+21], '>>' |
mov word[ds:_rs+46], '<<' |
.next: |
push si |
mov si, _rs |
.@@_sh: |
; add to the string pseudographics for scrollbar |
pop bx |
push bx |
mov byte [si+53], ' ' |
cmp bx, [scroll_start] |
jb @f |
cmp bx, [scroll_end] |
jae @f |
mov byte [si+53], 0xDB ; filled bar |
@@: |
push bx |
add bx, size_of_step |
cmp bx, [end_cursor] |
jnz @f |
mov byte [si+53], 31 ; 'down arrow' symbol |
@@: |
sub bx, [home_cursor] |
cmp bx, size_of_step*long_v_table |
jnz @f |
mov byte [si+53], 31 ; 'down arrow' symbol |
@@: |
pop bx |
cmp bx, [home_cursor] |
jnz @f |
mov byte [si+53], 30 ; 'up arrow' symbol |
@@: |
call printplain |
pop si |
add si, size_of_step |
dec bp |
jnz .@@_next_bit |
.@@_end: |
mov si, _bt |
call printplain |
ret |
.show_0x13: |
push si |
cmp si, word [cursor_pos] |
jne @f |
mov word[ds:_r1+21], '>>' |
mov word[ds:_r1+50], '<<' |
@@: |
mov si, _r1 |
jmp .@@_sh |
.show_0x12: |
push si |
cmp si, word [cursor_pos] |
jne @f |
mov word[ds:_r2+21], '>>' |
mov word[ds:_r2+45], '<<' |
@@: |
mov si, _r2 |
jmp .@@_sh |
;----------------------------------------------------------------------------- |
;Clear arrea of current video page (0xb800) |
clear_vmodes_table: |
pusha |
; draw frames |
push es |
push 0xb800 |
pop es |
mov di, 1444 |
xor ax, ax |
mov ah, 1*16+15 |
mov cx, 70 |
mov bp, 12 |
.loop_start: |
rep stosw |
mov cx, 70 |
add di, 20 |
dec bp |
jns .loop_start |
pop es |
popa |
ret |
;----------------------------------------------------------------------------- |
set_vmode: |
push 0 ;0;x1000 |
pop es |
mov si, word [preboot_graph] ;[preboot_graph] |
mov cx, word [es:si+6] ; number of mode |
mov ax, word [es:si+0] ; resolution X |
mov bx, word [es:si+2] ; resolution Y |
mov word [es:0x900A], ax ; resolution X |
mov word [es:0x900C], bx ; resolution Y |
mov word [es:0x9008], cx ; number of mode |
cmp cx, 0x12 |
je .mode0x12_0x13 |
cmp cx, 0x13 |
je .mode0x12_0x13 |
cmp byte [s_vesa.ver], '2' |
jb .vesa12 |
; VESA 2 and Vesa 3 |
mov ax, 0x4f01 |
and cx, 0xfff |
mov di, mi;0xa000 |
int 0x10 |
; LFB |
mov eax, [es:mi.PhysBasePtr];di+0x28] |
mov [es:0x9018], eax |
; ---- vbe voodoo |
BytesPerLine equ 0x10 |
mov ax, [es:di+BytesPerLine] |
mov [es:0x9001], ax |
; BPP |
cmp [es:mi.BitsPerPixel], 16 |
jne .l0 |
cmp [es:mi.GreenMaskSize], 5 |
jne .l0 |
mov [es:mi.BitsPerPixel], 15 |
.l0: |
mov al, byte [es:di+0x19] |
mov [es:0x9000], al |
jmp .exit |
.mode0x12_0x13: |
mov byte [es:0x9000], 32 |
or dword [es:0x9018], 0xFFFFFFFF; 0x800000 |
; VESA 1.2 PM BANK SWITCH ADDRESS |
.vesa12: |
mov ax, 0x4f0A |
xor bx, bx |
int 0x10 |
xor eax, eax |
xor ebx, ebx |
mov ax, es |
shl eax, 4 |
mov bx, di |
add eax, ebx |
movzx ebx, word[es:di] |
add eax, ebx |
push 0x0000 |
pop es |
mov [es:0x9014], eax |
.exit: |
ret |
; mov dword[es:0x9018],0x000A0000 |
; ret |
;============================================================================= |
;============================================================================= |
;============================================================================= |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/et.inc |
---|
1,14 → 1,14 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Full ASCII code font |
; only õ and ä added |
; Kaitz |
ET_FNT: |
fontfile file "ETFONT.FNT" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Full ASCII code font |
; only õ and ä added |
; Kaitz |
ET_FNT: |
fontfile file "ETFONT.FNT" |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/kolibri_ldm.asm |
---|
1,808 → 1,815 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Last modify Alexey Teplov <Lrz> 2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; kolibri_ldm.asm the module for Secondary Loader ;; |
;; ;; |
;; KolibriOS 16-bit loader module, ;; |
;; based on bootcode for KolibriOS ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include "lang.inc" |
macro _setcursor row,column |
{ |
mov dx, row*256 + column |
call setcursor |
} |
long_v_table equ 9 ;long of visible video table |
size_of_step equ 10 |
d80x25_bottom_num equ 3 |
d80x25_top_num equ 4 |
;It's a module for Secondary Loader to load kolibri OS |
; |
start_of_code: |
cld |
; \begin{diamond}[02.12.2005] |
; if bootloader sets ax = 'KL', then ds:si points to loader block |
; cmp ax, 'KL' |
; jnz @f |
; mov word [cs:cfgmanager.loader_block], si |
; mov word [cs:cfgmanager.loader_block+2], ds |
;@@: |
; \end{diamond}[02.12.2005] |
; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk |
; (see comment to bx_from_load) |
; cmp cx, 'HA' |
; jnz no_hd_load |
; cmp dx,'RD' |
; jnz no_hd_load |
; mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007] |
;no_hd_load: |
; set up stack |
push cs |
pop ss |
xor ax,ax |
mov sp,ax |
; mov ax, 3000h |
; mov ss, ax |
; mov sp, 0EC00h |
; set up segment registers |
push cs |
pop ds |
push cs |
pop es |
; set videomode |
mov ax, 3 |
int 0x10 |
;if lang eq ru |
; Load & set russian VGA font (RU.INC) |
mov bp, RU_FNT1 ; RU_FNT1 - First part |
mov bx, 1000h ; 768 bytes |
mov cx, 30h ; 48 symbols |
mov dx, 80h ; 128 - position of first symbol |
mov ax, 1100h |
int 10h |
mov bp, RU_FNT2 ; RU_FNT2 -Second part |
mov bx, 1000h ; 512 bytes |
mov cx, 20h ; 32 symbols |
mov dx, 0E0h ; 224 - position of first symbol |
mov ax, 1100h |
int 10h |
; End set VGA russian font |
;else if lang eq et |
; mov bp, ET_FNT ; ET_FNT1 |
; mov bx, 1000h ; |
; mov cx, 255 ; 256 symbols |
; xor dx, dx ; 0 - position of first symbol |
; mov ax, 1100h |
; int 10h |
;end if |
; draw frames |
push 0xb800 |
pop es |
xor di, di |
mov ah, 1*16+15 |
; draw top |
mov si, d80x25_top |
mov cx, d80x25_top_num * 80 |
@@: |
lodsb |
stosw |
loop @b |
; draw spaces |
mov si, space_msg |
mov dx, 25 - d80x25_top_num - d80x25_bottom_num |
dfl1: |
push si |
mov cx, 80 |
@@: |
lodsb |
stosw |
loop @b |
pop si |
dec dx |
jnz dfl1 |
; draw bottom |
mov si, d80x25_bottom |
mov cx, d80x25_bottom_num * 80 |
@@: |
lodsb |
stosw |
loop @b |
mov byte [space_msg+80], 0 ; now space_msg is null terminated |
_setcursor d80x25_top_num,0 |
; TEST FOR 386+ |
mov bx, 0x4000 |
pushf |
pop ax |
mov dx, ax |
xor ax, bx |
push ax |
popf |
pushf |
pop ax |
and ax, bx |
and dx, bx |
cmp ax, dx |
jnz cpugood |
mov si, not386 |
sayerr: |
call print |
jmp $ |
cpugood: |
push 0 |
popf |
sti |
; set up esp |
movzx esp, sp |
push 0 |
pop es |
and word [es:0x9031], 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 |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x80 |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
; b) class 1, subclass 1, programming interface 0x8A |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x8A |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
; c) class 1, subclass 1, programming interface 0x85 |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x85 |
xor si, si |
int 0x1A |
jc .nopci |
.found: |
; get memory base |
mov ax, 0xB10A |
mov di, 0x20 ; memory base is config register at 0x20 |
int 0x1A |
jc .nopci |
and cx, 0xFFF0 ; clear address decode type |
mov [es:0x9031], 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 |
;;;/diamond today 5.02.2008 |
; set keyboard typematic rate & delay |
mov al, 0xf3 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
mov al, 0 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; --------------- APM --------------------- |
and word [es:0x9044], 0 ; ver = 0.0 (APM not found) |
mov ax, 0x5300 |
xor bx, bx |
int 0x15 |
jc apm_end ; APM not found |
test cx, 2 |
jz apm_end ; APM 32-bit protected-mode interface not supported |
mov [es:0x9044], ax ; Save APM Version |
mov [es:0x9046], cx ; Save APM flags |
; Write APM ver ---- |
and ax, 0xf0f |
add ax, '00' |
mov si, msg_apm |
mov [si + 5], ah |
mov [si + 7], al |
_setcursor 0, 3 |
call printplain |
; ------------------ |
mov ax, 0x5304 ; Disconnect interface |
xor bx, bx |
int 0x15 |
mov ax, 0x5303 ; Connect 32 bit mode interface |
xor bx, bx |
int 0x15 |
mov [es:0x9040], ebx |
mov [es:0x9050], ax |
mov [es:0x9052], cx |
mov [es:0x9054], dx |
apm_end: |
_setcursor d80x25_top_num, 0 |
;CHECK current of code |
cmp [cfgmanager.loader_block], -1 |
jz noloaderblock |
les bx, [cfgmanager.loader_block] |
cmp byte [es:bx], 1 |
mov si, loader_block_error |
jnz sayerr |
push 0 |
pop es |
noloaderblock: |
; DISPLAY VESA INFORMATION |
call print_vesa_info |
call calc_vmodes_table |
call check_first_parm ;check and enable cursor_pos |
; \begin{diamond}[30.11.2005] |
cfgmanager: |
; settings: |
; a) preboot_graph = graphical mode |
; preboot_gprobe = probe this mode? |
; b) preboot_dma = use DMA access? |
; c) preboot_vrrm = use VRR? |
; determine default settings |
mov [.bSettingsChanged], 0 |
;.preboot_gr_end: |
mov di, preboot_device |
; if image in memory is present and [preboot_device] is uninitialized, |
; set it to use this preloaded image |
cmp byte [di], 0 |
jnz .preboot_device_inited |
cmp [.loader_block], -1 |
jz @f |
les bx, [.loader_block] |
test byte [es:bx+1], 1 |
jz @f |
mov byte [di], 3 |
jmp .preboot_device_inited |
@@: |
; otherwise, set [preboot_device] to 1 (default value - boot from floppy) |
mov byte [di], 1 |
.preboot_device_inited: |
; following 6 lines set variables to 1 if its current value is 0 |
cmp byte [di+preboot_dma-preboot_device], 1 |
adc byte [di+preboot_dma-preboot_device], 0 |
cmp byte [di+preboot_biosdisk-preboot_device], 1 |
adc byte [di+preboot_biosdisk-preboot_device], 0 |
cmp byte [di+preboot_vrrm-preboot_device], 1 |
adc byte [di+preboot_vrrm-preboot_device], 0 |
; notify user |
_setcursor 5,2 |
mov si, linef |
call printplain |
mov si, start_msg |
call print |
mov si, time_msg |
call print |
; get start time |
call .gettime |
mov [.starttime], eax |
mov word [.timer], .newtimer |
mov word [.timer+2], cs |
.printcfg: |
_setcursor 9,0 |
mov si, current_cfg_msg |
call print |
mov si, curvideo_msg |
call print |
call draw_current_vmode |
mov si, usebd_msg |
cmp [preboot_biosdisk], 1 |
call .say_on_off |
mov si, vrrm_msg |
cmp [preboot_vrrm], 1 |
call .say_on_off |
; mov si, preboot_device_msg |
; call print |
; mov al, [preboot_device] |
; and eax, 7 |
; mov si, [preboot_device_msgs+eax*2] |
; call printplain |
.show_remarks: |
; show remarks in gray color |
mov di, ((21-num_remarks)*80 + 2)*2 |
push 0xB800 |
pop es |
mov cx, num_remarks |
mov si, remarks |
.write_remarks: |
lodsw |
push si |
xchg ax, si |
mov ah, 1*16+7 ; background: blue (1), foreground: gray (7) |
push di |
.write_remark: |
lodsb |
test al, al |
jz @f |
stosw |
jmp .write_remark |
@@: |
pop di |
pop si |
add di, 80*2 |
loop .write_remarks |
.wait: |
_setcursor 25,0 ; out of screen |
; set timer interrupt handler |
cli |
push 0 |
pop es |
push dword [es:8*4] |
pop dword [.oldtimer] |
push dword [.timer] |
pop dword [es:8*4] |
; mov eax, [es:8*4] |
; mov [.oldtimer], eax |
; mov eax, [.timer] |
; mov [es:8*4], eax |
sti |
; wait for keypressed |
xor ax,ax |
int 16h |
push ax |
; restore timer interrupt |
; push 0 |
; pop es |
mov eax, [.oldtimer] |
mov [es:8*4], eax |
mov [.timer], eax |
_setcursor 7,0 |
mov si, space_msg |
call printplain |
; clear remarks and restore normal attributes |
push es |
mov di, ((21-num_remarks)*80 + 2)*2 |
push 0xB800 |
pop es |
mov cx, num_remarks |
mov ax, ' ' + (1*16 + 15)*100h |
@@: |
push cx |
mov cx, 76 |
rep stosw |
pop cx |
add di, 4*2 |
loop @b |
pop es |
pop ax |
; switch on key |
cmp al, 13 |
jz .continue |
or al, 20h |
cmp al, 'a' |
jz .change_a |
cmp al, 'b' |
jz .change_b |
cmp al, 'c' |
jnz .show_remarks |
_setcursor 15,0 |
mov si, vrrmprint |
call print |
mov bx, '12' |
call getkey |
mov [preboot_vrrm], al |
_setcursor 12,0 |
.d: |
mov [.bSettingsChanged], 1 |
call clear_vmodes_table ;clear vmodes_table |
jmp .printcfg |
.change_a: |
.loops: |
call draw_vmodes_table |
_setcursor 25,0 ; out of screen |
xor ax,ax |
int 0x16 |
; call clear_table_cursor ;clear current position of cursor |
mov si,word [cursor_pos] |
cmp ah,0x48;x,0x48E0 ; up |
jne .down |
cmp si,modes_table |
jbe .loops |
sub word [cursor_pos],size_of_step |
jmp .loops |
.down: cmp ah,0x50;x,0x50E0 ; down |
jne .pgup |
cmp word[es:si+10],-1 |
je .loops |
add word [cursor_pos],size_of_step |
jmp .loops |
.pgup: cmp ah,0x49 ; page up |
jne .pgdn |
sub si, size_of_step*long_v_table |
cmp si, modes_table |
jae @f |
mov si, modes_table |
@@: |
mov word [cursor_pos], si |
mov si, word [home_cursor] |
sub si, size_of_step*long_v_table |
cmp si, modes_table |
jae @f |
mov si, modes_table |
@@: |
mov word [home_cursor], si |
jmp .loops |
.pgdn: cmp ah,0x51 ; page down |
jne .enter |
mov ax, [end_cursor] |
add si, size_of_step*long_v_table |
cmp si, ax |
jb @f |
mov si, ax |
sub si, size_of_step |
@@: |
mov word [cursor_pos], si |
mov si, word [home_cursor] |
sub ax, size_of_step*long_v_table |
add si, size_of_step*long_v_table |
cmp si, ax |
jb @f |
mov si, ax |
@@: |
mov word [home_cursor], si |
jmp .loops |
.enter: cmp al,0x0D;x,0x1C0D ; enter |
jne .loops |
push word [cursor_pos] |
pop bp |
push word [es:bp] |
pop word [x_save] |
push word [es:bp+2] |
pop word [y_save] |
push word [es:bp+6] |
pop word [number_vm] |
mov word [preboot_graph],bp ;save choose |
jmp .d |
.change_b: |
_setcursor 15,0 |
; mov si, ask_dma |
; call print |
; mov bx, '13' |
; call getkey |
; mov [preboot_dma], al |
mov si, ask_bd |
call print |
mov bx, '12' |
call getkey |
mov [preboot_biosdisk], al |
_setcursor 11,0 |
jmp .d |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.say_on_off: |
pushf |
call print |
mov si, on_msg |
popf |
jz @f |
mov si, off_msg |
@@: jmp printplain |
; novesa and vervesa strings are not used at the moment of executing this code |
virtual at novesa |
.oldtimer dd ? |
.starttime dd ? |
.bSettingsChanged db ? |
.timer dd ? |
end virtual |
.loader_block dd -1 |
.gettime: |
mov ah, 0 |
int 1Ah |
xchg ax, cx |
shl eax, 10h |
xchg ax, dx |
ret |
.newtimer: |
push ds |
push cs |
pop ds |
pushf |
call [.oldtimer] |
pushad |
call .gettime |
sub eax, [.starttime] |
sub ax, 18*5 |
jae .timergo |
neg ax |
add ax, 18-1 |
mov bx, 18 |
xor dx, dx |
div bx |
if lang eq ru |
; ¯®¤®¦¤¨â¥ 5 ᥪã¤, 4/3/2 ᥪã¤ë, 1 ᥪã¤ã |
cmp al, 5 |
mov cl, ' ' |
jae @f |
cmp al, 1 |
mov cl, 'ã' |
jz @f |
mov cl, 'ë' |
@@: mov [time_str+9], cl |
else if lang eq et |
cmp al, 1 |
ja @f |
mov [time_str+9], ' ' |
mov [time_str+10],' ' |
@@: |
else |
; wait 5/4/3/2 seconds, 1 second |
cmp al, 1 |
mov cl, 's' |
ja @f |
mov cl, ' ' |
@@: mov [time_str+9], cl |
end if |
add al, '0' |
mov [time_str+1], al |
mov si, time_msg |
_setcursor 7,0 |
call print |
_setcursor 25,0 |
popad |
pop ds |
iret |
.timergo: |
push 0 |
pop es |
mov eax, [.oldtimer] |
mov [es:8*4], eax |
mov sp, 0EC00h |
.continue: |
sti |
_setcursor 6,0 |
mov si, space_msg |
call printplain |
call printplain |
_setcursor 6,0 |
mov si, loading_msg |
call print |
_setcursor 15,0 |
cmp [.bSettingsChanged], 0 |
jz .load |
cmp [.loader_block], -1 |
jz .load |
les bx, [.loader_block] |
mov eax, [es:bx+3] |
push ds |
pop es |
test eax, eax |
jz .load |
push eax |
mov si, save_quest |
call print |
.waityn: |
mov ah, 0 |
int 16h |
or al, 20h |
cmp al, 'n' |
jz .loadc |
cmp al, 'y' |
jnz .waityn |
call putchar |
mov byte [space_msg+80], 186 |
pop eax |
push cs |
push .cont |
push eax |
retf |
.loadc: |
pop eax |
.cont: |
push cs |
pop ds |
mov si, space_msg |
mov byte [si+80], 0 |
_setcursor 15,0 |
call printplain |
_setcursor 15,0 |
.load: |
; \end{diamond}[02.12.2005] |
; ASK GRAPHICS MODE |
call set_vmode |
; GRAPHICS ACCELERATION |
; force yes |
mov [es:0x901C], byte 1 |
; DMA ACCESS TO HD |
mov al, [preboot_dma] |
mov [es:0x901F], al |
; VRR_M USE |
mov al,[preboot_vrrm] |
mov [es:0x9030], al |
mov [es:0x901E], byte 1 |
; BOOT DEVICE |
mov al, [preboot_device] |
dec al |
mov [boot_dev], al |
;;;;;;;;;;; set videomode |
xor ax, ax |
mov es, ax |
mov ax, [es:0x9008] ; vga & 320x200 |
mov bx, ax |
cmp ax, 0x13 |
je setgr |
cmp ax, 0x12 |
je setgr |
mov ax, 0x4f02 ; Vesa |
setgr: |
int 0x10 |
test ah, ah |
mov si, fatalsel |
jnz v_mode_error |
; set mode 0x12 graphics registers: |
cmp bx, 0x12 |
jne gmok2 |
mov al, 0x05 |
mov dx, 0x03ce |
push dx |
out dx, al ; select GDC mode register |
mov al, 0x02 |
inc dx |
out dx, al ; set write mode 2 |
mov al, 0x02 |
mov dx, 0x03c4 |
out dx, al ; select VGA sequencer map mask register |
mov al, 0x0f |
inc dx |
out dx, al ; set mask for all planes 0-3 |
mov al, 0x08 |
pop dx |
out dx, al ; select GDC bit mask register |
; for writes to 0x03cf |
gmok2: |
push ds |
pop es |
jmp $ |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;data |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include "lang.inc" |
include "bootstr.inc" ; language-independent boot messages |
;if lang eq en |
;include "booteng.inc" ; english system boot messages |
;else if lang eq ru |
include "bootru.inc" ; russian system boot messages |
include "ru.inc" ; Russian font |
;else if lang eq et |
;include "bootet.inc" ; estonian system boot messages |
;include "et.inc" ; Estonian font |
;else |
;include "bootge.inc" ; german system boot messages |
;end if |
include 'macros.inc' |
include 'bootvesa.inc' |
include "preboot.inc" |
setcursor: |
; in: dl=column, dh=row |
mov ah, 2 |
mov bh, 0 |
int 10h |
ret |
putchar: |
; in: al=character |
mov ah, 0Eh |
mov bh, 0 |
int 10h |
ret |
print: |
; in: si->string |
mov al, 186 |
call putchar |
mov al, ' ' |
call putchar |
printplain: |
; in: si->string |
pusha |
lodsb |
@@: |
call putchar |
lodsb |
cmp al, 0 |
jnz @b |
popa |
ret |
getkey: |
; get number in range [bl,bh] (bl,bh in ['0'..'9']) |
; in: bx=range |
; out: ax=digit (1..9, 10 for 0) |
mov ah, 0 |
int 16h |
cmp al, bl |
jb getkey |
cmp al, bh |
ja getkey |
push ax |
call putchar |
pop ax |
and ax, 0Fh |
jnz @f |
mov al, 10 |
@@: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Last modify Alexey Teplov <Lrz> 2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; kolibri_ldm.asm the module for Secondary Loader ;; |
;; ;; |
;; KolibriOS 16-bit loader module, ;; |
;; based on bootcode for KolibriOS ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include "lang.inc" |
macro _setcursor row,column |
{ |
mov dx, row*256 + column |
call setcursor |
} |
long_v_table equ 9 ;long of visible video table |
size_of_step equ 10 |
d80x25_bottom_num equ 3 |
d80x25_top_num equ 4 |
;It's a module for Secondary Loader to load kolibri OS |
; |
start_of_code: |
cld |
; \begin{diamond}[02.12.2005] |
; if bootloader sets ax = 'KL', then ds:si points to loader block |
; cmp ax, 'KL' |
; jnz @f |
; mov word [cs:cfgmanager.loader_block], si |
; mov word [cs:cfgmanager.loader_block+2], ds |
;@@: |
; \end{diamond}[02.12.2005] |
; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk |
; (see comment to bx_from_load) |
; cmp cx, 'HA' |
; jnz no_hd_load |
; cmp dx,'RD' |
; jnz no_hd_load |
; mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007] |
;no_hd_load: |
; set up stack |
push cs |
pop ss |
xor ax, ax |
mov sp, ax |
; mov ax, 3000h |
; mov ss, ax |
; mov sp, 0EC00h |
; set up segment registers |
push cs |
pop ds |
push cs |
pop es |
; set videomode |
mov ax, 3 |
int 0x10 |
;if lang eq ru |
; Load & set russian VGA font (RU.INC) |
mov bp, RU_FNT1 ; RU_FNT1 - First part |
mov bx, 1000h ; 768 bytes |
mov cx, 30h ; 48 symbols |
mov dx, 80h ; 128 - position of first symbol |
mov ax, 1100h |
int 10h |
mov bp, RU_FNT2 ; RU_FNT2 -Second part |
mov bx, 1000h ; 512 bytes |
mov cx, 20h ; 32 symbols |
mov dx, 0E0h ; 224 - position of first symbol |
mov ax, 1100h |
int 10h |
; End set VGA russian font |
;else if lang eq et |
; mov bp, ET_FNT ; ET_FNT1 |
; mov bx, 1000h ; |
; mov cx, 255 ; 256 symbols |
; xor dx, dx ; 0 - position of first symbol |
; mov ax, 1100h |
; int 10h |
;end if |
; draw frames |
push 0xb800 |
pop es |
xor di, di |
mov ah, 1*16+15 |
; draw top |
mov si, d80x25_top |
mov cx, d80x25_top_num * 80 |
@@: |
lodsb |
stosw |
loop @b |
; draw spaces |
mov si, space_msg |
mov dx, 25 - d80x25_top_num - d80x25_bottom_num |
dfl1: |
push si |
mov cx, 80 |
@@: |
lodsb |
stosw |
loop @b |
pop si |
dec dx |
jnz dfl1 |
; draw bottom |
mov si, d80x25_bottom |
mov cx, d80x25_bottom_num * 80 |
@@: |
lodsb |
stosw |
loop @b |
mov byte [space_msg+80], 0 ; now space_msg is null terminated |
_setcursor d80x25_top_num,0 |
; TEST FOR 386+ |
mov bx, 0x4000 |
pushf |
pop ax |
mov dx, ax |
xor ax, bx |
push ax |
popf |
pushf |
pop ax |
and ax, bx |
and dx, bx |
cmp ax, dx |
jnz cpugood |
mov si, not386 |
sayerr: |
call print |
jmp $ |
cpugood: |
push 0 |
popf |
sti |
; set up esp |
movzx esp, sp |
push 0 |
pop es |
and word [es:0x9031], 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 |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x80 |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
; b) class 1, subclass 1, programming interface 0x8A |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x8A |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
; c) class 1, subclass 1, programming interface 0x85 |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x85 |
xor si, si |
int 0x1A |
jc .nopci |
.found: |
; get memory base |
mov ax, 0xB10A |
mov di, 0x20 ; memory base is config register at 0x20 |
int 0x1A |
jc .nopci |
and cx, 0xFFF0 ; clear address decode type |
mov [es:0x9031], 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 |
;;;/diamond today 5.02.2008 |
; set keyboard typematic rate & delay |
mov al, 0xf3 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
mov al, 0 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; --------------- APM --------------------- |
and word [es:0x9044], 0 ; ver = 0.0 (APM not found) |
mov ax, 0x5300 |
xor bx, bx |
int 0x15 |
jc apm_end ; APM not found |
test cx, 2 |
jz apm_end ; APM 32-bit protected-mode interface not supported |
mov [es:0x9044], ax ; Save APM Version |
mov [es:0x9046], cx ; Save APM flags |
; Write APM ver ---- |
and ax, 0xf0f |
add ax, '00' |
mov si, msg_apm |
mov [si + 5], ah |
mov [si + 7], al |
_setcursor 0, 3 |
call printplain |
; ------------------ |
mov ax, 0x5304 ; Disconnect interface |
xor bx, bx |
int 0x15 |
mov ax, 0x5303 ; Connect 32 bit mode interface |
xor bx, bx |
int 0x15 |
mov [es:0x9040], ebx |
mov [es:0x9050], ax |
mov [es:0x9052], cx |
mov [es:0x9054], dx |
apm_end: |
_setcursor d80x25_top_num, 0 |
;CHECK current of code |
cmp [cfgmanager.loader_block], -1 |
jz noloaderblock |
les bx, [cfgmanager.loader_block] |
cmp byte [es:bx], 1 |
mov si, loader_block_error |
jnz sayerr |
push 0 |
pop es |
noloaderblock: |
; DISPLAY VESA INFORMATION |
call print_vesa_info |
call calc_vmodes_table |
call check_first_parm ;check and enable cursor_pos |
; \begin{diamond}[30.11.2005] |
cfgmanager: |
; settings: |
; a) preboot_graph = graphical mode |
; preboot_gprobe = probe this mode? |
; b) preboot_dma = use DMA access? |
; c) preboot_vrrm = use VRR? |
; determine default settings |
mov [.bSettingsChanged], 0 |
;.preboot_gr_end: |
mov di, preboot_device |
; if image in memory is present and [preboot_device] is uninitialized, |
; set it to use this preloaded image |
cmp byte [di], 0 |
jnz .preboot_device_inited |
cmp [.loader_block], -1 |
jz @f |
les bx, [.loader_block] |
test byte [es:bx+1], 1 |
jz @f |
mov byte [di], 3 |
jmp .preboot_device_inited |
@@: |
; otherwise, set [preboot_device] to 1 (default value - boot from floppy) |
mov byte [di], 1 |
.preboot_device_inited: |
; following 6 lines set variables to 1 if its current value is 0 |
cmp byte [di+preboot_dma-preboot_device], 1 |
adc byte [di+preboot_dma-preboot_device], 0 |
cmp byte [di+preboot_biosdisk-preboot_device], 1 |
adc byte [di+preboot_biosdisk-preboot_device], 0 |
cmp byte [di+preboot_vrrm-preboot_device], 1 |
adc byte [di+preboot_vrrm-preboot_device], 0 |
; notify user |
_setcursor 5,2 |
mov si, linef |
call printplain |
mov si, start_msg |
call print |
mov si, time_msg |
call print |
; get start time |
call .gettime |
mov [.starttime], eax |
mov word [.timer], .newtimer |
mov word [.timer+2], cs |
.printcfg: |
_setcursor 9,0 |
mov si, current_cfg_msg |
call print |
mov si, curvideo_msg |
call print |
call draw_current_vmode |
mov si, usebd_msg |
cmp [preboot_biosdisk], 1 |
call .say_on_off |
mov si, vrrm_msg |
cmp [preboot_vrrm], 1 |
call .say_on_off |
; mov si, preboot_device_msg |
; call print |
; mov al, [preboot_device] |
; and eax, 7 |
; mov si, [preboot_device_msgs+eax*2] |
; call printplain |
.show_remarks: |
; show remarks in gray color |
mov di, ((21-num_remarks)*80 + 2)*2 |
push 0xB800 |
pop es |
mov cx, num_remarks |
mov si, remarks |
.write_remarks: |
lodsw |
push si |
xchg ax, si |
mov ah, 1*16+7 ; background: blue (1), foreground: gray (7) |
push di |
.write_remark: |
lodsb |
test al, al |
jz @f |
stosw |
jmp .write_remark |
@@: |
pop di |
pop si |
add di, 80*2 |
loop .write_remarks |
.wait: |
_setcursor 25,0 ; out of screen |
; set timer interrupt handler |
cli |
push 0 |
pop es |
push dword [es:8*4] |
pop dword [.oldtimer] |
push dword [.timer] |
pop dword [es:8*4] |
; mov eax, [es:8*4] |
; mov [.oldtimer], eax |
; mov eax, [.timer] |
; mov [es:8*4], eax |
sti |
; wait for keypressed |
xor ax, ax |
int 16h |
push ax |
; restore timer interrupt |
; push 0 |
; pop es |
mov eax, [.oldtimer] |
mov [es:8*4], eax |
mov [.timer], eax |
_setcursor 7,0 |
mov si, space_msg |
call printplain |
; clear remarks and restore normal attributes |
push es |
mov di, ((21-num_remarks)*80 + 2)*2 |
push 0xB800 |
pop es |
mov cx, num_remarks |
mov ax, ' ' + (1*16 + 15)*100h |
@@: |
push cx |
mov cx, 76 |
rep stosw |
pop cx |
add di, 4*2 |
loop @b |
pop es |
pop ax |
; switch on key |
cmp al, 13 |
jz .continue |
or al, 20h |
cmp al, 'a' |
jz .change_a |
cmp al, 'b' |
jz .change_b |
cmp al, 'c' |
jnz .show_remarks |
_setcursor 15,0 |
mov si, vrrmprint |
call print |
mov bx, '12' |
call getkey |
mov [preboot_vrrm], al |
_setcursor 12,0 |
.d: |
mov [.bSettingsChanged], 1 |
call clear_vmodes_table ;clear vmodes_table |
jmp .printcfg |
.change_a: |
.loops: |
call draw_vmodes_table |
_setcursor 25,0 ; out of screen |
xor ax, ax |
int 0x16 |
; call clear_table_cursor ;clear current position of cursor |
mov si, word [cursor_pos] |
cmp ah, 0x48;x,0x48E0 ; up |
jne .down |
cmp si, modes_table |
jbe .loops |
sub word [cursor_pos], size_of_step |
jmp .loops |
.down: |
cmp ah, 0x50;x,0x50E0 ; down |
jne .pgup |
cmp word[es:si+10], -1 |
je .loops |
add word [cursor_pos], size_of_step |
jmp .loops |
.pgup: |
cmp ah, 0x49 ; page up |
jne .pgdn |
sub si, size_of_step*long_v_table |
cmp si, modes_table |
jae @f |
mov si, modes_table |
@@: |
mov word [cursor_pos], si |
mov si, word [home_cursor] |
sub si, size_of_step*long_v_table |
cmp si, modes_table |
jae @f |
mov si, modes_table |
@@: |
mov word [home_cursor], si |
jmp .loops |
.pgdn: |
cmp ah, 0x51 ; page down |
jne .enter |
mov ax, [end_cursor] |
add si, size_of_step*long_v_table |
cmp si, ax |
jb @f |
mov si, ax |
sub si, size_of_step |
@@: |
mov word [cursor_pos], si |
mov si, word [home_cursor] |
sub ax, size_of_step*long_v_table |
add si, size_of_step*long_v_table |
cmp si, ax |
jb @f |
mov si, ax |
@@: |
mov word [home_cursor], si |
jmp .loops |
.enter: |
cmp al, 0x0D;x,0x1C0D ; enter |
jne .loops |
push word [cursor_pos] |
pop bp |
push word [es:bp] |
pop word [x_save] |
push word [es:bp+2] |
pop word [y_save] |
push word [es:bp+6] |
pop word [number_vm] |
mov word [preboot_graph], bp ;save choose |
jmp .d |
.change_b: |
_setcursor 15,0 |
; mov si, ask_dma |
; call print |
; mov bx, '13' |
; call getkey |
; mov [preboot_dma], al |
mov si, ask_bd |
call print |
mov bx, '12' |
call getkey |
mov [preboot_biosdisk], al |
_setcursor 11,0 |
jmp .d |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.say_on_off: |
pushf |
call print |
mov si, on_msg |
popf |
jz @f |
mov si, off_msg |
@@: |
jmp printplain |
; novesa and vervesa strings are not used at the moment of executing this code |
virtual at novesa |
.oldtimer dd ? |
.starttime dd ? |
.bSettingsChanged db ? |
.timer dd ? |
end virtual |
.loader_block dd -1 |
.gettime: |
mov ah, 0 |
int 1Ah |
xchg ax, cx |
shl eax, 10h |
xchg ax, dx |
ret |
.newtimer: |
push ds |
push cs |
pop ds |
pushf |
call [.oldtimer] |
pushad |
call .gettime |
sub eax, [.starttime] |
sub ax, 18*5 |
jae .timergo |
neg ax |
add ax, 18-1 |
mov bx, 18 |
xor dx, dx |
div bx |
if lang eq ru |
; ¯®¤®¦¤¨â¥ 5 ᥪã¤, 4/3/2 ᥪã¤ë, 1 ᥪã¤ã |
cmp al, 5 |
mov cl, ' ' |
jae @f |
cmp al, 1 |
mov cl, 'ã' |
jz @f |
mov cl, 'ë' |
@@: |
mov [time_str+9], cl |
else if lang eq et |
cmp al, 1 |
ja @f |
mov [time_str+9], ' ' |
mov [time_str+10], ' ' |
@@: |
else |
; wait 5/4/3/2 seconds, 1 second |
cmp al, 1 |
mov cl, 's' |
ja @f |
mov cl, ' ' |
@@: |
mov [time_str+9], cl |
end if |
add al, '0' |
mov [time_str+1], al |
mov si, time_msg |
_setcursor 7,0 |
call print |
_setcursor 25,0 |
popad |
pop ds |
iret |
.timergo: |
push 0 |
pop es |
mov eax, [.oldtimer] |
mov [es:8*4], eax |
mov sp, 0EC00h |
.continue: |
sti |
_setcursor 6,0 |
mov si, space_msg |
call printplain |
call printplain |
_setcursor 6,0 |
mov si, loading_msg |
call print |
_setcursor 15,0 |
cmp [.bSettingsChanged], 0 |
jz .load |
cmp [.loader_block], -1 |
jz .load |
les bx, [.loader_block] |
mov eax, [es:bx+3] |
push ds |
pop es |
test eax, eax |
jz .load |
push eax |
mov si, save_quest |
call print |
.waityn: |
mov ah, 0 |
int 16h |
or al, 20h |
cmp al, 'n' |
jz .loadc |
cmp al, 'y' |
jnz .waityn |
call putchar |
mov byte [space_msg+80], 186 |
pop eax |
push cs |
push .cont |
push eax |
retf |
.loadc: |
pop eax |
.cont: |
push cs |
pop ds |
mov si, space_msg |
mov byte [si+80], 0 |
_setcursor 15,0 |
call printplain |
_setcursor 15,0 |
.load: |
; \end{diamond}[02.12.2005] |
; ASK GRAPHICS MODE |
call set_vmode |
; GRAPHICS ACCELERATION |
; force yes |
mov [es:0x901C], byte 1 |
; DMA ACCESS TO HD |
mov al, [preboot_dma] |
mov [es:0x901F], al |
; VRR_M USE |
mov al, [preboot_vrrm] |
mov [es:0x9030], al |
mov [es:0x901E], byte 1 |
; BOOT DEVICE |
mov al, [preboot_device] |
dec al |
mov [boot_dev], al |
;;;;;;;;;;; set videomode |
xor ax, ax |
mov es, ax |
mov ax, [es:0x9008] ; vga & 320x200 |
mov bx, ax |
cmp ax, 0x13 |
je setgr |
cmp ax, 0x12 |
je setgr |
mov ax, 0x4f02 ; Vesa |
setgr: |
int 0x10 |
test ah, ah |
mov si, fatalsel |
jnz v_mode_error |
; set mode 0x12 graphics registers: |
cmp bx, 0x12 |
jne gmok2 |
mov al, 0x05 |
mov dx, 0x03ce |
push dx |
out dx, al ; select GDC mode register |
mov al, 0x02 |
inc dx |
out dx, al ; set write mode 2 |
mov al, 0x02 |
mov dx, 0x03c4 |
out dx, al ; select VGA sequencer map mask register |
mov al, 0x0f |
inc dx |
out dx, al ; set mask for all planes 0-3 |
mov al, 0x08 |
pop dx |
out dx, al ; select GDC bit mask register |
; for writes to 0x03cf |
gmok2: |
push ds |
pop es |
jmp $ |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;data |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include "lang.inc" |
include "bootstr.inc" ; language-independent boot messages |
;if lang eq en |
;include "booteng.inc" ; english system boot messages |
;else if lang eq ru |
include "bootru.inc" ; russian system boot messages |
include "ru.inc" ; Russian font |
;else if lang eq et |
;include "bootet.inc" ; estonian system boot messages |
;include "et.inc" ; Estonian font |
;else |
;include "bootge.inc" ; german system boot messages |
;end if |
include 'macros.inc' |
include 'bootvesa.inc' |
include "preboot.inc" |
setcursor: |
; in: dl=column, dh=row |
mov ah, 2 |
mov bh, 0 |
int 10h |
ret |
putchar: |
; in: al=character |
mov ah, 0Eh |
mov bh, 0 |
int 10h |
ret |
print: |
; in: si->string |
mov al, 186 |
call putchar |
mov al, ' ' |
call putchar |
printplain: |
; in: si->string |
pusha |
lodsb |
@@: |
call putchar |
lodsb |
cmp al, 0 |
jnz @b |
popa |
ret |
getkey: |
; get number in range [bl,bh] (bl,bh in ['0'..'9']) |
; in: bx=range |
; out: ax=digit (1..9, 10 for 0) |
mov ah, 0 |
int 16h |
cmp al, bl |
jb getkey |
cmp al, bh |
ja getkey |
push ax |
call putchar |
pop ax |
and ax, 0Fh |
jnz @f |
mov al, 10 |
@@: |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/macros.inc |
---|
1,86 → 1,86 |
; structure definition helper |
macro struct name, [arg] |
{ |
common |
name@struct equ name |
struc name arg { |
} |
macro struct_helper name |
{ |
match xname,name |
\{ |
virtual at 0 |
xname xname |
sizeof.#xname = $ - xname |
name equ sizeof.#xname |
end virtual |
\} |
} |
ends fix } struct_helper name@struct |
;// mike.dld, 2006-29-01 [ |
; macros definition |
macro diff16 title,l1,l2 |
{ |
local s,d |
s = l2-l1 |
display title,': 0x' |
repeat 16 |
d = 48 + s shr ((16-%) shl 2) and $0F |
if d > 57 |
d = d + 65-57-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
macro diff10 title,l1,l2 |
{ |
local s,d,z,m |
s = l2-l1 |
z = 0 |
m = 1000000000 |
display title,': ' |
repeat 10 |
d = '0' + s / m |
s = s - (s/m)*m |
m = m / 10 |
if d <> '0' |
z = 1 |
end if |
if z <> 0 |
display d |
end if |
end repeat |
display 13,10 |
} |
; \begin{diamond}[29.09.2006] |
; may be useful for kernel debugging |
; example 1: |
; dbgstr 'Hello, World!' |
; example 2: |
; dbgstr 'Hello, World!', save_flags |
macro dbgstr string*, f |
{ |
local a |
iglobal_nested |
a db 'K : ',string,13,10,0 |
endg_nested |
if ~ f eq |
pushfd |
end if |
push esi |
mov esi, a |
call sys_msg_board_str |
pop esi |
if ~ f eq |
popfd |
end if |
} |
; \end{diamond}[29.09.2006] |
; structure definition helper |
macro struct name, [arg] |
{ |
common |
name@struct equ name |
struc name arg { |
} |
macro struct_helper name |
{ |
match xname,name |
\{ |
virtual at 0 |
xname xname |
sizeof.#xname = $ - xname |
name equ sizeof.#xname |
end virtual |
\} |
} |
ends fix } struct_helper name@struct |
;// mike.dld, 2006-29-01 [ |
; macros definition |
macro diff16 title,l1,l2 |
{ |
local s,d |
s = l2-l1 |
display title,': 0x' |
repeat 16 |
d = 48 + s shr ((16-%) shl 2) and $0F |
if d > 57 |
d = d + 65-57-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
macro diff10 title,l1,l2 |
{ |
local s,d,z,m |
s = l2-l1 |
z = 0 |
m = 1000000000 |
display title,': ' |
repeat 10 |
d = '0' + s / m |
s = s - (s/m)*m |
m = m / 10 |
if d <> '0' |
z = 1 |
end if |
if z <> 0 |
display d |
end if |
end repeat |
display 13,10 |
} |
; \begin{diamond}[29.09.2006] |
; may be useful for kernel debugging |
; example 1: |
; dbgstr 'Hello, World!' |
; example 2: |
; dbgstr 'Hello, World!', save_flags |
macro dbgstr string*, f |
{ |
local a |
iglobal_nested |
a db 'K : ',string,13,10,0 |
endg_nested |
if ~ f eq |
pushfd |
end if |
push esi |
mov esi, a |
call sys_msg_board_str |
pop esi |
if ~ f eq |
popfd |
end if |
} |
; \end{diamond}[29.09.2006] |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/preboot.inc |
---|
1,36 → 1,36 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
display_modechg db 0 ; display mode change for text, yes/no (0 or 2) |
; |
; !! Important note !! |
; |
; Must be set to 2, to avoid two screenmode |
; changes within a very short period of time. |
display_atboot db 0 ; show boot screen messages ( 2-no ) |
preboot_graph dw 0 ; graph mode |
x_save dw 0 ; x |
y_save dw 0 ; y |
number_vm dw 0 ; |
;pixel_save dw 0 ; per to pixel |
preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) |
preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) |
preboot_dma db 0 ; use DMA for access to HDD (1-always, 2-only for read, 3-never) |
preboot_device db 0 ; boot device |
; (1-floppy 2-harddisk 3-kernel restart 4-format ram disk) |
;!!!! 0 - autodetect !!!! |
preboot_blogesc = 0 ; start immediately after bootlog |
preboot_biosdisk db 0 ; use V86 to access disks through BIOS (1-yes, 2-no) |
; if $>0x200 |
;ERROR: prebooting parameters must fit in first sector!!! |
; end if |
;hdsysimage db 'KOLIBRI IMG' ; load from |
;image_save db 'KOLIBRI IMG' ; save to |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
display_modechg db 0 ; display mode change for text, yes/no (0 or 2) |
; |
; !! Important note !! |
; |
; Must be set to 2, to avoid two screenmode |
; changes within a very short period of time. |
display_atboot db 0 ; show boot screen messages ( 2-no ) |
preboot_graph dw 0 ; graph mode |
x_save dw 0 ; x |
y_save dw 0 ; y |
number_vm dw 0 ; |
;pixel_save dw 0 ; per to pixel |
preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) |
preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) |
preboot_dma db 0 ; use DMA for access to HDD (1-always, 2-only for read, 3-never) |
preboot_device db 0 ; boot device |
; (1-floppy 2-harddisk 3-kernel restart 4-format ram disk) |
;!!!! 0 - autodetect !!!! |
preboot_blogesc = 0 ; start immediately after bootlog |
preboot_biosdisk db 0 ; use V86 to access disks through BIOS (1-yes, 2-no) |
; if $>0x200 |
;ERROR: prebooting parameters must fit in first sector!!! |
; end if |
;hdsysimage db 'KOLIBRI IMG' ; load from |
;image_save db 'KOLIBRI IMG' ; save to |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/rdload.inc |
---|
1,123 → 1,123 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; READ RAMDISK IMAGE FROM HD |
cmp [boot_dev+OS_BASE+0x10000],1 |
jne no_sys_on_hd |
test [DRIVE_DATA+1],byte 0x40 |
jz position_2 |
mov [hdbase],0x1f0 |
mov [hdid],0x0 |
mov [hdpos],1 |
mov [fat32part],0 |
position_1_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved],1 |
je yes_sys_on_hd |
movzx eax,byte [DRIVE_DATA+2] |
cmp [fat32part],eax |
jle position_1_1 |
position_2: |
test [DRIVE_DATA+1],byte 0x10 |
jz position_3 |
mov [hdbase],0x1f0 |
mov [hdid],0x10 |
mov [hdpos],2 |
mov [fat32part],0 |
position_2_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved],1 |
je yes_sys_on_hd |
movzx eax,byte [DRIVE_DATA+3] |
cmp eax,[fat32part] |
jle position_2_1 |
position_3: |
test [DRIVE_DATA+1],byte 0x4 |
jz position_4 |
mov [hdbase],0x170 |
mov [hdid],0x0 |
mov [hdpos],3 |
mov [fat32part],0 |
position_3_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved],1 |
je yes_sys_on_hd |
movzx eax,byte [DRIVE_DATA+4] |
cmp eax,[fat32part] |
jle position_3_1 |
position_4: |
test [DRIVE_DATA+1],byte 0x1 |
jz no_sys_on_hd |
mov [hdbase],0x170 |
mov [hdid],0x10 |
mov [hdpos],4 |
mov [fat32part],0 |
position_4_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved],1 |
je yes_sys_on_hd |
movzx eax,byte [DRIVE_DATA+5] |
cmp eax,[fat32part] |
jle position_4_1 |
jmp yes_sys_on_hd |
search_and_read_image: |
call set_FAT32_variables |
mov edx, bootpath |
call read_image |
test eax, eax |
jz image_present |
mov edx, bootpath2 |
call read_image |
test eax, eax |
jz image_present |
ret |
image_present: |
mov [image_retrieved],1 |
ret |
read_image: |
mov eax, hdsysimage+OS_BASE+0x10000 |
mov ebx, 1474560/512 |
mov ecx, RAMDISK |
mov esi, 0 |
mov edi, 12 |
call file_read |
ret |
image_retrieved db 0 |
counter_of_partitions db 0 |
no_sys_on_hd: |
; test_to_format_ram_disk (need if not using ram disk) |
cmp [boot_dev+OS_BASE+0x10000],3 |
jne not_format_ram_disk |
; format_ram_disk |
mov edi, RAMDISK |
mov ecx, 0x1080 |
xor eax,eax |
@@: |
stosd |
loop @b |
mov ecx, 0x58F7F |
mov eax,0xF6F6F6F6 |
@@: |
stosd |
loop @b |
mov [RAMDISK+0x200],dword 0xFFFFF0 ; fat table |
mov [RAMDISK+0x4200],dword 0xFFFFF0 |
not_format_ram_disk: |
yes_sys_on_hd: |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; READ RAMDISK IMAGE FROM HD |
cmp [boot_dev+OS_BASE+0x10000], 1 |
jne no_sys_on_hd |
test [DRIVE_DATA+1], byte 0x40 |
jz position_2 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x0 |
mov [hdpos], 1 |
mov [fat32part], 0 |
position_1_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved], 1 |
je yes_sys_on_hd |
movzx eax, byte [DRIVE_DATA+2] |
cmp [fat32part], eax |
jle position_1_1 |
position_2: |
test [DRIVE_DATA+1], byte 0x10 |
jz position_3 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x10 |
mov [hdpos], 2 |
mov [fat32part], 0 |
position_2_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved], 1 |
je yes_sys_on_hd |
movzx eax, byte [DRIVE_DATA+3] |
cmp eax, [fat32part] |
jle position_2_1 |
position_3: |
test [DRIVE_DATA+1], byte 0x4 |
jz position_4 |
mov [hdbase], 0x170 |
mov [hdid], 0x0 |
mov [hdpos], 3 |
mov [fat32part], 0 |
position_3_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved], 1 |
je yes_sys_on_hd |
movzx eax, byte [DRIVE_DATA+4] |
cmp eax, [fat32part] |
jle position_3_1 |
position_4: |
test [DRIVE_DATA+1], byte 0x1 |
jz no_sys_on_hd |
mov [hdbase], 0x170 |
mov [hdid], 0x10 |
mov [hdpos], 4 |
mov [fat32part], 0 |
position_4_1: |
inc [fat32part] |
call search_and_read_image |
cmp [image_retrieved], 1 |
je yes_sys_on_hd |
movzx eax, byte [DRIVE_DATA+5] |
cmp eax, [fat32part] |
jle position_4_1 |
jmp yes_sys_on_hd |
search_and_read_image: |
call set_FAT32_variables |
mov edx, bootpath |
call read_image |
test eax, eax |
jz image_present |
mov edx, bootpath2 |
call read_image |
test eax, eax |
jz image_present |
ret |
image_present: |
mov [image_retrieved], 1 |
ret |
read_image: |
mov eax, hdsysimage+OS_BASE+0x10000 |
mov ebx, 1474560/512 |
mov ecx, RAMDISK |
mov esi, 0 |
mov edi, 12 |
call file_read |
ret |
image_retrieved db 0 |
counter_of_partitions db 0 |
no_sys_on_hd: |
; test_to_format_ram_disk (need if not using ram disk) |
cmp [boot_dev+OS_BASE+0x10000], 3 |
jne not_format_ram_disk |
; format_ram_disk |
mov edi, RAMDISK |
mov ecx, 0x1080 |
xor eax, eax |
@@: |
stosd |
loop @b |
mov ecx, 0x58F7F |
mov eax, 0xF6F6F6F6 |
@@: |
stosd |
loop @b |
mov [RAMDISK+0x200], dword 0xFFFFF0 ; fat table |
mov [RAMDISK+0x4200], dword 0xFFFFF0 |
not_format_ram_disk: |
yes_sys_on_hd: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/ru.inc |
---|
1,100 → 1,100 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Generated by RUFNT.EXE |
; By BadBugsKiller (C) |
; Modifyed by BadBugsKiller 12.01.2004 17:45 |
; Øðèôò óìåíüøåí â ðàçìåðå è òåïåðü ñîñòîèò èç 2-óõ ÷àñòåé, |
; ñîäåðæàùèõ òîëüêî ñèìâîëû ðóññêîãî àëôàâèòà. |
; ñèìâîëû â êîäèðîâêå ASCII (ÄÎÑ'îâñêàÿ), êîäîâàÿ ñòðàíèöà 866. |
RU_FNT1: |
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
RU_FNT2: |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 |
db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 |
db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Generated by RUFNT.EXE |
; By BadBugsKiller (C) |
; Modifyed by BadBugsKiller 12.01.2004 17:45 |
; Øðèôò óìåíüøåí â ðàçìåðå è òåïåðü ñîñòîèò èç 2-óõ ÷àñòåé, |
; ñîäåðæàùèõ òîëüêî ñèìâîëû ðóññêîãî àëôàâèòà. |
; ñèìâîëû â êîäèðîâêå ASCII (ÄÎÑ'îâñêàÿ), êîäîâàÿ ñòðàíèöà 866. |
RU_FNT1: |
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 |
RU_FNT2: |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 |
db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 |
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 |
db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00 |
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/kolibri_ldm/shutdown.inc |
---|
1,207 → 1,207 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Shutdown for Menuet ;; |
;; ;; |
;; Distributed under General Public License ;; |
;; See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
pr_mode_exit: |
; setup stack |
mov ax, 0x3000 |
mov ss, ax |
mov esp, 0x0EC00 |
; setup ds |
push cs |
pop ds |
lidt [old_ints_h] |
;remap IRQs |
mov al,0x11 |
out 0x20,al |
call rdelay |
out 0xA0,al |
call rdelay |
mov al,0x08 |
out 0x21,al |
call rdelay |
mov al,0x70 |
out 0xA1,al |
call rdelay |
mov al,0x04 |
out 0x21,al |
call rdelay |
mov al,0x02 |
out 0xA1,al |
call rdelay |
mov al,0x01 |
out 0x21,al |
call rdelay |
out 0xA1,al |
call rdelay |
mov al,0xB8 |
out 0x21,al |
call rdelay |
mov al,0xBD |
out 0xA1,al |
sti |
temp_3456: |
xor ax,ax |
mov es,ax |
mov al,byte [es:0x9030] |
cmp al,1 |
jl nbw |
cmp al,4 |
jle nbw32 |
nbw: |
in al,0x60 |
cmp al,6 |
jae nbw |
mov bl,al |
nbw2: |
in al,0x60 |
cmp al,bl |
je nbw2 |
cmp al,240 ;ax,240 |
jne nbw31 |
mov al,bl |
dec ax |
jmp nbw32 |
nbw31: |
add bl,128 |
cmp al,bl |
jne nbw |
sub al,129 |
nbw32: |
dec ax |
dec ax ; 2 = power off |
jnz no_apm_off |
call APM_PowerOff |
jmp $ |
no_apm_off: |
dec ax ; 3 = reboot |
jnz restart_kernel ; 4 = restart kernel |
push 0x40 |
pop ds |
mov word[0x0072],0x1234 |
jmp 0xF000:0xFFF0 |
rdelay: |
ret |
APM_PowerOff: |
mov ax, 5304h |
xor bx, bx |
int 15h |
;!!!!!!!!!!!!!!!!!!!!!!!! |
mov ax,0x5300 |
xor bx,bx |
int 0x15 |
push ax |
mov ax,0x5301 |
xor bx,bx |
int 0x15 |
mov ax,0x5308 |
mov bx,1 |
mov cx,bx |
int 0x15 |
mov ax,0x530E |
xor bx,bx |
pop cx |
int 0x15 |
mov ax,0x530D |
mov bx,1 |
mov cx,bx |
int 0x15 |
mov ax,0x530F |
mov bx,1 |
mov cx,bx |
int 0x15 |
mov ax,0x5307 |
mov bx,1 |
mov cx,3 |
int 0x15 |
;!!!!!!!!!!!!!!!!!!!!!!!! |
ret |
restart_kernel: |
mov ax,0x0003 ; set text mode for screen |
int 0x10 |
jmp 0x4000:0000 |
restart_kernel_4000: |
cli |
push ds |
pop es |
mov cx, 0x8000 |
push cx |
push 0x7000 |
pop ds |
xor si, si |
xor di, di |
rep movsw |
pop cx |
mov ds, cx |
push 0x2000 |
pop es |
rep movsw |
push 0x9000 |
pop ds |
push 0x3000 |
pop es |
mov cx, 0xE000/2 |
rep movsw |
wbinvd ; write and invalidate cache |
mov al, 00110100b |
out 43h, al |
jcxz $+2 |
mov al, 0xFF |
out 40h, al |
jcxz $+2 |
out 40h, al |
jcxz $+2 |
sti |
; (hint by Black_mirror) |
; We must read data from keyboard port, |
; because there may be situation when previous keyboard interrupt is lost |
; (due to return to real mode and IRQ reprogramming) |
; and next interrupt will not be generated (as keyboard waits for handling) |
in al, 0x60 |
; bootloader interface |
push 0x1000 |
pop ds |
mov si, kernel_restart_bootblock |
mov ax, 'KL' |
jmp 0x1000:0000 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Shutdown for Menuet ;; |
;; ;; |
;; Distributed under General Public License ;; |
;; See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
pr_mode_exit: |
; setup stack |
mov ax, 0x3000 |
mov ss, ax |
mov esp, 0x0EC00 |
; setup ds |
push cs |
pop ds |
lidt [old_ints_h] |
;remap IRQs |
mov al, 0x11 |
out 0x20, al |
call rdelay |
out 0xA0, al |
call rdelay |
mov al, 0x08 |
out 0x21, al |
call rdelay |
mov al, 0x70 |
out 0xA1, al |
call rdelay |
mov al, 0x04 |
out 0x21, al |
call rdelay |
mov al, 0x02 |
out 0xA1, al |
call rdelay |
mov al, 0x01 |
out 0x21, al |
call rdelay |
out 0xA1, al |
call rdelay |
mov al, 0xB8 |
out 0x21, al |
call rdelay |
mov al, 0xBD |
out 0xA1, al |
sti |
temp_3456: |
xor ax, ax |
mov es, ax |
mov al, byte [es:0x9030] |
cmp al, 1 |
jl nbw |
cmp al, 4 |
jle nbw32 |
nbw: |
in al, 0x60 |
cmp al, 6 |
jae nbw |
mov bl, al |
nbw2: |
in al, 0x60 |
cmp al, bl |
je nbw2 |
cmp al, 240;ax,240 |
jne nbw31 |
mov al, bl |
dec ax |
jmp nbw32 |
nbw31: |
add bl, 128 |
cmp al, bl |
jne nbw |
sub al, 129 |
nbw32: |
dec ax |
dec ax ; 2 = power off |
jnz no_apm_off |
call APM_PowerOff |
jmp $ |
no_apm_off: |
dec ax ; 3 = reboot |
jnz restart_kernel ; 4 = restart kernel |
push 0x40 |
pop ds |
mov word[0x0072], 0x1234 |
jmp 0xF000:0xFFF0 |
rdelay: |
ret |
APM_PowerOff: |
mov ax, 5304h |
xor bx, bx |
int 15h |
;!!!!!!!!!!!!!!!!!!!!!!!! |
mov ax, 0x5300 |
xor bx, bx |
int 0x15 |
push ax |
mov ax, 0x5301 |
xor bx, bx |
int 0x15 |
mov ax, 0x5308 |
mov bx, 1 |
mov cx, bx |
int 0x15 |
mov ax, 0x530E |
xor bx, bx |
pop cx |
int 0x15 |
mov ax, 0x530D |
mov bx, 1 |
mov cx, bx |
int 0x15 |
mov ax, 0x530F |
mov bx, 1 |
mov cx, bx |
int 0x15 |
mov ax, 0x5307 |
mov bx, 1 |
mov cx, 3 |
int 0x15 |
;!!!!!!!!!!!!!!!!!!!!!!!! |
ret |
restart_kernel: |
mov ax, 0x0003 ; set text mode for screen |
int 0x10 |
jmp 0x4000:0000 |
restart_kernel_4000: |
cli |
push ds |
pop es |
mov cx, 0x8000 |
push cx |
push 0x7000 |
pop ds |
xor si, si |
xor di, di |
rep movsw |
pop cx |
mov ds, cx |
push 0x2000 |
pop es |
rep movsw |
push 0x9000 |
pop ds |
push 0x3000 |
pop es |
mov cx, 0xE000/2 |
rep movsw |
wbinvd ; write and invalidate cache |
mov al, 00110100b |
out 43h, al |
jcxz $+2 |
mov al, 0xFF |
out 40h, al |
jcxz $+2 |
out 40h, al |
jcxz $+2 |
sti |
; (hint by Black_mirror) |
; We must read data from keyboard port, |
; because there may be situation when previous keyboard interrupt is lost |
; (due to return to real mode and IRQ reprogramming) |
; and next interrupt will not be generated (as keyboard waits for handling) |
in al, 0x60 |
; bootloader interface |
push 0x1000 |
pop ds |
mov si, kernel_restart_bootblock |
mov ax, 'KL' |
jmp 0x1000:0000 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/listing.inc |
---|
1,635 → 1,635 |
; Listing generator |
; LocoDelAssembly 2007.06.01 |
INSTRUCTIONS equ bt in ja jb jc je jg jl jo jp js jz or \ |
aaa aad aam aas adc add and bsf bsr btc btr bts cbw cdq clc \ |
cld cli cmc cmp cqo cwd daa das dec div fld fst hlt inc ins \ |
int jae jbe jge jle jmp jna jnb jnc jne jng jnl jno jnp jns \ |
jnz jpe jpo lar lds lea les lfs lgs lsl lss ltr mov mul neg \ |
nop not out pop por rcl rcr ret rol ror rsm sal sar sbb shl \ |
shr stc std sti str sub ud2 xor \ |
arpl call cdqe clgi clts cmps cwde emms fabs fadd fbld fchs \ |
fcom fcos fdiv feni fild fist fld1 fldz fmul fnop fsin fstp \ |
fsub ftst fxam fxch idiv imul insb insd insw int1 int3 into \ |
invd iret jcxz jnae jnbe jnge jnle lahf lgdt lidt lldt lmsw \ |
lods loop movd movq movs orpd orps outs pand popa popd popf \ |
popq popw push pxor retd retf retn retq retw sahf salc scas \ |
seta setb setc sete setg setl seto setp sets setz sgdt shld \ |
shrd sidt sldt smsw stgi stos test verr verw wait xadd xchg \ |
xlat \ |
addpd addps addsd addss andpd andps bound bswap cmova cmovb \ |
cmovc cmove cmovg cmovl cmovo cmovp cmovs cmovz cmppd cmpps \ |
cmpsb cmpsd cmpsq cmpss cmpsw cpuid divpd divps divsd divss \ |
enter f2xm1 faddp fbstp fclex fcomi fcomp fdisi fdivp fdivr \ |
femms ffree fiadd ficom fidiv fimul finit fistp fisub fldcw \ |
fldpi fmulp fneni fprem fptan fsave fsqrt fstcw fstsw fsubp \ |
fsubr fucom fwait fyl2x icebp iretd iretq iretw jecxz jrcxz \ |
lddqu leave lodsb lodsd lodsq lodsw loopd loope loopq loopw \ |
loopz maxpd maxps maxsd maxss minpd minps minsd minss movsb \ |
movsd movsq movss movsw movsx movzx mulpd mulps mulsd mulss \ |
mwait outsb outsd outsw pabsb pabsd pabsw paddb paddd paddq \ |
paddw pandn pause pavgb pavgw pf2id pf2iw pfacc pfadd pfmax \ |
pfmin pfmul pfrcp pfsub pi2fd pi2fw popad popaw popfd popfq \ |
popfw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb \ |
psubd psubq psubw pusha pushd pushf pushq pushw rcpps rcpss \ |
rdmsr rdpmc rdtsc retfd retfq retfw retnd retnq retnw scasb \ |
scasd scasq scasw setae setbe setge setle setna setnb setnc \ |
setne setng setnl setno setnp setns setnz setpe setpo stosb \ |
stosd stosq stosw subpd subps subsd subss vmrun vmxon wrmsr \ |
xlatb xorpd xorps \ |
andnpd andnps cmovae cmovbe cmovge cmovle cmovna cmovnb cmovnc\ |
cmovne cmovng cmovnl cmovno cmovnp cmovns cmovnz cmovpe cmovpo\ |
comisd comiss fcmovb fcmove fcmovu fcomip fcompp fdivrp ffreep\ |
ficomp fidivr fisttp fisubr fldenv fldl2e fldl2t fldlg2 fldln2\ |
fnclex fndisi fninit fnsave fnstcw fnstsw fpatan fprem1 frstor\ |
frstpm fscale fsetpm fstenv fsubrp fucomi fucomp fxsave haddpd\ |
haddps hsubpd hsubps invlpg lfence looped loopeq loopew loopne\ |
loopnz loopzd loopzq loopzw mfence movapd movaps movdqa movdqu\ |
movhpd movhps movlpd movlps movnti movntq movsxd movupd movups\ |
paddsb paddsw pextrw pfnacc pfsubr phaddd phaddw phsubd phsubw\ |
pinsrw pmaxsw pmaxub pminsw pminub pmulhw pmullw psadbw pshufb\ |
pshufd pshufw psignb psignd psignw pslldq psrldq psubsb psubsw\ |
pswapd pushad pushaw pushfd pushfq pushfw rdmsrq rdtscp setalc\ |
setnae setnbe setnge setnle sfence shufpd shufps skinit sqrtpd\ |
sqrtps sqrtsd sqrtss swapgs sysret vmcall vmload vmread vmsave\ |
vmxoff wbinvd wrmsrq \ |
clflush cmovnae cmovnbe cmovnge cmovnle cmpeqpd cmpeqps \ |
cmpeqsd cmpeqss cmplepd cmpleps cmplesd cmpless cmpltpd \ |
cmpltps cmpltsd cmpltss cmpxchg fcmovbe fcmovnb fcmovne \ |
fcmovnu fdecstp fincstp fnstenv frndint fsincos fucomip \ |
fucompp fxrstor fxtract fyl2xp1 invlpga ldmxcsr loopned \ |
loopneq loopnew loopnzd loopnzq loopnzw monitor movddup \ |
movdq2q movhlps movlhps movntdq movntpd movntps movq2dq \ |
paddusb paddusw palignr pavgusb pcmpeqb pcmpeqd pcmpeqw \ |
pcmpgtb pcmpgtd pcmpgtw pfcmpeq pfcmpge pfcmpgt pfpnacc \ |
pfrsqrt phaddsw phsubsw pmaddwd pmulhrw pmulhuw pmuludq \ |
pshufhw pshuflw psubusb psubusw rsqrtps rsqrtss stmxcsr \ |
syscall sysexit sysretq ucomisd ucomiss vmclear vmmcall \ |
vmptrld vmptrst vmwrite \ |
addsubpd addsubps cmpneqpd cmpneqps cmpneqsd cmpneqss cmpnlepd\ |
cmpnleps cmpnlesd cmpnless cmpnltpd cmpnltps cmpnltsd cmpnltss\ |
cmpordpd cmpordps cmpordsd cmpordss cvtdq2pd cvtdq2ps cvtpd2dq\ |
cvtpd2pi cvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq cvtps2pd cvtps2pi\ |
cvtsd2si cvtsd2ss cvtsi2sd cvtsi2ss cvtss2sd cvtss2si fcmovnbe\ |
maskmovq movmskpd movmskps movshdup movsldup packssdw packsswb\ |
packuswb pfrcpit1 pfrcpit2 pfrsqit1 pmovmskb pmulhrsw prefetch\ |
sysenter sysexitq unpckhpd unpckhps unpcklpd unpcklps vmlaunch\ |
vmresume \ |
cmpxchg8b cvttpd2dq cvttpd2pi cvttps2dq cvttps2pi cvttsd2si \ |
cvttss2si pmaddubsw prefetchw punpckhbw punpckhdq punpckhwd \ |
punpcklbw punpckldq punpcklwd \ |
cmpunordpd cmpunordps cmpunordsd cmpunordss cmpxchg16b \ |
loadall286 loadall386 maskmovdqu prefetcht0 prefetcht1 \ |
prefetcht2 punpckhqdq punpcklqdq prefetchnta |
PREFIXES equ rep lock repe repz repne repnz |
DATA_DEFINITORS equ db dw du dd dp df dq dt file |
DATA_RESERVERS equ rb rw rd rp rf rq rt |
CRLF equ 13, 10 ; Remove 13 for Linux |
MAX_BYTES equ 13 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MODE MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro use16 |
{ |
use16 |
_USE = 16 |
} |
macro use32 |
{ |
use32 |
_USE = 32 |
} |
macro use64 |
{ |
use64 |
_USE = 64 |
} |
macro detect_mode |
{ |
local aux |
_USE = 32 |
virtual at 0 |
xchg eax, eax |
load aux byte from 0 |
if aux = $66 |
_USE = 16 |
else if aux = $87 |
_USE = 64 |
end if |
end virtual |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISPLAYING MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro display_address address* |
{ |
local aux, digit |
aux = address |
repeat _USE / 4 |
digit = aux shr (_USE - 4 * %) and $F |
display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F |
end repeat |
display ': ' |
} |
macro display_bytes pointer |
{ |
local aux, size, digit |
size = $ - pointer |
if size > MAX_BYTES |
size = MAX_BYTES |
end if |
repeat size |
load aux byte from pointer+%-1 |
digit = aux shr 4 |
display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F |
digit = aux and $F |
display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F |
display ' ' |
end repeat |
repeat MAX_BYTES - size |
display ' ' |
end repeat |
} |
; The macro below in some situations doesn't adds a space to separate things unfortunatelly, so for readability ensurance |
; another one will be used instead... |
;macro display_args [args] |
;{ |
;common |
; aux = 1 |
; |
;forward |
; if ~args eq |
; if aux |
; display ' ' |
; else |
; display ', ' |
; end if |
; |
; aux = 0 |
; |
; match =ON, _RESOLVE_EQUATES |
; \{ |
; match args, args |
; \\{ |
; irps arg, args |
; \\\{ |
; display \\\`arg |
; \\\} |
; \\} |
; \} |
; match =OFF, _RESOLVE_EQUATES |
; \{ |
; irps arg, args |
; \\{ |
; display \\`arg |
; \\} |
; |
; \} |
; end if |
;} |
; This one separates everything with one space. A very ugly listing but at least you will not see things |
; like "push ebxesiedi" nor "ret word0" |
macro display_args [args] |
{ |
common |
aux = 1 |
forward |
if ~args eq |
if ~aux |
display ',' |
end if |
aux = 0 |
match =ON, _RESOLVE_EQUATES |
\{ |
match args, args |
\\{ |
if ~args eqtype "" |
irps arg, args |
\\\{ |
display ' ', \\\`arg |
\\\} |
else |
display " '", args, "'" |
end if |
\\} |
\} |
match =OFF, _RESOLVE_EQUATES |
\{ |
if ~args eqtype "" |
irps arg, args |
\\{ |
display ' ', \\`arg |
\\} |
else |
display " '", args, "'" |
end if |
\} |
end if |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;; INSTRUCTIONS & PREFIXES MACROSES ;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro prefix mnemonic |
{ |
local aux |
macro mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
mnemonic |
match =1, _LISTING |
\\{ |
display_bytes aux |
display \`mnemonic |
display CRLF |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
def_prefix mnemonic |
args |
purge mnemonic |
\} |
} |
macro def_prefix mnemonic |
{ |
macro def_prefix mnemonic |
\{ |
prefix mnemonic |
\} |
def_prefix mnemonic |
} |
macro instruction mnemonic |
{ |
local aux |
macro mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
mnemonic args |
match =1, _LISTING |
\\{ |
display_bytes aux |
display \`mnemonic |
virtual at 0 |
db \`mnemonic |
repeat 11 - $ |
display ' ' |
end repeat |
end virtual |
display_args args |
display CRLF |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro data_define mnemonic |
{ |
local aux |
macro mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
mnemonic args |
match =1, _LISTING |
\\{ |
display_bytes aux |
display \`mnemonic |
display_args args |
display CRLF |
aux = aux + MAX_BYTES |
repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES |
display_address aux |
display_bytes aux |
display CRLF |
aux = aux + MAX_BYTES |
end repeat |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
struc mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
. mnemonic args |
match =1, _LISTING |
\\{ |
display_bytes aux |
display \`., ' ', \`mnemonic |
display_args args |
display CRLF |
aux = aux + MAX_BYTES |
repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES |
display_address aux |
display_bytes aux |
display CRLF |
aux = aux + MAX_BYTES |
end repeat |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
} |
macro data_reserve mnemonic |
{ |
local aux |
macro mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
mnemonic args |
match =1, _LISTING |
\\{ |
times MAX_BYTES display ' ' |
display \`mnemonic |
display_args args |
display CRLF |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
struc mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
. mnemonic args |
match =1, _LISTING |
\\{ |
times MAX_BYTES display ' ' |
display \`., ' ', \`mnemonic |
display_args args |
display CRLF |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; LISTING CONTROL MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro virtual [args] |
{ |
common |
_ON_VIRTUAL equ 1 |
virtual args |
} |
macro end [args] |
{ |
common |
match =virtual, args\{restore _ON_VIRTUAL\} |
end args |
} |
macro enable_listing |
{ |
detect_mode |
match =0, _MACROSES_INSTALLED |
\{ |
match instructions, INSTRUCTIONS |
\\{ |
irps ins, instructions |
\\\{ |
instruction ins |
\\\} |
\\} |
match prefixes, PREFIXES |
\\{ |
irps prefix, prefixes |
\\\{ |
def_prefix prefix |
\\\} |
\\} |
match data_definitors, DATA_DEFINITORS |
\\{ |
irps def, data_definitors |
\\\{ |
data_define def |
\\\} |
\\} |
match data_reservers, DATA_RESERVERS |
\\{ |
irps def, data_reservers |
\\\{ |
data_reserve def |
\\\} |
\\} |
\} |
_MACROSES_INSTALLED equ 1 |
_LISTING equ 1 |
} |
macro disable_listing |
{ |
_LISTING equ 0 |
} |
macro enable [feature*] |
{ |
forward |
UNKNOWN equ 1 |
match =resolve_equates, feature |
\{ |
restore _RESOLVE_EQUATES |
_RESOLVE_EQUATES equ ON |
UNKNOWN equ 0 |
\} |
match =listing, feature |
\{ |
enable_listing |
UNKNOWN equ 0 |
\} |
match =1, UNKNOWN |
\{ |
display 'ERROR: Unknown "',`feature, '" feature', 13, 10 |
err |
\} |
restore UNKNOWN |
restore UNKNOWN |
} |
macro disable [feature*] |
{ |
UNKNOWN equ 1 |
match =resolve_equates, feature |
\{ |
restore _RESOLVE_EQUATES |
_RESOLVE_EQUATES equ OFF |
UNKNOWN equ 0 |
\} |
match =listing, feature |
\{ |
disable_listing |
UNKNOWN equ 0 |
\} |
match =1, UNKNOWN |
\{ |
display 'ERROR: Unknown "',`feature, '" feature', 13, 10 |
err |
\} |
restore UNKNOWN |
restore UNKNOWN |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INITIALIZATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
_MACROSES_INSTALLED equ 0 |
_ON_VIRTUAL equ 0 |
disable resolve_equates |
; Listing generator |
; LocoDelAssembly 2007.06.01 |
INSTRUCTIONS equ bt in ja jb jc je jg jl jo jp js jz or \ |
aaa aad aam aas adc add and bsf bsr btc btr bts cbw cdq clc \ |
cld cli cmc cmp cqo cwd daa das dec div fld fst hlt inc ins \ |
int jae jbe jge jle jmp jna jnb jnc jne jng jnl jno jnp jns \ |
jnz jpe jpo lar lds lea les lfs lgs lsl lss ltr mov mul neg \ |
nop not out pop por rcl rcr ret rol ror rsm sal sar sbb shl \ |
shr stc std sti str sub ud2 xor \ |
arpl call cdqe clgi clts cmps cwde emms fabs fadd fbld fchs \ |
fcom fcos fdiv feni fild fist fld1 fldz fmul fnop fsin fstp \ |
fsub ftst fxam fxch idiv imul insb insd insw int1 int3 into \ |
invd iret jcxz jnae jnbe jnge jnle lahf lgdt lidt lldt lmsw \ |
lods loop movd movq movs orpd orps outs pand popa popd popf \ |
popq popw push pxor retd retf retn retq retw sahf salc scas \ |
seta setb setc sete setg setl seto setp sets setz sgdt shld \ |
shrd sidt sldt smsw stgi stos test verr verw wait xadd xchg \ |
xlat \ |
addpd addps addsd addss andpd andps bound bswap cmova cmovb \ |
cmovc cmove cmovg cmovl cmovo cmovp cmovs cmovz cmppd cmpps \ |
cmpsb cmpsd cmpsq cmpss cmpsw cpuid divpd divps divsd divss \ |
enter f2xm1 faddp fbstp fclex fcomi fcomp fdisi fdivp fdivr \ |
femms ffree fiadd ficom fidiv fimul finit fistp fisub fldcw \ |
fldpi fmulp fneni fprem fptan fsave fsqrt fstcw fstsw fsubp \ |
fsubr fucom fwait fyl2x icebp iretd iretq iretw jecxz jrcxz \ |
lddqu leave lodsb lodsd lodsq lodsw loopd loope loopq loopw \ |
loopz maxpd maxps maxsd maxss minpd minps minsd minss movsb \ |
movsd movsq movss movsw movsx movzx mulpd mulps mulsd mulss \ |
mwait outsb outsd outsw pabsb pabsd pabsw paddb paddd paddq \ |
paddw pandn pause pavgb pavgw pf2id pf2iw pfacc pfadd pfmax \ |
pfmin pfmul pfrcp pfsub pi2fd pi2fw popad popaw popfd popfq \ |
popfw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb \ |
psubd psubq psubw pusha pushd pushf pushq pushw rcpps rcpss \ |
rdmsr rdpmc rdtsc retfd retfq retfw retnd retnq retnw scasb \ |
scasd scasq scasw setae setbe setge setle setna setnb setnc \ |
setne setng setnl setno setnp setns setnz setpe setpo stosb \ |
stosd stosq stosw subpd subps subsd subss vmrun vmxon wrmsr \ |
xlatb xorpd xorps \ |
andnpd andnps cmovae cmovbe cmovge cmovle cmovna cmovnb cmovnc\ |
cmovne cmovng cmovnl cmovno cmovnp cmovns cmovnz cmovpe cmovpo\ |
comisd comiss fcmovb fcmove fcmovu fcomip fcompp fdivrp ffreep\ |
ficomp fidivr fisttp fisubr fldenv fldl2e fldl2t fldlg2 fldln2\ |
fnclex fndisi fninit fnsave fnstcw fnstsw fpatan fprem1 frstor\ |
frstpm fscale fsetpm fstenv fsubrp fucomi fucomp fxsave haddpd\ |
haddps hsubpd hsubps invlpg lfence looped loopeq loopew loopne\ |
loopnz loopzd loopzq loopzw mfence movapd movaps movdqa movdqu\ |
movhpd movhps movlpd movlps movnti movntq movsxd movupd movups\ |
paddsb paddsw pextrw pfnacc pfsubr phaddd phaddw phsubd phsubw\ |
pinsrw pmaxsw pmaxub pminsw pminub pmulhw pmullw psadbw pshufb\ |
pshufd pshufw psignb psignd psignw pslldq psrldq psubsb psubsw\ |
pswapd pushad pushaw pushfd pushfq pushfw rdmsrq rdtscp setalc\ |
setnae setnbe setnge setnle sfence shufpd shufps skinit sqrtpd\ |
sqrtps sqrtsd sqrtss swapgs sysret vmcall vmload vmread vmsave\ |
vmxoff wbinvd wrmsrq \ |
clflush cmovnae cmovnbe cmovnge cmovnle cmpeqpd cmpeqps \ |
cmpeqsd cmpeqss cmplepd cmpleps cmplesd cmpless cmpltpd \ |
cmpltps cmpltsd cmpltss cmpxchg fcmovbe fcmovnb fcmovne \ |
fcmovnu fdecstp fincstp fnstenv frndint fsincos fucomip \ |
fucompp fxrstor fxtract fyl2xp1 invlpga ldmxcsr loopned \ |
loopneq loopnew loopnzd loopnzq loopnzw monitor movddup \ |
movdq2q movhlps movlhps movntdq movntpd movntps movq2dq \ |
paddusb paddusw palignr pavgusb pcmpeqb pcmpeqd pcmpeqw \ |
pcmpgtb pcmpgtd pcmpgtw pfcmpeq pfcmpge pfcmpgt pfpnacc \ |
pfrsqrt phaddsw phsubsw pmaddwd pmulhrw pmulhuw pmuludq \ |
pshufhw pshuflw psubusb psubusw rsqrtps rsqrtss stmxcsr \ |
syscall sysexit sysretq ucomisd ucomiss vmclear vmmcall \ |
vmptrld vmptrst vmwrite \ |
addsubpd addsubps cmpneqpd cmpneqps cmpneqsd cmpneqss cmpnlepd\ |
cmpnleps cmpnlesd cmpnless cmpnltpd cmpnltps cmpnltsd cmpnltss\ |
cmpordpd cmpordps cmpordsd cmpordss cvtdq2pd cvtdq2ps cvtpd2dq\ |
cvtpd2pi cvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq cvtps2pd cvtps2pi\ |
cvtsd2si cvtsd2ss cvtsi2sd cvtsi2ss cvtss2sd cvtss2si fcmovnbe\ |
maskmovq movmskpd movmskps movshdup movsldup packssdw packsswb\ |
packuswb pfrcpit1 pfrcpit2 pfrsqit1 pmovmskb pmulhrsw prefetch\ |
sysenter sysexitq unpckhpd unpckhps unpcklpd unpcklps vmlaunch\ |
vmresume \ |
cmpxchg8b cvttpd2dq cvttpd2pi cvttps2dq cvttps2pi cvttsd2si \ |
cvttss2si pmaddubsw prefetchw punpckhbw punpckhdq punpckhwd \ |
punpcklbw punpckldq punpcklwd \ |
cmpunordpd cmpunordps cmpunordsd cmpunordss cmpxchg16b \ |
loadall286 loadall386 maskmovdqu prefetcht0 prefetcht1 \ |
prefetcht2 punpckhqdq punpcklqdq prefetchnta |
PREFIXES equ rep lock repe repz repne repnz |
DATA_DEFINITORS equ db dw du dd dp df dq dt file |
DATA_RESERVERS equ rb rw rd rp rf rq rt |
CRLF equ 13, 10 ; Remove 13 for Linux |
MAX_BYTES equ 13 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MODE MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro use16 |
{ |
use16 |
_USE = 16 |
} |
macro use32 |
{ |
use32 |
_USE = 32 |
} |
macro use64 |
{ |
use64 |
_USE = 64 |
} |
macro detect_mode |
{ |
local aux |
_USE = 32 |
virtual at 0 |
xchg eax, eax |
load aux byte from 0 |
if aux = $66 |
_USE = 16 |
else if aux = $87 |
_USE = 64 |
end if |
end virtual |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISPLAYING MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro display_address address* |
{ |
local aux, digit |
aux = address |
repeat _USE / 4 |
digit = aux shr (_USE - 4 * %) and $F |
display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F |
end repeat |
display ': ' |
} |
macro display_bytes pointer |
{ |
local aux, size, digit |
size = $ - pointer |
if size > MAX_BYTES |
size = MAX_BYTES |
end if |
repeat size |
load aux byte from pointer+%-1 |
digit = aux shr 4 |
display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F |
digit = aux and $F |
display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F |
display ' ' |
end repeat |
repeat MAX_BYTES - size |
display ' ' |
end repeat |
} |
; The macro below in some situations doesn't adds a space to separate things unfortunatelly, so for readability ensurance |
; another one will be used instead... |
;macro display_args [args] |
;{ |
;common |
; aux = 1 |
; |
;forward |
; if ~args eq |
; if aux |
; display ' ' |
; else |
; display ', ' |
; end if |
; |
; aux = 0 |
; |
; match =ON, _RESOLVE_EQUATES |
; \{ |
; match args, args |
; \\{ |
; irps arg, args |
; \\\{ |
; display \\\`arg |
; \\\} |
; \\} |
; \} |
; match =OFF, _RESOLVE_EQUATES |
; \{ |
; irps arg, args |
; \\{ |
; display \\`arg |
; \\} |
; |
; \} |
; end if |
;} |
; This one separates everything with one space. A very ugly listing but at least you will not see things |
; like "push ebxesiedi" nor "ret word0" |
macro display_args [args] |
{ |
common |
aux = 1 |
forward |
if ~args eq |
if ~aux |
display ',' |
end if |
aux = 0 |
match =ON, _RESOLVE_EQUATES |
\{ |
match args, args |
\\{ |
if ~args eqtype "" |
irps arg, args |
\\\{ |
display ' ', \\\`arg |
\\\} |
else |
display " '", args, "'" |
end if |
\\} |
\} |
match =OFF, _RESOLVE_EQUATES |
\{ |
if ~args eqtype "" |
irps arg, args |
\\{ |
display ' ', \\`arg |
\\} |
else |
display " '", args, "'" |
end if |
\} |
end if |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;; INSTRUCTIONS & PREFIXES MACROSES ;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro prefix mnemonic |
{ |
local aux |
macro mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
mnemonic |
match =1, _LISTING |
\\{ |
display_bytes aux |
display \`mnemonic |
display CRLF |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
def_prefix mnemonic |
args |
purge mnemonic |
\} |
} |
macro def_prefix mnemonic |
{ |
macro def_prefix mnemonic |
\{ |
prefix mnemonic |
\} |
def_prefix mnemonic |
} |
macro instruction mnemonic |
{ |
local aux |
macro mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
mnemonic args |
match =1, _LISTING |
\\{ |
display_bytes aux |
display \`mnemonic |
virtual at 0 |
db \`mnemonic |
repeat 11 - $ |
display ' ' |
end repeat |
end virtual |
display_args args |
display CRLF |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro data_define mnemonic |
{ |
local aux |
macro mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
mnemonic args |
match =1, _LISTING |
\\{ |
display_bytes aux |
display \`mnemonic |
display_args args |
display CRLF |
aux = aux + MAX_BYTES |
repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES |
display_address aux |
display_bytes aux |
display CRLF |
aux = aux + MAX_BYTES |
end repeat |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
struc mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
. mnemonic args |
match =1, _LISTING |
\\{ |
display_bytes aux |
display \`., ' ', \`mnemonic |
display_args args |
display CRLF |
aux = aux + MAX_BYTES |
repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES |
display_address aux |
display_bytes aux |
display CRLF |
aux = aux + MAX_BYTES |
end repeat |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
} |
macro data_reserve mnemonic |
{ |
local aux |
macro mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
mnemonic args |
match =1, _LISTING |
\\{ |
times MAX_BYTES display ' ' |
display \`mnemonic |
display_args args |
display CRLF |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
struc mnemonic [args] |
\{ |
\common |
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} |
match =equ, args\\{_LISTING equ 0\\} |
match =equ any, args\\{_LISTING equ 0\\} |
match =1, _LISTING |
\\{ |
display_address $ |
aux = $ |
\\} |
. mnemonic args |
match =1, _LISTING |
\\{ |
times MAX_BYTES display ' ' |
display \`., ' ', \`mnemonic |
display_args args |
display CRLF |
\\} |
match =1, _ON_VIRTUAL\\{restore _LISTING\\} |
match =equ, args\\{restore _LISTING\\} |
match =equ any, args\\{restore _LISTING\\} |
\} |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; LISTING CONTROL MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro virtual [args] |
{ |
common |
_ON_VIRTUAL equ 1 |
virtual args |
} |
macro end [args] |
{ |
common |
match =virtual, args\{restore _ON_VIRTUAL\} |
end args |
} |
macro enable_listing |
{ |
detect_mode |
match =0, _MACROSES_INSTALLED |
\{ |
match instructions, INSTRUCTIONS |
\\{ |
irps ins, instructions |
\\\{ |
instruction ins |
\\\} |
\\} |
match prefixes, PREFIXES |
\\{ |
irps prefix, prefixes |
\\\{ |
def_prefix prefix |
\\\} |
\\} |
match data_definitors, DATA_DEFINITORS |
\\{ |
irps def, data_definitors |
\\\{ |
data_define def |
\\\} |
\\} |
match data_reservers, DATA_RESERVERS |
\\{ |
irps def, data_reservers |
\\\{ |
data_reserve def |
\\\} |
\\} |
\} |
_MACROSES_INSTALLED equ 1 |
_LISTING equ 1 |
} |
macro disable_listing |
{ |
_LISTING equ 0 |
} |
macro enable [feature*] |
{ |
forward |
UNKNOWN equ 1 |
match =resolve_equates, feature |
\{ |
restore _RESOLVE_EQUATES |
_RESOLVE_EQUATES equ ON |
UNKNOWN equ 0 |
\} |
match =listing, feature |
\{ |
enable_listing |
UNKNOWN equ 0 |
\} |
match =1, UNKNOWN |
\{ |
display 'ERROR: Unknown "',`feature, '" feature', 13, 10 |
err |
\} |
restore UNKNOWN |
restore UNKNOWN |
} |
macro disable [feature*] |
{ |
UNKNOWN equ 1 |
match =resolve_equates, feature |
\{ |
restore _RESOLVE_EQUATES |
_RESOLVE_EQUATES equ OFF |
UNKNOWN equ 0 |
\} |
match =listing, feature |
\{ |
disable_listing |
UNKNOWN equ 0 |
\} |
match =1, UNKNOWN |
\{ |
display 'ERROR: Unknown "',`feature, '" feature', 13, 10 |
err |
\} |
restore UNKNOWN |
restore UNKNOWN |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INITIALIZATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
_MACROSES_INSTALLED equ 0 |
_ON_VIRTUAL equ 0 |
disable resolve_equates |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/loader.asm |
---|
1,317 → 1,317 |
; Copyright (c) 2008-2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;start of the project 13.02.2008 year. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;Secondary Loader copyright Alexey Teplov nickname <Lrz> |
;if you need log preproc |
;///////////// |
;include 'listing.inc' |
;enable listing |
;//////////// |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;start of code: ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
use16 |
org 0x0 |
jmp start |
include 'sl_equ.inc' ; â ôàéëå ðàçìåùåíû âñå equ ïðåäîïðåäåëåíèÿ |
include 'boot_st.inc' |
include 'debug_msg.inc' ;here is message from debug |
include 'parse_dat.inc' |
include 'sl_proc.inc' |
include 'parse.inc' |
include 'parse_loader.inc' |
include 'parse_any.inc' |
include 'parse_def_sect.inc' |
include 'parse_err.inc' |
file_data dw 0x0,ini_data_ ;ôîðìàò: ñìåùåíèå: ñåãìåíò ò.ê. èñïîëüçóåòñÿ les |
size_data dw 16 ;16 áëîêîâ ïî 4 êá ò.å ïðåäåë äî 64 êá |
name_ini_f db 'kord/startos.ini',0 |
;//////////// |
loader_callback dd ? |
load_drive dw ? |
load_ft dw ? |
;Start code |
start: |
; Save far pointer to callback procedure, ds:si is point |
mov word [cs:loader_callback], si |
mov word [cs:loader_callback+2], ds |
; Save type of drive |
mov word [cs:load_drive],ax |
; Save type of FT |
mov word [cs:load_ft],bx |
; set up stack |
mov ax, cs |
mov ss, ax |
xor sp, sp |
; set up segment registers |
mov ds,ax |
mov es,ax |
; just to be sure: force DF=0, IF=1 |
cld |
sti |
; set videomode |
mov ax,3 |
int 0x10 |
mov si,version |
call printplain |
mov al,'#' |
mov cx,80 |
;input cx=size al=char áóäåò âûâäåí ñèìâîë ñêîëüêî ðàç óêàçàíî â cx |
@@: |
call putchar |
loop @b |
if DEBUG |
pushad |
mov ax,cs |
shl eax,4 ; â äåñÿòè÷íîé ñèñòåìå àäðåñ ñåãìåíòà |
mov cx,0xa |
mov di,cseg_msg |
call decode |
;*************** |
mov si,cseg_msg |
call printplain |
popad |
end if |
if DEBUG |
mov si,stack_msg |
call printplain |
end if |
; Require 586 or higher processor (cpuid and rdtsc,rdmsr/wrmsr commands) |
; install int 6 (#UD) handler |
xor bx, bx |
mov ds, bx |
push word [bx+6*4+2] |
push word [bx+6*4] |
mov word [bx+6*4], ud16 |
mov word [bx+6*4+2], cs |
; issue CPUID command |
xor eax, eax ; N.B.: will cause #UD before 386 |
cpuid ; N.B.: will cause #UD before later 486s |
test eax, eax |
jz cpubad |
; get processor features |
xor eax, eax |
inc ax |
cpuid |
test dl, 10h ; CPUID[1].edx[4] - TSC support |
jz cpubad |
test dl, 20h ; CPUID[1].edx[5] - MSR support |
jnz cpugood |
ud16: ; #UD handler, called if processor did not recognize some commands |
cpubad: |
; restore int 6 (#UD) handler |
pop word [6*4] |
pop word [6*4+2] |
; say error |
push cs |
pop ds |
mov si, badprocessor |
sayerr: |
call printplain |
jmp $ |
cpugood: |
; restore int 6 (#UD) handler |
pop dword [6*4] |
push cs |
pop ds |
; set up esp |
movzx esp, sp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; init memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Load startos.ini |
mov cx,loop_read_startos_file ;êîë-âî ïîïûòîê ÷òåíèÿ ôàéëà êîíôèãóðàöèè startos.ini |
align 4 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Load startos.ini ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
load_startos_file: |
xor ax,ax |
mov di,file_data |
inc ax ;function 1 - read file |
push cx |
call far dword [loader_callback] |
pop cx |
push cs |
push cs |
pop ds |
pop es |
test bx,bx |
jz check_conf_file |
dec cx |
jnz load_startos_file |
;SET DEFAULT Not use ini file |
error_ini: |
mov si, error_ini_f1 ;Error: cannot load ini file, buffer is full |
dec bx |
jz err_show_ini |
mov si, error_ini_f2 ;Error: ini file not found |
dec bx |
jz err_show_ini |
mov si, error_ini_f3 ;Error: cannot read ini file |
dec bx |
jz err_show_ini |
mov si, error_ini_nf ;Error: unrecognized error when loading ini file |
err_show_ini: |
call printplain |
mov si, error_ini_common |
call printplain |
; wait for keypress |
xor ax,ax |
int 16h |
ini_loaded: |
jmp $ |
align 4 |
check_conf_file: |
;Check config file in current dir |
push ax ;save size file |
if DEBUG |
mov cx,0x0a |
mov di,show_decode |
call decode |
;Show size |
mov si,show_string |
call printplain |
end if |
;Show message |
mov si,load_ini |
call printplain |
pop cx ;restore size file |
use_parse ;parsing startos.ini |
; |
jmp ini_loaded |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;DATA |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; table for move to extended memory (int 15h, ah=87h) |
align 4 |
table_15_87: |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0xff,0xff |
db 0x0,0x10 |
db 0x00,0x93,0x0,0x0 |
db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
fat12_buffer: |
.BS_jmpBoot db 0x90,0x90,0x90 ;3 áàéòà NOP èíñòðóêöèÿ - íè÷åãî íå äåëàòü |
.BS_OEMName db 'K SyS 64' ;8 áàéò |
.BPB_BytsPerSec dw 512 ;êîë-âî áàéòîâ â ñåêòîðå ìîæåò áûòü ëþáîå 512 1024 2048 4096 2 áàéòà |
.BPB_SecPerClus db 0x1 ;êîë-âî ñåêòîðîâ â êëàñòåðå |
.BPB_RsvdSecCnt dw 0x1 ;äëÿ FAt12/16 òîëüêî 1, äëÿ FAT32 îáû÷íî 32 |
.BPB_NumFATs db 0x1 ;êîë-âî ôàò òàáëèö, íà òîò ñëó÷àé åñëè áóäåò ñáðîñ íà äèñêåòó îáðàçà ðàì äèñêà |
.BPB_RootEntCnt dw 512 ;äëÿ ìàê ñîâìåñòèìîñòè ñ fat16 |
.BPB_TotSec16 dw 0x0 ;êë-âî ñåêòîðîâ |
.BPB_Media db 0xF0 |
.BPB_FATSz16 dw 0x0 |
.BPB_SecPerTrk dw 0x0 ;ñîäåðæèò ãåîìåòðèþ äèñêà äëÿ RAMFS íà êàê áû áåç ðàçíèöû, ïîêà ïóñòîå ïîëå, ïîçæå âíåñòè ðåàëüíûå çíà÷åíèÿ. |
.BPB_NumHeads dw 0x0 |
.BPB_HiddSec dd 0x0 ;êîë-âî ñêðûòûõ ñåêòîðîâ |
.BPB_TotSec32 dd 0x0 |
.BS_DrvNum db 'R' ;îò ñëîâà RAM |
.BS_Reserved1 db 0x0 |
.BS_BootSig db 0x29 |
.BS_VolID db 'RFKS' |
.BS_VolLab db 'RAM DISK FS' ;11 ñèìâîëîâ |
.BS_FilSysType db 'FAT12 ' ;8 ñèìâîëîâ |
;62 áàéòà ñòðóêòóðà fat12. |
db (512-($-fat12_buffer))dup(0x90) |
;ñòðóêòóðà äëÿ äèððåêòîðèè fat |
struc FAT_32_entry ;Byte Directory Entry Structure |
{ |
.DIR_Name rb 11 |
.DIR_Attr db ? |
.DIR_NTRes db ? |
.DIR_CrtTimeTenth db ? |
.DIR_CrtTime dw ? |
.DIR_CrtDate dw ? |
.DIR_LstAccDate dw ? |
.DIR_FstClusHI dw ? |
.DIR_WrtTime dw ? |
.DIR_WrtDate dw ? |
.DIR_FstClusLO dw ? |
.DIR_FileSize dd ? |
} |
;Òóò áóäóò ðàñïîëîãàòñüÿ äàííûå, êîòîðûå çàòðóäíèòåëüíî ðàñïîëîãàòü â ñòåêîâîé îáëàñòè.... |
;;; |
;timer |
shot_name_fat rb 11 ;âðåìåííûé áóôåð äëÿ fat12, â íåì õðàíÿòüñÿ èìåíà ôàéëîâ ïðèâåäåííûå ê ïðàâèëàì FAT /* âäàëüíåéøåì ïåðåíåñòè â ñòýê |
if DEBUG |
rb 1 ;íóæåí äëÿ îòëàäêè è âûâîäà èìåíè ôàéëà ïîñëå ïðåîáðàçîâàíèÿ |
dest_name_fat db 24 dup('_');12 |
db 0x0 |
end if |
value_timeout rw 1 ;value to timeout |
old_timer rd 1 ;ñòàðîå çíà÷åíèå âåêòîðà òàéìåðà |
start_timer rd 1 ;çíà÷åíèå òàéìåðà |
timer_ rd 1 ;íîâîå çíà÷åíèå âåêòîðà òàéìåðà ò.å. SL |
start_stack rw 1 ;save stack |
save_bp_from_timer rw 1 ;save bp from timer |
; Copyright (c) 2008-2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;start of the project 13.02.2008 year. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;Secondary Loader copyright Alexey Teplov nickname <Lrz> |
;if you need log preproc |
;///////////// |
;include 'listing.inc' |
;enable listing |
;//////////// |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;start of code: ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
use16 |
org 0x0 |
jmp start |
include 'sl_equ.inc' ; â ôàéëå ðàçìåùåíû âñå equ ïðåäîïðåäåëåíèÿ |
include 'boot_st.inc' |
include 'debug_msg.inc' ;here is message from debug |
include 'parse_dat.inc' |
include 'sl_proc.inc' |
include 'parse.inc' |
include 'parse_loader.inc' |
include 'parse_any.inc' |
include 'parse_def_sect.inc' |
include 'parse_err.inc' |
file_data dw 0x0,ini_data_ ;ôîðìàò: ñìåùåíèå: ñåãìåíò ò.ê. èñïîëüçóåòñÿ les |
size_data dw 16 ;16 áëîêîâ ïî 4 êá ò.å ïðåäåë äî 64 êá |
name_ini_f db 'kord/startos.ini',0 |
;//////////// |
loader_callback dd ? |
load_drive dw ? |
load_ft dw ? |
;Start code |
start: |
; Save far pointer to callback procedure, ds:si is point |
mov word [cs:loader_callback], si |
mov word [cs:loader_callback+2], ds |
; Save type of drive |
mov word [cs:load_drive], ax |
; Save type of FT |
mov word [cs:load_ft], bx |
; set up stack |
mov ax, cs |
mov ss, ax |
xor sp, sp |
; set up segment registers |
mov ds, ax |
mov es, ax |
; just to be sure: force DF=0, IF=1 |
cld |
sti |
; set videomode |
mov ax, 3 |
int 0x10 |
mov si, version |
call printplain |
mov al, '#' |
mov cx, 80 |
;input cx=size al=char áóäåò âûâäåí ñèìâîë ñêîëüêî ðàç óêàçàíî â cx |
@@: |
call putchar |
loop @b |
if DEBUG |
pushad |
mov ax, cs |
shl eax, 4 ; â äåñÿòè÷íîé ñèñòåìå àäðåñ ñåãìåíòà |
mov cx, 0xa |
mov di, cseg_msg |
call decode |
;*************** |
mov si, cseg_msg |
call printplain |
popad |
end if |
if DEBUG |
mov si, stack_msg |
call printplain |
end if |
; Require 586 or higher processor (cpuid and rdtsc,rdmsr/wrmsr commands) |
; install int 6 (#UD) handler |
xor bx, bx |
mov ds, bx |
push word [bx+6*4+2] |
push word [bx+6*4] |
mov word [bx+6*4], ud16 |
mov word [bx+6*4+2], cs |
; issue CPUID command |
xor eax, eax ; N.B.: will cause #UD before 386 |
cpuid ; N.B.: will cause #UD before later 486s |
test eax, eax |
jz cpubad |
; get processor features |
xor eax, eax |
inc ax |
cpuid |
test dl, 10h ; CPUID[1].edx[4] - TSC support |
jz cpubad |
test dl, 20h ; CPUID[1].edx[5] - MSR support |
jnz cpugood |
ud16: ; #UD handler, called if processor did not recognize some commands |
cpubad: |
; restore int 6 (#UD) handler |
pop word [6*4] |
pop word [6*4+2] |
; say error |
push cs |
pop ds |
mov si, badprocessor |
sayerr: |
call printplain |
jmp $ |
cpugood: |
; restore int 6 (#UD) handler |
pop dword [6*4] |
push cs |
pop ds |
; set up esp |
movzx esp, sp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; init memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Load startos.ini |
mov cx, loop_read_startos_file ;êîë-âî ïîïûòîê ÷òåíèÿ ôàéëà êîíôèãóðàöèè startos.ini |
align 4 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Load startos.ini ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
load_startos_file: |
xor ax, ax |
mov di, file_data |
inc ax ;function 1 - read file |
push cx |
call far dword [loader_callback] |
pop cx |
push cs |
push cs |
pop ds |
pop es |
test bx, bx |
jz check_conf_file |
dec cx |
jnz load_startos_file |
;SET DEFAULT Not use ini file |
error_ini: |
mov si, error_ini_f1 ;Error: cannot load ini file, buffer is full |
dec bx |
jz err_show_ini |
mov si, error_ini_f2 ;Error: ini file not found |
dec bx |
jz err_show_ini |
mov si, error_ini_f3 ;Error: cannot read ini file |
dec bx |
jz err_show_ini |
mov si, error_ini_nf ;Error: unrecognized error when loading ini file |
err_show_ini: |
call printplain |
mov si, error_ini_common |
call printplain |
; wait for keypress |
xor ax, ax |
int 16h |
ini_loaded: |
jmp $ |
align 4 |
check_conf_file: |
;Check config file in current dir |
push ax ;save size file |
if DEBUG |
mov cx, 0x0a |
mov di, show_decode |
call decode |
;Show size |
mov si, show_string |
call printplain |
end if |
;Show message |
mov si, load_ini |
call printplain |
pop cx ;restore size file |
use_parse ;parsing startos.ini |
; |
jmp ini_loaded |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;DATA |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; table for move to extended memory (int 15h, ah=87h) |
align 4 |
table_15_87: |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0xff,0xff |
db 0x0,0x10 |
db 0x00,0x93,0x0,0x0 |
db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 |
fat12_buffer: |
.BS_jmpBoot db 0x90,0x90,0x90 ;3 áàéòà NOP èíñòðóêöèÿ - íè÷åãî íå äåëàòü |
.BS_OEMName db 'K SyS 64' ;8 áàéò |
.BPB_BytsPerSec dw 512 ;êîë-âî áàéòîâ â ñåêòîðå ìîæåò áûòü ëþáîå 512 1024 2048 4096 2 áàéòà |
.BPB_SecPerClus db 0x1 ;êîë-âî ñåêòîðîâ â êëàñòåðå |
.BPB_RsvdSecCnt dw 0x1 ;äëÿ FAt12/16 òîëüêî 1, äëÿ FAT32 îáû÷íî 32 |
.BPB_NumFATs db 0x1 ;êîë-âî ôàò òàáëèö, íà òîò ñëó÷àé åñëè áóäåò ñáðîñ íà äèñêåòó îáðàçà ðàì äèñêà |
.BPB_RootEntCnt dw 512 ;äëÿ ìàê ñîâìåñòèìîñòè ñ fat16 |
.BPB_TotSec16 dw 0x0 ;êë-âî ñåêòîðîâ |
.BPB_Media db 0xF0 |
.BPB_FATSz16 dw 0x0 |
.BPB_SecPerTrk dw 0x0 ;ñîäåðæèò ãåîìåòðèþ äèñêà äëÿ RAMFS íà êàê áû áåç ðàçíèöû, ïîêà ïóñòîå ïîëå, ïîçæå âíåñòè ðåàëüíûå çíà÷åíèÿ. |
.BPB_NumHeads dw 0x0 |
.BPB_HiddSec dd 0x0 ;êîë-âî ñêðûòûõ ñåêòîðîâ |
.BPB_TotSec32 dd 0x0 |
.BS_DrvNum db 'R' ;îò ñëîâà RAM |
.BS_Reserved1 db 0x0 |
.BS_BootSig db 0x29 |
.BS_VolID db 'RFKS' |
.BS_VolLab db 'RAM DISK FS' ;11 ñèìâîëîâ |
.BS_FilSysType db 'FAT12 ' ;8 ñèìâîëîâ |
;62 áàéòà ñòðóêòóðà fat12. |
db (512-($-fat12_buffer))dup(0x90) |
;ñòðóêòóðà äëÿ äèððåêòîðèè fat |
struc FAT_32_entry ;Byte Directory Entry Structure |
{ |
.DIR_Name rb 11 |
.DIR_Attr db ? |
.DIR_NTRes db ? |
.DIR_CrtTimeTenth db ? |
.DIR_CrtTime dw ? |
.DIR_CrtDate dw ? |
.DIR_LstAccDate dw ? |
.DIR_FstClusHI dw ? |
.DIR_WrtTime dw ? |
.DIR_WrtDate dw ? |
.DIR_FstClusLO dw ? |
.DIR_FileSize dd ? |
} |
;Òóò áóäóò ðàñïîëîãàòñüÿ äàííûå, êîòîðûå çàòðóäíèòåëüíî ðàñïîëîãàòü â ñòåêîâîé îáëàñòè.... |
;;; |
;timer |
shot_name_fat rb 11 ;âðåìåííûé áóôåð äëÿ fat12, â íåì õðàíÿòüñÿ èìåíà ôàéëîâ ïðèâåäåííûå ê ïðàâèëàì FAT /* âäàëüíåéøåì ïåðåíåñòè â ñòýê |
if DEBUG |
rb 1 ;íóæåí äëÿ îòëàäêè è âûâîäà èìåíè ôàéëà ïîñëå ïðåîáðàçîâàíèÿ |
dest_name_fat db 24 dup('_');12 |
db 0x0 |
end if |
value_timeout rw 1 ;value to timeout |
old_timer rd 1 ;ñòàðîå çíà÷åíèå âåêòîðà òàéìåðà |
start_timer rd 1 ;çíà÷åíèå òàéìåðà |
timer_ rd 1 ;íîâîå çíà÷åíèå âåêòîðà òàéìåðà ò.å. SL |
start_stack rw 1 ;save stack |
save_bp_from_timer rw 1 ;save bp from timer |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/parse.inc |
---|
1,118 → 1,118 |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; Ìîäóëü ïàðñèíãà - ýòî ñòàíäàðòíûé êîìïîíåíò, âñòðàèâàåìûé âî âòîðè÷íûé çàãðóç÷èê. |
; Äàííûé ìîäóëü ïîçâîëÿåò ñòàíäàðòíî ïðîèçâåñòè ðàçáîð ini ôàéëà |
; (è ñ èñïîëüçîâàíèåì ïîëó÷åííûõ äàííûõ ÎÑ áóäåò çàãðóæàòüñÿ äàëüøå). |
;  íà÷àëå íàéäåì îòêðûâàþùèé "[" - ýòî áóäåò óêàçûâàòü íà íà÷àëî |
; ñåêöèè. Ïîääåðæèâàåòñÿ 1 ñåêöèÿ ýòî [loader], îñòàëüíûå ñåêöèè ìîãóò èìåòü |
; ëþáûå èìåíà, íî îíè äîëæíû áûòü çàêëþ÷åíû â â ñêîáêè [] |
macro use_parse |
{ |
;input cx=size of ini file |
parse_start: |
;es:di as 2000:0000 new segment |
;óñòàíîâèì óêàçàòåëü íà çàãðóæåííûé áëîê |
enter 256,0 ;set 16 byte for current task in stack |
;we are is not use bp because bp is pointer on array 16 byte |
mov word [save_bp_from_timer],bp ;save point to own data array |
mov save_cx,cx ;it's placed size of ini file |
les di,dword [file_data] |
;îáíóëèì âñå ïåðåìåííûå âûäåëåííûå èç ñòåêà |
;init flag |
xor ax,ax |
mov status_flag,ax |
;set data size |
mov info_real_mode_size,ini_data_ +0x1000 ;èçìåíèì çíà÷åíèå çàíÿòîñòè ïàìÿòè |
;ïîèñê íà÷àëà áëîêà. |
;///////////check [loader] |
cld |
mov ret_on_ch,.start ;set return |
mov al,byte [es:di] |
push word .first_ret |
cmp al,' ' |
jz .first_sp_1 |
jmp get_firs_sym.not_space |
.first_sp_1: |
jmp get_firs_sym.first_sp |
.start: |
call get_firs_sym ;get first symbol on new line |
.first_ret: ;ïåðâûé âîçâðàò |
; jcxz .end_file ;.end_loader ;found or not found parametrs in section exit in section |
test cx,cx |
jz error.not_loader |
cmp al,'[' |
jz .parse_loader |
jmp .start |
;////// ïðîâåðêà íà íàëè÷åå ñåêöèè loader |
use_parse_loader |
;pause |
if DEBUG |
xor ax,ax |
int 16h |
end if |
;////// âûâîä ãðàôè÷åñêîãî ýêðàíà, âûáîð, ñåêöèè ïîä äåôîëòó |
use_any_sec |
;ïàðñèíã âûáðàíîé èëè äåôîëòíîé ñåêöèè ò.å. ðàçáîð ïàðàìåòðîâ âûïîëíåíèå ñöåíàðèÿ |
use_parse_def_sect |
;////////////////// |
;/end parse block |
;////////////////// |
;.end_bl: |
; mov cx,bx |
; |
; jmp .start |
.exit: |
; mov si,parse_ini_end |
; call printplain |
; |
;if DEBUG |
; pusha |
; mov ax,cx |
; mov cx,0x0a |
; mov di,show_db1_dec |
; mov dword[ds:di],' ' |
; call decode |
;Show size |
; mov si,show_db1 |
; call printplain |
; |
; popa |
;end if |
jmp $ |
;///////////////////procedure ////////// |
;input es:di - is pointer to date |
;cx - counter |
;return: cx - status if =0 - end of date else es:di point to first symbol on new line |
} |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; Ìîäóëü ïàðñèíãà - ýòî ñòàíäàðòíûé êîìïîíåíò, âñòðàèâàåìûé âî âòîðè÷íûé çàãðóç÷èê. |
; Äàííûé ìîäóëü ïîçâîëÿåò ñòàíäàðòíî ïðîèçâåñòè ðàçáîð ini ôàéëà |
; (è ñ èñïîëüçîâàíèåì ïîëó÷åííûõ äàííûõ ÎÑ áóäåò çàãðóæàòüñÿ äàëüøå). |
;  íà÷àëå íàéäåì îòêðûâàþùèé "[" - ýòî áóäåò óêàçûâàòü íà íà÷àëî |
; ñåêöèè. Ïîääåðæèâàåòñÿ 1 ñåêöèÿ ýòî [loader], îñòàëüíûå ñåêöèè ìîãóò èìåòü |
; ëþáûå èìåíà, íî îíè äîëæíû áûòü çàêëþ÷åíû â â ñêîáêè [] |
macro use_parse |
{ |
;input cx=size of ini file |
parse_start: |
;es:di as 2000:0000 new segment |
;óñòàíîâèì óêàçàòåëü íà çàãðóæåííûé áëîê |
enter 256, 0 ;set 16 byte for current task in stack |
;we are is not use bp because bp is pointer on array 16 byte |
mov word [save_bp_from_timer], bp ;save point to own data array |
mov save_cx, cx ;it's placed size of ini file |
les di, dword [file_data] |
;îáíóëèì âñå ïåðåìåííûå âûäåëåííûå èç ñòåêà |
;init flag |
xor ax, ax |
mov status_flag, ax |
;set data size |
mov info_real_mode_size, ini_data_ +0x1000 ;èçìåíèì çíà÷åíèå çàíÿòîñòè ïàìÿòè |
;ïîèñê íà÷àëà áëîêà. |
;///////////check [loader] |
cld |
mov ret_on_ch, .start ;set return |
mov al, byte [es:di] |
push word .first_ret |
cmp al, ' ' |
jz .first_sp_1 |
jmp get_firs_sym.not_space |
.first_sp_1: |
jmp get_firs_sym.first_sp |
.start: |
call get_firs_sym ;get first symbol on new line |
.first_ret: ;ïåðâûé âîçâðàò |
; jcxz .end_file ;.end_loader ;found or not found parametrs in section exit in section |
test cx, cx |
jz error.not_loader |
cmp al, '[' |
jz .parse_loader |
jmp .start |
;////// ïðîâåðêà íà íàëè÷åå ñåêöèè loader |
use_parse_loader |
;pause |
if DEBUG |
xor ax, ax |
int 16h |
end if |
;////// âûâîä ãðàôè÷åñêîãî ýêðàíà, âûáîð, ñåêöèè ïîä äåôîëòó |
use_any_sec |
;ïàðñèíã âûáðàíîé èëè äåôîëòíîé ñåêöèè ò.å. ðàçáîð ïàðàìåòðîâ âûïîëíåíèå ñöåíàðèÿ |
use_parse_def_sect |
;////////////////// |
;/end parse block |
;////////////////// |
;.end_bl: |
; mov cx,bx |
; |
; jmp .start |
.exit: |
; mov si,parse_ini_end |
; call printplain |
; |
;if DEBUG |
; pusha |
; mov ax,cx |
; mov cx,0x0a |
; mov di,show_db1_dec |
; mov dword[ds:di],' ' |
; call decode |
;Show size |
; mov si,show_db1 |
; call printplain |
; |
; popa |
;end if |
jmp $ |
;///////////////////procedure ////////// |
;input es:di - is pointer to date |
;cx - counter |
;return: cx - status if =0 - end of date else es:di point to first symbol on new line |
} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/parse_any.inc |
---|
1,683 → 1,686 |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;òóò ðàñïîëîãàåòñÿ ìîäóëü ñ ïîìîùüþ êîòîðîãî áóäóò ïàðñèòüñÿ âñå îñòàëüíûå ñåêöèè |
color_sym_black equ 0 |
color_sym_blue equ 1 |
color_sym_green equ 2 |
color_sym_turquoise equ 3 |
color_sym_red equ 4 |
color_sym_lightgray equ 7 |
color_sym_lightblue equ 9 |
color_sym_lettuce equ 10 |
color_sym_pink equ 12 |
color_sym_yellow equ 14 |
macro use_any_sec |
{ |
;óçíàåì ðàáîòó ïðåäûäóùåãî øàãà ò.å. ÷åìó = timeout, åñëè îí 0, òî âèçóàëüíàÿ ÷àñòü íå áóäåò îòîáðàæåíà íà äèñïëåå ñ âûáîðîì çàãðóçî÷íûõ ñåêöèé. |
;èíà÷å ìû åå äîëæíû îòîáðàçèòü è æäàòü çàÿâëåíîå âðåìÿ äëÿ âûáîðà è êîíèãóðèðîâàíèÿ ïóêíêòîâ ñåêöèè îò ïîëüçîâàòåëÿ. |
if DEBUG |
pusha |
mov ax,word [value_timeout] ;èäåò ïðîâåðêà íà íàëè÷åå çíà÷åíèÿ timeout, äëÿ áîëåå áûñòðîé ðàáîòû, ýòîò ïàðàìåòð äîëæåí áûòü óæå îáðàáîòàí,ò.å. â ýòîì ñëó÷àå ïðè åãî =0 áóäåò ñôîðìèðîâàí óêàçàòåëü òîëüêî íà äåôîëòíóþ ñåêöèþ, èíà÷å èíôîðìàöèÿ áóäåò ñîáðàíà ïî âñåì ñåêöèÿì è ñîñòàâëåíû óêàçàòåëè â áëîêå ïàìÿòè |
; mov ax,cx |
mov cx,0x0a |
mov di,show_db1 |
mov dword[ds:di],' ' |
mov word [ds:di+4],' ' |
call decode |
;Show size |
mov si,show_db1 |
call printplain |
; |
popa |
end if |
test ax,ax |
jz .parse_run_only |
;îòîáðàçèì ïîëíûé ñïèñîê âñåõ íàéäåíûõ ñåêöèé. |
if DEBUG |
pusha |
mov si,show_all_sect |
call printplain |
popa |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
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 |
; set keyboard typematic rate & delay |
mov al, 0xf3 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
mov al, 0 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; get start time |
call gettime |
mov dword [start_timer],eax |
mov word [timer_],newtimer |
mov word [timer_+2],cs |
;óñòàíîâèòü ñâîå ïðåðûâàíèå íà òàéìåð ò.å. êîä áóäåò ïåððûâàòüñÿ ~18 ðàç â ñåê è ïåðåõîäèòü íà îáðàáîò÷èê |
cli |
push 0 |
pop es |
push dword [es:8*4] |
pop dword [old_timer] |
push dword [timer_] |
pop dword [es:8*4] |
sti |
;ïðîöåäóðà ôîðìèðîâàíèÿ áóôåðà äëÿ ñêðîëèíãà ñåêöèé |
;if DEBUG |
; pusha |
; mov ax,point_default |
; mov ax,cx |
; mov cx,0x0a |
; mov di,show_db1 |
; mov dword[ds:di],' ' |
; mov word [ds:di+4],' ' |
; call decode |
;Show size |
; mov si,show_db1 |
; call printplain |
; |
; xor ax,ax |
; int 0x16 |
; popa |
;end if |
;;;;;;;;;;;;;ðàçìåð ïðåäûäóùåé ñåöèè óñòàíîâèì =0 |
mov save_descript_size,18 |
;îòîáðàçèòü black screen |
show_bl_sc ;es=0xb800 |
.show_all_scr: |
get_frame_buffer ;es=0x2000 |
;îòîáðàæåíèå ñåêöèé |
call show_bl_sc_sect ;es=0xb800 |
;îòîáðàçèòü àêòèâíûé êóðñîð |
.show_active_cursor: |
show_act_cursor |
show_descript ;ìàêðîñ ïî îòîáðàæåíèþ îïèñàíèÿ ñåêöèè |
;îòîáðàçèòü Press any key .... |
mov eax,dword [old_timer] |
cmp eax,dword [timer_] |
jz .interrupt_16 |
show_timer_message |
mov word [start_stack],sp |
.interrupt_16: |
xor ax,ax ;ïîëó÷èì èíôîðìàöèþ î òîì ÷òî íàæàòî |
int 0x16 |
;check on change |
mov ebx,dword [old_timer] |
cmp ebx,dword [timer_] |
jz @f |
;restore timer interrupt |
cli |
push 0 |
pop es |
; mov eax,dword [old_timer] ; âîññòàíîâèì ïðåæäíåå ïðåðûâàíèå |
mov [es:8*4],ebx |
mov dword [timer_],ebx |
sti |
push ax |
clear_timer_msg |
pop ax |
@@: |
call clean_active_cursor ;clean old cursor ;es=0xb800 |
cmp ah,0x48 ;ðåàêöèÿ ñèñòåìû íà ñîáûòèÿ |
jz .up |
cmp ah,0x50 |
jz .down |
cmp ah,0x49 |
jz .pgup |
cmp ah,0x51 |
jz .pgdown |
cmp ah,0x47 |
jz .home |
cmp ah,0x4f |
jz .end |
cmp al,0xD |
jnz .show_active_cursor |
jmp .end_show_all ;ïàðñèíã ñåêöèè êîòîðàÿ óêàçàíà â point_default |
.up: |
mov si,point_to_point_def ;çíà÷åíèå óêàçàòåëÿ |
add si,2 |
lea ax,point_to_hframe |
cmp si,ax |
ja @f |
mov point_to_point_def,si |
mov ax,[si] |
mov point_default,ax |
jmp .show_active_cursor |
@@: |
call find_before_sect |
jmp .show_all_scr |
.down: |
mov si,point_to_point_def ;çíà÷åíèå óêàçàòåëÿ |
mov ax,point_to_eframe ;óêàçàòåëü íà ïîñëåäíèé ýëåìåíò |
sub si,2 |
cmp si,ax |
jb @f |
mov point_to_point_def,si |
mov ax,[si] |
mov point_default,ax |
jmp .show_active_cursor |
@@: call find_next_sect |
jmp .show_all_scr |
.pgup: |
mov cx,size_show_section |
@@: |
push cx |
call find_before_sect |
pop cx |
loop @b |
jmp .show_all_scr |
.pgdown: |
mov cx,size_show_section |
@@: |
push cx |
call find_next_sect |
pop cx |
loop @b |
jmp .show_all_scr |
.home: |
xor di,di |
call find_next_sect.h |
jmp .show_all_scr |
.end: |
mov di,save_cx |
call find_before_sect.e |
jmp .show_all_scr |
; òóò ìû áóäåì ïàðñèòü òîëüêî äåôîëòíóþ ñåêöèþ è âûïîëíÿòü åå íè÷åãî íå ïðåäëàãàÿ ïîëüçîâàòåëþ èç äèàëîãîâ. |
.parse_run_only: |
if DEBUG |
pusha |
mov si,no_show_only_w |
call printplain |
popa |
end if |
.end_show_all: |
} |
;show black screen SL |
macro show_bl_sc |
{ |
;;;;;;;;;;;;;;; |
;î÷èñòèì ýêðàí è âûâåäåì ìåíþ |
; draw frames |
xor ax,ax |
if DEBUG |
mov ax,0x0720 |
end if |
push 0xb800 |
pop es |
xor di, di |
; draw top |
mov cx, 25 * 80 |
rep stosw |
;;;;;;;;;;;;;;;;;;;;;;; show 'Secondary Loader v0.xxx' |
mov di,164 |
mov si,version |
mov cx,version_end-version |
mov ah,color_sym_yellow |
@@: |
lodsb |
stosw |
loop @b |
;;;;;;;;;;;;;;;;;;;;;;; show firm )) |
mov di,(2*160-(2*(soft_mes_end-soft_mes+4))) ;286 |
mov ah,color_sym_pink;color_sym_red |
mov al,'K' |
stosw |
mov al,' ' |
stosw |
mov ah,color_sym_lightgray;color_sym_lightblue;color_sym_pink |
mov si,soft_mes |
mov cx,soft_mes_end- soft_mes |
@@: |
lodsb |
stosw |
loop @b |
;;;;;;;;;;;;;;;;;;;;;;; show '__________________________' |
mov di,480 |
mov ah,color_sym_yellow |
mov al,'Ä' |
mov cx,61 |
rep stosw |
;;;;;;;;;;;;;;;;;;;;;;; show 'Select section' |
mov di,804 |
mov si,select_section |
mov cx,select_section_end - select_section |
mov ah,color_sym_lightgray |
@@: |
lodsb |
stosw |
loop @b |
;;;;;;;;;;;;;;;;;;;;;;; show 'Section description' |
mov di,880 |
mov si,section_description |
mov cx,section_description_end - section_description |
; mov ah,color_sym_lightgray |
@@: |
lodsb |
stosw |
loop @b |
} |
macro show_timer_message |
{ |
;;;;;;;;;;;;;;;;;;;;; show Press any key |
;;;;;;;;;;;;;;;;;;;;; show ramk |
xor ax,ax |
mov di,3360 |
mov cx,80*4 |
rep stosw |
mov di,3362 |
mov ah,color_sym_pink |
mov al,0xDA |
stosw |
mov al,0xc4 |
mov cx,76 |
rep stosw |
mov al,0xBF |
stosw |
add di,4 |
mov al,0xb3 |
stosw |
add di,152 |
stosw |
add di,4 |
stosw |
add di,152 |
stosw |
add di,4 |
mov al,0xc0 |
stosw |
mov al,0xc4 |
mov cx,76 |
rep stosw |
mov al,0xd9 |
stosw |
;;;;;;;;;;;;;;;;;;;;;;;;ramk is complete show |
;show first message |
mov si,start_msg |
mov cx,start_msg_e-start_msg |
mov di,3526 |
@@: |
lodsb |
stosw |
loop @b |
;;;;;;;;;;;;;;;;;;;; show press Enter to.... |
add di,44 |
mov si,time_msg |
mov cx,time_msg_e-time_msg |
@@: |
lodsb |
stosw |
loop @b |
} |
macro get_frame_buffer |
{ |
mov cx,save_cx ;it's placed size of ini file |
les di,dword [file_data] |
mov si,di ;point frame |
mov bx,cx |
mov dx,size_show_section |
; mov point_to_hframe,di ; âíåñåì çíà÷åíèå, òàê ïîäñòðàõîâêà íå áîëåå |
mov al,byte [es:di] |
push word .first_ret_bl_sc |
cmp al,' ' |
jz .first_bl_sc |
jmp get_firs_sym.not_space |
.first_bl_sc: |
jmp get_firs_sym.first_sp |
.start_hbl: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before |
cmp al,'[' |
jnz .start_hbl |
mov si,di ;point frame |
mov bx,cx |
mov dx,size_show_section |
jmp .analisist_al |
.start_bl: |
call get_firs_sym ;get first symbol on new line |
.first_ret_bl_sc: ;ïåðâûé âîçâðàò |
test cx,cx |
jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before |
.analisist_al: |
cmp al,'[' |
jnz .start_bl |
;ïðîñìàòðèâàåì ini ôàéë ñ íà÷àëà â ïîèñêàõ ñåêöèè óêàçàíîé êàê default |
;ïîèñê ôðåéìà â êîòîðîì ñîäåðæèòüñÿ çíà÷åíèå default |
.found_sect_bl: |
cmp di,point_loader |
jz .start_bl |
cmp di,point_default |
jz .save_point_def |
dec dx |
jnz .start_bl |
jmp .start_hbl |
.save_point_def: |
;èòàê äàëåå ìû äîëæíû çàïîëíèòü frame áóôåð àäðåñîâ ñåêöèé, ÷òî áû ïîòîì ïî íåìó áûñòðî ïåðåìåùàòüñÿ íå âû÷èñëÿÿ ñíîâà àäðåñà |
mov di,si ;óêàçàòåëü íà íà÷àëî |
mov cx,bx |
lea si,point_to_hframe |
mov dx,size_show_section+1 ;ò.ê. ó íàñ ñòðóêòóðà ñîäåðæèò ðàçìåð ìåæäó ïåðâûì è âòîðûì óêàçàòåëåì, òî íàì íóæíî íà 1 àäðåñ áîëüøå îáñ÷èòàòü ñåêöèé. |
;ïåðåõîäèì íà îáðàáîòêó çíà÷åíèÿ óêàçàòåëÿ |
mov al,byte [es:di] |
push word .first_ret_mfb |
cmp al,' ' |
jz .first_bl_mbf |
jmp get_firs_sym.not_space |
.first_bl_mbf: |
jmp get_firs_sym.first_sp |
.start_mfb: |
call get_firs_sym ;get first symbol on new line |
.first_ret_mfb: ;ïåðâûé âîçâðàò |
jcxz .val_buff_comp ;.end_loader ;found or not found parametrs in section exit in section |
cmp al,'[' |
jnz .start_mfb |
.found_sect_mfb: |
cmp di,point_loader ;if we have section loader |
jz .start_mfb |
mov [si],di |
sub si,2 |
dec dx |
jnz .start_mfb |
;bufer is full |
jmp @f |
.val_buff_comp: |
push save_cx |
pop word [si] |
sub si,2 |
@@: |
add si,4 |
mov point_to_eframe,si |
} |
macro show_act_cursor |
{ |
;îòîáðàæåíèå êóðñîðà ïî óìîë÷àíèþ |
lea si,point_to_hframe |
mov di,962-160 |
mov ax,point_default |
mov cx,size_show_section |
.home_show_cur: |
mov bx,[si] |
add di,160 |
cmp bx,ax |
jz .show_cursor_activ |
sub si,2 |
loop .home_show_cur |
.show_cursor_activ: |
; push 0xb800 |
; pop es |
mov point_to_point_def,si |
mov ax,(color_sym_red*0x100+0x10) |
stosw |
add di,68 |
inc ax |
stosw |
} |
macro clear_timer_msg |
{ |
push 0xb800 |
pop es |
xor ax,ax |
if DEBUG |
mov ax,0x0720 |
end if |
;;;;;;;;;;;;;;;;;;;;; show Press any key |
mov di,3360 |
mov cx,80*4 |
rep stosw |
;show sect |
push ini_data_ |
pop es |
call show_bl_sc_sect ;es=0xb800 |
} |
macro show_descript |
;Ýòîò ìàêðîñ ïîêàçûâàåò êðàòêîå îïèñàíèå, åñëè îíî åñòü ó ñåêöèè â ïóíêòå |
;Section description |
{ |
local .start_p_sh_d |
local .exit |
local .rest_value_loop_sh_d |
local .end_sh_desc_sec |
local .loop_message |
local .show_mess_prev_eq |
mov di,point_default |
push ini_data_ |
mov si,point_to_point_def |
pop es |
sub si,2 |
mov cx,[si] ;çàãðóçèì óêàçàòåëü íàñëåäóþùèþ ñåêöèþ |
sub cx,di ;âîò òåïåðü èìååì èñòèíûé ðàçìåð |
;di - óêàçàòåëü íà äåôîëòíóþ ñåêöèþ ò.å. âûáðàííóþ cx - ðàçìåð îáëàñòè. äëÿ ïðîñìîòðà |
.start_p_sh_d: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz .exit ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al,'d' |
jnz .start_p_sh_d |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov bx,cx |
mov ax,di |
mov si,parse_descript |
mov cx,parse_descript_e - parse_descript |
repe cmpsb |
jnz .rest_value_loop_sh_d ;is not compare |
sub bx,parse_descript_e - parse_descript ;correct cx |
add bx,cx |
mov cx,bx |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ðàçáîð àëÿ ' = ' |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .rest_value_loop_sh_d ;not found param timeout |
cmp ah,byte [es:di-1] ;find '=' |
jnz .rest_value_loop_sh_d |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;di óêàçûâàåò íà ñòðî÷êó, êîòîðóþ íàì íóæíî âûâîäèòü. |
;ñòðî÷êà áóäåò âûâîäèòüñÿ áëîêàìè ïî 37 ñèìâîëîâ. |
;íàñòðîèì êóäà áóäåì âûâîäèòü ò.å. íà÷àëî |
;es:di - óêàçûâàþò íà ñòðî÷êó èç êîòîðîé ìû áåðåì ñèìâîë, ds:si êóäà áóäåì âûâîäèòü |
push di |
pop si |
push es |
pop ds |
push 0xb800 |
pop es |
mov di,1040 |
mov bx,18 |
mov find_sec_di,di |
mov save_cx_d,bx |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
;clean string |
push di |
xor ax,ax |
@@: mov cx,38 |
push di |
rep stosw |
pop di |
cmp save_descript_size,bx |
jz @f |
add di,160 |
dec bx |
jnz @b |
@@: pop di |
;enter in mess |
.show_mess_prev_eq: |
lodsb |
mov ah,color_sym_lettuce;color_sym_turquoise |
; sub di,2 |
cmp al,'"' |
jz .loop_message |
cmp al,"'" |
jnz .end_sh_desc_sec |
.loop_message: |
mov cx,38 |
@@: |
lodsb |
cmp al,'"' |
jz .end_sh_desc_sec |
cmp al,"'" |
jz .end_sh_desc_sec |
stosw |
loop @b |
add find_sec_di,160 |
mov di,find_sec_di |
dec save_cx_d |
cmp save_cx_d,0 |
jnz .loop_message |
.end_sh_desc_sec: |
push save_cx_d |
pop save_descript_size |
push cs |
pop ds |
jmp .exit |
.rest_value_loop_sh_d: |
mov di,ax |
mov cx,bx |
jmp .start_p_sh_d |
.exit: |
} |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;òóò ðàñïîëîãàåòñÿ ìîäóëü ñ ïîìîùüþ êîòîðîãî áóäóò ïàðñèòüñÿ âñå îñòàëüíûå ñåêöèè |
color_sym_black equ 0 |
color_sym_blue equ 1 |
color_sym_green equ 2 |
color_sym_turquoise equ 3 |
color_sym_red equ 4 |
color_sym_lightgray equ 7 |
color_sym_lightblue equ 9 |
color_sym_lettuce equ 10 |
color_sym_pink equ 12 |
color_sym_yellow equ 14 |
macro use_any_sec |
{ |
;óçíàåì ðàáîòó ïðåäûäóùåãî øàãà ò.å. ÷åìó = timeout, åñëè îí 0, òî âèçóàëüíàÿ ÷àñòü íå áóäåò îòîáðàæåíà íà äèñïëåå ñ âûáîðîì çàãðóçî÷íûõ ñåêöèé. |
;èíà÷å ìû åå äîëæíû îòîáðàçèòü è æäàòü çàÿâëåíîå âðåìÿ äëÿ âûáîðà è êîíèãóðèðîâàíèÿ ïóêíêòîâ ñåêöèè îò ïîëüçîâàòåëÿ. |
if DEBUG |
pusha |
mov ax, word [value_timeout];èäåò ïðîâåðêà íà íàëè÷åå çíà÷åíèÿ timeout, äëÿ áîëåå áûñòðîé ðàáîòû, ýòîò ïàðàìåòð äîëæåí áûòü óæå îáðàáîòàí,ò.å. â ýòîì ñëó÷àå ïðè åãî =0 áóäåò ñôîðìèðîâàí óêàçàòåëü òîëüêî íà äåôîëòíóþ ñåêöèþ, èíà÷å èíôîðìàöèÿ áóäåò ñîáðàíà ïî âñåì ñåêöèÿì è ñîñòàâëåíû óêàçàòåëè â áëîêå ïàìÿòè |
; mov ax,cx |
mov cx, 0x0a |
mov di, show_db1 |
mov dword[ds:di], ' ' |
mov word [ds:di+4], ' ' |
call decode |
;Show size |
mov si, show_db1 |
call printplain |
; |
popa |
end if |
test ax, ax |
jz .parse_run_only |
;îòîáðàçèì ïîëíûé ñïèñîê âñåõ íàéäåíûõ ñåêöèé. |
if DEBUG |
pusha |
mov si, show_all_sect |
call printplain |
popa |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
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 |
; set keyboard typematic rate & delay |
mov al, 0xf3 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
mov al, 0 |
out 0x60, al |
xor cx, cx |
@@: |
in al, 64h |
test al, 2 |
loopnz @b |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; get start time |
call gettime |
mov dword [start_timer], eax |
mov word [timer_], newtimer |
mov word [timer_+2], cs |
;óñòàíîâèòü ñâîå ïðåðûâàíèå íà òàéìåð ò.å. êîä áóäåò ïåððûâàòüñÿ ~18 ðàç â ñåê è ïåðåõîäèòü íà îáðàáîò÷èê |
cli |
push 0 |
pop es |
push dword [es:8*4] |
pop dword [old_timer] |
push dword [timer_] |
pop dword [es:8*4] |
sti |
;ïðîöåäóðà ôîðìèðîâàíèÿ áóôåðà äëÿ ñêðîëèíãà ñåêöèé |
;if DEBUG |
; pusha |
; mov ax,point_default |
; mov ax,cx |
; mov cx,0x0a |
; mov di,show_db1 |
; mov dword[ds:di],' ' |
; mov word [ds:di+4],' ' |
; call decode |
;Show size |
; mov si,show_db1 |
; call printplain |
; |
; xor ax,ax |
; int 0x16 |
; popa |
;end if |
;;;;;;;;;;;;;ðàçìåð ïðåäûäóùåé ñåöèè óñòàíîâèì =0 |
mov save_descript_size, 18 |
;îòîáðàçèòü black screen |
show_bl_sc ;es=0xb800 |
.show_all_scr: |
get_frame_buffer ;es=0x2000 |
;îòîáðàæåíèå ñåêöèé |
call show_bl_sc_sect ;es=0xb800 |
;îòîáðàçèòü àêòèâíûé êóðñîð |
.show_active_cursor: |
show_act_cursor |
show_descript ;ìàêðîñ ïî îòîáðàæåíèþ îïèñàíèÿ ñåêöèè |
;îòîáðàçèòü Press any key .... |
mov eax, dword [old_timer] |
cmp eax, dword [timer_] |
jz .interrupt_16 |
show_timer_message |
mov word [start_stack], sp |
.interrupt_16: |
xor ax, ax ;ïîëó÷èì èíôîðìàöèþ î òîì ÷òî íàæàòî |
int 0x16 |
;check on change |
mov ebx, dword [old_timer] |
cmp ebx, dword [timer_] |
jz @f |
;restore timer interrupt |
cli |
push 0 |
pop es |
; mov eax,dword [old_timer] ; âîññòàíîâèì ïðåæäíåå ïðåðûâàíèå |
mov [es:8*4], ebx |
mov dword [timer_], ebx |
sti |
push ax |
clear_timer_msg |
pop ax |
@@: |
call clean_active_cursor ;clean old cursor ;es=0xb800 |
cmp ah, 0x48 ;ðåàêöèÿ ñèñòåìû íà ñîáûòèÿ |
jz .up |
cmp ah, 0x50 |
jz .down |
cmp ah, 0x49 |
jz .pgup |
cmp ah, 0x51 |
jz .pgdown |
cmp ah, 0x47 |
jz .home |
cmp ah, 0x4f |
jz .end |
cmp al, 0xD |
jnz .show_active_cursor |
jmp .end_show_all ;ïàðñèíã ñåêöèè êîòîðàÿ óêàçàíà â point_default |
.up: |
mov si, point_to_point_def ;çíà÷åíèå óêàçàòåëÿ |
add si, 2 |
lea ax, point_to_hframe |
cmp si, ax |
ja @f |
mov point_to_point_def, si |
mov ax, [si] |
mov point_default, ax |
jmp .show_active_cursor |
@@: |
call find_before_sect |
jmp .show_all_scr |
.down: |
mov si, point_to_point_def ;çíà÷åíèå óêàçàòåëÿ |
mov ax, point_to_eframe ;óêàçàòåëü íà ïîñëåäíèé ýëåìåíò |
sub si, 2 |
cmp si, ax |
jb @f |
mov point_to_point_def, si |
mov ax, [si] |
mov point_default, ax |
jmp .show_active_cursor |
@@: |
call find_next_sect |
jmp .show_all_scr |
.pgup: |
mov cx, size_show_section |
@@: |
push cx |
call find_before_sect |
pop cx |
loop @b |
jmp .show_all_scr |
.pgdown: |
mov cx, size_show_section |
@@: |
push cx |
call find_next_sect |
pop cx |
loop @b |
jmp .show_all_scr |
.home: |
xor di, di |
call find_next_sect.h |
jmp .show_all_scr |
.end: |
mov di, save_cx |
call find_before_sect.e |
jmp .show_all_scr |
; òóò ìû áóäåì ïàðñèòü òîëüêî äåôîëòíóþ ñåêöèþ è âûïîëíÿòü åå íè÷åãî íå ïðåäëàãàÿ ïîëüçîâàòåëþ èç äèàëîãîâ. |
.parse_run_only: |
if DEBUG |
pusha |
mov si, no_show_only_w |
call printplain |
popa |
end if |
.end_show_all: |
} |
;show black screen SL |
macro show_bl_sc |
{ |
;;;;;;;;;;;;;;; |
;î÷èñòèì ýêðàí è âûâåäåì ìåíþ |
; draw frames |
xor ax, ax |
if DEBUG |
mov ax, 0x0720 |
end if |
push 0xb800 |
pop es |
xor di, di |
; draw top |
mov cx, 25 * 80 |
rep stosw |
;;;;;;;;;;;;;;;;;;;;;;; show 'Secondary Loader v0.xxx' |
mov di, 164 |
mov si, version |
mov cx, version_end-version |
mov ah, color_sym_yellow |
@@: |
lodsb |
stosw |
loop @b |
;;;;;;;;;;;;;;;;;;;;;;; show firm )) |
mov di, (2*160-(2*(soft_mes_end-soft_mes+4))) ;286 |
mov ah, color_sym_pink;color_sym_red |
mov al, 'K' |
stosw |
mov al, ' ' |
stosw |
mov ah, color_sym_lightgray;color_sym_lightblue;color_sym_pink |
mov si, soft_mes |
mov cx, soft_mes_end- soft_mes |
@@: |
lodsb |
stosw |
loop @b |
;;;;;;;;;;;;;;;;;;;;;;; show '__________________________' |
mov di, 480 |
mov ah, color_sym_yellow |
mov al, 'Ä' |
mov cx, 61 |
rep stosw |
;;;;;;;;;;;;;;;;;;;;;;; show 'Select section' |
mov di, 804 |
mov si, select_section |
mov cx, select_section_end - select_section |
mov ah, color_sym_lightgray |
@@: |
lodsb |
stosw |
loop @b |
;;;;;;;;;;;;;;;;;;;;;;; show 'Section description' |
mov di, 880 |
mov si, section_description |
mov cx, section_description_end - section_description |
; mov ah,color_sym_lightgray |
@@: |
lodsb |
stosw |
loop @b |
} |
macro show_timer_message |
{ |
;;;;;;;;;;;;;;;;;;;;; show Press any key |
;;;;;;;;;;;;;;;;;;;;; show ramk |
xor ax, ax |
mov di, 3360 |
mov cx, 80*4 |
rep stosw |
mov di, 3362 |
mov ah, color_sym_pink |
mov al, 0xDA |
stosw |
mov al, 0xc4 |
mov cx, 76 |
rep stosw |
mov al, 0xBF |
stosw |
add di, 4 |
mov al, 0xb3 |
stosw |
add di, 152 |
stosw |
add di, 4 |
stosw |
add di, 152 |
stosw |
add di, 4 |
mov al, 0xc0 |
stosw |
mov al, 0xc4 |
mov cx, 76 |
rep stosw |
mov al, 0xd9 |
stosw |
;;;;;;;;;;;;;;;;;;;;;;;;ramk is complete show |
;show first message |
mov si, start_msg |
mov cx, start_msg_e-start_msg |
mov di, 3526 |
@@: |
lodsb |
stosw |
loop @b |
;;;;;;;;;;;;;;;;;;;; show press Enter to.... |
add di, 44 |
mov si, time_msg |
mov cx, time_msg_e-time_msg |
@@: |
lodsb |
stosw |
loop @b |
} |
macro get_frame_buffer |
{ |
mov cx, save_cx ;it's placed size of ini file |
les di, dword [file_data] |
mov si, di ;point frame |
mov bx, cx |
mov dx, size_show_section |
; mov point_to_hframe,di ; âíåñåì çíà÷åíèå, òàê ïîäñòðàõîâêà íå áîëåå |
mov al, byte [es:di] |
push word .first_ret_bl_sc |
cmp al, ' ' |
jz .first_bl_sc |
jmp get_firs_sym.not_space |
.first_bl_sc: |
jmp get_firs_sym.first_sp |
.start_hbl: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before |
cmp al, '[' |
jnz .start_hbl |
mov si, di ;point frame |
mov bx, cx |
mov dx, size_show_section |
jmp .analisist_al |
.start_bl: |
call get_firs_sym ;get first symbol on new line |
.first_ret_bl_sc: ;ïåðâûé âîçâðàò |
test cx, cx |
jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before |
.analisist_al: |
cmp al, '[' |
jnz .start_bl |
;ïðîñìàòðèâàåì ini ôàéë ñ íà÷àëà â ïîèñêàõ ñåêöèè óêàçàíîé êàê default |
;ïîèñê ôðåéìà â êîòîðîì ñîäåðæèòüñÿ çíà÷åíèå default |
.found_sect_bl: |
cmp di, point_loader |
jz .start_bl |
cmp di, point_default |
jz .save_point_def |
dec dx |
jnz .start_bl |
jmp .start_hbl |
.save_point_def: |
;èòàê äàëåå ìû äîëæíû çàïîëíèòü frame áóôåð àäðåñîâ ñåêöèé, ÷òî áû ïîòîì ïî íåìó áûñòðî ïåðåìåùàòüñÿ íå âû÷èñëÿÿ ñíîâà àäðåñà |
mov di, si ;óêàçàòåëü íà íà÷àëî |
mov cx, bx |
lea si, point_to_hframe |
mov dx, size_show_section+1 ;ò.ê. ó íàñ ñòðóêòóðà ñîäåðæèò ðàçìåð ìåæäó ïåðâûì è âòîðûì óêàçàòåëåì, òî íàì íóæíî íà 1 àäðåñ áîëüøå îáñ÷èòàòü ñåêöèé. |
;ïåðåõîäèì íà îáðàáîòêó çíà÷åíèÿ óêàçàòåëÿ |
mov al, byte [es:di] |
push word .first_ret_mfb |
cmp al, ' ' |
jz .first_bl_mbf |
jmp get_firs_sym.not_space |
.first_bl_mbf: |
jmp get_firs_sym.first_sp |
.start_mfb: |
call get_firs_sym ;get first symbol on new line |
.first_ret_mfb: ;ïåðâûé âîçâðàò |
jcxz .val_buff_comp ;.end_loader ;found or not found parametrs in section exit in section |
cmp al, '[' |
jnz .start_mfb |
.found_sect_mfb: |
cmp di, point_loader ;if we have section loader |
jz .start_mfb |
mov [si], di |
sub si, 2 |
dec dx |
jnz .start_mfb |
;bufer is full |
jmp @f |
.val_buff_comp: |
push save_cx |
pop word [si] |
sub si, 2 |
@@: |
add si, 4 |
mov point_to_eframe, si |
} |
macro show_act_cursor |
{ |
;îòîáðàæåíèå êóðñîðà ïî óìîë÷àíèþ |
lea si, point_to_hframe |
mov di, 962-160 |
mov ax, point_default |
mov cx, size_show_section |
.home_show_cur: |
mov bx, [si] |
add di, 160 |
cmp bx, ax |
jz .show_cursor_activ |
sub si, 2 |
loop .home_show_cur |
.show_cursor_activ: |
; push 0xb800 |
; pop es |
mov point_to_point_def, si |
mov ax, (color_sym_red*0x100+0x10) |
stosw |
add di, 68 |
inc ax |
stosw |
} |
macro clear_timer_msg |
{ |
push 0xb800 |
pop es |
xor ax, ax |
if DEBUG |
mov ax, 0x0720 |
end if |
;;;;;;;;;;;;;;;;;;;;; show Press any key |
mov di, 3360 |
mov cx, 80*4 |
rep stosw |
;show sect |
push ini_data_ |
pop es |
call show_bl_sc_sect ;es=0xb800 |
} |
macro show_descript |
;Ýòîò ìàêðîñ ïîêàçûâàåò êðàòêîå îïèñàíèå, åñëè îíî åñòü ó ñåêöèè â ïóíêòå |
;Section description |
{ |
local .start_p_sh_d |
local .exit |
local .rest_value_loop_sh_d |
local .end_sh_desc_sec |
local .loop_message |
local .show_mess_prev_eq |
mov di, point_default |
push ini_data_ |
mov si, point_to_point_def |
pop es |
sub si, 2 |
mov cx, [si] ;çàãðóçèì óêàçàòåëü íàñëåäóþùèþ ñåêöèþ |
sub cx, di ;âîò òåïåðü èìååì èñòèíûé ðàçìåð |
;di - óêàçàòåëü íà äåôîëòíóþ ñåêöèþ ò.å. âûáðàííóþ cx - ðàçìåð îáëàñòè. äëÿ ïðîñìîòðà |
.start_p_sh_d: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz .exit ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al, 'd' |
jnz .start_p_sh_d |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov bx, cx |
mov ax, di |
mov si, parse_descript |
mov cx, parse_descript_e - parse_descript |
repe cmpsb |
jnz .rest_value_loop_sh_d ;is not compare |
sub bx, parse_descript_e - parse_descript;correct cx |
add bx, cx |
mov cx, bx |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ðàçáîð àëÿ ' = ' |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .rest_value_loop_sh_d ;not found param timeout |
cmp ah, byte [es:di-1] ;find '=' |
jnz .rest_value_loop_sh_d |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;di óêàçûâàåò íà ñòðî÷êó, êîòîðóþ íàì íóæíî âûâîäèòü. |
;ñòðî÷êà áóäåò âûâîäèòüñÿ áëîêàìè ïî 37 ñèìâîëîâ. |
;íàñòðîèì êóäà áóäåì âûâîäèòü ò.å. íà÷àëî |
;es:di - óêàçûâàþò íà ñòðî÷êó èç êîòîðîé ìû áåðåì ñèìâîë, ds:si êóäà áóäåì âûâîäèòü |
push di |
pop si |
push es |
pop ds |
push 0xb800 |
pop es |
mov di, 1040 |
mov bx, 18 |
mov find_sec_di, di |
mov save_cx_d, bx |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
;clean string |
push di |
xor ax, ax |
@@: |
mov cx, 38 |
push di |
rep stosw |
pop di |
cmp save_descript_size, bx |
jz @f |
add di, 160 |
dec bx |
jnz @b |
@@: |
pop di |
;enter in mess |
.show_mess_prev_eq: |
lodsb |
mov ah, color_sym_lettuce;color_sym_turquoise |
; sub di,2 |
cmp al, '"' |
jz .loop_message |
cmp al, "'" |
jnz .end_sh_desc_sec |
.loop_message: |
mov cx, 38 |
@@: |
lodsb |
cmp al, '"' |
jz .end_sh_desc_sec |
cmp al, "'" |
jz .end_sh_desc_sec |
stosw |
loop @b |
add find_sec_di, 160 |
mov di, find_sec_di |
dec save_cx_d |
cmp save_cx_d, 0 |
jnz .loop_message |
.end_sh_desc_sec: |
push save_cx_d |
pop save_descript_size |
push cs |
pop ds |
jmp .exit |
.rest_value_loop_sh_d: |
mov di, ax |
mov cx, bx |
jmp .start_p_sh_d |
.exit: |
} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/parse_dat.inc |
---|
1,56 → 1,56 |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;Òóò ïðåäñòàâëåííû òåãè, äëÿ ñðàâíåíèÿ |
parse_loader db '[loader]' |
parse_loader_e: |
parse_l_timeout db 'timeout' |
parse_l_timeout_e: |
parse_l_default db 'default' |
parse_l_default_e: |
parse_name db 'ame' |
parse_name_e: |
parse_descript db 'descript' |
parse_descript_e: |
parse_LoaderModule db 'LoaderModule' |
parse_LoaderModule_e: |
parse_RamdiskSize db 'RamdiskSize' |
parse_RamdiskSize_e: |
parse_RamdiskFS db 'RamdiskFS' |
parse_RamdiskFS_e: |
parse_RamdiskSector db 'RamdiskSector' |
parse_RamdiskSector_e: |
parse_RamdiskCluster db 'RamdiskCluster' |
parse_RamdiskCluster_e: |
parse_RFS_FAT db 'FAT' |
parse_RFS_FAT_e: |
parse_RFS_KRFS db 'KRFS' |
parse_RFS_KRFS_e: |
parse_Loader_Image db 'LoaderImage' |
parse_Loader_Image_e: |
parse_RamdiskFile db 'RamdiskFile' |
parse_RamdiskFile_e: |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;Òóò ïðåäñòàâëåííû òåãè, äëÿ ñðàâíåíèÿ |
parse_loader db '[loader]' |
parse_loader_e: |
parse_l_timeout db 'timeout' |
parse_l_timeout_e: |
parse_l_default db 'default' |
parse_l_default_e: |
parse_name db 'ame' |
parse_name_e: |
parse_descript db 'descript' |
parse_descript_e: |
parse_LoaderModule db 'LoaderModule' |
parse_LoaderModule_e: |
parse_RamdiskSize db 'RamdiskSize' |
parse_RamdiskSize_e: |
parse_RamdiskFS db 'RamdiskFS' |
parse_RamdiskFS_e: |
parse_RamdiskSector db 'RamdiskSector' |
parse_RamdiskSector_e: |
parse_RamdiskCluster db 'RamdiskCluster' |
parse_RamdiskCluster_e: |
parse_RFS_FAT db 'FAT' |
parse_RFS_FAT_e: |
parse_RFS_KRFS db 'KRFS' |
parse_RFS_KRFS_e: |
parse_Loader_Image db 'LoaderImage' |
parse_Loader_Image_e: |
parse_RamdiskFile db 'RamdiskFile' |
parse_RamdiskFile_e: |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/parse_def_sect.inc |
---|
1,2094 → 1,2121 |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; â ýòîé ñåêöèè èäåò ðàçáîð ïàðàìåòðîâ óêàçàòåëü íà ñåêöèþ õðàíèòüñÿ â point_default |
;òèïû îøèáîê ïðè îáðàáîòêå ìàêðîñà |
;Ìàêðîñ RamdiskFS |
;/îïðåäåëåíèå ôëàãîâ â çàïèñè êîðíåâîé äèðåêòîðèè |
ATTR_READ_ONLY equ 0x01 |
ATTR_HIDDEN equ 0x02 |
ATTR_SYSTEM equ 0x04 |
ATTR_VOLUME_ID equ 0x08 |
ATTR_DIRECTORY equ 0x10 |
ATTR_ARCHIVE equ 0x20 |
show_error_1 equ 0x1 ;êîí÷èëèñü äàííûå - íå çàïëàíèðîâàííûé êîíåö ñåêöèè |
show_error_2 equ 0x2 ;íåò çàâåðøàþùåãî ñèìâîëà â ðàçìåðå ðàì äèñêà. |
show_error_3 equ 0x4 ; ðàì äèñê áóäåò èìåòü ðàçìåð =64 êá. |
show_error_4 equ 0x8 ; |
macro use_parse_def_sect |
{ |
mov di,point_default |
push ini_data_ |
pop es |
mov si,point_to_point_def |
sub si,2 |
mov cx,[si] ;çàãðóçèì óêàçàòåëü íàñëåäóþùèþ ñåêöèþ |
xor ax,ax ;îáíóëèì àx äëÿ î÷èñòêè ôëàãîâ |
sub cx,di ;âîò òåïåðü èìååì èñòèíûé ðàçìåð |
mov save_cx_d,cx ;ñîõðàíèì çíà÷åíèå cx ñâîåé ïåðåìåííîé |
;îáíóëèì ïåðåìåííóþ ôëàãîâ, ýòî íåîáõîäèìî, äëÿ òîãî, ÷òî áû èçáåæàòü îáðàáîòêó ïîâòîðÿþùèõñÿ çíà÷åíèé |
mov status_flag,ax |
;;;; |
;ÂÕîä â îáðàáîòêó ïàðñèíãà çíà÷åíèé ñåêöèé. es:di - óêàçàòåëü íà íà÷àëî ñåêöèè cx ðàçìåð ñåêöèè äîñòóïíîé äëÿ ïàðñèíãà |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;ñîãëàøåíèå íå ðàçðóøàåì bp, es, cs, sp |
;use_Loader_Image ;çàãðóçèòü îáðàç âûøå 1 ìá |
use_RamdiskFS |
;ïðîâåðÿåòñÿ ñàìûé ïîñëåäíèé. |
use_LoaderModule ;îñîáåííîñòü - ïåðåäàåò óïðàâëåíèå íà çàãðóæåííûé ìîäóëü. |
} |
macro use_LoaderModule |
;êàê âàðèàíò ñåé÷àñ èñïîëüçóåòñÿ ìîäåëü, ïðè çàãðóçêå ìîäóëÿ íà íåãî ïåðåäàåòñÿ óïðàâëåíèå, ðåøåíèå âðåìåíîå |
;óïðàâëåíèå áóäåò ïåðåäàâàòüñÿ òîëüêî ïîñëå îáðàáîòêè âñåé ñåêöèè |
{ |
local .found_end_str |
mov di,point_default ;restore value |
mov cx,save_cx_d |
;îáðàáîòêà êîíñòðóêöèè òèïà LoaderModule=kord/kolibri.ldm |
.start_p_LM: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz ._afterLoaderModule ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al,'L' |
jnz .start_p_LM |
;ïðîâåðêà íà çíà÷åíèå LoaderModule |
; parse_LoaderModule |
mov bx,cx |
mov ax,di |
mov si,parse_LoaderModule |
mov cx,parse_LoaderModule_e - parse_LoaderModule |
repe cmpsb |
jnz .rest_value_loop_LM ;is not compare |
sub bx,parse_LoaderModule_e - parse_LoaderModule ;correct cx |
add bx,cx |
mov cx,bx |
test status_flag,flag_found_LM ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_LM |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_LM: |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .rest_value_loop_LM ;not found param timeout |
cmp ah,byte [es:di-1] ;find '=' |
jnz .rest_value_loop_LM |
repe scasb ;cut ' ' |
inc cx |
dec di |
;di óêàçûâàåò íà íà÷àëî áëîêà èíôîðìàöèè, â cx äëèííà äî êîíöà ñåêöèè. |
;ïîñëå çàãðóçêè çàíîñèòüñÿ çíà÷åíèå çàíÿòîé ïàìÿòè. |
;äëÿ òîãî ÷òî áû çàãðóçèòü ìîäóëü, âîñïîëüçóåìñÿ callback ñåðâèñîì |
;îðèãèíàëüíîå ðåøåíèå - ðàçìåñòèì dd ïåðåä ñòðî÷êîé è ïîñëå ñòðî÷êè ðàçìåñòèì byte =0 |
;ýòî âûãëÿäèò òàê: â ini ôàéëå ñóùåñòâóåò ñòðî÷êà LoaderModule = kord/kernel.loader |
;ìû åå ìîäèôèöèðóåì äî òàêîãî ñîñòîÿíèÿ dw,dw,db'kord/kernel.loader',0 êîíå÷íî ñîõðàíèâ òå çíà÷åíèÿ êîòîðûå ìû çàìåíÿåì |
;ñîõðàíèëè ïåâûå 2 word |
push dword [es:di-6] |
lea si,[di-6] |
push word [es:di-2] |
xor ax,ax |
mov word [es:di-6],ax ;âíîñèì íóæíûå çíà÷åíèÿ |
;info_real_mode_size ðàçìåð è óêàçàòåëü íà îáëàñòü â êîòîðóþ ìîæíî çàãðóçèòüñÿ |
mov ax,info_real_mode_size ;0x3000 ;ñëåäóþùèé ñåãìåíò çà äàííûìè |
mov word [es:di-4],ax |
mov word [es:di-2],16 ;êîë-âî áëîêîâ ïî 4 êá =64 êá ò.å. áîëüøå íå ñ÷èòàåì |
;;;;;; ïîèñê êîíöà ñòðî÷êè |
@@: mov al,byte [es:di] |
cmp al,' ' |
jz .found_end_str |
cmp al,0xa |
jz .found_end_str |
cmp al,0xd |
jz .found_end_str |
inc di |
dec cx |
jnz @b |
;;;not found äîïóñòèì,÷òî ýòî êîíåö ôàéëà è îí íå èìååò ïðèâû÷íîãî çàâåðåøíèÿ ñòðîêè |
.found_end_str: |
push word [es:di] |
xor ax,ax |
mov word [es:di],ax |
; xor ax,ax ; function 1 - read file |
mov di,si ;file_data |
inc ax |
push si |
push es |
push es |
pop ds |
push cs |
pop es |
call far dword [es:loader_callback] |
push cs |
pop ds |
pop es |
pop si |
test bx,bx |
jnz .error_LM |
jmp far dword [es:si] |
.error_LM: |
call error.LoaderModule |
.rest_value_loop_LM: |
mov di,ax |
mov cx,bx |
jmp .start_p_LM |
._afterLoaderModule: |
} |
macro use_RamdiskFS |
; ôîðìèðîâàíèå ðàì äèñêà, + îáðàáîòêà âñåãî ñâÿçàííîãî. |
{ |
if DEBUG |
local ._not_memory_in_sys |
;//////// clear window |
mov ax,3 |
int 0x10 |
;\\\\\\\\\ clear window is end |
mov si,ramdiskFS_st |
call printplain |
end if |
; îáíóëèì ðåãèñòð ñîñòîÿíèÿ îøèáîê |
xor ax,ax |
mov show_errors_sect,ax |
use_free_memory ; óçíàåì êàêîãî îáúåìà ó íàñ äîñòóïíà ïàìÿòü. çíà÷åíèå âîçàðàùàåòñÿ â ax |
;óçíàåì ñêîëüêî ó íàñ åñòü ïàìÿòè è ñìîæåì ëè ìû ñôîðìèðîâàòü íóæíîãî ðàçìåðà ðàì äèñê. |
use_RamdiskSize ;çíà÷åíèå âîçâðàùàåòñÿ â bx |
cmp free_ad_memory,bx ; ðàçìåðíîñòü â êá. |
jbe ._not_memory_in_sys |
movzx eax,bx |
shl eax,10 ;*1024 = get size in byte |
mov save_ramdisksize,eax ; ñîðõàíèì ðàçìåð â byte |
get_type_FS ;ïîëó÷èì òèï ôàéëîâîé ñèñòåìû + ñîçäàäèì åå |
._not_memory_in_sys: |
if DEBUG |
;pause |
xor ax,ax |
int 0x16 |
end if |
} |
macro use_RamdiskSize |
{ |
local .start_p_RS |
local .correct_is_not_set_RS |
local .CS |
local .correct_val_RS |
local .correct_size_RS |
local .rest_value_loop_RS |
local .end_get_RS_ERROR_1 |
local .end_get_RS_ERROR_2 |
local ._end_parse_RS |
;îáðàáàòûâàåòñÿ ðàçìåð ôîðìèðóåìîãî ðàì äèñêà |
;çàãðóçèì íà÷àëî ñåêöèè, ò.ê. áóäåì ïðîñìàòðèâàòü ñ íà÷àëà è âñþ ñåêöèþ |
mov di,point_default ;restore value |
mov cx,save_cx_d |
.start_p_RS: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz ._end_parse_RS ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al,'R' |
jnz .start_p_RS |
;ïðîâåðêà íà çíà÷åíèÿ RamdiskSize |
; parse_RamdiskSize |
mov bx,cx |
mov ax,di |
mov si,parse_RamdiskSize |
mov cx,parse_RamdiskSize_e - parse_RamdiskSize |
repe cmpsb |
jnz .rest_value_loop_RS ;is not compare |
sub bx,parse_RamdiskSize_e - parse_RamdiskSize ;correct cx |
add bx,cx |
mov cx,bx |
test status_flag,flag_found_RS ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_RS |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_RS: |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .end_get_RS_ERROR_1 ;not found param |
cmp ah,byte [es:di-1] ;find '=' |
jnz .start_p_RS ; ïåðåéäåì íà íà÷àëî è ïîïðîáóåì íàéòè åùå ñåêöèþ |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;Òóò íóæíî ïðåîáðàçîâûâàòü ñòðî÷êó â öèôðîâîå çíà÷åíèå. |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
xor bx,bx |
mov cx,5 |
@@: mov al,byte [es:di] |
cmp al,'0' |
jb .CS |
cmp al,'9' |
jbe .correct_val_RS |
.CS: |
cmp al,'K' |
jz .correct_size_RS |
jmp .end_get_RS_ERROR_2 |
.correct_val_RS: |
imul bx,10 |
xor al,0x30 |
add bl,al |
inc di |
loop @b |
.correct_size_RS: |
;âîçìîæåí 1 âàðèàíò, êîãäà ðàçìåð çàäàí â K êèëëîáàéòàõ |
;âíóòðåííûé ôîðìàò äàííûõ ýòî êîë-âî çàïðîùåíîé ïàìÿòè â êá. |
test bx,bx |
jnz @f ;åñëè çíà÷åíèå îòëè÷íî îò 0 |
;;;;;ñîîáùåíèå îá îøèáêå, ðàçìåð "íàéäåíîãî" áëîêà =0 ìèíèìàëüíî ìû äîëæíû |
;óñòàíîâèòü 64 êá ðàçìåð ðàì äèñêà. |
or show_errors_sect,show_error_3 |
mov bx,64 |
@@: |
jmp ._end_parse_RS |
.rest_value_loop_RS: |
mov di,ax |
mov cx,bx |
jmp .start_p_RS |
.end_get_RS_ERROR_1: |
;ñîîáùåíèå îá îøèáêå - äàííûé ó÷àñòîê êîäà íå áûë êîððåêòíî îáðàáîòàí :( |
or show_errors_sect,show_error_1 |
jmp ._end_parse_RS |
.end_get_RS_ERROR_2: |
or show_errors_sect,show_error_2 |
._end_parse_RS: |
if DEBUG |
pusha |
movzx eax,bx |
mov cx,0x0a |
mov di,RamdiskSize_msg |
mov dword[ds:di],' ' |
mov word [ds:di+4],' ' |
call decode |
;Show size |
mov si,RamdiskSize_msg |
call printplain |
popa |
end if |
} |
macro use_free_memory |
{ |
local _support_function_use_free_memory |
;ìàêðîñ äëÿ ïîëó÷åíèÿ îáùåãî ÷èñëà äîñòóïíîé ïàìÿòè â êá, äëÿ ôîðìèðîâàíèÿ ðàì äèñêà çà ïðåäåëàìè 1 ìá. |
;èñïîëüçóåòñÿ 0õ88 ôóíêöèÿ 0õ15 ïðåðûâàíèÿ |
; åñëè ïîääåðæèâàåòñÿ ôóíêöèÿ, òî â ax çíà÷åíèå â êá, åñëè íåò, òî â ax=0 |
mov ah,0x88 ;ah,0x88 |
int 0x15 |
jnc ._support_function_use_free_memory |
xor ax,ax |
;âîçâðàùàåò â ax ÷èñëî â êá |
._support_function_use_free_memory: |
mov free_ad_memory,ax ; åñëè íå ïîääåðæèâàåòñÿ áèîñîì, òî â ax=0 |
if DEBUG |
pushad |
movzx eax,ax |
mov cx,0x0a |
mov di,free_memory_msg |
mov dword[ds:di],' ' |
mov word [ds:di+4],' ' |
call decode |
;Show size |
mov si,free_memory_msg |
call printplain |
popad |
end if |
} |
macro show_ERRORS |
{ |
} |
macro get_type_FS ;ïîëó÷èòü è ñîçäàòü îáðàç äëÿ çàäàííîé RFS. |
{ |
mov di,point_default ;restore value |
mov cx,save_cx_d |
.start_g_tpe_RFS: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz ._end_parse_FRS ;._end_get_type_RFS ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al,'R' |
jnz .start_g_tpe_RFS |
;ïðîâåðêà íà çíà÷åíèÿ RamdiskSize |
; parse_RamdiskSize |
mov bx,cx |
mov ax,di |
mov si,parse_RamdiskFS |
mov cx,parse_RamdiskFS_e - parse_RamdiskFS |
repe cmpsb |
jnz .start_g_tpe_RFS_rest_v ;is not compare |
sub bx,parse_RamdiskFS_e - parse_RamdiskFS ;correct cx |
add bx,cx |
mov cx,bx |
test status_flag,flag_found_GTRFMS ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_FRS |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_FRS: |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
test cx,cx |
jz .end_get_FRS_ERROR_1 ;not found param |
cmp ah,byte [es:di-1] ;find '=' |
jnz .start_g_tpe_RFS ; ïåðåéäåì íà íà÷àëî è ïîïðîáóåì íàéòè åùå ñåêöèþ |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;Òóò íóæíî ïðåîáðàçîâûâàòü ñòðî÷êó â öèôðîâîå çíà÷åíèå. |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov bx,cx |
mov ax,di |
mov si,parse_RFS_FAT |
mov cx,parse_RFS_FAT_e - parse_RFS_FAT |
repe cmpsb |
jnz .krfs_cmp ;is not compare |
make_FAT_RamFS ;ñäåëàòü |
if DEBUG |
pusha |
mov si,make_fat12_RFS_msg |
call printplain |
popa |
end if |
jmp ._end_parse_FRS |
.krfs_cmp: |
mov cx,bx |
mov di,ax |
mov si,parse_RFS_KRFS |
mov cx,parse_RFS_KRFS_e - parse_RFS_KRFS |
repe cmpsb |
; jnz @f ;is not compare |
jmp ._end_parse_FRS |
.start_g_tpe_RFS_rest_v: |
mov cx,bx |
mov di,ax |
jmp .start_g_tpe_RFS |
.end_get_FRS_ERROR_1: |
;ñîîáùåíèå îá îøèáêå - äàííûé ó÷àñòîê êîäà íå áûë êîððåêòíî îáðàáîòàí :( |
or show_errors_sect,show_error_1 |
jmp ._end_parse_FRS |
.end_get_FRS_ERROR_2: |
or show_errors_sect,show_error_2 |
._end_parse_FRS: |
if DEBUG |
pusha |
mov si,get_type_FS_msg |
call printplain |
popa |
end if |
} |
macro make_FAT_RamFS |
{ |
local .RS1 |
local .fat12 |
local .fat16 |
; ìû äîëæíû ñôîðìèðîâàòü â íà÷àëüíûé îáðàç Ram FS, à ïîòîì çàïèñàòü åãî çà îáëàñòü âûøå 1 ìá.. |
;äëÿ ñëó÷àÿ ñ FAT12 |
; mov di,fat12_buffer ;ds äîëæåí áûòü = cs |
;es:di - óêàçûâàþò íà íà÷àëî áëîêà äëÿ ôîðìèðîâàíèÿ ðàì ôñ. |
use_RamdiskSector ;âîçðàùàåìîå çíà÷åíèå â ax ðàçìåð ñåêòîðà â áàéòàõ |
cmp ax,4096 ;ïî ñïåöèôèêàöèè çíà÷åíèå äîëæíî áûòü â ïðåäåëàõ îò 1 äî 4096 |
ja .RS1 |
test ax,ax |
jnz @f ;îøèáêà åñëè ñþäà ïðûãíóëè âñå òàêè ... |
.RS1: mov word [fat12_buffer.BPB_BytsPerSec],512 |
;;;;;;;;;;ñêàæåì ÷òî ïî äåôîëòó áóäåì þçàòü çíà÷åíèå... |
@@: mov word [fat12_buffer.BPB_BytsPerSec],ax ;òóò âñå îê |
;BPB_SecPerClus êîë-âî ñåêòîðîâ â êëàñòåðå |
use_RamdiskCluster ;âîçðàùàåìîå çíà÷åíèå â al |
cmp al,128 |
ja @f |
; test al,0x1 ;ïðîâåðêà íà êðàòíîñòü ) |
; jnz @f |
mov byte [fat12_buffer.BPB_SecPerClus],al |
;incorrect value will be set dafault |
;íèæå íåêîððåêòíîå çíà÷åíèå â ò.ê. ðàçìåð êðàòåí 2 è â äèàïàçîíå îò 1 äî 128 âêëþ÷èòåëüíî |
; ìû äîëæíû ðóãíóòüñÿ íà ýòî |
;@@: ;mov byte [fat12_buffer.BPB_SecPerClus],1 |
;;;;; îïðåäåëåèì êàêàÿ ó íàñ áóäåò èñïîëüçîâàòüñÿ FAT |
;ïî óñëîâèþ, fat12<4085<=fat16<65525<=fat32 |
; fat12_buffer.BPB_BytsPerSec*fat12_buffer.BPB_SecPerClus = êîë-âî ñåêòîðîâ |
movzx eax,word [fat12_buffer.BPB_BytsPerSec] |
movzx ebx,byte [fat12_buffer.BPB_SecPerClus] |
imul ebx,eax ;òóò ðàçìåðíîñòü ñåêòîðà |
mov eax,save_ramdisksize ;ðàçìåð çàïðîøåííîãî ðàì äèñêà â áàéòàõ |
cdq |
idiv ebx |
;;;;;;;; ñåé÷àñ ÷àñòíîå â eax, à îñòàòîê â edx |
;ïîëó÷èì êîë-âî ñåêòîðîâ, è ìîæåì óæå îïðåäåëèòü òèï FAT êîòîðóþ íóæíî äåëàòü. |
cmp eax,4085 |
jb .fat12 |
cmp eax,65525 |
jb .fat16 |
;;;;;;;;;;;;;;;;;;;;;;;; òóò fat32 |
mov set_ramfs,32 ;óñòàíîâèì òèï ôàéëîâîé ñèñòåìû |
mov word [fat12_buffer.BPB_RsvdSecCnt],32 |
xor eax,eax |
mov word [fat12_buffer.BPB_RootEntCnt],ax |
mov word [fat12_buffer.BPB_TotSec16],ax |
mov dword [fat12_buffer.BPB_TotSec32],eax |
.fat16: ;fat16 |
;Äëÿ FAT12 è FAT16 äèñêîâ ýòî ïîëå ñîäåðæèò êîëè÷åñòâî ñåêòîðîâ, à BPB_TotSec32 ðàâíî 0, åñëè çíà÷åíèå <óìåùàåòñÿ> (ìåíüøå 0x10000). |
jmp $ |
mov set_ramfs,16 ;óñòàíîâèì òèï ôàéëîâîé ñèñòåìû |
movzx ebx,byte [fat12_buffer.BPB_SecPerClus] |
imul eax,ebx |
cmp eax,0x10000 |
jae @f |
mov word [fat12_buffer.BPB_TotSec16],ax |
mov dword [fat12_buffer.BPB_TotSec32],0 |
@@: |
;êîëè÷åñòâî ñåêòîðîâ çàíèìàåìîå îäíîé êîïèåé ôàò |
; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Äëÿ FAT12/FAT16 ýòî êîëè÷åñòâî ñåêòîðîâ îäíîé FAT. ?? |
;;;; çàïîëíèì BPB_RootEntCnt Äëÿ FAT12 è FAT16 äèñêîâ, ýòî ïîëå ñîäåðæèò ÷èñëî |
;32-áàéòíûõ ýëåìåíòîâ êîðíåâîé äèðåêòîðèè. Äëÿ FAT32 äèñêîâ, ýòî ïîëå äîëæíî |
;áûòü 0. Ïîêà êîíñòàíòà, íóæíî áóäåò ïîçæå äîäåëàòü. |
mov eax,root_dir_entry_count |
mov word [fat12_buffer.BPB_RootEntCnt],ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) |
;ïî äîêóìåíòàöèè ðåêîìåíäóþò îòðåçàòü 16 êá äëÿ ðóò äèð íî ýòî î÷ ìíîãî, äàæå äëÿ êîîñ. èìõî äëÿ íà÷àëà õâàòèò è 7 êá |
;;;;;;; |
;Äëÿ FAT16 ýòî êîëè÷åñòâî ñåêòîðîâ îäíîé FAT. Äëÿ FAT32 ýòî çíà÷åíèå |
;ðàâíî 0, à êîëè÷åñòâî ñåêòîðîâ îäíîé FAT ñîäåðæèòñÿ â BPB_FATSz32. |
;RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec; |
;TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors); |
;TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs; |
;If(FATType == FAT32) |
; TmpVal2 = TmpVal2 / 2; |
;FATSz = (TMPVal1 + (TmpVal2 - 1)) / TmpVal2; |
;If(FATType == FAT32) { |
; BPB_FATSz16 = 0; |
; BPB_FATSz32 = FATSz; |
;} else { |
; BPB_FATSz16 = LOWORD(FATSz); |
; /* there is no BPB_FATSz32 in a FAT16 BPB */ |
;} |
;===================================== |
;RootDirSectors |
movzx ebx, word [fat12_buffer.BPB_BytsPerSec] |
imul eax,32 |
add eax,ebx |
dec eax |
cdq |
idiv ebx |
;;;;;;;; ñåé÷àñ ÷àñòíîå â eax, à îñòàòîê â edx äëÿ äèñêåòû 1.44 ó íàñ äîëæíî áûòü çíà÷åíèå =14 |
;BPB_ResvdSecCnt + RootDirSectors |
movzx ebx, word [fat12_buffer.BPB_RsvdSecCnt] |
add ebx,eax |
;DskSize ó íàñ ýòî çíà÷åíèå óæå ïîëó÷åíî è äîñòóïíî |
movzx eax,word [fat12_buffer.BPB_TotSec16] ;äîëæåí áûòü â ñåêòîðàõ |
sub eax,ebx |
;TmpVal1=eax |
shl edi,8 ;=edi*256 |
movzx ecx,byte [fat12_buffer.BPB_NumFATs] |
add edi,ecx |
;TmpVal2=edi |
add eax,edi |
dec eax |
cdq |
idiv edi |
;FATSz = ñåé÷àñ ÷àñòíîå â eax, à îñòàòîê â edx |
mov word [fat12_buffer.BPB_FATSz16],ax |
.fat12: ;fat12 |
if DEBUG |
; âûâåäåì â îòëàäêå, ÷òî ñîáèðàåìñÿ äåëàòü îáðàç äèñêà c FS=fat12 |
pushad |
mov si,start_making_FAT12_msg |
call printplain |
popad |
end if |
;Äëÿ FAT12 è FAT16 äèñêîâ ýòî ïîëå ñîäåðæèò êîëè÷åñòâî ñåêòîðîâ, à BPB_TotSec32 ðàâíî 0, åñëè çíà÷åíèå <óìåùàåòñÿ> (ìåíüøå 0x10000). |
mov set_ramfs,12 ;óñòàíîâèì òèï ôàéëîâîé ñèñòåìû |
movzx ebx,byte [fat12_buffer.BPB_SecPerClus] |
imul eax,ebx |
cmp eax,0x10000 |
jae @f |
mov word [fat12_buffer.BPB_TotSec16],ax |
mov dword [fat12_buffer.BPB_TotSec32],0 |
@@: |
;êîëè÷åñòâî ñåêòîðîâ çàíèìàåìîå îäíîé êîïèåé ôàò |
; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Äëÿ FAT12/FAT16 ýòî êîëè÷åñòâî ñåêòîðîâ îäíîé FAT. ?? |
;;;; çàïîëíèì BPB_RootEntCnt Äëÿ FAT12 è FAT16 äèñêîâ, ýòî ïîëå ñîäåðæèò ÷èñëî |
;32-áàéòíûõ ýëåìåíòîâ êîðíåâîé äèðåêòîðèè. Äëÿ FAT32 äèñêîâ, ýòî ïîëå äîëæíî |
;áûòü 0. Ïîêà êîíñòàíòà, íóæíî áóäåò ïîçæå äîäåëàòü. |
mov eax,root_dir_entry_count |
mov word [fat12_buffer.BPB_RootEntCnt],ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) |
;ïî äîêóìåíòàöèè ðåêîìåíäóþò îòðåçàòü 16 êá äëÿ ðóò äèð íî ýòî î÷ ìíîãî, äàæå äëÿ êîîñ. èìõî äëÿ íà÷àëà õâàòèò è 7 êá |
;;;;;;; |
;DskSize(â ñåêòîðàõ)*12 (ðàçìåðíîñòü ôàéëîâîé ñèñòåìû, ò.å ïðåäïîëîæèì ñêîëüêî áèòîâ ïîòðåáóåòñÿ äëÿ àäðåñàöèè ýòîãî îáúåìà) /8 (÷òî ïîëó÷èòü ðàçìåð â áàéòàõ) |
;ïîëó÷åííîå ÷èñëî îêðóãëÿåì â áîëüøóþ ñòîðîíó êðàòíîå ñåêòîðó ò.å. 512 áàéò Òàêîé ïîäõîä íå óíèâåðñàëåí, íî ïîêà ïîéäåò |
;âîîáùå ó ìåëêîñîôò ýòî âñå ñ÷èòàåòñÿ ðó÷êàìè, íî ìû áóäåì þçàòü òîëüêî ïîä êîîñ ðàì äèñê ñ ôàò12 |
movzx eax, word [fat12_buffer.BPB_TotSec16] |
imul eax,12 |
shr eax,3 ;äåëèì íà 8 íî ò.å. íàì íóæíî äåëèòü åùå è íà 512 èëè áîëåå â çàâèñèìîñòè îò ðàçìåðîâ êëàñòåðà |
movzx ebx,word [fat12_buffer.BPB_BytsPerSec] ;ðàçìåð ñåêòîðà |
cdq |
idiv ebx ;ðàçäåëèì íà ðàçìåð êëàñòåðà |
;ñåé÷àñ ó íàñ â eax çíà÷åíèå åãî íóæíî îêðóãëèòü â áîëüøóþ ñòîðîíó êðàòíîìó 512 áàéòàì |
;ïðèìåíèì ñëåäóþùåå î÷èñòèì and è äîáàâèì 512 áàéò. òàêèì îáðàçîì âûðàâíèì íà 512 áàéò |
;íî ò.ê. âñå ðàâíî äåëèòü íèæíèé êîä íàì íå íóæåí |
; and eax,0xfff200 |
; add eax,0x200 ;äîáàâèì 512 áàéò äëÿ 1.44 äèñêåòû èäåàëüíî ïîäõîäèò )) |
inc ax |
;ïî èäåå äîëæíî íà êàæäóþ ôàò òàáëèöó |
;ðåçåðâèðîâàòüñÿ 9 ñåêòîðîâ ò.å. ïîëó÷àåòñÿ 2*9=18+1 =19 ñåêòîðîâ ò.å. ðóò äèð íàõîäèòüñÿ íà ñ 20 ñåòîðà ò.å. ñ àäðåñà 0õ2600 |
;ñåé÷àñ íóæíî âû÷èñëèòü ñêîëüêî áóäåò ñåêòîðîâ çàíèìàòü ôàò ) íóæíî ðàçäåëèòü íà 512 |
;FATSz = ñåé÷àñ ÷àñòíîå â eax |
mov word [fat12_buffer.BPB_FATSz16],ax |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
get_firstDataSector ;ïîëó÷èòü ñìåùåíèå äî äàííûõ |
;ñîçäàäèì ïåâóþ çàïèñü â ôàò ïî îïðåäåëåííîìó àäðåñó. |
first_create_fat_table |
;çàêèíèì BPB ôàéëîâîé ñèñòåìû çà 1 ìá. |
use_BPB_RAM |
; |
;êîïèðîâàíèå ôàéëà. |
use_RamdiskFile |
;;;; âû÷èñëÿåì óêàçàòåëü íà êîðíåâóþ äèð FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16); |
; movzx ebx, [fat12_buffer.BPB_NumFATs] |
; movzx eax,ax |
; imul eax,ebx |
;eax=(BPB_NumFATs * BPB_FATSz16) |
; inc eax |
; BPB_ResvdSecCnt çíà÷åíèå òîëüêî 1 äëÿ fat12/16 |
;â eax óêàçàòåëü íà root dir. äëÿ äèñêåòû fat12 äîëæíî ïîëó÷èòüñÿ ïðè êîë-âî êîïèé fat 1 = 1+ (1*1) =2 èëè 3 |
if DEBUG |
pusha |
; mov ax,point_default |
; mov ax,cx |
mov cx,0x0a |
mov di,show_db1 |
; mov dword[ds:di],' ' |
; mov word [ds:di+4],' ' |
call decode |
;Show size |
mov si,show_db1 |
call printplain |
; |
; xor ax,ax |
; int 0x16 |
popa |
end if |
} |
macro use_RamdiskSector |
{ |
;äëÿ íåêîòîðûõ FS áóäåò èãíîðèðîâàòüñÿ |
mov di,point_default ;restore value |
mov cx,save_cx_d |
.start_RamdiskSector: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz .end_RamdiskSector ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al,'R' |
jnz .start_RamdiskSector |
;ïðîâåðêà íà çíà÷åíèÿ RamdiskSize |
; parse_RamdiskSize |
mov bx,cx |
mov ax,di |
mov si,parse_RamdiskSector |
mov cx,parse_RamdiskSector_e - parse_RamdiskSector |
repe cmpsb |
jnz .RamdiskSector_rest_val ;is not compare |
sub bx,parse_RamdiskSector_e - parse_RamdiskSector ;correct cx |
add bx,cx |
mov cx,bx |
test status_flag,flag_found_RamdiskSector ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_RamdiskSector |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_RamdiskSector: |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .end_get_RamS_ERROR_1 ;not found param |
cmp ah,byte [es:di-1] ;find '=' |
jnz .start_RamdiskSector ; ïåðåéäåì íà íà÷àëî è ïîïðîáóåì íàéòè åùå ñåêöèþ |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
xor bx,bx |
mov cx,4 |
@@: movzx ax,byte [es:di] |
cmp al,'0' |
jb .end_RamdiskSector |
cmp al,'9' |
ja .end_RamdiskSector |
;;;;;;;;;;;;;;;;;;; |
imul bx,10 |
xor al,0x30 |
add bx,ax |
inc di |
loop @b |
jmp .end_RamdiskSector |
.RamdiskSector_rest_val: |
mov cx,bx |
mov di,ax |
jmp .start_RamdiskSector |
.end_get_RamS_ERROR_1: |
.end_RamdiskSector: |
mov ax,bx |
if DEBUG |
pusha |
movzx eax,bx;save_cx_d;point_default |
mov cx,0x0a |
mov di,RamdiskSector_msg |
mov dword[ds:di],' ' |
mov dword [ds:di+4],' ' |
call decode |
;Show size |
mov si,RamdiskSector_msg |
call printplain |
popa |
end if |
; pop di |
; pop es |
} |
macro use_RamdiskCluster |
{ |
;äëÿ íåêîòîðûõ FS áóäåò èãíîðèðîâàòüñÿ |
; push es |
; push di |
mov di,point_default ;restore value |
mov cx,save_cx_d |
; push ini_data_ |
; pop es |
.start_RamdiskCluster: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz .end_RamdiskCluster ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al,'R' |
jnz .start_RamdiskCluster |
;ïðîâåðêà íà çíà÷åíèÿ RamdiskSize |
; parse_RamdiskSize |
mov bx,cx |
mov ax,di |
mov si,parse_RamdiskCluster |
mov cx,parse_RamdiskCluster_e - parse_RamdiskCluster |
repe cmpsb |
jnz .RamdiskCluster_rest_val ;is not compare |
sub bx,parse_RamdiskCluster_e - parse_RamdiskCluster ;correct cx |
add bx,cx |
mov cx,bx |
test status_flag,flag_found_RamdiskCluster ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_RamdiskCluster |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_RamdiskCluster: |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .end_get_RamSC_ERROR_1 ;not found param |
cmp ah,byte [es:di-1] ;find '=' |
jnz .start_RamdiskCluster ; ïåðåéäåì íà íà÷àëî è ïîïðîáóåì íàéòè åùå ñåêöèþ |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
@@: movzx ax,byte [es:di] |
cmp al,'0' |
jb .end_RamdiskCluster |
cmp al,'9' |
ja .end_RamdiskCluster |
;;;;;;;;;;;;;;;;;;; |
xor al,0x30 |
jmp .end_RamdiskCluster |
.RamdiskCluster_rest_val: |
mov cx,bx |
mov di,ax |
jmp .start_RamdiskCluster |
.end_get_RamSC_ERROR_1: |
.end_RamdiskCluster: |
if DEBUG |
pusha |
mov cx,0x0a |
mov di,RamdiskCluster_msg |
; mov word[ds:di],' ' |
call decode |
;Show size |
mov si,RamdiskCluster_msg |
call printplain |
popa |
end if |
} |
macro use_Loader_Image |
;ïðåäíàçíà÷åí äëÿ çàãðóçêè îáðàçîâ âûøå 1 Ìá. |
;ïåðâîíà÷àëüíàÿ âåðñèÿ çàãðóæàåò îáðàç äèñêåòû 1.44 ìá |
{ |
local .start_p_LI |
local .exit |
local .error_LI |
local .rest_value_loop |
local .found_end_str |
mov di,point_default ;restore value |
mov cx,save_cx_d |
;îáðàáîòêà êîíñòðóêöèè òèïà LoaderModule=kord/kolibri.ldm |
.start_p_LI: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz .exit ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al,'L' |
jnz .start_p_LI |
;ïðîâåðêà íà çíà÷åíèå LoaderModule |
; parse_LoaderModule |
mov bx,cx |
mov ax,di |
mov si,parse_LoaderImage |
mov cx,parse_LoaderImage_e - parse_LoaderImage |
repe cmpsb |
jnz .rest_value_loop ;is not compare |
sub bx,parse_LoaderImage_e - parse_LoaderImage ;correct cx |
add bx,cx |
mov cx,bx |
; test status_flag,flag_found_LM ;îöåíêà ôëàãîâ |
; jz .correct_is_not_set_LI |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
;.correct_is_not_set_LI: |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .rest_value_loop_LI ;not found param timeout |
cmp ah,byte [es:di-1] ;find '=' |
jnz .rest_value_loop_LI |
repe scasb ;cut ' ' |
inc cx |
dec di |
;di óêàçûâàåò íà íà÷àëî áëîêà èíôîðìàöèè, â cx äëèííà äî êîíöà ñåêöèè. |
;ïîñëå çàãðóçêè çàíîñèòüñÿ çíà÷åíèå çàíÿòîé ïàìÿòè. |
;äëÿ òîãî ÷òî áû çàãðóçèòü ìîäóëü, âîñïîëüçóåìñÿ callback ñåðâèñîì |
;îðèãèíàëüíîå ðåøåíèå - ðàçìåñòèì dd ïåðåä ñòðî÷êîé è ïîñëå ñòðî÷êè ðàçìåñòèì byte =0 |
;ýòî âûãëÿäèò òàê: â ini ôàéëå ñóùåñòâóåò ñòðî÷êà LoaderModule = kord/kernel.loader |
;ìû åå ìîäèôèöèðóåì äî òàêîãî ñîñòîÿíèÿ dw,dw,db'kord/kernel.loader',0 êîíå÷íî ñîõðàíèâ òå çíà÷åíèÿ êîòîðûå ìû çàìåíÿåì |
;ñîõðàíèëè ïåâûå 2 word |
push dword [es:di-6] |
lea si,[di-6] |
push word [es:di-2] |
xor ax,ax |
mov word [es:di-6],ax ;âíîñèì íóæíûå çíà÷åíèÿ |
;info_real_mode_size ðàçìåð è óêàçàòåëü íà îáëàñòü â êîòîðóþ ìîæíî çàãðóçèòüñÿ |
mov ax,info_real_mode_size ;0x3000 ;ñëåäóþùèé ñåãìåíò çà äàííûìè |
mov word [es:di-4],ax |
mov word [es:di-2],16 ;êîë-âî áëîêîâ ïî 4 êá =64 êá ò.å. áîëüøå íå ñ÷èòàåì |
;;;;;; ïîèñê êîíöà ñòðî÷êè |
@@: mov al,byte [es:di] |
cmp al,' ' |
jz .found_end_str |
cmp al,0xa |
jz .found_end_str |
cmp al,0xd |
jz .found_end_str |
inc di |
dec cx |
jnz @b |
;;;not found äîïóñòèì,÷òî ýòî êîíåö ôàéëà è îí íå èìååò ïðèâû÷íîãî çàâåðåøíèÿ ñòðîêè |
.found_end_str: |
; ÷òåíèå áëîêà ïî 64 êá â ñåãìåíò è çàáðàñûâàíèå åãî âûøå 1 ìá. |
push word [es:di] |
xor ax,ax |
mov word [es:di],ax |
; xor ax,ax ; function 1 - read file |
mov di,si ;file_data |
inc ax |
push si |
push es |
call far dword [loader_callback] |
push cs |
pop ds |
pop es |
pop si |
test bx,bx |
jnz .error_LM |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; çàáðàñûâàíèå áëîêà â 64 êá âûøå 1 ìá. |
mov si,table_15_87 |
push es |
push ds |
pop es |
mov cx, 256*18 |
mov ah, 0x87 |
int 0x15 |
pop es |
pop dx cx |
test ah, ah |
jmp far dword [es:si] |
.rest_value_loop: |
mov di,ax |
mov cx,bx |
jmp .start_p_LI |
.exit: |
} |
macro name_in_root_fat |
;ìàêðîñ, êîòîðûé çàïèñûâàåò èíôîðìàöèþ î çàãðóæåííîì ôàéëå â êîðíåâóþ ôàò òàáëèöó |
{ |
} |
macro use_RamdiskFile |
{ |
;çàãðóçêà ôàéëîâ ñ èñïîëüçîâàíèå callback ñåðâèñà ïåðâè÷íîãî çàãðóç÷èêà |
;èñïîëüçóåòñÿ òîëüêî äëÿ çàãðóçêè íåîáõîäèìûõ è íåáîëüøèõ ôàéëîâ, ò.ê. äîñòàòî÷íî ìåäëåííî ðàáîòàåò |
;äëÿ çàãðóçêè èñïîëüçóåò 0õ87 ôóíêöèþ int 0x15 ïðåðûâàíèÿ - çàãðóçêà áëîêîâ äàííûõ äî 64 êá âûøå 1 ìá |
local .start_loop |
local ._end |
local .rest_value_loop |
local .error |
mov di,point_default ;restore value |
mov cx,save_cx_d |
mov data_offset,0 ;clean offset |
;îáðàáîòêà êîíñòðóêöèè òèïà LoaderModule=kord/kolibri.ldm |
.start_loop: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz ._end ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al,'R' |
jnz .start_loop |
;ïðîâåðêà íà çíà÷åíèå RamdiskFile |
mov bx,cx |
mov ax,di |
mov si,parse_RamdiskFile |
mov cx,parse_RamdiskFile_e - parse_RamdiskFile |
repe cmpsb |
jnz .rest_value_loop ;is not compare |
sub bx,parse_RamdiskFile_e - parse_RamdiskFile ;correct cx |
add bx,cx |
mov cx,bx |
; test status_flag,flag_found_LM ;îöåíêà ôëàãîâ |
; jz .correct_is_not_set_LM |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
;.correct_is_not_set_LM: |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
test ecx,ecx |
jz .rest_value_loop ;not found param timeout |
cmp ah,byte [es:di-1] ;find '=' |
jnz .rest_value_loop |
repe scasb ;cut ' ' |
inc cx |
dec di |
mov save_di_RAMDISK,di |
mov save_cx_RAMDISK,cx |
;di óêàçûâàåò íà íà÷àëî áëîêà èíôîðìàöèè, â cx äëèííà äî êîíöà ñåêöèè. |
;ïîñëå çàãðóçêè çàíîñèòüñÿ çíà÷åíèå çàíÿòîé ïàìÿòè. |
;äëÿ òîãî ÷òî áû çàãðóçèòü ìîäóëü, âîñïîëüçóåìñÿ callback ñåðâèñîì |
;îðèãèíàëüíîå ðåøåíèå - ðàçìåñòèì dd ïåðåä ñòðî÷êîé è ïîñëå ñòðî÷êè ðàçìåñòèì byte =0 |
;ýòî âûãëÿäèò òàê: â ini ôàéëå ñóùåñòâóåò ñòðî÷êà RamdiskFile = @menu,@menu |
;ìû åå ìîäèôèöèðóåì äî òàêîãî ñîñòîÿíèÿ dw,dw,db'@menu',0 êîíå÷íî ñîõðàíèâ òå çíà÷åíèÿ êîòîðûå ìû çàìåíÿåì |
;ñîõðàíèëè ïåâûå 2 word |
; |
@@: mov al,byte [es:di] |
cmp al,',' ; ò.å. èùåì ðàçäåëèòåëü |
jz .found_end_str |
inc di |
dec cx |
jnz @b |
;;;not found äîïóñòèì,÷òî ýòî êîíåö ôàéëà è îí íå èìååò ïðèâû÷íîãî çàâåðøåíèÿ ñòðîêè |
.found_end_str: |
; mov al,byte [es:di] |
; cmp al,' ' ; óáèðàåì ïðîáåëû, åñëè îíè åñòü |
; jnz @f |
; inc di |
; dec cx |
; jnz .found_end_str |
;@@: |
mov point_to_dest_file_name,di |
inc di |
;ïðîâåðêà èíäèâèäóàëüíîñòè èìåíè ôàéëà |
check_name_file |
;/restore di - point and cx -size section |
mov di,save_di_RAMDISK |
mov cx,save_cx_RAMDISK |
test al,al |
jnz .start_loop ;åñëè â al çíà÷åíèå íå =0, òî òàêîå èìÿ óæå ñóùåñòâóåò â ñèñòåìå. |
push dword [es:di-6] |
lea si,[di-6] |
push word [es:di-2] |
push di |
xor ax,ax |
mov word [es:di-6],ax ;âíîñèì íóæíûå çíà÷åíèÿ |
;info_real_mode_size ðàçìåð è óêàçàòåëü íà îáëàñòü â êîòîðóþ ìîæíî çàãðóçèòüñÿ |
mov ax,info_real_mode_size ;0x3000 ;ñëåäóþùèé ñåãìåíò çà äàííûìè |
mov word [es:di-4],ax |
mov word [es:di-2],16 ;êîë-âî áëîêîâ ïî 4 êá =64 êá ò.å. áîëüøå íå ÷èòàåì |
mov di,point_to_dest_file_name |
if DEBUG |
pushad |
; mov ax,di |
mov cx,0x0a |
mov di,name_of_seg_get_64 |
mov dword[ds:di],' ' |
mov word[ds:di+4],' ' |
call decode |
;Show size |
mov si,name_of_seg_get_64 |
call printplain |
popad |
end if |
push word [es:di] |
push cx |
xor ax,ax |
mov word [es:di],ax |
; xor ax,ax ; function 1 - read file |
push di |
mov di,si ;file_data |
inc ax |
push si |
push es |
push bp |
push es |
pop ds |
push cs |
pop es |
call far dword [es:loader_callback] |
push cs |
pop ds |
pop bp |
pop es |
pop si |
cmp bx,2 |
ja .error |
; ñåé÷àñ ó íàñ â dx:ax ðàçìåð ôàéëà, êîòîðûé ìû çàãðóçèëè. |
; âîçìîæíà ñèòóàöèÿ, êîãäà â bx=1 ò.å. åñòü åùå äàííûå íà äèñêå |
mov status_flag_loader_f,bx |
shl edx,16 |
mov dx,ax |
; shr edx,10 ;ðàçìåð ôàéëà â êá. |
;;â edx ðàçìåð â áàéòàõ. |
mov save_file_size,edx |
mov eax,edx |
;âîññòàíîâèì ïîëíîñòüþ ôàéë ñöåíàðèÿ |
pop di |
pop cx ;äëèííà îñòàòêà ñ 2-îé ÷àñòüþ èìåíè ò.å. ñ èìåíåì íàçíà÷åíèåì. |
pop word [es:di] |
pop di |
pop word [es:di-2] |
pop dword [es:di-6] |
if DEBUG |
pushad |
mov cx,0x0a |
mov di,RamdiskFile_msg |
mov dword[ds:di],' ' |
call decode |
;Show size |
mov si,RamdiskFile_msg |
call printplain |
popad |
end if |
; çàãðóçèì ÷åìó ó íàñ ðàâåí êëàñòåð |
; mov ax,word [fat12_buffer.BPB_BytsPerSec] ;êîë-âî áàéòîâ â ñåêòîðå ìîæåò áûòü ëþáîå 512 1024 2048 4096 2 áàéòà |
; movzx bx,byte [fat12_buffer.BPB_SecPerClus] ;êîë-âî ñåêòîðîâ â êëàñòåðå |
; imul ax,bx |
;ñåé÷àñ â eax ðàçìåð êëàñòåðà (512) áàéò |
;â edx äëèíà ôàéëà â áàéòàõ äî 64 êá |
;çàêèíèì ôàéë çà 1 ìá |
;1 íàì íóæíî ñîñòàâèòü ôàò òàáëèöó ò.å. ïðîèçâåñòè ðàçìåòêó ðàìäèñêà, çàòåì ïåðåíåñåì ïî àäðåñó ôàéë |
;çàïèñàòü èíôîðàìàöèþ î ôàéëå â êîðíåâóþ äèðåêòîðèþ |
register_file_in_fat |
;ïåðåíåñòè çà 1 ìá ñîäåðæèìîå ôàéëà |
move_file_up |
;ïðîâåðèì, çàãðóæåí ëè äî êîíöà ôàéë? ò.å. åñëè ðàçìåð ôàéëà áîëüøå ÷åì 64 êá, òî áóäåò ïîäãðóæàòü îñòàâøèåñÿ áëîêè |
cmp status_flag_loader_f,0x1 |
jnz @f |
;íóæíî äîçàãóçèòü äàííûå ôàéëà è ïåðåíåñòè èõ çà 1-ûé ìá ñîãëàñíî ôàò ñòðóêòóðå |
@@: |
;òóò îðãàíèçîâàí öèêë ïî çàãðóçêå ôàéëîâ â êîðíåâóþ äèðåêòîðèþ |
mov di,save_di_RAMDISK |
mov cx,save_cx_RAMDISK |
if DEBUG |
pusha |
xor ax,ax |
int 0x16 |
popa |
end if |
jmp .start_loop |
.error: |
;call error.LoaderModule |
;fixme! |
.rest_value_loop: |
mov di,ax |
mov cx,bx |
jmp .start_loop |
._end: |
;ïåðåíåñåì çà 1-ûé ìá ôàò è ðóò äèð |
move_up_fat_and_root_d |
;çàãðóçêà áëîêà |
; mov ah,0x87 |
; mov cx, ;size in byte |
;es:si point to descripts |
} |
macro use_BPB_RAM ;çàêèíóòü ñàìûå ïåðâûå 512 áàéò çà 1-é ìá |
;äàííûé ìàêðîñ çàêèäûâàåò BPB ñòðóêòóðó ò.å. ïåðâûå 512 áàéò, ïîêà òîëüêî ôàò12 çà 1 ìá |
{ |
mov ax,fat12_buffer |
mov si,table_15_87 |
add word [si+8*2+2],ax |
push es |
push ds |
pop es |
mov cx,256 ;áóò ñåêòîð óêëàäûâàåòñÿ â 512 áàéò 512/2=256 |
mov ah, 0x87 |
int 0x15 |
pop es |
;add 512 byte for destination adress |
; add dword [si+8*3+2], 512 |
; test ah, ah |
; jz |
if DEBUG |
pusha |
mov ax,word [si+8*2+2] |
mov cx,0x0a |
mov di,BPB_msg |
call decode |
;Show size |
mov si,BPB_msg |
call printplain |
popa |
end if |
} |
macro first_create_fat_table |
;äàííûé ìàêðîñ ñîçäàåò îôîðìëÿåò 3 ïåðâûõ áàéòà fat òàáëèöû, è óñòàíàâëèâàåò óêàçàòåëü íà ñëåäóþùèé áëîê, è âíîñèò 0 çíà÷åíèå |
;äëÿ ñìåùåíèÿ â êîðíåâîé òàáëèöå. |
{ |
mov al,byte [fat12_buffer.BPB_Media] |
push ds |
mov di,info_real_mode_size |
add di,0x1000 |
if DEBUG |
pushad |
mov ax,info_real_mode_size |
add ax,0x1000 |
; mov ax,ds |
mov cx,0xa |
mov di,first_entry_in_fat |
mov dword [di],' ' |
mov word [di+4],' ' |
call decode |
;Show size |
mov si,first_entry_in_fat |
call printplain |
xor ax,ax |
int 0x16 |
popad |
end if |
push di ; push word info_real_mode_size+0x1000 ;cëåäóþùèé ñåãìåíò çà çàãðóæåííûì ó÷àñòêîì |
xor di,di |
mov point_to_free_root,di ;çíà÷åíèå ñìåùåíèÿ =0 â êîðíåâîé ôàò òàáëèöå îïèñàíèÿ |
pop ds ; çàãðóæåí ñëåäóþùèé ñåãìåíò ò.å. ïóñòîé ñåãìåíò |
mov byte [di],al |
or ax,-1 |
inc di |
mov word [di],ax |
pop ds |
mov point_next_fat_str,3 |
if DEBUG |
pushad |
mov ax,point_next_fat_str |
mov cx,0x0a |
mov di,fat_create_msg |
call decode |
;Show size |
mov si,fat_create_msg |
call printplain |
popad |
end if |
} |
macro register_file_in_fat |
;ìàêðîñ ðåãèñòðàöèè ôàéëà â ôàéëîâîé ñòðóêòóðå Fat |
;ïîêà ïîääåðæèâàåòñÿ òîëüêî ôàò12, ïîêà )) |
;âû÷èñëåíèå ñìåæíûõ êëàñòåðîâ è çàíåñåíèå èíôû â fat/ |
{ |
local .step2 |
local .step3 |
local .end |
local .eof_file |
;di point on root dir íà ôðè ñåêöèþ. |
push es |
mov ax,info_real_mode_size |
add ax,0x1000 |
mov es,ax ; push word info_real_mode_size+0x1000 ;ñåãìåíò ñëåäóþùèé çà çàãðóæåííûì áëîêîì â 64 êá |
; îïðåäåëÿåì òèï ôàò ïîêà íå îïðåäåëÿåì, ïîêà òîëüêî ôàò 12 |
; 12 áèò, äëÿ âû÷åñëåíèÿ ñîñåäíèõ êàëàñòåðîâ. |
mov di,firstDataSect ;â ñåêòîðàõ |
sub di,size_root_dir |
;òåïåðü â ax ðàçìåð â ñåêòîðàõ íà÷àëà ðóò äèð |
shl di,9 ;imul 512 |
add di,point_to_free_root ;ñìåùåíèå â óæå çàïèñàííûõ 32-õ ñòðóêòóðàõ. |
;íåîáõîäèìî âíåñòè çíà÷åíèå â ðóò äèð ò.å. 32 áàéòà |
if DEBUG |
pushad |
; mov ax,point_default |
; mov ax, |
mov cx,0x0a |
mov di,show_db2 |
mov dword[ds:di],' ' |
mov word [ds:di+4],' ' |
call decode |
;Show size |
mov si,show_db2 |
call printplain |
; |
; xor ax,ax |
; int 0x16 |
popad |
end if |
;gs:di - óêàçàòåëü äëÿ âíåñåíèÿ èíôîðàöèè â ðóò îáëàñòü ôàò òàáëèöû èíîðìàöèè î ôàéëå. |
mov si,shot_name_fat |
mov cx,11 |
;çàïèøåì â ñòðóêòóðó èìÿ |
@@: lodsb |
stosb |
loop @b |
;çàïèøåì àòðèáóòû ôàéëà è DIR_NTRes - çàðåçåâðèðîâàííûé áàéò =0 |
xor ax,ax |
mov ah,ATTR_VOLUME_ID |
mov word [es:di],ax |
add di,2 |
;DIR_CrtTimeTenth |
mov byte [es:di],100 |
inc di |
;DIR_CrtTime |
mov word [es:di],0x032b ;äàòà |
add di,2 |
;DIR_CrtDate |
mov word [es:di],0x0 ;âðåìÿ >< |
add di,2 |
;DIR_LstAccDate |
mov word [es:di],0x032b ;äàòà ìîåãî |
add di,2 |
;DIR_FstClusHI |
mov word [es:di],0x0 ;âðåìÿ äëÿ ôàò12 /16 âñåãäà 0 |
add di,2 |
;DIR_WrtTime |
mov word [es:di],0x0 ;âðåìÿ >< |
add di,2 |
;DIR_WrtDate |
mov word [es:di],0x032b |
add di,2 |
mov ax,point_next_fat_str |
mov word [es:di],ax |
add di,2 |
push di |
;DIR_FstClusLO Ìëàäøåå ñëîâî íîìåðà ïåðâîãî êëàñòåðà. |
; mov ax,point_next_fat_str ;çàãðóçèì óêàçàòåëü íà ýëåìåíò ôàò òàáëèöû ò.å. ýòî íîìåð ôàò çàïèñè |
;FATOffset = N + (N / 2) ò.å. ýòî óæå ó íàñ ñìåùåíèå ìû çíàåì ÷òî -íà÷èíàåòñÿ âñå ñ 3-ãî ýëåìåíòà çàïèñè ôàò |
mov bx,ax |
shr bx,1 |
add ax,bx |
;â àõ ñåé÷àñ FATOffset |
;ThisFATEntOffset = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec); |
mov bx, word [fat12_buffer.BPB_BytsPerSec] |
cwd |
idiv bx |
;ax=ThisFATEntOffset= rem (FATOffset / BPB_BytsPerSec) ÷åòíûé èëè íå÷åòíûé óêàçàòåëü. |
mov si,ax |
;íàì íóæíî â öèêëå çàïèñàòü âñå êëàñòåðû êîòîðûå áóäóò èñïîëüçîâàíû äëÿ ðàçìåùåíèÿ ôàéëà. |
;óçíàåì ðàçìåð êëàñòåðà. |
movzx eax,word [fat12_buffer.BPB_BytsPerSec] |
movzx ebx,byte [fat12_buffer.BPB_SecPerClus] |
imul eax,ebx |
;ax - ðàçìåð êëàñòåðà. |
;ñåé÷àñ áóäåì çàïèñûâàòü âî âðåìåííûé áóôåð ôàò òàáëèöó äëÿ âûáðàííîãî ôàéëà. Ïîñêîëüêó ìû åãî çàãðóçèëè âîçìîæíî íå ïîëíîñòüþ |
;ìû îáðàáîòàåì çàïèñü äëÿ ôàò ïîëíîñòüþ, â íå çàâèñèìîñòè îò ïðåäåëà áóôåðà ãäå âîçìîæíà ÷àñòü ôàéëà. |
mov ebx,save_file_size ;ðàçìåð ôàéëà â áàéòàõ |
@@: sub ebx,eax |
cmp ebx,eax |
jbe .eof_file |
inc point_next_fat_str |
mov cx,point_next_fat_str ;çàãðóçèì óêàçàòåëü íà ýëåìåíò ôàò òàáëèöû ò.å. ýòî íîìåð ôàò çàïèñè |
;FATOffset = N + (N / 2) ò.å. ýòî óæå ó íàñ ñìåùåíèå ìû çíàåì ÷òî -íà÷èíàåòñÿ âñå ñ 3-ãî ýëåìåíòà çàïèñè ôàò |
mov dx,ax |
shr dx,1 |
add cx,dx |
test si,0x1 |
jz .step2 |
shl cx,4 |
mov word[es:si],cx |
inc si |
add cx,ax |
jmp @b |
.step2: and cx,0x0FFF |
mov word[es:si],cx |
inc si |
add cx,ax |
jmp @b |
.eof_file: |
mov cx,0x0fff |
test si,0x1 |
jz .step3 |
shl cx,4 |
mov word[es:si],cx |
jmp .end |
.step3: and cx,0x0FFF |
mov word[es:si],cx |
.end: inc point_next_fat_str |
pop di |
;DIR_FileSize 32-áèòíûé DWORD ñîäåðæèò ðàçìåð ôàéëà â áàéòàõ. |
mov eax,save_file_size |
mov dword [es:di],eax |
if DEBUG |
pushad |
mov di,firstDataSect ;â ñåêòîðàõ |
sub di,size_root_dir |
;òåïåðü â ax ðàçìåð â ñåêòîðàõ íà÷àëà ðóò äèð |
shl di,9 ;imul 512 |
add di,point_to_free_root ;ñìåùåíèå â óæå çàïèñàííûõ 32-õ ñòðóêòóðàõ. |
push di |
mov si,dest_name_fat |
mov cx,11 |
;çàïèøåì â ñòðóêòóðó èìÿ |
@@: mov al,byte [es:di] |
inc di |
mov byte [ds:si],al |
inc si |
loop @b |
mov di,si |
inc di |
pop ax |
mov cx,0xa |
call decode |
mov si,dest_name_fat |
call printplain |
popad |
END IF |
add point_to_free_root,32 ;óâåëèöèì ñìåùåíèå äî ñëåäóþùåãî çíà÷åíèÿ. |
pop es |
} |
macro get_firstDataSector |
;ìàêðîñ äëÿ âû÷èñëåíèÿ ïåâîãî ñåêòîðà äàííûõ ò.å. äàííûõ ôàéëîâ â ôàòå |
;âû÷èñëèì FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors; |
{ |
mov ax,word [fat12_buffer.BPB_FATSz16] |
movzx bx,byte [fat12_buffer.BPB_NumFATs] |
imul ax,bx ;9x1=9 |
;ax=BPB_NumFATs * FATSz |
mov bx,word [fat12_buffer.BPB_RootEntCnt] ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) |
shr bx,4 ;imul bx,32 and then div 512 -> in bx size in sectors |
add ax,bx ;9+14=23 |
mov size_root_dir,bx |
movzx bx,byte [fat12_buffer.BPB_RsvdSecCnt] ;add 1 for fat 16/12 |
add ax,bx |
;ax=firstDataSector - ãäå íà÷èíàåòñÿ ïåðâûé ñåêòîðî îò 0 ñåêòîðà â ñåêòîðàõ. - ôàêòè÷åñêè = 24 ñåêòîð |
mov firstDataSect,ax ;ñîõðàíèì äëÿ âû÷èñëåíèÿ |
; ïîëó÷èìçíà÷åíèå êëàñòåðîâ, ýòî îáúåì â êîòîðûé ìû ìîæåì çàïèñàòü äàííûå |
mov bx,word [fat12_buffer.BPB_TotSec16] |
sub bx,ax |
mov ax,bx |
movzx bx,byte [fat12_buffer.BPB_SecPerClus] |
cwd |
idiv bx |
mov DataClasters,ax |
if DEBUG |
pushad |
mov ax,firstDataSect ;ïåðâûé ñåêòîð äàííûõ |
mov cx,0x0a |
mov di,firstDataSect_msg |
call decode |
;Show size |
mov si,firstDataSect_msg |
call printplain |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov ax,size_root_dir ;ðàçìåð ðóò äèð â ñåòîêòîðàõ |
mov cx,0x0a |
mov di,size_root_dir_msg |
call decode |
;Show size |
mov si,size_root_dir_msg |
call printplain |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov ax,DataClasters ;êëàñòåðû |
mov cx,0x0a |
mov di,DataClasters_msg |
call decode |
;Show size |
mov si,DataClasters_msg |
call printplain |
popad |
end if |
} |
macro use_RamdiskPATHS |
;ïàðñèíã ïóòè èñòî÷íèêà ôàéëîâ. |
{ |
} |
macro use_RamdiskPATHD |
;ïàðñèíã ïóòè íàçíà÷åíèÿ ôàéëîâ. |
{ |
} |
macro check_name_file |
;ìàêðîñ ïðîâåðêè èìåíè íà ïîâòîð, èìÿ äîëæíî áûòü óíèêàëüíûì. |
;âõîäíûå äàííûå: es- ñåãìåíò ãäå ëåæèò ôàéë äëÿ ïàðñèíãà ò.å. startos.ini |
;di - óêàçàòåëü íà èìÿ ôàéëà ò.å. es:di óêàçûâàåò íà èìÿ ôàéëà íàçíà÷åíèÿ |
;âûõîäíûå äàííûå eax =-1 èìÿ ñîâïàëî, eax=0 èìÿ íå ñîâïàëî. |
{ |
local .no_equal |
local .exit |
local .loop_size_root_dir |
;âû÷èñëèì äëèííó ñòðî÷êè èìåíè íàçíà÷åíèÿ, êîòîðóþ áóäåì ñðàâíèâàòü ñ óæå çàïèñàííûìè äàííûìè. |
;ïðåîáðàçóåì â àíàëîã ôàò çàïèñè ñòî÷êó ñ èìåíåì íàçíà÷åíèÿ |
convertion_file_name ; ïðåîáðàçîâàëè èìÿ ïî íóæíûì ïðàâèëàì |
test ax,ax |
jnz .exit |
lea si,[shot_name_fat] ; desination name of file |
;âû÷èñëèì óêàçàòåëü íà êîðíåâóþ äèðåêòîðèþ |
mov di,firstDataSect |
sub di,size_root_dir |
;òåïåðü â ax ðàçìåð â ñåêòîðàõ íà÷àëà ðóò äèð |
shl di,9 ;imul 512 |
;di= Ýòî ñìåùåíèå îò íà÷àëà áóôåðà äî ðóò äèðåêòîðèè. â ïðåäåëàõ 64 êá. |
;çàãðóçèì çíà÷åíèå - ò.å. êîë-âî ýëåìåíòîâ, êîòîðûå ìû ìîæåì ïðîñìàòðèâàòü. |
mov dx,root_dir_entry_count |
mov ax,info_real_mode_size |
add ax,0x1000 |
mov gs,ax |
.loop_size_root_dir: |
DEBUG1 equ 0 |
if DEBUG1 |
pushad |
push di |
mov eax,dword[gs:di] |
lea si,[check_root_fat_+14] |
mov dword [ds:si],'----' |
mov dword [ds:si+4],'----' |
mov dword [ds:si+8],'----' |
mov dword[ds:si],eax |
mov eax,dword[gs:di+4] |
mov dword[ds:si+4],eax |
mov eax,dword[gs:di+8] |
mov dword[ds:si+8],eax |
; |
xor eax,eax |
mov ax,gs;point_next_fat_str |
mov cx,0x0a |
mov di,check_root_fat_ |
mov dword [di],' ' |
mov word [di+4],' ' |
call decode |
xor eax,eax |
pop ax |
mov di,(check_root_fat_+7) |
mov dword [di],' ' |
mov word [di+4],' ' |
call decode |
;Show size |
lea si,[check_root_fat_] |
call printplain |
lea si,[shot_name_fat] |
call printplain |
xor ax,ax |
int 0x16 |
popad |
end if |
xor bx,bx |
mov cx,11 ;size of name in struct FAT |
@@: |
mov al,byte [ds:si+bx] ;ds:si - point to name of convertion variable. |
mov ah,byte [gs:di+bx] ;gs:di - point to name in fat struct |
inc bx |
if DEBUG |
; pushad |
; lea si,[check_root_fat_+14] |
; mov dword [ds:si],'----' |
; mov word [ds:si],ax |
; call printplain |
; xor ax,ax |
; int 0x16 |
; popad |
end if |
cmp ah,al |
jnz .no_equal |
; dec cx |
; jnz @b |
loop @b |
;.succesfuly: |
;ïå÷àëüíî, òàêîå èìÿ óæå èìååòñÿ :( |
or ax,-1 |
jmp .exit |
.no_equal: |
add di,32 ;fat struct =32 byte |
dec dx |
jnz .loop_size_root_dir |
;.exit_check_name: |
and ax,0 |
.exit: |
if DEBUG |
pushad |
;Show size |
lea si,[check_name_fat_msg_n] |
test ax,ax |
jz @f |
lea si,[check_name_fat_msg_y] |
call printplain |
lea si,[alarm_msg] |
@@: call printplain |
popad |
end if |
} |
macro convertion_file_name |
;ìàêðîñ êîíâåðòàöèè èìåíè, ýòî íóæíî ïîñêîëüêó ôîðìàò ïðåäñòàâëåííûé íå ñîîòâåòñâóåò ôàò è íàïðÿìóþ ðåäêî ìîæíî êîãäà èñïîëüçîâàòü |
;ïðåîáðàçîâàíèå èìåíè òèïà hello.asm â 'HELLO ASM', â ñîîòâåòñòâèè ñ ïðàâèëàìè fat. |
;âõîäíûå ïàðàìåòðû es:di óêàçàòåëü íà èìÿ ôàéëà êîòîðîå íóæíî ïðåîáðàçîâàòü, êîíå÷íûé áóôåð shot_name_fat |
{ |
local .next_step |
local .error |
local .st1 |
local .st2 |
local .st2_l |
local .st3 |
local .st4_s |
local .st4 |
local .st5 |
;âû÷èñëèì äëèííó ñòðî÷êè èìåíè íàçíà÷åíèÿ, êîòîðóþ áóäåì ñðàâíèâàòü ñ óæå çàïèñàííûìè äàííûìè. |
; mov di,point_to_dest_file_name âõîäíîé ïàðàìåòð |
mov si,shot_name_fat |
or first_input,-1 ;ïðè ïåðâîì âõîäå óñòàíàâëèâàåì ôëàã |
mov cx,11 ;äëèííà èìåíè â ñòóêòóðå ôàò òàáëèöû |
@@: |
mov al,byte [es:di] |
cmp al,0xa |
jz .st4_s |
cmp al,0xd |
jz .st4_s |
cmp al,0x20 |
jz .st4_s |
cmp al,0x20 |
jb .error |
cmp al,0x22 |
jz .error |
cmp al,0x2a |
jz .error |
cmp al,0x2b |
jz .error |
cmp al,0x2c |
jz .error |
cmp al,0x2F |
jz .error |
cmp al,0x3a |
jz .error |
cmp al,0x3b |
jz .error |
cmp al,0x3c |
jz .error |
cmp al,0x3d |
jz .error |
cmp al,0x3E |
jz .error |
cmp al,0x3F |
jz .error |
cmp al,0x5b |
jz .error |
cmp al,0x5c |
jz .error |
cmp al,0x5d |
jz .error |
cmp al,0x7c |
jz .error |
cmp first_input,-1 |
jnz .next_step |
and first_input,0 ;ñáîðîñèì ôëàã. |
cmp al,'.' |
jz .error ;îáðàáîòêà òî÷êè, ôàéë íå ìîæåò íà÷èíàòüñÿ ñ òî÷êè |
.next_step: |
cmp al,0x2e |
jnz .st2 ;îáðàáîòêà òî÷êè, â ñåðåäèíå ôàéëà |
;òóò ó íàñ óñòàíîâëåí ðàçäåëèòåëü |
;âñå îñòàëüíåî ìåñòî çàéìóò ïðîáåëû |
mov al,' ' |
;!fixme îáðàáîòàíû íå âñå èñêëþ÷åíèÿ :( |
cmp cl,3 ;ôîðìàò ôàéëà òàêîé GIDGIDIIASM ò.å. gidgidii.asm |
jbe .st2 |
.st3: |
mov byte [si],al |
inc si |
dec cx |
cmp cx,3 |
ja .st3 |
; inc cx |
inc di |
jmp @b |
.st2: |
cmp al,0x60 |
jbe .st2_l |
xor al,0x20 ;ñäåëàåì çàãëàâíûå áóêâû |
.st2_l: mov byte [si],al |
inc di |
inc si |
; dec cx |
; jnz @b |
loop @b |
.st5: xor ax,ax |
jmp @f |
;;;;;;;;ôàéë çàêîí÷èëñÿ, è íóæíî âíåñòè â êîíåö ïðîáåëû |
.st4_s: mov al,' ' |
.st4: mov byte [si],al |
inc si |
loop .st4 |
jmp .st5 |
.error: or ax,-1 |
@@: |
if DEBUG |
pushad |
mov si,convertion_file_name_msg_y |
test ax,ax |
jz @f |
mov si,convertion_file_name_msg_n |
@@: call printplain |
mov si,shot_name_fat |
mov byte [si+12],0 |
call printplain |
popad |
end if |
} |
macro move_file_up |
;ìàêðîñ êîòîðûé ïåðåìåùàåò çà 1 ìá ñ ïðàâèëàìè ôàò äàííûå ôàéëà. |
{ |
local .st1 |
local .correct_on_byte |
;ñåé÷àñ èìååò áûòü ñèòóàöèÿ, êîãäà BPB óæå ïåðåìåùåí çà 1 ìá, ôàò, è ðóò äèð áóäóò ïîçæå ïåðåìåùåíû, |
;à íàì íóæíî âû÷èñëèòü ìåñòî, è ïåðåíåñòè òóäà ñîäåðæèìîå ôàéëà |
;ïîëó÷åíîå çíà÷åíèå óêàçûâàåò â áàéòàõ íà íà÷àëî äàííûõ |
mov ax,info_real_mode_size ; ñåãìåíò ãäå ðàñïîëîæåíû äàííûå |
mov si,table_15_87 |
mov word [si+8*2+2],ax |
;ñìåùåíèå äî äàííûõ óæå çà 1-ì ìá |
movzx eax,firstDataSect |
movzx edx,data_offset |
add eax,edx |
movzx ebx,word [fat12_buffer.BPB_BytsPerSec] |
movzx edx,byte [fat12_buffer.BPB_SecPerClus] |
imul bx,dx ;ïîëó÷èì ðàçìåð êëàñòåðà |
push ebx ;save bx |
imul eax,ebx |
; shl eax,9 ;óìíîæèì íà 512 |
if DEBUG |
pushad |
xor eax,eax |
mov ax,info_real_mode_size |
mov cx,0x0a |
mov di,seg_where_get_data |
mov dword [di],' ' |
mov word [di+4],' ' |
call decode |
;Show size |
mov si,seg_where_get_data |
call printplain |
popad |
end if |
; mov bx,word [fat12_buffer.BPB_BytsPerSec] |
; movzx dx,byte [fat12_buffer.BPB_SecPerClus] |
; imul bx,dx |
; cwd |
; idiv bx |
mov dl,0x10 |
@@: cmp eax,0x00010000 |
jb @f |
sub eax,0x00010000 |
inc dl |
jmp @b |
@@: mov byte [si+8*3+3],dl ;êóäà ïèñàòü |
mov word [si+8*3+2],ax |
mov ecx,save_file_size ;ðàçìåð ôàéëà â áàéòàõ. |
cmp ecx,0x0000ffff ;ðàçìåð áëîêà ò.å. 64 êá |
jbe .correct_on_byte ;êîððåêòèðîâêà íà áàéò çíà÷åíèÿ |
mov ecx,0x00010000 ;65536 |
sub save_file_size,ecx ;îòíèìèì |
; jmp .st1 ;ïîëó÷èì 0õ8000 |
;êîððåêòèðîâêà çíà÷åíèÿ äîëæíà áûòü âûïîëåíåíà íà ðàçìåð êëàñòåðà |
.correct_on_byte: |
;/óçíàåì ðàçìåð êëàñòåðà |
pop eax ;restore size of claster |
push ecx |
@@: inc data_offset |
cmp eax,ecx |
jae @f |
sub ecx,eax |
jmp @b |
@@: pop ecx |
test ecx,0x1 |
jz .st1 |
inc ecx |
.st1: shr ecx,1 ; ïðåîáðàçîâàòü çíà÷åíèå äëÿ 0x87 function |
;ïåðåíåñåì áëîê çà 1 ìá |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
if DEBUG |
pusha |
; mov ax,point_next_fat_str |
mov cx,0x0a |
mov di,return_code_af_move |
call decode |
;Show size |
mov si,return_code_af_move |
call printplain |
popa |
end if |
} |
macro move_up_fat_and_root_d |
;ìàêðîñ, êîòîðûé ïîçâîëÿåò ïåðåíåñòè âûøå 1 ìá â ñòðóêòóðó îáðàçà ôàò òàáëèöó è ðóò äèðåêòîðèþ |
{ |
local .st1 |
mov ax,info_real_mode_size |
add ax,0x1000 |
mov si,table_15_87 |
mov word [si+8*2+2],ax |
;ñìåùåíèå äî äàííûõ |
mov ax,512 |
mov word [si+8*3+2],ax |
;fixme! òóò íåîáõîäèìî ñäåëàòü ïîäåðæêó ò.å. ôîðìèðîâàòü ñìåùåíèå ôàéëà â óæå çàïèñàííûõ äàííûõ. |
movzx ecx,word [fat12_buffer.BPB_FATSz16] |
movzx bx,byte [fat12_buffer.BPB_NumFATs] |
imul cx,bx ;9x1=9 |
add cx,size_root_dir ;ðàçìåð êîðíåâîé äèððåêòîðèè |
shl ecx,9 ;imul 512 |
;êîððåêòèðîâêà çíà÷åíèÿ |
test ecx,0x1 |
jz .st1 |
inc ecx |
.st1: shr ecx,1 |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
if DEBUG |
pusha |
; mov ax,point_next_fat_str |
mov cx,0x0a |
mov di,return_code_af_fat_m |
call decode |
;Show size |
mov si,return_code_af_fat_m |
call printplain |
popa |
end if |
} |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; â ýòîé ñåêöèè èäåò ðàçáîð ïàðàìåòðîâ óêàçàòåëü íà ñåêöèþ õðàíèòüñÿ â point_default |
;òèïû îøèáîê ïðè îáðàáîòêå ìàêðîñà |
;Ìàêðîñ RamdiskFS |
;/îïðåäåëåíèå ôëàãîâ â çàïèñè êîðíåâîé äèðåêòîðèè |
ATTR_READ_ONLY equ 0x01 |
ATTR_HIDDEN equ 0x02 |
ATTR_SYSTEM equ 0x04 |
ATTR_VOLUME_ID equ 0x08 |
ATTR_DIRECTORY equ 0x10 |
ATTR_ARCHIVE equ 0x20 |
show_error_1 equ 0x1 ;êîí÷èëèñü äàííûå - íå çàïëàíèðîâàííûé êîíåö ñåêöèè |
show_error_2 equ 0x2 ;íåò çàâåðøàþùåãî ñèìâîëà â ðàçìåðå ðàì äèñêà. |
show_error_3 equ 0x4 ; ðàì äèñê áóäåò èìåòü ðàçìåð =64 êá. |
show_error_4 equ 0x8 ; |
macro use_parse_def_sect |
{ |
mov di, point_default |
push ini_data_ |
pop es |
mov si, point_to_point_def |
sub si, 2 |
mov cx, [si] ;çàãðóçèì óêàçàòåëü íàñëåäóþùèþ ñåêöèþ |
xor ax, ax ;îáíóëèì àx äëÿ î÷èñòêè ôëàãîâ |
sub cx, di ;âîò òåïåðü èìååì èñòèíûé ðàçìåð |
mov save_cx_d, cx ;ñîõðàíèì çíà÷åíèå cx ñâîåé ïåðåìåííîé |
;îáíóëèì ïåðåìåííóþ ôëàãîâ, ýòî íåîáõîäèìî, äëÿ òîãî, ÷òî áû èçáåæàòü îáðàáîòêó ïîâòîðÿþùèõñÿ çíà÷åíèé |
mov status_flag, ax |
;;;; |
;ÂÕîä â îáðàáîòêó ïàðñèíãà çíà÷åíèé ñåêöèé. es:di - óêàçàòåëü íà íà÷àëî ñåêöèè cx ðàçìåð ñåêöèè äîñòóïíîé äëÿ ïàðñèíãà |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;ñîãëàøåíèå íå ðàçðóøàåì bp, es, cs, sp |
;use_Loader_Image ;çàãðóçèòü îáðàç âûøå 1 ìá |
use_RamdiskFS |
;ïðîâåðÿåòñÿ ñàìûé ïîñëåäíèé. |
use_LoaderModule ;îñîáåííîñòü - ïåðåäàåò óïðàâëåíèå íà çàãðóæåííûé ìîäóëü. |
} |
macro use_LoaderModule |
;êàê âàðèàíò ñåé÷àñ èñïîëüçóåòñÿ ìîäåëü, ïðè çàãðóçêå ìîäóëÿ íà íåãî ïåðåäàåòñÿ óïðàâëåíèå, ðåøåíèå âðåìåíîå |
;óïðàâëåíèå áóäåò ïåðåäàâàòüñÿ òîëüêî ïîñëå îáðàáîòêè âñåé ñåêöèè |
{ |
local .found_end_str |
mov di, point_default ;restore value |
mov cx, save_cx_d |
;îáðàáîòêà êîíñòðóêöèè òèïà LoaderModule=kord/kolibri.ldm |
.start_p_LM: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz ._afterLoaderModule ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al, 'L' |
jnz .start_p_LM |
;ïðîâåðêà íà çíà÷åíèå LoaderModule |
; parse_LoaderModule |
mov bx, cx |
mov ax, di |
mov si, parse_LoaderModule |
mov cx, parse_LoaderModule_e - parse_LoaderModule |
repe cmpsb |
jnz .rest_value_loop_LM ;is not compare |
sub bx, parse_LoaderModule_e - parse_LoaderModule;correct cx |
add bx, cx |
mov cx, bx |
test status_flag, flag_found_LM ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_LM |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_LM: |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .rest_value_loop_LM ;not found param timeout |
cmp ah, byte [es:di-1] ;find '=' |
jnz .rest_value_loop_LM |
repe scasb ;cut ' ' |
inc cx |
dec di |
;di óêàçûâàåò íà íà÷àëî áëîêà èíôîðìàöèè, â cx äëèííà äî êîíöà ñåêöèè. |
;ïîñëå çàãðóçêè çàíîñèòüñÿ çíà÷åíèå çàíÿòîé ïàìÿòè. |
;äëÿ òîãî ÷òî áû çàãðóçèòü ìîäóëü, âîñïîëüçóåìñÿ callback ñåðâèñîì |
;îðèãèíàëüíîå ðåøåíèå - ðàçìåñòèì dd ïåðåä ñòðî÷êîé è ïîñëå ñòðî÷êè ðàçìåñòèì byte =0 |
;ýòî âûãëÿäèò òàê: â ini ôàéëå ñóùåñòâóåò ñòðî÷êà LoaderModule = kord/kernel.loader |
;ìû åå ìîäèôèöèðóåì äî òàêîãî ñîñòîÿíèÿ dw,dw,db'kord/kernel.loader',0 êîíå÷íî ñîõðàíèâ òå çíà÷åíèÿ êîòîðûå ìû çàìåíÿåì |
;ñîõðàíèëè ïåâûå 2 word |
push dword [es:di-6] |
lea si, [di-6] |
push word [es:di-2] |
xor ax, ax |
mov word [es:di-6], ax ;âíîñèì íóæíûå çíà÷åíèÿ |
;info_real_mode_size ðàçìåð è óêàçàòåëü íà îáëàñòü â êîòîðóþ ìîæíî çàãðóçèòüñÿ |
mov ax, info_real_mode_size ;0x3000 ;ñëåäóþùèé ñåãìåíò çà äàííûìè |
mov word [es:di-4], ax |
mov word [es:di-2], 16 ;êîë-âî áëîêîâ ïî 4 êá =64 êá ò.å. áîëüøå íå ñ÷èòàåì |
;;;;;; ïîèñê êîíöà ñòðî÷êè |
@@: |
mov al, byte [es:di] |
cmp al, ' ' |
jz .found_end_str |
cmp al, 0xa |
jz .found_end_str |
cmp al, 0xd |
jz .found_end_str |
inc di |
dec cx |
jnz @b |
;;;not found äîïóñòèì,÷òî ýòî êîíåö ôàéëà è îí íå èìååò ïðèâû÷íîãî çàâåðåøíèÿ ñòðîêè |
.found_end_str: |
push word [es:di] |
xor ax, ax |
mov word [es:di], ax |
; xor ax,ax ; function 1 - read file |
mov di, si ;file_data |
inc ax |
push si |
push es |
push es |
pop ds |
push cs |
pop es |
call far dword [es:loader_callback] |
push cs |
pop ds |
pop es |
pop si |
test bx, bx |
jnz .error_LM |
jmp far dword [es:si] |
.error_LM: |
call error.LoaderModule |
.rest_value_loop_LM: |
mov di, ax |
mov cx, bx |
jmp .start_p_LM |
._afterLoaderModule: |
} |
macro use_RamdiskFS |
; ôîðìèðîâàíèå ðàì äèñêà, + îáðàáîòêà âñåãî ñâÿçàííîãî. |
{ |
if DEBUG |
local ._not_memory_in_sys |
;//////// clear window |
mov ax, 3 |
int 0x10 |
;\\\\\\\\\ clear window is end |
mov si, ramdiskFS_st |
call printplain |
end if |
; îáíóëèì ðåãèñòð ñîñòîÿíèÿ îøèáîê |
xor ax, ax |
mov show_errors_sect, ax |
use_free_memory ; óçíàåì êàêîãî îáúåìà ó íàñ äîñòóïíà ïàìÿòü. çíà÷åíèå âîçàðàùàåòñÿ â ax |
;óçíàåì ñêîëüêî ó íàñ åñòü ïàìÿòè è ñìîæåì ëè ìû ñôîðìèðîâàòü íóæíîãî ðàçìåðà ðàì äèñê. |
use_RamdiskSize ;çíà÷åíèå âîçâðàùàåòñÿ â bx |
cmp free_ad_memory, bx ; ðàçìåðíîñòü â êá. |
jbe ._not_memory_in_sys |
movzx eax, bx |
shl eax, 10 ;*1024 = get size in byte |
mov save_ramdisksize, eax ; ñîðõàíèì ðàçìåð â byte |
get_type_FS ;ïîëó÷èì òèï ôàéëîâîé ñèñòåìû + ñîçäàäèì åå |
._not_memory_in_sys: |
if DEBUG |
;pause |
xor ax, ax |
int 0x16 |
end if |
} |
macro use_RamdiskSize |
{ |
local .start_p_RS |
local .correct_is_not_set_RS |
local .CS |
local .correct_val_RS |
local .correct_size_RS |
local .rest_value_loop_RS |
local .end_get_RS_ERROR_1 |
local .end_get_RS_ERROR_2 |
local ._end_parse_RS |
;îáðàáàòûâàåòñÿ ðàçìåð ôîðìèðóåìîãî ðàì äèñêà |
;çàãðóçèì íà÷àëî ñåêöèè, ò.ê. áóäåì ïðîñìàòðèâàòü ñ íà÷àëà è âñþ ñåêöèþ |
mov di, point_default ;restore value |
mov cx, save_cx_d |
.start_p_RS: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz ._end_parse_RS ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al, 'R' |
jnz .start_p_RS |
;ïðîâåðêà íà çíà÷åíèÿ RamdiskSize |
; parse_RamdiskSize |
mov bx, cx |
mov ax, di |
mov si, parse_RamdiskSize |
mov cx, parse_RamdiskSize_e - parse_RamdiskSize |
repe cmpsb |
jnz .rest_value_loop_RS ;is not compare |
sub bx, parse_RamdiskSize_e - parse_RamdiskSize;correct cx |
add bx, cx |
mov cx, bx |
test status_flag, flag_found_RS ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_RS |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_RS: |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .end_get_RS_ERROR_1 ;not found param |
cmp ah, byte [es:di-1] ;find '=' |
jnz .start_p_RS ; ïåðåéäåì íà íà÷àëî è ïîïðîáóåì íàéòè åùå ñåêöèþ |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;Òóò íóæíî ïðåîáðàçîâûâàòü ñòðî÷êó â öèôðîâîå çíà÷åíèå. |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
xor bx, bx |
mov cx, 5 |
@@: |
mov al, byte [es:di] |
cmp al, '0' |
jb .CS |
cmp al, '9' |
jbe .correct_val_RS |
.CS: |
cmp al, 'K' |
jz .correct_size_RS |
jmp .end_get_RS_ERROR_2 |
.correct_val_RS: |
imul bx, 10 |
xor al, 0x30 |
add bl, al |
inc di |
loop @b |
.correct_size_RS: |
;âîçìîæåí 1 âàðèàíò, êîãäà ðàçìåð çàäàí â K êèëëîáàéòàõ |
;âíóòðåííûé ôîðìàò äàííûõ ýòî êîë-âî çàïðîùåíîé ïàìÿòè â êá. |
test bx, bx |
jnz @f ;åñëè çíà÷åíèå îòëè÷íî îò 0 |
;;;;;ñîîáùåíèå îá îøèáêå, ðàçìåð "íàéäåíîãî" áëîêà =0 ìèíèìàëüíî ìû äîëæíû |
;óñòàíîâèòü 64 êá ðàçìåð ðàì äèñêà. |
or show_errors_sect, show_error_3 |
mov bx, 64 |
@@: |
jmp ._end_parse_RS |
.rest_value_loop_RS: |
mov di, ax |
mov cx, bx |
jmp .start_p_RS |
.end_get_RS_ERROR_1: |
;ñîîáùåíèå îá îøèáêå - äàííûé ó÷àñòîê êîäà íå áûë êîððåêòíî îáðàáîòàí :( |
or show_errors_sect, show_error_1 |
jmp ._end_parse_RS |
.end_get_RS_ERROR_2: |
or show_errors_sect, show_error_2 |
._end_parse_RS: |
if DEBUG |
pusha |
movzx eax, bx |
mov cx, 0x0a |
mov di, RamdiskSize_msg |
mov dword[ds:di], ' ' |
mov word [ds:di+4], ' ' |
call decode |
;Show size |
mov si, RamdiskSize_msg |
call printplain |
popa |
end if |
} |
macro use_free_memory |
{ |
local _support_function_use_free_memory |
;ìàêðîñ äëÿ ïîëó÷åíèÿ îáùåãî ÷èñëà äîñòóïíîé ïàìÿòè â êá, äëÿ ôîðìèðîâàíèÿ ðàì äèñêà çà ïðåäåëàìè 1 ìá. |
;èñïîëüçóåòñÿ 0õ88 ôóíêöèÿ 0õ15 ïðåðûâàíèÿ |
; åñëè ïîääåðæèâàåòñÿ ôóíêöèÿ, òî â ax çíà÷åíèå â êá, åñëè íåò, òî â ax=0 |
mov ah, 0x88 ;ah,0x88 |
int 0x15 |
jnc ._support_function_use_free_memory |
xor ax, ax |
;âîçâðàùàåò â ax ÷èñëî â êá |
._support_function_use_free_memory: |
mov free_ad_memory, ax ; åñëè íå ïîääåðæèâàåòñÿ áèîñîì, òî â ax=0 |
if DEBUG |
pushad |
movzx eax, ax |
mov cx, 0x0a |
mov di, free_memory_msg |
mov dword[ds:di], ' ' |
mov word [ds:di+4], ' ' |
call decode |
;Show size |
mov si, free_memory_msg |
call printplain |
popad |
end if |
} |
macro show_ERRORS |
{ |
} |
macro get_type_FS ;ïîëó÷èòü è ñîçäàòü îáðàç äëÿ çàäàííîé RFS. |
{ |
mov di, point_default ;restore value |
mov cx, save_cx_d |
.start_g_tpe_RFS: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz ._end_parse_FRS ;._end_get_type_RFS ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al, 'R' |
jnz .start_g_tpe_RFS |
;ïðîâåðêà íà çíà÷åíèÿ RamdiskSize |
; parse_RamdiskSize |
mov bx, cx |
mov ax, di |
mov si, parse_RamdiskFS |
mov cx, parse_RamdiskFS_e - parse_RamdiskFS |
repe cmpsb |
jnz .start_g_tpe_RFS_rest_v ;is not compare |
sub bx, parse_RamdiskFS_e - parse_RamdiskFS;correct cx |
add bx, cx |
mov cx, bx |
test status_flag, flag_found_GTRFMS ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_FRS |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_FRS: |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
test cx, cx |
jz .end_get_FRS_ERROR_1 ;not found param |
cmp ah, byte [es:di-1] ;find '=' |
jnz .start_g_tpe_RFS ; ïåðåéäåì íà íà÷àëî è ïîïðîáóåì íàéòè åùå ñåêöèþ |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;Òóò íóæíî ïðåîáðàçîâûâàòü ñòðî÷êó â öèôðîâîå çíà÷åíèå. |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov bx, cx |
mov ax, di |
mov si, parse_RFS_FAT |
mov cx, parse_RFS_FAT_e - parse_RFS_FAT |
repe cmpsb |
jnz .krfs_cmp ;is not compare |
make_FAT_RamFS ;ñäåëàòü |
if DEBUG |
pusha |
mov si, make_fat12_RFS_msg |
call printplain |
popa |
end if |
jmp ._end_parse_FRS |
.krfs_cmp: |
mov cx, bx |
mov di, ax |
mov si, parse_RFS_KRFS |
mov cx, parse_RFS_KRFS_e - parse_RFS_KRFS |
repe cmpsb |
; jnz @f ;is not compare |
jmp ._end_parse_FRS |
.start_g_tpe_RFS_rest_v: |
mov cx, bx |
mov di, ax |
jmp .start_g_tpe_RFS |
.end_get_FRS_ERROR_1: |
;ñîîáùåíèå îá îøèáêå - äàííûé ó÷àñòîê êîäà íå áûë êîððåêòíî îáðàáîòàí :( |
or show_errors_sect, show_error_1 |
jmp ._end_parse_FRS |
.end_get_FRS_ERROR_2: |
or show_errors_sect, show_error_2 |
._end_parse_FRS: |
if DEBUG |
pusha |
mov si, get_type_FS_msg |
call printplain |
popa |
end if |
} |
macro make_FAT_RamFS |
{ |
local .RS1 |
local .fat12 |
local .fat16 |
; ìû äîëæíû ñôîðìèðîâàòü â íà÷àëüíûé îáðàç Ram FS, à ïîòîì çàïèñàòü åãî çà îáëàñòü âûøå 1 ìá.. |
;äëÿ ñëó÷àÿ ñ FAT12 |
; mov di,fat12_buffer ;ds äîëæåí áûòü = cs |
;es:di - óêàçûâàþò íà íà÷àëî áëîêà äëÿ ôîðìèðîâàíèÿ ðàì ôñ. |
use_RamdiskSector ;âîçðàùàåìîå çíà÷åíèå â ax ðàçìåð ñåêòîðà â áàéòàõ |
cmp ax, 4096;ïî ñïåöèôèêàöèè çíà÷åíèå äîëæíî áûòü â ïðåäåëàõ îò 1 äî 4096 |
ja .RS1 |
test ax, ax |
jnz @f ;îøèáêà åñëè ñþäà ïðûãíóëè âñå òàêè ... |
.RS1: |
mov word [fat12_buffer.BPB_BytsPerSec], 512 |
;;;;;;;;;;ñêàæåì ÷òî ïî äåôîëòó áóäåì þçàòü çíà÷åíèå... |
@@: |
mov word [fat12_buffer.BPB_BytsPerSec], ax;òóò âñå îê |
;BPB_SecPerClus êîë-âî ñåêòîðîâ â êëàñòåðå |
use_RamdiskCluster ;âîçðàùàåìîå çíà÷åíèå â al |
cmp al, 128 |
ja @f |
; test al,0x1 ;ïðîâåðêà íà êðàòíîñòü ) |
; jnz @f |
mov byte [fat12_buffer.BPB_SecPerClus], al |
;incorrect value will be set dafault |
;íèæå íåêîððåêòíîå çíà÷åíèå â ò.ê. ðàçìåð êðàòåí 2 è â äèàïàçîíå îò 1 äî 128 âêëþ÷èòåëüíî |
; ìû äîëæíû ðóãíóòüñÿ íà ýòî |
;@@: ;mov byte [fat12_buffer.BPB_SecPerClus],1 |
;;;;; îïðåäåëåèì êàêàÿ ó íàñ áóäåò èñïîëüçîâàòüñÿ FAT |
;ïî óñëîâèþ, fat12<4085<=fat16<65525<=fat32 |
; fat12_buffer.BPB_BytsPerSec*fat12_buffer.BPB_SecPerClus = êîë-âî ñåêòîðîâ |
movzx eax, word [fat12_buffer.BPB_BytsPerSec] |
movzx ebx, byte [fat12_buffer.BPB_SecPerClus] |
imul ebx, eax;òóò ðàçìåðíîñòü ñåêòîðà |
mov eax, save_ramdisksize ;ðàçìåð çàïðîøåííîãî ðàì äèñêà â áàéòàõ |
cdq |
idiv ebx |
;;;;;;;; ñåé÷àñ ÷àñòíîå â eax, à îñòàòîê â edx |
;ïîëó÷èì êîë-âî ñåêòîðîâ, è ìîæåì óæå îïðåäåëèòü òèï FAT êîòîðóþ íóæíî äåëàòü. |
cmp eax, 4085 |
jb .fat12 |
cmp eax, 65525 |
jb .fat16 |
;;;;;;;;;;;;;;;;;;;;;;;; òóò fat32 |
mov set_ramfs, 32 ;óñòàíîâèì òèï ôàéëîâîé ñèñòåìû |
mov word [fat12_buffer.BPB_RsvdSecCnt], 32 |
xor eax, eax |
mov word [fat12_buffer.BPB_RootEntCnt], ax |
mov word [fat12_buffer.BPB_TotSec16], ax |
mov dword [fat12_buffer.BPB_TotSec32], eax |
.fat16: ;fat16 |
;Äëÿ FAT12 è FAT16 äèñêîâ ýòî ïîëå ñîäåðæèò êîëè÷åñòâî ñåêòîðîâ, à BPB_TotSec32 ðàâíî 0, åñëè çíà÷åíèå <óìåùàåòñÿ> (ìåíüøå 0x10000). |
jmp $ |
mov set_ramfs, 16 ;óñòàíîâèì òèï ôàéëîâîé ñèñòåìû |
movzx ebx, byte [fat12_buffer.BPB_SecPerClus] |
imul eax, ebx |
cmp eax, 0x10000 |
jae @f |
mov word [fat12_buffer.BPB_TotSec16], ax |
mov dword [fat12_buffer.BPB_TotSec32], 0 |
@@: |
;êîëè÷åñòâî ñåêòîðîâ çàíèìàåìîå îäíîé êîïèåé ôàò |
; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Äëÿ FAT12/FAT16 ýòî êîëè÷åñòâî ñåêòîðîâ îäíîé FAT. ?? |
;;;; çàïîëíèì BPB_RootEntCnt Äëÿ FAT12 è FAT16 äèñêîâ, ýòî ïîëå ñîäåðæèò ÷èñëî |
;32-áàéòíûõ ýëåìåíòîâ êîðíåâîé äèðåêòîðèè. Äëÿ FAT32 äèñêîâ, ýòî ïîëå äîëæíî |
;áûòü 0. Ïîêà êîíñòàíòà, íóæíî áóäåò ïîçæå äîäåëàòü. |
mov eax, root_dir_entry_count |
mov word [fat12_buffer.BPB_RootEntCnt], ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) |
;ïî äîêóìåíòàöèè ðåêîìåíäóþò îòðåçàòü 16 êá äëÿ ðóò äèð íî ýòî î÷ ìíîãî, äàæå äëÿ êîîñ. èìõî äëÿ íà÷àëà õâàòèò è 7 êá |
;;;;;;; |
;Äëÿ FAT16 ýòî êîëè÷åñòâî ñåêòîðîâ îäíîé FAT. Äëÿ FAT32 ýòî çíà÷åíèå |
;ðàâíî 0, à êîëè÷åñòâî ñåêòîðîâ îäíîé FAT ñîäåðæèòñÿ â BPB_FATSz32. |
;RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec; |
;TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors); |
;TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs; |
;If(FATType == FAT32) |
; TmpVal2 = TmpVal2 / 2; |
;FATSz = (TMPVal1 + (TmpVal2 - 1)) / TmpVal2; |
;If(FATType == FAT32) { |
; BPB_FATSz16 = 0; |
; BPB_FATSz32 = FATSz; |
;} else { |
; BPB_FATSz16 = LOWORD(FATSz); |
; /* there is no BPB_FATSz32 in a FAT16 BPB */ |
;} |
;===================================== |
;RootDirSectors |
movzx ebx, word [fat12_buffer.BPB_BytsPerSec] |
imul eax, 32 |
add eax, ebx |
dec eax |
cdq |
idiv ebx |
;;;;;;;; ñåé÷àñ ÷àñòíîå â eax, à îñòàòîê â edx äëÿ äèñêåòû 1.44 ó íàñ äîëæíî áûòü çíà÷åíèå =14 |
;BPB_ResvdSecCnt + RootDirSectors |
movzx ebx, word [fat12_buffer.BPB_RsvdSecCnt] |
add ebx, eax |
;DskSize ó íàñ ýòî çíà÷åíèå óæå ïîëó÷åíî è äîñòóïíî |
movzx eax, word [fat12_buffer.BPB_TotSec16] ;äîëæåí áûòü â ñåêòîðàõ |
sub eax, ebx |
;TmpVal1=eax |
shl edi, 8 ;=edi*256 |
movzx ecx, byte [fat12_buffer.BPB_NumFATs] |
add edi, ecx |
;TmpVal2=edi |
add eax, edi |
dec eax |
cdq |
idiv edi |
;FATSz = ñåé÷àñ ÷àñòíîå â eax, à îñòàòîê â edx |
mov word [fat12_buffer.BPB_FATSz16], ax |
.fat12: ;fat12 |
if DEBUG |
; âûâåäåì â îòëàäêå, ÷òî ñîáèðàåìñÿ äåëàòü îáðàç äèñêà c FS=fat12 |
pushad |
mov si, start_making_FAT12_msg |
call printplain |
popad |
end if |
;Äëÿ FAT12 è FAT16 äèñêîâ ýòî ïîëå ñîäåðæèò êîëè÷åñòâî ñåêòîðîâ, à BPB_TotSec32 ðàâíî 0, åñëè çíà÷åíèå <óìåùàåòñÿ> (ìåíüøå 0x10000). |
mov set_ramfs, 12 ;óñòàíîâèì òèï ôàéëîâîé ñèñòåìû |
movzx ebx, byte [fat12_buffer.BPB_SecPerClus] |
imul eax, ebx |
cmp eax, 0x10000 |
jae @f |
mov word [fat12_buffer.BPB_TotSec16], ax |
mov dword [fat12_buffer.BPB_TotSec32], 0 |
@@: |
;êîëè÷åñòâî ñåêòîðîâ çàíèìàåìîå îäíîé êîïèåé ôàò |
; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Äëÿ FAT12/FAT16 ýòî êîëè÷åñòâî ñåêòîðîâ îäíîé FAT. ?? |
;;;; çàïîëíèì BPB_RootEntCnt Äëÿ FAT12 è FAT16 äèñêîâ, ýòî ïîëå ñîäåðæèò ÷èñëî |
;32-áàéòíûõ ýëåìåíòîâ êîðíåâîé äèðåêòîðèè. Äëÿ FAT32 äèñêîâ, ýòî ïîëå äîëæíî |
;áûòü 0. Ïîêà êîíñòàíòà, íóæíî áóäåò ïîçæå äîäåëàòü. |
mov eax, root_dir_entry_count |
mov word [fat12_buffer.BPB_RootEntCnt], ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) |
;ïî äîêóìåíòàöèè ðåêîìåíäóþò îòðåçàòü 16 êá äëÿ ðóò äèð íî ýòî î÷ ìíîãî, äàæå äëÿ êîîñ. èìõî äëÿ íà÷àëà õâàòèò è 7 êá |
;;;;;;; |
;DskSize(â ñåêòîðàõ)*12 (ðàçìåðíîñòü ôàéëîâîé ñèñòåìû, ò.å ïðåäïîëîæèì ñêîëüêî áèòîâ ïîòðåáóåòñÿ äëÿ àäðåñàöèè ýòîãî îáúåìà) /8 (÷òî ïîëó÷èòü ðàçìåð â áàéòàõ) |
;ïîëó÷åííîå ÷èñëî îêðóãëÿåì â áîëüøóþ ñòîðîíó êðàòíîå ñåêòîðó ò.å. 512 áàéò Òàêîé ïîäõîä íå óíèâåðñàëåí, íî ïîêà ïîéäåò |
;âîîáùå ó ìåëêîñîôò ýòî âñå ñ÷èòàåòñÿ ðó÷êàìè, íî ìû áóäåì þçàòü òîëüêî ïîä êîîñ ðàì äèñê ñ ôàò12 |
movzx eax, word [fat12_buffer.BPB_TotSec16] |
imul eax, 12 |
shr eax, 3 ;äåëèì íà 8 íî ò.å. íàì íóæíî äåëèòü åùå è íà 512 èëè áîëåå â çàâèñèìîñòè îò ðàçìåðîâ êëàñòåðà |
movzx ebx, word [fat12_buffer.BPB_BytsPerSec] ;ðàçìåð ñåêòîðà |
cdq |
idiv ebx ;ðàçäåëèì íà ðàçìåð êëàñòåðà |
;ñåé÷àñ ó íàñ â eax çíà÷åíèå åãî íóæíî îêðóãëèòü â áîëüøóþ ñòîðîíó êðàòíîìó 512 áàéòàì |
;ïðèìåíèì ñëåäóþùåå î÷èñòèì and è äîáàâèì 512 áàéò. òàêèì îáðàçîì âûðàâíèì íà 512 áàéò |
;íî ò.ê. âñå ðàâíî äåëèòü íèæíèé êîä íàì íå íóæåí |
; and eax,0xfff200 |
; add eax,0x200 ;äîáàâèì 512 áàéò äëÿ 1.44 äèñêåòû èäåàëüíî ïîäõîäèò )) |
inc ax |
;ïî èäåå äîëæíî íà êàæäóþ ôàò òàáëèöó |
;ðåçåðâèðîâàòüñÿ 9 ñåêòîðîâ ò.å. ïîëó÷àåòñÿ 2*9=18+1 =19 ñåêòîðîâ ò.å. ðóò äèð íàõîäèòüñÿ íà ñ 20 ñåòîðà ò.å. ñ àäðåñà 0õ2600 |
;ñåé÷àñ íóæíî âû÷èñëèòü ñêîëüêî áóäåò ñåêòîðîâ çàíèìàòü ôàò ) íóæíî ðàçäåëèòü íà 512 |
;FATSz = ñåé÷àñ ÷àñòíîå â eax |
mov word [fat12_buffer.BPB_FATSz16], ax |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
get_firstDataSector ;ïîëó÷èòü ñìåùåíèå äî äàííûõ |
;ñîçäàäèì ïåâóþ çàïèñü â ôàò ïî îïðåäåëåííîìó àäðåñó. |
first_create_fat_table |
;çàêèíèì BPB ôàéëîâîé ñèñòåìû çà 1 ìá. |
use_BPB_RAM |
; |
;êîïèðîâàíèå ôàéëà. |
use_RamdiskFile |
;;;; âû÷èñëÿåì óêàçàòåëü íà êîðíåâóþ äèð FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16); |
; movzx ebx, [fat12_buffer.BPB_NumFATs] |
; movzx eax,ax |
; imul eax,ebx |
;eax=(BPB_NumFATs * BPB_FATSz16) |
; inc eax |
; BPB_ResvdSecCnt çíà÷åíèå òîëüêî 1 äëÿ fat12/16 |
;â eax óêàçàòåëü íà root dir. äëÿ äèñêåòû fat12 äîëæíî ïîëó÷èòüñÿ ïðè êîë-âî êîïèé fat 1 = 1+ (1*1) =2 èëè 3 |
if DEBUG |
pusha |
; mov ax,point_default |
; mov ax,cx |
mov cx, 0x0a |
mov di, show_db1 |
; mov dword[ds:di],' ' |
; mov word [ds:di+4],' ' |
call decode |
;Show size |
mov si, show_db1 |
call printplain |
; |
; xor ax,ax |
; int 0x16 |
popa |
end if |
} |
macro use_RamdiskSector |
{ |
;äëÿ íåêîòîðûõ FS áóäåò èãíîðèðîâàòüñÿ |
mov di, point_default ;restore value |
mov cx, save_cx_d |
.start_RamdiskSector: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz .end_RamdiskSector ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al, 'R' |
jnz .start_RamdiskSector |
;ïðîâåðêà íà çíà÷åíèÿ RamdiskSize |
; parse_RamdiskSize |
mov bx, cx |
mov ax, di |
mov si, parse_RamdiskSector |
mov cx, parse_RamdiskSector_e - parse_RamdiskSector |
repe cmpsb |
jnz .RamdiskSector_rest_val ;is not compare |
sub bx, parse_RamdiskSector_e - parse_RamdiskSector;correct cx |
add bx, cx |
mov cx, bx |
test status_flag, flag_found_RamdiskSector ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_RamdiskSector |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_RamdiskSector: |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .end_get_RamS_ERROR_1 ;not found param |
cmp ah, byte [es:di-1] ;find '=' |
jnz .start_RamdiskSector ; ïåðåéäåì íà íà÷àëî è ïîïðîáóåì íàéòè åùå ñåêöèþ |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
xor bx, bx |
mov cx, 4 |
@@: |
movzx ax, byte [es:di] |
cmp al, '0' |
jb .end_RamdiskSector |
cmp al, '9' |
ja .end_RamdiskSector |
;;;;;;;;;;;;;;;;;;; |
imul bx, 10 |
xor al, 0x30 |
add bx, ax |
inc di |
loop @b |
jmp .end_RamdiskSector |
.RamdiskSector_rest_val: |
mov cx, bx |
mov di, ax |
jmp .start_RamdiskSector |
.end_get_RamS_ERROR_1: |
.end_RamdiskSector: |
mov ax, bx |
if DEBUG |
pusha |
movzx eax, bx;save_cx_d;point_default |
mov cx, 0x0a |
mov di, RamdiskSector_msg |
mov dword[ds:di], ' ' |
mov dword [ds:di+4], ' ' |
call decode |
;Show size |
mov si, RamdiskSector_msg |
call printplain |
popa |
end if |
; pop di |
; pop es |
} |
macro use_RamdiskCluster |
{ |
;äëÿ íåêîòîðûõ FS áóäåò èãíîðèðîâàòüñÿ |
; push es |
; push di |
mov di, point_default ;restore value |
mov cx, save_cx_d |
; push ini_data_ |
; pop es |
.start_RamdiskCluster: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz .end_RamdiskCluster ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al, 'R' |
jnz .start_RamdiskCluster |
;ïðîâåðêà íà çíà÷åíèÿ RamdiskSize |
; parse_RamdiskSize |
mov bx, cx |
mov ax, di |
mov si, parse_RamdiskCluster |
mov cx, parse_RamdiskCluster_e - parse_RamdiskCluster |
repe cmpsb |
jnz .RamdiskCluster_rest_val ;is not compare |
sub bx, parse_RamdiskCluster_e - parse_RamdiskCluster;correct cx |
add bx, cx |
mov cx, bx |
test status_flag, flag_found_RamdiskCluster ;îöåíêà ôëàãîâ |
jz .correct_is_not_set_RamdiskCluster |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
.correct_is_not_set_RamdiskCluster: |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .end_get_RamSC_ERROR_1 ;not found param |
cmp ah, byte [es:di-1] ;find '=' |
jnz .start_RamdiskCluster ; ïåðåéäåì íà íà÷àëî è ïîïðîáóåì íàéòè åùå ñåêöèþ |
repe scasb ;cut ' ' |
inc cx |
dec di |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
@@: |
movzx ax, byte [es:di] |
cmp al, '0' |
jb .end_RamdiskCluster |
cmp al, '9' |
ja .end_RamdiskCluster |
;;;;;;;;;;;;;;;;;;; |
xor al, 0x30 |
jmp .end_RamdiskCluster |
.RamdiskCluster_rest_val: |
mov cx, bx |
mov di, ax |
jmp .start_RamdiskCluster |
.end_get_RamSC_ERROR_1: |
.end_RamdiskCluster: |
if DEBUG |
pusha |
mov cx, 0x0a |
mov di, RamdiskCluster_msg |
; mov word[ds:di],' ' |
call decode |
;Show size |
mov si, RamdiskCluster_msg |
call printplain |
popa |
end if |
} |
macro use_Loader_Image |
;ïðåäíàçíà÷åí äëÿ çàãðóçêè îáðàçîâ âûøå 1 Ìá. |
;ïåðâîíà÷àëüíàÿ âåðñèÿ çàãðóæàåò îáðàç äèñêåòû 1.44 ìá |
{ |
local .start_p_LI |
local .exit |
local .error_LI |
local .rest_value_loop |
local .found_end_str |
mov di, point_default ;restore value |
mov cx, save_cx_d |
;îáðàáîòêà êîíñòðóêöèè òèïà LoaderModule=kord/kolibri.ldm |
.start_p_LI: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz .exit ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al, 'L' |
jnz .start_p_LI |
;ïðîâåðêà íà çíà÷åíèå LoaderModule |
; parse_LoaderModule |
mov bx, cx |
mov ax, di |
mov si, parse_LoaderImage |
mov cx, parse_LoaderImage_e - parse_LoaderImage |
repe cmpsb |
jnz .rest_value_loop ;is not compare |
sub bx, parse_LoaderImage_e - parse_LoaderImage;correct cx |
add bx, cx |
mov cx, bx |
; test status_flag,flag_found_LM ;îöåíêà ôëàãîâ |
; jz .correct_is_not_set_LI |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
;.correct_is_not_set_LI: |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .rest_value_loop_LI ;not found param timeout |
cmp ah, byte [es:di-1] ;find '=' |
jnz .rest_value_loop_LI |
repe scasb ;cut ' ' |
inc cx |
dec di |
;di óêàçûâàåò íà íà÷àëî áëîêà èíôîðìàöèè, â cx äëèííà äî êîíöà ñåêöèè. |
;ïîñëå çàãðóçêè çàíîñèòüñÿ çíà÷åíèå çàíÿòîé ïàìÿòè. |
;äëÿ òîãî ÷òî áû çàãðóçèòü ìîäóëü, âîñïîëüçóåìñÿ callback ñåðâèñîì |
;îðèãèíàëüíîå ðåøåíèå - ðàçìåñòèì dd ïåðåä ñòðî÷êîé è ïîñëå ñòðî÷êè ðàçìåñòèì byte =0 |
;ýòî âûãëÿäèò òàê: â ini ôàéëå ñóùåñòâóåò ñòðî÷êà LoaderModule = kord/kernel.loader |
;ìû åå ìîäèôèöèðóåì äî òàêîãî ñîñòîÿíèÿ dw,dw,db'kord/kernel.loader',0 êîíå÷íî ñîõðàíèâ òå çíà÷åíèÿ êîòîðûå ìû çàìåíÿåì |
;ñîõðàíèëè ïåâûå 2 word |
push dword [es:di-6] |
lea si, [di-6] |
push word [es:di-2] |
xor ax, ax |
mov word [es:di-6], ax ;âíîñèì íóæíûå çíà÷åíèÿ |
;info_real_mode_size ðàçìåð è óêàçàòåëü íà îáëàñòü â êîòîðóþ ìîæíî çàãðóçèòüñÿ |
mov ax, info_real_mode_size ;0x3000 ;ñëåäóþùèé ñåãìåíò çà äàííûìè |
mov word [es:di-4], ax |
mov word [es:di-2], 16 ;êîë-âî áëîêîâ ïî 4 êá =64 êá ò.å. áîëüøå íå ñ÷èòàåì |
;;;;;; ïîèñê êîíöà ñòðî÷êè |
@@: |
mov al, byte [es:di] |
cmp al, ' ' |
jz .found_end_str |
cmp al, 0xa |
jz .found_end_str |
cmp al, 0xd |
jz .found_end_str |
inc di |
dec cx |
jnz @b |
;;;not found äîïóñòèì,÷òî ýòî êîíåö ôàéëà è îí íå èìååò ïðèâû÷íîãî çàâåðåøíèÿ ñòðîêè |
.found_end_str: |
; ÷òåíèå áëîêà ïî 64 êá â ñåãìåíò è çàáðàñûâàíèå åãî âûøå 1 ìá. |
push word [es:di] |
xor ax, ax |
mov word [es:di], ax |
; xor ax,ax ; function 1 - read file |
mov di, si ;file_data |
inc ax |
push si |
push es |
call far dword [loader_callback] |
push cs |
pop ds |
pop es |
pop si |
test bx, bx |
jnz .error_LM |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; çàáðàñûâàíèå áëîêà â 64 êá âûøå 1 ìá. |
mov si, table_15_87 |
push es |
push ds |
pop es |
mov cx, 256*18 |
mov ah, 0x87 |
int 0x15 |
pop es |
pop dx cx |
test ah, ah |
jmp far dword [es:si] |
.rest_value_loop: |
mov di, ax |
mov cx, bx |
jmp .start_p_LI |
.exit: |
} |
macro name_in_root_fat |
;ìàêðîñ, êîòîðûé çàïèñûâàåò èíôîðìàöèþ î çàãðóæåííîì ôàéëå â êîðíåâóþ ôàò òàáëèöó |
{ |
} |
macro use_RamdiskFile |
{ |
;çàãðóçêà ôàéëîâ ñ èñïîëüçîâàíèå callback ñåðâèñà ïåðâè÷íîãî çàãðóç÷èêà |
;èñïîëüçóåòñÿ òîëüêî äëÿ çàãðóçêè íåîáõîäèìûõ è íåáîëüøèõ ôàéëîâ, ò.ê. äîñòàòî÷íî ìåäëåííî ðàáîòàåò |
;äëÿ çàãðóçêè èñïîëüçóåò 0õ87 ôóíêöèþ int 0x15 ïðåðûâàíèÿ - çàãðóçêà áëîêîâ äàííûõ äî 64 êá âûøå 1 ìá |
local .start_loop |
local ._end |
local .rest_value_loop |
local .error |
mov di, point_default ;restore value |
mov cx, save_cx_d |
mov data_offset, 0 ;clean offset |
;îáðàáîòêà êîíñòðóêöèè òèïà LoaderModule=kord/kolibri.ldm |
.start_loop: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz ._end ;íåòó? íó ëàäíî - ñëåäóþùåå çíà÷åíèå òîãäà ) |
cmp al, 'R' |
jnz .start_loop |
;ïðîâåðêà íà çíà÷åíèå RamdiskFile |
mov bx, cx |
mov ax, di |
mov si, parse_RamdiskFile |
mov cx, parse_RamdiskFile_e - parse_RamdiskFile |
repe cmpsb |
jnz .rest_value_loop ;is not compare |
sub bx, parse_RamdiskFile_e - parse_RamdiskFile;correct cx |
add bx, cx |
mov cx, bx |
; test status_flag,flag_found_LM ;îöåíêà ôëàãîâ |
; jz .correct_is_not_set_LM |
; mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
; call printplain |
; jmp .get_next_str |
;.correct_is_not_set_LM: |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
test ecx, ecx |
jz .rest_value_loop ;not found param timeout |
cmp ah, byte [es:di-1] ;find '=' |
jnz .rest_value_loop |
repe scasb ;cut ' ' |
inc cx |
dec di |
mov save_di_RAMDISK, di |
mov save_cx_RAMDISK, cx |
;di óêàçûâàåò íà íà÷àëî áëîêà èíôîðìàöèè, â cx äëèííà äî êîíöà ñåêöèè. |
;ïîñëå çàãðóçêè çàíîñèòüñÿ çíà÷åíèå çàíÿòîé ïàìÿòè. |
;äëÿ òîãî ÷òî áû çàãðóçèòü ìîäóëü, âîñïîëüçóåìñÿ callback ñåðâèñîì |
;îðèãèíàëüíîå ðåøåíèå - ðàçìåñòèì dd ïåðåä ñòðî÷êîé è ïîñëå ñòðî÷êè ðàçìåñòèì byte =0 |
;ýòî âûãëÿäèò òàê: â ini ôàéëå ñóùåñòâóåò ñòðî÷êà RamdiskFile = @menu,@menu |
;ìû åå ìîäèôèöèðóåì äî òàêîãî ñîñòîÿíèÿ dw,dw,db'@menu',0 êîíå÷íî ñîõðàíèâ òå çíà÷åíèÿ êîòîðûå ìû çàìåíÿåì |
;ñîõðàíèëè ïåâûå 2 word |
; |
@@: |
mov al, byte [es:di] |
cmp al, ',' ; ò.å. èùåì ðàçäåëèòåëü |
jz .found_end_str |
inc di |
dec cx |
jnz @b |
;;;not found äîïóñòèì,÷òî ýòî êîíåö ôàéëà è îí íå èìååò ïðèâû÷íîãî çàâåðøåíèÿ ñòðîêè |
.found_end_str: |
; mov al,byte [es:di] |
; cmp al,' ' ; óáèðàåì ïðîáåëû, åñëè îíè åñòü |
; jnz @f |
; inc di |
; dec cx |
; jnz .found_end_str |
;@@: |
mov point_to_dest_file_name, di |
inc di |
;ïðîâåðêà èíäèâèäóàëüíîñòè èìåíè ôàéëà |
check_name_file |
;/restore di - point and cx -size section |
mov di, save_di_RAMDISK |
mov cx, save_cx_RAMDISK |
test al, al |
jnz .start_loop ;åñëè â al çíà÷åíèå íå =0, òî òàêîå èìÿ óæå ñóùåñòâóåò â ñèñòåìå. |
push dword [es:di-6] |
lea si, [di-6] |
push word [es:di-2] |
push di |
xor ax, ax |
mov word [es:di-6], ax ;âíîñèì íóæíûå çíà÷åíèÿ |
;info_real_mode_size ðàçìåð è óêàçàòåëü íà îáëàñòü â êîòîðóþ ìîæíî çàãðóçèòüñÿ |
mov ax, info_real_mode_size ;0x3000 ;ñëåäóþùèé ñåãìåíò çà äàííûìè |
mov word [es:di-4], ax |
mov word [es:di-2], 16 ;êîë-âî áëîêîâ ïî 4 êá =64 êá ò.å. áîëüøå íå ÷èòàåì |
mov di, point_to_dest_file_name |
if DEBUG |
pushad |
; mov ax,di |
mov cx, 0x0a |
mov di, name_of_seg_get_64 |
mov dword[ds:di], ' ' |
mov word[ds:di+4], ' ' |
call decode |
;Show size |
mov si, name_of_seg_get_64 |
call printplain |
popad |
end if |
push word [es:di] |
push cx |
xor ax, ax |
mov word [es:di], ax |
; xor ax,ax ; function 1 - read file |
push di |
mov di, si ;file_data |
inc ax |
push si |
push es |
push bp |
push es |
pop ds |
push cs |
pop es |
call far dword [es:loader_callback] |
push cs |
pop ds |
pop bp |
pop es |
pop si |
cmp bx, 2 |
ja .error |
; ñåé÷àñ ó íàñ â dx:ax ðàçìåð ôàéëà, êîòîðûé ìû çàãðóçèëè. |
; âîçìîæíà ñèòóàöèÿ, êîãäà â bx=1 ò.å. åñòü åùå äàííûå íà äèñêå |
mov status_flag_loader_f, bx |
shl edx, 16 |
mov dx, ax |
; shr edx,10 ;ðàçìåð ôàéëà â êá. |
;;â edx ðàçìåð â áàéòàõ. |
mov save_file_size, edx |
mov eax, edx |
;âîññòàíîâèì ïîëíîñòüþ ôàéë ñöåíàðèÿ |
pop di |
pop cx ;äëèííà îñòàòêà ñ 2-îé ÷àñòüþ èìåíè ò.å. ñ èìåíåì íàçíà÷åíèåì. |
pop word [es:di] |
pop di |
pop word [es:di-2] |
pop dword [es:di-6] |
if DEBUG |
pushad |
mov cx, 0x0a |
mov di, RamdiskFile_msg |
mov dword[ds:di], ' ' |
call decode |
;Show size |
mov si, RamdiskFile_msg |
call printplain |
popad |
end if |
; çàãðóçèì ÷åìó ó íàñ ðàâåí êëàñòåð |
; mov ax,word [fat12_buffer.BPB_BytsPerSec] ;êîë-âî áàéòîâ â ñåêòîðå ìîæåò áûòü ëþáîå 512 1024 2048 4096 2 áàéòà |
; movzx bx,byte [fat12_buffer.BPB_SecPerClus] ;êîë-âî ñåêòîðîâ â êëàñòåðå |
; imul ax,bx |
;ñåé÷àñ â eax ðàçìåð êëàñòåðà (512) áàéò |
;â edx äëèíà ôàéëà â áàéòàõ äî 64 êá |
;çàêèíèì ôàéë çà 1 ìá |
;1 íàì íóæíî ñîñòàâèòü ôàò òàáëèöó ò.å. ïðîèçâåñòè ðàçìåòêó ðàìäèñêà, çàòåì ïåðåíåñåì ïî àäðåñó ôàéë |
;çàïèñàòü èíôîðàìàöèþ î ôàéëå â êîðíåâóþ äèðåêòîðèþ |
register_file_in_fat |
;ïåðåíåñòè çà 1 ìá ñîäåðæèìîå ôàéëà |
move_file_up |
;ïðîâåðèì, çàãðóæåí ëè äî êîíöà ôàéë? ò.å. åñëè ðàçìåð ôàéëà áîëüøå ÷åì 64 êá, òî áóäåò ïîäãðóæàòü îñòàâøèåñÿ áëîêè |
cmp status_flag_loader_f, 0x1 |
jnz @f |
;íóæíî äîçàãóçèòü äàííûå ôàéëà è ïåðåíåñòè èõ çà 1-ûé ìá ñîãëàñíî ôàò ñòðóêòóðå |
@@: |
;òóò îðãàíèçîâàí öèêë ïî çàãðóçêå ôàéëîâ â êîðíåâóþ äèðåêòîðèþ |
mov di, save_di_RAMDISK |
mov cx, save_cx_RAMDISK |
if DEBUG |
pusha |
xor ax, ax |
int 0x16 |
popa |
end if |
jmp .start_loop |
.error: |
;call error.LoaderModule |
;fixme! |
.rest_value_loop: |
mov di, ax |
mov cx, bx |
jmp .start_loop |
._end: |
;ïåðåíåñåì çà 1-ûé ìá ôàò è ðóò äèð |
move_up_fat_and_root_d |
;çàãðóçêà áëîêà |
; mov ah,0x87 |
; mov cx, ;size in byte |
;es:si point to descripts |
} |
macro use_BPB_RAM ;çàêèíóòü ñàìûå ïåðâûå 512 áàéò çà 1-é ìá |
;äàííûé ìàêðîñ çàêèäûâàåò BPB ñòðóêòóðó ò.å. ïåðâûå 512 áàéò, ïîêà òîëüêî ôàò12 çà 1 ìá |
{ |
mov ax, fat12_buffer |
mov si, table_15_87 |
add word [si+8*2+2], ax |
push es |
push ds |
pop es |
mov cx, 256 ;áóò ñåêòîð óêëàäûâàåòñÿ â 512 áàéò 512/2=256 |
mov ah, 0x87 |
int 0x15 |
pop es |
;add 512 byte for destination adress |
; add dword [si+8*3+2], 512 |
; test ah, ah |
; jz |
if DEBUG |
pusha |
mov ax, word [si+8*2+2] |
mov cx, 0x0a |
mov di, BPB_msg |
call decode |
;Show size |
mov si, BPB_msg |
call printplain |
popa |
end if |
} |
macro first_create_fat_table |
;äàííûé ìàêðîñ ñîçäàåò îôîðìëÿåò 3 ïåðâûõ áàéòà fat òàáëèöû, è óñòàíàâëèâàåò óêàçàòåëü íà ñëåäóþùèé áëîê, è âíîñèò 0 çíà÷åíèå |
;äëÿ ñìåùåíèÿ â êîðíåâîé òàáëèöå. |
{ |
mov al, byte [fat12_buffer.BPB_Media] |
push ds |
mov di, info_real_mode_size |
add di, 0x1000 |
if DEBUG |
pushad |
mov ax, info_real_mode_size |
add ax, 0x1000 |
; mov ax,ds |
mov cx, 0xa |
mov di, first_entry_in_fat |
mov dword [di], ' ' |
mov word [di+4], ' ' |
call decode |
;Show size |
mov si, first_entry_in_fat |
call printplain |
xor ax, ax |
int 0x16 |
popad |
end if |
push di ; push word info_real_mode_size+0x1000 ;cëåäóþùèé ñåãìåíò çà çàãðóæåííûì ó÷àñòêîì |
xor di, di |
mov point_to_free_root, di ;çíà÷åíèå ñìåùåíèÿ =0 â êîðíåâîé ôàò òàáëèöå îïèñàíèÿ |
pop ds ; çàãðóæåí ñëåäóþùèé ñåãìåíò ò.å. ïóñòîé ñåãìåíò |
mov byte [di], al |
or ax, -1 |
inc di |
mov word [di], ax |
pop ds |
mov point_next_fat_str, 3 |
if DEBUG |
pushad |
mov ax, point_next_fat_str |
mov cx, 0x0a |
mov di, fat_create_msg |
call decode |
;Show size |
mov si, fat_create_msg |
call printplain |
popad |
end if |
} |
macro register_file_in_fat |
;ìàêðîñ ðåãèñòðàöèè ôàéëà â ôàéëîâîé ñòðóêòóðå Fat |
;ïîêà ïîääåðæèâàåòñÿ òîëüêî ôàò12, ïîêà )) |
;âû÷èñëåíèå ñìåæíûõ êëàñòåðîâ è çàíåñåíèå èíôû â fat/ |
{ |
local .step2 |
local .step3 |
local .end |
local .eof_file |
;di point on root dir íà ôðè ñåêöèþ. |
push es |
mov ax, info_real_mode_size |
add ax, 0x1000 |
mov es, ax ; push word info_real_mode_size+0x1000 ;ñåãìåíò ñëåäóþùèé çà çàãðóæåííûì áëîêîì â 64 êá |
; îïðåäåëÿåì òèï ôàò ïîêà íå îïðåäåëÿåì, ïîêà òîëüêî ôàò 12 |
; 12 áèò, äëÿ âû÷åñëåíèÿ ñîñåäíèõ êàëàñòåðîâ. |
mov di, firstDataSect ;â ñåêòîðàõ |
sub di, size_root_dir |
;òåïåðü â ax ðàçìåð â ñåêòîðàõ íà÷àëà ðóò äèð |
shl di, 9;imul 512 |
add di, point_to_free_root ;ñìåùåíèå â óæå çàïèñàííûõ 32-õ ñòðóêòóðàõ. |
;íåîáõîäèìî âíåñòè çíà÷åíèå â ðóò äèð ò.å. 32 áàéòà |
if DEBUG |
pushad |
; mov ax,point_default |
; mov ax, |
mov cx, 0x0a |
mov di, show_db2 |
mov dword[ds:di], ' ' |
mov word [ds:di+4], ' ' |
call decode |
;Show size |
mov si, show_db2 |
call printplain |
; |
; xor ax,ax |
; int 0x16 |
popad |
end if |
;gs:di - óêàçàòåëü äëÿ âíåñåíèÿ èíôîðàöèè â ðóò îáëàñòü ôàò òàáëèöû èíîðìàöèè î ôàéëå. |
mov si, shot_name_fat |
mov cx, 11 |
;çàïèøåì â ñòðóêòóðó èìÿ |
@@: |
lodsb |
stosb |
loop @b |
;çàïèøåì àòðèáóòû ôàéëà è DIR_NTRes - çàðåçåâðèðîâàííûé áàéò =0 |
xor ax, ax |
mov ah, ATTR_VOLUME_ID |
mov word [es:di], ax |
add di, 2 |
;DIR_CrtTimeTenth |
mov byte [es:di], 100 |
inc di |
;DIR_CrtTime |
mov word [es:di], 0x032b ;äàòà |
add di, 2 |
;DIR_CrtDate |
mov word [es:di], 0x0 ;âðåìÿ >< |
add di, 2 |
;DIR_LstAccDate |
mov word [es:di], 0x032b ;äàòà ìîåãî |
add di, 2 |
;DIR_FstClusHI |
mov word [es:di], 0x0 ;âðåìÿ äëÿ ôàò12 /16 âñåãäà 0 |
add di, 2 |
;DIR_WrtTime |
mov word [es:di], 0x0 ;âðåìÿ >< |
add di, 2 |
;DIR_WrtDate |
mov word [es:di], 0x032b |
add di, 2 |
mov ax, point_next_fat_str |
mov word [es:di], ax |
add di, 2 |
push di |
;DIR_FstClusLO Ìëàäøåå ñëîâî íîìåðà ïåðâîãî êëàñòåðà. |
; mov ax,point_next_fat_str ;çàãðóçèì óêàçàòåëü íà ýëåìåíò ôàò òàáëèöû ò.å. ýòî íîìåð ôàò çàïèñè |
;FATOffset = N + (N / 2) ò.å. ýòî óæå ó íàñ ñìåùåíèå ìû çíàåì ÷òî -íà÷èíàåòñÿ âñå ñ 3-ãî ýëåìåíòà çàïèñè ôàò |
mov bx, ax |
shr bx, 1 |
add ax, bx |
;â àõ ñåé÷àñ FATOffset |
;ThisFATEntOffset = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec); |
mov bx, word [fat12_buffer.BPB_BytsPerSec] |
cwd |
idiv bx |
;ax=ThisFATEntOffset= rem (FATOffset / BPB_BytsPerSec) ÷åòíûé èëè íå÷åòíûé óêàçàòåëü. |
mov si, ax |
;íàì íóæíî â öèêëå çàïèñàòü âñå êëàñòåðû êîòîðûå áóäóò èñïîëüçîâàíû äëÿ ðàçìåùåíèÿ ôàéëà. |
;óçíàåì ðàçìåð êëàñòåðà. |
movzx eax, word [fat12_buffer.BPB_BytsPerSec] |
movzx ebx, byte [fat12_buffer.BPB_SecPerClus] |
imul eax, ebx |
;ax - ðàçìåð êëàñòåðà. |
;ñåé÷àñ áóäåì çàïèñûâàòü âî âðåìåííûé áóôåð ôàò òàáëèöó äëÿ âûáðàííîãî ôàéëà. Ïîñêîëüêó ìû åãî çàãðóçèëè âîçìîæíî íå ïîëíîñòüþ |
;ìû îáðàáîòàåì çàïèñü äëÿ ôàò ïîëíîñòüþ, â íå çàâèñèìîñòè îò ïðåäåëà áóôåðà ãäå âîçìîæíà ÷àñòü ôàéëà. |
mov ebx, save_file_size ;ðàçìåð ôàéëà â áàéòàõ |
@@: |
sub ebx, eax |
cmp ebx, eax |
jbe .eof_file |
inc point_next_fat_str |
mov cx, point_next_fat_str ;çàãðóçèì óêàçàòåëü íà ýëåìåíò ôàò òàáëèöû ò.å. ýòî íîìåð ôàò çàïèñè |
;FATOffset = N + (N / 2) ò.å. ýòî óæå ó íàñ ñìåùåíèå ìû çíàåì ÷òî -íà÷èíàåòñÿ âñå ñ 3-ãî ýëåìåíòà çàïèñè ôàò |
mov dx, ax |
shr dx, 1 |
add cx, dx |
test si, 0x1 |
jz .step2 |
shl cx, 4 |
mov word[es:si], cx |
inc si |
add cx, ax |
jmp @b |
.step2: |
and cx, 0x0FFF |
mov word[es:si], cx |
inc si |
add cx, ax |
jmp @b |
.eof_file: |
mov cx, 0x0fff |
test si, 0x1 |
jz .step3 |
shl cx, 4 |
mov word[es:si], cx |
jmp .end |
.step3: |
and cx, 0x0FFF |
mov word[es:si], cx |
.end: |
inc point_next_fat_str |
pop di |
;DIR_FileSize 32-áèòíûé DWORD ñîäåðæèò ðàçìåð ôàéëà â áàéòàõ. |
mov eax, save_file_size |
mov dword [es:di], eax |
if DEBUG |
pushad |
mov di, firstDataSect ;â ñåêòîðàõ |
sub di, size_root_dir |
;òåïåðü â ax ðàçìåð â ñåêòîðàõ íà÷àëà ðóò äèð |
shl di, 9;imul 512 |
add di, point_to_free_root ;ñìåùåíèå â óæå çàïèñàííûõ 32-õ ñòðóêòóðàõ. |
push di |
mov si, dest_name_fat |
mov cx, 11 |
;çàïèøåì â ñòðóêòóðó èìÿ |
@@: |
mov al, byte [es:di] |
inc di |
mov byte [ds:si], al |
inc si |
loop @b |
mov di, si |
inc di |
pop ax |
mov cx, 0xa |
call decode |
mov si, dest_name_fat |
call printplain |
popad |
END IF |
add point_to_free_root, 32 ;óâåëèöèì ñìåùåíèå äî ñëåäóþùåãî çíà÷åíèÿ. |
pop es |
} |
macro get_firstDataSector |
;ìàêðîñ äëÿ âû÷èñëåíèÿ ïåâîãî ñåêòîðà äàííûõ ò.å. äàííûõ ôàéëîâ â ôàòå |
;âû÷èñëèì FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors; |
{ |
mov ax, word [fat12_buffer.BPB_FATSz16] |
movzx bx, byte [fat12_buffer.BPB_NumFATs] |
imul ax, bx ;9x1=9 |
;ax=BPB_NumFATs * FATSz |
mov bx, word [fat12_buffer.BPB_RootEntCnt] ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) |
shr bx, 4 ;imul bx,32 and then div 512 -> in bx size in sectors |
add ax, bx ;9+14=23 |
mov size_root_dir, bx |
movzx bx, byte [fat12_buffer.BPB_RsvdSecCnt] ;add 1 for fat 16/12 |
add ax, bx |
;ax=firstDataSector - ãäå íà÷èíàåòñÿ ïåðâûé ñåêòîðî îò 0 ñåêòîðà â ñåêòîðàõ. - ôàêòè÷åñêè = 24 ñåêòîð |
mov firstDataSect, ax ;ñîõðàíèì äëÿ âû÷èñëåíèÿ |
; ïîëó÷èìçíà÷åíèå êëàñòåðîâ, ýòî îáúåì â êîòîðûé ìû ìîæåì çàïèñàòü äàííûå |
mov bx, word [fat12_buffer.BPB_TotSec16] |
sub bx, ax |
mov ax, bx |
movzx bx, byte [fat12_buffer.BPB_SecPerClus] |
cwd |
idiv bx |
mov DataClasters, ax |
if DEBUG |
pushad |
mov ax, firstDataSect ;ïåðâûé ñåêòîð äàííûõ |
mov cx, 0x0a |
mov di, firstDataSect_msg |
call decode |
;Show size |
mov si, firstDataSect_msg |
call printplain |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov ax, size_root_dir ;ðàçìåð ðóò äèð â ñåòîêòîðàõ |
mov cx, 0x0a |
mov di, size_root_dir_msg |
call decode |
;Show size |
mov si, size_root_dir_msg |
call printplain |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
mov ax, DataClasters;êëàñòåðû |
mov cx, 0x0a |
mov di, DataClasters_msg |
call decode |
;Show size |
mov si, DataClasters_msg |
call printplain |
popad |
end if |
} |
macro use_RamdiskPATHS |
;ïàðñèíã ïóòè èñòî÷íèêà ôàéëîâ. |
{ |
} |
macro use_RamdiskPATHD |
;ïàðñèíã ïóòè íàçíà÷åíèÿ ôàéëîâ. |
{ |
} |
macro check_name_file |
;ìàêðîñ ïðîâåðêè èìåíè íà ïîâòîð, èìÿ äîëæíî áûòü óíèêàëüíûì. |
;âõîäíûå äàííûå: es- ñåãìåíò ãäå ëåæèò ôàéë äëÿ ïàðñèíãà ò.å. startos.ini |
;di - óêàçàòåëü íà èìÿ ôàéëà ò.å. es:di óêàçûâàåò íà èìÿ ôàéëà íàçíà÷åíèÿ |
;âûõîäíûå äàííûå eax =-1 èìÿ ñîâïàëî, eax=0 èìÿ íå ñîâïàëî. |
{ |
local .no_equal |
local .exit |
local .loop_size_root_dir |
;âû÷èñëèì äëèííó ñòðî÷êè èìåíè íàçíà÷åíèÿ, êîòîðóþ áóäåì ñðàâíèâàòü ñ óæå çàïèñàííûìè äàííûìè. |
;ïðåîáðàçóåì â àíàëîã ôàò çàïèñè ñòî÷êó ñ èìåíåì íàçíà÷åíèÿ |
convertion_file_name ; ïðåîáðàçîâàëè èìÿ ïî íóæíûì ïðàâèëàì |
test ax, ax |
jnz .exit |
lea si, [shot_name_fat] ; desination name of file |
;âû÷èñëèì óêàçàòåëü íà êîðíåâóþ äèðåêòîðèþ |
mov di, firstDataSect |
sub di, size_root_dir |
;òåïåðü â ax ðàçìåð â ñåêòîðàõ íà÷àëà ðóò äèð |
shl di, 9;imul 512 |
;di= Ýòî ñìåùåíèå îò íà÷àëà áóôåðà äî ðóò äèðåêòîðèè. â ïðåäåëàõ 64 êá. |
;çàãðóçèì çíà÷åíèå - ò.å. êîë-âî ýëåìåíòîâ, êîòîðûå ìû ìîæåì ïðîñìàòðèâàòü. |
mov dx, root_dir_entry_count |
mov ax, info_real_mode_size |
add ax, 0x1000 |
mov gs, ax |
.loop_size_root_dir: |
DEBUG1 equ 0 |
if DEBUG1 |
pushad |
push di |
mov eax, dword[gs:di] |
lea si, [check_root_fat_+14] |
mov dword [ds:si], '----' |
mov dword [ds:si+4], '----' |
mov dword [ds:si+8], '----' |
mov dword[ds:si], eax |
mov eax, dword[gs:di+4] |
mov dword[ds:si+4], eax |
mov eax, dword[gs:di+8] |
mov dword[ds:si+8], eax |
; |
xor eax, eax |
mov ax, gs;point_next_fat_str |
mov cx, 0x0a |
mov di, check_root_fat_ |
mov dword [di], ' ' |
mov word [di+4], ' ' |
call decode |
xor eax, eax |
pop ax |
mov di, (check_root_fat_+7) |
mov dword [di], ' ' |
mov word [di+4], ' ' |
call decode |
;Show size |
lea si, [check_root_fat_] |
call printplain |
lea si, [shot_name_fat] |
call printplain |
xor ax, ax |
int 0x16 |
popad |
end if |
xor bx, bx |
mov cx, 11 ;size of name in struct FAT |
@@: |
mov al, byte [ds:si+bx] ;ds:si - point to name of convertion variable. |
mov ah, byte [gs:di+bx] ;gs:di - point to name in fat struct |
inc bx |
if DEBUG |
; pushad |
; lea si,[check_root_fat_+14] |
; mov dword [ds:si],'----' |
; mov word [ds:si],ax |
; call printplain |
; xor ax,ax |
; int 0x16 |
; popad |
end if |
cmp ah, al |
jnz .no_equal |
; dec cx |
; jnz @b |
loop @b |
;.succesfuly: |
;ïå÷àëüíî, òàêîå èìÿ óæå èìååòñÿ :( |
or ax, -1 |
jmp .exit |
.no_equal: |
add di, 32 ;fat struct =32 byte |
dec dx |
jnz .loop_size_root_dir |
;.exit_check_name: |
and ax, 0 |
.exit: |
if DEBUG |
pushad |
;Show size |
lea si, [check_name_fat_msg_n] |
test ax, ax |
jz @f |
lea si, [check_name_fat_msg_y] |
call printplain |
lea si, [alarm_msg] |
@@: |
call printplain |
popad |
end if |
} |
macro convertion_file_name |
;ìàêðîñ êîíâåðòàöèè èìåíè, ýòî íóæíî ïîñêîëüêó ôîðìàò ïðåäñòàâëåííûé íå ñîîòâåòñâóåò ôàò è íàïðÿìóþ ðåäêî ìîæíî êîãäà èñïîëüçîâàòü |
;ïðåîáðàçîâàíèå èìåíè òèïà hello.asm â 'HELLO ASM', â ñîîòâåòñòâèè ñ ïðàâèëàìè fat. |
;âõîäíûå ïàðàìåòðû es:di óêàçàòåëü íà èìÿ ôàéëà êîòîðîå íóæíî ïðåîáðàçîâàòü, êîíå÷íûé áóôåð shot_name_fat |
{ |
local .next_step |
local .error |
local .st1 |
local .st2 |
local .st2_l |
local .st3 |
local .st4_s |
local .st4 |
local .st5 |
;âû÷èñëèì äëèííó ñòðî÷êè èìåíè íàçíà÷åíèÿ, êîòîðóþ áóäåì ñðàâíèâàòü ñ óæå çàïèñàííûìè äàííûìè. |
; mov di,point_to_dest_file_name âõîäíîé ïàðàìåòð |
mov si, shot_name_fat |
or first_input, -1 ;ïðè ïåðâîì âõîäå óñòàíàâëèâàåì ôëàã |
mov cx, 11 ;äëèííà èìåíè â ñòóêòóðå ôàò òàáëèöû |
@@: |
mov al, byte [es:di] |
cmp al, 0xa |
jz .st4_s |
cmp al, 0xd |
jz .st4_s |
cmp al, 0x20 |
jz .st4_s |
cmp al, 0x20 |
jb .error |
cmp al, 0x22 |
jz .error |
cmp al, 0x2a |
jz .error |
cmp al, 0x2b |
jz .error |
cmp al, 0x2c |
jz .error |
cmp al, 0x2F |
jz .error |
cmp al, 0x3a |
jz .error |
cmp al, 0x3b |
jz .error |
cmp al, 0x3c |
jz .error |
cmp al, 0x3d |
jz .error |
cmp al, 0x3E |
jz .error |
cmp al, 0x3F |
jz .error |
cmp al, 0x5b |
jz .error |
cmp al, 0x5c |
jz .error |
cmp al, 0x5d |
jz .error |
cmp al, 0x7c |
jz .error |
cmp first_input, -1 |
jnz .next_step |
and first_input, 0 ;ñáîðîñèì ôëàã. |
cmp al, '.' |
jz .error ;îáðàáîòêà òî÷êè, ôàéë íå ìîæåò íà÷èíàòüñÿ ñ òî÷êè |
.next_step: |
cmp al, 0x2e |
jnz .st2 ;îáðàáîòêà òî÷êè, â ñåðåäèíå ôàéëà |
;òóò ó íàñ óñòàíîâëåí ðàçäåëèòåëü |
;âñå îñòàëüíåî ìåñòî çàéìóò ïðîáåëû |
mov al, ' ' |
;!fixme îáðàáîòàíû íå âñå èñêëþ÷åíèÿ :( |
cmp cl, 3 ;ôîðìàò ôàéëà òàêîé GIDGIDIIASM ò.å. gidgidii.asm |
jbe .st2 |
.st3: |
mov byte [si], al |
inc si |
dec cx |
cmp cx, 3 |
ja .st3 |
; inc cx |
inc di |
jmp @b |
.st2: |
cmp al, 0x60 |
jbe .st2_l |
xor al, 0x20;ñäåëàåì çàãëàâíûå áóêâû |
.st2_l: |
mov byte [si], al |
inc di |
inc si |
; dec cx |
; jnz @b |
loop @b |
.st5: |
xor ax, ax |
jmp @f |
;;;;;;;;ôàéë çàêîí÷èëñÿ, è íóæíî âíåñòè â êîíåö ïðîáåëû |
.st4_s: |
mov al, ' ' |
.st4: |
mov byte [si], al |
inc si |
loop .st4 |
jmp .st5 |
.error: |
or ax, -1 |
@@: |
if DEBUG |
pushad |
mov si, convertion_file_name_msg_y |
test ax, ax |
jz @f |
mov si, convertion_file_name_msg_n |
@@: |
call printplain |
mov si, shot_name_fat |
mov byte [si+12], 0 |
call printplain |
popad |
end if |
} |
macro move_file_up |
;ìàêðîñ êîòîðûé ïåðåìåùàåò çà 1 ìá ñ ïðàâèëàìè ôàò äàííûå ôàéëà. |
{ |
local .st1 |
local .correct_on_byte |
;ñåé÷àñ èìååò áûòü ñèòóàöèÿ, êîãäà BPB óæå ïåðåìåùåí çà 1 ìá, ôàò, è ðóò äèð áóäóò ïîçæå ïåðåìåùåíû, |
;à íàì íóæíî âû÷èñëèòü ìåñòî, è ïåðåíåñòè òóäà ñîäåðæèìîå ôàéëà |
;ïîëó÷åíîå çíà÷åíèå óêàçûâàåò â áàéòàõ íà íà÷àëî äàííûõ |
mov ax, info_real_mode_size ; ñåãìåíò ãäå ðàñïîëîæåíû äàííûå |
mov si, table_15_87 |
mov word [si+8*2+2], ax |
;ñìåùåíèå äî äàííûõ óæå çà 1-ì ìá |
movzx eax, firstDataSect |
movzx edx, data_offset |
add eax, edx |
movzx ebx, word [fat12_buffer.BPB_BytsPerSec] |
movzx edx, byte [fat12_buffer.BPB_SecPerClus] |
imul bx, dx ;ïîëó÷èì ðàçìåð êëàñòåðà |
push ebx ;save bx |
imul eax, ebx |
; shl eax,9 ;óìíîæèì íà 512 |
if DEBUG |
pushad |
xor eax, eax |
mov ax, info_real_mode_size |
mov cx, 0x0a |
mov di, seg_where_get_data |
mov dword [di], ' ' |
mov word [di+4], ' ' |
call decode |
;Show size |
mov si, seg_where_get_data |
call printplain |
popad |
end if |
; mov bx,word [fat12_buffer.BPB_BytsPerSec] |
; movzx dx,byte [fat12_buffer.BPB_SecPerClus] |
; imul bx,dx |
; cwd |
; idiv bx |
mov dl, 0x10 |
@@: |
cmp eax, 0x00010000 |
jb @f |
sub eax, 0x00010000 |
inc dl |
jmp @b |
@@: |
mov byte [si+8*3+3], dl ;êóäà ïèñàòü |
mov word [si+8*3+2], ax |
mov ecx, save_file_size ;ðàçìåð ôàéëà â áàéòàõ. |
cmp ecx, 0x0000ffff ;ðàçìåð áëîêà ò.å. 64 êá |
jbe .correct_on_byte ;êîððåêòèðîâêà íà áàéò çíà÷åíèÿ |
mov ecx, 0x00010000 ;65536 |
sub save_file_size, ecx ;îòíèìèì |
; jmp .st1 ;ïîëó÷èì 0õ8000 |
;êîððåêòèðîâêà çíà÷åíèÿ äîëæíà áûòü âûïîëåíåíà íà ðàçìåð êëàñòåðà |
.correct_on_byte: |
;/óçíàåì ðàçìåð êëàñòåðà |
pop eax ;restore size of claster |
push ecx |
@@: |
inc data_offset |
cmp eax, ecx |
jae @f |
sub ecx, eax |
jmp @b |
@@: |
pop ecx |
test ecx, 0x1 |
jz .st1 |
inc ecx |
.st1: |
shr ecx, 1 ; ïðåîáðàçîâàòü çíà÷åíèå äëÿ 0x87 function |
;ïåðåíåñåì áëîê çà 1 ìá |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
if DEBUG |
pusha |
; mov ax,point_next_fat_str |
mov cx, 0x0a |
mov di, return_code_af_move |
call decode |
;Show size |
mov si, return_code_af_move |
call printplain |
popa |
end if |
} |
macro move_up_fat_and_root_d |
;ìàêðîñ, êîòîðûé ïîçâîëÿåò ïåðåíåñòè âûøå 1 ìá â ñòðóêòóðó îáðàçà ôàò òàáëèöó è ðóò äèðåêòîðèþ |
{ |
local .st1 |
mov ax, info_real_mode_size |
add ax, 0x1000 |
mov si, table_15_87 |
mov word [si+8*2+2], ax |
;ñìåùåíèå äî äàííûõ |
mov ax, 512 |
mov word [si+8*3+2], ax |
;fixme! òóò íåîáõîäèìî ñäåëàòü ïîäåðæêó ò.å. ôîðìèðîâàòü ñìåùåíèå ôàéëà â óæå çàïèñàííûõ äàííûõ. |
movzx ecx, word [fat12_buffer.BPB_FATSz16] |
movzx bx, byte [fat12_buffer.BPB_NumFATs] |
imul cx, bx ;9x1=9 |
add cx, size_root_dir ;ðàçìåð êîðíåâîé äèððåêòîðèè |
shl ecx, 9 ;imul 512 |
;êîððåêòèðîâêà çíà÷åíèÿ |
test ecx, 0x1 |
jz .st1 |
inc ecx |
.st1: |
shr ecx, 1 |
push es |
push ds |
pop es |
mov ah, 0x87 |
int 0x15 |
pop es |
if DEBUG |
pusha |
; mov ax,point_next_fat_str |
mov cx, 0x0a |
mov di, return_code_af_fat_m |
call decode |
;Show size |
mov si, return_code_af_fat_m |
call printplain |
popa |
end if |
} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/parse_err.inc |
---|
1,66 → 1,66 |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
error: |
.rest_value: |
mov di,ax ;restore value after repe cmpsb |
mov cx,bx |
jmp ret_on_ch ;return |
;///// îøèáêà ïðè íàõîäæåíèè äëèííû ñåêöèè â ïàðàìåòðå default |
.error_get_size_d_sect: |
leave ;clear array in stack |
mov si,not_found_def_sect |
jmp err_show_ini |
;/////ERROR |
.not_loader: |
leave ;clear array in stack |
mov si,not_found_sec_loader |
jmp err_show_ini |
.default_eq_loader: ;êðèòè÷åñêàÿ îøèáêà default ñåêöèÿ = loader |
leave |
mov si,default_eq_loader |
jmp err_show_ini |
.correct_exit_bl: |
leave |
mov si,point_to_default_sec_not_found |
jmp err_show_ini |
.incorect_section_def: |
leave |
mov si,incorect_section_define |
jmp err_show_ini |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;show message error |
.LoaderModule: |
push word 0xb800 |
pop es |
ret |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
error: |
.rest_value: |
mov di, ax;restore value after repe cmpsb |
mov cx, bx |
jmp ret_on_ch ;return |
;///// îøèáêà ïðè íàõîäæåíèè äëèííû ñåêöèè â ïàðàìåòðå default |
.error_get_size_d_sect: |
leave ;clear array in stack |
mov si, not_found_def_sect |
jmp err_show_ini |
;/////ERROR |
.not_loader: |
leave ;clear array in stack |
mov si, not_found_sec_loader |
jmp err_show_ini |
.default_eq_loader: ;êðèòè÷åñêàÿ îøèáêà default ñåêöèÿ = loader |
leave |
mov si, default_eq_loader |
jmp err_show_ini |
.correct_exit_bl: |
leave |
mov si, point_to_default_sec_not_found |
jmp err_show_ini |
.incorect_section_def: |
leave |
mov si, incorect_section_define |
jmp err_show_ini |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;show message error |
.LoaderModule: |
push word 0xb800 |
pop es |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/parse_loader.inc |
---|
1,332 → 1,335 |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;áëîê ìàêðîñîâ ïî îáðàáîòêå ñåêöèè [loader] |
;âõîäíûå äàííûå: |
;es:di - óêàçàòåëü íà ñåêöèþ íà÷èíàþùèþñÿ ñ '[' âñòå÷àþùèþñÿ ïîñëå 0õa |
;cx - ñ÷åò÷èê êîë-âî áàéò äëÿ ïðîâåðêå â êàäðå |
; |
macro use_parse_loader |
{ |
.parse_loader: |
;////////////////// |
;/ parse [loader] |
;////////////////// |
mov bx,cx ;cîõðàíèì â ðåãèñòðû çíà÷åíèÿ ñ÷åò÷èêà è óêàçàòåëÿ |
mov ax,di |
; mov word [bp-4],.start ;is alredy set, see up |
mov si,parse_loader |
mov cx,parse_loader_e - parse_loader |
repe cmpsb |
jnz error.rest_value ;öåïî÷êà íå ñîâïàëà :( ïåðåéäåì äàëåå ò.å. áóäåì ñíîâà èñêàòü)) |
;ñîõðàíèì óêàçàòåëüíà loader, ÷òî áû ïîòîì áîëüøå åãî íå èñêàòü |
mov point_loader,ax |
sub bx,parse_loader_e - parse_loader ;correct cx |
add bx,cx |
mov cx,bx |
if DEBUG |
pusha |
mov si,lm_l_found |
call printplain |
popa |
end if |
;/////////////////end check [loader]. [loader] is found |
;parsing section [loader] |
;first found end section,let's found '[' -it's start next section |
;in previosly steep bx =cx we are not need save cx, save only di - point |
mov dx,di |
@@: |
call get_firs_sym |
jcxz .loader_f_end ;.end_loader ; end äàæå åñëè ìû íå íàøëè ñåêöèþ ïðåäïîëîæèì ÷òî ñåêöèÿ [loader] ñòîèò â êîíöå |
cmp al,'[' |
jnz @b |
.loader_f_end: |
sub bx,cx ;bx = n byte presend in section [loader] |
mov di,dx ;restore di |
;////////////////parse parametrs in section [loader] |
;//timeout=5 |
;//default=main |
; mov di,dx ;set pointer on section [loader] i think it's not need |
mov cx,bx ;set counter for parsing section [loader] cx= êîë-âó ñèìâîëîâ â ñåêöèè [loader] |
mov ret_on_ch,.get_next_str ; return point |
;;;;;;; parse timeout & default |
.get_next_str: |
call get_firs_sym ;get first symbol on new line |
test cx,cx |
jz .end_loader |
; jcxz .end_loader ;çàâåðøåíèå ïàðñèíãà çíà÷åíèé timeout & default |
cmp al,'t' |
jz .loader_timeout |
cmp al,'d' |
jnz .get_next_str |
;//////[loader].default |
;input di point to data cx=size [loader] |
mov bx,cx |
mov ax,di |
mov si,parse_l_default |
mov cx,parse_l_default_e - parse_l_default |
repe cmpsb |
jnz error.rest_value ;is not compare öåïî÷êà íå ñîâïàëà |
sub bx,parse_l_default_e - parse_l_default ;correct cx |
add bx,cx |
mov cx,bx |
test status_flag,flag_found_default |
jz .correct_is_not_set |
mov si,found_equal_default ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
call printplain |
jmp .get_next_str |
.correct_is_not_set: |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
test cx,cx |
jz .end_loader |
cmp ah,byte [es:di-1] ;find '=' |
jnz .get_next_str |
repe scasb ;cut ' ' |
inc cx |
dec di |
;ñåé÷àñ es:di óêàçûâàþò íà íàçâàíèå ñåêöèè, èìÿ ñåêöèè ïî äåôîëòó íå äîëæíî áûòü loader ò.å. èíà÷å âîçìîæíî çàöèêëèâàíèå |
;óñòàíîâèì óêàçàòåëü si íà ýòî çíà÷åíèå è ñíà÷àëà ïðîâåðèì |
;ïîëó÷åíèå äëèííû ñåêöèè |
; cx=bx ñîäåðæèò äëèííó îñòàòêà ñåêöèè |
; di=ax óêàçàòåëü íà òåêóùèþ ñåêöèþ |
mov bx,cx |
mov dx,di |
@@: mov al,byte [es:di] |
inc di |
dec cx |
test cx,cx |
jz error.error_get_size_d_sect ;ïåðåõîä íà îáðàáîòêó îøèáêè ïî íàõîæäåíèþ äëèíû äåôîëòíîé ñåêöèè |
cmp al,' ' |
jz @b |
cmp al,0xd |
jz .found_size_d_sect |
cmp al,0xa |
jnz @b |
.found_size_d_sect: |
; |
inc cx ;correct cx |
mov ax,bx |
sub bx,cx ; â bx äëèíà ñåêöèè êîòîðàÿ îïðåäåëåíà ïî äåôîëòó |
mov save_cx_d,bx |
mov di,dx |
mov cx,bx ;set size default section |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ïðîâåðêà íà =loader |
;save in reg point and ñ÷åò÷èê |
;check on loader |
mov bx,ax |
mov ax,dx |
mov si,parse_loader |
inc si ;set only loader and 6 char in counter |
repe cmpsb |
jnz .check_section ;öåïî÷êà íå ñîâïàëà :( ïåðåéäåì äàëåå )) çíà÷èò íå èñêëþ÷åíèå |
jmp error.default_eq_loader ;error êðèòè÷åñêàÿ îøèáêà ò.å. â äåôîëòå ïðèñóòñòâóåò èìÿ [loader] |
.check_section: ;ïîèñê ñîîòâåòñòâóþùåé ñåêöèè íàì íóæíî áóäåò óçíàòü àäðåñ ýòîé ñåêöèè |
mov cx,bx |
mov di,ax |
;///////////////////////////// |
; mov ret_on_ch,.start_d ;set return |
mov si,di ;óñòàíîâèì óêàçàòåëü íà íàøó ñåêöèþ, êîòîðàÿ ïî äåôîëòó |
push di ;save point di |
push cx ;save cx |
;óñòàíîâèì óêàçàòåëü es:di íà íà÷àëî ini ôàéëà |
mov cx,save_cx ;it's placed size of ini file |
les di,dword [file_data] |
mov al,byte [es:di] |
push word .first_ret_d |
cmp al,' ' |
jz .first_sp_1_d |
jmp get_firs_sym.not_space |
.first_sp_1_d: |
jmp get_firs_sym.first_sp |
.start_d: |
call get_firs_sym ;get first symbol on new line |
.first_ret_d: ;ïåðâûé âîçâðàò |
jcxz .correct_exit ;.end_loader ;found or not found parametrs in section exit in section |
cmp al,'[' |
jz .found_sect_d |
jmp .start_d |
;ïðîñìàòðèâàåì ini ôàéë ñ íà÷àëà â ïîèñêàõ ñåêöèè óêàçàíîé êàê default |
;èäåò ïðîâåðêà íà íàëè÷åå çíà÷åíèÿ timeout, äëÿ áîëåå áûñòðîé ðàáîòû, ýòîò ïàðàìåòð äîëæåí áûòü óæå îáðàáîòàí,ò.å. â ýòîì ñëó÷àå ïðè åãî =0 áóäåò ñôîðìèðîâàí óêàçàòåëü òîëüêî íà äåôîëòíóþ ñåêöèþ, èíà÷å èíôîðìàöèÿ áóäåò ñîáðàíà ïî âñåì ñåêöèÿì è ñîñòàâëåíû óêàçàòåëè â áëîêå ïàìÿòè |
.found_sect_d: |
;check on name section |
mov bx,cx |
mov ax,di |
push si ;save point |
; mov si,parse_loader |
mov cx,save_cx_d ;load size section |
push es |
pop ds |
inc di |
repe cmpsb |
push cs |
pop ds |
pop si |
jnz .not_compare_d_s ;öåïî÷êà íå ñîâïàëà :( ïåðåéäåì äàëåå )) çíà÷èò íå èñêëþ÷åíèå |
cmp byte[es:di],']' |
jnz .not_compare_d_s ;íåò â êîíöå íàøåé ñåêöèè çàâåðøàþùåãî ñèìâîëà :( |
;set flag -we have found default -not enter again in this prosedure |
or status_flag,flag_found_default |
pop cx |
pop di |
mov point_default,ax ;point to [ |
if DEBUG |
pusha |
mov si,lm_lf_default_f |
call printplain |
popa |
end if |
jmp .get_next_str |
.not_compare_d_s: |
mov cx,bx |
mov di,ax |
jmp .start_d |
.correct_exit: |
pop cx ;âîññòàíîâèì çíà÷åíèå ñ÷åò÷èêà |
pop di |
if DEBUG |
pusha |
mov si,lm_lf_default |
call printplain |
popa |
end if |
jmp .get_next_str |
;//////////[loader].timeout |
.loader_timeout: |
mov bx,cx |
mov ax,di |
mov si,parse_l_timeout |
mov cx,parse_l_timeout_e - parse_l_timeout |
repe cmpsb |
jnz error.rest_value ;is not compare |
sub bx,parse_l_timeout_e - parse_l_timeout ;correct cx |
add bx,cx |
mov cx,bx |
test status_flag,flag_found_timeout |
jz .correct_is_not_set_t |
mov si,found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
call printplain |
jmp .get_next_str |
.correct_is_not_set_t: |
mov ax,0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .timeout_sec_end_d ;not found param timeout |
cmp ah,byte [es:di-1] ;find '=' |
jnz .get_next_str |
repe scasb ;cut ' ' |
inc cx |
dec di |
;get timeout value |
;2 çíàêa ìîæåò áûòü îáðàáîòàíî ò.å. çíà÷åíèå îò 0 äî 99 ñåêóíä |
push cx |
xor bx,bx |
mov cx,2 |
@@: mov al,byte [es:di] |
cmp al,'0' |
jb .end_get_val_t |
cmp al,'9' |
ja .end_get_val_t |
imul bx,10 |
xor al,0x30 |
add bl,al |
.end_get_val_t: |
inc di |
loop @b |
mov word [value_timeout],bx |
; pop cx |
if DEBUG |
pusha |
mov si,lm_lf_timeout |
call printplain |
popa |
end if |
jmp @f |
.timeout_sec_end_d: |
mov word [value_timeout],default_timeout_value |
mov si,set_default_timeout_val |
call printplain |
@@: pop cx |
jmp .get_next_str |
;///////here end block loader |
.end_loader: |
if DEBUG |
pusha |
mov si,lm_l_end |
call printplain |
popa |
end if |
} |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
;áëîê ìàêðîñîâ ïî îáðàáîòêå ñåêöèè [loader] |
;âõîäíûå äàííûå: |
;es:di - óêàçàòåëü íà ñåêöèþ íà÷èíàþùèþñÿ ñ '[' âñòå÷àþùèþñÿ ïîñëå 0õa |
;cx - ñ÷åò÷èê êîë-âî áàéò äëÿ ïðîâåðêå â êàäðå |
; |
macro use_parse_loader |
{ |
.parse_loader: |
;////////////////// |
;/ parse [loader] |
;////////////////// |
mov bx, cx ;cîõðàíèì â ðåãèñòðû çíà÷åíèÿ ñ÷åò÷èêà è óêàçàòåëÿ |
mov ax, di |
; mov word [bp-4],.start ;is alredy set, see up |
mov si, parse_loader |
mov cx, parse_loader_e - parse_loader |
repe cmpsb |
jnz error.rest_value ;öåïî÷êà íå ñîâïàëà :( ïåðåéäåì äàëåå ò.å. áóäåì ñíîâà èñêàòü)) |
;ñîõðàíèì óêàçàòåëüíà loader, ÷òî áû ïîòîì áîëüøå åãî íå èñêàòü |
mov point_loader, ax |
sub bx, parse_loader_e - parse_loader;correct cx |
add bx, cx |
mov cx, bx |
if DEBUG |
pusha |
mov si, lm_l_found |
call printplain |
popa |
end if |
;/////////////////end check [loader]. [loader] is found |
;parsing section [loader] |
;first found end section,let's found '[' -it's start next section |
;in previosly steep bx =cx we are not need save cx, save only di - point |
mov dx, di |
@@: |
call get_firs_sym |
jcxz .loader_f_end ;.end_loader ; end äàæå åñëè ìû íå íàøëè ñåêöèþ ïðåäïîëîæèì ÷òî ñåêöèÿ [loader] ñòîèò â êîíöå |
cmp al, '[' |
jnz @b |
.loader_f_end: |
sub bx, cx ;bx = n byte presend in section [loader] |
mov di, dx ;restore di |
;////////////////parse parametrs in section [loader] |
;//timeout=5 |
;//default=main |
; mov di,dx ;set pointer on section [loader] i think it's not need |
mov cx, bx ;set counter for parsing section [loader] cx= êîë-âó ñèìâîëîâ â ñåêöèè [loader] |
mov ret_on_ch, .get_next_str; return point |
;;;;;;; parse timeout & default |
.get_next_str: |
call get_firs_sym ;get first symbol on new line |
test cx, cx |
jz .end_loader |
; jcxz .end_loader ;çàâåðøåíèå ïàðñèíãà çíà÷åíèé timeout & default |
cmp al, 't' |
jz .loader_timeout |
cmp al, 'd' |
jnz .get_next_str |
;//////[loader].default |
;input di point to data cx=size [loader] |
mov bx, cx |
mov ax, di |
mov si, parse_l_default |
mov cx, parse_l_default_e - parse_l_default |
repe cmpsb |
jnz error.rest_value ;is not compare öåïî÷êà íå ñîâïàëà |
sub bx, parse_l_default_e - parse_l_default;correct cx |
add bx, cx |
mov cx, bx |
test status_flag, flag_found_default |
jz .correct_is_not_set |
mov si, found_equal_default ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
call printplain |
jmp .get_next_str |
.correct_is_not_set: |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
test cx, cx |
jz .end_loader |
cmp ah, byte [es:di-1] ;find '=' |
jnz .get_next_str |
repe scasb ;cut ' ' |
inc cx |
dec di |
;ñåé÷àñ es:di óêàçûâàþò íà íàçâàíèå ñåêöèè, èìÿ ñåêöèè ïî äåôîëòó íå äîëæíî áûòü loader ò.å. èíà÷å âîçìîæíî çàöèêëèâàíèå |
;óñòàíîâèì óêàçàòåëü si íà ýòî çíà÷åíèå è ñíà÷àëà ïðîâåðèì |
;ïîëó÷åíèå äëèííû ñåêöèè |
; cx=bx ñîäåðæèò äëèííó îñòàòêà ñåêöèè |
; di=ax óêàçàòåëü íà òåêóùèþ ñåêöèþ |
mov bx, cx |
mov dx, di |
@@: |
mov al, byte [es:di] |
inc di |
dec cx |
test cx, cx |
jz error.error_get_size_d_sect ;ïåðåõîä íà îáðàáîòêó îøèáêè ïî íàõîæäåíèþ äëèíû äåôîëòíîé ñåêöèè |
cmp al, ' ' |
jz @b |
cmp al, 0xd |
jz .found_size_d_sect |
cmp al, 0xa |
jnz @b |
.found_size_d_sect: |
; |
inc cx ;correct cx |
mov ax, bx |
sub bx, cx ; â bx äëèíà ñåêöèè êîòîðàÿ îïðåäåëåíà ïî äåôîëòó |
mov save_cx_d, bx |
mov di, dx |
mov cx, bx ;set size default section |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ïðîâåðêà íà =loader |
;save in reg point and ñ÷åò÷èê |
;check on loader |
mov bx, ax |
mov ax, dx |
mov si, parse_loader |
inc si ;set only loader and 6 char in counter |
repe cmpsb |
jnz .check_section ;öåïî÷êà íå ñîâïàëà :( ïåðåéäåì äàëåå )) çíà÷èò íå èñêëþ÷åíèå |
jmp error.default_eq_loader ;error êðèòè÷åñêàÿ îøèáêà ò.å. â äåôîëòå ïðèñóòñòâóåò èìÿ [loader] |
.check_section: ;ïîèñê ñîîòâåòñòâóþùåé ñåêöèè íàì íóæíî áóäåò óçíàòü àäðåñ ýòîé ñåêöèè |
mov cx, bx |
mov di, ax |
;///////////////////////////// |
; mov ret_on_ch,.start_d ;set return |
mov si, di ;óñòàíîâèì óêàçàòåëü íà íàøó ñåêöèþ, êîòîðàÿ ïî äåôîëòó |
push di ;save point di |
push cx ;save cx |
;óñòàíîâèì óêàçàòåëü es:di íà íà÷àëî ini ôàéëà |
mov cx, save_cx ;it's placed size of ini file |
les di, dword [file_data] |
mov al, byte [es:di] |
push word .first_ret_d |
cmp al, ' ' |
jz .first_sp_1_d |
jmp get_firs_sym.not_space |
.first_sp_1_d: |
jmp get_firs_sym.first_sp |
.start_d: |
call get_firs_sym ;get first symbol on new line |
.first_ret_d: ;ïåðâûé âîçâðàò |
jcxz .correct_exit ;.end_loader ;found or not found parametrs in section exit in section |
cmp al, '[' |
jz .found_sect_d |
jmp .start_d |
;ïðîñìàòðèâàåì ini ôàéë ñ íà÷àëà â ïîèñêàõ ñåêöèè óêàçàíîé êàê default |
;èäåò ïðîâåðêà íà íàëè÷åå çíà÷åíèÿ timeout, äëÿ áîëåå áûñòðîé ðàáîòû, ýòîò ïàðàìåòð äîëæåí áûòü óæå îáðàáîòàí,ò.å. â ýòîì ñëó÷àå ïðè åãî =0 áóäåò ñôîðìèðîâàí óêàçàòåëü òîëüêî íà äåôîëòíóþ ñåêöèþ, èíà÷å èíôîðìàöèÿ áóäåò ñîáðàíà ïî âñåì ñåêöèÿì è ñîñòàâëåíû óêàçàòåëè â áëîêå ïàìÿòè |
.found_sect_d: |
;check on name section |
mov bx, cx |
mov ax, di |
push si ;save point |
; mov si,parse_loader |
mov cx, save_cx_d;load size section |
push es |
pop ds |
inc di |
repe cmpsb |
push cs |
pop ds |
pop si |
jnz .not_compare_d_s ;öåïî÷êà íå ñîâïàëà :( ïåðåéäåì äàëåå )) çíà÷èò íå èñêëþ÷åíèå |
cmp byte[es:di], ']' |
jnz .not_compare_d_s ;íåò â êîíöå íàøåé ñåêöèè çàâåðøàþùåãî ñèìâîëà :( |
;set flag -we have found default -not enter again in this prosedure |
or status_flag, flag_found_default |
pop cx |
pop di |
mov point_default, ax ;point to [ |
if DEBUG |
pusha |
mov si, lm_lf_default_f |
call printplain |
popa |
end if |
jmp .get_next_str |
.not_compare_d_s: |
mov cx, bx |
mov di, ax |
jmp .start_d |
.correct_exit: |
pop cx ;âîññòàíîâèì çíà÷åíèå ñ÷åò÷èêà |
pop di |
if DEBUG |
pusha |
mov si, lm_lf_default |
call printplain |
popa |
end if |
jmp .get_next_str |
;//////////[loader].timeout |
.loader_timeout: |
mov bx, cx |
mov ax, di |
mov si, parse_l_timeout |
mov cx, parse_l_timeout_e - parse_l_timeout |
repe cmpsb |
jnz error.rest_value ;is not compare |
sub bx, parse_l_timeout_e - parse_l_timeout;correct cx |
add bx, cx |
mov cx, bx |
test status_flag, flag_found_timeout |
jz .correct_is_not_set_t |
mov si, found_equal_timeout ;ìû íàøëè ÷òî ôëàã óæå óñòàíîâëåí, èíôîðìèðóåì |
call printplain |
jmp .get_next_str |
.correct_is_not_set_t: |
mov ax, 0x3d20 ;cut al=' ' ah='=' |
repe scasb |
jcxz .timeout_sec_end_d ;not found param timeout |
cmp ah, byte [es:di-1] ;find '=' |
jnz .get_next_str |
repe scasb ;cut ' ' |
inc cx |
dec di |
;get timeout value |
;2 çíàêa ìîæåò áûòü îáðàáîòàíî ò.å. çíà÷åíèå îò 0 äî 99 ñåêóíä |
push cx |
xor bx, bx |
mov cx, 2 |
@@: |
mov al, byte [es:di] |
cmp al, '0' |
jb .end_get_val_t |
cmp al, '9' |
ja .end_get_val_t |
imul bx, 10 |
xor al, 0x30 |
add bl, al |
.end_get_val_t: |
inc di |
loop @b |
mov word [value_timeout], bx |
; pop cx |
if DEBUG |
pusha |
mov si, lm_lf_timeout |
call printplain |
popa |
end if |
jmp @f |
.timeout_sec_end_d: |
mov word [value_timeout], default_timeout_value |
mov si, set_default_timeout_val |
call printplain |
@@: |
pop cx |
jmp .get_next_str |
;///////here end block loader |
.end_loader: |
if DEBUG |
pusha |
mov si, lm_l_end |
call printplain |
popa |
end if |
} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/sl_equ.inc |
---|
1,98 → 1,98 |
; Copyright (c) 2008-2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; Ïðåäîïðåäåëåíèÿ |
DEBUG equ 1 ;êîìïèëÿöèÿ ñ îòëàäî÷íîé èíôîðìàöèåé =1 áåç îòëàäî÷íîé èíôîðàöèè =0 |
loop_read_startos_file equ 3 ;êîë-âî ïîïûòîê ñ÷èòàòü ÷åðåç callback ñåðâèñ ôàéë êîíôèãóðàöèè áëîê2 |
root_dir_entry_count equ 224 ;êîë-âî ýëåìåíòîâ â êîðíåâîé äèððåêòîðèè |
;point_to_fat_struc equ 0xA000 ;âðåìåííûé áóôåð, êóäà áóäåò ðàçìåùåíà Fat òàáëèöà, è çàòåì ïåðåíåñåíà çà 1 ìá |
ini_data_ equ 0x2000 ;ôàéë ãäå ðàçìåùåí ôàéë ñöåíàðèÿ çàãðóçêè, òàì ïðîèñõîäèò ñèíòàêñè÷åñêèé ðàçáîð |
size_show_section equ 18 |
default_timeout_value equ 5 ;default value to timeout is will was some errors |
flag_found_default equ 0x1 ;default value is found |
flag_found_timeout equ 0x2 ;timeout value is found |
flag_found_LM equ 0x1 ;found LM value |
flag_found_RS equ 0x2 ;found RS value |
flag_found_GTRFMS equ 0x4 ;found type RamFS |
flag_found_RamdiskSector equ 0x8 ;found RamdiskSector |
flag_found_RamdiskCluster equ 0x16 ;found RamdiskCluster |
;statick data ýòè äàííûå íå ïðåäîïðåäåëÿþòñÿ â òå÷åíèè âûïîëíåíèÿ âñåé ïðîãðàììû. |
save_cx equ word [bp-2] ;save cx size ini file |
ret_on_ch equ word [bp-4] ;point to return ðàçðóøàåìîå çíà÷åíèå |
save_cx_d equ word [bp-6] ;save cx - size default section and working section |
status_flag equ word [bp-8] ;status flag |
point_loader equ word [bp-10] |
point_default equ word [bp-12] ;point to default |
;äàííûå êîòîðûå çàâèñèìû îò âåòêè âûïîëíåíèÿ è êîòîðûå ìîãóò áûòü ïåðåîïðåäåëåíû â ïðîöåññå âûïîëíåíèÿ ïðîãðàììû. |
point_to_hframe equ word [bp-14] ;point on start frame (for change section) |
point_to_1 equ word [bp-16] |
point_to_2 equ word [bp-18] |
point_to_3 equ word [bp-20] |
point_to_4 equ word [bp-22] |
point_to_5 equ word [bp-24] |
point_to_6 equ word [bp-26] |
point_to_7 equ word [bp-28] |
point_to_8 equ word [bp-30] |
point_to_9 equ word [bp-32] |
point_to_10 equ word [bp-34] |
point_to_11 equ word [bp-36] |
point_to_12 equ word [bp-38] |
point_to_13 equ word [bp-40] |
point_to_14 equ word [bp-42] |
point_to_15 equ word [bp-44] |
point_to_16 equ word [bp-46] |
point_to_16 equ word [bp-48] |
point_to_17 equ word [bp-50] |
point_to_18 equ word [bp-52] |
;here array for fast scroling 16 word - poin to start section |
point_to_point_def equ word [bp-54] |
point_to_eframe equ word [bp-56] ;point on point frame |
; òóò ðàñïîëîæåíî âðåìåííîå õðàíèëèùå äëÿ cx è di ïðè ïåðåõîäå íà ñëåäóþùèé áóôåð ïðè ïîèñêå ñåêöèé |
find_sec_di equ word [bp-58] ;òóò áóäåò õðàíèòüñÿ di |
info_real_mode_size equ word [bp-60];òóò õðàíèòüñÿ èíôîðìàöèÿ î çàíÿòîé îáëàñòè ò.å. ðàçìåð, ìîæíî óçíàòü ñêîëüêî îñòàëîñü ìåñòà âû÷èñëèâ |
free_ad_memory equ word [bp-62] ;ñêîëüêî ó íàñ ðàñøèðåííîé ïàìÿòè äëÿ ôîðìèðîâàíèÿ ðàì äèñêà è çàãðóçêè ìîäóëåé |
show_errors_sect equ word [bp-64] ;ïåðåìåíàÿ êîòîðàÿ õðàíèò áèòû îøèáîê äëÿ êàæäîé ëîãè÷åñêîé ñåêöèè. |
save_descript_size equ word [bp-66] ;save descript size previos section ñîõðàíèì ðàçìåð ïðåäûäóùåé ñåêöèè êîòîðóþ âûâîäèëè |
save_ramdisksize equ dword [bp-70] ;save size of ramdisk in byte |
save_file_size equ dword [bp-74] ;save size of reading file |
set_ramfs equ word [bp-76] ;îïðåäåëåííûé òèï ôàéëîâîé ñèñòåìû,íóæíî äëÿ ôîðìèðîâàíèÿ ðàì äèñêà |
point_next_fat_str equ word [bp-78] ;óêàçàòåëü íà ñëåäóþùèé ýëåìåíò fat òàáëèöû |
size_root_dir equ word [bp-80] ;êîë-âî ýëåìåíòîâ â ñåêòîðàõ ïî 512 áàéò êîðíåâîé äèðåêòîðèè |
firstDataSect equ word [bp-82] ;ïåðâûé ñåêòîð äàííûõ â ñåòîðàõ îò 0 |
DataClasters equ word [bp-84] ;ðàçìåð ìàññèâà äîñòóïíîé äëÿ çàïèñè äàííûõ â êëàñòåðàõ. |
point_to_free_root equ word [bp-86] ;óêàçàòåëü íà ñëåäóþùèé ïóñòóþ çàïèñü â ðóò äèð |
point_to_dest_file_name equ word [bp-88] ;óêàçûâàåò íà íà÷àëî èìåíè ôàéëà íàçíà÷åíèÿ. â ôîðìàòå es:point_to_dest_file_name, ãäå es =0x2000 |
data_offset equ word [bp-90] ;ñìåùåíèå â êëàñòåðàõ äëÿ çàïèñàííûõ äàííûõ ò.å ïåðåêèíóòûõ çà 1-é ìá |
first_input equ word [bp-92] ;ïîëå äëÿ ôëàãîâ â ïðåîáðàçîâàíèè èìåíè. |
save_di_RAMDISK equ word [bp-94] ;ñîõðàíèì di -óêàçàòåëÿ ïðè îáðàáîòêå ñåêöèè |
save_cx_RAMDISK equ word [bp-96] ;ñîõðàíèì ðàçìåð îñòàòêà ñåêöèè |
status_flag_loader_f equ word [bp-98] ;ñîõðàíèì ðåçóëüòàò âûïîëåíåíèÿ çàãðóçêè ôàéëà |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;äàííûå êîòîðûå èñïîëüçóþòñÿ ïðè îáðàáîòêå ñåêöèè, ò.å. ïîñëå íàæàòèÿ Enter, óæå íå âîçìîæíî âåðíóòüñÿ â ïåðâîíà÷àëüíûé ýêðàí |
;äëÿ âîçâðàòà, íåîáõîäèìî ïåðåçàïóñòèòü ïîëíîñòüþ êîä ò.å. ñòàðòîâàòü ñ 0õ1000:0000 |
; Copyright (c) 2008-2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; Ïðåäîïðåäåëåíèÿ |
DEBUG equ 1 ;êîìïèëÿöèÿ ñ îòëàäî÷íîé èíôîðìàöèåé =1 áåç îòëàäî÷íîé èíôîðàöèè =0 |
loop_read_startos_file equ 3 ;êîë-âî ïîïûòîê ñ÷èòàòü ÷åðåç callback ñåðâèñ ôàéë êîíôèãóðàöèè áëîê2 |
root_dir_entry_count equ 224 ;êîë-âî ýëåìåíòîâ â êîðíåâîé äèððåêòîðèè |
;point_to_fat_struc equ 0xA000 ;âðåìåííûé áóôåð, êóäà áóäåò ðàçìåùåíà Fat òàáëèöà, è çàòåì ïåðåíåñåíà çà 1 ìá |
ini_data_ equ 0x2000 ;ôàéë ãäå ðàçìåùåí ôàéë ñöåíàðèÿ çàãðóçêè, òàì ïðîèñõîäèò ñèíòàêñè÷åñêèé ðàçáîð |
size_show_section equ 18 |
default_timeout_value equ 5 ;default value to timeout is will was some errors |
flag_found_default equ 0x1 ;default value is found |
flag_found_timeout equ 0x2 ;timeout value is found |
flag_found_LM equ 0x1 ;found LM value |
flag_found_RS equ 0x2 ;found RS value |
flag_found_GTRFMS equ 0x4 ;found type RamFS |
flag_found_RamdiskSector equ 0x8 ;found RamdiskSector |
flag_found_RamdiskCluster equ 0x16 ;found RamdiskCluster |
;statick data ýòè äàííûå íå ïðåäîïðåäåëÿþòñÿ â òå÷åíèè âûïîëíåíèÿ âñåé ïðîãðàììû. |
save_cx equ word [bp-2] ;save cx size ini file |
ret_on_ch equ word [bp-4] ;point to return ðàçðóøàåìîå çíà÷åíèå |
save_cx_d equ word [bp-6] ;save cx - size default section and working section |
status_flag equ word [bp-8] ;status flag |
point_loader equ word [bp-10] |
point_default equ word [bp-12] ;point to default |
;äàííûå êîòîðûå çàâèñèìû îò âåòêè âûïîëíåíèÿ è êîòîðûå ìîãóò áûòü ïåðåîïðåäåëåíû â ïðîöåññå âûïîëíåíèÿ ïðîãðàììû. |
point_to_hframe equ word [bp-14] ;point on start frame (for change section) |
point_to_1 equ word [bp-16] |
point_to_2 equ word [bp-18] |
point_to_3 equ word [bp-20] |
point_to_4 equ word [bp-22] |
point_to_5 equ word [bp-24] |
point_to_6 equ word [bp-26] |
point_to_7 equ word [bp-28] |
point_to_8 equ word [bp-30] |
point_to_9 equ word [bp-32] |
point_to_10 equ word [bp-34] |
point_to_11 equ word [bp-36] |
point_to_12 equ word [bp-38] |
point_to_13 equ word [bp-40] |
point_to_14 equ word [bp-42] |
point_to_15 equ word [bp-44] |
point_to_16 equ word [bp-46] |
point_to_16 equ word [bp-48] |
point_to_17 equ word [bp-50] |
point_to_18 equ word [bp-52] |
;here array for fast scroling 16 word - poin to start section |
point_to_point_def equ word [bp-54] |
point_to_eframe equ word [bp-56] ;point on point frame |
; òóò ðàñïîëîæåíî âðåìåííîå õðàíèëèùå äëÿ cx è di ïðè ïåðåõîäå íà ñëåäóþùèé áóôåð ïðè ïîèñêå ñåêöèé |
find_sec_di equ word [bp-58] ;òóò áóäåò õðàíèòüñÿ di |
info_real_mode_size equ word [bp-60];òóò õðàíèòüñÿ èíôîðìàöèÿ î çàíÿòîé îáëàñòè ò.å. ðàçìåð, ìîæíî óçíàòü ñêîëüêî îñòàëîñü ìåñòà âû÷èñëèâ |
free_ad_memory equ word [bp-62] ;ñêîëüêî ó íàñ ðàñøèðåííîé ïàìÿòè äëÿ ôîðìèðîâàíèÿ ðàì äèñêà è çàãðóçêè ìîäóëåé |
show_errors_sect equ word [bp-64] ;ïåðåìåíàÿ êîòîðàÿ õðàíèò áèòû îøèáîê äëÿ êàæäîé ëîãè÷åñêîé ñåêöèè. |
save_descript_size equ word [bp-66] ;save descript size previos section ñîõðàíèì ðàçìåð ïðåäûäóùåé ñåêöèè êîòîðóþ âûâîäèëè |
save_ramdisksize equ dword [bp-70] ;save size of ramdisk in byte |
save_file_size equ dword [bp-74] ;save size of reading file |
set_ramfs equ word [bp-76] ;îïðåäåëåííûé òèï ôàéëîâîé ñèñòåìû,íóæíî äëÿ ôîðìèðîâàíèÿ ðàì äèñêà |
point_next_fat_str equ word [bp-78] ;óêàçàòåëü íà ñëåäóþùèé ýëåìåíò fat òàáëèöû |
size_root_dir equ word [bp-80] ;êîë-âî ýëåìåíòîâ â ñåêòîðàõ ïî 512 áàéò êîðíåâîé äèðåêòîðèè |
firstDataSect equ word [bp-82] ;ïåðâûé ñåêòîð äàííûõ â ñåòîðàõ îò 0 |
DataClasters equ word [bp-84] ;ðàçìåð ìàññèâà äîñòóïíîé äëÿ çàïèñè äàííûõ â êëàñòåðàõ. |
point_to_free_root equ word [bp-86] ;óêàçàòåëü íà ñëåäóþùèé ïóñòóþ çàïèñü â ðóò äèð |
point_to_dest_file_name equ word [bp-88] ;óêàçûâàåò íà íà÷àëî èìåíè ôàéëà íàçíà÷åíèÿ. â ôîðìàòå es:point_to_dest_file_name, ãäå es =0x2000 |
data_offset equ word [bp-90] ;ñìåùåíèå â êëàñòåðàõ äëÿ çàïèñàííûõ äàííûõ ò.å ïåðåêèíóòûõ çà 1-é ìá |
first_input equ word [bp-92] ;ïîëå äëÿ ôëàãîâ â ïðåîáðàçîâàíèè èìåíè. |
save_di_RAMDISK equ word [bp-94] ;ñîõðàíèì di -óêàçàòåëÿ ïðè îáðàáîòêå ñåêöèè |
save_cx_RAMDISK equ word [bp-96] ;ñîõðàíèì ðàçìåð îñòàòêà ñåêöèè |
status_flag_loader_f equ word [bp-98] ;ñîõðàíèì ðåçóëüòàò âûïîëåíåíèÿ çàãðóçêè ôàéëà |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;äàííûå êîòîðûå èñïîëüçóþòñÿ ïðè îáðàáîòêå ñåêöèè, ò.å. ïîñëå íàæàòèÿ Enter, óæå íå âîçìîæíî âåðíóòüñÿ â ïåðâîíà÷àëüíûé ýêðàí |
;äëÿ âîçâðàòà, íåîáõîäèìî ïåðåçàïóñòèòü ïîëíîñòüþ êîä ò.å. ñòàðòîâàòü ñ 0õ1000:0000 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sec_loader/trunk/sl_proc.inc |
---|
1,524 → 1,528 |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; òóò îïèñûâàþòñÿ ïðîöåäóðû êîòîðûå èñïîëüçóþòñÿ â secondary loader |
color_sym_black equ 0 |
color_sym_blue equ 1 |
color_sym_green equ 2 |
color_sym_turquoise equ 3 |
color_sym_red equ 4 |
color_sym_lightgray equ 7 |
color_sym_lightblue equ 9 |
color_sym_lettuce equ 10 |
color_sym_pink equ 12 |
color_sym_yellow equ 14 |
color_sym_white equ 15 |
if DEBUG |
decode: |
;input eax - ÷èñëî, es:di êóäà ïèñàòü, cx=10 |
cmp eax,ecx |
jb @f |
xor edx,edx |
div ecx |
push edx |
call decode |
pop eax |
@@: or al,0x30 |
mov [ds:di],al |
inc di |
ret |
end if |
putchar: |
; in: al=character |
mov ah, 0Eh |
mov bh, 0 |
int 10h |
ret |
printplain: |
; in: si->string |
pushad |
lodsb |
@@: |
call putchar |
lodsb |
test al,al |
jnz @b |
mov al,13 |
call putchar |
mov al,10 |
call putchar |
popad |
ret |
getkey: |
; get number in range [bl,bh] (bl,bh in ['0'..'9']) |
; in: bx=range |
; out: ax=digit (1..9, 10 for 0) |
mov ah, 0 |
int 16h |
cmp al, bl |
jb getkey |
cmp al, bh |
ja getkey |
push ax |
call putchar |
pop ax |
and ax, 0Fh |
jnz @f |
mov al, 10 |
@@: |
ret |
;setcursor: |
; in: dl=column, dh=row |
; mov ah, 2 |
; mov bh, 0 |
; int 10h |
; ret |
;macro _setcursor row,column |
;{ |
; mov dx, row*256 + column |
; call setcursor |
;} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
get_firs_sym: |
.start: |
mov al,byte [es:di] |
inc di |
dec cx |
jcxz .exit |
cmp al,0xa ;cmp al,0xa |
jz ._entry |
cmp al,';' |
jnz .start |
.first_com: |
mov al,0xa |
repnz scasb |
jcxz .exit |
._entry: |
mov al,byte [es:di] |
.first_sp: |
cmp al,' ' |
jnz .not_space |
; mov al,' ' ;cut ' ' |
repe scasb |
dec di |
inc cx |
mov al,byte [es:di] |
.not_space: |
cmp al,';' |
jz .first_com |
.exit: ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
show_name_section: |
push si |
push ini_data_ |
pop es |
mov al,']' |
repnz scasb |
test cx,cx |
jz error.incorect_section_def |
.find_val_name_fb1: |
mov al,'n' |
.find_val_name_fb: |
repnz scasb |
jcxz .not_name_sec_fb |
mov si,parse_name |
push cx |
push di |
mov cx,parse_name_e -parse_name |
repe cmpsb |
pop di |
pop cx |
jz .yaaa_find_value |
jmp .find_val_name_fb |
.yaaa_find_value: |
sub cx,parse_name_e -parse_name |
add di,parse_name_e -parse_name |
mov ax,0x3d20 ; ah='=' |
repe scasb |
test cx,cx |
jz .not_name_sec_fb |
cmp ah,byte [es:di-1] ;find '=' |
jnz .find_val_name_fb1 |
repe scasb ;cut ' ' |
inc cx |
dec di |
;âñå âûðåçàëè è âñå ãîòîâî äëÿ âûâîäà èìåíè ñåêöèè )) |
push es |
pop ds |
.def_sect_name: |
push 0xb800 |
pop es |
;clear array for message |
xor ax,ax |
if DEBUG |
mov ax,0x0720 |
end if |
mov cx,39 |
mov si,di |
mov di,dx |
sub di,2 |
rep stosw |
;////////////////////// |
mov di,dx |
mov ah,color_sym_white;color_sym_lightblue |
mov cx,36 |
lodsb |
sub di,2 |
cmp al,'"' |
jz @f |
cmp al,"'" |
jnz .end_sh_name_sec |
@@: lodsb |
@@: |
stosw |
lodsb |
cmp al,'"' |
jz .end_sh_name_sec |
cmp al,"'" |
jz .end_sh_name_sec |
loop @b |
mov al,'}' |
mov ah,color_sym_yellow |
stosw |
.end_sh_name_sec: |
push cs |
pop ds |
pop si |
ret |
.not_name_sec_fb: ;íåò èìåíè â íàçâàíèè ñåêöèè - çíà÷èò òàê è ñêàæåì îá ýòîì |
push cs |
pop ds |
mov di,default_section_name |
jmp .def_sect_name |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;ïðîöåäóðà ïîèñêà ââåðõ ñëåäóþùåé ñåêöèè |
;â point_default ñîäåðæèòüñÿ óêàçàòåëü íà äåôàóëò ñåêöèþ, è â ïðåäåëàõ âðåéìà ìû áåãàåì ïî çàðàíåå ïðîïàðñåíûìè çíà÷åíèÿì óêàçàòåëåé |
;äëÿ òîãî ÷òî áû îòîáðàçèòü è ïðîïàðñèòü ñëåäóþùèé ôðåéì, íàì íóæíî ïîëó÷èòü çà ïåðäûäóùèé èëè ñëåäóþùèé óêàçàòåëü |
find_before_sect: |
mov di,point_default |
.e: |
push ini_data_ |
pop es |
mov cx,di ;ïðåäïîëîæèì áóäåì ïðîñìàòðèâàòü ê íà÷àëó, òåêóùàÿ ïîçèöèÿ di = ñêîëüêî ñèìâîëîâ îò íà÷àëà äîêóìåíòà èìååòñÿ |
mov bx,cx ;êîïèÿ |
;íàñòðîèëè óêàçàòåëü íà äåôàóëò ñåêöèþ |
;áóäåì èñêàòü ââåðõ |
.find_start_section: |
std ;óñòàíîâêà ôëàãà íàïðàâëåíèÿ - áóäåì ïðîñìàòèðâàòü ê íà÷àëó íàøåãî èíè ôàéëà |
;áóäåì èñêàòü íà÷àëî ñåêöèè ò.å. '[' ýòîò ñèìâîë |
mov al,0xa |
repnz scasb ;ïðîñêàíèðóåì íà íàëè÷åå ñèìâîëà íà÷àëà ñåêöèè |
jcxz .go_ ;ìû ïðîñìîòðåëè äî íà÷àëà ôàéëà, íî òàê è íè÷åãî íå íàøëè ;(( ïî òèõîìó âûéäåì ) |
mov find_sec_di,di ;ñîõðàíèì äàííûå |
mov cx,di ; |
sub bx,cx |
mov cx,bx ;â ñx çíà÷åíèå - êîë-âî ñèìâîëîâ |
cld |
call get_firs_sym |
.ret_go: |
jcxz ._not_section ; â äàííîì ñëó÷àå èìååì êîíñòðóêöèþ 0xa ... ; hello [ñåêöèÿ] îáëîìñ èùåì äàëåå |
cmp di,point_loader ; ñåêöèþ loader ìû íå çàíîñèì èíà÷å êðàõ |
jz ._not_section |
;âñå óäà÷íî ìû íàøëè âõîæäåíèå ñåêöèè ïðåäûäóùåé |
cmp al,'[' |
jnz ._not_section |
mov point_default,di |
.exit_scan_sect: |
ret |
;;;;;;;; âîññòàíîâèì çíà÷åíèÿ è ïðîäîëæèì ïîèñêè íà÷àëà ñåêöèè êîòîðàÿ íàñ óñòðîèò )) |
._not_section: |
mov di,find_sec_di |
mov cx,di |
mov bx,cx |
jmp .find_start_section |
.go_: |
cld |
mov cx,bx ;â ñx çíà÷åíèå - êîë-âî ñèìâîëîâ |
mov al,byte [es:di] |
push word .f_go |
cmp al,' ' |
jz @f |
jmp get_firs_sym.not_space |
@@: |
jmp get_firs_sym.first_sp |
.f_go: |
jcxz .exit_scan_sect ; â äàííîì ñëó÷àå èìååì êîíñòðóêöèþ 0xa ... ; hello [ñåêöèÿ] îáëîìñ èùåì äàëåå |
cmp di,point_loader ; ñåêöèþ loader ìû íå çàíîñèì èíà÷å êðàõ |
jz .exit_scan_sect |
;âñå óäà÷íî ìû íàøëè âõîæäåíèå ñåêöèè ïðåäûäóùåé |
cmp al,'[' |
jnz .exit_scan_sect |
mov point_default,di |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
find_next_sect: |
mov di,point_default |
push ini_data_ |
pop es |
mov cx,save_cx;di ;ïðåäïîëîæèì áóäåì ïðîñìàòðèâàòü ê êîíöó, òåêóùàÿ ïîçèöèÿ di = ñêîëüêî ñèìâîëîâ îò íà÷àëà äîêóìåíòà èìååòñÿ |
sub cx,di ;ñåé÷àñ â cx îñòàòîê ò.å. ñêîëüêî ìîæíî êðóòèòü äî êîíöà è íå âûëàçèòü íà íà÷àëî |
jmp .let_s_go |
.h: |
push ini_data_ |
pop es |
mov cx,save_cx;di ;ïðåäïîëîæèì áóäåì ïðîñìàòðèâàòü ê êîíöó, òåêóùàÿ ïîçèöèÿ di = ñêîëüêî ñèìâîëîâ îò íà÷àëà äîêóìåíòà èìååòñÿ |
; sub cx,di ;ñåé÷àñ â cx îñòàòîê ò.å. ñêîëüêî ìîæíî êðóòèòü äî êîíöà è íå âûëàçèòü íà íà÷àëî |
mov al,byte [es:di] |
push word .let_s_go_ret |
cmp al,' ' |
jz @f |
jmp get_firs_sym.not_space |
@@: |
jmp get_firs_sym.first_sp |
;íàñòðîèëè óêàçàòåëü íà äåôàóëò ñåêöèþ |
;áóäåì èñêàòü âíèç |
.let_s_go: |
call get_firs_sym |
.let_s_go_ret: |
jcxz .exit_scan_sect ; â äàííîì ñëó÷àå èìååì êîíñòðóêöèþ 0xa ... ; hello [ñåêöèÿ] îáëîìñ èùåì äàëåå |
cmp al,'[' |
jnz .let_s_go |
cmp di,point_loader |
jz .let_s_go |
;âñå óäà÷íî ìû íàøëè âõîæäåíèå ñåêöèè ïðåäûäóùåé |
mov point_default,di |
.exit_scan_sect: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
;clean old cursor |
clean_active_cursor: |
;íå èçìåíÿåò çíà÷åíèå ax |
;îòîáðàæåíèå êóðñîðà ïî óìîë÷àíèþ |
lea si,point_to_hframe |
mov di,962-160 |
mov dx,point_default |
mov cx,18 |
.clean_show_cur: |
mov bx,[si] |
add di,160 |
cmp bx,dx |
jz .clean_cursor_ |
sub si,2 |
loop .clean_show_cur |
; jmp $ |
.clean_cursor_: |
push 0xb800 |
pop es |
push ax |
mov point_to_point_def,si |
xor ax,ax |
if DEBUG |
mov ax,0x0720 |
end if |
stosw |
add di,68 |
stosw |
pop ax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;óñòàíîâêà òàéìåðà è îòîáðàæåíèå ñ÷åò÷èêà âðåìåíè |
gettime: |
mov ah,0 |
int 1Ah |
xchg ax, cx |
shl eax, 10h |
xchg ax, dx |
ret |
newtimer: |
push ds |
push cs |
pop ds |
pushf |
call far dword [old_timer] |
pushad |
call gettime |
sub eax, dword[start_timer] |
mov bx, word [value_timeout] |
imul bx,18 |
sub bx, ax |
jbe .timergo |
push es |
push 0xb800 |
pop es |
mov ax,bx |
mov bx, 18 |
xor dx, dx |
div bx |
mov bx,10 |
mov di,3734 |
call .decode |
xor ax,ax |
stosw |
; wait 5/4/3/2 seconds, 1 second |
pop es |
popad |
pop ds |
iret |
.timergo: |
push 0 |
pop es |
mov eax,dword [old_timer] |
mov [es:8*4], eax |
mov dword [timer_],eax |
mov sp, word [start_stack] |
mov bp,word [save_bp_from_timer] |
;;íå âîññòàíîâëåíûé ñòåê :( |
sti |
jmp parse_start.parse_run_only |
.decode: |
;input ax - ÷èñëî, es:di êóäà ïèñàòü, bx=10 |
cmp ax,bx |
jb @f |
xor dx,dx |
div bx |
push dx |
call .decode |
pop ax |
@@: or al,0x30 |
push ax |
mov ah,9 |
stosw |
pop ax |
ret |
show_bl_sc_sect: |
;1) îòîáðàæåíèå ñïèñêà ñåêöèé. Åñëè ñåêöèÿ íå èìåò èìÿ - îøèáêà - âûâîä Section unname |
;ïðîâåðêà íà íàëè÷åå èìåíè. |
;âõîäíûå äàííûå es:di -óêàçàòåëü íà ñåêöèþ - cx ðàçìåð ñåêöèè |
; push bp |
mov bx,point_to_eframe |
lea si,point_to_hframe |
mov dx,966 |
.home_show_fb: |
cmp si,bx |
jb ._show_space_fb |
mov di,[si] |
sub si,2 |
mov cx,[si] |
sub cx,di ;home first section it's end before section |
call show_name_section |
add dx,160 |
jmp .home_show_fb |
._show_space_fb: |
sub dx,4 |
push 0xb800 |
pop es |
@@: |
cmp dx,0xE64 |
ja .exit_show_fb |
mov di,dx |
;clear array for message |
xor ax,ax |
if DEBUG |
mov ax,0x0720 |
end if |
mov cx,39 |
rep stosw |
;////////////////////// |
add dx,160 |
jmp @b |
.exit_show_fb: |
; pop bp |
ret |
; Copyright (c) 2009, <Lrz> |
; All rights reserved. |
; |
; Redistribution and use in source and binary forms, with or without |
; modification, are permitted provided that the following conditions are met: |
; * Redistributions of source code must retain the above copyright |
; notice, this list of conditions and the following disclaimer. |
; * Redistributions in binary form must reproduce the above copyright |
; notice, this list of conditions and the following disclaimer in the |
; documentation and/or other materials provided with the distribution. |
; * Neither the name of the <organization> nor the |
; names of its contributors may be used to endorse or promote products |
; derived from this software without specific prior written permission. |
; |
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY |
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
;***************************************************************************** |
; òóò îïèñûâàþòñÿ ïðîöåäóðû êîòîðûå èñïîëüçóþòñÿ â secondary loader |
color_sym_black equ 0 |
color_sym_blue equ 1 |
color_sym_green equ 2 |
color_sym_turquoise equ 3 |
color_sym_red equ 4 |
color_sym_lightgray equ 7 |
color_sym_lightblue equ 9 |
color_sym_lettuce equ 10 |
color_sym_pink equ 12 |
color_sym_yellow equ 14 |
color_sym_white equ 15 |
if DEBUG |
decode: |
;input eax - ÷èñëî, es:di êóäà ïèñàòü, cx=10 |
cmp eax, ecx |
jb @f |
xor edx, edx |
div ecx |
push edx |
call decode |
pop eax |
@@: |
or al, 0x30 |
mov [ds:di], al |
inc di |
ret |
end if |
putchar: |
; in: al=character |
mov ah, 0Eh |
mov bh, 0 |
int 10h |
ret |
printplain: |
; in: si->string |
pushad |
lodsb |
@@: |
call putchar |
lodsb |
test al, al |
jnz @b |
mov al, 13 |
call putchar |
mov al, 10 |
call putchar |
popad |
ret |
getkey: |
; get number in range [bl,bh] (bl,bh in ['0'..'9']) |
; in: bx=range |
; out: ax=digit (1..9, 10 for 0) |
mov ah, 0 |
int 16h |
cmp al, bl |
jb getkey |
cmp al, bh |
ja getkey |
push ax |
call putchar |
pop ax |
and ax, 0Fh |
jnz @f |
mov al, 10 |
@@: |
ret |
;setcursor: |
; in: dl=column, dh=row |
; mov ah, 2 |
; mov bh, 0 |
; int 10h |
; ret |
;macro _setcursor row,column |
;{ |
; mov dx, row*256 + column |
; call setcursor |
;} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
get_firs_sym: |
.start: |
mov al, byte [es:di] |
inc di |
dec cx |
jcxz .exit |
cmp al, 0xa ;cmp al,0xa |
jz ._entry |
cmp al, ';' |
jnz .start |
.first_com: |
mov al, 0xa |
repnz scasb |
jcxz .exit |
._entry: |
mov al, byte [es:di] |
.first_sp: |
cmp al, ' ' |
jnz .not_space |
; mov al,' ' ;cut ' ' |
repe scasb |
dec di |
inc cx |
mov al, byte [es:di] |
.not_space: |
cmp al, ';' |
jz .first_com |
.exit: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
show_name_section: |
push si |
push ini_data_ |
pop es |
mov al, ']' |
repnz scasb |
test cx, cx |
jz error.incorect_section_def |
.find_val_name_fb1: |
mov al, 'n' |
.find_val_name_fb: |
repnz scasb |
jcxz .not_name_sec_fb |
mov si, parse_name |
push cx |
push di |
mov cx, parse_name_e -parse_name |
repe cmpsb |
pop di |
pop cx |
jz .yaaa_find_value |
jmp .find_val_name_fb |
.yaaa_find_value: |
sub cx, parse_name_e -parse_name |
add di, parse_name_e -parse_name |
mov ax, 0x3d20 ; ah='=' |
repe scasb |
test cx, cx |
jz .not_name_sec_fb |
cmp ah, byte [es:di-1] ;find '=' |
jnz .find_val_name_fb1 |
repe scasb ;cut ' ' |
inc cx |
dec di |
;âñå âûðåçàëè è âñå ãîòîâî äëÿ âûâîäà èìåíè ñåêöèè )) |
push es |
pop ds |
.def_sect_name: |
push 0xb800 |
pop es |
;clear array for message |
xor ax, ax |
if DEBUG |
mov ax, 0x0720 |
end if |
mov cx, 39 |
mov si, di |
mov di, dx |
sub di, 2 |
rep stosw |
;////////////////////// |
mov di, dx |
mov ah, color_sym_white;color_sym_lightblue |
mov cx, 36 |
lodsb |
sub di, 2 |
cmp al, '"' |
jz @f |
cmp al, "'" |
jnz .end_sh_name_sec |
@@: |
lodsb |
@@: |
stosw |
lodsb |
cmp al, '"' |
jz .end_sh_name_sec |
cmp al, "'" |
jz .end_sh_name_sec |
loop @b |
mov al, '}' |
mov ah, color_sym_yellow |
stosw |
.end_sh_name_sec: |
push cs |
pop ds |
pop si |
ret |
.not_name_sec_fb: ;íåò èìåíè â íàçâàíèè ñåêöèè - çíà÷èò òàê è ñêàæåì îá ýòîì |
push cs |
pop ds |
mov di, default_section_name |
jmp .def_sect_name |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;ïðîöåäóðà ïîèñêà ââåðõ ñëåäóþùåé ñåêöèè |
;â point_default ñîäåðæèòüñÿ óêàçàòåëü íà äåôàóëò ñåêöèþ, è â ïðåäåëàõ âðåéìà ìû áåãàåì ïî çàðàíåå ïðîïàðñåíûìè çíà÷åíèÿì óêàçàòåëåé |
;äëÿ òîãî ÷òî áû îòîáðàçèòü è ïðîïàðñèòü ñëåäóþùèé ôðåéì, íàì íóæíî ïîëó÷èòü çà ïåðäûäóùèé èëè ñëåäóþùèé óêàçàòåëü |
find_before_sect: |
mov di, point_default |
.e: |
push ini_data_ |
pop es |
mov cx, di ;ïðåäïîëîæèì áóäåì ïðîñìàòðèâàòü ê íà÷àëó, òåêóùàÿ ïîçèöèÿ di = ñêîëüêî ñèìâîëîâ îò íà÷àëà äîêóìåíòà èìååòñÿ |
mov bx, cx ;êîïèÿ |
;íàñòðîèëè óêàçàòåëü íà äåôàóëò ñåêöèþ |
;áóäåì èñêàòü ââåðõ |
.find_start_section: |
std ;óñòàíîâêà ôëàãà íàïðàâëåíèÿ - áóäåì ïðîñìàòèðâàòü ê íà÷àëó íàøåãî èíè ôàéëà |
;áóäåì èñêàòü íà÷àëî ñåêöèè ò.å. '[' ýòîò ñèìâîë |
mov al, 0xa |
repnz scasb ;ïðîñêàíèðóåì íà íàëè÷åå ñèìâîëà íà÷àëà ñåêöèè |
jcxz .go_ ;ìû ïðîñìîòðåëè äî íà÷àëà ôàéëà, íî òàê è íè÷åãî íå íàøëè ;(( ïî òèõîìó âûéäåì ) |
mov find_sec_di, di ;ñîõðàíèì äàííûå |
mov cx, di ; |
sub bx, cx |
mov cx, bx ;â ñx çíà÷åíèå - êîë-âî ñèìâîëîâ |
cld |
call get_firs_sym |
.ret_go: |
jcxz ._not_section ; â äàííîì ñëó÷àå èìååì êîíñòðóêöèþ 0xa ... ; hello [ñåêöèÿ] îáëîìñ èùåì äàëåå |
cmp di, point_loader; ñåêöèþ loader ìû íå çàíîñèì èíà÷å êðàõ |
jz ._not_section |
;âñå óäà÷íî ìû íàøëè âõîæäåíèå ñåêöèè ïðåäûäóùåé |
cmp al, '[' |
jnz ._not_section |
mov point_default, di |
.exit_scan_sect: |
ret |
;;;;;;;; âîññòàíîâèì çíà÷åíèÿ è ïðîäîëæèì ïîèñêè íà÷àëà ñåêöèè êîòîðàÿ íàñ óñòðîèò )) |
._not_section: |
mov di, find_sec_di |
mov cx, di |
mov bx, cx |
jmp .find_start_section |
.go_: |
cld |
mov cx, bx ;â ñx çíà÷åíèå - êîë-âî ñèìâîëîâ |
mov al, byte [es:di] |
push word .f_go |
cmp al, ' ' |
jz @f |
jmp get_firs_sym.not_space |
@@: |
jmp get_firs_sym.first_sp |
.f_go: |
jcxz .exit_scan_sect ; â äàííîì ñëó÷àå èìååì êîíñòðóêöèþ 0xa ... ; hello [ñåêöèÿ] îáëîìñ èùåì äàëåå |
cmp di, point_loader; ñåêöèþ loader ìû íå çàíîñèì èíà÷å êðàõ |
jz .exit_scan_sect |
;âñå óäà÷íî ìû íàøëè âõîæäåíèå ñåêöèè ïðåäûäóùåé |
cmp al, '[' |
jnz .exit_scan_sect |
mov point_default, di |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
find_next_sect: |
mov di, point_default |
push ini_data_ |
pop es |
mov cx, save_cx;di ;ïðåäïîëîæèì áóäåì ïðîñìàòðèâàòü ê êîíöó, òåêóùàÿ ïîçèöèÿ di = ñêîëüêî ñèìâîëîâ îò íà÷àëà äîêóìåíòà èìååòñÿ |
sub cx, di ;ñåé÷àñ â cx îñòàòîê ò.å. ñêîëüêî ìîæíî êðóòèòü äî êîíöà è íå âûëàçèòü íà íà÷àëî |
jmp .let_s_go |
.h: |
push ini_data_ |
pop es |
mov cx, save_cx;di ;ïðåäïîëîæèì áóäåì ïðîñìàòðèâàòü ê êîíöó, òåêóùàÿ ïîçèöèÿ di = ñêîëüêî ñèìâîëîâ îò íà÷àëà äîêóìåíòà èìååòñÿ |
; sub cx,di ;ñåé÷àñ â cx îñòàòîê ò.å. ñêîëüêî ìîæíî êðóòèòü äî êîíöà è íå âûëàçèòü íà íà÷àëî |
mov al, byte [es:di] |
push word .let_s_go_ret |
cmp al, ' ' |
jz @f |
jmp get_firs_sym.not_space |
@@: |
jmp get_firs_sym.first_sp |
;íàñòðîèëè óêàçàòåëü íà äåôàóëò ñåêöèþ |
;áóäåì èñêàòü âíèç |
.let_s_go: |
call get_firs_sym |
.let_s_go_ret: |
jcxz .exit_scan_sect ; â äàííîì ñëó÷àå èìååì êîíñòðóêöèþ 0xa ... ; hello [ñåêöèÿ] îáëîìñ èùåì äàëåå |
cmp al, '[' |
jnz .let_s_go |
cmp di, point_loader |
jz .let_s_go |
;âñå óäà÷íî ìû íàøëè âõîæäåíèå ñåêöèè ïðåäûäóùåé |
mov point_default, di |
.exit_scan_sect: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;; |
;clean old cursor |
clean_active_cursor: |
;íå èçìåíÿåò çíà÷åíèå ax |
;îòîáðàæåíèå êóðñîðà ïî óìîë÷àíèþ |
lea si, point_to_hframe |
mov di, 962-160 |
mov dx, point_default |
mov cx, 18 |
.clean_show_cur: |
mov bx, [si] |
add di, 160 |
cmp bx, dx |
jz .clean_cursor_ |
sub si, 2 |
loop .clean_show_cur |
; jmp $ |
.clean_cursor_: |
push 0xb800 |
pop es |
push ax |
mov point_to_point_def, si |
xor ax, ax |
if DEBUG |
mov ax, 0x0720 |
end if |
stosw |
add di, 68 |
stosw |
pop ax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;óñòàíîâêà òàéìåðà è îòîáðàæåíèå ñ÷åò÷èêà âðåìåíè |
gettime: |
mov ah, 0 |
int 1Ah |
xchg ax, cx |
shl eax, 10h |
xchg ax, dx |
ret |
newtimer: |
push ds |
push cs |
pop ds |
pushf |
call far dword [old_timer] |
pushad |
call gettime |
sub eax, dword[start_timer] |
mov bx, word [value_timeout] |
imul bx, 18 |
sub bx, ax |
jbe .timergo |
push es |
push 0xb800 |
pop es |
mov ax, bx |
mov bx, 18 |
xor dx, dx |
div bx |
mov bx, 10 |
mov di, 3734 |
call .decode |
xor ax, ax |
stosw |
; wait 5/4/3/2 seconds, 1 second |
pop es |
popad |
pop ds |
iret |
.timergo: |
push 0 |
pop es |
mov eax, dword [old_timer] |
mov [es:8*4], eax |
mov dword [timer_], eax |
mov sp, word [start_stack] |
mov bp, word [save_bp_from_timer] |
;;íå âîññòàíîâëåíûé ñòåê :( |
sti |
jmp parse_start.parse_run_only |
.decode: |
;input ax - ÷èñëî, es:di êóäà ïèñàòü, bx=10 |
cmp ax, bx |
jb @f |
xor dx, dx |
div bx |
push dx |
call .decode |
pop ax |
@@: |
or al, 0x30 |
push ax |
mov ah, 9 |
stosw |
pop ax |
ret |
show_bl_sc_sect: |
;1) îòîáðàæåíèå ñïèñêà ñåêöèé. Åñëè ñåêöèÿ íå èìåò èìÿ - îøèáêà - âûâîä Section unname |
;ïðîâåðêà íà íàëè÷åå èìåíè. |
;âõîäíûå äàííûå es:di -óêàçàòåëü íà ñåêöèþ - cx ðàçìåð ñåêöèè |
; push bp |
mov bx, point_to_eframe |
lea si, point_to_hframe |
mov dx, 966 |
.home_show_fb: |
cmp si, bx |
jb ._show_space_fb |
mov di, [si] |
sub si, 2 |
mov cx, [si] |
sub cx, di ;home first section it's end before section |
call show_name_section |
add dx, 160 |
jmp .home_show_fb |
._show_space_fb: |
sub dx, 4 |
push 0xb800 |
pop es |
@@: |
cmp dx, 0xE64 |
ja .exit_show_fb |
mov di, dx |
;clear array for message |
xor ax, ax |
if DEBUG |
mov ax, 0x0720 |
end if |
mov cx, 39 |
rep stosw |
;////////////////////// |
add dx, 160 |
jmp @b |
.exit_show_fb: |
; pop bp |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/skin/default.asm |
---|
1,38 → 1,38 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include 'me_skin.inc' |
SKIN_PARAMS \ |
height = bmp_base.height,\ ; skin height |
margins = [5:1:43:1],\ ; margins [left:top:right:bottom] |
colors active = [binner=0x00081d:\ ; border inner color |
bouter=0x00081d:\ ; border outer color |
bframe=0x0054e7],\ ; border frame color |
colors inactive = [binner=0x00081d:\ ; border inner color |
bouter=0x00081d:\ ; border outer color |
bframe=0x1a8acc],\ ; border frame color |
dtp = 'myblue.dtp' ; dtp colors |
SKIN_BUTTONS \ |
close = [-21:3][16:16],\ ; buttons coordinates |
minimize = [-39:3][16:16] ; [left:top][width:height] |
SKIN_BITMAPS \ |
left active = bmp_left,\ ; skin bitmaps pointers |
left inactive = bmp_left1,\ |
oper active = bmp_oper,\ |
oper inactive = bmp_oper1,\ |
base active = bmp_base,\ |
base inactive = bmp_base1 |
BITMAP bmp_left ,'left.bmp' ; skin bitmaps |
BITMAP bmp_oper ,'oper.bmp' |
BITMAP bmp_base ,'base.bmp' |
BITMAP bmp_left1,'left_1.bmp' |
BITMAP bmp_oper1,'oper_1.bmp' |
BITMAP bmp_base1,'base_1.bmp' |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include 'me_skin.inc' |
SKIN_PARAMS \ |
height = bmp_base.height,\ ; skin height |
margins = [5:1:43:1],\ ; margins [left:top:right:bottom] |
colors active = [binner=0x00081d:\ ; border inner color |
bouter=0x00081d:\ ; border outer color |
bframe=0x0054e7],\ ; border frame color |
colors inactive = [binner=0x00081d:\ ; border inner color |
bouter=0x00081d:\ ; border outer color |
bframe=0x1a8acc],\ ; border frame color |
dtp = 'myblue.dtp' ; dtp colors |
SKIN_BUTTONS \ |
close = [-21:3][16:16],\ ; buttons coordinates |
minimize = [-39:3][16:16] ; [left:top][width:height] |
SKIN_BITMAPS \ |
left active = bmp_left,\ ; skin bitmaps pointers |
left inactive = bmp_left1,\ |
oper active = bmp_oper,\ |
oper inactive = bmp_oper1,\ |
base active = bmp_base,\ |
base inactive = bmp_base1 |
BITMAP bmp_left ,'left.bmp' ; skin bitmaps |
BITMAP bmp_oper ,'oper.bmp' |
BITMAP bmp_base ,'base.bmp' |
BITMAP bmp_left1,'left_1.bmp' |
BITMAP bmp_oper1,'oper_1.bmp' |
BITMAP bmp_base1,'base_1.bmp' |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/skin/me_skin.inc |
---|
1,242 → 1,242 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;============================================================================ |
; This file should be used to generate skins of new standard |
;============================================================================ |
; skin file structure: |
;---------------------------------------------------------------------------- |
; header: |
; dd 'SKIN' |
; dd = version (1 for now) |
; dd @ params |
; dd @ buttons |
; dd @ bitmaps |
; ... |
;---------------------------------------------------------------------------- |
; NOTE: order of sections listed below is insignificant |
; since they're identified by pointer in above header |
;---------------------------------------------------------------------------- |
; ... |
; params: |
; dd = skin height |
; dw = right margin |
; dw = left margin |
; dw = bottom margin |
; dw = top margin |
; dd = inner line color |
; dd = outer line color |
; dd = frame color |
; dd = dtp file size |
; ?? = dtp file itself |
; ... |
;---------------------------------------------------------------------------- |
; ... |
; buttons: |
; dd = button type (1 = close, 2 = minimize) |
; dw = left button coord (could be negative) |
; dw = top button coord (could be negative) |
; dw = button width |
; dw = button height |
; ... etc for all buttons |
; dd = 0 (end of buttons list) |
; ... |
;---------------------------------------------------------------------------- |
; ... |
; bitmaps: |
; dw = bitmap kind (1 = left, 2 = oper, 3 = base) |
; dw = bitmap type (1 = active, 0 = inactive) |
; dd @ bitmap |
; ... etc for all bitmaps |
; dd 0 (end of bitmaps list) |
; ... |
;---------------------------------------------------------------------------- |
; ... |
; bitmap: |
; dd = bitmap width |
; dd = bitmap height |
; ?? = raw bitmap data |
; ... etc for all bitmaps |
; ... |
;============================================================================ |
dd 'SKIN',1,__params__,__buttons__,__bitmaps__ |
struc BITMAPFILEHEADER { |
.bfType dw ? ; WORD |
.bfSize dd ? ; DWORD |
.bfReserved1 dw ? ; WORD |
.bfReserved2 dw ? ; WORD |
.bfOffBits dd ? ; DWORD |
} |
struc BITMAPINFOHEADER { |
.biSize dd ? ; DWORD |
.biWidth dd ? ; LONG |
.biHeight dd ? ; LONG |
.biPlanes dw ? ; WORD |
.biBitCount dw ? ; WORD |
.biCompression dd ? ; DWORD |
.biSizeImage dd ? ; DWORD |
.biXPelsPerMeter dd ? ; LONG |
.biYPelsPerMeter dd ? ; LONG |
.biClrUsed dd ? ; DWORD |
.biClrImportant dd ? ; DWORD |
} |
struc _bmp { |
.h BITMAPFILEHEADER |
.i BITMAPINFOHEADER |
} |
virtual at 0 |
_bmp _bmp |
end virtual |
macro BITMAP _name*,_fname* |
{ |
local w,h,a,r,g,b |
virtual at 0 |
file _fname |
load w dword from _bmp.i.biWidth |
load h dword from _bmp.i.biHeight |
end virtual |
align 4 |
label _name |
.width = w |
.height = h |
dd w,h |
a=54+(w*3+(w mod 4))*(h-1) |
size = $ |
repeat h |
repeat w |
virtual at 0 |
file _fname |
load r from a+0 |
load g from a+1 |
load b from a+2 |
end virtual |
db r,g,b |
a=a+3 |
end repeat |
a=a-w*3*2-(w mod 4) |
end repeat |
} |
macro define_colors name,[col,val] |
{ |
common |
local a,b,c |
forward |
match =binner,col \{ a = val \} |
match =bouter,col \{ b = val \} |
match =bframe,col \{ c = val \} |
common |
name equ a,b,c |
} |
macro SKIN_PARAMS [a] |
{ |
common |
local _height,_margins,_colors,_colors_1,_dtp,_dtp_sz |
__params__: |
forward |
match qq == ww,a |
\{ |
match =height,qq \\{ _height = ww \\} |
match =margins,qq \\{ |
match [q1:q2:q3:q4],ww |
\\\{ |
_margins equ q3,q1,q4,q2 |
\\\} |
\\} |
match =colors =active,qq |
\\{ |
match [q10==q11:q20==q21:q30==q31],ww |
\\\{ |
define_colors _colors,q10,q11,q20,q21,q30,q31 |
\\\} |
\\} |
match =colors =inactive,qq |
\\{ |
match [q10==q11:q20==q21:q30==q31],ww |
\\\{ |
define_colors _colors_1,q10,q11,q20,q21,q30,q31 |
\\\} |
\\} |
match =dtp,qq \\{ _dtp equ ww \\} |
\} |
common |
dd _height |
dw _margins |
dd _colors,_colors_1 |
virtual at 0 |
file _dtp |
_dtp_sz = $ |
end virtual |
dd _dtp_sz |
file _dtp |
} |
macro SKIN_BUTTONS [a] |
{ |
common |
local btn |
__buttons__: |
forward |
match qq == ww,a |
\{ |
btn = 0 |
match =close,qq \\{ btn = 1 \\} |
match =minimize,qq \\{ btn = 2 \\} |
match [q1:q2][q3:q4],ww |
\\{ |
if btn <> 0 |
dd btn |
dw q1,q2,q3,q4 |
end if |
\\} |
\} |
common |
dd 0 |
} |
macro SKIN_BITMAPS [a] |
{ |
common |
local bmp |
__bitmaps__: |
forward |
match qq == ww,a |
\{ |
bmp=-1 |
match qqq =active,qq \\{ bmp = 1 \\} |
match qqq =inactive,qq \\{ bmp = 0 \\} |
match =left qqq,qq |
\\{ |
if bmp >= 0 |
dw 1,bmp |
dd ww |
end if |
\\} |
match =oper qqq,qq |
\\{ |
if bmp >= 0 |
dw 2,bmp |
dd ww |
end if |
\\} |
match =base qqq,qq |
\\{ |
if bmp >= 0 |
dw 3,bmp |
dd ww |
end if |
\\} |
\} |
common |
dd 0 |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;============================================================================ |
; This file should be used to generate skins of new standard |
;============================================================================ |
; skin file structure: |
;---------------------------------------------------------------------------- |
; header: |
; dd 'SKIN' |
; dd = version (1 for now) |
; dd @ params |
; dd @ buttons |
; dd @ bitmaps |
; ... |
;---------------------------------------------------------------------------- |
; NOTE: order of sections listed below is insignificant |
; since they're identified by pointer in above header |
;---------------------------------------------------------------------------- |
; ... |
; params: |
; dd = skin height |
; dw = right margin |
; dw = left margin |
; dw = bottom margin |
; dw = top margin |
; dd = inner line color |
; dd = outer line color |
; dd = frame color |
; dd = dtp file size |
; ?? = dtp file itself |
; ... |
;---------------------------------------------------------------------------- |
; ... |
; buttons: |
; dd = button type (1 = close, 2 = minimize) |
; dw = left button coord (could be negative) |
; dw = top button coord (could be negative) |
; dw = button width |
; dw = button height |
; ... etc for all buttons |
; dd = 0 (end of buttons list) |
; ... |
;---------------------------------------------------------------------------- |
; ... |
; bitmaps: |
; dw = bitmap kind (1 = left, 2 = oper, 3 = base) |
; dw = bitmap type (1 = active, 0 = inactive) |
; dd @ bitmap |
; ... etc for all bitmaps |
; dd 0 (end of bitmaps list) |
; ... |
;---------------------------------------------------------------------------- |
; ... |
; bitmap: |
; dd = bitmap width |
; dd = bitmap height |
; ?? = raw bitmap data |
; ... etc for all bitmaps |
; ... |
;============================================================================ |
dd 'SKIN',1,__params__,__buttons__,__bitmaps__ |
struc BITMAPFILEHEADER { |
.bfType dw ? ; WORD |
.bfSize dd ? ; DWORD |
.bfReserved1 dw ? ; WORD |
.bfReserved2 dw ? ; WORD |
.bfOffBits dd ? ; DWORD |
} |
struc BITMAPINFOHEADER { |
.biSize dd ? ; DWORD |
.biWidth dd ? ; LONG |
.biHeight dd ? ; LONG |
.biPlanes dw ? ; WORD |
.biBitCount dw ? ; WORD |
.biCompression dd ? ; DWORD |
.biSizeImage dd ? ; DWORD |
.biXPelsPerMeter dd ? ; LONG |
.biYPelsPerMeter dd ? ; LONG |
.biClrUsed dd ? ; DWORD |
.biClrImportant dd ? ; DWORD |
} |
struc _bmp { |
.h BITMAPFILEHEADER |
.i BITMAPINFOHEADER |
} |
virtual at 0 |
_bmp _bmp |
end virtual |
macro BITMAP _name*,_fname* |
{ |
local w,h,a,r,g,b |
virtual at 0 |
file _fname |
load w dword from _bmp.i.biWidth |
load h dword from _bmp.i.biHeight |
end virtual |
align 4 |
label _name |
.width = w |
.height = h |
dd w,h |
a=54+(w*3+(w mod 4))*(h-1) |
size = $ |
repeat h |
repeat w |
virtual at 0 |
file _fname |
load r from a+0 |
load g from a+1 |
load b from a+2 |
end virtual |
db r,g,b |
a=a+3 |
end repeat |
a=a-w*3*2-(w mod 4) |
end repeat |
} |
macro define_colors name,[col,val] |
{ |
common |
local a,b,c |
forward |
match =binner,col \{ a = val \} |
match =bouter,col \{ b = val \} |
match =bframe,col \{ c = val \} |
common |
name equ a,b,c |
} |
macro SKIN_PARAMS [a] |
{ |
common |
local _height,_margins,_colors,_colors_1,_dtp,_dtp_sz |
__params__: |
forward |
match qq == ww,a |
\{ |
match =height,qq \\{ _height = ww \\} |
match =margins,qq \\{ |
match [q1:q2:q3:q4],ww |
\\\{ |
_margins equ q3,q1,q4,q2 |
\\\} |
\\} |
match =colors =active,qq |
\\{ |
match [q10==q11:q20==q21:q30==q31],ww |
\\\{ |
define_colors _colors,q10,q11,q20,q21,q30,q31 |
\\\} |
\\} |
match =colors =inactive,qq |
\\{ |
match [q10==q11:q20==q21:q30==q31],ww |
\\\{ |
define_colors _colors_1,q10,q11,q20,q21,q30,q31 |
\\\} |
\\} |
match =dtp,qq \\{ _dtp equ ww \\} |
\} |
common |
dd _height |
dw _margins |
dd _colors,_colors_1 |
virtual at 0 |
file _dtp |
_dtp_sz = $ |
end virtual |
dd _dtp_sz |
file _dtp |
} |
macro SKIN_BUTTONS [a] |
{ |
common |
local btn |
__buttons__: |
forward |
match qq == ww,a |
\{ |
btn = 0 |
match =close,qq \\{ btn = 1 \\} |
match =minimize,qq \\{ btn = 2 \\} |
match [q1:q2][q3:q4],ww |
\\{ |
if btn <> 0 |
dd btn |
dw q1,q2,q3,q4 |
end if |
\\} |
\} |
common |
dd 0 |
} |
macro SKIN_BITMAPS [a] |
{ |
common |
local bmp |
__bitmaps__: |
forward |
match qq == ww,a |
\{ |
bmp=-1 |
match qqq =active,qq \\{ bmp = 1 \\} |
match qqq =inactive,qq \\{ bmp = 0 \\} |
match =left qqq,qq |
\\{ |
if bmp >= 0 |
dw 1,bmp |
dd ww |
end if |
\\} |
match =oper qqq,qq |
\\{ |
if bmp >= 0 |
dw 2,bmp |
dd ww |
end if |
\\} |
match =base qqq,qq |
\\{ |
if bmp >= 0 |
dw 3,bmp |
dd ww |
end if |
\\} |
\} |
common |
dd 0 |
} |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/sound/playnote.inc |
---|
1,166 → 1,166 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; PLAYNOTE.INC version 1.1 22 November 2003 ;; |
;; ;; |
;; Player Notes for Speaker PC ;; |
;; subfunction #55 from function #55 Menuet OS ;; |
;; ;; |
;; Copyright 2003 VaStaNi ;; |
;; vastani@ukr.net ;; |
;; >>>- SIMPLY - QUICKLY - SHORTLY -<<< ;; |
;; ;; |
;; Note: playnote.txt ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
align 4 |
sound_interface: |
cmp eax,ebx ; this is subfunction #55 ? |
jne retFunc55 ; if no then return. |
cmp byte [sound_flag],0 |
jne retFunc55 |
movzx eax, byte [countDelayNote] |
or al, al ; player is busy ? |
jnz retFunc55 ; return counter delay Note |
mov [memAdrNote],esi;edx |
call get_pid |
mov [pidProcessNote],eax |
xor eax, eax ; Ok! EAX = 0 |
retFunc55: |
mov [esp+32], eax ; return value EAX for application |
ret |
iglobal |
align 4 |
kontrOctave dw 0x4742, 0x4342, 0x3F7C, 0x3BEC, 0x388F, 0x3562 |
dw 0x3264, 0x2F8F, 0x2CE4, 0x2A5F, 0x2802, 0x25BF |
memAdrNote dd 0 |
pidProcessNote dd 0 |
slotProcessNote dd 0 |
count_timer_Note dd 1 |
mem8253r42 dw 0 |
countDelayNote db 0 |
endg |
playNote: |
; jmp NotPlayNotes |
mov esi, [memAdrNote] |
or esi, esi ; ESI = 0 ? - OFF Notes Play ? |
jz NotPlayNotes ; if ESI = 0 -> ignore play pocedure |
cmp eax, [count_timer_Note] |
jb NotPlayNotes |
push eax |
inc eax |
mov [count_timer_Note], eax |
mov al, [countDelayNote] |
dec al ; decrement counter Delay for Playing Note |
jz NewLoadNote@Delay |
cmp al, 0xFF ; this is first Note Play ? |
jne NextDelayNote |
;This is FIRST Note, save counter channel 2 chip 8253 |
mov al, 0xB6 ; control byte to timer chip 8253 |
out 0x43, al ; Send it to the control port chip 8253 |
in al, 0x42 ; Read Lower byte counter channel 2 chip 8253 |
mov ah, al ; AH = Lower byte counter channel 2 |
in al, 0x42 ; Read Upper byte counter channel 2 chip 8253 |
mov [mem8253r42], ax ; Save counter channel 2 timer chip 8253 |
NewLoadNote@Delay: |
cld |
; lodsb ; load AL - counter Delay |
call ReadNoteByte |
or al, al ; THE END ? |
jz EndPlayNote |
cmp al, 0x81 |
jnc NoteforOctave |
mov [countDelayNote], al |
; lodsw ; load AX - counter for Note! |
call ReadNoteByte |
mov ah,al |
call ReadNoteByte |
xchg al,ah |
jmp pokeNote |
EndPlayNote: ; THE END Play Notes! |
in al, 0x61 ; Get contents of system port B chip 8255 |
and al, 0xFC ; Turn OFF timer and speaker |
out 0x61, al ; Send out new values to port B chip 8255 |
mov ax, [mem8253r42] ; memorize counter channel 2 timer chip 8253 |
xchg al, ah ; reverse byte in word |
out 0x42, al ; restore Lower byte counter channel 2 |
mov al, ah ; AL = Upper byte counter channel 2 |
out 0x42, al ; restore Upper byte channel 2 |
xor eax, eax ; EAX = 0 |
mov [memAdrNote], eax ; clear header control Delay-Note string |
NextDelayNote: |
mov [countDelayNote], al ; save new counter delay Note |
pop eax |
NotPlayNotes: |
RET |
NoteforOctave: |
sub al, 0x81 ; correction value for delay Note |
mov [countDelayNote], al ; save counter delay this new Note |
; lodsb ; load pack control code |
call ReadNoteByte |
cmp al, 0xFF ; this is PAUSE ? |
jne packCode ; no, this is PACK CODE |
in al, 0x61 ; Get contents of system port B chip 8255 |
and al, 0xFC ; Turn OFF timer and speaker |
out 0x61, al ; Send out new values to port B chip 8255 |
jmp saveESI |
packCode: |
mov cl, al ; save code |
and al, 0xF ; clear upper bits |
dec al ; correction |
add al, al ; transform number to offset constant |
movsx eax, al ; EAX - offset |
add eax, dword kontrOctave ; EAX - address from constant |
mov ax, [eax] ; read constant |
shr cl, 4 ; transform for number Octave |
shr ax, cl ; calculate from Note this Octave! |
pokeNote: |
out 0x42, al ; Lower byte Out to channel 2 timer chip 8253 |
mov al, ah |
out 0x42, al ; Upper byte Out to channel 2 timer chip 8253 |
in al, 0x61 ; Get contents of system port B chip 8255 |
or al, 3 ; Turn ON timer and speaker |
out 0x61, al ; Send out new values to port B chip 8255 |
saveESI: |
; mov [memAdrNote], esi ; save new header control Delay-Note string |
pop eax |
RET |
ReadNoteByte: |
;result: |
; al - note |
push eax |
push ecx |
push edx |
push esi |
mov eax,[pidProcessNote] |
call pid_to_slot |
test eax,eax |
jz .failed |
lea ecx,[esp+12] |
mov edx,1 |
mov esi,[memAdrNote] |
inc [memAdrNote] |
call read_process_memory |
.failed: |
pop esi |
pop edx |
pop ecx |
pop eax |
ret |
;------------------- END CODE ------------------- |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; PLAYNOTE.INC version 1.1 22 November 2003 ;; |
;; ;; |
;; Player Notes for Speaker PC ;; |
;; subfunction #55 from function #55 Menuet OS ;; |
;; ;; |
;; Copyright 2003 VaStaNi ;; |
;; vastani@ukr.net ;; |
;; >>>- SIMPLY - QUICKLY - SHORTLY -<<< ;; |
;; ;; |
;; Note: playnote.txt ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
align 4 |
sound_interface: |
cmp eax, ebx ; this is subfunction #55 ? |
jne retFunc55 ; if no then return. |
cmp byte [sound_flag], 0 |
jne retFunc55 |
movzx eax, byte [countDelayNote] |
or al, al ; player is busy ? |
jnz retFunc55 ; return counter delay Note |
mov [memAdrNote], esi;edx |
call get_pid |
mov [pidProcessNote], eax |
xor eax, eax ; Ok! EAX = 0 |
retFunc55: |
mov [esp+32], eax ; return value EAX for application |
ret |
iglobal |
align 4 |
kontrOctave dw 0x4742, 0x4342, 0x3F7C, 0x3BEC, 0x388F, 0x3562 |
dw 0x3264, 0x2F8F, 0x2CE4, 0x2A5F, 0x2802, 0x25BF |
memAdrNote dd 0 |
pidProcessNote dd 0 |
slotProcessNote dd 0 |
count_timer_Note dd 1 |
mem8253r42 dw 0 |
countDelayNote db 0 |
endg |
playNote: |
; jmp NotPlayNotes |
mov esi, [memAdrNote] |
or esi, esi ; ESI = 0 ? - OFF Notes Play ? |
jz NotPlayNotes ; if ESI = 0 -> ignore play pocedure |
cmp eax, [count_timer_Note] |
jb NotPlayNotes |
push eax |
inc eax |
mov [count_timer_Note], eax |
mov al, [countDelayNote] |
dec al ; decrement counter Delay for Playing Note |
jz NewLoadNote@Delay |
cmp al, 0xFF ; this is first Note Play ? |
jne NextDelayNote |
;This is FIRST Note, save counter channel 2 chip 8253 |
mov al, 0xB6 ; control byte to timer chip 8253 |
out 0x43, al ; Send it to the control port chip 8253 |
in al, 0x42 ; Read Lower byte counter channel 2 chip 8253 |
mov ah, al ; AH = Lower byte counter channel 2 |
in al, 0x42 ; Read Upper byte counter channel 2 chip 8253 |
mov [mem8253r42], ax ; Save counter channel 2 timer chip 8253 |
NewLoadNote@Delay: |
cld |
; lodsb ; load AL - counter Delay |
call ReadNoteByte |
or al, al ; THE END ? |
jz EndPlayNote |
cmp al, 0x81 |
jnc NoteforOctave |
mov [countDelayNote], al |
; lodsw ; load AX - counter for Note! |
call ReadNoteByte |
mov ah, al |
call ReadNoteByte |
xchg al, ah |
jmp pokeNote |
EndPlayNote: ; THE END Play Notes! |
in al, 0x61 ; Get contents of system port B chip 8255 |
and al, 0xFC ; Turn OFF timer and speaker |
out 0x61, al ; Send out new values to port B chip 8255 |
mov ax, [mem8253r42] ; memorize counter channel 2 timer chip 8253 |
xchg al, ah ; reverse byte in word |
out 0x42, al ; restore Lower byte counter channel 2 |
mov al, ah ; AL = Upper byte counter channel 2 |
out 0x42, al ; restore Upper byte channel 2 |
xor eax, eax ; EAX = 0 |
mov [memAdrNote], eax; clear header control Delay-Note string |
NextDelayNote: |
mov [countDelayNote], al; save new counter delay Note |
pop eax |
NotPlayNotes: |
RET |
NoteforOctave: |
sub al, 0x81 ; correction value for delay Note |
mov [countDelayNote], al; save counter delay this new Note |
; lodsb ; load pack control code |
call ReadNoteByte |
cmp al, 0xFF ; this is PAUSE ? |
jne packCode ; no, this is PACK CODE |
in al, 0x61 ; Get contents of system port B chip 8255 |
and al, 0xFC ; Turn OFF timer and speaker |
out 0x61, al ; Send out new values to port B chip 8255 |
jmp saveESI |
packCode: |
mov cl, al ; save code |
and al, 0xF ; clear upper bits |
dec al ; correction |
add al, al ; transform number to offset constant |
movsx eax, al ; EAX - offset |
add eax, dword kontrOctave; EAX - address from constant |
mov ax, [eax] ; read constant |
shr cl, 4 ; transform for number Octave |
shr ax, cl ; calculate from Note this Octave! |
pokeNote: |
out 0x42, al ; Lower byte Out to channel 2 timer chip 8253 |
mov al, ah |
out 0x42, al ; Upper byte Out to channel 2 timer chip 8253 |
in al, 0x61 ; Get contents of system port B chip 8255 |
or al, 3 ; Turn ON timer and speaker |
out 0x61, al ; Send out new values to port B chip 8255 |
saveESI: |
; mov [memAdrNote], esi ; save new header control Delay-Note string |
pop eax |
RET |
ReadNoteByte: |
;result: |
; al - note |
push eax |
push ecx |
push edx |
push esi |
mov eax, [pidProcessNote] |
call pid_to_slot |
test eax, eax |
jz .failed |
lea ecx, [esp+12] |
mov edx, 1 |
mov esi, [memAdrNote] |
inc [memAdrNote] |
call read_process_memory |
.failed: |
pop esi |
pop edx |
pop ecx |
pop eax |
ret |
;------------------- END CODE ------------------- |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/unpacker.inc |
---|
1,527 → 1,528 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; void __stdcall unpack(void* packed_data, void* unpacked_data); |
unpack: |
pushad |
mov esi, [esp+32+4] |
mov edi, [esp+32+8] |
mov eax, [esi+8] |
and al, 0xC0 |
cmp al, 0xC0 |
jz .failed |
mov eax, [esi+8] |
push eax |
add esi, 12 |
and al, not 0xC0 |
dec al |
jz .lzma |
.failed: |
pop eax |
popad |
ret 8 |
.lzma: |
call .lzma_unpack |
.common: |
pop eax |
test al, 0x80 |
jnz .ctr1 |
test al, 0x40 |
jz .ok |
lodsd |
mov ecx, eax |
jecxz .ok |
mov dl, [esi] |
mov esi, [esp+32+8] |
.c1: |
lodsb |
sub al, 0E8h |
cmp al, 1 |
ja .c1 |
cmp byte [esi], dl |
jnz .c1 |
lodsd |
; "bswap eax" is not supported on i386 |
shr ax, 8 |
ror eax, 16 |
xchg al, ah |
sub eax, esi |
add eax, [esp+32+8] |
mov [esi-4], eax |
loop .c1 |
.ok: |
popad |
ret 8 |
.ctr1: |
lodsd |
mov ecx, eax |
jecxz .ok |
mov dl, [esi] |
mov esi, [esp+32+8] |
.c2: |
lodsb |
@@: |
cmp al, 0xF |
jnz .f |
lodsb |
cmp al, 80h |
jb @b |
cmp al, 90h |
jb @f |
.f: |
sub al, 0E8h |
cmp al, 1 |
ja .c2 |
@@: |
cmp byte [esi], dl |
jnz .c2 |
lodsd |
shr ax, 8 |
ror eax, 16 |
xchg al, ah |
sub eax, esi |
add eax, [esp+32+8] |
mov [esi-4], eax |
loop .c2 |
jmp .ok |
.lzma_unpack: |
.pb = 2 ; pos state bits |
.lp = 0 ; literal pos state bits |
.lc = 3 ; literal context bits |
.posStateMask = ((1 shl .pb)-1) |
.literalPosMask = ((1 shl .lp)-1) |
.kNumPosBitsMax = 4 |
.kNumPosStatesMax = (1 shl .kNumPosBitsMax) |
.kLenNumLowBits = 3 |
.kLenNumLowSymbols = (1 shl .kLenNumLowBits) |
.kLenNumMidBits = 3 |
.kLenNumMidSymbols = (1 shl .kLenNumMidBits) |
.kLenNumHighBits = 8 |
.kLenNumHighSymbols = (1 shl .kLenNumHighBits) |
.LenChoice = 0 |
.LenChoice2 = 1 |
.LenLow = 2 |
.LenMid = (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits)) |
.LenHigh = (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits)) |
.kNumLenProbs = (.LenHigh + .kLenNumHighSymbols) |
.kNumStates = 12 |
.kNumLitStates = 7 |
.kStartPosModelIndex = 4 |
.kEndPosModelIndex = 14 |
.kNumFullDistances = (1 shl (.kEndPosModelIndex/2)) |
.kNumPosSlotBits = 6 |
.kNumLenToPosStates = 4 |
.kNumAlignBits = 4 |
.kAlignTableSize = (1 shl .kNumAlignBits) |
.kMatchMinLen = 2 |
.IsMatch = 0 |
.IsRep = (.IsMatch + (.kNumStates shl .kNumPosBitsMax)) |
.IsRepG0 = (.IsRep + .kNumStates) |
.IsRepG1 = (.IsRepG0 + .kNumStates) |
.IsRepG2 = (.IsRepG1 + .kNumStates) |
.IsRep0Long = (.IsRepG2 + .kNumStates) |
.PosSlot = (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax)) |
.SpecPos = (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits)) |
.Align_ = (.SpecPos + .kNumFullDistances - .kEndPosModelIndex) |
.Lencoder = (.Align_ + .kAlignTableSize) |
.RepLencoder = (.Lencoder + .kNumLenProbs) |
.Literal = (.RepLencoder + .kNumLenProbs) |
.LZMA_BASE_SIZE = 1846 ; must be ==Literal |
.LZMA_LIT_SIZE = 768 |
.kNumTopBits = 24 |
.kTopValue = (1 shl .kNumTopBits) |
.kNumBitModelTotalBits = 11 |
.kBitModelTotal = (1 shl .kNumBitModelTotalBits) |
.kNumMoveBits = 5 |
push edi |
; int state=0; |
xor ebx, ebx |
mov [.previousByte], bl |
; unsigned rep0=1,rep1=1,rep2=1,rep3=1; |
mov eax, 1 |
mov edi, .rep0 |
stosd |
stosd |
stosd |
stosd |
; int len=0; |
; result=0; |
mov ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp)) |
mov eax, .kBitModelTotal/2 |
mov edi, [.p] |
rep stosd |
; RangeDecoderInit |
; rd->ExtraBytes = 0 |
; rd->Buffer = stream |
; rd->BufferLim = stream+bufferSize |
; rd->Range = 0xFFFFFFFF |
pop edi |
mov ebp, [esi-8] ; dest_length |
add ebp, edi ; ebp = destination limit |
lodsd |
; rd->code_ = eax |
mov [.code_], eax |
or [.range], -1 |
.main_loop: |
cmp edi, ebp |
jae .main_loop_done |
mov edx, edi |
and edx, .posStateMask |
mov eax, ebx |
shl eax, .kNumPosBitsMax+2 |
lea eax, [.IsMatch*4 + eax + edx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
jc .1 |
movzx eax, [.previousByte] |
if .literalPosMask |
mov ah, dl |
and ah, .literalPosMask |
end if |
shr eax, 8-.lc |
imul eax, .LZMA_LIT_SIZE*4 |
add eax, .Literal*4 |
add eax, [.p] |
cmp ebx, .kNumLitStates |
jb .literal |
xor edx, edx |
sub edx, [.rep0] |
mov dl, [edi + edx] |
call .LzmaLiteralDecodeMatch |
jmp @f |
.literal: |
call .LzmaLiteralDecode |
@@: |
mov [.previousByte], al |
stosb |
mov al, bl |
cmp bl, 4 |
jb @f |
mov al, 3 |
cmp bl, 10 |
jb @f |
mov al, 6 |
@@: sub bl, al |
jmp .main_loop |
.1: |
lea eax, [.IsRep*4 + ebx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
jnc .10 |
lea eax, [.IsRepG0*4 + ebx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
jc .111 |
mov eax, ebx |
shl eax, .kNumPosBitsMax+2 |
lea eax, [.IsRep0Long*4 + eax + edx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
jc .1101 |
cmp bl, 7 |
setae bl |
lea ebx, [9 + ebx + ebx] |
xor edx, edx |
sub edx, [.rep0] |
mov al, [edi + edx] |
stosb |
mov [.previousByte], al |
jmp .main_loop |
.111: |
lea eax, [.IsRepG1*4 + ebx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
mov eax, [.rep1] |
jnc .l3 |
.l1: |
lea eax, [.IsRepG2*4 + ebx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
mov eax, [.rep2] |
jnc .l2 |
xchg [.rep3], eax |
.l2: |
push [.rep1] |
pop [.rep2] |
.l3: |
xchg eax, [.rep0] |
mov [.rep1], eax |
.1101: |
mov eax, .RepLencoder*4 |
add eax, [.p] |
call .LzmaLenDecode |
cmp bl, 7 |
setc bl |
adc bl, bl |
xor bl, 3 |
add bl, 8 |
jmp .repmovsb |
.10: |
mov eax, [.rep0] |
xchg eax, [.rep1] |
xchg eax, [.rep2] |
xchg eax, [.rep3] |
cmp bl, 7 |
setc bl |
adc bl, bl |
xor bl, 3 |
add bl, 7 |
mov eax, .Lencoder*4 |
add eax, [.p] |
call .LzmaLenDecode |
mov eax, .kNumLenToPosStates-1 |
cmp eax, ecx |
jb @f |
mov eax, ecx |
@@: |
push ecx |
mov ecx, .kNumPosSlotBits |
shl eax, cl |
shl eax, 2 |
add eax, .PosSlot*4 |
add eax, [.p] |
call .RangeDecoderBitTreeDecode |
mov [.rep0], ecx |
cmp ecx, .kStartPosModelIndex |
jb .l6 |
push ecx |
mov eax, ecx |
and eax, 1 |
shr ecx, 1 |
or eax, 2 |
dec ecx |
shl eax, cl |
mov [.rep0], eax |
pop edx |
cmp edx, .kEndPosModelIndex |
jae .l5 |
sub eax, edx |
shl eax, 2 |
add eax, (.SpecPos - 1)*4 |
add eax, [.p] |
call .RangeDecoderReverseBitTreeDecode |
add [.rep0], ecx |
jmp .l6 |
.l5: |
sub ecx, .kNumAlignBits |
call .RangeDecoderDecodeDirectBits |
mov ecx, .kNumAlignBits |
shl eax, cl |
add [.rep0], eax |
mov eax, .Align_*4 |
add eax, [.p] |
call .RangeDecoderReverseBitTreeDecode |
add [.rep0], ecx |
.l6: |
pop ecx |
inc [.rep0] |
jz .main_loop_done |
.repmovsb: |
add ecx, .kMatchMinLen |
push esi |
mov esi, edi |
sub esi, [.rep0] |
rep movsb |
pop esi |
mov al, [edi-1] |
mov [.previousByte], al |
jmp .main_loop |
.main_loop_done: |
ret |
.RangeDecoderBitDecode: |
; in: eax->prob |
; out: CF=bit; destroys eax |
push edx |
mov edx, [.range] |
shr edx, .kNumBitModelTotalBits |
imul edx, [eax] |
cmp [.code_], edx |
jae .ae |
mov [.range], edx |
mov edx, .kBitModelTotal |
sub edx, [eax] |
shr edx, .kNumMoveBits |
add [eax], edx |
clc |
.n: |
lahf |
cmp [.range], .kTopValue |
jae @f |
shl [.range], 8 |
shl [.code_], 8 |
lodsb |
mov byte [.code_], al |
@@: |
sahf |
pop edx |
ret |
.ae: |
sub [.range], edx |
sub [.code_], edx |
mov edx, [eax] |
shr edx, .kNumMoveBits |
sub [eax], edx |
stc |
jmp .n |
.RangeDecoderDecodeDirectBits: |
; in: ecx=numTotalBits |
; out: eax=result; destroys edx |
xor eax, eax |
.l: |
shr [.range], 1 |
shl eax, 1 |
mov edx, [.code_] |
sub edx, [.range] |
jb @f |
mov [.code_], edx |
or eax, 1 |
@@: |
cmp [.range], .kTopValue |
jae @f |
shl [.range], 8 |
shl [.code_], 8 |
push eax |
lodsb |
mov byte [.code_], al |
pop eax |
@@: |
loop .l |
ret |
.LzmaLiteralDecode: |
; in: eax->probs |
; out: al=byte; destroys edx |
push ecx |
mov ecx, 1 |
@@: |
push eax |
lea eax, [eax+ecx*4] |
call .RangeDecoderBitDecode |
pop eax |
adc cl, cl |
jnc @b |
.LzmaLiteralDecode.ret: |
mov al, cl |
pop ecx |
ret |
.LzmaLiteralDecodeMatch: |
; in: eax->probs, dl=matchByte |
; out: al=byte; destroys edx |
push ecx |
mov ecx, 1 |
.LzmaLiteralDecodeMatch.1: |
add dl, dl |
setc ch |
push eax |
lea eax, [eax+ecx*4+0x100*4] |
call .RangeDecoderBitDecode |
pop eax |
adc cl, cl |
jc .LzmaLiteralDecode.ret |
xor ch, cl |
test ch, 1 |
mov ch, 0 |
jnz @b |
jmp .LzmaLiteralDecodeMatch.1 |
.LzmaLenDecode: |
; in: eax->prob, edx=posState |
; out: ecx=len |
push eax |
add eax, .LenChoice*4 |
call .RangeDecoderBitDecode |
pop eax |
jnc .0 |
push eax |
add eax, .LenChoice2*4 |
call .RangeDecoderBitDecode |
pop eax |
jc @f |
mov ecx, .kLenNumMidBits |
shl edx, cl |
lea eax, [eax + .LenMid*4 + edx*4] |
call .RangeDecoderBitTreeDecode |
add ecx, .kLenNumLowSymbols |
ret |
@@: |
add eax, .LenHigh*4 |
mov ecx, .kLenNumHighBits |
call .RangeDecoderBitTreeDecode |
add ecx, .kLenNumLowSymbols + .kLenNumMidSymbols |
ret |
.0: |
mov ecx, .kLenNumLowBits |
shl edx, cl |
lea eax, [eax + .LenLow*4 + edx*4] |
.RangeDecoderBitTreeDecode: |
; in: eax->probs,ecx=numLevels |
; out: ecx=length; destroys edx |
push ebx |
mov edx, 1 |
mov ebx, edx |
@@: |
push eax |
lea eax, [eax+edx*4] |
call .RangeDecoderBitDecode |
pop eax |
adc dl, dl |
add bl, bl |
loop @b |
sub dl, bl |
pop ebx |
mov ecx, edx |
ret |
.RangeDecoderReverseBitTreeDecode: |
; in: eax->probs,ecx=numLevels |
; out: ecx=length; destroys edx |
push ebx ecx |
mov edx, 1 |
xor ebx, ebx |
@@: |
push eax |
lea eax, [eax+edx*4] |
call .RangeDecoderBitDecode |
lahf |
adc edx, edx |
sahf |
rcr ebx, 1 |
pop eax |
loop @b |
pop ecx |
rol ebx, cl |
mov ecx, ebx |
pop ebx |
ret |
uglobal |
align 4 |
;unpack.p rd unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp)) |
unpack.p dd ? |
unpack.code_ dd ? |
unpack.range dd ? |
unpack.rep0 dd ? |
unpack.rep1 dd ? |
unpack.rep2 dd ? |
unpack.rep3 dd ? |
unpack.previousByte db ? |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; void __stdcall unpack(void* packed_data, void* unpacked_data); |
unpack: |
pushad |
mov esi, [esp+32+4] |
mov edi, [esp+32+8] |
mov eax, [esi+8] |
and al, 0xC0 |
cmp al, 0xC0 |
jz .failed |
mov eax, [esi+8] |
push eax |
add esi, 12 |
and al, not 0xC0 |
dec al |
jz .lzma |
.failed: |
pop eax |
popad |
ret 8 |
.lzma: |
call .lzma_unpack |
.common: |
pop eax |
test al, 0x80 |
jnz .ctr1 |
test al, 0x40 |
jz .ok |
lodsd |
mov ecx, eax |
jecxz .ok |
mov dl, [esi] |
mov esi, [esp+32+8] |
.c1: |
lodsb |
sub al, 0E8h |
cmp al, 1 |
ja .c1 |
cmp byte [esi], dl |
jnz .c1 |
lodsd |
; "bswap eax" is not supported on i386 |
shr ax, 8 |
ror eax, 16 |
xchg al, ah |
sub eax, esi |
add eax, [esp+32+8] |
mov [esi-4], eax |
loop .c1 |
.ok: |
popad |
ret 8 |
.ctr1: |
lodsd |
mov ecx, eax |
jecxz .ok |
mov dl, [esi] |
mov esi, [esp+32+8] |
.c2: |
lodsb |
@@: |
cmp al, 0xF |
jnz .f |
lodsb |
cmp al, 80h |
jb @b |
cmp al, 90h |
jb @f |
.f: |
sub al, 0E8h |
cmp al, 1 |
ja .c2 |
@@: |
cmp byte [esi], dl |
jnz .c2 |
lodsd |
shr ax, 8 |
ror eax, 16 |
xchg al, ah |
sub eax, esi |
add eax, [esp+32+8] |
mov [esi-4], eax |
loop .c2 |
jmp .ok |
.lzma_unpack: |
.pb = 2 ; pos state bits |
.lp = 0 ; literal pos state bits |
.lc = 3 ; literal context bits |
.posStateMask = ((1 shl .pb)-1) |
.literalPosMask = ((1 shl .lp)-1) |
.kNumPosBitsMax = 4 |
.kNumPosStatesMax = (1 shl .kNumPosBitsMax) |
.kLenNumLowBits = 3 |
.kLenNumLowSymbols = (1 shl .kLenNumLowBits) |
.kLenNumMidBits = 3 |
.kLenNumMidSymbols = (1 shl .kLenNumMidBits) |
.kLenNumHighBits = 8 |
.kLenNumHighSymbols = (1 shl .kLenNumHighBits) |
.LenChoice = 0 |
.LenChoice2 = 1 |
.LenLow = 2 |
.LenMid = (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits)) |
.LenHigh = (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits)) |
.kNumLenProbs = (.LenHigh + .kLenNumHighSymbols) |
.kNumStates = 12 |
.kNumLitStates = 7 |
.kStartPosModelIndex = 4 |
.kEndPosModelIndex = 14 |
.kNumFullDistances = (1 shl (.kEndPosModelIndex/2)) |
.kNumPosSlotBits = 6 |
.kNumLenToPosStates = 4 |
.kNumAlignBits = 4 |
.kAlignTableSize = (1 shl .kNumAlignBits) |
.kMatchMinLen = 2 |
.IsMatch = 0 |
.IsRep = (.IsMatch + (.kNumStates shl .kNumPosBitsMax)) |
.IsRepG0 = (.IsRep + .kNumStates) |
.IsRepG1 = (.IsRepG0 + .kNumStates) |
.IsRepG2 = (.IsRepG1 + .kNumStates) |
.IsRep0Long = (.IsRepG2 + .kNumStates) |
.PosSlot = (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax)) |
.SpecPos = (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits)) |
.Align_ = (.SpecPos + .kNumFullDistances - .kEndPosModelIndex) |
.Lencoder = (.Align_ + .kAlignTableSize) |
.RepLencoder = (.Lencoder + .kNumLenProbs) |
.Literal = (.RepLencoder + .kNumLenProbs) |
.LZMA_BASE_SIZE = 1846 ; must be ==Literal |
.LZMA_LIT_SIZE = 768 |
.kNumTopBits = 24 |
.kTopValue = (1 shl .kNumTopBits) |
.kNumBitModelTotalBits = 11 |
.kBitModelTotal = (1 shl .kNumBitModelTotalBits) |
.kNumMoveBits = 5 |
push edi |
; int state=0; |
xor ebx, ebx |
mov [.previousByte], bl |
; unsigned rep0=1,rep1=1,rep2=1,rep3=1; |
mov eax, 1 |
mov edi, .rep0 |
stosd |
stosd |
stosd |
stosd |
; int len=0; |
; result=0; |
mov ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp)) |
mov eax, .kBitModelTotal/2 |
mov edi, [.p] |
rep stosd |
; RangeDecoderInit |
; rd->ExtraBytes = 0 |
; rd->Buffer = stream |
; rd->BufferLim = stream+bufferSize |
; rd->Range = 0xFFFFFFFF |
pop edi |
mov ebp, [esi-8] ; dest_length |
add ebp, edi ; ebp = destination limit |
lodsd |
; rd->code_ = eax |
mov [.code_], eax |
or [.range], -1 |
.main_loop: |
cmp edi, ebp |
jae .main_loop_done |
mov edx, edi |
and edx, .posStateMask |
mov eax, ebx |
shl eax, .kNumPosBitsMax+2 |
lea eax, [.IsMatch*4 + eax + edx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
jc .1 |
movzx eax, [.previousByte] |
if .literalPosMask |
mov ah, dl |
and ah, .literalPosMask |
end if |
shr eax, 8-.lc |
imul eax, .LZMA_LIT_SIZE*4 |
add eax, .Literal*4 |
add eax, [.p] |
cmp ebx, .kNumLitStates |
jb .literal |
xor edx, edx |
sub edx, [.rep0] |
mov dl, [edi + edx] |
call .LzmaLiteralDecodeMatch |
jmp @f |
.literal: |
call .LzmaLiteralDecode |
@@: |
mov [.previousByte], al |
stosb |
mov al, bl |
cmp bl, 4 |
jb @f |
mov al, 3 |
cmp bl, 10 |
jb @f |
mov al, 6 |
@@: |
sub bl, al |
jmp .main_loop |
.1: |
lea eax, [.IsRep*4 + ebx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
jnc .10 |
lea eax, [.IsRepG0*4 + ebx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
jc .111 |
mov eax, ebx |
shl eax, .kNumPosBitsMax+2 |
lea eax, [.IsRep0Long*4 + eax + edx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
jc .1101 |
cmp bl, 7 |
setae bl |
lea ebx, [9 + ebx + ebx] |
xor edx, edx |
sub edx, [.rep0] |
mov al, [edi + edx] |
stosb |
mov [.previousByte], al |
jmp .main_loop |
.111: |
lea eax, [.IsRepG1*4 + ebx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
mov eax, [.rep1] |
jnc .l3 |
.l1: |
lea eax, [.IsRepG2*4 + ebx*4] |
add eax, [.p] |
call .RangeDecoderBitDecode |
mov eax, [.rep2] |
jnc .l2 |
xchg [.rep3], eax |
.l2: |
push [.rep1] |
pop [.rep2] |
.l3: |
xchg eax, [.rep0] |
mov [.rep1], eax |
.1101: |
mov eax, .RepLencoder*4 |
add eax, [.p] |
call .LzmaLenDecode |
cmp bl, 7 |
setc bl |
adc bl, bl |
xor bl, 3 |
add bl, 8 |
jmp .repmovsb |
.10: |
mov eax, [.rep0] |
xchg eax, [.rep1] |
xchg eax, [.rep2] |
xchg eax, [.rep3] |
cmp bl, 7 |
setc bl |
adc bl, bl |
xor bl, 3 |
add bl, 7 |
mov eax, .Lencoder*4 |
add eax, [.p] |
call .LzmaLenDecode |
mov eax, .kNumLenToPosStates-1 |
cmp eax, ecx |
jb @f |
mov eax, ecx |
@@: |
push ecx |
mov ecx, .kNumPosSlotBits |
shl eax, cl |
shl eax, 2 |
add eax, .PosSlot*4 |
add eax, [.p] |
call .RangeDecoderBitTreeDecode |
mov [.rep0], ecx |
cmp ecx, .kStartPosModelIndex |
jb .l6 |
push ecx |
mov eax, ecx |
and eax, 1 |
shr ecx, 1 |
or eax, 2 |
dec ecx |
shl eax, cl |
mov [.rep0], eax |
pop edx |
cmp edx, .kEndPosModelIndex |
jae .l5 |
sub eax, edx |
shl eax, 2 |
add eax, (.SpecPos - 1)*4 |
add eax, [.p] |
call .RangeDecoderReverseBitTreeDecode |
add [.rep0], ecx |
jmp .l6 |
.l5: |
sub ecx, .kNumAlignBits |
call .RangeDecoderDecodeDirectBits |
mov ecx, .kNumAlignBits |
shl eax, cl |
add [.rep0], eax |
mov eax, .Align_*4 |
add eax, [.p] |
call .RangeDecoderReverseBitTreeDecode |
add [.rep0], ecx |
.l6: |
pop ecx |
inc [.rep0] |
jz .main_loop_done |
.repmovsb: |
add ecx, .kMatchMinLen |
push esi |
mov esi, edi |
sub esi, [.rep0] |
rep movsb |
pop esi |
mov al, [edi-1] |
mov [.previousByte], al |
jmp .main_loop |
.main_loop_done: |
ret |
.RangeDecoderBitDecode: |
; in: eax->prob |
; out: CF=bit; destroys eax |
push edx |
mov edx, [.range] |
shr edx, .kNumBitModelTotalBits |
imul edx, [eax] |
cmp [.code_], edx |
jae .ae |
mov [.range], edx |
mov edx, .kBitModelTotal |
sub edx, [eax] |
shr edx, .kNumMoveBits |
add [eax], edx |
clc |
.n: |
lahf |
cmp [.range], .kTopValue |
jae @f |
shl [.range], 8 |
shl [.code_], 8 |
lodsb |
mov byte [.code_], al |
@@: |
sahf |
pop edx |
ret |
.ae: |
sub [.range], edx |
sub [.code_], edx |
mov edx, [eax] |
shr edx, .kNumMoveBits |
sub [eax], edx |
stc |
jmp .n |
.RangeDecoderDecodeDirectBits: |
; in: ecx=numTotalBits |
; out: eax=result; destroys edx |
xor eax, eax |
.l: |
shr [.range], 1 |
shl eax, 1 |
mov edx, [.code_] |
sub edx, [.range] |
jb @f |
mov [.code_], edx |
or eax, 1 |
@@: |
cmp [.range], .kTopValue |
jae @f |
shl [.range], 8 |
shl [.code_], 8 |
push eax |
lodsb |
mov byte [.code_], al |
pop eax |
@@: |
loop .l |
ret |
.LzmaLiteralDecode: |
; in: eax->probs |
; out: al=byte; destroys edx |
push ecx |
mov ecx, 1 |
@@: |
push eax |
lea eax, [eax+ecx*4] |
call .RangeDecoderBitDecode |
pop eax |
adc cl, cl |
jnc @b |
.LzmaLiteralDecode.ret: |
mov al, cl |
pop ecx |
ret |
.LzmaLiteralDecodeMatch: |
; in: eax->probs, dl=matchByte |
; out: al=byte; destroys edx |
push ecx |
mov ecx, 1 |
.LzmaLiteralDecodeMatch.1: |
add dl, dl |
setc ch |
push eax |
lea eax, [eax+ecx*4+0x100*4] |
call .RangeDecoderBitDecode |
pop eax |
adc cl, cl |
jc .LzmaLiteralDecode.ret |
xor ch, cl |
test ch, 1 |
mov ch, 0 |
jnz @b |
jmp .LzmaLiteralDecodeMatch.1 |
.LzmaLenDecode: |
; in: eax->prob, edx=posState |
; out: ecx=len |
push eax |
add eax, .LenChoice*4 |
call .RangeDecoderBitDecode |
pop eax |
jnc .0 |
push eax |
add eax, .LenChoice2*4 |
call .RangeDecoderBitDecode |
pop eax |
jc @f |
mov ecx, .kLenNumMidBits |
shl edx, cl |
lea eax, [eax + .LenMid*4 + edx*4] |
call .RangeDecoderBitTreeDecode |
add ecx, .kLenNumLowSymbols |
ret |
@@: |
add eax, .LenHigh*4 |
mov ecx, .kLenNumHighBits |
call .RangeDecoderBitTreeDecode |
add ecx, .kLenNumLowSymbols + .kLenNumMidSymbols |
ret |
.0: |
mov ecx, .kLenNumLowBits |
shl edx, cl |
lea eax, [eax + .LenLow*4 + edx*4] |
.RangeDecoderBitTreeDecode: |
; in: eax->probs,ecx=numLevels |
; out: ecx=length; destroys edx |
push ebx |
mov edx, 1 |
mov ebx, edx |
@@: |
push eax |
lea eax, [eax+edx*4] |
call .RangeDecoderBitDecode |
pop eax |
adc dl, dl |
add bl, bl |
loop @b |
sub dl, bl |
pop ebx |
mov ecx, edx |
ret |
.RangeDecoderReverseBitTreeDecode: |
; in: eax->probs,ecx=numLevels |
; out: ecx=length; destroys edx |
push ebx ecx |
mov edx, 1 |
xor ebx, ebx |
@@: |
push eax |
lea eax, [eax+edx*4] |
call .RangeDecoderBitDecode |
lahf |
adc edx, edx |
sahf |
rcr ebx, 1 |
pop eax |
loop @b |
pop ecx |
rol ebx, cl |
mov ecx, ebx |
pop ebx |
ret |
uglobal |
align 4 |
;unpack.p rd unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp)) |
unpack.p dd ? |
unpack.code_ dd ? |
unpack.range dd ? |
unpack.rep0 dd ? |
unpack.rep1 dd ? |
unpack.rep2 dd ? |
unpack.rep3 dd ? |
unpack.previousByte db ? |
endg |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/video/blitter.inc |
---|
34,128 → 34,128 |
align 4 |
__L1OutCode: |
push ebx |
mov ebx, 8 |
cmp edx, [eax] |
jl .L2 |
xor ebx, ebx |
cmp edx, [eax+8] |
setg bl |
sal ebx, 2 |
push ebx |
mov ebx, 8 |
cmp edx, [eax] |
jl .L2 |
xor ebx, ebx |
cmp edx, [eax+8] |
setg bl |
sal ebx, 2 |
.L2: |
cmp ecx, [eax+4] |
jge .L3 |
or ebx, 1 |
jmp .L4 |
cmp ecx, [eax+4] |
jge .L3 |
or ebx, 1 |
jmp .L4 |
.L3: |
cmp ecx, [eax+12] |
jle .L4 |
or ebx, 2 |
cmp ecx, [eax+12] |
jle .L4 |
or ebx, 2 |
.L4: |
mov eax, ebx |
pop ebx |
mov eax, ebx |
pop ebx |
ret |
align 4 |
block_clip: |
push ebp |
push edi |
push esi |
push ebx |
sub esp, 4 |
push ebp |
push edi |
push esi |
push ebx |
sub esp, 4 |
mov ebx, eax |
mov [esp], edx |
mov ebp, ecx |
mov ecx, [ecx] |
mov edx, [edx] |
call __L1OutCode |
mov ebx, eax |
mov [esp], edx |
mov ebp, ecx |
mov ecx, [ecx] |
mov edx, [edx] |
call __L1OutCode |
mov esi, eax |
mov edx, [esp+28] |
mov ecx, [edx] |
mov esi, eax |
mov edx, [esp+28] |
mov ecx, [edx] |
.L21: |
mov eax, [esp+24] |
mov edx, [eax] |
mov eax, ebx |
call __L1OutCode |
mov eax, [esp+24] |
mov edx, [eax] |
mov eax, ebx |
call __L1OutCode |
mov edi, eax |
mov edi, eax |
.L20: |
mov eax, edi |
and eax, esi |
jne .L9 |
cmp esi, edi |
je .L9 |
test esi, esi |
jne .L10 |
test edi, 1 |
je .L11 |
mov eax, [ebx+4] |
jmp .L25 |
mov eax, edi |
and eax, esi |
jne .L9 |
cmp esi, edi |
je .L9 |
test esi, esi |
jne .L10 |
test edi, 1 |
je .L11 |
mov eax, [ebx+4] |
jmp .L25 |
.L11: |
test edi, 2 |
je .L13 |
mov eax, [ebx+12] |
test edi, 2 |
je .L13 |
mov eax, [ebx+12] |
.L25: |
mov edx, [esp+28] |
jmp .L22 |
mov edx, [esp+28] |
jmp .L22 |
.L13: |
test edi, 4 |
je .L14 |
mov eax, [ebx+8] |
jmp .L26 |
test edi, 4 |
je .L14 |
mov eax, [ebx+8] |
jmp .L26 |
.L14: |
and edi, 8 |
je .L12 |
mov eax, [ebx] |
and edi, 8 |
je .L12 |
mov eax, [ebx] |
.L26: |
mov edx, [esp+24] |
mov edx, [esp+24] |
.L22: |
mov [edx], eax |
mov [edx], eax |
.L12: |
mov eax, [esp+28] |
mov ecx, [eax] |
jmp .L21 |
mov eax, [esp+28] |
mov ecx, [eax] |
jmp .L21 |
.L10: |
test esi, 1 |
je .L16 |
mov eax, [ebx+4] |
jmp .L23 |
test esi, 1 |
je .L16 |
mov eax, [ebx+4] |
jmp .L23 |
.L16: |
test esi, 2 |
je .L18 |
mov eax, [ebx+12] |
test esi, 2 |
je .L18 |
mov eax, [ebx+12] |
.L23: |
mov [ebp+0], eax |
jmp .L17 |
mov [ebp+0], eax |
jmp .L17 |
.L18: |
test esi, 4 |
je .L19 |
mov eax, [ebx+8] |
jmp .L24 |
test esi, 4 |
je .L19 |
mov eax, [ebx+8] |
jmp .L24 |
.L19: |
and esi, 8 |
je .L17 |
mov eax, [ebx] |
and esi, 8 |
je .L17 |
mov eax, [ebx] |
.L24: |
mov edx, [esp] |
mov [edx], eax |
mov edx, [esp] |
mov [edx], eax |
.L17: |
mov ecx, [ebp+0] |
mov eax, [esp] |
mov edx, [eax] |
mov eax, ebx |
call __L1OutCode |
mov esi, eax |
jmp .L20 |
mov ecx, [ebp+0] |
mov eax, [esp] |
mov edx, [eax] |
mov eax, ebx |
call __L1OutCode |
mov esi, eax |
jmp .L20 |
.L9: |
add esp, 4 |
pop ebx |
pop esi |
pop edi |
pop ebp |
add esp, 4 |
pop ebx |
pop esi |
pop edi |
pop ebp |
ret |
align 4 |
172,97 → 172,97 |
.dy1 equ 8 |
push edi |
push esi |
push ebx |
sub esp, 40 |
push edi |
push esi |
push ebx |
sub esp, 40 |
mov ebx, ecx |
mov edx, [ecx+BLITTER.src_x] |
mov [esp+.sx0], edx |
mov eax, [ecx+BLITTER.src_y] |
mov [esp+.sy0], eax |
add edx, [ecx+BLITTER.w] |
dec edx |
mov [esp+.sx1], edx |
add eax, [ecx+BLITTER.h] |
dec eax |
mov [esp+.sy1], eax |
mov ebx, ecx |
mov edx, [ecx+BLITTER.src_x] |
mov [esp+.sx0], edx |
mov eax, [ecx+BLITTER.src_y] |
mov [esp+.sy0], eax |
add edx, [ecx+BLITTER.w] |
dec edx |
mov [esp+.sx1], edx |
add eax, [ecx+BLITTER.h] |
dec eax |
mov [esp+.sy1], eax |
lea ecx, [esp+.sy0] |
lea edx, [esp+.sx0] |
lea eax, [ebx+BLITTER.sc] |
lea esi, [esp+.sy1] |
lea ecx, [esp+.sy0] |
lea edx, [esp+.sx0] |
lea eax, [ebx+BLITTER.sc] |
lea esi, [esp+.sy1] |
mov [esp+4], esi |
lea esi, [esp+.sx1] |
mov [esp], esi |
call block_clip |
mov [esp+4], esi |
lea esi, [esp+.sx1] |
mov [esp], esi |
call block_clip |
mov esi, 1 |
test eax, eax |
jne .L28 |
mov esi, 1 |
test eax, eax |
jne .L28 |
mov edi, [esp+.sx0] |
mov edx, [ebx+BLITTER.dst_x] |
add edx, edi |
sub edx, [ebx+BLITTER.src_x] |
mov [esp+.dx0], edx |
mov edi, [esp+.sx0] |
mov edx, [ebx+BLITTER.dst_x] |
add edx, edi |
sub edx, [ebx+BLITTER.src_x] |
mov [esp+.dx0], edx |
mov ecx, [esp+.sy0] |
mov eax, [ebx+BLITTER.dst_y] |
add eax, ecx |
sub eax, [ebx+BLITTER.src_y] |
mov [esp+.dy0], eax |
sub edx, edi |
add edx, [esp+.sx1] |
mov [esp+.dx1], edx |
mov ecx, [esp+.sy0] |
mov eax, [ebx+BLITTER.dst_y] |
add eax, ecx |
sub eax, [ebx+BLITTER.src_y] |
mov [esp+.dy0], eax |
sub edx, edi |
add edx, [esp+.sx1] |
mov [esp+.dx1], edx |
sub eax, ecx |
add eax, [esp+.sy1] |
mov [esp+.dy1], eax |
sub eax, ecx |
add eax, [esp+.sy1] |
mov [esp+.dy1], eax |
lea ecx, [esp+.dy0] |
lea edx, [esp+.dx0] |
lea eax, [esp+.dy1] |
mov [esp+4], eax |
lea eax, [esp+.dx1] |
mov [esp], eax |
mov eax, ebx |
call block_clip |
test eax, eax |
jne .L28 |
lea ecx, [esp+.dy0] |
lea edx, [esp+.dx0] |
lea eax, [esp+.dy1] |
mov [esp+4], eax |
lea eax, [esp+.dx1] |
mov [esp], eax |
mov eax, ebx |
call block_clip |
test eax, eax |
jne .L28 |
mov edx, [esp+.dx0] |
mov eax, [esp+.dx1] |
inc eax |
sub eax, edx |
mov [ebx+BLITTER.w], eax |
mov edx, [esp+.dx0] |
mov eax, [esp+.dx1] |
inc eax |
sub eax, edx |
mov [ebx+BLITTER.w], eax |
mov eax, [esp+.dy0] |
mov ecx, [esp+.dy1] |
inc ecx |
sub ecx, eax |
mov [ebx+BLITTER.h], ecx |
mov eax, [esp+.dy0] |
mov ecx, [esp+.dy1] |
inc ecx |
sub ecx, eax |
mov [ebx+BLITTER.h], ecx |
mov ecx, [ebx+BLITTER.src_x] |
add ecx, edx |
sub ecx, [ebx+BLITTER.dst_x] |
mov [ebx+BLITTER.src_x], ecx |
mov ecx, [ebx+BLITTER.src_x] |
add ecx, edx |
sub ecx, [ebx+BLITTER.dst_x] |
mov [ebx+BLITTER.src_x], ecx |
mov ecx, [ebx+BLITTER.src_y] |
add ecx, eax |
sub ecx, [ebx+BLITTER.dst_y] |
mov [ebx+BLITTER.src_y], ecx |
mov [ebx+BLITTER.dst_x], edx |
mov [ebx+BLITTER.dst_y], eax |
xor esi, esi |
mov ecx, [ebx+BLITTER.src_y] |
add ecx, eax |
sub ecx, [ebx+BLITTER.dst_y] |
mov [ebx+BLITTER.src_y], ecx |
mov [ebx+BLITTER.dst_x], edx |
mov [ebx+BLITTER.dst_y], eax |
xor esi, esi |
.L28: |
mov eax, esi |
add esp, 40 |
pop ebx |
pop esi |
pop edi |
mov eax, esi |
add esp, 40 |
pop ebx |
pop esi |
pop edi |
purge .sx0 |
282,163 → 282,163 |
align 4 |
blit_32: |
push ebp |
push edi |
push esi |
push ebx |
sub esp, 72 |
push ebp |
push edi |
push esi |
push ebx |
sub esp, 72 |
mov eax, [TASK_BASE] |
mov ebx, [eax-twdw + WDATA.box.width] |
mov edx, [eax-twdw + WDATA.box.height] |
mov eax, [TASK_BASE] |
mov ebx, [eax-twdw + WDATA.box.width] |
mov edx, [eax-twdw + WDATA.box.height] |
xor eax, eax |
xor eax, eax |
mov [esp+BLITTER.dc.xmin], eax |
mov [esp+BLITTER.dc.ymin], eax |
mov [esp+BLITTER.dc.xmax], ebx |
mov [esp+BLITTER.dc.ymax], edx |
mov [esp+BLITTER.dc.xmin], eax |
mov [esp+BLITTER.dc.ymin], eax |
mov [esp+BLITTER.dc.xmax], ebx |
mov [esp+BLITTER.dc.ymax], edx |
mov [esp+BLITTER.sc.xmin], eax |
mov [esp+BLITTER.sc.ymin], eax |
mov eax, [ecx+24] |
dec eax |
mov [esp+BLITTER.sc.xmax], eax |
mov eax, [ecx+28] |
dec eax |
mov [esp+BLITTER.sc.ymax], eax |
mov [esp+BLITTER.sc.xmin], eax |
mov [esp+BLITTER.sc.ymin], eax |
mov eax, [ecx+24] |
dec eax |
mov [esp+BLITTER.sc.xmax], eax |
mov eax, [ecx+28] |
dec eax |
mov [esp+BLITTER.sc.ymax], eax |
mov eax, [ecx] |
mov [esp+BLITTER.dst_x], eax |
mov eax, [ecx+4] |
mov [esp+BLITTER.dst_y], eax |
mov eax, [ecx] |
mov [esp+BLITTER.dst_x], eax |
mov eax, [ecx+4] |
mov [esp+BLITTER.dst_y], eax |
mov eax, [ecx+16] |
mov [esp+BLITTER.src_x], eax |
mov eax, [ecx+20] |
mov [esp+BLITTER.src_y], eax |
mov eax, [ecx+8] |
mov [esp+BLITTER.w], eax |
mov eax, [ecx+12] |
mov [esp+BLITTER.h], eax |
mov eax, [ecx+16] |
mov [esp+BLITTER.src_x], eax |
mov eax, [ecx+20] |
mov [esp+BLITTER.src_y], eax |
mov eax, [ecx+8] |
mov [esp+BLITTER.w], eax |
mov eax, [ecx+12] |
mov [esp+BLITTER.h], eax |
mov eax, [ecx+32] |
mov [esp+56], eax |
mov eax, [ecx+36] |
mov [esp+60], eax |
mov eax, [ecx+32] |
mov [esp+56], eax |
mov eax, [ecx+36] |
mov [esp+60], eax |
mov ecx, esp |
call blit_clip |
test eax, eax |
jne .L57 |
mov ecx, esp |
call blit_clip |
test eax, eax |
jne .L57 |
inc [mouse_pause] |
call [_display.disable_mouse] |
inc [mouse_pause] |
call [_display.disable_mouse] |
mov eax, [TASK_BASE] |
mov eax, [TASK_BASE] |
mov ebx, [esp+BLITTER.dst_x] |
mov ebp, [esp+BLITTER.dst_y] |
add ebx, [eax-twdw + WDATA.box.left] |
add ebp, [eax-twdw + WDATA.box.top] |
mov edi, ebp |
mov ebx, [esp+BLITTER.dst_x] |
mov ebp, [esp+BLITTER.dst_y] |
add ebx, [eax-twdw + WDATA.box.left] |
add ebp, [eax-twdw + WDATA.box.top] |
mov edi, ebp |
imul edi, [_display.pitch] |
imul ebp, [_display.width] |
add ebp, ebx |
add ebp, [_WinMapAddress] |
imul edi, [_display.pitch] |
imul ebp, [_display.width] |
add ebp, ebx |
add ebp, [_WinMapAddress] |
mov eax, [esp+BLITTER.src_y] |
imul eax, [esp+BLITTER.stride] |
mov esi, [esp+BLITTER.src_x] |
lea esi, [eax+esi*4] |
add esi, [esp+BLITTER.bitmap] |
mov eax, [esp+BLITTER.src_y] |
imul eax, [esp+BLITTER.stride] |
mov esi, [esp+BLITTER.src_x] |
lea esi, [eax+esi*4] |
add esi, [esp+BLITTER.bitmap] |
mov ecx, [esp+BLITTER.h] |
mov edx, [esp+BLITTER.w] |
mov ecx, [esp+BLITTER.h] |
mov edx, [esp+BLITTER.w] |
test ecx, ecx ;FIXME check clipping |
jz .L57 |
test ecx, ecx ;FIXME check clipping |
jz .L57 |
test edx, edx |
jz .L57 |
test edx, edx |
jz .L57 |
cmp [_display.bpp], 32 |
jne .core_24 |
cmp [_display.bpp], 32 |
jne .core_24 |
lea edi, [edi+ebx*4] |
lea edi, [edi+ebx*4] |
mov ebx, [CURRENT_TASK] |
mov ebx, [CURRENT_TASK] |
align 4 |
.outer32: |
xor ecx, ecx |
xor ecx, ecx |
align 4 |
.inner32: |
cmp [ebp+ecx], bl |
jne @F |
cmp [ebp+ecx], bl |
jne @F |
mov eax, [esi+ecx*4] |
mov [LFB_BASE+edi+ecx*4], eax |
mov eax, [esi+ecx*4] |
mov [LFB_BASE+edi+ecx*4], eax |
@@: |
inc ecx |
dec edx |
jnz .inner32 |
inc ecx |
dec edx |
jnz .inner32 |
add esi, [esp+BLITTER.stride] |
add edi, [_display.pitch] |
add ebp, [_display.width] |
add esi, [esp+BLITTER.stride] |
add edi, [_display.pitch] |
add ebp, [_display.width] |
mov edx, [esp+BLITTER.w] |
dec [esp+BLITTER.h] |
jnz .outer32 |
mov edx, [esp+BLITTER.w] |
dec [esp+BLITTER.h] |
jnz .outer32 |
.done: |
dec [mouse_pause] |
call [draw_pointer] |
dec [mouse_pause] |
call [draw_pointer] |
.L57: |
add esp, 72 |
pop ebx |
pop esi |
pop edi |
pop ebp |
add esp, 72 |
pop ebx |
pop esi |
pop edi |
pop ebp |
ret |
.core_24: |
lea ebx, [ebx+ebx*2] |
lea edi, [LFB_BASE+edi+ebx] |
mov ebx, [CURRENT_TASK] |
lea ebx, [ebx+ebx*2] |
lea edi, [LFB_BASE+edi+ebx] |
mov ebx, [CURRENT_TASK] |
align 4 |
.outer24: |
mov [esp+64], edi |
xor ecx, ecx |
mov [esp+64], edi |
xor ecx, ecx |
align 4 |
.inner24: |
cmp [ebp+ecx], bl |
jne @F |
cmp [ebp+ecx], bl |
jne @F |
mov eax, [esi+ecx*4] |
mov eax, [esi+ecx*4] |
lea edi, [edi+ecx*2] |
mov [edi+ecx], ax |
shr eax, 16 |
mov [edi+ecx+2], al |
lea edi, [edi+ecx*2] |
mov [edi+ecx], ax |
shr eax, 16 |
mov [edi+ecx+2], al |
@@: |
mov edi, [esp+64] |
inc ecx |
dec edx |
jnz .inner24 |
mov edi, [esp+64] |
inc ecx |
dec edx |
jnz .inner24 |
add esi, [esp+BLITTER.stride] |
add edi, [_display.pitch] |
add ebp, [_display.width] |
add esi, [esp+BLITTER.stride] |
add edi, [_display.pitch] |
add ebp, [_display.width] |
mov edx, [esp+BLITTER.w] |
dec [esp+BLITTER.h] |
jnz .outer24 |
mov edx, [esp+BLITTER.w] |
dec [esp+BLITTER.h] |
jnz .outer24 |
jmp .done |
jmp .done |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/video/cursors.inc |
---|
1,806 → 1,806 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
LOAD_FROM_FILE equ 0 |
LOAD_FROM_MEM equ 1 |
LOAD_INDIRECT equ 2 |
LOAD_SYSTEM equ 3 |
struc BITMAPINFOHEADER { |
.biSize dd ? ; DWORD |
.biWidth dd ? ; LONG |
.biHeight dd ? ; LONG |
.biPlanes dw ? ; WORD |
.biBitCount dw ? ; WORD |
.biCompression dd ? ; DWORD |
.biSizeImage dd ? ; DWORD |
.biXPelsPerMeter dd ? ; LONG |
.biYPelsPerMeter dd ? ; LONG |
.biClrUsed dd ? ; DWORD |
.biClrImportant dd ? ; DWORD |
} |
virtual at 0 |
BI BITMAPINFOHEADER |
end virtual |
align 4 |
proc init_cursor stdcall, dst:dword, src:dword |
locals |
rBase dd ? |
pQuad dd ? |
pBits dd ? |
pAnd dd ? |
width dd ? |
height dd ? |
counter dd ? |
endl |
mov esi, [src] |
add esi,[esi+18] |
mov eax,esi |
cmp [esi+BI.biBitCount], 24 |
je .img_24 |
cmp [esi+BI.biBitCount], 8 |
je .img_8 |
cmp [esi+BI.biBitCount], 4 |
je .img_4 |
.img_2: |
add eax, [esi] |
mov [pQuad],eax |
add eax,8 |
mov [pBits],eax |
add eax, 128 |
mov [pAnd],eax |
mov eax,[esi+4] |
mov [width],eax |
mov ebx,[esi+8] |
shr ebx,1 |
mov [height],ebx |
mov edi, [dst] |
add edi, 32*31*4 |
mov [rBase],edi |
mov esi,[pQuad] |
.l21: |
mov ebx, [pBits] |
mov ebx, [ebx] |
bswap ebx |
mov eax, [pAnd] |
mov eax, [eax] |
bswap eax |
mov [counter], 32 |
@@: |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
xor ecx, ecx |
shl ebx,1 |
setc cl |
mov ecx, [esi+ecx*4] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
add edi, 4 |
dec [counter] |
jnz @B |
add [pBits], 4 |
add [pAnd], 4 |
mov edi,[rBase] |
sub edi,128 |
mov [rBase],edi |
sub [height],1 |
jnz .l21 |
ret |
.img_4: |
add eax, [esi] |
mov [pQuad],eax |
add eax,64 |
mov [pBits],eax |
add eax, 0x200 |
mov [pAnd],eax |
mov eax,[esi+4] |
mov [width],eax |
mov ebx,[esi+8] |
shr ebx,1 |
mov [height],ebx |
mov edi, [dst] |
add edi, 32*31*4 |
mov [rBase],edi |
mov esi,[pQuad] |
mov ebx, [pBits] |
.l4: |
mov eax, [pAnd] |
mov eax, [eax] |
bswap eax |
mov [counter], 16 |
@@: |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
movzx ecx, byte [ebx] |
and cl, 0xF0 |
shr ecx, 2 |
mov ecx, [esi+ecx] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
movzx ecx, byte [ebx] |
and cl, 0x0F |
mov ecx, [esi+ecx*4] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi+4], edx |
inc ebx |
add edi, 8 |
dec [counter] |
jnz @B |
add [pAnd], 4 |
mov edi,[rBase] |
sub edi,128 |
mov [rBase],edi |
sub [height],1 |
jnz .l4 |
ret |
.img_8: |
add eax, [esi] |
mov [pQuad],eax |
add eax,1024 |
mov [pBits],eax |
add eax, 1024 |
mov [pAnd],eax |
mov eax,[esi+4] |
mov [width],eax |
mov ebx,[esi+8] |
shr ebx,1 |
mov [height],ebx |
mov edi, [dst] |
add edi, 32*31*4 |
mov [rBase],edi |
mov esi,[pQuad] |
mov ebx, [pBits] |
.l81: |
mov eax, [pAnd] |
mov eax, [eax] |
bswap eax |
mov [counter], 32 |
@@: |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
movzx ecx, byte [ebx] |
mov ecx, [esi+ecx*4] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
inc ebx |
add edi, 4 |
dec [counter] |
jnz @B |
add [pAnd], 4 |
mov edi,[rBase] |
sub edi,128 |
mov [rBase],edi |
sub [height],1 |
jnz .l81 |
ret |
.img_24: |
add eax, [esi] |
mov [pQuad],eax |
add eax, 0xC00 |
mov [pAnd],eax |
mov eax,[esi+BI.biWidth] |
mov [width],eax |
mov ebx,[esi+BI.biHeight] |
shr ebx,1 |
mov [height],ebx |
mov edi, [dst] |
add edi, 32*31*4 |
mov [rBase],edi |
mov esi,[pAnd] |
mov ebx, [pQuad] |
.row_24: |
mov eax, [esi] |
bswap eax |
mov [counter], 32 |
@@: |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
mov ecx, [ebx] |
and ecx, 0x00FFFFFF |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
add ebx, 3 |
add edi, 4 |
dec [counter] |
jnz @B |
add esi, 4 |
mov edi,[rBase] |
sub edi,128 |
mov [rBase],edi |
sub [height],1 |
jnz .row_24 |
ret |
endp |
align 4 |
proc set_cursor stdcall, hcursor:dword |
mov eax, [hcursor] |
cmp [eax+CURSOR.magic], 'CURS' |
jne .fail |
; cmp [eax+CURSOR.size], CURSOR_SIZE |
; jne .fail |
mov ebx, [current_slot] |
xchg eax, [ebx+APPDATA.cursor] |
ret |
.fail: |
mov eax, [def_cursor] |
mov ebx, [current_slot] |
xchg eax, [ebx+APPDATA.cursor] |
ret |
endp |
; param |
; eax= pid |
; ebx= src |
; ecx= flags |
create_cursor: |
.src equ esp |
.flags equ esp+4 |
.hcursor equ esp+8 |
sub esp, 4 ;space for .hcursor |
push ecx |
push ebx |
mov ebx, eax |
mov eax, CURSOR.sizeof |
call create_kernel_object |
test eax, eax |
jz .fail |
mov [.hcursor],eax |
xor ebx, ebx |
mov [eax+CURSOR.magic], 'CURS' |
mov [eax+CURSOR.destroy], destroy_cursor |
mov [eax+CURSOR.hot_x], ebx |
mov [eax+CURSOR.hot_y], ebx |
stdcall kernel_alloc, 0x1000 |
test eax, eax |
jz .fail |
mov edi, [.hcursor] |
mov [edi+CURSOR.base], eax |
mov esi, [.src] |
mov ebx, [.flags] |
cmp bx, LOAD_INDIRECT |
je .indirect |
movzx ecx, word [esi+10] |
movzx edx, word [esi+12] |
mov [edi+CURSOR.hot_x], ecx |
mov [edi+CURSOR.hot_y], edx |
stdcall init_cursor, eax, esi |
mov eax, [.hcursor] |
lea eax, [eax+CURSOR.list_next] |
lea edx, [_display.cr_list.next] |
pushfd |
cli |
mov ecx, [edx] |
mov [eax], ecx |
mov [eax+4], edx |
mov [ecx+4], eax |
mov [edx], eax |
popfd |
mov eax, [.hcursor] |
.check_hw: |
cmp [_display.init_cursor], 0 |
je .fail |
push eax |
call [_display.init_cursor] |
add esp, 4 |
mov eax, [.hcursor] |
.fail: |
add esp, 12 |
ret |
.indirect: |
shr ebx, 16 |
movzx ecx, bh |
movzx edx, bl |
mov [eax+CURSOR.hot_x], ecx |
mov [eax+CURSOR.hot_y], edx |
xchg edi, eax |
mov ecx, 1024 |
cld |
rep movsd |
jmp .check_hw |
align 4 |
proc load_cursor stdcall, src:dword, flags:dword |
locals |
handle dd ? |
endl |
xor eax, eax |
cmp [create_cursor], eax |
je .fail2 |
mov [handle], eax |
cmp word [flags], LOAD_FROM_FILE |
jne @F |
stdcall load_file, [src] |
test eax, eax |
jz .fail |
mov [src], eax |
@@: |
push ebx |
push esi |
push edi |
mov eax, [CURRENT_TASK] |
shl eax, 5 |
mov eax, [CURRENT_TASK+eax+4] |
mov ebx, [src] |
mov ecx, [flags] |
call create_cursor ;eax, ebx, ecx |
mov [handle], eax |
cmp word [flags], LOAD_FROM_FILE |
jne .exit |
stdcall kernel_free, [src] |
.exit: |
pop edi |
pop esi |
pop ebx |
.fail: |
mov eax, [handle] |
.fail2: |
ret |
endp |
align 4 |
proc delete_cursor stdcall, hcursor:dword |
locals |
hsrv dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
endl |
mov esi, [hcursor] |
cmp [esi+CURSOR.magic], 'CURS' |
jne .fail |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov ebx, [CURRENT_TASK+ebx+4] |
cmp ebx, [esi+CURSOR.pid] |
jne .fail |
mov ebx, [current_slot] |
cmp esi, [ebx+APPDATA.cursor] |
jne @F |
mov eax, [def_cursor] |
mov [ebx+APPDATA.cursor], eax |
@@: |
mov eax, [hcursor] |
call [eax+APPOBJ.destroy] |
.fail: |
ret |
endp |
; param |
; eax= cursor |
align 4 |
destroy_cursor: |
push eax |
stdcall kernel_free, [eax+CURSOR.base] |
pop eax |
call destroy_kernel_object |
ret |
align 4 |
select_cursor: |
mov eax, [esp+4] |
mov [_display.cursor], eax |
ret 4 |
align 4 |
proc restore_24 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 |
mov ecx, [cur.w] |
lea ecx, [ecx+ecx*2] |
push ecx |
@@: |
mov edi, ebx |
add ebx, [BytesPerScanLine] |
mov ecx, [esp] |
rep movsb |
dec edx |
jnz @B |
pop ecx |
pop edi |
pop esi |
.ret: |
pop ebx |
ret |
endp |
align 4 |
proc restore_32 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 |
@@: |
mov edi, ebx |
add ebx, [BytesPerScanLine] |
mov ecx, [cur.w] |
rep movsd |
dec edx |
jnz @B |
pop edi |
.ret: |
pop esi |
pop ebx |
ret |
endp |
align 4 |
proc move_cursor_24 stdcall, hcursor:dword, x:dword, y:dword |
locals |
h dd ? |
_dx dd ? |
_dy dd ? |
endl |
mov esi, [hcursor] |
mov ecx, [x] |
mov eax, [y] |
mov ebx, [BytesPerScanLine] |
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] |
lea edx, [LFB_BASE+ecx*3] |
add edx, eax |
mov [cur_saved_base],edx |
cmp ebx, [Screen_Max_X] |
jbe @F |
mov ebx, [Screen_Max_X] |
@@: |
cmp edi, [Screen_Max_Y] |
jbe @F |
mov edi, [Screen_Max_Y] |
@@: |
mov [cur.right], ebx |
mov [cur.bottom], edi |
sub ebx, [x] |
sub edi, [y] |
inc ebx |
inc edi |
mov [cur.w], ebx |
mov [cur.h], edi |
mov [h], edi |
mov eax, edi |
mov edi, cur_saved_data |
@@: |
mov esi, edx |
add edx, [BytesPerScanLine] |
mov ecx, [cur.w] |
lea ecx, [ecx+ecx*2] |
rep movsb |
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] |
.row: |
mov ecx, [cur.w] |
mov esi, edx |
mov edi, ebx |
add edx, 32*4 |
add ebx, [BytesPerScanLine] |
.pix: |
lodsd |
test eax, 0xFF000000 |
jz @F |
mov [edi], ax |
shr eax, 16 |
mov [edi+2],al |
@@: |
add edi, 3 |
dec ecx |
jnz .pix |
dec [h] |
jnz .row |
ret |
endp |
align 4 |
proc move_cursor_32 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] |
lea edx, [LFB_BASE+eax+ecx*4] |
mov [cur_saved_base],edx |
cmp ebx, [Screen_Max_X] |
jbe @F |
mov ebx, [Screen_Max_X] |
@@: |
cmp edi, [Screen_Max_Y] |
jbe @F |
mov edi, [Screen_Max_Y] |
@@: |
mov [cur.right], ebx |
mov [cur.bottom], edi |
sub ebx, [x] |
sub edi, [y] |
inc ebx |
inc edi |
mov [cur.w], ebx |
mov [cur.h], edi |
mov [h], edi |
mov eax, edi |
mov edi, cur_saved_data |
@@: |
mov esi, edx |
add edx, [BytesPerScanLine] |
mov ecx, [cur.w] |
rep movsd |
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] |
.row: |
mov ecx, [cur.w] |
mov esi, edx |
mov edi, ebx |
add edx, 32*4 |
add ebx, [BytesPerScanLine] |
.pix: |
lodsd |
test eax, 0xFF000000 |
jz @F |
mov [edi], eax |
@@: |
add edi, 4 |
dec ecx |
jnz .pix |
dec [h] |
jnz .row |
ret |
endp |
align 4 |
get_display: |
mov eax, _display |
ret |
align 4 |
init_display: |
xor eax, eax |
mov edi, _display |
mov [edi+display_t.init_cursor], eax |
mov [edi+display_t.select_cursor], eax |
mov [edi+display_t.show_cursor], eax |
mov [edi+display_t.move_cursor], eax |
mov [edi+display_t.restore_cursor], eax |
lea ecx, [edi+display_t.cr_list.next] |
mov [edi+display_t.cr_list.next], ecx |
mov [edi+display_t.cr_list.prev], ecx |
cmp [SCR_MODE],word 0x13 |
jbe .fail |
test word [SCR_MODE], 0x4000 |
jz .fail |
mov ebx, restore_32 |
mov ecx, move_cursor_32 |
movzx eax, byte [ScreenBPP] |
cmp eax, 32 |
je @F |
mov ebx, restore_24 |
mov ecx, move_cursor_24 |
cmp eax, 24 |
jne .fail |
@@: |
mov [_display.select_cursor], select_cursor |
mov [_display.move_cursor], ecx |
mov [_display.restore_cursor], ebx |
stdcall load_cursor, def_arrow, dword LOAD_FROM_MEM |
mov [def_cursor], eax |
ret |
.fail: |
xor eax, eax |
mov [_display.select_cursor], eax |
mov [_display.move_cursor], eax |
ret |
align 4 |
def_arrow: |
file 'arrow.cur' |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
LOAD_FROM_FILE equ 0 |
LOAD_FROM_MEM equ 1 |
LOAD_INDIRECT equ 2 |
LOAD_SYSTEM equ 3 |
struc BITMAPINFOHEADER { |
.biSize dd ? ; DWORD |
.biWidth dd ? ; LONG |
.biHeight dd ? ; LONG |
.biPlanes dw ? ; WORD |
.biBitCount dw ? ; WORD |
.biCompression dd ? ; DWORD |
.biSizeImage dd ? ; DWORD |
.biXPelsPerMeter dd ? ; LONG |
.biYPelsPerMeter dd ? ; LONG |
.biClrUsed dd ? ; DWORD |
.biClrImportant dd ? ; DWORD |
} |
virtual at 0 |
BI BITMAPINFOHEADER |
end virtual |
align 4 |
proc init_cursor stdcall, dst:dword, src:dword |
locals |
rBase dd ? |
pQuad dd ? |
pBits dd ? |
pAnd dd ? |
width dd ? |
height dd ? |
counter dd ? |
endl |
mov esi, [src] |
add esi, [esi+18] |
mov eax, esi |
cmp [esi+BI.biBitCount], 24 |
je .img_24 |
cmp [esi+BI.biBitCount], 8 |
je .img_8 |
cmp [esi+BI.biBitCount], 4 |
je .img_4 |
.img_2: |
add eax, [esi] |
mov [pQuad], eax |
add eax, 8 |
mov [pBits], eax |
add eax, 128 |
mov [pAnd], eax |
mov eax, [esi+4] |
mov [width], eax |
mov ebx, [esi+8] |
shr ebx, 1 |
mov [height], ebx |
mov edi, [dst] |
add edi, 32*31*4 |
mov [rBase], edi |
mov esi, [pQuad] |
.l21: |
mov ebx, [pBits] |
mov ebx, [ebx] |
bswap ebx |
mov eax, [pAnd] |
mov eax, [eax] |
bswap eax |
mov [counter], 32 |
@@: |
xor edx, edx |
shl eax, 1 |
setc dl |
dec edx |
xor ecx, ecx |
shl ebx, 1 |
setc cl |
mov ecx, [esi+ecx*4] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
add edi, 4 |
dec [counter] |
jnz @B |
add [pBits], 4 |
add [pAnd], 4 |
mov edi, [rBase] |
sub edi, 128 |
mov [rBase], edi |
sub [height], 1 |
jnz .l21 |
ret |
.img_4: |
add eax, [esi] |
mov [pQuad], eax |
add eax, 64 |
mov [pBits], eax |
add eax, 0x200 |
mov [pAnd], eax |
mov eax, [esi+4] |
mov [width], eax |
mov ebx, [esi+8] |
shr ebx, 1 |
mov [height], ebx |
mov edi, [dst] |
add edi, 32*31*4 |
mov [rBase], edi |
mov esi, [pQuad] |
mov ebx, [pBits] |
.l4: |
mov eax, [pAnd] |
mov eax, [eax] |
bswap eax |
mov [counter], 16 |
@@: |
xor edx, edx |
shl eax, 1 |
setc dl |
dec edx |
movzx ecx, byte [ebx] |
and cl, 0xF0 |
shr ecx, 2 |
mov ecx, [esi+ecx] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
xor edx, edx |
shl eax, 1 |
setc dl |
dec edx |
movzx ecx, byte [ebx] |
and cl, 0x0F |
mov ecx, [esi+ecx*4] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi+4], edx |
inc ebx |
add edi, 8 |
dec [counter] |
jnz @B |
add [pAnd], 4 |
mov edi, [rBase] |
sub edi, 128 |
mov [rBase], edi |
sub [height], 1 |
jnz .l4 |
ret |
.img_8: |
add eax, [esi] |
mov [pQuad], eax |
add eax, 1024 |
mov [pBits], eax |
add eax, 1024 |
mov [pAnd], eax |
mov eax, [esi+4] |
mov [width], eax |
mov ebx, [esi+8] |
shr ebx, 1 |
mov [height], ebx |
mov edi, [dst] |
add edi, 32*31*4 |
mov [rBase], edi |
mov esi, [pQuad] |
mov ebx, [pBits] |
.l81: |
mov eax, [pAnd] |
mov eax, [eax] |
bswap eax |
mov [counter], 32 |
@@: |
xor edx, edx |
shl eax, 1 |
setc dl |
dec edx |
movzx ecx, byte [ebx] |
mov ecx, [esi+ecx*4] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
inc ebx |
add edi, 4 |
dec [counter] |
jnz @B |
add [pAnd], 4 |
mov edi, [rBase] |
sub edi, 128 |
mov [rBase], edi |
sub [height], 1 |
jnz .l81 |
ret |
.img_24: |
add eax, [esi] |
mov [pQuad], eax |
add eax, 0xC00 |
mov [pAnd], eax |
mov eax, [esi+BI.biWidth] |
mov [width], eax |
mov ebx, [esi+BI.biHeight] |
shr ebx, 1 |
mov [height], ebx |
mov edi, [dst] |
add edi, 32*31*4 |
mov [rBase], edi |
mov esi, [pAnd] |
mov ebx, [pQuad] |
.row_24: |
mov eax, [esi] |
bswap eax |
mov [counter], 32 |
@@: |
xor edx, edx |
shl eax, 1 |
setc dl |
dec edx |
mov ecx, [ebx] |
and ecx, 0x00FFFFFF |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
add ebx, 3 |
add edi, 4 |
dec [counter] |
jnz @B |
add esi, 4 |
mov edi, [rBase] |
sub edi, 128 |
mov [rBase], edi |
sub [height], 1 |
jnz .row_24 |
ret |
endp |
align 4 |
proc set_cursor stdcall, hcursor:dword |
mov eax, [hcursor] |
cmp [eax+CURSOR.magic], 'CURS' |
jne .fail |
; cmp [eax+CURSOR.size], CURSOR_SIZE |
; jne .fail |
mov ebx, [current_slot] |
xchg eax, [ebx+APPDATA.cursor] |
ret |
.fail: |
mov eax, [def_cursor] |
mov ebx, [current_slot] |
xchg eax, [ebx+APPDATA.cursor] |
ret |
endp |
; param |
; eax= pid |
; ebx= src |
; ecx= flags |
create_cursor: |
.src equ esp |
.flags equ esp+4 |
.hcursor equ esp+8 |
sub esp, 4 ;space for .hcursor |
push ecx |
push ebx |
mov ebx, eax |
mov eax, CURSOR.sizeof |
call create_kernel_object |
test eax, eax |
jz .fail |
mov [.hcursor], eax |
xor ebx, ebx |
mov [eax+CURSOR.magic], 'CURS' |
mov [eax+CURSOR.destroy], destroy_cursor |
mov [eax+CURSOR.hot_x], ebx |
mov [eax+CURSOR.hot_y], ebx |
stdcall kernel_alloc, 0x1000 |
test eax, eax |
jz .fail |
mov edi, [.hcursor] |
mov [edi+CURSOR.base], eax |
mov esi, [.src] |
mov ebx, [.flags] |
cmp bx, LOAD_INDIRECT |
je .indirect |
movzx ecx, word [esi+10] |
movzx edx, word [esi+12] |
mov [edi+CURSOR.hot_x], ecx |
mov [edi+CURSOR.hot_y], edx |
stdcall init_cursor, eax, esi |
mov eax, [.hcursor] |
lea eax, [eax+CURSOR.list_next] |
lea edx, [_display.cr_list.next] |
pushfd |
cli |
mov ecx, [edx] |
mov [eax], ecx |
mov [eax+4], edx |
mov [ecx+4], eax |
mov [edx], eax |
popfd |
mov eax, [.hcursor] |
.check_hw: |
cmp [_display.init_cursor], 0 |
je .fail |
push eax |
call [_display.init_cursor] |
add esp, 4 |
mov eax, [.hcursor] |
.fail: |
add esp, 12 |
ret |
.indirect: |
shr ebx, 16 |
movzx ecx, bh |
movzx edx, bl |
mov [eax+CURSOR.hot_x], ecx |
mov [eax+CURSOR.hot_y], edx |
xchg edi, eax |
mov ecx, 1024 |
cld |
rep movsd |
jmp .check_hw |
align 4 |
proc load_cursor stdcall, src:dword, flags:dword |
locals |
handle dd ? |
endl |
xor eax, eax |
cmp [create_cursor], eax |
je .fail2 |
mov [handle], eax |
cmp word [flags], LOAD_FROM_FILE |
jne @F |
stdcall load_file, [src] |
test eax, eax |
jz .fail |
mov [src], eax |
@@: |
push ebx |
push esi |
push edi |
mov eax, [CURRENT_TASK] |
shl eax, 5 |
mov eax, [CURRENT_TASK+eax+4] |
mov ebx, [src] |
mov ecx, [flags] |
call create_cursor ;eax, ebx, ecx |
mov [handle], eax |
cmp word [flags], LOAD_FROM_FILE |
jne .exit |
stdcall kernel_free, [src] |
.exit: |
pop edi |
pop esi |
pop ebx |
.fail: |
mov eax, [handle] |
.fail2: |
ret |
endp |
align 4 |
proc delete_cursor stdcall, hcursor:dword |
locals |
hsrv dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
endl |
mov esi, [hcursor] |
cmp [esi+CURSOR.magic], 'CURS' |
jne .fail |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov ebx, [CURRENT_TASK+ebx+4] |
cmp ebx, [esi+CURSOR.pid] |
jne .fail |
mov ebx, [current_slot] |
cmp esi, [ebx+APPDATA.cursor] |
jne @F |
mov eax, [def_cursor] |
mov [ebx+APPDATA.cursor], eax |
@@: |
mov eax, [hcursor] |
call [eax+APPOBJ.destroy] |
.fail: |
ret |
endp |
; param |
; eax= cursor |
align 4 |
destroy_cursor: |
push eax |
stdcall kernel_free, [eax+CURSOR.base] |
pop eax |
call destroy_kernel_object |
ret |
align 4 |
select_cursor: |
mov eax, [esp+4] |
mov [_display.cursor], eax |
ret 4 |
align 4 |
proc restore_24 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 |
mov ecx, [cur.w] |
lea ecx, [ecx+ecx*2] |
push ecx |
@@: |
mov edi, ebx |
add ebx, [BytesPerScanLine] |
mov ecx, [esp] |
rep movsb |
dec edx |
jnz @B |
pop ecx |
pop edi |
pop esi |
.ret: |
pop ebx |
ret |
endp |
align 4 |
proc restore_32 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 |
@@: |
mov edi, ebx |
add ebx, [BytesPerScanLine] |
mov ecx, [cur.w] |
rep movsd |
dec edx |
jnz @B |
pop edi |
.ret: |
pop esi |
pop ebx |
ret |
endp |
align 4 |
proc move_cursor_24 stdcall, hcursor:dword, x:dword, y:dword |
locals |
h dd ? |
_dx dd ? |
_dy dd ? |
endl |
mov esi, [hcursor] |
mov ecx, [x] |
mov eax, [y] |
mov ebx, [BytesPerScanLine] |
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] |
lea edx, [LFB_BASE+ecx*3] |
add edx, eax |
mov [cur_saved_base], edx |
cmp ebx, [Screen_Max_X] |
jbe @F |
mov ebx, [Screen_Max_X] |
@@: |
cmp edi, [Screen_Max_Y] |
jbe @F |
mov edi, [Screen_Max_Y] |
@@: |
mov [cur.right], ebx |
mov [cur.bottom], edi |
sub ebx, [x] |
sub edi, [y] |
inc ebx |
inc edi |
mov [cur.w], ebx |
mov [cur.h], edi |
mov [h], edi |
mov eax, edi |
mov edi, cur_saved_data |
@@: |
mov esi, edx |
add edx, [BytesPerScanLine] |
mov ecx, [cur.w] |
lea ecx, [ecx+ecx*2] |
rep movsb |
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] |
.row: |
mov ecx, [cur.w] |
mov esi, edx |
mov edi, ebx |
add edx, 32*4 |
add ebx, [BytesPerScanLine] |
.pix: |
lodsd |
test eax, 0xFF000000 |
jz @F |
mov [edi], ax |
shr eax, 16 |
mov [edi+2], al |
@@: |
add edi, 3 |
dec ecx |
jnz .pix |
dec [h] |
jnz .row |
ret |
endp |
align 4 |
proc move_cursor_32 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] |
lea edx, [LFB_BASE+eax+ecx*4] |
mov [cur_saved_base], edx |
cmp ebx, [Screen_Max_X] |
jbe @F |
mov ebx, [Screen_Max_X] |
@@: |
cmp edi, [Screen_Max_Y] |
jbe @F |
mov edi, [Screen_Max_Y] |
@@: |
mov [cur.right], ebx |
mov [cur.bottom], edi |
sub ebx, [x] |
sub edi, [y] |
inc ebx |
inc edi |
mov [cur.w], ebx |
mov [cur.h], edi |
mov [h], edi |
mov eax, edi |
mov edi, cur_saved_data |
@@: |
mov esi, edx |
add edx, [BytesPerScanLine] |
mov ecx, [cur.w] |
rep movsd |
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] |
.row: |
mov ecx, [cur.w] |
mov esi, edx |
mov edi, ebx |
add edx, 32*4 |
add ebx, [BytesPerScanLine] |
.pix: |
lodsd |
test eax, 0xFF000000 |
jz @F |
mov [edi], eax |
@@: |
add edi, 4 |
dec ecx |
jnz .pix |
dec [h] |
jnz .row |
ret |
endp |
align 4 |
get_display: |
mov eax, _display |
ret |
align 4 |
init_display: |
xor eax, eax |
mov edi, _display |
mov [edi+display_t.init_cursor], eax |
mov [edi+display_t.select_cursor], eax |
mov [edi+display_t.show_cursor], eax |
mov [edi+display_t.move_cursor], eax |
mov [edi+display_t.restore_cursor], eax |
lea ecx, [edi+display_t.cr_list.next] |
mov [edi+display_t.cr_list.next], ecx |
mov [edi+display_t.cr_list.prev], ecx |
cmp [SCR_MODE], word 0x13 |
jbe .fail |
test word [SCR_MODE], 0x4000 |
jz .fail |
mov ebx, restore_32 |
mov ecx, move_cursor_32 |
movzx eax, byte [ScreenBPP] |
cmp eax, 32 |
je @F |
mov ebx, restore_24 |
mov ecx, move_cursor_24 |
cmp eax, 24 |
jne .fail |
@@: |
mov [_display.select_cursor], select_cursor |
mov [_display.move_cursor], ecx |
mov [_display.restore_cursor], ebx |
stdcall load_cursor, def_arrow, dword LOAD_FROM_MEM |
mov [def_cursor], eax |
ret |
.fail: |
xor eax, eax |
mov [_display.select_cursor], eax |
mov [_display.move_cursor], eax |
ret |
align 4 |
def_arrow: |
file 'arrow.cur' |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/video/vesa12.inc |
---|
1,1004 → 1,1004 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; VESA12.INC ;; |
;; ;; |
;; Vesa 1.2 functions for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Ville Turjanmaa ;; |
;; ;; |
;; quickcode@mail.ru - bankswitch for S3 cards ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
TRIDENT equ 0 |
S3_VIDEO equ 0 |
INTEL_VIDEO equ 0 |
if TRIDENT |
if S3_VIDEO or INTEL_VIDEO |
stop |
end if |
end if |
if S3_VIDEO |
if TRIDENT or INTEL_VIDEO |
stop |
end if |
end if |
if INTEL_VIDEO |
if S3_VIDEO or TRIDENT |
stop |
end if |
end if |
; A complete video driver should include the following types of function |
; |
; Putpixel |
; Getpixel |
; |
; Drawimage |
; Drawbar |
; |
; Drawbackground |
; |
; |
; Modifying the set_bank -function is mostly enough |
; for different Vesa 1.2 setups. |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
; set_bank for Trident videocards, work on Trident 9440 |
; modified by Mario79 |
if TRIDENT |
set_bank: |
pushfd |
cli |
cmp al,[BANK_RW] |
je .retsb |
mov [BANK_RW],al |
push dx |
mov dx,3D8h |
out dx,al |
pop dx |
.retsb: |
popfd |
ret |
end if |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
; set_bank for S3 videocards, work on S3 ViRGE PCI (325) |
; modified by kmeaw |
if S3_VIDEO |
set_bank: |
pushfd |
cli |
cmp al,[BANK_RW] |
je .retsb |
mov [BANK_RW],al |
push ax |
push dx |
push cx |
mov cl, al |
mov dx, 0x3D4 |
mov al, 0x38 |
out dx, al ;CR38 Register Lock 1 ;Note: Traditionally 48h is used to |
;unlock and 00h to lock |
inc dx |
mov al, 0x48 |
out dx, al ;3d5 -? |
dec dx |
mov al, 0x31 |
out dx, al ;CR31 Memory Configuration Register |
;0 Enable Base Address Offset (CPUA BASE). Enables bank operation if set, ;disables if clear. |
;4-5 Bit 16-17 of the Display Start Address. For the 801/5,928 see index 51h, |
;for the 864/964 see index 69h. |
inc dx |
in al, dx |
dec dx |
mov ah, al |
mov al, 0x31 |
out dx, ax |
mov al, ah |
or al, 9 |
inc dx |
out dx, al |
dec dx |
mov al, 0x35 |
out dx, al ;CR35 CRT Register Lock |
inc dx |
in al, dx |
dec dx |
and al, 0xF0 |
mov ch, cl |
and ch, 0x0F |
or ch, al |
mov al, 0x35 |
out dx, al |
inc dx |
mov al, ch |
out dx, ax |
dec dx |
mov al, 0x51 ;Extended System Control 2 Register |
out dx, al |
inc dx |
in al, dx |
dec dx |
and al, 0xF3 |
shr cl, 2 |
and cl, 0x0C |
or cl, al |
mov al, 0x51 |
out dx, al |
inc dx |
mov al, cl |
out dx, al |
dec dx |
mov al, 0x38 |
out dx, al |
inc dx |
xor al, al |
out dx, al |
dec dx |
pop cx |
pop dx |
pop ax |
.retsb: |
popfd |
ret |
end if |
;Set bank function for Intel 810/815 chipsets |
; *****Modified by Protopopius, Russia.***** |
; ********* http://menuetos.hut.ru ************** |
; ************************************************ |
if INTEL_VIDEO |
set_bank: |
pushfd |
cli |
cmp al,[BANK_RW] |
je .retsb |
mov [BANK_RW],al |
push ax |
push dx |
mov dx,3CEh |
mov ah,al ; Save value for later use |
mov al,10h ; Index GR10 (Address Mapping) |
out dx,al ; Select GR10 |
inc dl |
mov al,3 ; Set bits 0 and 1 (Enable linear page mapping) |
out dx,al ; Write value |
dec dl |
mov al,11h ; Index GR11 (Page Selector) |
out dx,al ; Select GR11 |
inc dl |
mov al,ah ; Write address |
out dx,al ; Write the value |
pop dx |
pop ax |
.retsb: |
popfd |
ret |
end if |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} |
if (TRIDENT or S3_VIDEO or INTEL_VIDEO) |
else |
set_bank: |
pushfd |
cli |
cmp al,[BANK_RW] |
je .retsb |
mov [BANK_RW],al |
push ax |
push dx |
mov ah,al |
mov dx,0x03D4 |
mov al,0x39 |
out dx,al |
inc dl |
mov al,0xA5 |
out dx,al |
dec dl |
mov al,6Ah |
out dx,al |
inc dl |
mov al,ah |
out dx,al |
dec dl |
mov al,0x39 |
out dx,al |
inc dl |
mov al,0x5A |
out dx,al |
dec dl |
pop dx |
pop ax |
.retsb: |
popfd |
ret |
end if |
vesa12_drawbackground: |
call [_display.disable_mouse] |
push eax |
push ebx |
push ecx |
push edx |
xor edx,edx |
mov eax,dword[BgrDataWidth] |
mov ebx,dword[BgrDataHeight] |
mul ebx |
mov ebx,3 |
mul ebx |
mov [imax],eax |
mov eax,[draw_data+32+RECT.left] |
mov ebx,[draw_data+32+RECT.top] |
xor edi,edi ;no force |
v12dp3: |
push eax |
push ebx |
cmp [BgrDrawMode],dword 1 ; tiled background |
jne no_vesa12_tiled_bgr |
push edx |
xor edx,edx |
div dword [BgrDataWidth] |
push edx |
mov eax,ebx |
xor edx,edx |
div dword [BgrDataHeight] |
mov ebx,edx |
pop eax |
pop edx |
no_vesa12_tiled_bgr: |
cmp [BgrDrawMode],dword 2 ; stretched background |
jne no_vesa12_stretched_bgr |
push edx |
mul dword [BgrDataWidth] |
mov ecx,[Screen_Max_X] |
inc ecx |
div ecx |
push eax |
mov eax,ebx |
mul dword [BgrDataHeight] |
mov ecx,[Screen_Max_Y] |
inc ecx |
div ecx |
mov ebx,eax |
pop eax |
pop edx |
no_vesa12_stretched_bgr: |
mov esi,ebx |
imul esi, dword [BgrDataWidth] |
add esi,eax |
lea esi,[esi*3] |
add esi,[img_background] ;IMG_BACKGROUND |
pop ebx |
pop eax |
v12di4: |
mov cl,[esi+2] |
shl ecx,16 |
mov cx,[esi] |
pusha |
mov esi,eax |
mov edi,ebx |
mov eax,[Screen_Max_X] |
add eax,1 |
mul ebx |
add eax, [_WinMapAddress] |
cmp [eax+esi],byte 1 |
jnz v12nbgp |
mov eax,[BytesPerScanLine] |
mov ebx,edi |
mul ebx |
add eax, esi |
lea eax, [VGABasePtr+eax+esi*2] |
cmp [ScreenBPP],byte 24 |
jz v12bgl3 |
add eax,esi |
v12bgl3: |
push ebx |
push eax |
sub eax,VGABasePtr |
shr eax,16 |
call set_bank |
pop eax |
and eax,65535 |
add eax,VGABasePtr |
pop ebx |
mov [eax],cx |
add eax,2 |
shr ecx,16 |
mov [eax],cl |
sti |
v12nbgp: |
popa |
add esi,3 |
inc eax |
cmp eax,[draw_data+32+RECT.right] |
jg v12nodp31 |
jmp v12dp3 |
v12nodp31: |
mov eax,[draw_data+32+RECT.left] |
inc ebx |
cmp ebx,[draw_data+32+RECT.bottom] |
jg v12dp4 |
jmp v12dp3 |
v12dp4: |
pop edx |
pop ecx |
pop ebx |
pop eax |
ret |
vesa12_drawbar: |
call [_display.disable_mouse] |
;; mov [novesachecksum],dword 0 |
sub edx,ebx |
sub ecx,eax |
push esi |
push edi |
push eax |
push ebx |
push ecx |
push edx |
mov ecx,[TASK_BASE] |
add eax,[ecx-twdw+WDATA.box.left] |
add ebx,[ecx-twdw+WDATA.box.top] |
push eax |
mov eax,ebx ; y |
mov ebx,[BytesPerScanLine] |
mul ebx |
pop ecx |
add eax,ecx ; x |
add eax,ecx |
add eax,ecx |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x start |
jz dbpi2412 |
add eax,ecx |
dbpi2412: |
add eax,VGABasePtr |
mov edi,eax |
; x size |
mov eax,[esp+4] ; [esp+6] |
mov ecx,eax |
add ecx,eax |
add ecx,eax |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size |
jz dbpi24312 |
add ecx,eax |
dbpi24312: |
mov ebx,[esp+0] |
; check limits ? |
push eax |
push ecx |
mov eax,[TASK_BASE] |
mov ecx,[eax+draw_data-CURRENT_TASK+RECT.left] |
cmp ecx,0 |
jnz dbcblimitlset12 |
mov ecx,[eax+draw_data-CURRENT_TASK+RECT.top] |
cmp ecx,0 |
jnz dbcblimitlset12 |
mov ecx,[eax+draw_data-CURRENT_TASK+RECT.right] |
cmp ecx,[Screen_Max_X] |
jnz dbcblimitlset12 |
mov ecx,[eax+draw_data-CURRENT_TASK+RECT.bottom] |
cmp ecx,[Screen_Max_Y] |
jnz dbcblimitlset12 |
pop ecx |
pop eax |
push dword 0 |
jmp dbcblimitlno12 |
dbcblimitlset12: |
pop ecx |
pop eax |
push dword 1 |
dbcblimitlno12: |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? |
jz dbpi24bit12 |
jmp dbpi32bit12 |
; DRAWBAR 24 BBP |
dbpi24bit12: |
push eax |
push ebx |
push edx |
mov eax,ecx |
mov ebx,3 |
div ebx |
mov ecx,eax |
pop edx |
pop ebx |
pop eax |
cld |
dbnewpi12: |
push ebx |
push edi |
push ecx |
xor edx,edx |
mov eax,edi |
sub eax,VGABasePtr |
mov ebx,3 |
div ebx |
add eax, [_WinMapAddress] |
mov ebx,[CURRENT_TASK] |
cld |
dbnp2412: |
mov dl,[eax] |
push eax |
push ecx |
cmp dl,bl |
jnz dbimp24no12 |
cmp [esp+5*4],dword 0 |
jz dbimp24yes12 |
; call dbcplimit |
; jnz dbimp24no12 |
dbimp24yes12: |
push edi |
mov eax,edi |
sub eax,VGABasePtr |
shr eax,16 |
call set_bank |
and edi,0xffff |
add edi,VGABasePtr |
mov eax,[esp+8+3*4+16+4+4] |
stosw |
shr eax,16 |
stosb |
sti |
pop edi |
add edi,3 |
pop ecx |
pop eax |
inc eax |
loop dbnp2412 |
jmp dbnp24d12 |
dbimp24no12: |
pop ecx |
pop eax |
cld |
add edi,3 |
inc eax |
loop dbnp2412 |
dbnp24d12: |
mov eax,[esp+3*4+16+4] |
test eax,0x80000000 |
jz nodbgl2412 |
cmp al,0 |
jz nodbgl2412 |
dec eax |
mov [esp+3*4+16+4],eax |
nodbgl2412: |
pop ecx |
pop edi |
pop ebx |
add edi,[BytesPerScanLine] |
dec ebx |
jz dbnonewpi12 |
jmp dbnewpi12 |
dbnonewpi12: |
add esp,7*4 |
ret |
; DRAWBAR 32 BBP |
dbpi32bit12: |
cld |
shr ecx,2 |
dbnewpi3212: |
push ebx |
push edi |
push ecx |
mov eax,edi |
sub eax,VGABasePtr |
shr eax,2 |
add eax, [_WinMapAddress] |
mov ebx,[CURRENT_TASK] |
cld |
dbnp3212: |
mov dl,[eax] |
push eax |
push ecx |
cmp dl,bl |
jnz dbimp32no12 |
cmp [esp+5*4],dword 0 |
jz dbimp32yes12 |
; call dbcplimit |
; jnz dbimp32no12 |
dbimp32yes12: |
push edi |
mov eax,edi |
sub eax,VGABasePtr |
shr eax,16 |
call set_bank |
and edi,0xffff |
add edi,VGABasePtr |
mov eax,[esp+8+3*4+16+4+4] |
stosw |
shr eax,16 |
stosb |
sti |
pop edi |
add edi,4 |
inc ebp |
pop ecx |
pop eax |
inc eax |
loop dbnp3212 |
jmp dbnp32d12 |
dbimp32no12: |
pop ecx |
pop eax |
inc eax |
add edi,4 |
inc ebp |
loop dbnp3212 |
dbnp32d12: |
mov eax,[esp+12+16+4] |
test eax,0x80000000 |
jz nodbgl3212 |
cmp al,0 |
jz nodbgl3212 |
dec eax |
mov [esp+12+16+4],eax |
nodbgl3212: |
pop ecx |
pop edi |
pop ebx |
add edi,[BytesPerScanLine] |
dec ebx |
jz nodbnewpi3212 |
jmp dbnewpi3212 |
nodbnewpi3212: |
add esp,7*4 |
ret |
Vesa12_putpixel24: |
mov edi,eax ; x |
mov eax,ebx ; y |
lea edi,[edi+edi*2] |
mov ebx,[BytesPerScanLine] |
mul ebx |
add edi,eax |
mov eax,edi |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,VGABasePtr |
mov eax,[esp+28] |
stosw |
shr eax,16 |
mov [edi],al |
sti |
ret |
Vesa12_putpixel32: |
mov edi,eax ; x |
mov eax,ebx ; y |
shl edi,2 |
mov ebx,[BytesPerScanLine] |
mul ebx |
add edi,eax |
mov eax,edi |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,VGABasePtr |
mov ecx,[esp+28] |
mov [edi],ecx |
sti |
ret |
Vesa12_getpixel24: |
mov edi,eax ; x |
mov eax,ebx ; y |
lea edi,[edi+edi*2] |
mov ebx,[BytesPerScanLine] |
mul ebx |
add edi,eax |
mov eax,edi |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,VGABasePtr |
mov ecx,[edi] |
and ecx,255*256*256+255*256+255 |
sti |
ret |
Vesa12_getpixel32: |
mov edi,eax ; x |
mov eax,ebx ; y |
shl edi,2 |
mov ebx,[BytesPerScanLine] |
xor edx,edx |
mul ebx |
add edi,eax |
mov eax,edi |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,VGABasePtr |
mov ecx,[edi] |
and ecx,255*256*256+255*256+255 |
sti |
ret |
vesa12_putimage: |
; ebx = pointer to image |
; ecx = size [x|y] |
; edx = coordinates [x|y] |
; ebp = pointer to 'get' function |
; esi = pointer to 'init' function |
; edi = parameter for 'get' function |
; mov ebx,image |
; mov ecx,320*65536+240 |
; mov edx,20*65536+20 |
call [_display.disable_mouse] |
mov [novesachecksum],dword 0 |
push esi |
push edi |
push eax |
push ebx |
push ecx |
push edx |
movzx eax,word [esp+2] |
movzx ebx,word [esp+0] |
mov ecx,[TASK_BASE] |
add eax,[ecx-twdw+WDATA.box.left] |
add ebx,[ecx-twdw+WDATA.box.top] |
push eax |
mov eax,ebx ; y |
mul dword [BytesPerScanLine] |
pop ecx |
add eax,ecx ; x |
add eax,ecx |
add eax,ecx |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x start |
jz pi2412 |
add eax,ecx |
pi2412: |
add eax,VGABasePtr |
mov edi,eax |
; x size |
movzx ecx,word [esp+6] |
mov esi,[esp+8] |
movzx ebx,word [esp+4] |
; check limits while draw ? |
push ecx |
mov eax,[TASK_BASE] |
cmp dword [eax+draw_data-CURRENT_TASK+RECT.left], 0 |
jnz dbcblimitlset212 |
cmp dword [eax+draw_data-CURRENT_TASK+RECT.top], 0 |
jnz dbcblimitlset212 |
mov ecx,[eax+draw_data-CURRENT_TASK+RECT.right] |
cmp ecx,[Screen_Max_X] |
jnz dbcblimitlset212 |
mov ecx,[eax+draw_data-CURRENT_TASK+RECT.bottom] |
cmp ecx,[Screen_Max_Y] |
jnz dbcblimitlset212 |
pop ecx |
push 0 |
jmp dbcblimitlno212 |
dbcblimitlset212: |
pop ecx |
push 1 |
dbcblimitlno212: |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? |
jnz pi32bit12 |
pi24bit12: |
newpi12: |
push edi |
push ecx |
push ebx |
mov edx,edi |
sub edx,VGABasePtr |
mov ebx,3 |
div ebx |
add edx, [_WinMapAddress] |
mov ebx,[CURRENT_TASK] |
mov bh,[esp+4*3] |
np2412: |
cmp bl,[edx] |
jnz imp24no12 |
; mov eax,[esi] |
push dword [esp+4*3+20] |
call ebp |
; cmp bh,0 |
; jz imp24yes12 |
; call dbcplimit |
; jnz imp24no12 |
imp24yes12: |
push edi |
push eax |
mov eax,edi |
sub eax,VGABasePtr |
shr eax,16 |
call set_bank |
pop eax |
and edi,0xffff |
add edi,VGABasePtr |
mov [edi],ax |
shr eax,16 |
mov [edi+2],al |
pop edi |
imp24no12: |
inc edx |
; add esi,3 |
add edi,3 |
dec ecx |
jnz np2412 |
np24d12: |
pop ebx |
pop ecx |
pop edi |
add edi,[BytesPerScanLine] |
add esi,[esp+32] |
cmp ebp,putimage_get1bpp |
jz .correct |
cmp ebp,putimage_get2bpp |
jz .correct |
cmp ebp,putimage_get4bpp |
jnz @f |
.correct: |
mov eax,[esp+20] |
mov byte[eax],80h |
@@: |
dec ebx |
jnz newpi12 |
nonewpi12: |
pop eax edx ecx ebx eax edi esi |
xor eax, eax |
ret |
pi32bit12: |
newpi3212: |
push edi |
push ecx |
push ebx |
mov edx,edi |
sub edx,VGABasePtr |
shr edx,2 |
add edx, [_WinMapAddress] |
mov ebx,[CURRENT_TASK] |
mov bh,[esp+4*3] |
np3212: |
cmp bl,[edx] |
jnz imp32no12 |
; mov eax,[esi] |
push dword [esp+4*3+20] |
call ebp |
; cmp bh,0 |
; jz imp32yes12 |
; call dbcplimit |
; jnz imp32no12 |
imp32yes12: |
push edi |
push eax |
mov eax,edi |
sub eax,VGABasePtr |
shr eax,16 |
call set_bank |
pop eax |
and edi,0xffff |
mov [edi+VGABasePtr],eax |
pop edi |
imp32no12: |
inc edx |
; add esi,3 |
add edi,4 |
dec ecx |
jnz np3212 |
np32d12: |
pop ebx |
pop ecx |
pop edi |
add edi,[BytesPerScanLine] |
cmp ebp,putimage_get1bpp |
jz .correct |
cmp ebp,putimage_get2bpp |
jz .correct |
cmp ebp,putimage_get4bpp |
jnz @f |
.correct: |
mov eax,[esp+20] |
mov byte[eax],80h |
@@: |
dec ebx |
jnz newpi3212 |
nonewpi3212: |
pop eax edx ecx ebx eax edi esi |
xor eax, eax |
ret |
vesa12_read_screen_pixel: |
and eax,0x3FFFFF |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? |
jz v12rsp24 |
mov edi,eax |
shl edi,2 |
mov eax,edi |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,VGABasePtr |
mov eax,[edi] |
and eax,0x00ffffff |
ret |
v12rsp24: |
imul eax,3 |
mov edi,eax |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,VGABasePtr |
mov eax,[edi] |
and eax,0x00ffffff |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; VESA12.INC ;; |
;; ;; |
;; Vesa 1.2 functions for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Ville Turjanmaa ;; |
;; ;; |
;; quickcode@mail.ru - bankswitch for S3 cards ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
TRIDENT equ 0 |
S3_VIDEO equ 0 |
INTEL_VIDEO equ 0 |
if TRIDENT |
if S3_VIDEO or INTEL_VIDEO |
stop |
end if |
end if |
if S3_VIDEO |
if TRIDENT or INTEL_VIDEO |
stop |
end if |
end if |
if INTEL_VIDEO |
if S3_VIDEO or TRIDENT |
stop |
end if |
end if |
; A complete video driver should include the following types of function |
; |
; Putpixel |
; Getpixel |
; |
; Drawimage |
; Drawbar |
; |
; Drawbackground |
; |
; |
; Modifying the set_bank -function is mostly enough |
; for different Vesa 1.2 setups. |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
; set_bank for Trident videocards, work on Trident 9440 |
; modified by Mario79 |
if TRIDENT |
set_bank: |
pushfd |
cli |
cmp al, [BANK_RW] |
je .retsb |
mov [BANK_RW], al |
push dx |
mov dx, 3D8h |
out dx, al |
pop dx |
.retsb: |
popfd |
ret |
end if |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
; set_bank for S3 videocards, work on S3 ViRGE PCI (325) |
; modified by kmeaw |
if S3_VIDEO |
set_bank: |
pushfd |
cli |
cmp al, [BANK_RW] |
je .retsb |
mov [BANK_RW], al |
push ax |
push dx |
push cx |
mov cl, al |
mov dx, 0x3D4 |
mov al, 0x38 |
out dx, al ;CR38 Register Lock 1 ;Note: Traditionally 48h is used to |
;unlock and 00h to lock |
inc dx |
mov al, 0x48 |
out dx, al ;3d5 -? |
dec dx |
mov al, 0x31 |
out dx, al ;CR31 Memory Configuration Register |
;0 Enable Base Address Offset (CPUA BASE). Enables bank operation if set, ;disables if clear. |
;4-5 Bit 16-17 of the Display Start Address. For the 801/5,928 see index 51h, |
;for the 864/964 see index 69h. |
inc dx |
in al, dx |
dec dx |
mov ah, al |
mov al, 0x31 |
out dx, ax |
mov al, ah |
or al, 9 |
inc dx |
out dx, al |
dec dx |
mov al, 0x35 |
out dx, al ;CR35 CRT Register Lock |
inc dx |
in al, dx |
dec dx |
and al, 0xF0 |
mov ch, cl |
and ch, 0x0F |
or ch, al |
mov al, 0x35 |
out dx, al |
inc dx |
mov al, ch |
out dx, ax |
dec dx |
mov al, 0x51 ;Extended System Control 2 Register |
out dx, al |
inc dx |
in al, dx |
dec dx |
and al, 0xF3 |
shr cl, 2 |
and cl, 0x0C |
or cl, al |
mov al, 0x51 |
out dx, al |
inc dx |
mov al, cl |
out dx, al |
dec dx |
mov al, 0x38 |
out dx, al |
inc dx |
xor al, al |
out dx, al |
dec dx |
pop cx |
pop dx |
pop ax |
.retsb: |
popfd |
ret |
end if |
;Set bank function for Intel 810/815 chipsets |
; *****Modified by Protopopius, Russia.***** |
; ********* http://menuetos.hut.ru ************** |
; ************************************************ |
if INTEL_VIDEO |
set_bank: |
pushfd |
cli |
cmp al, [BANK_RW] |
je .retsb |
mov [BANK_RW], al |
push ax |
push dx |
mov dx, 3CEh |
mov ah, al ; Save value for later use |
mov al, 10h ; Index GR10 (Address Mapping) |
out dx, al ; Select GR10 |
inc dl |
mov al, 3 ; Set bits 0 and 1 (Enable linear page mapping) |
out dx, al ; Write value |
dec dl |
mov al, 11h ; Index GR11 (Page Selector) |
out dx, al ; Select GR11 |
inc dl |
mov al, ah ; Write address |
out dx, al ; Write the value |
pop dx |
pop ax |
.retsb: |
popfd |
ret |
end if |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} |
if (TRIDENT or S3_VIDEO or INTEL_VIDEO) |
else |
set_bank: |
pushfd |
cli |
cmp al, [BANK_RW] |
je .retsb |
mov [BANK_RW], al |
push ax |
push dx |
mov ah, al |
mov dx, 0x03D4 |
mov al, 0x39 |
out dx, al |
inc dl |
mov al, 0xA5 |
out dx, al |
dec dl |
mov al, 6Ah |
out dx, al |
inc dl |
mov al, ah |
out dx, al |
dec dl |
mov al, 0x39 |
out dx, al |
inc dl |
mov al, 0x5A |
out dx, al |
dec dl |
pop dx |
pop ax |
.retsb: |
popfd |
ret |
end if |
vesa12_drawbackground: |
call [_display.disable_mouse] |
push eax |
push ebx |
push ecx |
push edx |
xor edx, edx |
mov eax, dword[BgrDataWidth] |
mov ebx, dword[BgrDataHeight] |
mul ebx |
mov ebx, 3 |
mul ebx |
mov [imax], eax |
mov eax, [draw_data+32+RECT.left] |
mov ebx, [draw_data+32+RECT.top] |
xor edi, edi;no force |
v12dp3: |
push eax |
push ebx |
cmp [BgrDrawMode], dword 1 ; tiled background |
jne no_vesa12_tiled_bgr |
push edx |
xor edx, edx |
div dword [BgrDataWidth] |
push edx |
mov eax, ebx |
xor edx, edx |
div dword [BgrDataHeight] |
mov ebx, edx |
pop eax |
pop edx |
no_vesa12_tiled_bgr: |
cmp [BgrDrawMode], dword 2 ; stretched background |
jne no_vesa12_stretched_bgr |
push edx |
mul dword [BgrDataWidth] |
mov ecx, [Screen_Max_X] |
inc ecx |
div ecx |
push eax |
mov eax, ebx |
mul dword [BgrDataHeight] |
mov ecx, [Screen_Max_Y] |
inc ecx |
div ecx |
mov ebx, eax |
pop eax |
pop edx |
no_vesa12_stretched_bgr: |
mov esi, ebx |
imul esi, dword [BgrDataWidth] |
add esi, eax |
lea esi, [esi*3] |
add esi, [img_background];IMG_BACKGROUND |
pop ebx |
pop eax |
v12di4: |
mov cl, [esi+2] |
shl ecx, 16 |
mov cx, [esi] |
pusha |
mov esi, eax |
mov edi, ebx |
mov eax, [Screen_Max_X] |
add eax, 1 |
mul ebx |
add eax, [_WinMapAddress] |
cmp [eax+esi], byte 1 |
jnz v12nbgp |
mov eax, [BytesPerScanLine] |
mov ebx, edi |
mul ebx |
add eax, esi |
lea eax, [VGABasePtr+eax+esi*2] |
cmp [ScreenBPP], byte 24 |
jz v12bgl3 |
add eax, esi |
v12bgl3: |
push ebx |
push eax |
sub eax, VGABasePtr |
shr eax, 16 |
call set_bank |
pop eax |
and eax, 65535 |
add eax, VGABasePtr |
pop ebx |
mov [eax], cx |
add eax, 2 |
shr ecx, 16 |
mov [eax], cl |
sti |
v12nbgp: |
popa |
add esi, 3 |
inc eax |
cmp eax, [draw_data+32+RECT.right] |
jg v12nodp31 |
jmp v12dp3 |
v12nodp31: |
mov eax, [draw_data+32+RECT.left] |
inc ebx |
cmp ebx, [draw_data+32+RECT.bottom] |
jg v12dp4 |
jmp v12dp3 |
v12dp4: |
pop edx |
pop ecx |
pop ebx |
pop eax |
ret |
vesa12_drawbar: |
call [_display.disable_mouse] |
;; mov [novesachecksum],dword 0 |
sub edx, ebx |
sub ecx, eax |
push esi |
push edi |
push eax |
push ebx |
push ecx |
push edx |
mov ecx, [TASK_BASE] |
add eax, [ecx-twdw+WDATA.box.left] |
add ebx, [ecx-twdw+WDATA.box.top] |
push eax |
mov eax, ebx ; y |
mov ebx, [BytesPerScanLine] |
mul ebx |
pop ecx |
add eax, ecx ; x |
add eax, ecx |
add eax, ecx |
cmp [ScreenBPP], byte 24; 24 or 32 bpp ? - x start |
jz dbpi2412 |
add eax, ecx |
dbpi2412: |
add eax, VGABasePtr |
mov edi, eax |
; x size |
mov eax, [esp+4]; [esp+6] |
mov ecx, eax |
add ecx, eax |
add ecx, eax |
cmp [ScreenBPP], byte 24; 24 or 32 bpp ? - x size |
jz dbpi24312 |
add ecx, eax |
dbpi24312: |
mov ebx, [esp+0] |
; check limits ? |
push eax |
push ecx |
mov eax, [TASK_BASE] |
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.left] |
cmp ecx, 0 |
jnz dbcblimitlset12 |
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.top] |
cmp ecx, 0 |
jnz dbcblimitlset12 |
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.right] |
cmp ecx, [Screen_Max_X] |
jnz dbcblimitlset12 |
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.bottom] |
cmp ecx, [Screen_Max_Y] |
jnz dbcblimitlset12 |
pop ecx |
pop eax |
push dword 0 |
jmp dbcblimitlno12 |
dbcblimitlset12: |
pop ecx |
pop eax |
push dword 1 |
dbcblimitlno12: |
cmp [ScreenBPP], byte 24; 24 or 32 bpp ? |
jz dbpi24bit12 |
jmp dbpi32bit12 |
; DRAWBAR 24 BBP |
dbpi24bit12: |
push eax |
push ebx |
push edx |
mov eax, ecx |
mov ebx, 3 |
div ebx |
mov ecx, eax |
pop edx |
pop ebx |
pop eax |
cld |
dbnewpi12: |
push ebx |
push edi |
push ecx |
xor edx, edx |
mov eax, edi |
sub eax, VGABasePtr |
mov ebx, 3 |
div ebx |
add eax, [_WinMapAddress] |
mov ebx, [CURRENT_TASK] |
cld |
dbnp2412: |
mov dl, [eax] |
push eax |
push ecx |
cmp dl, bl |
jnz dbimp24no12 |
cmp [esp+5*4], dword 0 |
jz dbimp24yes12 |
; call dbcplimit |
; jnz dbimp24no12 |
dbimp24yes12: |
push edi |
mov eax, edi |
sub eax, VGABasePtr |
shr eax, 16 |
call set_bank |
and edi, 0xffff |
add edi, VGABasePtr |
mov eax, [esp+8+3*4+16+4+4] |
stosw |
shr eax, 16 |
stosb |
sti |
pop edi |
add edi, 3 |
pop ecx |
pop eax |
inc eax |
loop dbnp2412 |
jmp dbnp24d12 |
dbimp24no12: |
pop ecx |
pop eax |
cld |
add edi, 3 |
inc eax |
loop dbnp2412 |
dbnp24d12: |
mov eax, [esp+3*4+16+4] |
test eax, 0x80000000 |
jz nodbgl2412 |
cmp al, 0 |
jz nodbgl2412 |
dec eax |
mov [esp+3*4+16+4], eax |
nodbgl2412: |
pop ecx |
pop edi |
pop ebx |
add edi, [BytesPerScanLine] |
dec ebx |
jz dbnonewpi12 |
jmp dbnewpi12 |
dbnonewpi12: |
add esp, 7*4 |
ret |
; DRAWBAR 32 BBP |
dbpi32bit12: |
cld |
shr ecx, 2 |
dbnewpi3212: |
push ebx |
push edi |
push ecx |
mov eax, edi |
sub eax, VGABasePtr |
shr eax, 2 |
add eax, [_WinMapAddress] |
mov ebx, [CURRENT_TASK] |
cld |
dbnp3212: |
mov dl, [eax] |
push eax |
push ecx |
cmp dl, bl |
jnz dbimp32no12 |
cmp [esp+5*4], dword 0 |
jz dbimp32yes12 |
; call dbcplimit |
; jnz dbimp32no12 |
dbimp32yes12: |
push edi |
mov eax, edi |
sub eax, VGABasePtr |
shr eax, 16 |
call set_bank |
and edi, 0xffff |
add edi, VGABasePtr |
mov eax, [esp+8+3*4+16+4+4] |
stosw |
shr eax, 16 |
stosb |
sti |
pop edi |
add edi, 4 |
inc ebp |
pop ecx |
pop eax |
inc eax |
loop dbnp3212 |
jmp dbnp32d12 |
dbimp32no12: |
pop ecx |
pop eax |
inc eax |
add edi, 4 |
inc ebp |
loop dbnp3212 |
dbnp32d12: |
mov eax, [esp+12+16+4] |
test eax, 0x80000000 |
jz nodbgl3212 |
cmp al, 0 |
jz nodbgl3212 |
dec eax |
mov [esp+12+16+4], eax |
nodbgl3212: |
pop ecx |
pop edi |
pop ebx |
add edi, [BytesPerScanLine] |
dec ebx |
jz nodbnewpi3212 |
jmp dbnewpi3212 |
nodbnewpi3212: |
add esp, 7*4 |
ret |
Vesa12_putpixel24: |
mov edi, eax; x |
mov eax, ebx; y |
lea edi, [edi+edi*2] |
mov ebx, [BytesPerScanLine] |
mul ebx |
add edi, eax |
mov eax, edi |
shr eax, 16 |
call set_bank |
and edi, 65535 |
add edi, VGABasePtr |
mov eax, [esp+28] |
stosw |
shr eax, 16 |
mov [edi], al |
sti |
ret |
Vesa12_putpixel32: |
mov edi, eax; x |
mov eax, ebx; y |
shl edi, 2 |
mov ebx, [BytesPerScanLine] |
mul ebx |
add edi, eax |
mov eax, edi |
shr eax, 16 |
call set_bank |
and edi, 65535 |
add edi, VGABasePtr |
mov ecx, [esp+28] |
mov [edi], ecx |
sti |
ret |
Vesa12_getpixel24: |
mov edi, eax; x |
mov eax, ebx; y |
lea edi, [edi+edi*2] |
mov ebx, [BytesPerScanLine] |
mul ebx |
add edi, eax |
mov eax, edi |
shr eax, 16 |
call set_bank |
and edi, 65535 |
add edi, VGABasePtr |
mov ecx, [edi] |
and ecx, 255*256*256+255*256+255 |
sti |
ret |
Vesa12_getpixel32: |
mov edi, eax; x |
mov eax, ebx; y |
shl edi, 2 |
mov ebx, [BytesPerScanLine] |
xor edx, edx |
mul ebx |
add edi, eax |
mov eax, edi |
shr eax, 16 |
call set_bank |
and edi, 65535 |
add edi, VGABasePtr |
mov ecx, [edi] |
and ecx, 255*256*256+255*256+255 |
sti |
ret |
vesa12_putimage: |
; ebx = pointer to image |
; ecx = size [x|y] |
; edx = coordinates [x|y] |
; ebp = pointer to 'get' function |
; esi = pointer to 'init' function |
; edi = parameter for 'get' function |
; mov ebx,image |
; mov ecx,320*65536+240 |
; mov edx,20*65536+20 |
call [_display.disable_mouse] |
mov [novesachecksum], dword 0 |
push esi |
push edi |
push eax |
push ebx |
push ecx |
push edx |
movzx eax, word [esp+2] |
movzx ebx, word [esp+0] |
mov ecx, [TASK_BASE] |
add eax, [ecx-twdw+WDATA.box.left] |
add ebx, [ecx-twdw+WDATA.box.top] |
push eax |
mov eax, ebx ; y |
mul dword [BytesPerScanLine] |
pop ecx |
add eax, ecx ; x |
add eax, ecx |
add eax, ecx |
cmp [ScreenBPP], byte 24; 24 or 32 bpp ? - x start |
jz pi2412 |
add eax, ecx |
pi2412: |
add eax, VGABasePtr |
mov edi, eax |
; x size |
movzx ecx, word [esp+6] |
mov esi, [esp+8] |
movzx ebx, word [esp+4] |
; check limits while draw ? |
push ecx |
mov eax, [TASK_BASE] |
cmp dword [eax+draw_data-CURRENT_TASK+RECT.left], 0 |
jnz dbcblimitlset212 |
cmp dword [eax+draw_data-CURRENT_TASK+RECT.top], 0 |
jnz dbcblimitlset212 |
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.right] |
cmp ecx, [Screen_Max_X] |
jnz dbcblimitlset212 |
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.bottom] |
cmp ecx, [Screen_Max_Y] |
jnz dbcblimitlset212 |
pop ecx |
push 0 |
jmp dbcblimitlno212 |
dbcblimitlset212: |
pop ecx |
push 1 |
dbcblimitlno212: |
cmp [ScreenBPP], byte 24; 24 or 32 bpp ? |
jnz pi32bit12 |
pi24bit12: |
newpi12: |
push edi |
push ecx |
push ebx |
mov edx, edi |
sub edx, VGABasePtr |
mov ebx, 3 |
div ebx |
add edx, [_WinMapAddress] |
mov ebx, [CURRENT_TASK] |
mov bh, [esp+4*3] |
np2412: |
cmp bl, [edx] |
jnz imp24no12 |
; mov eax,[esi] |
push dword [esp+4*3+20] |
call ebp |
; cmp bh,0 |
; jz imp24yes12 |
; call dbcplimit |
; jnz imp24no12 |
imp24yes12: |
push edi |
push eax |
mov eax, edi |
sub eax, VGABasePtr |
shr eax, 16 |
call set_bank |
pop eax |
and edi, 0xffff |
add edi, VGABasePtr |
mov [edi], ax |
shr eax, 16 |
mov [edi+2], al |
pop edi |
imp24no12: |
inc edx |
; add esi,3 |
add edi, 3 |
dec ecx |
jnz np2412 |
np24d12: |
pop ebx |
pop ecx |
pop edi |
add edi, [BytesPerScanLine] |
add esi, [esp+32] |
cmp ebp, putimage_get1bpp |
jz .correct |
cmp ebp, putimage_get2bpp |
jz .correct |
cmp ebp, putimage_get4bpp |
jnz @f |
.correct: |
mov eax, [esp+20] |
mov byte[eax], 80h |
@@: |
dec ebx |
jnz newpi12 |
nonewpi12: |
pop eax edx ecx ebx eax edi esi |
xor eax, eax |
ret |
pi32bit12: |
newpi3212: |
push edi |
push ecx |
push ebx |
mov edx, edi |
sub edx, VGABasePtr |
shr edx, 2 |
add edx, [_WinMapAddress] |
mov ebx, [CURRENT_TASK] |
mov bh, [esp+4*3] |
np3212: |
cmp bl, [edx] |
jnz imp32no12 |
; mov eax,[esi] |
push dword [esp+4*3+20] |
call ebp |
; cmp bh,0 |
; jz imp32yes12 |
; call dbcplimit |
; jnz imp32no12 |
imp32yes12: |
push edi |
push eax |
mov eax, edi |
sub eax, VGABasePtr |
shr eax, 16 |
call set_bank |
pop eax |
and edi, 0xffff |
mov [edi+VGABasePtr], eax |
pop edi |
imp32no12: |
inc edx |
; add esi,3 |
add edi, 4 |
dec ecx |
jnz np3212 |
np32d12: |
pop ebx |
pop ecx |
pop edi |
add edi, [BytesPerScanLine] |
cmp ebp, putimage_get1bpp |
jz .correct |
cmp ebp, putimage_get2bpp |
jz .correct |
cmp ebp, putimage_get4bpp |
jnz @f |
.correct: |
mov eax, [esp+20] |
mov byte[eax], 80h |
@@: |
dec ebx |
jnz newpi3212 |
nonewpi3212: |
pop eax edx ecx ebx eax edi esi |
xor eax, eax |
ret |
vesa12_read_screen_pixel: |
and eax, 0x3FFFFF |
cmp [ScreenBPP], byte 24; 24 or 32 bpp ? |
jz v12rsp24 |
mov edi, eax |
shl edi, 2 |
mov eax, edi |
shr eax, 16 |
call set_bank |
and edi, 65535 |
add edi, VGABasePtr |
mov eax, [edi] |
and eax, 0x00ffffff |
ret |
v12rsp24: |
imul eax, 3 |
mov edi, eax |
shr eax, 16 |
call set_bank |
and edi, 65535 |
add edi, VGABasePtr |
mov eax, [edi] |
and eax, 0x00ffffff |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/video/vesa20.inc |
---|
1,1150 → 1,1150 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; VESA20.INC ;; |
;; ;; |
;; Vesa 2.0 functions for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Ville Turjanmaa ;; |
;; Alexey, kgaz@crosswindws.net ;; |
;; - Voodoo compatible graphics ;; |
;; Juan M. Caravaca ;; |
;; - Graphics optimimizations eg. drawline ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; If you're planning to write your own video driver I suggest |
; you replace the VESA12.INC file and see those instructions. |
;Screen_Max_X equ 0xfe00 |
;Screen_Max_Y equ 0xfe04 |
;BytesPerScanLine equ 0xfe08 |
;LFBAddress equ 0xfe80 |
;ScreenBPP equ 0xfbf1 |
;************************************************* |
; getpixel |
; |
; in: |
; eax = x coordinate |
; ebx = y coordinate |
; |
; ret: |
; ecx = 00 RR GG BB |
getpixel: |
push eax ebx edx edi |
call dword [GETPIXEL] |
pop edi edx ebx eax |
ret |
Vesa20_getpixel24: |
; eax = x |
; ebx = y |
imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier |
lea edi, [eax+eax*2] ; edi = x*3 |
add edi, ebx ; edi = x*3+(y*y multiplier) |
mov ecx, [LFB_BASE+edi] |
and ecx, 0xffffff |
ret |
Vesa20_getpixel32: |
imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier |
lea edi, [ebx+eax*4] ; edi = x*4+(y*y multiplier) |
mov ecx, [LFB_BASE+edi] |
and ecx, 0xffffff |
ret |
;************************************************* |
virtual at esp |
putimg: |
.real_sx dd ? |
.real_sy dd ? |
.image_sx dd ? |
.image_sy dd ? |
.image_cx dd ? |
.image_cy dd ? |
.pti dd ? |
.abs_cx dd ? |
.abs_cy dd ? |
.line_increment dd ? |
.winmap_newline dd ? |
.screen_newline dd ? |
.stack_data = 4*12 |
.edi dd ? |
.esi dd ? |
.ebp dd ? |
.esp dd ? |
.ebx dd ? |
.edx dd ? |
.ecx dd ? |
.eax dd ? |
.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 |
call [_display.disable_mouse] |
sub esp, putimg.stack_data |
; save pointer to image |
mov [putimg.pti], ebx |
; unpack the size |
mov eax, ecx |
and ecx, 0xFFFF |
shr eax, 16 |
mov [putimg.image_sx], eax |
mov [putimg.image_sy], ecx |
; unpack the coordinates |
mov eax, edx |
and edx, 0xFFFF |
shr eax, 16 |
mov [putimg.image_cx], eax |
mov [putimg.image_cy], edx |
; calculate absolute (i.e. screen) coordinates |
mov eax, [TASK_BASE] |
mov ebx, [eax-twdw + WDATA.box.left] |
add ebx, [putimg.image_cx] |
mov [putimg.abs_cx], ebx |
mov ebx, [eax-twdw + WDATA.box.top] |
add ebx, [putimg.image_cy] |
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] |
sub ebx, [putimg.image_cx] |
ja @f |
add esp, putimg.stack_data |
popad |
ret |
@@: |
cmp ebx, [putimg.image_sx] |
jbe .end_x |
mov ebx, [putimg.image_sx] |
.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 |
@@: |
cmp ebx, [putimg.image_sy] |
jbe .end_y |
mov ebx, [putimg.image_sy] |
.end_y: |
mov [putimg.real_sy], ebx |
; line increment |
mov eax, [putimg.image_sx] |
mov ecx, [putimg.real_sx] |
sub eax, ecx |
;; imul eax, [putimg.source_bpp] |
; lea eax, [eax + eax * 2] |
call esi |
add eax, [putimg.arg_0] |
mov [putimg.line_increment], eax |
; winmap new line increment |
mov eax, [Screen_Max_X] |
inc eax |
sub eax, [putimg.real_sx] |
mov [putimg.winmap_newline], eax |
; screen new line increment |
mov eax, [BytesPerScanLine] |
movzx ebx, byte [ScreenBPP] |
shr ebx, 3 |
imul ecx, ebx |
sub eax, ecx |
mov [putimg.screen_newline], eax |
; pointer to image |
mov esi, [putimg.pti] |
; pointer to screen |
mov edx, [putimg.abs_cy] |
imul edx, [BytesPerScanLine] |
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] |
add eax, [putimg.abs_cx] |
add eax, [_WinMapAddress] |
xchg eax, ebp |
; get process number |
mov ebx, [CURRENT_TASK] |
cmp byte [ScreenBPP], 32 |
je put_image_end_32 |
;put_image_end_24: |
mov edi, [putimg.real_sy] |
align 4 |
.new_line: |
mov ecx, [putimg.real_sx] |
; push ebp edx |
align 4 |
.new_x: |
push [putimg.edi] |
mov eax, [putimg.ebp+4] |
call eax |
cmp [ebp], bl |
jne .skip |
; mov eax, [esi] ; eax = RRBBGGRR |
mov [LFB_BASE+edx], ax |
shr eax, 16 |
mov [LFB_BASE+edx+2], al |
.skip: |
; add esi, 3 ;[putimg.source_bpp] |
add edx, 3 |
inc ebp |
dec ecx |
jnz .new_x |
; pop edx ebp |
add esi, [putimg.line_increment] |
add edx, [putimg.screen_newline] ;[BytesPerScanLine] |
add ebp, [putimg.winmap_newline] ;[Screen_Max_X] |
; inc ebp |
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 |
put_image_end_32: |
mov edi, [putimg.real_sy] |
align 4 |
.new_line: |
mov ecx, [putimg.real_sx] |
; push ebp edx |
align 4 |
.new_x: |
push [putimg.edi] |
mov eax, [putimg.ebp+4] |
call eax |
cmp [ebp], bl |
jne .skip |
; mov eax, [esi] ; ecx = RRBBGGRR |
mov [LFB_BASE+edx], eax |
.skip: |
; add esi, [putimg.source_bpp] |
add edx, 4 |
inc ebp |
dec ecx |
jnz .new_x |
; pop edx ebp |
add esi, [putimg.line_increment] |
add edx, [putimg.screen_newline] ;[BytesPerScanLine] |
add ebp, [putimg.winmap_newline] ;[Screen_Max_X] |
; inc ebp |
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 |
call VGA__putimage |
mov [EGA_counter],1 |
ret |
;************************************************* |
align 4 |
__sys_putpixel: |
; eax = x coordinate |
; ebx = y coordinate |
; ecx = ?? RR GG BB ; 0x01000000 negation |
; edi = 0x00000001 force |
;;; mov [novesachecksum], dword 0 |
pushad |
cmp [Screen_Max_X], eax |
jb .exit |
cmp [Screen_Max_Y], ebx |
jb .exit |
test edi,1 ; force ? |
jnz .forced |
; not forced: |
push eax |
mov edx,[_display.width] ; screen x size |
imul edx, ebx |
add eax, [_WinMapAddress] |
movzx edx, byte [eax+edx] |
cmp edx, [CURRENT_TASK] |
pop eax |
jne .exit |
.forced: |
; check if negation |
test ecx,0x01000000 |
jz .noneg |
call getpixel |
not ecx |
mov [esp+32-8],ecx |
.noneg: |
; OK to set pixel |
call dword [PUTPIXEL] ; call the real put_pixel function |
.exit: |
popad |
ret |
align 4 |
Vesa20_putpixel24: |
; eax = x |
; ebx = y |
imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier |
lea edi, [eax+eax*2] ; edi = x*3 |
mov eax, [esp+32-8+4] |
mov [LFB_BASE+ebx+edi], ax |
shr eax, 16 |
mov [LFB_BASE+ebx+edi+2], al |
ret |
align 4 |
Vesa20_putpixel32: |
; eax = x |
; ebx = y |
imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier |
lea edi, [ebx+eax*4] ; edi = x*4+(y*y multiplier) |
mov eax, [esp+32-8+4] ; eax = color |
mov [LFB_BASE+edi], eax |
ret |
;************************************************* |
;align 4 |
calculate_edi: |
mov edi, ebx |
imul edi, [Screen_Max_X] |
add edi, ebx |
add edi, eax |
ret |
;************************************************* |
; DRAWLINE |
align 4 |
__sys_draw_line: |
; inc [mouse_pause] |
call [_display.disable_mouse] |
; draw a line |
; eax = HIWORD = x1 |
; LOWORD = x2 |
; ebx = HIWORD = y1 |
; LOWORD = y2 |
; ecx = color |
; edi = force ? |
pusha |
dl_x1 equ esp+20 |
dl_y1 equ esp+16 |
dl_x2 equ esp+12 |
dl_y2 equ esp+8 |
dl_dx equ esp+4 |
dl_dy equ esp+0 |
xor edx, edx ; clear edx |
xor esi, esi ; unpack arguments |
xor ebp, ebp |
mov si, ax ; esi = x2 |
mov bp, bx ; ebp = y2 |
shr eax, 16 ; eax = x1 |
shr ebx, 16 ; ebx = y1 |
push eax ; save x1 |
push ebx ; save y1 |
push esi ; save x2 |
push ebp ; save y2 |
; checking x-axis... |
sub esi, eax ; esi = x2-x1 |
push esi ; save y2-y1 |
jl .x2lx1 ; is x2 less than x1 ? |
jg .no_vline ; x1 > x2 ? |
mov edx, ebp ; else (if x1=x2) |
call vline |
push edx ; necessary to rightly restore stack frame at .exit |
jmp .exit |
.x2lx1: |
neg esi ; get esi absolute value |
.no_vline: |
; checking y-axis... |
sub ebp, ebx ; ebp = y2-y1 |
push ebp ; save y2-y1 |
jl .y2ly1 ; is y2 less than y1 ? |
jg .no_hline ; y1 > y2 ? |
mov edx, [dl_x2] ; else (if y1=y2) |
call hline |
jmp .exit |
.y2ly1: |
neg ebp ; get ebp absolute value |
.no_hline: |
cmp ebp, esi |
jle .x_rules ; |y2-y1| < |x2-x1| ? |
cmp [dl_y2], ebx ; make sure y1 is at the begining |
jge .no_reverse1 |
neg dword [dl_dx] |
mov edx, [dl_x2] |
mov [dl_x2], eax |
mov [dl_x1], edx |
mov edx, [dl_y2] |
mov [dl_y2], ebx |
mov [dl_y1], edx |
.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) |
mov edx, ebp ; edx = counter (number of pixels to draw) |
mov ebp, 1 *65536 ; <<16 ; ebp = dy = 1.0 |
mov esi, eax ; esi = dx |
jmp .y_rules |
.x_rules: |
cmp [dl_x2], eax ; make sure x1 is at the begining |
jge .no_reverse2 |
neg dword [dl_dy] |
mov edx, [dl_x2] |
mov [dl_x2], eax |
mov [dl_x1], edx |
mov edx, [dl_y2] |
mov [dl_y2], ebx |
mov [dl_y1], edx |
.no_reverse2: |
xor edx, edx |
mov eax, [dl_dy] |
cdq ; extend eax sing to edx |
shl eax, 16 ; using 16bit fix-point maths |
idiv esi ; eax = ((y2-y1)*65536)/(x2-x1) |
mov edx, esi ; edx = counter (number of pixels to draw) |
mov esi, 1 *65536 ;<< 16 ; esi = dx = 1.0 |
mov ebp, eax ; ebp = dy |
.y_rules: |
mov eax, [dl_x1] |
mov ebx, [dl_y1] |
shl eax, 16 |
shl ebx, 16 |
align 4 |
.draw: |
push eax ebx |
shr eax, 16 |
shr ebx, 16 |
call [putpixel] |
pop ebx eax |
add ebx, ebp ; y = y+dy |
add eax, esi ; x = x+dx |
dec edx |
jnz .draw |
; force last drawn pixel to be at (x2,y2) |
mov eax, [dl_x2] |
mov ebx, [dl_y2] |
call [putpixel] |
.exit: |
add esp, 6*4 |
popa |
; dec [mouse_pause] |
call [draw_pointer] |
ret |
hline: |
; draw an horizontal line |
; eax = x1 |
; edx = x2 |
; ebx = y |
; ecx = color |
; edi = force ? |
push eax edx |
cmp edx, eax ; make sure x2 is above x1 |
jge @f |
xchg eax, edx |
align 4 |
@@: |
call [putpixel] |
inc eax |
cmp eax, edx |
jle @b |
pop edx eax |
ret |
vline: |
; draw a vertical line |
; eax = x |
; ebx = y1 |
; edx = y2 |
; ecx = color |
; edi = force ? |
push ebx edx |
cmp edx, ebx ; make sure y2 is above y1 |
jge @f |
xchg ebx, edx |
align 4 |
@@: |
call [putpixel] |
inc ebx |
cmp ebx, edx |
jle @b |
pop edx ebx |
ret |
;************************************************* |
virtual at esp |
drbar: |
.bar_sx dd ? |
.bar_sy dd ? |
.bar_cx dd ? |
.bar_cy dd ? |
.abs_cx dd ? |
.abs_cy dd ? |
.real_sx dd ? |
.real_sy dd ? |
.color dd ? |
.line_inc_scr dd ? |
.line_inc_map dd ? |
.stack_data = 4*11 |
end virtual |
align 4 |
; eax cx |
; ebx cy |
; ecx xe |
; edx ye |
; edi color |
vesa20_drawbar: |
pushad |
call [_display.disable_mouse] |
sub esp, drbar.stack_data |
mov [drbar.color], edi |
sub edx, ebx |
jle .exit ;// mike.dld, 2005-01-29 |
sub ecx, eax |
jle .exit ;// mike.dld, 2005-01-29 |
mov [drbar.bar_sy], edx |
mov [drbar.bar_sx], ecx |
mov [drbar.bar_cx], eax |
mov [drbar.bar_cy], ebx |
mov edi, [TASK_BASE] |
add eax, [edi-twdw + WDATA.box.left] ; win_cx |
add ebx, [edi-twdw + WDATA.box.top] ; win_cy |
mov [drbar.abs_cx], eax |
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] |
sub ebx, [drbar.bar_cx] |
ja @f |
.exit: ;// mike.dld, 2005-01-29 |
add esp, drbar.stack_data |
popad |
xor eax, eax |
inc eax |
ret |
@@: |
cmp ebx, [drbar.bar_sx] |
jbe .end_x |
mov ebx, [drbar.bar_sx] |
.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 |
popad |
xor eax, eax |
inc eax |
ret |
@@: |
cmp ebx, [drbar.bar_sy] |
jbe .end_y |
mov ebx, [drbar.bar_sy] |
.end_y: |
mov [drbar.real_sy], ebx |
; line_inc_map |
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] |
movzx ebx, byte [ScreenBPP] |
shr ebx, 3 |
imul eax, ebx |
neg eax |
add eax, [BytesPerScanLine] |
mov [drbar.line_inc_scr], eax |
; pointer to screen |
mov edx, [drbar.abs_cy] |
imul edx, [BytesPerScanLine] |
mov eax, [drbar.abs_cx] |
; movzx ebx, byte [ScreenBPP] |
; shr ebx, 3 |
imul eax, ebx |
add edx, eax |
; pointer to pixel map |
mov eax, [drbar.abs_cy] |
imul eax, [Screen_Max_X] |
add eax, [drbar.abs_cy] |
add eax, [drbar.abs_cx] |
add eax, [_WinMapAddress] |
xchg eax, ebp |
; get process number |
mov ebx, [CURRENT_TASK] |
cmp byte [ScreenBPP], 24 |
jne draw_bar_end_32 |
draw_bar_end_24: |
mov eax, [drbar.color] ;; BBGGRR00 |
mov bh, al ;; bh = BB |
shr eax, 8 ;; eax = RRGG |
; eax - color high RRGG |
; bl - process num |
; bh - color low BB |
; ecx - temp |
; edx - pointer to screen |
; esi - counter |
; edi - counter |
mov esi, [drbar.real_sy] |
align 4 |
.new_y: |
mov edi, [drbar.real_sx] |
align 4 |
.new_x: |
cmp byte [ebp], bl |
jne .skip |
mov [LFB_BASE+edx], bh |
mov [LFB_BASE+edx + 1], ax |
.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] |
; <Ivan 15.10.04> drawing gradient bars |
test eax, 0x00800000 |
jz @f |
test bh, bh |
jz @f |
dec bh |
@@: |
; </Ivan 15.10.04> |
dec esi |
jnz .new_y |
add esp, drbar.stack_data |
popad |
xor eax, eax |
ret |
draw_bar_end_32: |
mov eax, [drbar.color] ;; BBGGRR00 |
mov esi, [drbar.real_sy] |
align 4 |
.new_y: |
mov edi, [drbar.real_sx] |
align 4 |
.new_x: |
cmp byte [ebp], bl |
jne .skip |
mov [LFB_BASE+edx], eax |
.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] |
; <Ivan 15.10.04> drawing gradient bars |
test eax, 0x80000000 |
jz @f |
test al, al |
jz @f |
dec al |
@@: |
; </Ivan 15.10.04> |
dec esi |
jnz .new_y |
add esp, drbar.stack_data |
popad |
call VGA_draw_bar |
xor eax, eax |
mov [EGA_counter],1 |
ret |
align 4 |
vesa20_drawbackground_tiled: |
call [_display.disable_mouse] |
pushad |
; External loop for all y from start to end |
mov ebx, [draw_data+32+RECT.top] ; y start |
dp2: |
mov ebp, [draw_data+32+RECT.left] ; x start |
; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp] |
; and LFB data (output for our function) [edi] |
mov eax, [BytesPerScanLine] |
mul ebx |
xchg ebp, eax |
add ebp, eax |
add ebp, eax |
add ebp, eax |
cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
add ebp, eax |
@@: |
add ebp, LFB_BASE |
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB |
call calculate_edi |
xchg edi, ebp |
add ebp, [_WinMapAddress] |
; Now eax=x, ebx=y, edi->output, ebp=offset in WinMapAddress |
; 2) Calculate offset in background memory block |
push eax |
xor edx, edx |
mov eax, ebx |
div dword [BgrDataHeight] ; edx := y mod BgrDataHeight |
pop eax |
push eax |
mov ecx, [BgrDataWidth] |
mov esi, edx |
imul esi, ecx ; esi := (y mod BgrDataHeight) * BgrDataWidth |
xor edx, edx |
div ecx ; edx := x mod BgrDataWidth |
sub ecx, edx |
add esi, edx ; esi := (y mod BgrDataHeight)*BgrDataWidth + (x mod BgrDataWidth) |
pop eax |
lea esi, [esi*3] |
add esi, [img_background] |
xor edx, edx |
inc edx |
; 3) Loop through redraw rectangle and copy background data |
; Registers meaning: |
; eax = x, ebx = y (screen coordinates) |
; ecx = deltax - number of pixels left in current tile block |
; edx = 1 |
; esi -> bgr memory, edi -> output |
; ebp = offset in WinMapAddress |
dp3: |
cmp [ebp], dl |
jnz nbgp |
movsb |
movsb |
movsb |
jmp @f |
nbgp: |
add esi, 3 |
add edi, 3 |
@@: |
cmp [ScreenBPP], byte 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 ebp, edx |
add eax, edx |
cmp eax, [draw_data+32+RECT.right] |
ja dp4 |
sub ecx, edx |
jnz dp3 |
; next tile block on x-axis |
mov ecx, [BgrDataWidth] |
sub esi, ecx |
sub esi, ecx |
sub esi, ecx |
jmp dp3 |
dp4: |
; next scan line |
inc ebx |
cmp ebx, [draw_data+32+RECT.bottom] |
jbe dp2 |
popad |
mov [EGA_counter], 1 |
call VGA_drawbackground |
ret |
; ---------- |
vesa20_drawbackground_stretch: |
call [_display.disable_mouse] |
pushad |
; Helper variables |
; calculate 2^32*(BgrDataWidth-1) mod (ScreenWidth-1) |
mov eax, [BgrDataWidth] |
dec eax |
xor edx, edx |
div dword [Screen_Max_X] |
push eax ; high |
xor eax, eax |
div dword [Screen_Max_X] |
push eax ; low |
; the same for height |
mov eax, [BgrDataHeight] |
dec eax |
xor edx, edx |
div dword [Screen_Max_Y] |
push eax ; high |
xor eax, eax |
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 |
; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp] |
; and LFB data (output for our function) [edi] |
mov eax, [BytesPerScanLine] |
mul ebx |
xchg ebp, eax |
add ebp, eax |
add ebp, eax |
add ebp, eax |
cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
add ebp, eax |
@@: |
; 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 |
; 2) Calculate offset in background memory block |
mov eax, ebx |
imul ebx, dword [esp+12] |
mul dword [esp+8] |
add edx, ebx ; edx:eax = y * 2^32*(BgrDataHeight-1)/(ScreenHeight-1) |
mov esi, edx |
imul esi, [BgrDataWidth] |
push edx |
push eax |
mov eax, [esp+8] |
mul dword [esp+28] |
push eax |
mov eax, [esp+12] |
mul dword [esp+28] |
add [esp], edx |
pop edx ; edx:eax = x * 2^32*(BgrDataWidth-1)/(ScreenWidth-1) |
add esi, edx |
lea esi, [esi*3] |
add esi, [img_background] |
push eax |
push edx |
push esi |
; 3) Smooth horizontal |
bgr_resmooth0: |
mov ecx, [esp+8] |
mov edx, [esp+4] |
mov esi, [esp] |
push edi |
mov edi, bgr_cur_line |
call smooth_line |
bgr_resmooth1: |
mov eax, [esp+16+4] |
inc eax |
cmp eax, [BgrDataHeight] |
jae bgr.no2nd |
mov ecx, [esp+8+4] |
mov edx, [esp+4+4] |
mov esi, [esp+4] |
add esi, [BgrDataWidth] |
add esi, [BgrDataWidth] |
add esi, [BgrDataWidth] |
mov edi, bgr_next_line |
call smooth_line |
bgr.no2nd: |
pop edi |
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 |
; ebp = offset in WinMapAddress |
; dword [esp] = offset in bgr data |
; qword [esp+4] = x * 2^32 * (BgrDataWidth-1) / (ScreenWidth-1) |
; qword [esp+12] = y * 2^32 * (BgrDataHeight-1) / (ScreenHeight-1) |
; dword [esp+20] = x |
; dword [esp+24] = y |
; precalculated constants: |
; qword [esp+28] = 2^32*(BgrDataHeight-1)/(ScreenHeight-1) |
; qword [esp+36] = 2^32*(BgrDataWidth-1)/(ScreenWidth-1) |
sdp3a: |
mov eax, [_WinMapAddress] |
cmp [ebp+eax], byte 1 |
jnz snbgp |
mov eax, [bgr_cur_line+esi] |
test ecx, ecx |
jz .novert |
mov ebx, [bgr_next_line+esi] |
call [overlapping_of_points_ptr] |
.novert: |
mov [LFB_BASE+edi], ax |
shr eax, 16 |
mov [LFB_BASE+edi+2], al |
snbgp: |
cmp [ScreenBPP], byte 25 |
sbb edi, -4 |
add ebp, 1 |
mov eax, [esp+20] |
add eax, 1 |
mov [esp+20], eax |
add esi, 4 |
cmp eax, [draw_data+32+RECT.right] |
jbe sdp3a |
sdp4: |
; next y |
mov ebx, [esp+24] |
add ebx, 1 |
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, [Screen_Max_X] |
add ebp, 1 |
sub edi, eax |
sub edi, eax |
sub edi, eax |
cmp [ScreenBPP], byte 24 |
jz @f |
sub edi, eax |
@@: |
add edi, [BytesPerScanLine] |
; restore ecx,edx; advance esi to next background line |
mov eax, [esp+28] |
mov ebx, [esp+32] |
add [esp+12], eax |
mov eax, [esp+16] |
adc [esp+16], ebx |
sub eax, [esp+16] |
mov ebx, eax |
lea eax, [eax*3] |
imul eax, [BgrDataWidth] |
sub [esp], eax |
mov eax, [draw_data+32+RECT.left] |
mov [esp+20], eax |
test ebx, ebx |
jz sdp3 |
cmp ebx, -1 |
jnz bgr_resmooth0 |
push edi |
mov esi, bgr_next_line |
mov edi, bgr_cur_line |
mov ecx, [Screen_Max_X] |
inc ecx |
rep movsd |
jmp bgr_resmooth1 |
sdpdone: |
add esp, 44 |
popad |
mov [EGA_counter],1 |
call VGA_drawbackground |
ret |
uglobal |
align 4 |
bgr_cur_line rd 1920 ; maximum width of screen |
bgr_next_line rd 1920 |
endg |
smooth_line: |
mov al, [esi+2] |
shl eax, 16 |
mov ax, [esi] |
test ecx, ecx |
jz @f |
mov ebx, [esi+2] |
shr ebx, 8 |
call [overlapping_of_points_ptr] |
@@: |
stosd |
mov eax, [esp+20+8] |
add eax, 1 |
mov [esp+20+8], eax |
cmp eax, [draw_data+32+RECT.right] |
ja @f |
add ecx, [esp+36+8] |
mov eax, edx |
adc edx, [esp+40+8] |
sub eax, edx |
lea eax, [eax*3] |
sub esi, eax |
jmp smooth_line |
@@: |
mov eax, [draw_data+32+RECT.left] |
mov [esp+20+8], eax |
ret |
align 16 |
overlapping_of_points: |
if 0 |
; this version of procedure works, but is slower than next version |
push ecx edx |
mov edx, eax |
push esi |
shr ecx, 24 |
mov esi, ecx |
mov ecx, ebx |
movzx ebx, dl |
movzx eax, cl |
sub eax, ebx |
movzx ebx, dh |
imul eax, esi |
add dl, ah |
movzx eax, ch |
sub eax, ebx |
imul eax, esi |
add dh, ah |
ror ecx, 16 |
ror edx, 16 |
movzx eax, cl |
movzx ebx, dl |
sub eax, ebx |
imul eax, esi |
pop esi |
add dl, ah |
mov eax, edx |
pop edx |
ror eax, 16 |
pop ecx |
ret |
else |
push ecx edx |
mov edx, eax |
push esi |
shr ecx, 26 |
mov esi, ecx |
mov ecx, ebx |
shl esi, 9 |
movzx ebx, dl |
movzx eax, cl |
sub eax, ebx |
movzx ebx, dh |
add dl, [BgrAuxTable+(eax+0x100)+esi] |
movzx eax, ch |
sub eax, ebx |
add dh, [BgrAuxTable+(eax+0x100)+esi] |
ror ecx, 16 |
ror edx, 16 |
movzx eax, cl |
movzx ebx, dl |
sub eax, ebx |
add dl, [BgrAuxTable+(eax+0x100)+esi] |
pop esi |
mov eax, edx |
pop edx |
ror eax, 16 |
pop ecx |
ret |
end if |
iglobal |
align 4 |
overlapping_of_points_ptr dd overlapping_of_points |
endg |
init_background: |
mov edi, BgrAuxTable |
xor edx, edx |
.loop2: |
mov eax, edx |
shl eax, 8 |
neg eax |
mov ecx, 0x200 |
.loop1: |
mov byte [edi], ah |
inc edi |
add eax, edx |
loop .loop1 |
add dl, 4 |
jnz .loop2 |
test byte [cpu_caps+(CAPS_MMX/8)], 1 shl (CAPS_MMX mod 8) |
jz @f |
mov [overlapping_of_points_ptr], overlapping_of_points_mmx |
@@: |
ret |
align 16 |
overlapping_of_points_mmx: |
movd mm0, eax |
movd mm4, eax |
movd mm1, ebx |
pxor mm2, mm2 |
punpcklbw mm0, mm2 |
punpcklbw mm1, mm2 |
psubw mm1, mm0 |
movd mm3, ecx |
psrld mm3, 24 |
packuswb mm3, mm3 |
packuswb mm3, mm3 |
pmullw mm1, mm3 |
psrlw mm1, 8 |
packuswb mm1, mm2 |
paddb mm4, mm1 |
movd eax, mm4 |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; VESA20.INC ;; |
;; ;; |
;; Vesa 2.0 functions for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Ville Turjanmaa ;; |
;; Alexey, kgaz@crosswindws.net ;; |
;; - Voodoo compatible graphics ;; |
;; Juan M. Caravaca ;; |
;; - Graphics optimimizations eg. drawline ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; If you're planning to write your own video driver I suggest |
; you replace the VESA12.INC file and see those instructions. |
;Screen_Max_X equ 0xfe00 |
;Screen_Max_Y equ 0xfe04 |
;BytesPerScanLine equ 0xfe08 |
;LFBAddress equ 0xfe80 |
;ScreenBPP equ 0xfbf1 |
;************************************************* |
; getpixel |
; |
; in: |
; eax = x coordinate |
; ebx = y coordinate |
; |
; ret: |
; ecx = 00 RR GG BB |
getpixel: |
push eax ebx edx edi |
call dword [GETPIXEL] |
pop edi edx ebx eax |
ret |
Vesa20_getpixel24: |
; eax = x |
; ebx = y |
imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier |
lea edi, [eax+eax*2]; edi = x*3 |
add edi, ebx ; edi = x*3+(y*y multiplier) |
mov ecx, [LFB_BASE+edi] |
and ecx, 0xffffff |
ret |
Vesa20_getpixel32: |
imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier |
lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier) |
mov ecx, [LFB_BASE+edi] |
and ecx, 0xffffff |
ret |
;************************************************* |
virtual at esp |
putimg: |
.real_sx dd ? |
.real_sy dd ? |
.image_sx dd ? |
.image_sy dd ? |
.image_cx dd ? |
.image_cy dd ? |
.pti dd ? |
.abs_cx dd ? |
.abs_cy dd ? |
.line_increment dd ? |
.winmap_newline dd ? |
.screen_newline dd ? |
.stack_data = 4*12 |
.edi dd ? |
.esi dd ? |
.ebp dd ? |
.esp dd ? |
.ebx dd ? |
.edx dd ? |
.ecx dd ? |
.eax dd ? |
.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 |
call [_display.disable_mouse] |
sub esp, putimg.stack_data |
; save pointer to image |
mov [putimg.pti], ebx |
; unpack the size |
mov eax, ecx |
and ecx, 0xFFFF |
shr eax, 16 |
mov [putimg.image_sx], eax |
mov [putimg.image_sy], ecx |
; unpack the coordinates |
mov eax, edx |
and edx, 0xFFFF |
shr eax, 16 |
mov [putimg.image_cx], eax |
mov [putimg.image_cy], edx |
; calculate absolute (i.e. screen) coordinates |
mov eax, [TASK_BASE] |
mov ebx, [eax-twdw + WDATA.box.left] |
add ebx, [putimg.image_cx] |
mov [putimg.abs_cx], ebx |
mov ebx, [eax-twdw + WDATA.box.top] |
add ebx, [putimg.image_cy] |
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] |
sub ebx, [putimg.image_cx] |
ja @f |
add esp, putimg.stack_data |
popad |
ret |
@@: |
cmp ebx, [putimg.image_sx] |
jbe .end_x |
mov ebx, [putimg.image_sx] |
.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 |
@@: |
cmp ebx, [putimg.image_sy] |
jbe .end_y |
mov ebx, [putimg.image_sy] |
.end_y: |
mov [putimg.real_sy], ebx |
; line increment |
mov eax, [putimg.image_sx] |
mov ecx, [putimg.real_sx] |
sub eax, ecx |
;; imul eax, [putimg.source_bpp] |
; lea eax, [eax + eax * 2] |
call esi |
add eax, [putimg.arg_0] |
mov [putimg.line_increment], eax |
; winmap new line increment |
mov eax, [Screen_Max_X] |
inc eax |
sub eax, [putimg.real_sx] |
mov [putimg.winmap_newline], eax |
; screen new line increment |
mov eax, [BytesPerScanLine] |
movzx ebx, byte [ScreenBPP] |
shr ebx, 3 |
imul ecx, ebx |
sub eax, ecx |
mov [putimg.screen_newline], eax |
; pointer to image |
mov esi, [putimg.pti] |
; pointer to screen |
mov edx, [putimg.abs_cy] |
imul edx, [BytesPerScanLine] |
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] |
add eax, [putimg.abs_cx] |
add eax, [_WinMapAddress] |
xchg eax, ebp |
; get process number |
mov ebx, [CURRENT_TASK] |
cmp byte [ScreenBPP], 32 |
je put_image_end_32 |
;put_image_end_24: |
mov edi, [putimg.real_sy] |
align 4 |
.new_line: |
mov ecx, [putimg.real_sx] |
; push ebp edx |
align 4 |
.new_x: |
push [putimg.edi] |
mov eax, [putimg.ebp+4] |
call eax |
cmp [ebp], bl |
jne .skip |
; mov eax, [esi] ; eax = RRBBGGRR |
mov [LFB_BASE+edx], ax |
shr eax, 16 |
mov [LFB_BASE+edx+2], al |
.skip: |
; add esi, 3 ;[putimg.source_bpp] |
add edx, 3 |
inc ebp |
dec ecx |
jnz .new_x |
; pop edx ebp |
add esi, [putimg.line_increment] |
add edx, [putimg.screen_newline];[BytesPerScanLine] |
add ebp, [putimg.winmap_newline];[Screen_Max_X] |
; inc ebp |
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 |
put_image_end_32: |
mov edi, [putimg.real_sy] |
align 4 |
.new_line: |
mov ecx, [putimg.real_sx] |
; push ebp edx |
align 4 |
.new_x: |
push [putimg.edi] |
mov eax, [putimg.ebp+4] |
call eax |
cmp [ebp], bl |
jne .skip |
; mov eax, [esi] ; ecx = RRBBGGRR |
mov [LFB_BASE+edx], eax |
.skip: |
; add esi, [putimg.source_bpp] |
add edx, 4 |
inc ebp |
dec ecx |
jnz .new_x |
; pop edx ebp |
add esi, [putimg.line_increment] |
add edx, [putimg.screen_newline];[BytesPerScanLine] |
add ebp, [putimg.winmap_newline];[Screen_Max_X] |
; inc ebp |
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 |
call VGA__putimage |
mov [EGA_counter], 1 |
ret |
;************************************************* |
align 4 |
__sys_putpixel: |
; eax = x coordinate |
; ebx = y coordinate |
; ecx = ?? RR GG BB ; 0x01000000 negation |
; edi = 0x00000001 force |
;;; mov [novesachecksum], dword 0 |
pushad |
cmp [Screen_Max_X], eax |
jb .exit |
cmp [Screen_Max_Y], ebx |
jb .exit |
test edi, 1 ; force ? |
jnz .forced |
; not forced: |
push eax |
mov edx, [_display.width]; screen x size |
imul edx, ebx |
add eax, [_WinMapAddress] |
movzx edx, byte [eax+edx] |
cmp edx, [CURRENT_TASK] |
pop eax |
jne .exit |
.forced: |
; check if negation |
test ecx, 0x01000000 |
jz .noneg |
call getpixel |
not ecx |
mov [esp+32-8], ecx |
.noneg: |
; OK to set pixel |
call dword [PUTPIXEL]; call the real put_pixel function |
.exit: |
popad |
ret |
align 4 |
Vesa20_putpixel24: |
; eax = x |
; ebx = y |
imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier |
lea edi, [eax+eax*2]; edi = x*3 |
mov eax, [esp+32-8+4] |
mov [LFB_BASE+ebx+edi], ax |
shr eax, 16 |
mov [LFB_BASE+ebx+edi+2], al |
ret |
align 4 |
Vesa20_putpixel32: |
; eax = x |
; ebx = y |
imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier |
lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier) |
mov eax, [esp+32-8+4]; eax = color |
mov [LFB_BASE+edi], eax |
ret |
;************************************************* |
;align 4 |
calculate_edi: |
mov edi, ebx |
imul edi, [Screen_Max_X] |
add edi, ebx |
add edi, eax |
ret |
;************************************************* |
; DRAWLINE |
align 4 |
__sys_draw_line: |
; inc [mouse_pause] |
call [_display.disable_mouse] |
; draw a line |
; eax = HIWORD = x1 |
; LOWORD = x2 |
; ebx = HIWORD = y1 |
; LOWORD = y2 |
; ecx = color |
; edi = force ? |
pusha |
dl_x1 equ esp+20 |
dl_y1 equ esp+16 |
dl_x2 equ esp+12 |
dl_y2 equ esp+8 |
dl_dx equ esp+4 |
dl_dy equ esp+0 |
xor edx, edx ; clear edx |
xor esi, esi ; unpack arguments |
xor ebp, ebp |
mov si, ax ; esi = x2 |
mov bp, bx ; ebp = y2 |
shr eax, 16 ; eax = x1 |
shr ebx, 16 ; ebx = y1 |
push eax ; save x1 |
push ebx ; save y1 |
push esi ; save x2 |
push ebp ; save y2 |
; checking x-axis... |
sub esi, eax ; esi = x2-x1 |
push esi ; save y2-y1 |
jl .x2lx1 ; is x2 less than x1 ? |
jg .no_vline ; x1 > x2 ? |
mov edx, ebp ; else (if x1=x2) |
call vline |
push edx ; necessary to rightly restore stack frame at .exit |
jmp .exit |
.x2lx1: |
neg esi ; get esi absolute value |
.no_vline: |
; checking y-axis... |
sub ebp, ebx ; ebp = y2-y1 |
push ebp ; save y2-y1 |
jl .y2ly1 ; is y2 less than y1 ? |
jg .no_hline ; y1 > y2 ? |
mov edx, [dl_x2]; else (if y1=y2) |
call hline |
jmp .exit |
.y2ly1: |
neg ebp ; get ebp absolute value |
.no_hline: |
cmp ebp, esi |
jle .x_rules ; |y2-y1| < |x2-x1| ? |
cmp [dl_y2], ebx; make sure y1 is at the begining |
jge .no_reverse1 |
neg dword [dl_dx] |
mov edx, [dl_x2] |
mov [dl_x2], eax |
mov [dl_x1], edx |
mov edx, [dl_y2] |
mov [dl_y2], ebx |
mov [dl_y1], edx |
.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) |
mov edx, ebp ; edx = counter (number of pixels to draw) |
mov ebp, 1 *65536; <<16 ; ebp = dy = 1.0 |
mov esi, eax ; esi = dx |
jmp .y_rules |
.x_rules: |
cmp [dl_x2], eax ; make sure x1 is at the begining |
jge .no_reverse2 |
neg dword [dl_dy] |
mov edx, [dl_x2] |
mov [dl_x2], eax |
mov [dl_x1], edx |
mov edx, [dl_y2] |
mov [dl_y2], ebx |
mov [dl_y1], edx |
.no_reverse2: |
xor edx, edx |
mov eax, [dl_dy] |
cdq ; extend eax sing to edx |
shl eax, 16 ; using 16bit fix-point maths |
idiv esi ; eax = ((y2-y1)*65536)/(x2-x1) |
mov edx, esi ; edx = counter (number of pixels to draw) |
mov esi, 1 *65536;<< 16 ; esi = dx = 1.0 |
mov ebp, eax ; ebp = dy |
.y_rules: |
mov eax, [dl_x1] |
mov ebx, [dl_y1] |
shl eax, 16 |
shl ebx, 16 |
align 4 |
.draw: |
push eax ebx |
shr eax, 16 |
shr ebx, 16 |
call [putpixel] |
pop ebx eax |
add ebx, ebp ; y = y+dy |
add eax, esi ; x = x+dx |
dec edx |
jnz .draw |
; force last drawn pixel to be at (x2,y2) |
mov eax, [dl_x2] |
mov ebx, [dl_y2] |
call [putpixel] |
.exit: |
add esp, 6*4 |
popa |
; dec [mouse_pause] |
call [draw_pointer] |
ret |
hline: |
; draw an horizontal line |
; eax = x1 |
; edx = x2 |
; ebx = y |
; ecx = color |
; edi = force ? |
push eax edx |
cmp edx, eax ; make sure x2 is above x1 |
jge @f |
xchg eax, edx |
align 4 |
@@: |
call [putpixel] |
inc eax |
cmp eax, edx |
jle @b |
pop edx eax |
ret |
vline: |
; draw a vertical line |
; eax = x |
; ebx = y1 |
; edx = y2 |
; ecx = color |
; edi = force ? |
push ebx edx |
cmp edx, ebx ; make sure y2 is above y1 |
jge @f |
xchg ebx, edx |
align 4 |
@@: |
call [putpixel] |
inc ebx |
cmp ebx, edx |
jle @b |
pop edx ebx |
ret |
;************************************************* |
virtual at esp |
drbar: |
.bar_sx dd ? |
.bar_sy dd ? |
.bar_cx dd ? |
.bar_cy dd ? |
.abs_cx dd ? |
.abs_cy dd ? |
.real_sx dd ? |
.real_sy dd ? |
.color dd ? |
.line_inc_scr dd ? |
.line_inc_map dd ? |
.stack_data = 4*11 |
end virtual |
align 4 |
; eax cx |
; ebx cy |
; ecx xe |
; edx ye |
; edi color |
vesa20_drawbar: |
pushad |
call [_display.disable_mouse] |
sub esp, drbar.stack_data |
mov [drbar.color], edi |
sub edx, ebx |
jle .exit ;// mike.dld, 2005-01-29 |
sub ecx, eax |
jle .exit ;// mike.dld, 2005-01-29 |
mov [drbar.bar_sy], edx |
mov [drbar.bar_sx], ecx |
mov [drbar.bar_cx], eax |
mov [drbar.bar_cy], ebx |
mov edi, [TASK_BASE] |
add eax, [edi-twdw + WDATA.box.left]; win_cx |
add ebx, [edi-twdw + WDATA.box.top]; win_cy |
mov [drbar.abs_cx], eax |
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] |
sub ebx, [drbar.bar_cx] |
ja @f |
.exit: ;// mike.dld, 2005-01-29 |
add esp, drbar.stack_data |
popad |
xor eax, eax |
inc eax |
ret |
@@: |
cmp ebx, [drbar.bar_sx] |
jbe .end_x |
mov ebx, [drbar.bar_sx] |
.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 |
popad |
xor eax, eax |
inc eax |
ret |
@@: |
cmp ebx, [drbar.bar_sy] |
jbe .end_y |
mov ebx, [drbar.bar_sy] |
.end_y: |
mov [drbar.real_sy], ebx |
; line_inc_map |
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] |
movzx ebx, byte [ScreenBPP] |
shr ebx, 3 |
imul eax, ebx |
neg eax |
add eax, [BytesPerScanLine] |
mov [drbar.line_inc_scr], eax |
; pointer to screen |
mov edx, [drbar.abs_cy] |
imul edx, [BytesPerScanLine] |
mov eax, [drbar.abs_cx] |
; movzx ebx, byte [ScreenBPP] |
; shr ebx, 3 |
imul eax, ebx |
add edx, eax |
; pointer to pixel map |
mov eax, [drbar.abs_cy] |
imul eax, [Screen_Max_X] |
add eax, [drbar.abs_cy] |
add eax, [drbar.abs_cx] |
add eax, [_WinMapAddress] |
xchg eax, ebp |
; get process number |
mov ebx, [CURRENT_TASK] |
cmp byte [ScreenBPP], 24 |
jne draw_bar_end_32 |
draw_bar_end_24: |
mov eax, [drbar.color] ;; BBGGRR00 |
mov bh, al ;; bh = BB |
shr eax, 8 ;; eax = RRGG |
; eax - color high RRGG |
; bl - process num |
; bh - color low BB |
; ecx - temp |
; edx - pointer to screen |
; esi - counter |
; edi - counter |
mov esi, [drbar.real_sy] |
align 4 |
.new_y: |
mov edi, [drbar.real_sx] |
align 4 |
.new_x: |
cmp byte [ebp], bl |
jne .skip |
mov [LFB_BASE+edx], bh |
mov [LFB_BASE+edx + 1], ax |
.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] |
; <Ivan 15.10.04> drawing gradient bars |
test eax, 0x00800000 |
jz @f |
test bh, bh |
jz @f |
dec bh |
@@: |
; </Ivan 15.10.04> |
dec esi |
jnz .new_y |
add esp, drbar.stack_data |
popad |
xor eax, eax |
ret |
draw_bar_end_32: |
mov eax, [drbar.color] ;; BBGGRR00 |
mov esi, [drbar.real_sy] |
align 4 |
.new_y: |
mov edi, [drbar.real_sx] |
align 4 |
.new_x: |
cmp byte [ebp], bl |
jne .skip |
mov [LFB_BASE+edx], eax |
.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] |
; <Ivan 15.10.04> drawing gradient bars |
test eax, 0x80000000 |
jz @f |
test al, al |
jz @f |
dec al |
@@: |
; </Ivan 15.10.04> |
dec esi |
jnz .new_y |
add esp, drbar.stack_data |
popad |
call VGA_draw_bar |
xor eax, eax |
mov [EGA_counter], 1 |
ret |
align 4 |
vesa20_drawbackground_tiled: |
call [_display.disable_mouse] |
pushad |
; External loop for all y from start to end |
mov ebx, [draw_data+32+RECT.top] ; y start |
dp2: |
mov ebp, [draw_data+32+RECT.left] ; x start |
; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp] |
; and LFB data (output for our function) [edi] |
mov eax, [BytesPerScanLine] |
mul ebx |
xchg ebp, eax |
add ebp, eax |
add ebp, eax |
add ebp, eax |
cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
add ebp, eax |
@@: |
add ebp, LFB_BASE |
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB |
call calculate_edi |
xchg edi, ebp |
add ebp, [_WinMapAddress] |
; Now eax=x, ebx=y, edi->output, ebp=offset in WinMapAddress |
; 2) Calculate offset in background memory block |
push eax |
xor edx, edx |
mov eax, ebx |
div dword [BgrDataHeight] ; edx := y mod BgrDataHeight |
pop eax |
push eax |
mov ecx, [BgrDataWidth] |
mov esi, edx |
imul esi, ecx ; esi := (y mod BgrDataHeight) * BgrDataWidth |
xor edx, edx |
div ecx ; edx := x mod BgrDataWidth |
sub ecx, edx |
add esi, edx ; esi := (y mod BgrDataHeight)*BgrDataWidth + (x mod BgrDataWidth) |
pop eax |
lea esi, [esi*3] |
add esi, [img_background] |
xor edx, edx |
inc edx |
; 3) Loop through redraw rectangle and copy background data |
; Registers meaning: |
; eax = x, ebx = y (screen coordinates) |
; ecx = deltax - number of pixels left in current tile block |
; edx = 1 |
; esi -> bgr memory, edi -> output |
; ebp = offset in WinMapAddress |
dp3: |
cmp [ebp], dl |
jnz nbgp |
movsb |
movsb |
movsb |
jmp @f |
nbgp: |
add esi, 3 |
add edi, 3 |
@@: |
cmp [ScreenBPP], byte 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 ebp, edx |
add eax, edx |
cmp eax, [draw_data+32+RECT.right] |
ja dp4 |
sub ecx, edx |
jnz dp3 |
; next tile block on x-axis |
mov ecx, [BgrDataWidth] |
sub esi, ecx |
sub esi, ecx |
sub esi, ecx |
jmp dp3 |
dp4: |
; next scan line |
inc ebx |
cmp ebx, [draw_data+32+RECT.bottom] |
jbe dp2 |
popad |
mov [EGA_counter], 1 |
call VGA_drawbackground |
ret |
; ---------- |
vesa20_drawbackground_stretch: |
call [_display.disable_mouse] |
pushad |
; Helper variables |
; calculate 2^32*(BgrDataWidth-1) mod (ScreenWidth-1) |
mov eax, [BgrDataWidth] |
dec eax |
xor edx, edx |
div dword [Screen_Max_X] |
push eax ; high |
xor eax, eax |
div dword [Screen_Max_X] |
push eax ; low |
; the same for height |
mov eax, [BgrDataHeight] |
dec eax |
xor edx, edx |
div dword [Screen_Max_Y] |
push eax ; high |
xor eax, eax |
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 |
; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp] |
; and LFB data (output for our function) [edi] |
mov eax, [BytesPerScanLine] |
mul ebx |
xchg ebp, eax |
add ebp, eax |
add ebp, eax |
add ebp, eax |
cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
add ebp, eax |
@@: |
; 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 |
; 2) Calculate offset in background memory block |
mov eax, ebx |
imul ebx, dword [esp+12] |
mul dword [esp+8] |
add edx, ebx ; edx:eax = y * 2^32*(BgrDataHeight-1)/(ScreenHeight-1) |
mov esi, edx |
imul esi, [BgrDataWidth] |
push edx |
push eax |
mov eax, [esp+8] |
mul dword [esp+28] |
push eax |
mov eax, [esp+12] |
mul dword [esp+28] |
add [esp], edx |
pop edx ; edx:eax = x * 2^32*(BgrDataWidth-1)/(ScreenWidth-1) |
add esi, edx |
lea esi, [esi*3] |
add esi, [img_background] |
push eax |
push edx |
push esi |
; 3) Smooth horizontal |
bgr_resmooth0: |
mov ecx, [esp+8] |
mov edx, [esp+4] |
mov esi, [esp] |
push edi |
mov edi, bgr_cur_line |
call smooth_line |
bgr_resmooth1: |
mov eax, [esp+16+4] |
inc eax |
cmp eax, [BgrDataHeight] |
jae bgr.no2nd |
mov ecx, [esp+8+4] |
mov edx, [esp+4+4] |
mov esi, [esp+4] |
add esi, [BgrDataWidth] |
add esi, [BgrDataWidth] |
add esi, [BgrDataWidth] |
mov edi, bgr_next_line |
call smooth_line |
bgr.no2nd: |
pop edi |
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 |
; ebp = offset in WinMapAddress |
; dword [esp] = offset in bgr data |
; qword [esp+4] = x * 2^32 * (BgrDataWidth-1) / (ScreenWidth-1) |
; qword [esp+12] = y * 2^32 * (BgrDataHeight-1) / (ScreenHeight-1) |
; dword [esp+20] = x |
; dword [esp+24] = y |
; precalculated constants: |
; qword [esp+28] = 2^32*(BgrDataHeight-1)/(ScreenHeight-1) |
; qword [esp+36] = 2^32*(BgrDataWidth-1)/(ScreenWidth-1) |
sdp3a: |
mov eax, [_WinMapAddress] |
cmp [ebp+eax], byte 1 |
jnz snbgp |
mov eax, [bgr_cur_line+esi] |
test ecx, ecx |
jz .novert |
mov ebx, [bgr_next_line+esi] |
call [overlapping_of_points_ptr] |
.novert: |
mov [LFB_BASE+edi], ax |
shr eax, 16 |
mov [LFB_BASE+edi+2], al |
snbgp: |
cmp [ScreenBPP], byte 25 |
sbb edi, -4 |
add ebp, 1 |
mov eax, [esp+20] |
add eax, 1 |
mov [esp+20], eax |
add esi, 4 |
cmp eax, [draw_data+32+RECT.right] |
jbe sdp3a |
sdp4: |
; next y |
mov ebx, [esp+24] |
add ebx, 1 |
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, [Screen_Max_X] |
add ebp, 1 |
sub edi, eax |
sub edi, eax |
sub edi, eax |
cmp [ScreenBPP], byte 24 |
jz @f |
sub edi, eax |
@@: |
add edi, [BytesPerScanLine] |
; restore ecx,edx; advance esi to next background line |
mov eax, [esp+28] |
mov ebx, [esp+32] |
add [esp+12], eax |
mov eax, [esp+16] |
adc [esp+16], ebx |
sub eax, [esp+16] |
mov ebx, eax |
lea eax, [eax*3] |
imul eax, [BgrDataWidth] |
sub [esp], eax |
mov eax, [draw_data+32+RECT.left] |
mov [esp+20], eax |
test ebx, ebx |
jz sdp3 |
cmp ebx, -1 |
jnz bgr_resmooth0 |
push edi |
mov esi, bgr_next_line |
mov edi, bgr_cur_line |
mov ecx, [Screen_Max_X] |
inc ecx |
rep movsd |
jmp bgr_resmooth1 |
sdpdone: |
add esp, 44 |
popad |
mov [EGA_counter], 1 |
call VGA_drawbackground |
ret |
uglobal |
align 4 |
bgr_cur_line rd 1920 ; maximum width of screen |
bgr_next_line rd 1920 |
endg |
smooth_line: |
mov al, [esi+2] |
shl eax, 16 |
mov ax, [esi] |
test ecx, ecx |
jz @f |
mov ebx, [esi+2] |
shr ebx, 8 |
call [overlapping_of_points_ptr] |
@@: |
stosd |
mov eax, [esp+20+8] |
add eax, 1 |
mov [esp+20+8], eax |
cmp eax, [draw_data+32+RECT.right] |
ja @f |
add ecx, [esp+36+8] |
mov eax, edx |
adc edx, [esp+40+8] |
sub eax, edx |
lea eax, [eax*3] |
sub esi, eax |
jmp smooth_line |
@@: |
mov eax, [draw_data+32+RECT.left] |
mov [esp+20+8], eax |
ret |
align 16 |
overlapping_of_points: |
if 0 |
; this version of procedure works, but is slower than next version |
push ecx edx |
mov edx, eax |
push esi |
shr ecx, 24 |
mov esi, ecx |
mov ecx, ebx |
movzx ebx, dl |
movzx eax, cl |
sub eax, ebx |
movzx ebx, dh |
imul eax, esi |
add dl, ah |
movzx eax, ch |
sub eax, ebx |
imul eax, esi |
add dh, ah |
ror ecx, 16 |
ror edx, 16 |
movzx eax, cl |
movzx ebx, dl |
sub eax, ebx |
imul eax, esi |
pop esi |
add dl, ah |
mov eax, edx |
pop edx |
ror eax, 16 |
pop ecx |
ret |
else |
push ecx edx |
mov edx, eax |
push esi |
shr ecx, 26 |
mov esi, ecx |
mov ecx, ebx |
shl esi, 9 |
movzx ebx, dl |
movzx eax, cl |
sub eax, ebx |
movzx ebx, dh |
add dl, [BgrAuxTable+(eax+0x100)+esi] |
movzx eax, ch |
sub eax, ebx |
add dh, [BgrAuxTable+(eax+0x100)+esi] |
ror ecx, 16 |
ror edx, 16 |
movzx eax, cl |
movzx ebx, dl |
sub eax, ebx |
add dl, [BgrAuxTable+(eax+0x100)+esi] |
pop esi |
mov eax, edx |
pop edx |
ror eax, 16 |
pop ecx |
ret |
end if |
iglobal |
align 4 |
overlapping_of_points_ptr dd overlapping_of_points |
endg |
init_background: |
mov edi, BgrAuxTable |
xor edx, edx |
.loop2: |
mov eax, edx |
shl eax, 8 |
neg eax |
mov ecx, 0x200 |
.loop1: |
mov byte [edi], ah |
inc edi |
add eax, edx |
loop .loop1 |
add dl, 4 |
jnz .loop2 |
test byte [cpu_caps+(CAPS_MMX/8)], 1 shl (CAPS_MMX mod 8) |
jz @f |
mov [overlapping_of_points_ptr], overlapping_of_points_mmx |
@@: |
ret |
align 16 |
overlapping_of_points_mmx: |
movd mm0, eax |
movd mm4, eax |
movd mm1, ebx |
pxor mm2, mm2 |
punpcklbw mm0, mm2 |
punpcklbw mm1, mm2 |
psubw mm1, mm0 |
movd mm3, ecx |
psrld mm3, 24 |
packuswb mm3, mm3 |
packuswb mm3, mm3 |
pmullw mm1, mm3 |
psrlw mm1, 8 |
packuswb mm1, mm2 |
paddb mm4, mm1 |
movd eax, mm4 |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/kernel/trunk/video/vga.inc |
---|
1,450 → 1,450 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; VGA.INC ;; |
;; ;; |
;; 640x480 mode 0x12 VGA functions for MenuetOS ;; |
;; ;; |
;; Paul Butcher, paul.butcher@asa.co.uk ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
paletteVGA: |
;16 colour palette |
mov dx,0x3c8 |
mov al,0 |
out dx,al |
mov ecx,16 |
mov dx,0x3c9 |
xor eax,eax |
palvganew: |
mov al,0 |
test ah,4 |
jz palvgalbl1 |
add al,31 |
test ah,8 |
jz palvgalbl1 |
add al,32 |
palvgalbl1: |
out dx,al ; red 0,31 or 63 |
mov al,0 |
test ah,2 |
jz palvgalbl2 |
add al,31 |
test ah,8 |
jz palvgalbl2 |
add al,32 |
palvgalbl2: |
out dx,al ; blue 0,31 or 63 |
mov al,0 |
test ah,1 |
jz palvgalbl3 |
add al,31 |
test ah,8 |
jz palvgalbl3 |
add al,32 |
palvgalbl3: |
out dx,al ; green 0,31 or 63 |
add ah,1 |
loop palvganew |
; mov dx, 3ceh |
; mov ax, 0005h |
; out dx, ax |
ret |
palette320x200: |
mov edx,0x3c8 |
xor eax, eax |
out dx,al |
mov ecx,256 |
mov edx,0x3c9 |
xor eax,eax |
palnew: |
mov al,0 |
test ah,64 |
jz pallbl1 |
add al,21 |
pallbl1: |
test ah,128 |
jz pallbl2 |
add al,42 |
pallbl2: |
out dx,al |
mov al,0 |
test ah,8 |
jz pallbl3 |
add al,8 |
pallbl3: |
test ah,16 |
jz pallbl4 |
add al,15 |
pallbl4: |
test ah,32 |
jz pallbl5 |
add al,40 |
pallbl5: |
out dx,al |
mov al,0 |
test ah,1 |
jz pallbl6 |
add al,8 |
pallbl6: |
test ah,2 |
jz pallbl7 |
add al,15 |
pallbl7: |
test ah,4 |
jz pallbl8 |
add al,40 |
pallbl8: |
out dx,al |
add ah,1 |
loop palnew |
ret |
align 4 |
uglobal |
novesachecksum dd 0x0 |
EGA_counter db 0 |
VGA_drawing_screen db 0 |
VGA_8_pixels: |
rb 16 |
temp: |
.cx dd 0 |
endg |
align 4 |
checkVga_N13: |
cmp [SCR_MODE],dword 0x13 |
jne @f |
; cnvl: |
pushad |
cmp [EGA_counter],1 |
je novesal |
mov ecx,[MOUSE_X] |
cmp ecx,[novesachecksum] |
jne novesal |
popad |
@@: |
ret |
novesal: |
mov [novesachecksum],ecx |
mov ecx,0 |
movzx eax,word [MOUSE_Y] |
cmp eax,100 |
jge m13l3 |
mov eax,100 |
m13l3: |
cmp eax,480-100 |
jbe m13l4 |
mov eax,480-100 |
m13l4: |
sub eax,100 |
imul eax,640*4 |
add ecx,eax |
movzx eax,word [MOUSE_X] |
cmp eax,160 |
jge m13l1 |
mov eax,160 |
m13l1: |
cmp eax,640-160 |
jbe m13l2 |
mov eax,640-160 |
m13l2: |
sub eax,160 |
shl eax,2 |
add ecx,eax |
mov esi,[LFBAddress] |
add esi,ecx |
mov edi,VGABasePtr |
mov edx,200 |
mov ecx,320 |
cld |
m13pix: |
lodsd |
test eax,eax |
jz .save_pixel |
push eax |
mov ebx,eax |
and eax,(128+64+32) ; blue |
shr eax,5 |
and ebx,(128+64+32)*256 ; green |
shr ebx,8+2 |
add eax,ebx |
pop ebx |
and ebx,(128+64)*256*256 ; red |
shr ebx,8+8 |
add eax,ebx |
.save_pixel: |
stosb |
loop m13pix |
mov ecx,320 |
add esi,4*(640-320) |
dec edx |
jnz m13pix |
mov [EGA_counter],0 |
popad |
ret |
VGA_drawbackground: |
; draw all |
cmp [SCR_MODE],dword 0x12 |
jne .end |
pushad |
mov esi,[LFBAddress] |
mov edi,VGABasePtr |
mov ebx,640/32 ; 640*480/(8*4) |
mov edx,480 |
@@: |
push ebx edx esi edi |
shl edx,9 |
lea edx,[edx+edx*4] |
add esi,edx |
shr edx,5 |
add edi,edx |
call VGA_draw_long_line |
pop edi esi edx ebx |
dec edx |
jnz @r |
call VGA_draw_long_line_1 |
popad |
.end: |
ret |
VGA_draw_long_line: |
mov dx,3ceh |
mov ax,0ff08h |
cli |
out dx, ax |
mov ax,0005h |
out dx, ax |
m12pix: |
call VGA_draw_32_pixels |
dec ebx |
jnz m12pix |
mov dx,3c4h |
mov ax,0ff02h |
out dx,ax |
mov dx,3ceh |
mov ax,0205h |
out dx,ax |
mov dx,3ceh |
mov al,08h |
out dx,al |
sti |
ret |
VGA_draw_32_pixels: |
xor eax,eax |
mov ebp,VGA_8_pixels |
mov [ebp],eax |
mov [ebp+4],eax |
mov [ebp+8],eax |
mov [ebp+12],eax |
mov ch,4 |
.main_loop: |
mov cl,8 |
.convert_pixels_to_VGA: |
lodsd ; eax = 24bit colour |
test eax,eax |
jz .end |
rol eax,8 |
mov al,ch |
ror eax,8 |
mov ch,1 |
dec cl |
shl ch,cl |
cmp al,85 |
jbe .p13green |
or [ebp],ch |
cmp al,170 |
jbe .p13green |
or [ebp+12],ch |
.p13green: |
cmp ah,85 |
jbe .p13red |
or [ebp+4],ch |
cmp ah,170 |
jbe .p13red |
or [ebp+12],ch |
.p13red: |
shr eax,8 |
cmp ah,85 |
jbe .p13cont |
or [ebp+8],ch |
cmp ah,170 |
jbe .p13cont |
or [ebp+12],ch |
.p13cont: |
ror eax,8 |
mov ch,ah |
inc cl |
.end: |
dec cl |
jnz .convert_pixels_to_VGA |
inc ebp |
dec ch |
jnz .main_loop |
push esi |
sub ebp,4 |
mov esi,ebp |
mov dx, 3c4h |
mov ah, 1h |
@@: |
mov al, 02h |
out dx,ax |
xchg ax,bp |
lodsd |
mov [edi],eax |
xchg ax,bp |
shl ah, 1 |
cmp ah, 10h |
jnz @r |
add edi,4 |
pop esi |
ret |
VGA_putpixel: |
; eax = x |
; ebx = y |
mov ecx,eax |
mov eax, [esp+32-8+4] ; color |
shl ebx,9 |
lea ebx,[ebx+ebx*4] ; óìíîæåíèå íà 5 |
lea edx, [ebx+ecx*4] ; + x*BytesPerPixel (Vesa2.0 32) |
mov edi,edx |
add edi, [LFBAddress] ; + LFB address |
mov [edi], eax ; write to LFB for Vesa2.0 |
shr edx,5 ; change BytesPerPixel to 1/8 |
mov edi,edx |
add edi, VGABasePtr ; address of pixel in VGA area |
and ecx,0x07 ; bit no. (modulo 8) |
pushfd |
; edi = address, eax = 24bit colour, ecx = bit no. (modulo 8) |
xor edx,edx |
test eax,eax |
jz .p13cont |
cmp al,85 |
jbe .p13green |
or dl,0x01 |
cmp al,170 |
jbe .p13green |
or dl,0x08 |
.p13green: |
cmp ah,85 |
jbe .p13red |
or dl,0x02 |
cmp ah,170 |
jbe .p13red |
or dl,0x08 |
.p13red: |
shr eax,8 |
cmp ah,85 |
jbe .p13cont |
or dl,0x04 |
cmp ah,170 |
jbe .p13cont |
or dl,0x08 |
.p13cont: |
ror edx,8 |
inc cl |
xor eax,eax |
inc ah |
shr ax,cl |
mov dx,3cfh |
cli |
out dx,al |
mov al,[edi] ; dummy read |
rol edx,8 |
mov [edi],dl |
popfd |
;.end: |
ret |
VGA__putimage: |
; ecx = size [x|y] |
; edx = coordinates [x|y] |
cmp [SCR_MODE],dword 0x12 |
jne @f |
pushad |
rol edx,16 |
movzx eax,dx |
rol edx,16 |
movzx ebx,dx |
movzx edx,cx |
rol ecx,16 |
movzx ecx,cx |
call VGA_draw_bar_1 |
popad |
@@: |
ret |
VGA_draw_bar: |
; eax cx |
; ebx cy |
; ecx xe |
; edx ye |
cmp [SCR_MODE],dword 0x12 |
jne @f |
pushad |
sub ecx,eax |
sub edx,ebx |
and eax,0xffff |
and ebx,0xffff |
and ecx,0xffff |
and edx,0xffff |
call VGA_draw_bar_1 |
popad |
@@: |
ret |
VGA_draw_bar_1: |
mov [temp.cx],eax |
mov eax, [TASK_BASE] |
add ebx, [eax-twdw + 4] |
mov eax, [eax-twdw + 0] |
add eax, [temp.cx] |
and eax,0xfff8 |
shl ebx,9 |
lea ebx,[ebx+ebx*4] ; óìíîæåíèå íà 5 |
lea ebx, [ebx+eax*4] ; + x*BytesPerPixel (Vesa2.0 32) |
mov esi,ebx |
add esi, [LFBAddress] ; + LFB address |
shr ebx,5 ; change BytesPerPixel to 1/8 |
mov edi,ebx |
add edi, VGABasePtr ; address of pixel in VGA area |
mov ebx,ecx |
shr ebx,5 |
inc ebx |
.main_loop: |
call VGA_draw_long_line_1 |
dec edx |
jnz .main_loop |
call VGA_draw_long_line_1 |
ret |
VGA_draw_long_line_1: |
push ebx edx esi edi |
shl edx,9 |
lea edx,[edx+edx*4] |
add esi,edx |
shr edx,5 |
add edi,edx |
call VGA_draw_long_line |
pop edi esi edx ebx |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; VGA.INC ;; |
;; ;; |
;; 640x480 mode 0x12 VGA functions for MenuetOS ;; |
;; ;; |
;; Paul Butcher, paul.butcher@asa.co.uk ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
paletteVGA: |
;16 colour palette |
mov dx, 0x3c8 |
mov al, 0 |
out dx, al |
mov ecx, 16 |
mov dx, 0x3c9 |
xor eax, eax |
palvganew: |
mov al, 0 |
test ah, 4 |
jz palvgalbl1 |
add al, 31 |
test ah, 8 |
jz palvgalbl1 |
add al, 32 |
palvgalbl1: |
out dx, al; red 0,31 or 63 |
mov al, 0 |
test ah, 2 |
jz palvgalbl2 |
add al, 31 |
test ah, 8 |
jz palvgalbl2 |
add al, 32 |
palvgalbl2: |
out dx, al; blue 0,31 or 63 |
mov al, 0 |
test ah, 1 |
jz palvgalbl3 |
add al, 31 |
test ah, 8 |
jz palvgalbl3 |
add al, 32 |
palvgalbl3: |
out dx, al; green 0,31 or 63 |
add ah, 1 |
loop palvganew |
; mov dx, 3ceh |
; mov ax, 0005h |
; out dx, ax |
ret |
palette320x200: |
mov edx, 0x3c8 |
xor eax, eax |
out dx, al |
mov ecx, 256 |
mov edx, 0x3c9 |
xor eax, eax |
palnew: |
mov al, 0 |
test ah, 64 |
jz pallbl1 |
add al, 21 |
pallbl1: |
test ah, 128 |
jz pallbl2 |
add al, 42 |
pallbl2: |
out dx, al |
mov al, 0 |
test ah, 8 |
jz pallbl3 |
add al, 8 |
pallbl3: |
test ah, 16 |
jz pallbl4 |
add al, 15 |
pallbl4: |
test ah, 32 |
jz pallbl5 |
add al, 40 |
pallbl5: |
out dx, al |
mov al, 0 |
test ah, 1 |
jz pallbl6 |
add al, 8 |
pallbl6: |
test ah, 2 |
jz pallbl7 |
add al, 15 |
pallbl7: |
test ah, 4 |
jz pallbl8 |
add al, 40 |
pallbl8: |
out dx, al |
add ah, 1 |
loop palnew |
ret |
align 4 |
uglobal |
novesachecksum dd 0x0 |
EGA_counter db 0 |
VGA_drawing_screen db 0 |
VGA_8_pixels: |
rb 16 |
temp: |
.cx dd 0 |
endg |
align 4 |
checkVga_N13: |
cmp [SCR_MODE], dword 0x13 |
jne @f |
; cnvl: |
pushad |
cmp [EGA_counter], 1 |
je novesal |
mov ecx, [MOUSE_X] |
cmp ecx, [novesachecksum] |
jne novesal |
popad |
@@: |
ret |
novesal: |
mov [novesachecksum], ecx |
mov ecx, 0 |
movzx eax, word [MOUSE_Y] |
cmp eax, 100 |
jge m13l3 |
mov eax, 100 |
m13l3: |
cmp eax, 480-100 |
jbe m13l4 |
mov eax, 480-100 |
m13l4: |
sub eax, 100 |
imul eax, 640*4 |
add ecx, eax |
movzx eax, word [MOUSE_X] |
cmp eax, 160 |
jge m13l1 |
mov eax, 160 |
m13l1: |
cmp eax, 640-160 |
jbe m13l2 |
mov eax, 640-160 |
m13l2: |
sub eax, 160 |
shl eax, 2 |
add ecx, eax |
mov esi, [LFBAddress] |
add esi, ecx |
mov edi, VGABasePtr |
mov edx, 200 |
mov ecx, 320 |
cld |
m13pix: |
lodsd |
test eax, eax |
jz .save_pixel |
push eax |
mov ebx, eax |
and eax, (128+64+32) ; blue |
shr eax, 5 |
and ebx, (128+64+32)*256; green |
shr ebx, 8+2 |
add eax, ebx |
pop ebx |
and ebx, (128+64)*256*256; red |
shr ebx, 8+8 |
add eax, ebx |
.save_pixel: |
stosb |
loop m13pix |
mov ecx, 320 |
add esi, 4*(640-320) |
dec edx |
jnz m13pix |
mov [EGA_counter], 0 |
popad |
ret |
VGA_drawbackground: |
; draw all |
cmp [SCR_MODE], dword 0x12 |
jne .end |
pushad |
mov esi, [LFBAddress] |
mov edi, VGABasePtr |
mov ebx, 640/32; 640*480/(8*4) |
mov edx, 480 |
@@: |
push ebx edx esi edi |
shl edx, 9 |
lea edx, [edx+edx*4] |
add esi, edx |
shr edx, 5 |
add edi, edx |
call VGA_draw_long_line |
pop edi esi edx ebx |
dec edx |
jnz @r |
call VGA_draw_long_line_1 |
popad |
.end: |
ret |
VGA_draw_long_line: |
mov dx, 3ceh |
mov ax, 0ff08h |
cli |
out dx, ax |
mov ax, 0005h |
out dx, ax |
m12pix: |
call VGA_draw_32_pixels |
dec ebx |
jnz m12pix |
mov dx, 3c4h |
mov ax, 0ff02h |
out dx, ax |
mov dx, 3ceh |
mov ax, 0205h |
out dx, ax |
mov dx, 3ceh |
mov al, 08h |
out dx, al |
sti |
ret |
VGA_draw_32_pixels: |
xor eax, eax |
mov ebp, VGA_8_pixels |
mov [ebp], eax |
mov [ebp+4], eax |
mov [ebp+8], eax |
mov [ebp+12], eax |
mov ch, 4 |
.main_loop: |
mov cl, 8 |
.convert_pixels_to_VGA: |
lodsd ; eax = 24bit colour |
test eax, eax |
jz .end |
rol eax, 8 |
mov al, ch |
ror eax, 8 |
mov ch, 1 |
dec cl |
shl ch, cl |
cmp al, 85 |
jbe .p13green |
or [ebp], ch |
cmp al, 170 |
jbe .p13green |
or [ebp+12], ch |
.p13green: |
cmp ah, 85 |
jbe .p13red |
or [ebp+4], ch |
cmp ah, 170 |
jbe .p13red |
or [ebp+12], ch |
.p13red: |
shr eax, 8 |
cmp ah, 85 |
jbe .p13cont |
or [ebp+8], ch |
cmp ah, 170 |
jbe .p13cont |
or [ebp+12], ch |
.p13cont: |
ror eax, 8 |
mov ch, ah |
inc cl |
.end: |
dec cl |
jnz .convert_pixels_to_VGA |
inc ebp |
dec ch |
jnz .main_loop |
push esi |
sub ebp, 4 |
mov esi, ebp |
mov dx, 3c4h |
mov ah, 1h |
@@: |
mov al, 02h |
out dx, ax |
xchg ax, bp |
lodsd |
mov [edi], eax |
xchg ax, bp |
shl ah, 1 |
cmp ah, 10h |
jnz @r |
add edi, 4 |
pop esi |
ret |
VGA_putpixel: |
; eax = x |
; ebx = y |
mov ecx, eax |
mov eax, [esp+32-8+4] ; color |
shl ebx, 9 |
lea ebx, [ebx+ebx*4] ; óìíîæåíèå íà 5 |
lea edx, [ebx+ecx*4] ; + x*BytesPerPixel (Vesa2.0 32) |
mov edi, edx |
add edi, [LFBAddress] ; + LFB address |
mov [edi], eax ; write to LFB for Vesa2.0 |
shr edx, 5 ; change BytesPerPixel to 1/8 |
mov edi, edx |
add edi, VGABasePtr ; address of pixel in VGA area |
and ecx, 0x07 ; bit no. (modulo 8) |
pushfd |
; edi = address, eax = 24bit colour, ecx = bit no. (modulo 8) |
xor edx, edx |
test eax, eax |
jz .p13cont |
cmp al, 85 |
jbe .p13green |
or dl, 0x01 |
cmp al, 170 |
jbe .p13green |
or dl, 0x08 |
.p13green: |
cmp ah, 85 |
jbe .p13red |
or dl, 0x02 |
cmp ah, 170 |
jbe .p13red |
or dl, 0x08 |
.p13red: |
shr eax, 8 |
cmp ah, 85 |
jbe .p13cont |
or dl, 0x04 |
cmp ah, 170 |
jbe .p13cont |
or dl, 0x08 |
.p13cont: |
ror edx, 8 |
inc cl |
xor eax, eax |
inc ah |
shr ax, cl |
mov dx, 3cfh |
cli |
out dx, al |
mov al, [edi] ; dummy read |
rol edx, 8 |
mov [edi], dl |
popfd |
;.end: |
ret |
VGA__putimage: |
; ecx = size [x|y] |
; edx = coordinates [x|y] |
cmp [SCR_MODE], dword 0x12 |
jne @f |
pushad |
rol edx, 16 |
movzx eax, dx |
rol edx, 16 |
movzx ebx, dx |
movzx edx, cx |
rol ecx, 16 |
movzx ecx, cx |
call VGA_draw_bar_1 |
popad |
@@: |
ret |
VGA_draw_bar: |
; eax cx |
; ebx cy |
; ecx xe |
; edx ye |
cmp [SCR_MODE], dword 0x12 |
jne @f |
pushad |
sub ecx, eax |
sub edx, ebx |
and eax, 0xffff |
and ebx, 0xffff |
and ecx, 0xffff |
and edx, 0xffff |
call VGA_draw_bar_1 |
popad |
@@: |
ret |
VGA_draw_bar_1: |
mov [temp.cx], eax |
mov eax, [TASK_BASE] |
add ebx, [eax-twdw + 4] |
mov eax, [eax-twdw + 0] |
add eax, [temp.cx] |
and eax, 0xfff8 |
shl ebx, 9 |
lea ebx, [ebx+ebx*4]; óìíîæåíèå íà 5 |
lea ebx, [ebx+eax*4] ; + x*BytesPerPixel (Vesa2.0 32) |
mov esi, ebx |
add esi, [LFBAddress] ; + LFB address |
shr ebx, 5 ; change BytesPerPixel to 1/8 |
mov edi, ebx |
add edi, VGABasePtr ; address of pixel in VGA area |
mov ebx, ecx |
shr ebx, 5 |
inc ebx |
.main_loop: |
call VGA_draw_long_line_1 |
dec edx |
jnz .main_loop |
call VGA_draw_long_line_1 |
ret |
VGA_draw_long_line_1: |
push ebx edx esi edi |
shl edx, 9 |
lea edx, [edx+edx*4] |
add esi, edx |
shr edx, 5 |
add edi, edx |
call VGA_draw_long_line |
pop edi esi edx ebx |
ret |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |