/trunk/boot/booteng.inc |
---|
File deleted |
/trunk/boot/bootcode.inc |
---|
File deleted |
/trunk/boot/rdload.inc |
---|
File deleted |
/trunk/boot/ru.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/boot/bootru.inc |
---|
File deleted |
/trunk/boot/preboot.inc |
---|
File deleted |
/trunk/boot/shutdown.inc |
---|
File deleted |
/trunk/hid/set_dtc.inc |
---|
File deleted |
/trunk/hid/keyboard.inc |
---|
File deleted |
/trunk/video/vga.inc |
---|
File deleted |
/trunk/video/vesa20.inc |
---|
File deleted |
/trunk/video/vesa12.inc |
---|
File deleted |
/trunk/kglobals.inc |
---|
File deleted |
/trunk/blkdev/cdrom.inc |
---|
File deleted |
/trunk/blkdev/rdsave.inc |
---|
File deleted |
/trunk/blkdev/rd.inc |
---|
File deleted |
/trunk/blkdev/fdc.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/blkdev/flp_drv.inc |
---|
File deleted |
/trunk/fs/fat12.inc |
---|
File deleted |
/trunk/fs/fat32.inc |
---|
File deleted |
/trunk/fs/fs.inc |
---|
File deleted |
/trunk/fs/fs_phys.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/detect/commouse.inc |
---|
File deleted |
/trunk/detect/dev_fd.inc |
---|
File deleted |
/trunk/detect/sear_par.inc |
---|
File deleted |
/trunk/detect/disks.inc |
---|
File deleted |
/trunk/detect/dev_hdcd.inc |
---|
File deleted |
/trunk/build_ru.bat |
---|
File deleted |
\ No newline at end of file |
/trunk/memmap.inc |
---|
File deleted |
/trunk/gui/skincode.inc |
---|
File deleted |
/trunk/gui/event.inc |
---|
File deleted |
/trunk/gui/font.inc |
---|
File deleted |
/trunk/gui/window.inc |
---|
File deleted |
/trunk/gui/mouse.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/gui/button.inc |
---|
File deleted |
/trunk/gui/skindata.inc |
---|
File deleted |
/trunk/build_en.bat |
---|
File deleted |
\ No newline at end of file |
/trunk/sound/sb16.inc |
---|
File deleted |
/trunk/sound/playnote.inc |
---|
File deleted |
/trunk/core/newproce.inc |
---|
File deleted |
/trunk/core/memmanag.inc |
---|
File deleted |
/trunk/core/physmem.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/core/sys32.inc |
---|
File deleted |
/trunk/core/sched.inc |
---|
File deleted |
/trunk/core/fpu.inc |
---|
File deleted |
/trunk/core/syscall.inc |
---|
File deleted |
/trunk/core/sync.inc |
---|
File deleted |
/trunk/core/mem.inc |
---|
File deleted |
/trunk/network/eth_drv/rtl8139.inc |
---|
File deleted |
/trunk/network/eth_drv/sis900.inc |
---|
File deleted |
/trunk/network/eth_drv/3c59x.inc |
---|
File deleted |
/trunk/network/eth_drv/ethernet.inc |
---|
File deleted |
/trunk/network/eth_drv/pcnet32.inc |
---|
File deleted |
/trunk/network/eth_drv/rtl8029.inc |
---|
File deleted |
/trunk/network/eth_drv/i8255x.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/network/queue.inc |
---|
File deleted |
/trunk/network/stack.inc |
---|
File deleted |
/trunk/network/tcp.inc |
---|
File deleted |
/trunk/network/ip.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/network/udp.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/bus/pci/pci32.inc |
---|
File deleted |
/trunk/bus/pci/pci16.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/vmodeint.inc |
---|
File deleted |
/trunk/kernel32.inc |
---|
File deleted |
/trunk/kernel16.inc |
---|
File deleted |
\ No newline at end of file |
/trunk/kernel.asm |
---|
File deleted |
/trunk/vmodeld.inc |
---|
File deleted |
\ No newline at end of file |
/trunk |
---|
Property changes: |
Deleted: svn:ignore |
-*.mnt |
-lang.inc |
-*.bat |
-out.txt |
-scin* |
/kernel/trunk/blkdev/cdrom.inc |
---|
0,0 → 1,261 |
sys_cd_audio: |
cmp word [cdbase],word 0 |
jnz @f |
mov eax,1 |
ret |
@@: |
; eax=1 cdplay at ebx 0x00FFSSMM |
; eax=2 get tracklist size of ecx to [ebx] |
; eax=3 stop/pause playing |
cmp eax,1 |
jnz nocdp |
call sys_cdplay |
ret |
nocdp: |
cmp eax,2 |
jnz nocdtl |
mov edi,[0x3010] |
add edi,0x10 |
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 |
/kernel/trunk/blkdev/fdc.inc |
---|
0,0 → 1,369 |
;### fdc.inc ### Menuetos floppy stuff. |
;Version 0.2: Write individual tracks. / Sync ramdisk <-> floppy |
;Version 0.1: Write full ramdisk to floppy. |
;£loppyright Tolle. |
;depends on: |
;restorefatchain |
;memmove |
;Int 6 (sys32.inc) should call fdc_irq func. |
;The ramdisk should be at 0x100000 |
;Keeping track of the tracks. |
iglobal |
cylinder db 0 |
sector db 1 |
head db 0 |
;Memory and dma variables. |
fdcmem dd 0x100000 |
cpymem dd 0x100000 |
dmamem dd 0x100000 |
endg |
uglobal |
dmasize db 0x0 |
dmamode db 0x0 |
endg |
iglobal |
;function pointers. |
fdc_irq_func dd fdc_null |
fdc_pump_func dd fdc_null |
endg |
uglobal |
;General stuff |
fdc_st0 db 0 ;status register 0 of last resultphase. |
fdc_mutex db 0 ;wait in line. (Block calling app) |
fdc_callspending db 0 ;mystery sauce |
fdc_settings dd 0 ;bitfield. |
endg |
;Bit 0 enable direct file write [yes/no] |
fdc_set: ;ebx: fdc_settings bitfield. |
mov [fdc_settings],ebx |
ret |
fdc_get: ;returns fdc_settings in ecx |
mov ecx, [fdc_settings] |
ret |
fdc_init: ;start with clean tracks. |
mov edi,0xD201 |
mov al,0 |
mov ecx,160 |
rep stosb |
ret |
fdc_filesave: ;ebx: cluster to be saved. |
pusha ;returns immediately. does not trigger a write. |
mov eax,ebx |
add eax,31 |
mov bl,18 |
div bl |
mov ah,0 |
add eax,0xD201 |
mov [eax],byte 1 ;This track is now dirty. |
popa |
ret |
fdc_writeramdisk: ;mark all tracks as dirty. |
mov edi,0xD201 |
mov al,1 |
mov ecx,160 |
rep stosb |
jmp fdc_commitflush |
fdc_commitfile: ;flush dirty tracks to floppy |
test [fdc_settings],1 ;...but only if this is really wanted by the user. |
je fdc_commitend |
fdc_commitflush: |
cmp [fdc_callspending],5 |
je fdc_commitend |
inc [fdc_callspending] |
cmp [fdc_callspending],1 |
je fdc_commitonce |
fdc_commitend: |
ret |
fdc_commitonce: ;One at a time. |
.stall: |
cli |
cmp [fdc_mutex],0 |
jne .stallret |
mov [fdc_mutex],1 |
jmp .goahead |
.stallret: |
sti |
jmp .stall |
.goahead: |
sti |
fdc_commitramdisk: |
call restorefatchain |
;Move the bootsector to a safe place. |
mov eax,0x100000 |
mov ebx,0xD000 |
mov ecx,512 |
call memmove |
;Always write the FAT table |
mov eax,0xD201 |
mov [eax],byte 1 |
inc eax |
mov [eax],byte 1 |
mov [dmamode],0x4A ;read from memory to floppy. |
mov [dmasize],0x1 ;read 512 bytes sectors. |
mov [fdc_irq_func],fdc_commitramdisk1 |
call fdc_floppy_on ;start floppy A: moter starts interruptflow. |
ret |
fdc_commitramdisk1: |
mov [fdc_irq_func],fdc_recalibrate_result |
mov [fdc_pump_func],fdc_commitramdisk2 |
call fdc_recalibrate ;retract the head to cylinder 0, sector 1 |
ret |
fdc_commitramdisk2: |
mov[head],0 ;set variables. |
mov[cylinder],0 |
mov [sector],1 |
mov[cpymem],0x102400 |
mov [fdc_pump_func],fdc_fullpump |
call fdc_write ;fdc_write will continue interruptflow |
ret |
fdc_fullpump: |
add [dmamem],512 |
add [sector],1 |
cmp [sector],19 |
jne .clusterwrite |
sub [dmamem],9216 |
mov eax,[cpymem] |
mov ebx,[fdcmem] |
mov ecx,9216 |
call memmove |
add [cpymem],9216 |
cmp [head],0 |
je .nocylinderchange |
add [cylinder],1 |
.nocylinderchange: |
xor [head],1 |
cmp [cylinder],80 |
jne .noendofwrite |
mov[fdc_irq_func],fdc_complete |
call fdc_floppy_off |
call fdc_init |
jmp .end |
.noendofwrite: |
mov [sector],1 |
.clusterwrite: |
xor eax,eax |
mov al,[cylinder] |
shl eax,1 |
add al,[head] |
add eax,0xD201 |
mov bl,[eax] |
cmp bl,1 |
jne fdc_fullpump |
call fdc_write |
.end: |
ret |
fdc_write: |
call fdc_program_dma |
call fdc_seek |
ret |
fdc_seek: |
mov al, 0x0f |
call fdc_write_reg |
mov al,[head] |
shl al,2 |
call fdc_write_reg |
mov al,[cylinder] |
call fdc_write_reg |
mov [fdc_irq_func],fdc_seek_result |
ret |
fdc_seek_result: |
call fdc_sensei |
cmp al,[cylinder] |
je .succes |
call fdc_seek |
jmp .end |
.succes: |
call fdc_write_sector |
.end: |
ret |
fdc_write_sector: |
mov al,0x45 ;write sector command |
fdc_commandphase: |
call fdc_write_reg |
mov al,[head] |
shl al,2 |
call fdc_write_reg |
mov al,[cylinder] |
call fdc_write_reg |
mov al,[head] |
call fdc_write_reg |
mov al,[sector] |
call fdc_write_reg |
mov al,2 ;Sector size (2 ~> 512 bytes) |
call fdc_write_reg |
mov al,18 ;last sector on track. |
call fdc_write_reg |
mov al,27 ;length of GAP3 |
call fdc_write_reg |
mov al,0xFF ;data length, ignored. |
call fdc_write_reg |
mov [fdc_irq_func],fdc_resultphase |
ret |
fdc_resultphase: |
call fdc_read_reg |
mov [fdc_st0],al |
mov cx,6 |
.readresult: |
call fdc_read_reg |
loop .readresult |
and [fdc_st0],11000000b |
cmp [fdc_st0],byte 0 |
jz .succes |
call fdc_seek |
jmp .end |
.succes: |
call [fdc_pump_func] |
.end: |
ret |
fdc_sensei: |
mov al,0x08 ;get interrupt status command |
call fdc_write_reg |
call fdc_read_reg ;get result in al; |
and al,0x80 |
cmp al,0x80 |
je fdc_sensei ;retry |
call fdc_read_reg |
ret |
fdc_program_dma: |
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,[dmamem] |
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, [dmasize] ;(0x1ff = 511 / 0x23ff =9215) |
out 0x5,al |
mov al,2 |
out 0xa,al |
ret |
fdc_recalibrate: |
mov al,0x07 ;calibrate command |
call fdc_write_reg |
mov al,0 ;select drive 0 |
call fdc_write_reg |
ret |
fdc_recalibrate_result: |
mov al,0x08 ;get interrupt status command |
call fdc_write_reg ;send it |
call fdc_read_reg ;get command in al; |
cmp al,0x80 |
je fdc_recalibrate_result |
mov ah,al |
call fdc_read_reg |
cmp ah,0x70 |
jne .end |
call fdc_recalibrate |
jmp .reallyend |
.end: |
call [fdc_pump_func] |
.reallyend: |
ret |
fdc_busy: |
.command_check: |
mov dx,0x3F4 |
in al,dx |
and al,0x10 |
cmp al,0x10 |
je .command_check |
ret |
fdc_read_reg: |
status_check: |
mov dx,0x3F4 |
in al,dx |
and al,0xc0 |
cmp al,0xc0 |
jne status_check |
mov dx, 0x3F5 |
in al, dx |
ret |
fdc_write_reg: |
mov bl,al |
.command_check: |
mov dx,0x3F4 |
in al,dx |
and al,0x80 |
cmp al,0x80 |
jne .command_check |
mov al,bl |
mov dx,0x3F5 |
out dx,al |
ret |
fdc_floppy_off: |
mov al,0xC |
mov dx,0x3f2 |
out dx,al |
ret |
fdc_floppy_on: |
mov dx,0x3f2 |
mov al,0x0 |
out dx,al |
mov al,0x1C |
out dx,al |
mov eax,50 |
call delay_hs |
ret |
fdc_complete: |
mov eax,0xD000 |
mov ebx,0x100000 |
mov ecx,512 |
call memmove |
mov [fdc_irq_func],fdc_null |
mov [fdc_mutex],0 |
dec [fdc_callspending] |
cmp [fdc_callspending],0 |
je .realyend |
mov [fdc_mutex],1 |
call fdc_commitramdisk |
.realyend: |
ret |
fdc_irq: |
call [fdc_irq_func] |
fdc_null: |
ret |
/kernel/trunk/blkdev/flp_drv.inc |
---|
0,0 → 1,685 |
;********************************************************** |
; ¥¯®á।á⢥ ï à ¡®â á ª®â஫«¥à®¬ £¨¡ª®£® ¤¨áª |
;********************************************************** |
; ¢â®à ¨á室®£® ⥪áâ ã« ª®¢ « ¤¨¬¨à ¥ ¤ì¥¢¨ç. |
; ¤ ¯â æ¨ï ¨ ¤®à ¡®âª Mario79 |
fdd_read_and_write: |
pusha |
read_sector: |
cmp eax,1 |
jne write_sector |
call save_HTS_values |
call flp_readsector |
call give_back_application_data |
jmp fdd_read_end |
write_sector: |
cmp eax,2 |
jne fdd_read_end |
call save_HTS_values |
call take_data_from_application |
call flp_writesector |
fdd_read_end: |
popa |
ret |
save_HTS_values: |
mov [FDD_Sector],bl |
mov [FDD_Head],bh |
shr ebx,16 |
mov [FDD_Track],bl |
mov [FDD_Type],bh |
ret |
give_back_application_data: ; ¯¥à¥á« âì ¯à¨«®¦¥¨î |
mov edi,[3010h] |
mov edi,[edi+10h] |
add edi,ecx |
give_back_application_data_1: |
mov esi,0xD000 ;FDD_DataBuffer ;0x40000 |
xor ecx,ecx |
mov cx,128 |
cld |
rep movsd |
ret |
take_data_from_application: ; ¢§ïâì ¨§ ¯à¨«®¦¥¨ï |
mov esi,[3010h] |
mov esi,[esi+10h] |
add esi,ecx |
take_data_from_application_1: |
mov edi,0xD000 ;FDD_DataBuffer ;0x40000 |
xor ecx,ecx |
mov cx,128 |
cld |
rep movsd |
ret |
flp_initialization: |
; áâ ®¢¨âì ®¢ë© ®¡à ¡®â稪 ¯à¥àë¢ ¨ï |
call SetUserInterrupts |
; ª«îç¨âì ¬®â®à ¤¨áª®¢®¤ |
call FDDMotorON |
; ¨æ¨ «¨§¨à®¢ âì ¯¥à¥¬¥ë¥ |
; mov [FDD_Track],0 |
; mov [FDD_Head],0 |
; mov [FDD_Sector],1 |
; ஢¥á⨠४ «¨¡à®¢ªã ¨ ¯®¨áª ã«¥¢®© ¤®à®¦ª¨ |
call RecalibrateFDD |
call SeekTrack |
ret |
flp_readsector: |
call flp_initialization |
; à®ç¨â âì ᥪâ®à |
call ReadSectWithRetr |
; call ReadSector |
; cmp [FDC_Status],0 |
; jne @@SectorNotFound |
mov [fdc_irq_func],fdc_null |
; call FDDMotorOFF |
ret |
flp_writesector: |
call flp_initialization |
; ¯¨á âì ᥪâ®à |
call WriteSectWithRetr |
; call WriteSector |
; cmp [FDC_Status],0 |
; jne @@SectorNotFound |
mov [fdc_irq_func],fdc_null |
; call FDDMotorOFF |
ret |
@@DiskNotFound: |
ret |
@@SectorNotFound: |
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 |
; ç¥â稪 ⨪®¢ â ©¬¥à |
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 ? |
; ¡« áâì ¯ ¬ï⨠¤«ï åà ¥¨ï ¯à®ç¨â ®£® ᥪâ®à |
;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 ax cx dx |
mov AH,AL ;§ ¯®¬¨âì ¡ ©â ¢ AH |
; ¡à®á¨âì ¯¥à¥¬¥ãî á®áâ®ï¨ï ª®â஫«¥à |
mov [FDC_Status],FDC_Normal |
; ஢¥à¨âì £®â®¢®áâì ª®â஫«¥à ª ¯à¨¥¬ã ¤ ëå |
mov DX,3F4h ;(¯®àâ á®áâ®ï¨ï FDC) |
xor CX,CX ;ãáâ ®¢¨âì áç¥â稪 â ©¬- ãâ |
@@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 dx cx ax |
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: |
; §à¥è¨âì ¯à¥àë¢ ¨ï |
; sti |
; push AX |
; áâ ®¢¨âì ä« £ ¯à¥àë¢ ¨ï |
mov [FDD_IntFlag],1 |
; ®á« âì ª®¬ ¤ã EOI ª®â஫«¥àã ¯à¥àë¢ ¨© |
; mov AL,20h |
; out 20h,AL |
; pop AX |
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 ;¯à¥àë¢ ¨¥ ¯à®¨§®è«® |
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: |
mov eax,[timer_ticks] |
sub eax,[TickCounter] |
cmp eax,50 ;10 |
jb @@dT |
cmp [flp_number],1 |
jne fdd_motor_on_B |
mov [fdd_motor_status],1 |
jmp fdd_motor_on |
fdd_motor_on_B: |
mov [fdd_motor_status],2 |
fdd_motor_on: |
call save_timer_fdd_motor |
popa |
ret |
;***************************************** |
;* * |
;***************************************** |
save_timer_fdd_motor: |
mov eax,[timer_ticks] |
mov [timer_fdd_motor],eax |
ret |
;***************************************** |
;* * |
;***************************************** |
check_fdd_motor_status: |
cmp [fdd_motor_status],0 |
je end_check_fdd_motor_status |
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: |
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 |
/kernel/trunk/blkdev/rd.inc |
---|
0,0 → 1,446 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; RAMDISK functions ;; |
;; (C) 2004 Ville Turjanmaa, License: GPL ;; |
;; Addings by M.Lisovin ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
ramdisk_free_space: |
;--------------------------------------------- |
; |
; returns free space in edi |
; rewr.by Mihasik |
;--------------------------------------------- |
push eax ebx ecx |
mov edi,0x280000 ;start of FAT |
xor ax,ax ;Free cluster=0x0000 in FAT |
xor ebx,ebx ;counter |
mov ecx,2847 ;2849 ;2849 clusters |
cld |
rdfs1: |
repne scasw |
jnz rdfs2 ;if last cluster not 0 |
inc ebx |
jcxz rdfs2 ;if last cluster=0 |
jmp rdfs1 ;if not last |
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,14 ;ebx+ecx=14 |
pushf |
jbe fr_do1 |
sub edx,14 |
sub ecx,edx |
fr_do1: |
shl ebx,9 |
mov esi,0x100000+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,0x100000 ;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 ? |
cmp [esp+12],dword 0 |
je frnoread |
jmp frfl8 |
frfl7: |
dec dword [esp+16] |
frfl8: |
shl edi,1 ;find next cluster from FAT |
add edi,0x280000 |
movzx eax,word [edi] |
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 |
filedelete: |
;-------------------------------------------- |
; |
; filedelete - sys floppy |
; in: |
; eax - pointer to filename 11 chars |
; |
; out: |
; eax - 0 = successful, 5 = file not found |
; |
;-------------------------------------------- |
sub esp,32 |
call expand_filename |
push eax ebx ecx edx esi edi |
call rd_findfile |
je fifoundd |
pop edi esi edx ecx ebx eax ;file not found |
add esp,32 |
mov eax,5 |
ret |
fifoundd: |
mov [edi-11],byte 0xE5 ;mark filename deleted |
add edi,0xf |
movzx eax,word [edi] |
mov edi,eax ;edi = cluster |
frnewd: |
shl edi,1 ;find next cluster from FAT |
add edi,0x280000 |
movzx eax,word [edi] |
mov [edi],word 0x0 ;clear fat chain cluster |
mov edi,eax |
cmp edi,dword 0xff8 ;last cluster ? |
jb frnewd |
pop edi esi edx ecx ebx eax |
add esp,32 |
xor eax,eax ; file found |
ret |
filesave: |
;---------------------------------------------------------- |
; |
; filesave - sys floppy |
; |
; eax points to filename 11 chars |
; |
; eax ; pointer to file name |
; ebx ; buffer |
; ecx ; count to write in bytes |
; edx ; 0 create new , 1 append |
; |
;----------------------------------------------------------- |
sub esp,32 |
call expand_filename |
test edx,edx |
jnz fsdel |
pusha |
call filedelete |
popa |
fsdel: |
call ramdisk_free_space |
cmp ecx,edi |
jbe rd_do_save |
add esp,32 |
mov eax,8 ;disk full |
ret |
rd_do_save: |
push eax ebx ecx edx esi edi |
mov edi,0x100000+512*18+512 ;Point at directory |
mov edx,224 +1 |
; find an empty spot for filename in the root dir |
l20ds: |
dec edx |
test edx,edx |
jz frnoreadds |
l21ds: |
cmp [edi],byte 0xE5 |
jz fifoundds |
cmp [edi],byte 0x0 |
jz fifoundds |
add edi,32 ; Advance to next entry |
jmp l20ds |
fifoundds: |
push edi ; move the filename to root dir |
mov esi,[esp+4+20] |
mov ecx,11 |
cld |
rep movsb |
pop edi |
mov edx,edi |
add edx,11+0xf ; edx <- cluster save position |
mov ebx,[esp+12] ; save file size |
mov [edi+28],ebx |
mov [edi+11],byte 0x20 ; attribute |
; Ivan Poddubny 11/12/2003: |
call get_date_for_file ; from FAT32.INC |
mov [edi+24],ax ; date |
call get_time_for_file ; from FAT32.INC |
mov [edi+22],ax ; time |
; End |
mov edi,0x280000 ;pointer to first cluster |
mov ecx,2849 |
cld |
frnewds: |
xor ax,ax |
repne scasw |
mov ebx,2848 |
sub ebx,ecx |
mov [edx],bx ; save next cluster pos. to prev cl. |
mov edx,edi ; next save pos abs mem add |
dec edx |
dec edx |
call fdc_filesave |
pusha ; move save to floppy cluster |
add ebx,31 |
shl ebx,9 |
add ebx,0x100000 |
mov eax,[esp+32+16] |
mov ecx,512 |
call memmove |
popa |
mov eax,[esp+12] |
cmp eax,512 |
jb flnsa |
sub eax,512 |
mov [esp+12],eax |
mov eax,[esp+16] |
add eax,512 |
mov [esp+16],eax |
jmp frnewds |
flnsa: |
dec edi |
dec edi |
mov [edi],word 4095 ; mark end of file - last cluster |
frnoreadds: |
pop edi esi edx ecx ebx eax |
add esp,32 |
pusha |
cli |
call fdc_commitfile |
sti |
popa |
xor eax,eax ;ok write |
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,0x100000+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,0x100000+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 |
rd_getfileinfo: |
;get date, time, size or attributes of file |
;IN: eax - pointer to file, ebx - type of function: 12-get filesize, 13-get fileattr, 14-get filedate |
;ecx - filelengh 0=root |
;OUT: eax=0 - Ok or 5 - file not found ebx - date/time, size or attributes |
test ecx,ecx |
jnz no_getfinfo_root |
mov eax,5 ;if root - fnf |
xor ebx,ebx |
dec ebx |
ret |
no_getfinfo_root: ;if not root |
sub esp,32 |
call expand_filename |
call rd_findfile |
je fifoundi |
add esp,32 ;if file not found |
ret |
fifoundi: |
cmp ebx,13 |
jne no_rd_attr |
movzx ebx,byte [edi] ;get attributes |
jmp rd_getfileinfo_end |
no_rd_attr: |
cmp ebx,14 |
jne no_rd_date |
mov ebx,dword [edi+11] ;get date/time |
jmp rd_getfileinfo_end |
no_rd_date: |
mov ebx,dword [edi+17] ;get size |
rd_getfileinfo_end: |
xor eax,eax |
add esp,32 |
ret |
/kernel/trunk/blkdev/rdsave.inc |
---|
0,0 → 1,26 |
cmp eax,6 ; SAVE FLOPPY IMAGE (HD version only) |
jnz nosaveimage |
cmp ebx,1 |
jnz img_save_hd_1 |
mov edx,bootpath ; path = '/KOLIBRI ' |
jmp img_save_hd_3 |
img_save_hd_1: |
cmp ebx,2 |
jnz img_save_hd_2 |
mov edx,bootpath2 ; path = 0 (root dir) |
jmp img_save_hd_3 |
img_save_hd_2: |
cmp ebx,3 |
jnz exit_for_anyone |
mov edx,[3010h] |
mov edx,[edx+10h] |
add edx,ecx |
img_save_hd_3: |
call restorefatchain ; restore FAT !!! |
mov eax,image_save |
mov ebx,1440*1024 ; size 1440 Kb |
mov ecx,0x100000 ; address of image |
call file_write |
ret |
nosaveimage: |
/kernel/trunk/boot/bootcode.inc |
---|
0,0 → 1,917 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; BOOTCODE.INC ;; |
;; ;; |
;; 16 bit bootcode for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Ville Turjanmaa ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;========================================================================== |
; |
; 16 BIT FUNCTIONS |
; |
;========================================================================== |
print: push si |
mov si,leftpr-0x10000 |
call printplain |
pop si |
printplain: pusha |
mov dx,0x1000 |
mov es,dx |
cmp byte [es:display_atboot-0x10000],2 |
je printplain_exit |
mov ds,dx |
cld |
lodsb |
prpl1: |
mov ah,0xe |
xor bh,bh |
int 0x10 |
lodsb |
cmp al,0 |
jne prpl1 |
printplain_exit: |
popa |
ret |
setbase1000: push ax |
mov ax,0x1000 |
mov es,ax |
mov ds,ax |
pop ax |
ret |
getkey: push ecx |
push edx |
add ebx,0x0101 |
xor eax,eax |
gk1: |
in al,0x60 |
mov cl,al |
gk0: |
in al,0x60 |
cmp al,cl |
je gk0 |
cmp ax,11 |
jg gk0 |
gk0_1: |
mov cl,al |
; add al,47 |
; mov [ds:keyinbs-0x10000],al |
; mov si,keyinbs-0x10000 |
; call printplain |
gk12: |
in al,0x60 |
cmp al,cl |
je gk12 |
cmp ax,240 |
jne gk13 |
mov al,cl |
jmp gk14 |
gk13: |
add cl,128 |
cmp al,cl |
jne gk1 |
sub al,128 |
gk14: |
movzx edx,bl |
cmp eax,edx |
jb gk1 |
movzx edx,bh |
cmp eax,edx |
jg gk1 |
test ebx,0x010000 |
jnz gk3 |
mov cx,0x1000 |
mov dx,cx |
add eax,47 |
mov cx,ax |
cmp cx,58 |
jb gk_nozero |
sub cx,10 |
gk_nozero: |
mov [ds:keyin-0x10000],cl |
mov si,keyin-0x10000 |
call printplain |
gk3: |
sub eax,48 |
pop edx |
pop ecx |
ret |
;========================================================================= |
; |
; 16 BIT CODE |
; |
;========================================================================= |
start_of_code: |
; RESET 16 BIT SELECTORS/REGISTERS/STACK |
mov ax,0x1000 |
mov es,ax |
mov ds,ax |
mov ax,0x2000 |
mov ss,ax |
mov sp,0xffff |
xor ax,ax |
xor bx,bx |
xor cx,cx |
xor dx,dx |
xor si,si |
xor di,di |
xor bp,bp |
; DRAW FRAMES |
call setbase1000 |
cmp byte [es:display_atboot-0x10000],2 |
je no_mode_atboot |
mov ax,0x0003 |
mov bx,0x0000 |
mov dx,0x0000 |
int 0x10 |
no_mode_atboot: |
; Load & set russian VGA font (RU.INC) |
mov bp,RU_FNT1-10000h ; 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 |
push cs |
pop es |
int 10h |
mov bp,RU_FNT2-10000h ; 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 |
push cs |
pop es |
int 10h |
; End set VGA russian font |
call setbase1000 |
mov ax,0xb800 |
mov es,ax |
mov di,0 |
mov si,d80x25-0x10000 |
mov cx,80*25 |
mov ah,1*16+15 |
dfl1: |
cld |
lodsb |
stosw |
loop dfl1 |
call setbase1000 |
; SAY HI TO USER |
mov si,linef2-0x10000 |
call printplain |
mov si,version-0x10000 |
call print |
; TEST FOR 386+ |
pushf |
pop ax |
mov dx,ax |
xor ax,0x4000 |
push ax |
popf |
pushf |
pop ax |
and ax,0x4000 |
and dx,0x4000 |
cmp ax,dx |
jnz cpugood |
mov si,not386-0x10000 |
call print |
jmp $ |
cpugood: |
; RESET 32 BIT SELECTORS/REGISTERS/SELECTORS |
mov ax,0x1000 |
mov es,ax |
mov ds,ax |
mov ax,0x2000 |
mov ss,ax |
mov esp,0xffff |
xor eax,eax |
xor ebx,ebx |
xor ecx,ecx |
xor edx,edx |
xor esi,esi |
xor edi,edi |
xor ebp,ebp |
; FLUSH 8042 KEYBOARD CONTROLLER |
;// mike.dld [ |
; mov al,0xED |
; out 0x60,al |
; or cx,-1 |
; @@: |
; in al,0x64 |
; test al,2 |
; jz @f |
; loop @b |
; @@: |
; mov al,0 |
; out 0x60,al |
; or cx,-1 |
; @@: |
; in al,0x64 |
; test al,2 |
; jz @f |
; loop @b |
; @@: |
;// mike.dld ] |
; mov ecx,10000 |
; fl1: |
; in al,0x64 |
; loop fl1 |
; test al,1 |
; jz fl2 |
; in al,0x60 |
; jmp fl1 |
; fl2: |
;**************************************************************** |
; The function is modified Mario79 |
;***************************************************************** |
; wait_kbd: ; variant 1 |
; mov cx,2500h ;çàäåðæêà ïîðÿäêà 10 ìñåê |
; test_kbd: |
; in al,64h ;÷èòàåì ñîñòîÿíèå êëàâèàòóðû |
; test al,2 ;ïðîâåðêà áèòà ãîòîâíîñòè |
; loopnz test_kbd |
mov al,0xf6 ; Ñáðîñ êëàâèàòóðû, ðàçðåøèòü ñêàíèðîâàíèå |
out 0x60,al |
mov cx,0 |
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 |
; DISPLAY VESA INFORMATION |
mov ax,0x0 |
mov es,ax |
mov ax,0x4f00 |
mov di,0xa000 |
int 0x10 |
cmp ax,0x004f |
je vesaok2 |
mov dx,0x1000 |
mov es,dx |
mov si,novesa-0x10000 |
call print |
mov ax,16 |
jmp novesafound |
vesaok2: |
mov ax,[es:di+4] |
mov dx,ax |
add ax,'0'*256+'0' |
push word 0x1000 |
pop es |
mov [es:vervesa+vervesa_off-0x10000], ah |
mov [es:vervesa+vervesa_off+2-0x10000], al |
; ivan 24/11/2004 begin |
;push ax |
; ivan 24/11/2004 end |
mov si,vervesa-0x10000 |
call print |
novesafound: |
call setbase1000 |
; ivan 24/11/2004 begin |
;pop bx |
; ivan 24/11/2004 end |
; ASK GRAPHICS MODE |
movzx eax,byte [es:preboot_graph-0x10000] |
cmp eax,0 |
jne pre_graph |
mov si,gr_mode-0x10000 |
call printplain |
gml0: |
mov ebx,0x0A01 |
call getkey |
pre_graph: |
cmp eax,1 |
jl sgml1 |
cmp eax,8 |
jg sgml1 |
mov si,ax |
sub si,1 |
shl si,4 |
add si,gr_table-0x10000 |
mov bx,[es:si+0] |
mov cx,[es:si+4] |
mov dx,[es:si+8] |
jmp gml10 |
sgml1: |
cmp al,9 |
jnz gml00 |
mov bx,0x13 |
mov cx,640 |
mov dx,480 |
push word 0x0 |
pop es |
mov [es:0x9000],byte 32 |
mov dword [es:0x9018],0x800000 |
push word 0x1000 |
pop es |
jmp gml10 |
gml00: |
cmp al,0xa |
jnz gml02 |
mov bx,0x12 |
mov cx,640 |
mov dx,480 |
push word 0x0 |
pop es |
mov [es:0x9000],byte 32 |
mov dword [es:0x9018],0x800000 |
push word 0x1000 |
pop es |
jmp gml10 |
gml02: |
jmp gml0 |
gr_table: |
dd 0x112+0100000000000000b , 640 , 480 , 0 |
dd 0x115+0100000000000000b , 800 , 600 , 0 |
dd 0x118+0100000000000000b , 1024 , 768 , 0 |
dd 0x11B+0100000000000000b , 1280 , 1024 , 0 |
dd 0x112 , 640 , 480 , 0 |
dd 0x115 , 800 , 600 , 0 |
dd 0x118 , 1024 , 768 , 0 |
dd 0x11B , 1280 ,1024 , 0 |
gml10: |
push word 0x0000 |
pop es |
mov [es:0x9008],bx |
mov [es:0x900A],cx |
mov [es:0x900C],dx |
push word 0x1000 |
pop es |
mov ax,32 |
cmp bx,0x13 |
je nov |
cmp bx,0x12 |
je nov |
; USE DEFAULTS OR PROBE |
; bx - mode : cx - x size : dx - y size |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
movzx ax,[es:preboot_gprobe-0x10000] |
test ax,ax |
jne pre_probe |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
test bx,0100000000000000b |
jz noprobe |
mov si,probetext-0x10000 |
call printplain |
push bx |
mov ebx,0x0201 |
call getkey |
pop bx |
pre_probe: |
cmp ax,1 |
je noprobe |
push cx dx |
mov bx,0x100 |
newprobe: |
inc bx |
cmp bx,0x17f |
jne probemore |
mov si,prnotfnd-0x10000 |
call printplain |
jmp $ |
probemore: |
mov ax,0x4f01 |
mov cx,bx |
and cx,0xfff |
push word 0x0000 |
pop es |
mov di,0xa000 |
int 0x10 |
mov eax,[es:di] ; lfb ? |
test eax,10000000b |
jz newprobe |
mov eax,[es:di+0x12] ; x size ? |
cmp ax,word [esp+2] |
jne newprobe |
mov eax,[es:di+0x14] ; y size ? |
cmp ax,dx |
jne newprobe |
movzx eax,byte [es:di+0x19] |
cmp eax,32 ;24 |
jb newprobe |
push word 0x0000 ; save probed mode |
pop es |
add bx,0100000000000000b |
mov [es:0x9008],bx |
push word 0x1000 |
pop es |
push bx |
mov si,prid-0x10000 |
call printplain |
pop bx dx cx |
noprobe: |
; FIND VESA 2.0 LFB & BPP |
mov ax,0x4f01 |
mov cx,bx |
and cx,0xfff |
push word 0x0000 |
pop es |
mov di,0xa000 |
int 0x10 |
; LFB |
mov ecx,[es:di+0x28] |
mov [es:0x9018],ecx |
; BPP |
movzx ax,byte [es:di+0x19] |
mov [es:0x9000],ax |
; ---- vbe voodoo |
BytesPerScanLine equ 0x10 |
push ax |
mov ax, [es:di+BytesPerScanLine] |
mov [es:0x9001],ax |
pop ax |
; ----- |
nov: |
cmp ax,24 |
jnz nbpp24 |
mov si,bt24-0x10000 |
jmp bppl |
nbpp24: |
cmp ax,32 |
jnz nbpp32 |
mov si,bt32-0x10000 |
jmp bppl |
nbpp32: |
mov si,btns-0x10000 |
call print |
jmp $ |
bppl: |
call printplain |
; FIND VESA 1.2 PM BANK SWITCH ADDRESS |
mov ax,0x4f0A |
mov bx,0x0 |
int 0x10 |
xor eax,eax |
xor ebx,ebx |
mov ax,es |
shl eax,4 |
mov bx,di |
add eax,ebx |
xor ebx,ebx |
mov bx,[es:di] |
add eax,ebx |
push word 0x0 |
pop es |
mov [es:0x9014],eax |
push word 0x1000 |
pop es |
; GRAPHICS ACCELERATION |
mov al, [es:preboot_mtrr-0x10000] |
test al,al |
jne pre_mtrr |
mov si,gr_acc-0x10000 |
call printplain |
mov ebx,0x0201 |
call getkey |
pre_mtrr: |
push word 0x0000 |
pop es |
mov [es:0x901C],al |
push word 0x1000 |
pop es |
mov si,linef-0x10000 |
call printplain |
; VRR_M USE |
mov al,[es:preboot_vrrm-0x10000] |
test al,al |
jne pre_vrrm |
mov si,vrrmprint-0x10000 |
call print |
mov ebx,0x0301 |
call getkey |
pre_vrrm: |
push word 0x0000 |
pop es |
mov [es:0x9030],al |
push word 0x1000 |
pop es |
mov si,linef2-0x10000 |
call printplain |
; MEMORY MODEL |
; movzx eax,byte [es:preboot_memory-0x10000] |
; cmp eax,0 |
; jne pre_mem |
;;;;;;;;;;;;;;;;;;;;;;;;; |
; mario79 - memory size ; |
;;;;;;;;;;;;;;;;;;;;;;;;; |
; mov ax,0E801h |
;;; xor bx,bx ; thanks to Alexei for bugfix [18.07.2004] |
; xor cx, cx |
; xor dx, dx |
; int 0x15 |
; movzx ebx, dx ;bx |
; movzx eax, cx ;ax |
; shl ebx,6 ; ïåðåâîä â êèëîáàéòû (x64) |
; add eax,ebx |
; add eax, 1000h ;440h |
; cmp eax,40000h ; 256? |
; jge mem_256_z |
; cmp eax,20000h ; 128? |
; jge mem_128_z |
; cmp eax,10000h ; 64? |
; jge mem_64_z |
; cmp eax,8000h ; 32? |
; jge mem_32_z |
; jmp mem_16_z |
; |
;mem_256_z: mov si,memokz256-0x10000 |
; call printplain |
; mov eax,5 |
; jmp pre_mem |
;mem_128_z: mov si,memokz128-0x10000 |
; call printplain |
; mov eax,4 |
; jmp pre_mem |
;mem_64_z: mov si,memokz64-0x10000 |
; call printplain |
; mov eax,3 |
; jmp pre_mem |
;mem_32_z: mov si,memokz32-0x10000 |
; call printplain |
; mov eax,2 |
; jmp pre_mem |
;mem_16_z: mov si,memokz16-0x10000 |
; call printplain |
; mov eax,1 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; pre_mem: |
; push word 0x0000 |
; pop es |
; mov [es:0x9030],al |
; push word 0x1000 |
; pop es |
; mov si,linef-0x10000 |
; call printplain |
; DIRECT WRITE TO LFB, PAGING DISABLED |
; movzx eax,byte [es:preboot_lfb-0x10000] |
; mov eax,1 ; paging disabled |
; cmp eax,0 |
; jne pre_lfb |
; mov si,gr_direct-0x10000 |
; call printplain |
; mov ebx,0x0201 |
; call getkey |
; pre_lfb: |
; push word 0x0000 |
; pop es |
; mov [es:0x901E],al |
; mov ax,0x1000 |
; mov es,ax |
; mov si,linef-0x10000 |
; call printplain |
push 0 |
pop es |
mov [es:0x901E],byte 1 |
push 0x1000 |
pop es |
; BOOT DEVICE |
movzx eax,byte [es:preboot_device-0x10000] |
cmp eax,0 |
jne pre_device |
mov si,bdev-0x10000 |
call printplain |
mov ebx,0x0301 |
call getkey |
pre_device: |
dec al |
mov [es:boot_dev-0x10000],al |
mov si,linef-0x10000 |
call printplain |
; READ DISKETTE TO MEMORY |
cmp [boot_dev-0x10000],0 |
jne no_sys_on_floppy |
mov si,diskload-0x10000 |
call print |
mov ax,0x0000 ; reset drive |
mov dx,0x0000 |
int 0x13 |
mov cx,0x0001 ; startcyl,startsector |
mov dx,0x0000 ; starthead,drive |
push word 80*2 ; read no of sect |
reads: |
pusha |
xor si,si |
newread: |
push word 0x0 |
pop es |
mov bx,0xa000 ; es:bx -> data area |
mov ax,0x0200+18 ; read, no of sectors to read |
int 0x13 |
cmp ah,0 |
jz goodread |
add si,1 |
cmp si,10 |
jnz newread |
mov si,badsect-0x10000 |
call printplain |
jmp $ |
goodread: |
; move -> 1mb |
mov si,movedesc-0x10000 |
push word 0x1000 |
pop es |
mov cx,256*18 |
mov ah,0x87 |
int 0x15 |
cmp ah,0 ; was the move successfull ? |
je goodmove |
mov dx,0x3f2 ; floppy motor off |
mov al,0 |
out dx,al |
mov si,memmovefailed-0x10000 |
call print |
jmp $ |
goodmove: |
mov eax,[es:movedesc-0x10000+0x18+2] |
add eax,512*18 |
mov [es:movedesc-0x10000+0x18+2],eax |
popa |
inc dh |
cmp dh,2 |
jnz bb2 |
mov dh,0 |
inc ch |
pusha ; print prosentage |
push word 0x1000 |
pop es |
xor eax,eax ; 5 |
mov al,ch |
shr eax,2 |
and eax,1 |
mov ebx,5 |
mul bx |
add al,48 |
mov [es:pros+1-0x10000],al |
xor eax,eax ; 10 |
mov al,ch |
shr eax,3 |
add al,48 |
mov [es:pros-0x10000],al |
mov si,pros-0x10000 |
call printplain |
popa |
bb2: |
pop ax |
dec ax |
push ax |
cmp ax,0 |
jnz rs |
jmp readdone |
rs: |
jmp reads |
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 |
readdone: |
pop ax |
mov dx,0x3f2 ; floppy motor off |
mov al,0 |
out dx,al |
mov si,backspace-0x10000 |
call printplain |
call printplain |
mov si,okt-0x10000 |
call printplain |
no_sys_on_floppy: |
mov ax,0x0000 ; reset drive |
mov dx,0x0000 |
int 0x13 |
mov dx,0x3f2 ; floppy motor off |
mov al,0 |
out dx,al |
; PAGE TABLE |
push word 0x0000 |
pop es |
mov ecx,[es:0x9018] |
push ecx |
map_mem equ 64 ; amount of memory to map |
mov bx,0x6000 |
mov es,bx ; [es:di] = 6000:0 |
xor edi,edi |
mov ecx,256*map_mem ; Map (mapmem) M |
mov eax,7 |
cld |
pt2: |
cmp ecx,256*(map_mem-8) ; 8 M map to LFB |
jnz pt3 |
pop eax |
add eax,7 |
pt3: |
cmp ecx,256*(map_mem-12) ; 12 M back to linear = physical |
jnz pt4 |
mov eax,12*0x100000 + 7 |
pt4: |
stosd |
add eax,4096 |
loop pt2 |
mov bx,0x7100 |
mov es,bx |
xor edi,edi |
mov eax,8*0x100000+7 |
mov ecx,256*4 |
pt5: |
stosd |
add eax,0x1000 |
loop pt5 |
; 4 KB PAGE DIRECTORY |
mov bx , 0x7F00 |
mov es , bx ; [es:di] = 7000:0 |
xor edi, edi |
mov ecx, 64 / 4 |
mov eax, 0x60007 ; for 0 M |
cld |
pd4k: |
stosd |
add eax, 0x1000 |
loop pd4k |
mov dword [es:0x800],0x71007 ;map region 0x80000000-0x803FFFFF to 0x800000-0xCFFFFF |
xor esi,esi |
mov edi,second_base_address shr 20 |
mov ecx,64/4 |
mov bx,0x7F00 |
mov ds,bx |
rep movsd |
mov bx,0x1000 |
mov ds,bx |
mov eax, 0x7F000 +8+16 ; Page directory and enable caches |
mov cr3, eax |
; SET GRAPHICS |
mov dx,0x0000 |
mov es,dx |
mov bx,[es:0x9008] |
mov ax,bx ; vga & 320x200 |
cmp ax,0x13 |
je setgr |
cmp ax,0x12 |
je setgr |
mov ax,0x4f02 ; Vesa |
setgr: |
int 0x10 |
cmp ah,0 |
jz gmok |
mov si,fatalsel-0x10000 |
call print |
jmp $ |
gmok: |
mov dx,0x1000 |
mov es,dx |
; set mode 0x12 graphics registers: |
cmp bx,0x12 |
jne gmok2 |
mov al,0x05 |
mov dx,0x03ce |
out dx,al ; select GDC mode register |
mov al,0x02 |
mov dx,0x03cf |
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 |
mov dx,0x03c5 |
out dx,al ; set mask for all planes 0-3 |
mov al,0x08 |
mov dx,0x03ce |
out dx,al ; select GDC bit mask register |
; for writes to 0x03cf |
gmok2: |
mov dx,0x1000 |
mov es,dx |
/kernel/trunk/boot/booteng.inc |
---|
0,0 → 1,109 |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
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: line_full_top |
line_space |
line_space |
line_half |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
db 186,' Kolibri OS comes with ABSOLUTELY NO WARR' |
db 'ANTY; See file COPYING for details ',186 |
line_full_bottom |
novesa db "Display: EGA/CGA",13,10,0 |
vervesa db "Version of Vesa: Vesa x.x ",13,10,0 |
vervesa_off=22 |
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 Colors: [9] 320x200, " |
db "VGA 16 Colors: [0] 640x480",13,10 |
db 186," Select mode: ",0 |
bt24 db 13,10,186," Bits Per Pixel: 24",13,10,0 |
bt32 db 13,10,186," Bits Per Pixel: 32",13,10,0 |
vrrmprint db 13,10,186," 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 |
askmouse db " Mouse at:" |
db " [1] PS/2 (USB), [2] Com1, [3] Com2." |
db " Select port [1-3]: ",0 |
no_com1 db 13,10,186, " No COM1 mouse",0 |
no_com2 db 13,10,186, " No COM2 mouse",0 |
gr_acc db 13,10,186," Vesa 2.0+ : MTRR graphics acceleration " |
db "[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 13,10,186 |
db " Load ramdisk from [1-floppy; 2-C:\menuet.img (FAT32);" |
db 13,10,186," " |
db "3-use preloaded ram-image from kernel restart]: ",0 |
probetext db 13,10,13,10,186," Use standart graphics mode? [1-yes, " |
db "2-probe bios (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 |
prid db " pr.",0 |
prnotfnd db " pr. - not found.",0 |
modena db "Fatal - VBE 0x112+ required.",0 |
not386 db "Fatal - CPU 386+ required.",0 |
btns db 13,10,186,"Fatal - Can't determine color depth.",0 |
fatalsel db 13,10,"Fatal - Graphics mode not supported by hardware.",0 |
badsect db 13,10,186," Fatal - Bad sector. Replace floppy. ",0 |
memmovefailed db "Fatal - Int 0x15 move failed.",0 |
linef2 db 13,10 |
linef db 13,10,0 |
okt db " ... OK",0 |
keyin db "x",0 |
keyinbs db "x",8,0 |
diskload db 13,10,186," Loading diskette: 00 %",8,8,8,8,0 |
backspace db 8,0 |
pros db "00",8,8,0 |
leftpr db 186," ",0 |
boot_dev db 0 ; 0=floppy, 1=hd |
/kernel/trunk/boot/bootru.inc |
---|
0,0 → 1,110 |
;====================================================================== |
; |
; BOOT DATA |
; |
;====================================================================== |
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: line_full_top |
line_space |
line_space |
line_half |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
line_space |
db 186,' Kolibri OS ¥ ¯à¥¤®áâ ¢«ï¥â ¨ª ª¨å £ àa' |
db '⨩; ®¤à®¡¥¥ - á¬. GNU.TXT ',186 |
line_full_bottom |
novesa db "¨¤¥®ª àâ : EGA/CGA",13,10,0 |
vervesa db "¥àá¨ï VESA: Vesa x.x ",13,10,0 |
vervesa_off=19 |
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 ¢¥â®¢: [9] 320x200, " |
db "VGA 16 ¢¥â®¢: [0] 640x480",13,10 |
db 186," ë¡¥à¨â¥ ¢¨¤¥®à¥¦¨¬: ",0 |
bt24 db 13,10,186," «ã¡¨ 梥â : 24",13,10,0 |
bt32 db 13,10,186," «ã¡¨ 梥â : 32",13,10,0 |
vrrmprint db 13,10,186," ᯮ«ì§®¢ âì VRR? (ç áâ®â ª ¤à®¢ ¢ëè¥ 60 æ" |
db " ⮫쪮 ¤«ï ¯¥à¥å®¤®¢:",13,10 |
db 186," 1024*768>800*600 ¨ 800*600>640*480) [1-¤ , 2-¥â]: ",0 |
askmouse db "ëèì:" ; 186, " " |
db " [1] PS/2 (USB), [2] Com1, [3] Com2." |
db " ë¡¥à¨â¥ ¯®àâ [1-3]: ",0 |
no_com1 db 13,10,186," No COM1 mouse",0 |
no_com2 db 13,10,186," No COM2 mouse",0 |
gr_acc db 13,10,186," Vesa 2.0+: ª«îç¨âì MTRR ¤«ï ãáª®à¥¨ï £à 䨪¨? " |
db "[1-¤ /2-¥â]: ",0 |
gr_direct db 186," ᯮ«ì§®¢ âì «¨¥©ë© ¢¨¤¥®¡ãä¥à? " |
db "[1-¤ /2-¥â]: ",0 |
;mem_model db 13,10,186," ¡ê+¬ ¯ ¬ï⨠[1-16 Mb / 2-32 Mb / " |
; db "3-64Mb / 4-128 Mb / 5-256 Mb]: ",0 |
bootlog db 13,10,186," à®á¬®âà¥âì ¦ãà « § £à㧪¨? [1-¥â/2-¤ ]: ",0 |
bdev db 186 |
db " £à㧨âì ®¡à § ¨§ [1-¤¨áª¥â ; 2-C:\menuet.img (FAT32);" |
db 13,10,186," " |
db "3-¨á¯®«ì§®¢ âì 㦥 § £àã¦¥ë© ®¡à §]: ",0 |
probetext db 13,10,13,10,186," â ¤ àâë© ¢¨¤¥®à¥¦¨¬? [1-¤ , " |
db "2-¯à®¢¥à¨âì ¤à㣨¥ (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 |
prid db " pr.",0 |
prnotfnd db " pr. - ®è¨¡ª .",0 |
modena db "訡ª - ॡã¥âáï ¯®¤¤¥à¦ª VBE 0x112+.",0 |
not386 db "訡ª - ॡã¥âáï ¯à®æ¥áá®à 386+.",0 |
btns db 13,10,186," 訡ª - ¥ ¬®£ã ®¯à¥¤¥«¨âì £«ã¡¨ã 梥â .",0 |
fatalsel db 13,10,"訡ª - ë¡à ë© ¢¨¤¥®à¥¦¨¬ ¥ ¯®¤¤¥à¦¨¢ ¥âáï.",0 |
badsect db 13,10,186," 訡ª - ¨áª¥â ¯®¢à¥¦¤¥ . ®¯à®¡ã©â¥ ¤àã£ãî. " |
db 0 |
memmovefailed db "Fatal - Int 0x15 move failed.",0 |
linef2 db 13,10 |
linef db 13,10,0 |
okt db " ... OK",0 |
keyin db "x",0 |
keyinbs db "x",8,0 |
diskload db 13,10,186," £à㧪 ¤¨áª¥âë: 00 %",8,8,8,8,0 |
backspace db 8,0 |
pros db "00",8,8,0 |
leftpr db 186," ",0 |
boot_dev db 0 |
/kernel/trunk/boot/preboot.inc |
---|
0,0 → 1,23 |
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 db 0 ; graph mode |
preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) |
preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) |
;;preboot_mouse db 0 ; mouse port (1-PS2, 2-COM1, 3-COM2) |
preboot_mtrr db 0 ; mtrr acceleration (1-yes, 2-no) |
preboot_device db 0 ; boot device |
; (1-floppy 2-harddisk 3-kernel restart) |
;;preboot_memory db 0 ; amount of memory |
; (1-16Mb;2-32Mb;3-64Mb;4-128Mb;5-256Mb) |
; !!!! 0 - autodetect !!!! |
preboot_blogesc db 0 ; start immediately after bootlog |
hdsysimage db 'MENUET IMG' ; load from |
image_save db 'MENUET IMG' ; save to |
/kernel/trunk/boot/rdload.inc |
---|
0,0 → 1,95 |
; READ RAMDISK IMAGE FROM HD |
cmp [boot_dev],1 |
jne no_sys_on_hd |
test [0x40001],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 [0x40002] |
cmp [fat32part],eax |
jle position_1_1 |
position_2: |
test [0x40001],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 [0x40003] |
cmp eax,[fat32part] |
jle position_2_1 |
position_3: |
test [0x40001],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 [0x40004] |
cmp eax,[fat32part] |
jle position_3_1 |
position_4: |
test [0x40001],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 [0x40005] |
cmp eax,[fat32part] |
jle position_4_1 |
jmp yes_sys_on_hd |
search_and_read_image: |
; mov [0xfe10],dword 0 ; entries in hd cache |
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 |
mov ebx, 1474560/512 |
mov ecx, 0x100000 |
mov esi, 0 |
mov edi, 12 |
call file_read |
ret |
image_retrieved db 0 |
counter_of_partitions db 0 |
no_sys_on_hd: |
yes_sys_on_hd: |
/kernel/trunk/boot/ru.inc |
---|
0,0 → 1,92 |
; 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 |
/kernel/trunk/boot/shutdown.inc |
---|
0,0 → 1,496 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; |
;; Shutdown for Menuet |
;; |
;; Distributed under General Public License |
;; See file COPYING for details. |
;; Copyright 2003 Ville Turjanmaa |
;; |
system_shutdown: ; shut down the system |
mov eax,3 ; stop playing cd |
call sys_cd_audio |
cli |
cld |
mov al,[0x2f0000+0x9030] |
cmp al,1 |
jl no_shutdown_parameter |
cmp al,4 |
jg no_shutdown_parameter |
jmp yes_shutdown_param |
no_shutdown_parameter: |
movzx ecx,word [0x2f0000+0x900A] |
movzx esi,word [0x2f0000+0x900C] |
imul ecx,esi ;[0xfe04] |
; mov ecx,0x500000/4 ;3fff00/4 ; darken screen |
push ecx |
mov esi,[0xfe80] |
cmp esi,32*0x100000 |
jbe no_darken_screen |
mov edi,16*0x100000 |
sdnewpix: |
mov eax,[esi] |
add esi,4 |
shr eax,1 |
and eax,0x7f7f7f7f |
stosd |
loop sdnewpix |
pop ecx |
mov esi,16*0x100000 |
mov edi,[0xfe80] |
cld |
rep movsd |
no_darken_screen: |
mov eax,[0xfe00] |
shr eax,1 |
sub eax,220 |
mov ebx,[0xfe04] |
shr ebx,1 |
mov [shutdownpos],ebx |
sub ebx,120 |
mov edi,1 |
mov ecx,0x0000ff |
sdnewpix2: |
call [putpixel] |
inc eax |
mov esi,[0xfe00] |
shr esi,1 |
add esi,220 |
cmp eax,esi |
jnz sdnewpix2 |
dec ecx |
mov eax,[0xfe00] |
shr eax,1 |
sub eax,220 |
inc ebx |
mov edx,[shutdownpos] |
add edx,105 |
cmp ebx,edx |
jnz sdnewpix2 |
mov esi,[0xfe00] ; menuet version |
shr esi,1 |
sub esi,220 |
add esi,27 |
shl esi,16 |
mov eax,esi |
add eax,[shutdownpos] |
sub eax,105 |
mov ebx,0xffff00 |
mov ecx,version |
mov edx,34 |
mov edi,1 |
call dtext |
mov esi,[0xfe00] ; 'it is safe..' |
shr esi,1 |
sub esi,220 |
add esi,27 |
shl esi,16 |
mov eax,esi |
add eax,[shutdownpos] |
add eax,33 |
mov esi,6 |
mov ebx,0xffffff |
mov ecx,shutdowntext |
mov edx,40 |
mov edi,1 |
newsdt: |
call dtext |
add eax,10 |
add ecx,40 |
dec esi |
jnz newsdt |
mov eax,rosef ; load rose.txt |
mov ebx,0 |
mov ecx,16800 |
mov edx,0x90000 |
mov esi,12 |
call fileread |
mov esi,[0xfe00] ; draw rose |
shr esi,1 |
add esi,20 |
shl esi,16 |
mov eax,esi |
add eax,[shutdownpos] |
sub eax,110 |
mov ebx,0x00ff00 |
mov ecx,0x90001 |
mov edx,27 |
mov edi,1 |
nrl: |
call dtext |
sub ebx,0x050000 |
add eax,8 |
add ecx,31 |
cmp ecx,dword 0x90001+25*31 |
jnz nrl |
call checkEgaCga |
yes_shutdown_param: |
cli |
mov eax,kernel ; load kernel.mnt to 0x8000:0 |
mov esi,12 |
mov ebx,0 |
mov ecx,-1 |
mov edx,0x80000 |
call fileread |
mov esi,restart_kernel_4000 ; move kernel re-starter to 0x4000:0 |
mov edi,0x40000 |
mov ecx,1000 |
cld |
rep movsb |
mov eax,0x2F0000 ; restore 0x0 - 0xffff |
mov ebx,0x0000 |
mov ecx,0xffff |
call memmove |
call restorefatchain |
mov eax,pr_mode_exit |
mov [0x467+0],ax |
mov [0x467+2],word 0x1000 |
mov al,0x0F |
out 0x70,al |
mov al,0x05 |
out 0x71,al |
mov al,0xFE |
out 0x64,al |
hlt |
use16 |
pr_mode_exit: |
mov ax,1000 |
mov ds,ax |
mov es,ax |
mov fs,ax |
mov gs,ax |
mov ss,ax |
; mov bl,[shutdown_parameter] |
mov al,2 |
out 0x21,al |
mov al,0 |
out 0xA1,al |
; mov [es:shutdown_parameter-0x10000],bl |
jmp real_mode-0x10000 |
old_ints_h: |
dw 4*0x20 |
dd 0 |
dw 0 |
real_mode: |
lidt [cs:old_ints_h-0x10000] |
mov sp,0xfff0 |
sti |
jmp temp_3456 |
nbw: |
xor ax,ax |
in al,0x60 |
call pause_key |
cmp al,7 |
jge nbw |
mov bl,al |
nbw2: |
in al,0x60 |
call pause_key |
cmp al,bl |
je nbw2 |
cmp al,240 ;ax,240 |
jne nbw31 |
mov al,bl |
dec al |
jmp nbw32 |
nbw31: |
add bl,128 |
cmp al,bl |
jne nbw |
sub al,129 |
nbw32: |
cmp al,1 ; write floppy |
jne no_floppy_write |
call floppy_write |
jmp temp_3456 ;nbw |
no_floppy_write: |
cmp al,2 ; poweroff |
jne no_apm_off |
call APM_PowerOff |
no_apm_off: |
cmp al,3 ; boot |
jnz no_sys_boot |
mov ax,0x0040 |
mov ds,ax |
mov word[0x0072],0x1234 |
jmp 0xF000:0xFFF0 |
no_sys_boot: |
cmp al,4 ; restart kernel |
je restart_kernel |
temp_3456: |
push word 0x0000 |
pop es |
mov al,byte [es:0x9030] |
cmp al,1 |
jl nbw |
cmp al,4 |
jg nbw |
jmp nbw32 |
; jmp nbw |
pause_key: |
mov ecx,100 |
pause_key_1: |
loop pause_key_1 |
ret |
iglobal |
kernel db 'KERNEL MNT' |
; shutdown_parameter db 0 |
endg |
restart_kernel: |
mov ax,0x0003 ; set text mode for screen |
int 0x10 |
jmp 0x4000:0000 |
restart_kernel_4000: |
mov di,0x1000 ; load kernel image from 0x8000:0 -> 0x1000:0 |
new_kernel_block_move: |
mov ebx,0 |
new_kernel_byte_move: |
mov ax,di |
add ax,0x7000 |
mov es,ax |
mov dl,[es:bx] |
mov es,di |
mov [es:bx],dl |
inc ebx |
cmp ebx,65536 |
jbe new_kernel_byte_move |
add di,0x1000 |
cmp di,0x2000 |
jbe new_kernel_block_move |
wbinvd ; write and invalidate cache |
mov ax,0x1000 |
mov es,ax |
mov ax,0x2000 |
mov ss,ax |
mov sp,0xff00 |
jmp 0x1000:0000 |
APM_PowerOff: |
;!!!!!!!!!!!!!!!!!!!!!!!! |
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 |
uglobal |
flm db 0 |
endg |
floppy_write: ; write diskette image to physical floppy |
pusha |
mov ax,0x1000 |
mov es,ax |
cmp [es:flm-0x10000],byte 1 |
je fwwritedone |
mov [es:flm-0x10000],byte 1 |
mov ax,0x0000 ; reset drive |
mov dx,0x0000 |
int 0x13 |
mov cx,0x0001 ; startcyl,startsector |
mov dx,0x0000 ; starthead,drive |
push word 80*2 ; read no of sect |
fwwrites: |
pusha |
; move 1mb+ -> 0:a000 |
pusha |
mov si,fwmovedesc -0x10000 |
push word 0x1000 |
pop es |
mov cx,256*18 |
mov ah,0x87 |
int 0x15 |
mov eax,[es:fwmovedesc-0x10000+0x12] |
add eax,512*18 |
mov [es:fwmovedesc-0x10000+0x12],eax |
popa |
xor si,si |
fwnewwrite: |
push word 0x0 |
pop es |
mov bx,0xa000 ; es:bx -> data area |
mov ax,0x0300+18 ; read, no of sectors to read |
int 0x13 |
cmp ah,0 |
jz fwgoodwrite |
add si,1 |
cmp si,10 |
jnz fwnewwrite |
add esp,32+2 |
popa ; can't access diskette |
ret |
fwgoodwrite: |
popa |
inc dh |
cmp dh,2 |
jnz fwbb2 |
mov dh,0 |
inc ch |
fwbb2: |
cld |
pop ax |
dec ax |
push ax |
cmp ax,0 |
jnz fwrs |
pop ax |
jmp fwwritedone |
fwrs: |
jmp fwwrites |
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 |
fwwritedone: |
popa |
ret |
use32 |
uglobal |
shutdownpos dd 0x0 |
endg |
iglobal |
;shutdowntext: |
; db "IT'S SAFE TO POWER OFF COMPUTER OR " |
; db ' ' |
; db '1) SAVE RAMDISK TO FLOPPY ' |
; db '2) APM - POWEROFF ' |
; db '3) REBOOT ' |
; db '4) RESTART KERNEL ' |
shutdowntext: |
db "¥§®¯ ᮥ ¢ëª«î票¥ ª®¬¯ìîâ¥à ¨«¨ " |
db ' ' |
db '1) ®åà ¨âì à ¬¤¨áª ¤¨áª¥âã ' |
db '2) APM - ¢ëª«î票¥ ¯¨â ¨ï ' |
db '3) ¥à¥§ £à㧪 á¨á⥬ë ' |
db '4) ¥áâ àâ ï¤à ¨§ ' |
rosef: |
db 'ROSE TXT' |
endg |
/kernel/trunk/build_en.bat |
---|
0,0 → 1,4 |
@if not exist lang.inc ( |
@echo lang fix en >lang.inc |
) |
@fasm kernel.asm kernel.mnt |
/kernel/trunk/build_ru.bat |
---|
0,0 → 1,4 |
@if not exist lang.inc ( |
@echo lang fix ru >lang.inc |
) |
@fasm kernel.asm kernel.mnt |
/kernel/trunk/bus/pci/pci16.inc |
---|
0,0 → 1,46 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; PCI16.INC ;; |
;; ;; |
;; 16 bit PCI driver code ;; |
;; ;; |
;; Version 0.2 December 21st, 2002 ;; |
;; ;; |
;; Author: Victor Prodan, victorprodan@yahoo.com ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
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 |
/kernel/trunk/bus/pci/pci32.inc |
---|
0,0 → 1,358 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; PCI32.INC ;; |
;; ;; |
;; 32 bit PCI driver code ;; |
;; ;; |
;; Version 0.2 December 21st, 2002 ;; |
;; ;; |
;; Author: Victor Prodan, victorprodan@yahoo.com ;; |
;; Credits: ;; |
;; Ralf Brown ;; |
;; Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;*************************************************************************** |
; Function |
; pci_api: |
; |
; Description |
; entry point for system PCI calls |
;*************************************************************************** |
align 4 |
pci_api: |
cmp [pci_access_enabled],1 |
jne no_pci_access_for_applications |
or al,al |
jnz pci_fn_1 |
; PCI function 0: get pci version (AH.AL) |
movzx eax,word [0x2F0000+0x9022] |
ret |
pci_fn_1: |
cmp al,1 |
jnz pci_fn_2 |
; PCI function 1: get last bus in AL |
mov al,[0x2F0000+0x9021] |
ret |
pci_fn_2: |
cmp al,2 |
jne pci_fn_3 |
; PCI function 2: get pci access mechanism |
mov al,[0x2F0000+0x9020] |
ret |
pci_fn_3: |
cmp al,4 |
jz pci_read_reg ;byte |
cmp al,5 |
jz pci_read_reg ;word |
cmp al,6 |
jz pci_read_reg ;dword |
cmp al,8 |
jz pci_write_reg ;byte |
cmp al,9 |
jz pci_write_reg ;word |
cmp al,10 |
jz pci_write_reg ;dword |
no_pci_access_for_applications: |
mov eax,-1 |
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 |
;*************************************************************************** |
align 4 |
pci_read_reg: |
cmp byte [0x2F0000+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 |
;*************************************************************************** |
align 4 |
pci_write_reg: |
cmp byte [0x2F0000+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 |
/kernel/trunk/core/fpu.inc |
---|
0,0 → 1,62 |
iglobal |
prev_user_of_fpu dd 0x1 ; set to OS |
endg |
label fpu_tss at 0xB080 |
label fpu_stack dword at 0xB060 |
align 4 |
fpu_handler: |
; clear TS flag in CR0 -> for task switching |
clts |
; save FPU context of the previous task |
mov eax,[prev_user_of_fpu] |
shl eax,8 |
add eax,0x80000+0x10 |
fsave [eax] |
; next task switch save our FPU context |
; now restore context of current task (if exists) |
mov eax,[0x3000] |
mov [prev_user_of_fpu],eax |
shl eax,8 |
add eax,0x80000 |
cmp [eax+0x7f],byte 0 |
je bs7_first_fpu |
frstor [eax+0x10] |
bs7_first_fpu: |
mov [eax+0x7f],byte 1 |
; prepare structure in stack for proper IRET |
movzx eax,word [fpu_tss+l.ss-tss_sceleton] ; push ss |
push eax |
mov eax,[fpu_tss+l.esp-tss_sceleton] ; push esp |
push eax |
mov eax,[fpu_tss+l.eflags-tss_sceleton] ; push eflags |
push eax |
movzx eax,word [fpu_tss+l.cs-tss_sceleton] ; push cs |
push eax |
mov eax,[fpu_tss+l.eip-tss_sceleton] ; push eip |
push eax |
; save eax |
push dword [fpu_tss+l.eax-tss_sceleton] |
; restore all segment registers |
mov ax,[fpu_tss+l.es-tss_sceleton] |
mov es,ax |
mov ax,[fpu_tss+l.fs-tss_sceleton] |
mov fs,ax |
mov ax,[fpu_tss+l.gs-tss_sceleton] |
mov gs,ax |
mov ax,[fpu_tss+l.ds-tss_sceleton] |
mov ds,ax |
; restore eax |
pop eax |
iret |
/kernel/trunk/core/mem.inc |
---|
0,0 → 1,473 |
if ~defined mem_inc |
mem_inc_fix: |
mem_inc fix mem_inc_fix |
;include "memmanag.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;High-level memory management in MenuetOS. |
;;It uses memory manager in memmanager.inc |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
second_base_address=0xC0000000 |
std_application_base_address=0x10000000 |
general_page_table_ dd 0 |
general_page_table=general_page_table_+second_base_address |
;----------------------------------------------------------------------------- |
create_general_page_table: |
;input |
; none |
;output |
; none |
;Procedure create general page directory and write |
;it address to [general_page_table]. |
pushad |
mov eax,1 ;alloc 1 page |
mov ebx,general_page_table ;write address to [general_page_table] |
call MEM_Alloc_Pages ;allocate page directory |
mov eax,[general_page_table] |
call MEM_Get_Linear_Address ;eax - linear address of page directory |
mov edi,eax |
mov ebx,eax |
xor eax,eax |
mov ecx,4096/4 |
cld |
rep stosd ;clear page directory |
mov eax,4 |
mov edx,eax |
call MEM_Alloc_Pages ;alloc page tables for 0x0-0x1000000 region |
cmp eax,edx |
jnz $ ;hang if not enough memory |
;fill page tables |
xor esi,esi |
mov ebp,7 |
.loop: |
;esi - number of page in page directory |
;ebp - current page address |
;ebx - linear address of page directory |
mov eax,[ebx+4*esi] |
add dword [ebx+4*esi],7 ;add flags to address of page table |
call MEM_Get_Linear_Address |
;eax - linear address of page table |
mov ecx,4096/4 |
;ecx (counter) - number of pages in page table |
;current address=4Mb*esi |
cmp esi,2 |
jz .start_lfb_map ;lfb map begin at 0x800000 |
cmp esi,3 |
jz .end_lfb_map ;lfb map end at 0xC00000 |
jmp .loop1 |
.start_lfb_map: |
;current address=lfb address |
mov ebp,[0x2f0000+0x9018] |
add ebp,7 ;add flags |
jmp .loop1 |
.end_lfb_map: |
;current address=linear address |
mov ebp,12*0x100000+7 |
.loop1: |
mov [eax],ebp ;write page address (with flags) in page table |
add eax,4 |
add ebp,4096 ;size of page=4096 bytes |
loop .loop1 |
inc esi ;next page directory entry |
cmp esi,edx |
jnz .loop |
;map region 0x80000000-0x803fffff to 0x800000-0xcfffff |
mov eax,1 ;size of the region is 4Mb so only 1 page table needed |
mov edx,ebx ;ebx still contains linear address of the page directory |
add ebx,0x800 |
call MEM_Alloc_Pages ;alloc page table for the region |
mov eax,[ebx] |
add dword [ebx],7 ;add flags |
call MEM_Get_Linear_Address ;get linear address of the page table |
mov ebx,eax |
mov ecx,4096/4 ;number of pages in page table |
mov eax,8*0x100000+7 |
.loop3: |
;ebx - linear address of page table |
;eax - current linear address with flags |
mov [ebx],eax |
add ebx,4 |
add eax,4096 |
loop .loop3 |
;map region 0xC0000000-* to 0x0-* |
mov esi,edx ;esi=linear address of the page directory |
lea edi,[esi+(second_base_address shr 20)];add offset of entry (0xC00) |
mov ecx,4 |
rep movsd ;first 16Mb of the region mapped as 0x0-0x1000000 block |
mov eax,[0xfe8c] ;eax=memory size |
add eax,0x3fffff |
shr eax,22 |
mov esi,eax ;calculate number of entries in page directory |
sub esi,4 ;subtract entries for first 16Mb. |
mov ebp,0x1000000+7 ;start physical address with flags |
;mapping memory higher than 16Mb |
.loop4: |
;esi (counter) - number of entries in page directory |
;edi - address of entry |
test esi,esi |
jle .loop4end |
call MEM_Alloc_Page ;alloc page table for entry in page directory |
mov [edi],eax |
add dword [edi],7 ;write physical address of page table in page directory |
add edi,4 ;move entry pointer |
call MEM_Get_Linear_Address |
mov ecx,eax |
xor edx,edx |
.loop5: |
;ecx - linear address of page table |
;edx - index of page in page table |
;ebp - current mapped physical address with flags |
mov [ecx+4*edx],ebp ;write address of page in page table |
add ebp,0x1000 ;move to next page |
inc edx |
cmp edx,4096/4 |
jl .loop5 |
dec esi |
jmp .loop4 |
.loop4end: |
.set_cr3: |
;set value of cr3 register to the address of page directory |
mov eax,[general_page_table] |
add eax,8+16 ;add flags |
mov cr3,eax ;now we have full access paging |
popad |
ret |
;----------------------------------------------------------------------------- |
simple_clone_cr3_table: |
;Parameters: |
; eax - physical address of cr3 table (page directory) |
;result: |
; eax - physical address of clone of cr3 table. |
;Function copy only page directory. |
push ecx |
push edx |
push esi |
push edi |
call MEM_Get_Linear_Address |
;eax - linear address of cr3 table |
mov esi,eax |
call MEM_Alloc_Page |
test eax,eax |
jz .failed |
;eax - physical address of new page diretory |
mov edx,eax |
call MEM_Get_Linear_Address |
mov edi,eax |
mov ecx,4096/4 |
cld |
;esi - address of old page directory |
;edi - address of new page directory |
rep movsd ;copy page directory |
mov eax,edx |
.failed: |
pop edi |
pop esi |
pop edx |
pop ecx |
ret |
;----------------------------------------------------------------------------- |
create_app_cr3_table: |
;Parameters: |
; eax - slot of process (index in 0x3000 table) |
;result: |
; eax - physical address of table. |
;This function create page directory for new process and |
;write it physical address to offset 0xB8 of extended |
;process information. |
push ebx |
mov ebx,eax |
mov eax,[general_page_table] |
call simple_clone_cr3_table ;clone general page table |
shl ebx,8 |
mov [second_base_address+0x80000+ebx+0xB8],eax ;save address of page directory |
pop ebx |
ret |
;----------------------------------------------------------------------------- |
get_cr3_table: |
;Input: |
; eax - slot of process |
;result: |
; eax - physical address of page directory |
shl eax,8 ;size of process extended information=256 bytes |
mov eax,[second_base_address+0x80000+eax+0xB8] |
ret |
;----------------------------------------------------------------------------- |
dispose_app_cr3_table: |
;Input: |
; eax - slot of process |
;result: |
; none |
;This procedure frees page directory, |
;page tables and all memory of process. |
pushad |
mov ebp,eax |
;ebp = process slot in the procedure. |
shl eax,8 |
mov eax,[second_base_address+0x80000+eax+0xB8] |
mov ebx,eax |
;ebx = physical address of page directory |
call MEM_Get_Linear_Address |
mov edi,eax |
;edi = linear address of page directory |
mov eax,[edi+(std_application_base_address shr 20)] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov esi,eax |
;esi = linear address of first page table |
;search threads |
; mov ecx,0x200 |
xor edx,edx |
mov eax,0x2 |
.loop: |
;eax = current slot of process |
mov ecx,eax |
shl ecx,5 |
cmp byte [second_base_address+0x3000+ecx+0xa],0 ;if process running? |
jnz .next ;slot empty or process is terminating - go to next slot |
shl ecx,3 |
cmp [second_base_address+0x80000+ecx+0xB8],ebx ;compare page directory addresses |
jnz .next |
inc edx ;thread found |
.next: |
inc eax |
cmp eax,[0x3004] ;exit loop if we look through all processes |
jle .loop |
;edx = number of threads |
;our process is zombi so it isn't counted |
test edx,edx |
jnz .threadsexists |
;if there isn't threads then clear memory. |
add edi,std_application_base_address shr 20 |
.loop1: |
;edi = linear address of current directory entry |
;esi = linear address of current page table |
test esi,esi |
jz .loop1end |
xor ecx,ecx |
.loop2: |
;ecx = index of page |
mov eax,[esi+4*ecx] |
test eax,eax |
jz .loopend ;skip empty entries |
and eax,not (4096-1) ;clear flags |
push ecx |
call MEM_Free_Page ;free page |
pop ecx |
.loopend: |
inc ecx |
cmp ecx,1024 ;there are 1024 pages in page table |
jl .loop2 |
mov eax,esi |
call MEM_Free_Page_Linear ;free page table |
.loop1end: |
add edi,4 ;move to next directory entry |
mov eax,[edi] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov esi,eax ;calculate linear address of new page table |
test edi,0x800 |
jz .loop1 ;test if we at 0x80000000 address? |
and edi,not (4096-1) ;clear offset of page directory entry |
mov eax,edi |
call MEM_Free_Page_Linear ;free page directory |
popad |
ret |
.threadsexists: ;do nothing |
popad ;last thread will free memory |
ret |
;----------------------------------------------------------------------------- |
mem_alloc_specified_region: |
;eax - linear directory address |
;ebx - start address (aligned to 4096 bytes) |
;ecx - size in pages |
;result: |
; eax=1 - ok |
; eax=0 - failed |
;Try to alloc and map ecx pages to [ebx;ebx+4096*ecx) interval. |
pushad |
mov ebp,ebx ;save start address for recoil |
mov esi,eax |
.gen_loop: |
;esi = linear directory address |
;ebx = current address |
;ecx = remaining size in pages |
mov edx,ebx |
shr edx,22 |
mov edi,[esi+4*edx] ;find directory entry for current address |
test edi,edi |
jnz .table_exists ;check if page table allocated |
call MEM_Alloc_Page ;alloc page table |
test eax,eax |
jz .failed |
mov [esi+4*edx],eax |
add dword [esi+4*edx],7 ;write it address with flags |
call MEM_Get_Linear_Address |
call mem_fill_page ;clear page table |
jmp .table_linear |
.table_exists: |
;calculate linear address of page table |
mov eax,edi |
and eax,not (4096-1) ;clear flags |
call MEM_Get_Linear_Address |
.table_linear: |
;eax = linear address of page table |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) ;calculate index in page table |
mov edi,eax |
.loop: |
;edi = linear address of page table |
;edx = current page table index |
;ecx = remaining size in pages |
;ebx = current address |
test ecx,ecx |
jle .endloop1 ;all requested pages allocated |
call MEM_Alloc_Page ;alloc new page |
test eax,eax |
jz .failed |
mov [edi+4*edx],eax |
add dword [edi+4*edx],7 ;write it address with flags |
call MEM_Get_Linear_Address |
call mem_fill_page ;clear new page |
;go to next page table entry |
dec ecx |
add ebx,4096 |
inc edx |
test edx,(1024-1) |
jnz .loop |
jmp .gen_loop |
.endloop1: |
popad |
mov eax,1 ;ok |
ret |
.failed: |
;calculate data for recoil |
sub ebx,ebp |
shr ebx,12 |
mov ecx,ebx ;calculate number of allocated pages |
mov eax,esi ;restore linear address of page directory |
mov ebx,ebp ;restore initial address |
call mem_free_specified_region ;free all allocated pages |
popad |
xor eax,eax ;fail |
ret |
;----------------------------------------------------------------------------- |
mem_fill_page: |
;Input: |
; eax - address |
;result: |
; none |
;set to zero 4096 bytes at eax address. |
push ecx |
push edi |
mov edi,eax |
mov ecx,4096/4 |
xor eax,eax |
rep stosd |
lea eax,[edi-4096] |
pop edi |
pop ecx |
ret |
;----------------------------------------------------------------------------- |
mem_free_specified_region: |
;eax - linear page directory address |
;ebx - start address (aligned to 4096 bytes) |
;ecx - size in pages |
;result - none |
;Free pages in [ebx;ebx+4096*ecx) region. |
pushad |
mov esi,eax |
xor ebp,ebp |
.gen_loop: |
;esi = linear page directory address |
;ebx = current address |
;ecx = remaining pages |
;ebp = 0 for first page table |
; 1 otherwise |
mov edx,ebx |
shr edx,22 |
mov eax,[esi+4*edx] ;find directory entry for current address |
and eax,not (4096-1) |
test eax,eax |
jnz .table_exists |
;skip absent page tables |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) ;edx - index of current page |
add ebx,1 shl 22 |
add ecx,edx |
and ebx,not ((1 shl 22)-1) |
mov ebp,1 ;set flag |
sub ecx,1024 ;ecx=ecx-(1024-edx) |
jg .gen_loop |
popad |
ret |
.table_exists: |
call MEM_Get_Linear_Address |
;eax - linear address of table |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) ;edx - index of current page |
mov edi,eax |
.loop: |
;edi = linear address of page table entry |
;edx = index of page table entry |
;ecx = remaining pages |
test ecx,ecx |
jle .endloop1 |
mov eax,[edi+4*edx] |
and eax,not (4096-1) |
call MEM_Free_Page ;free page |
mov dword [edi+4*edx],0 ;and clear page table entry |
dec ecx |
inc edx |
cmp edx,1024 |
jl .loop |
test ebp,ebp |
jz .first_page |
mov eax,edi |
call MEM_Free_Page_Linear ;free page table |
mov edx,ebx |
shr edx,22 |
mov dword [esi+4*edx],0 ;and clear page directory entry |
.first_page: |
add ebx,1 shl 22 |
and ebx,not ((1 shl 22)-1) ;calculate new current address |
mov ebp,1 ;set flag |
jmp .gen_loop |
.endloop1: |
popad |
ret |
end if |
/kernel/trunk/core/memmanag.inc |
---|
0,0 → 1,977 |
if ~defined memmanager_inc |
memmanager_inc_fix: |
memmanager_inc fix memmanager_inc_fix |
;for testing in applications |
if defined B32 |
iskernel=1 |
else |
iskernel=0 |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; Memory allocator for MenuetOS kernel |
;; Andrey Halyavin, halyavin@land.ru 2005 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; heap block structure - |
;; you can handle several ranges of |
;; pages simultaneosly. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.heap_linear_address equ 0 |
.heap_block_size equ 4 |
.heap_physical_address equ 8 |
.heap_reserved equ 12 |
.heap_block_info equ 16 |
max_heaps equ 8 |
.range_info equ 36 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; memory manager data |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_heap_block_ rd .heap_block_info*max_heaps/4 |
MEM_heap_block=MEM_heap_block_+second_base_address |
MEM_heap_count_ rd 1 |
MEM_heap_count=MEM_heap_count_+second_base_address |
if iskernel = 0 |
MEM_general_mutex rd 1 |
MEM_call_count rd 1 |
MEM_mutex_pid rd 1 |
MEM_mutex_count rd 1 |
else |
MEM_cli_count_ rd 1 |
MEM_cli_count=MEM_cli_count_+second_base_address |
MEM_cli_prev_ rd 1 |
MEM_cli_prev=MEM_cli_prev_+second_base_address |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Init |
;;Initialize memory manager structures. |
;;Must be called first. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Init: |
push eax |
xor eax,eax |
if iskernel = 0 |
mov [MEM_heap_count],eax |
mov [MEM_general_mutex],eax |
mov [MEM_call_count],eax |
mov [MEM_mutex_pid],eax |
mov [MEM_mutex_count],eax |
else |
mov [MEM_cli_prev],eax ;init value = 0 |
dec eax |
mov [MEM_cli_count],eax ;init value = -1 |
end if |
pop eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;change_task |
;;procedure for changing tasks. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if iskernel = 0 |
change_task: |
push eax |
push ebx |
mov eax,5 |
xor ebx,ebx |
inc ebx |
int 0x40 |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_get_pid |
;;determine current pid |
;;result: |
;; eax - pid |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if iskernel = 0 |
MEM_get_pid: |
push ebx |
push ecx |
sub esp,1024 |
mov eax,9 |
mov ebx,esp |
mov ecx,-1 |
int 0x40 |
mov eax,[esp+30] |
add esp,1024 |
pop ecx |
pop ebx |
ret |
else |
; pid_address dd 0x3000 |
;MEM_get_pid: |
; mov eax,[pid_address] |
; mov eax,[eax] |
; ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Heap_Lock |
;;Wait until all operations with heap will be finished. |
;;Between MEM_Heap_Lock and MEM_Heap_UnLock operations |
;;with heap are forbidden. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Heap_Lock: |
if iskernel = 0 |
push eax |
inc dword [MEM_call_count] |
MEM_Heap_Lock_wait: |
mov eax,1 |
xchg [MEM_general_mutex],eax |
test eax,eax |
jz MEM_Heap_Lock_end |
call MEM_get_pid |
cmp [MEM_mutex_pid],eax |
jz MEM_Heap_Lock_end1 |
call change_task |
jmp MEM_Heap_Lock_wait |
MEM_Heap_Lock_end1: |
inc dword [MEM_mutex_count] |
pop eax |
ret |
MEM_Heap_Lock_end: |
call MEM_get_pid |
mov [MEM_mutex_pid],eax |
mov dword [MEM_mutex_count],1 |
pop eax |
ret |
else |
pushfd |
cli |
inc dword [MEM_cli_count] |
jz MEM_Heap_First_Lock |
add esp,4 |
ret |
MEM_Heap_First_Lock: ;save interrupt flag |
shr dword [esp],9 |
and dword [esp],1 |
pop dword [MEM_cli_prev] |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Heap_UnLock |
;;After this routine operations with heap are allowed. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Heap_UnLock: |
if iskernel = 0 |
push eax |
xor eax,eax |
dec dword [MEM_mutex_count] |
jnz MEM_Heap_UnLock_No_Wait1 |
dec dword [MEM_call_count] |
mov [MEM_mutex_pid],eax |
mov [MEM_general_mutex],eax;release mutex BEFORE task switching |
jz MEM_Heap_UnLock_No_Wait |
call change_task ;someone want to use heap - switch tasks |
MEM_Heap_UnLock_No_Wait: |
pop eax |
ret |
MEM_Heap_UnLock_No_Wait1: |
dec dword [MEM_call_count] |
jz MEM_Heap_UnLock_No_Wait2 |
call change_task |
MEM_Heap_UnLock_No_Wait2: |
pop eax |
ret |
else |
dec dword [MEM_cli_count] |
js MEM_Heap_UnLock_last |
ret |
MEM_Heap_UnLock_last: |
cmp dword [MEM_cli_prev],0 ;restore saved interrupt flag |
jz MEM_Heap_UnLock_No_sti |
sti |
MEM_Heap_UnLock_No_sti: |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Heap |
;;Add new range to memory manager. |
;;eax - linear address |
;;ebx - size in pages |
;;ecx - physical address |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Add_Heap: |
push edx |
call MEM_Heap_Lock |
mov edx,[MEM_heap_count] |
cmp edx,max_heaps |
jz MEM_Add_Heap_Error |
inc dword [MEM_heap_count] |
shl edx,4 |
mov [MEM_heap_block+edx+.heap_linear_address],eax |
mov [MEM_heap_block+edx+.heap_block_size],ebx |
shl dword [MEM_heap_block+edx+.heap_block_size],12 |
mov [MEM_heap_block+edx+.heap_physical_address],ecx |
lea edx,[4*ebx+.range_info+4095] ;calculate space for page info table |
and edx,0xFFFFF000 |
mov [eax],eax |
add [eax],edx ;first 4 bytes - pointer to first free page |
;clean page info area |
push edi |
lea edi,[eax+4] |
mov ecx,edx |
shr ecx,2 |
push eax |
xor eax,eax |
rep stosd |
pop eax |
pop edi |
;create free pages list. |
mov ecx,[eax] |
shl ebx,12 |
add eax,ebx ;eax - address after block |
MEM_Add_Heap_loop: |
add ecx,4096 |
mov [ecx-4096],ecx ;set forward pointer |
cmp ecx,eax |
jnz MEM_Add_Heap_loop |
mov dword [ecx-4096],0 ;set end of list |
MEM_Add_Heap_ret: |
call MEM_Heap_UnLock |
pop edx |
ret |
MEM_Add_Heap_Error: |
xor eax,eax |
jmp MEM_Add_Heap_ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Physical_Address |
;;Translate linear address to physical address |
;;Parameters: |
;; eax - linear address |
;;Result: |
;; eax - physical address |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Physical_Address |
MEM_Get_Physical_Address: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Physical_Address_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
jl MEM_Get_Physical_Address_next |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jge MEM_Get_Physical_Address_next |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
jmp MEM_Get_Physical_Address_loopend |
MEM_Get_Physical_Address_next: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Get_Physical_Address_loop |
xor eax,eax ;address not found |
MEM_Get_Physical_Address_loopend: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Linear_Address |
;;Translate physical address to linear address. |
;;Parameters: |
;; eax - physical address |
;;Result: |
;; eax - linear address |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Linear_Address |
MEM_Get_Linear_Address: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Linear_Address_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
jl MEM_Get_Linear_Address_Next |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jge MEM_Get_Linear_Address_Next |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
call MEM_Heap_UnLock |
pop ecx |
ret |
MEM_Get_Linear_Address_Next: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Get_Linear_Address_loop |
call MEM_Heap_UnLock |
pop ecx |
xor eax,eax ;address not found |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Page |
;;Allocate and add reference to page |
;;Result: |
;; eax<>0 - physical address of page |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Page |
MEM_Alloc_Page: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Page_loop: |
push ecx |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [ecx],0 |
jz MEM_Alloc_Page_loopend |
mov eax,[ecx] |
push dword [eax] |
pop dword [ecx] |
sub eax,ecx |
push eax |
shr eax,10 |
mov word [ecx+.range_info+eax],1 |
pop eax |
pop ecx |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
jmp MEM_Alloc_Page_ret |
MEM_Alloc_Page_loopend: |
pop ecx |
sub ecx,16 |
jns MEM_Alloc_Page_loop |
xor eax,eax |
MEM_Alloc_Page_ret: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Page_Linear |
;;Allocate and add reference to page |
;;Result: |
;; eax<>0 - linear address of page |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Page_Linear |
MEM_Alloc_Page_Linear: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Page_Linear_loop: |
push ecx |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [ecx],0 |
jz MEM_Alloc_Page_Linear_loopend |
mov eax,[ecx] |
push dword [eax] |
pop dword [ecx] |
push eax |
sub eax,ecx |
shr eax,10 |
mov word [ecx+.range_info+eax],1 |
pop eax |
pop ecx |
jmp MEM_Alloc_Page_Linear_ret |
MEM_Alloc_Page_Linear_loopend: |
pop ecx |
sub ecx,16 |
jns MEM_Alloc_Page_Linear_loop |
xor eax,eax |
MEM_Alloc_Page_Linear_ret: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Page |
;;Remove reference and free page if number of |
;;references is equal to 0 |
;;Parameters: |
;; eax - physical address of page |
;;Result: |
;; eax - 1 success |
;; eax - 0 failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Page |
MEM_Free_Page: |
test eax,eax |
jz MEM_Free_Page_Zero |
test eax,0xFFF |
jnz MEM_Free_Page_Not_Aligned |
push ebx |
push ecx |
push edx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Free_Page_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
js MEM_Free_Page_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Free_Page_Heap_loopend |
MEM_Free_Page_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Free_Page_Heap_loop |
xor eax,eax |
inc eax |
jmp MEM_Free_Page_ret |
MEM_Free_Page_Heap_loopend: |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov ebx,eax |
add eax,ecx |
shr ebx,10 |
mov edx,[ecx+.range_info+ebx] |
test edx,0x80000000 |
jnz MEM_Free_Page_Bucket |
test dx,dx |
jz MEM_Free_Page_Error |
dec word [ecx+.range_info+ebx] |
jnz MEM_Free_Page_OK |
MEM_Free_Page_Bucket: |
push dword [ecx] |
mov [ecx],eax |
pop dword [eax] |
mov dword [ecx+.range_info+ebx],0 |
MEM_Free_Page_OK: |
mov eax,1 |
MEM_Free_Page_ret: |
call MEM_Heap_UnLock |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Page_Error: |
xor eax,eax |
jmp MEM_Free_Page_ret |
MEM_Free_Page_Zero: |
inc eax |
ret |
MEM_Free_Page_Not_Aligned: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Page_Linear |
;;Remove reference and free page if number of |
;;references is equal to 0 |
;;Parameters: |
;; eax - linear address of page |
;;Result: |
;; eax - 1 success |
;; eax - 0 failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Page_Linear |
MEM_Free_Page_Linear: |
test eax,eax |
jz MEM_Free_Page_Linear_Zero |
test eax,0xFFF |
jnz MEM_Free_Page_Linear_Not_Aligned |
push ebx |
push ecx |
push edx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Free_Page_Linear_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
js MEM_Free_Page_Linear_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Free_Page_Linear_Heap_loopend |
MEM_Free_Page_Linear_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Free_Page_Linear_Heap_loop |
xor eax,eax |
inc eax |
jmp MEM_Free_Page_Linear_ret |
MEM_Free_Page_Linear_Heap_loopend: |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov ebx,eax |
add eax,ecx |
shr ebx,10 |
mov edx,[ecx+.range_info+ebx] |
test edx,0x80000000 |
jnz MEM_Free_Page_Linear_Bucket |
test dx,dx |
jz MEM_Free_Page_Linear_Error |
dec word [ecx+.range_info+ebx] |
jnz MEM_Free_Page_Linear_OK |
MEM_Free_Page_Linear_Bucket: |
mov edx,[ecx] |
mov [eax],edx |
mov dword [eax+4],0 |
mov [ecx],eax |
test edx,edx |
jz MEM_Free_Page_No_Next |
mov [edx+4],eax |
MEM_Free_Page_No_Next: |
mov dword [ecx+.range_info+ebx],0 |
MEM_Free_Page_Linear_OK: |
xor eax, eax |
inc eax |
MEM_Free_Page_Linear_ret: |
call MEM_Heap_UnLock |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Page_Linear_Error: |
xor eax,eax |
jmp MEM_Free_Page_Linear_ret |
MEM_Free_Page_Linear_Zero: |
inc eax |
ret |
MEM_Free_Page_Linear_Not_Aligned: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Pages |
;;Allocates set of pages. |
;;Parameters: |
;; eax - number of pages |
;; ebx - buffer for physical addresses |
;;Result: |
;; eax - number of allocated pages |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Pages |
MEM_Alloc_Pages: |
push eax |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Alloc_Pages_ret |
MEM_Alloc_Pages_loop: |
call MEM_Alloc_Page |
test eax,eax |
jz MEM_Alloc_Pages_ret |
mov [ebx],eax |
add ebx,4 |
dec ecx |
jnz MEM_Alloc_Pages_loop |
MEM_Alloc_Pages_ret: |
sub [esp+8],ecx |
pop ecx |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Pages_Linear |
;;Allocates set of pages. |
;;Parameters: |
;; eax - number of pages |
;; ebx - buffer for linear addresses |
;;Result: |
;; eax - number of allocated pages |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Pages_Linear |
MEM_Alloc_Pages_Linear: |
push eax |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Alloc_Pages_Linear_ret |
MEM_Alloc_Pages_Linear_loop: |
call MEM_Alloc_Page_Linear |
test eax,eax |
jz MEM_Alloc_Pages_Linear_ret |
mov [ebx],eax |
add ebx,4 |
dec ecx |
jnz MEM_Alloc_Pages_Linear_loop |
MEM_Alloc_Pages_Linear_ret: |
sub [esp+8],ecx |
pop ecx |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Pages |
;;Parameters: |
;; eax - number of pages |
;; ebx - array of addresses |
;;Result: |
;; eax=1 - succcess |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Pages |
MEM_Free_Pages: |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Free_Pages_ret |
MEM_Free_Pages_loop: |
mov eax,[ebx] |
call MEM_Free_Page |
add ebx,4 |
test eax,eax |
jz MEM_Free_Pages_ret |
dec ecx |
jnz MEM_Free_Pages_loop |
MEM_Free_Pages_ret: |
pop ecx |
pop ebx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Pages_Linear |
;;Parameters: |
;; eax - number of pages |
;; ebx - array of addresses |
;;Result: |
;; eax=1 - succcess |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Pages_Linear |
MEM_Free_Pages_Linear: |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Free_Pages_Linear_ret |
MEM_Free_Pages_Linear_loop: |
mov eax,[ebx] |
call MEM_Free_Page_Linear |
add ebx,4 |
test eax,eax |
jz MEM_Free_Pages_Linear_ret |
dec ecx |
jnz MEM_Free_Pages_Linear_loop |
MEM_Free_Pages_Linear_ret: |
pop ecx |
pop ebx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Heap_Number |
;;Calculate number of heap which pointer belongs to. |
;;Parameter: |
;; eax - address |
;;Result: |
;; ecx - number of heap*16. |
;; eax=0 if address not found. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Heap_Number |
MEM_Get_Heap_Number: |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
jl MEM_Get_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Get_Heap_loopend |
MEM_Get_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Get_Heap_loop |
call MEM_Heap_UnLock |
xor eax,eax |
ret |
MEM_Get_Heap_loopend: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
call MEM_Heap_UnLock |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Heap_Number_Linear |
;;Calculate number of heap which pointer belongs to. |
;;Parameter: |
;; eax - address |
;;Result: |
;; ecx - number of heap*16. |
;; eax=0 if address not found. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Heap_Number_Linear |
MEM_Get_Heap_Number_Linear: |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Heap_Linear_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
jl MEM_Get_Heap_Linear_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Get_Heap_Linear_loopend |
MEM_Get_Heap_Linear_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Get_Heap_Linear_loop |
call MEM_Heap_UnLock |
xor eax,eax |
ret |
MEM_Get_Heap_Linear_loopend: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
call MEM_Heap_UnLock |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc |
;;Allocate small region. |
;;Parameters: |
;; eax - size (0<eax<=4096) |
;;Result: |
;; eax - linear address |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc |
MEM_Alloc: |
;find chain |
test eax,eax |
jng MEM_Alloc_Wrong_Size |
cmp eax,4096 |
jg MEM_Alloc_Wrong_Size |
push ebx |
push ecx |
push edx |
push esi |
dec eax |
shr eax,4 |
xor edx,edx |
MEM_Alloc_Find_Size: |
add edx,4 |
shr eax,1 |
jnz MEM_Alloc_Find_Size |
MEM_Alloc_Size_Found: |
mov ecx,edx |
shr ecx,2 |
add ecx,4 |
mov eax,1 |
shl eax,cl |
mov esi,eax |
;esi - block size |
;edx - offset |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Find_Heap: |
mov eax,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [eax+edx],0 |
jnz MEM_Alloc_Use_Existing |
sub ecx,16 |
jns MEM_Alloc_Find_Heap |
;create new bucket page |
call MEM_Alloc_Page_Linear |
call MEM_Get_Heap_Number_Linear |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov [ecx+edx],eax |
lea ebx,[eax+4096] |
MEM_Alloc_List_loop: |
mov [eax],eax |
mov [eax+4],eax |
add [eax],esi |
sub [eax+4],esi |
add eax,esi |
cmp eax,ebx |
jnz MEM_Alloc_List_loop |
sub ebx,esi |
mov dword [ebx],0 |
sub eax,4096 |
mov dword [eax+4],0 |
mov eax,ecx |
MEM_Alloc_Use_Existing: |
mov ebx,eax |
mov eax,[eax+edx] |
mov ecx,[eax] |
mov [ebx+edx],ecx |
test ecx,ecx |
jz MEM_Alloc_Became_Empty |
mov dword [ecx+4],0 |
MEM_Alloc_Became_Empty: |
mov ecx,eax |
sub ecx,ebx |
shr ecx,10 |
and ecx,0xFFFFFFFC |
inc byte [ebx+.range_info+ecx+2] |
shr edx,2 |
add edx,128 |
dec edx |
mov [ebx+.range_info+ecx+3],dl |
MEM_Alloc_ret: |
call MEM_Heap_UnLock |
pop esi |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Alloc_Wrong_Size: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free |
;;Parameters: |
;; eax - linear address |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free |
MEM_Free: |
test eax,eax |
jz MEM_Free_Zero |
push ebx |
push ecx |
push edx |
push esi |
push edi |
push ebp |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number_Linear |
test eax,eax |
jz MEM_Free_ret |
mov edx,eax |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
sub edx,ecx |
shr edx,10 |
and edx,0xFFFFFFFC |
mov ebx,[ecx+.range_info+edx] |
mov esi,ebx |
shr esi,24 |
sub esi,128 |
mov edi,[ecx+4+4*esi] |
mov [eax],edi |
mov dword [eax+4],0 |
test edi,edi |
jz MEM_Free_Empty_List |
mov [edi+4],eax |
MEM_Free_Empty_List: |
mov [ecx+4+4*esi],eax |
sub ebx,0x10000 |
mov [ecx+.range_info+edx],ebx |
test ebx,0xFF0000 |
jnz MEM_Free_ret |
;delete empty blocks on the page |
lea edx,[esi+5] |
and eax,0xFFFFF000 |
mov edi,eax |
mov eax,1 |
xchg ecx,edx |
shl eax,cl |
mov ecx,edx |
mov edx,eax |
;edx - size of block |
;edi - start of page |
mov eax,edi |
lea ebx,[eax+4096] |
MEM_Free_Block_loop: |
cmp dword [eax+4],0 |
jnz MEM_Free_Block_Not_First |
mov ebp,dword [eax] |
mov [ecx+4+4*esi],ebp |
test ebp,ebp |
jz MEM_Free_Block_Last |
mov dword [ebp+4],0 |
MEM_Free_Block_Last: |
jmp MEM_Free_Block_loop_end |
MEM_Free_Block_Not_First: |
mov ebp,dword [eax] |
push ebp |
mov ebp,dword [eax+4] |
pop dword [ebp] |
mov ebp,dword [eax] |
test ebp,ebp |
jz MEM_Free_Block_loop_end |
push dword [eax+4] |
pop dword [ebp+4] |
; jmp MEM_Free_Block_loop_end |
MEM_Free_Block_loop_end: |
add eax,edx |
cmp eax,ebx |
jnz MEM_Free_Block_loop |
mov eax,edi |
call MEM_Free_Page_Linear |
MEM_Free_ret: |
call MEM_Heap_UnLock |
pop ebp |
pop edi |
pop esi |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Zero: |
inc eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Reference |
;; eax - physical address of page |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Add_Reference |
MEM_Add_Reference: |
push ebx |
push ecx |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number |
test eax,eax |
jz MEM_Add_Reference_ret |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
shr eax,10 |
and eax,0xFFFFFFFC |
test dword [ecx+eax+.range_info],0x80000000 |
jnz MEM_Add_Reference_failed |
inc dword [ecx+eax+.range_info] |
MEM_Add_Reference_ret: |
call MEM_Heap_UnLock |
pop ecx |
pop ebx |
ret |
MEM_Add_Reference_failed: |
xor eax,eax |
jmp MEM_Add_Reference_ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Reference_Linear |
;; eax - linear address of page |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Add_Reference_Linear |
MEM_Add_Reference_Linear: |
push ebx |
push ecx |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number_Linear |
test eax,eax |
jz MEM_Add_Reference_Linear_ret |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
sub eax,ecx |
shr eax,10 |
and eax,0xFFFFFFFC |
test dword [ecx+eax+.range_info],0x80000000 |
jnz MEM_Add_Reference_Linear_failed |
inc dword [ecx+eax+.range_info] |
mov eax,1 |
MEM_Add_Reference_Linear_ret: |
call MEM_Heap_UnLock |
pop ecx |
pop ebx |
ret |
MEM_Add_Reference_Linear_failed: |
xor eax,eax |
jmp MEM_Add_Reference_Linear_ret |
end if |
end if ;memmanager.inc |
/kernel/trunk/core/newproce.inc |
---|
0,0 → 1,1321 |
if ~defined newprocess_inc |
newprocess_inc_fix: |
newprocess_inc fix newprocess_inc_fix |
include "mem.inc" |
include "memmanag.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;Working with new types of processes. |
;;Author: Khalyavin Andrey halyavin@land.ru |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
iglobal |
new_process_loading db 'K : New Process - loading',13,10,0 |
new_process_running db 'K : New Process - done',13,10,0 |
start_not_enough_memory db 'K : New Process - not enough memory',13,10,0 |
endg |
;----------------------------------------------------------------------------- |
find_new_process_place: |
;input: |
; none |
;result: |
; eax=[new_process_place]<>0 - ok |
; 0 - failed. |
;This function find least empty slot. |
;It doesn't increase [0x3004]! |
mov eax,0x3000+second_base_address |
push ebx |
mov ebx,[0x3004] |
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,0x3000+second_base_address |
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) |
mov [new_process_place],eax ;save process slot |
pop ebx |
ret |
.failed: |
xor eax,eax |
pop ebx |
ret |
;----------------------------------------------------------------------------- |
new_start_application_floppy: |
;input: |
; eax - pointer to filename |
; ebx - parameters to pass |
;result: |
; eax - pid of new process |
; or 0 if call fails. |
pushad |
mov esi,new_process_loading |
call sys_msg_board_str ;write to debug board |
;wait application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
;we can change system tables now |
push edi |
push ebx |
push eax |
call find_new_process_place ;find empty process slot |
sti |
test eax,eax |
jz .failed |
mov edi,eax |
shl edi,8 |
add edi,0x80000 |
mov ecx,256/4 |
xor eax,eax |
cld |
rep stosd ;clean extended information about process |
;set new process name |
mov eax,[esp+8] |
.find_last_byte: |
cmp byte [eax],0 |
jz .find_last_byte_end |
inc eax |
jmp .find_last_byte |
.find_last_byte_end: |
sub eax,11 ;last 11 bytes = application name |
; mov eax,[esp] ;eax - pointer to file name |
mov ebx,[new_process_place] |
shl ebx,8 |
add ebx,0x80000 |
mov ecx,11 |
call memmove |
;read header of file |
mov eax,[esp] |
mov ebx,1 ;index of first block |
mov ecx,2 ;number of blocks |
mov edx,0x90000 ;temp area |
mov esi,12 ;file name length |
mov edi,[esp+8] |
; cli |
call floppy_fileread ;read file from FD |
; sti |
cmp eax,0 |
jne .cleanfailed |
;check MENUET signature |
cmp [0x90000],dword 'MENU' |
jnz .cleanfailed |
cmp [0x90004],word 'ET' |
jnz .cleanfailed |
call get_app_params ;parse header fields |
cmp esi,0 |
jz .cleanfailed |
mov eax,[new_process_place] |
call create_app_cr3_table ;create page directory for new process |
test eax,eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address ;calculate linear address of it |
mov ebx,std_application_base_address |
mov ecx,[app_mem] |
add ecx,4095 |
shr ecx,12 |
mov edx,eax |
call mem_alloc_specified_region ;allocate memory for application |
test eax,eax |
jz .cleanfailed_mem |
mov eax,[edx+(std_application_base_address shr 20)] |
and eax,not (4096-1) ;eax - physical address of first (for application memory) page table |
call MEM_Get_Linear_Address |
mov edx,eax |
;read file |
mov ebx,1 |
mov esi,12 ;length of file name |
.loop1: |
;edx = linear address of current page table entry |
;ebx = index of current block in file |
push edx |
mov eax,[edx] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov edx,eax ;read file block to current page |
mov eax,[esp+4] ;restore pointer to file name |
mov ecx,8 ;number of blocks read |
push ebx |
mov edi,[esp+16] |
; cli |
call floppy_fileread |
;ebx=file size |
; sti |
pop ecx |
shr ebx,9 |
cmp ecx,ebx |
jg .endloop1 ;if end of file? |
mov ebx,ecx |
test eax,eax |
jnz .endloop1 ;check io errors |
pop edx |
add ebx,8 ;go to next page |
add edx,4 |
jmp .loop1 |
.endloop1: |
add esp,8+4 ;pop linear address of page table entry and pointer to file name |
call new_start_application_fl.add_app_parameters |
mov [esp+28],eax |
popad |
ret |
.cleanfailed_mem: |
mov esi,start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: ;clean process name |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
mov eax,' ' |
cld |
rep stosb |
.failed: |
add esp,8+4 |
mov [application_table_status],0 |
popad |
sti |
mov eax,-1 |
ret |
;----------------------------------------------------------------------------- |
new_start_application_fl: |
;input: |
; eax - pointer to filename |
; ebx - parameters to pass |
;result: |
; eax - pid of new process |
; or 0 if call fails. |
pushad |
mov esi,new_process_loading |
call sys_msg_board_str ;write to debug board |
;wait application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
;we can change system tables now |
push ebx |
push eax |
call find_new_process_place ;find empty process slot |
sti |
test eax,eax |
jz .failed |
mov edi,eax |
shl edi,8 |
add edi,0x80000 |
mov ecx,256/4 |
xor eax,eax |
cld |
rep stosd ;clean extended information about process |
;set new process name |
mov eax,[esp] ;eax - pointer to file name |
mov ebx,[new_process_place] |
shl ebx,8 |
add ebx,0x80000 |
mov ecx,11 |
call memmove |
;read header of file |
mov ebx,1 ;index of first block |
mov ecx,2 ;number of blocks |
mov edx,0x90000 ;temp area |
mov esi,12 ;file name length |
cli |
call fileread ;read file from RD |
sti |
cmp eax,0 |
jne .cleanfailed |
;check MENUET signature |
cmp [0x90000],dword 'MENU' |
jnz .cleanfailed |
cmp [0x90004],word 'ET' |
jnz .cleanfailed |
call get_app_params ;parse header fields |
cmp esi,0 |
jz .failed |
mov eax,[new_process_place] |
call create_app_cr3_table ;create page directory for new process |
test eax,eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address ;calculate linear address of it |
mov ebx,std_application_base_address |
mov ecx,[app_mem] |
add ecx,4095 |
shr ecx,12 |
mov edx,eax |
call mem_alloc_specified_region ;allocate memory for application |
test eax,eax |
jz .cleanfailed_mem |
mov eax,[edx+(std_application_base_address shr 20)] |
and eax,not (4096-1) ;eax - physical address of first (for application memory) page table |
call MEM_Get_Linear_Address |
mov edx,eax |
;read file |
mov ebx,1 |
mov esi,12 ;length of file name |
.loop1: |
;edx = linear address of current page table entry |
;ebx = index of current block in file |
push edx |
mov eax,[edx] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov edx,eax ;read file block to current page |
mov eax,[esp+4] ;restore pointer to file name |
mov ecx,8 ;number of blocks read |
push ebx |
cli |
call fileread |
;ebx=file size |
sti |
pop ecx |
shr ebx,9 |
cmp ecx,ebx |
jg .endloop1 ;if end of file? |
mov ebx,ecx |
test eax,eax |
jnz .endloop1 ;check io errors |
pop edx |
add ebx,8 ;go to next page |
add edx,4 |
jmp .loop1 |
.endloop1: |
add esp,8 ;pop linear address of page table entry and pointer to file name |
call .add_app_parameters |
mov [esp+28],eax |
popad |
ret |
.cleanfailed_mem: |
mov esi,start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: ;clean process name |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
mov eax,' ' |
cld |
rep stosb |
.failed: |
add esp,8 |
mov [application_table_status],0 |
popad |
sti |
mov eax,-1 |
ret |
.add_app_parameters: |
;input: |
; [esp] - pointer to parameters |
; [esp+4]-[esp+36] pushad registers. |
;result |
; eax - pid of new process |
; or zero if failed |
cli |
mov ebx,[new_process_place] |
cmp ebx,[0x3004] |
jle .noinc |
inc dword [0x3004] ;update number of processes |
.noinc: |
; mov ebx,[new_process_place] |
;set 0x8c field of extended information about process |
;(size of application memory) |
shl ebx,8 |
mov eax,[app_mem] |
mov [second_base_address+0x80000+0x8c+ebx],eax |
;set 0x10 field of information about process |
;(application base address) |
; mov ebx,[new_process_place] |
; shl ebx,5 |
shr ebx,3 |
mov dword [second_base_address+0x3000+ebx+0x10],std_application_base_address |
;add command line parameters |
.add_command_line: |
mov edx,[app_i_param] |
test edx,edx |
jz .no_command_line ;application don't need parameters |
mov eax,[esp+4] |
test eax,eax |
jz .no_command_line ;no parameters specified |
;calculate parameter length |
mov esi,eax |
xor ecx,ecx |
.command_line_len: |
cmp byte [esi],0 |
jz .command_line_len_end |
inc esi |
inc ecx |
cmp ecx,256 |
jl .command_line_len |
.command_line_len_end: |
;ecx - parameter length |
;edx - address of parameters in new process address space |
mov ebx,eax ;ebx - address of parameters in our address space |
mov eax,[new_process_place] |
call write_process_memory ;copy parameters to new process address space |
.no_command_line: |
mov ebx,[new_process_place] |
mov eax,ebx |
shl ebx,5 |
add ebx,0x3000 ;ebx - pointer to information about process |
mov [ebx+0xe],al ;set window number on screen = process slot |
mov [ebx],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 |
mov ecx,ebx |
add ecx,draw_data-0x3000 ;ecx - pointer to draw data |
;set draw data to full screen |
mov [ecx+0],dword 0 |
mov [ecx+4],dword 0 |
mov eax,[0xfe00] |
mov [ecx+8],eax |
mov eax,[0xfe04] |
mov [ecx+12],eax |
;set cr3 register in TSS of application |
mov ecx,[new_process_place] |
shl ecx,8 |
mov eax,[0x800B8+ecx] |
add eax,8+16 ;add flags |
mov [l.cr3],eax |
;write cr3 in TSS of System Call Handler |
mov ecx,[new_process_place] |
shl ecx,7 |
mov [0x298000+ecx+l.cr3-tss_sceleton],eax ;write directy to TSS |
mov eax,[app_start] |
mov [l.eip],eax ;set eip in TSS |
mov eax,[app_esp] |
mov [l.esp],eax ;set stack in TSS |
;gdt |
mov ebx,[new_process_place] |
shl ebx,3 |
mov ax,app_code ;ax - selector of code segment |
add ax,bx |
mov [l.cs],ax |
mov ax,app_data |
add ax,bx ;ax - selector of data segment |
mov [l.ss],ax |
mov [l.ds],ax |
mov [l.es],ax |
mov [l.fs],ax |
mov ax,graph_data ;ax - selector of graphic segment |
mov [l.gs],ax |
mov [l.io],word 128 |
mov [l.eflags],dword 0x11202 |
mov [l.ss0],os_data |
mov [l.esp0],0x55000 |
; mov [l.esp1],0x56000 |
; mov [l.esp2],0x57000 |
;copy tss to it place |
mov eax,tss_sceleton |
mov ebx,[new_process_place] |
imul ebx,tss_step |
add ebx,tss_data ;ebx - address of application TSS |
mov ecx,120 |
call memmove |
;Add IO access table - bit array of permitted ports |
or eax,-1 |
mov edi,[new_process_place] |
imul edi,tss_step |
add edi,tss_data+128 |
mov ecx,2048 |
cld |
rep stosd ;full access to 2048*8=16384 ports |
mov ecx,ebx ;ecx - address of application TSS |
mov edi,[new_process_place] |
shl edi,3 |
;set TSS descriptor |
mov [edi+gdts+tss0+0],word tss_step ;limit (size) |
mov [edi+gdts+tss0+2],cx ;part of offset |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+tss0+4],al ;part of offset |
mov [edi+gdts+tss0+7],ah ;part of offset |
mov [edi+gdts+tss0+5],word 01010000b*256+11101001b ;system flags |
;set code and data segments |
mov eax,[new_process_place] |
shl eax,3 |
;set base address of code segment |
mov word [eax+gdts+app_code-3+2],0 |
mov byte [eax+gdts+app_code-3+4],0 |
mov byte [eax+gdts+app_code-3+7],std_application_base_address shr 24 |
;set limit of code segment |
; mov ebx,[app_mem] |
; add ebx,4095 |
; shr ebx,12 |
mov ebx,(0x80000000-std_application_base_address) shr 12 |
mov [eax+gdts+app_code-3+0],bx |
mov [eax+gdts+app_code-3+5],word 11010000b*256+11111010b+256*((0x80000000-std_application_base_address) shr 28) |
;set base address of data segment |
mov word [eax+gdts+app_data-3+2],0 |
mov byte [eax+gdts+app_data-3+4],0 |
mov byte [eax+gdts+app_data-3+7],std_application_base_address shr 24 |
;set limit of data segment |
mov [eax+gdts+app_data-3+0],bx |
mov [eax+gdts+app_data-3+5],word 11010000b*256+11110010b+256*((0x80000000-std_application_base_address) shr 28) |
;flush keyboard and buttons queue |
mov [0xf400],byte 0 |
mov [0xf500],byte 0 |
mov edi,[new_process_place] |
shl edi,5 |
add edi,window_data |
mov ebx,[new_process_place] |
movzx esi,word [0xC000+ebx*2] |
lea esi,[0xC400+esi*2] |
call windowactivate ;gui initialization |
mov ebx,[new_process_place] |
shl ebx,5 |
mov [0x3000+ebx+0xa],byte 0 ;set process state - running |
mov esi,new_process_running |
call sys_msg_board_str ;output information about succefull startup |
; add esp,4 ;pop pointer to parameters |
; popad |
mov eax,[process_number] ;set result |
mov [application_table_status],0 ;unlock application_table_status mutex |
sti |
ret 4 |
;----------------------------------------------------------------------------- |
new_sys_threads: |
;eax=1 - create thread |
; ebx=thread start |
; ecx=thread stack value |
;result: |
; eax=pid |
pushad |
cmp eax,1 |
jnz .ret ;other subfunctions |
mov esi,new_process_loading |
call sys_msg_board_str |
;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 |
;find free process slot |
call find_new_process_place |
test eax,eax |
jz .failed |
;set parameters for thread |
xor eax,eax |
mov [app_i_param],eax |
mov [app_i_icon],eax |
mov [app_start],ebx |
mov [app_esp],ecx |
mov esi,[0x3000] |
shl esi,8 |
add esi,0x80000 |
mov ebx,esi ;ebx=esi - pointer to extended information about current thread |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov edx,edi ;edx=edi - pointer to extended infomation about new thread |
mov ecx,256/4 |
rep stosd ;clean extended information about new thread |
mov edi,edx |
mov ecx,11 |
rep movsb ;copy process name |
mov eax,[ebx+0x8c] |
mov [app_mem],eax ;set memory size |
mov eax,[ebx+0xb8] |
mov [edx+0xb8],eax ;copy page directory |
; mov eax,[new_process_place] |
; mov ebx,[0x3000] |
; call addreference_app_cr3_table |
push 0 ;no parameters |
call new_start_application_fl.add_app_parameters ;start thread |
mov [esp+28],eax |
popad |
ret |
.failed: |
sti |
popad |
mov eax,-1 |
ret |
.ret: |
popad |
ret |
;----------------------------------------------------------------------------- |
new_mem_resize: |
;input: |
; ebx - new size |
;result: |
; [esp+36]:=0 - normal |
; [esp+36]:=1 - error |
;This function set new application memory size. |
mov esi,ebx ;save new size |
add ebx,4095 |
and ebx,not (4096-1) ;round up size |
mov ecx,[0x3000] |
shl ecx,8 |
mov edx,[0x8008C+ecx] |
add edx,4095 |
and edx,not (4096-1) ;old size |
mov eax,[0x800B8+ecx] |
call MEM_Get_Linear_Address |
;eax - linear address of page directory |
call MEM_Heap_Lock ;guarantee that two threads willn't |
;change memory size simultaneously |
cmp ebx,edx |
; mov esi,ebx ;save new size |
jg .expand |
.free: |
sub edx,ebx |
jz .unlock ;do nothing |
mov ecx,edx |
shr ecx,12 |
add ebx,std_application_base_address |
call mem_free_specified_region ;free unnecessary pages |
jmp .unlock |
.expand: |
sub ebx,edx |
mov ecx,ebx |
shr ecx,12 |
mov ebx,edx |
add ebx,std_application_base_address |
call mem_alloc_specified_region ;alloc necessary pages |
test eax,eax |
jz .failed ;not enough memory |
.unlock: |
mov ebx,esi |
mov eax,[0x3000] |
shl eax,8 |
mov [eax+0x8008c],ebx ;write new memory size |
;search threads and update |
;application memory size infomation |
mov ecx,[eax+0x800b8] |
mov eax,2 |
.search_threads: |
;eax = current slot |
;ebx = new memory size |
;ecx = page directory |
cmp eax,[0x3004] |
jg .search_threads_end |
mov edx,eax |
shl edx,5 |
cmp word [0x3000+edx+0xa],9 ;if slot empty? |
jz .search_threads_next |
shl edx,3 |
cmp [edx+0x800b8],ecx ;if it is our thread? |
jnz .search_threads_next |
mov [edx+0x8008c],ebx ;update memory size |
.search_threads_next: |
inc eax |
jmp .search_threads |
.search_threads_end: |
call MEM_Heap_UnLock |
mov dword [esp+36],0 |
ret |
.failed: |
call MEM_Heap_UnLock |
mov dword [esp+36],1 |
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,[0x3004] |
shl ebx,5 |
mov ecx,2*32 |
.loop: |
;ecx=offset of current process info entry |
;ebx=maximum permitted offset |
cmp byte [second_base_address+0x3000+ecx+0xa],9 |
jz .endloop ;skip empty slots |
cmp [second_base_address+0x3000+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 |
;----------------------------------------------------------------------------- |
is_new_process: |
;Input: |
; eax - process slot |
;Output: |
; eax=1 - it is new process |
; eax=0 - it is old process |
; shl eax,5 |
; mov eax,[second_base_address+0x3000+eax+0x10] |
; cmp eax,std_application_base_address ;check base address of application |
; jz .new_process |
; xor eax,eax |
; ret |
;.new_process: |
mov eax,1 |
ret |
;----------------------------------------------------------------------------- |
write_process_memory: |
;Input: |
; eax - process slot |
; ebx - buffer address |
; ecx - buffer size |
; edx - start address in other process |
;Output: |
; eax - number of bytes written |
pushad |
shl eax,8 |
mov eax,[0x80000+eax+0xB8] |
call MEM_Get_Linear_Address |
mov ebp,eax |
;ebp=linear address of page directory of other process. |
add edx,std_application_base_address ;convert to linear address |
test ecx,ecx |
jle .ret |
.write_loop: |
;ebx = current buffer address |
;ecx>0 = current size |
;edx = current address in other process |
;ebp = linear address of page directory |
call MEM_Heap_Lock ;cli |
mov esi,edx |
shr esi,22 |
mov eax,[ebp+4*esi] ;find page directory entry |
and eax,not (4096-1) ;clear flags |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address ;calculate linear address of page table |
test eax,eax |
jz .page_not_found |
mov esi,edx |
shr esi,12 |
and esi,1023 |
mov eax,[eax+4*esi] ;find page table entry |
and eax,not (4096-1) |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address ;calculate linear address of page |
test eax,eax |
jz .page_not_found |
mov edi,eax |
call MEM_Add_Reference_Linear;guarantee that page willn't disappear |
call MEM_Heap_UnLock ;sti |
mov esi,edx |
and esi,4095 |
add edi,esi ;add offset in page |
;edi = linear address corresponding edx in other process |
sub esi,4096 |
neg esi ;esi - number of remaining bytes in page |
cmp esi,ecx |
jl .min_ecx |
mov esi,ecx |
.min_ecx: ;esi=min(ecx,esi) - number of bytes to write |
sub ecx,esi |
push ecx |
mov ecx,esi ;ecx - number of bytes to write |
mov esi,ebx ;esi - source, edi - destination |
add edx,ecx ;move pointer in address space of other process |
push edi |
;move ecx bytes |
test ecx,3 |
jnz .not_aligned |
shr ecx,2 |
rep movsd |
jmp .next_iter |
.not_aligned: |
rep movsb |
.next_iter: |
pop eax |
and eax,not (4096-1) ;eax - linear address of current page |
call MEM_Free_Page_Linear ;free reference |
mov ebx,esi ;new pointer to buffer - movsb automaticaly advance it. |
pop ecx ;restore number of remaining bytes |
test ecx,ecx |
jnz .write_loop |
.ret: |
popad |
mov eax,ecx |
ret |
.page_not_found: |
call MEM_Heap_UnLock ;error has appeared in critical region |
sub ecx,[esp+24] ;[esp+24]<-->ecx |
neg ecx ;ecx=number_of_written_bytes |
mov [esp+28],ecx ;[esp+28]<-->eax |
popad |
ret |
;----------------------------------------------------------------------------- |
syscall_test: |
;for testing memory manager from applications. |
mov edx,ecx |
mov ecx,ebx |
call trans_address |
mov ebx,eax |
mov eax,[0x3000] |
call read_process_memory |
ret |
;----------------------------------------------------------------------------- |
read_process_memory: |
;Input: |
; eax - process slot |
; ebx - buffer address |
; ecx - buffer size |
; edx - start address in other process |
;Output: |
; eax - number of bytes read. |
pushad |
shl eax,8 |
mov eax,[0x80000+eax+0xB8] |
call MEM_Get_Linear_Address |
mov ebp,eax |
add edx,std_application_base_address |
.read_loop: |
;ebx = current buffer address |
;ecx>0 = current size |
;edx = current address in other process |
;ebp = linear address of page directory |
call MEM_Heap_Lock ;cli |
mov esi,edx |
shr esi,22 |
mov eax,[ebp+4*esi] ;find page directory entry |
and eax,not (4096-1) |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address |
test eax,eax |
jz .page_not_found |
mov esi,edx |
shr esi,12 |
and esi,1023 |
mov eax,[eax+4*esi] ;find page table entry |
and eax,not (4096-1) |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address ;calculate linear address of page |
test eax,eax |
jz .page_not_found |
mov esi,eax |
call MEM_Add_Reference_Linear;guarantee that page willn't disappear |
call MEM_Heap_UnLock ;sti |
mov edi,edx |
and edi,4095 |
add esi,edi ;add offset in page |
;esi = linear address corresponding edx in other process |
sub edi,4096 |
neg edi |
;edi=min(edi,ecx) - number of bytes to copy |
cmp edi,ecx |
jl .min_ecx |
mov edi,ecx |
.min_ecx: |
sub ecx,edi ;update size of remaining bytes |
add edx,edi ;update current pointer in other address space. |
push ecx |
mov ecx,edi ;ecx - number of bytes to read |
mov edi,ebx ;esi - source, edi - destination |
push esi |
;move ecx bytes |
test ecx,3 |
jnz .not_aligned |
shr ecx,2 |
rep movsd |
jmp .next_iter |
.not_aligned: |
rep movsb |
.next_iter: |
pop eax |
and eax,not (4096-1) ;eax - linear address of current page |
call MEM_Free_Page_Linear ;free reference |
mov ebx,edi ;new pointer to buffer - movsb automaticaly advance it. |
pop ecx ;restore number of remaining bytes |
test ecx,ecx |
jnz .read_loop |
popad |
mov eax,ecx |
ret |
.page_not_found: |
call MEM_Heap_UnLock ;error has appeared in critical region |
sub ecx,[esp+24] ;[esp+24]<-->ecx |
neg ecx ;ecx=number_of_read_bytes |
mov [esp+28],ecx ;[esp+28]<-->eax |
popad |
ret |
;----------------------------------------------------------------------------- |
check_region: |
;input: |
; ebx - start of buffer |
; ecx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
mov eax,[0x3000] |
jmp check_process_region |
;----------------------------------------------------------------------------- |
check_process_region: |
;input: |
; eax - slot |
; ebx - start of buffer |
; ecx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
test ecx,ecx |
jle .ok |
shl eax,5 |
cmp word [0x3000+eax+0xa],0 |
jnz .failed |
shl eax,3 |
mov eax,[0x80000+eax+0xb8] |
test eax,eax |
jz .failed |
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 |
;----------------------------------------------------------------------------- |
new_sys_ipc: |
;input: |
; eax=1 - set ipc buffer area |
; ebx=address of buffer |
; ecx=size of buffer |
; eax=2 - send message |
; ebx=PID |
; ecx=address of message |
; edx=size of message |
cmp eax,1 |
jnz .no_ipc_def |
;set ipc buffer area |
mov edi,[0x3000] |
shl edi,8 |
add edi,0x80000 |
cli |
mov [edi+0xA0],ebx ;set fields in extended information area |
mov [edi+0xA4],ecx |
sti |
mov [esp+36],dword 0 ;success |
ret |
.no_ipc_def: |
cmp eax,2 |
jnz .no_ipc_send |
;send message |
cli |
;obtain slot from PID |
mov eax,ebx |
call pid_to_slot |
test eax,eax |
jz .no_pid |
mov ebp,eax |
;ebp = slot of other process |
shl eax,8 |
mov edi,[eax+0x80000+0xa0] ;is ipc area defined? |
test edi,edi |
jz .no_ipc_area |
mov esi,[eax+0x80000+0xa4] ;esi - size of buffer |
push dword -1 ;temp variable for read_process_memory |
mov ebx,esp |
push ecx |
push edx |
mov ecx,4 ;read 4 bytes |
mov eax,ebp |
mov edx,edi ;from beginning of buffer. |
call read_process_memory |
mov eax,[esp+8] |
test eax,eax |
jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now |
add edx,4 ;move to next 4 bytes |
mov eax,ebp |
call read_process_memory ;read size of occupied space in buffer |
sub esi,8 |
sub esi,[esp] |
sub esi,[esp+8] ;esi=(buffer size)-(occupied size)-(message size)-(header of message size) |
js .buffer_overflow ;esi<0 - not enough memory in buffer |
mov esi,[esp+8] ;previous offset |
add dword [esp+8],8 |
mov edi,[esp] |
add [esp+8],edi ;add (size of message)+(size of header of message) to [buffer+4] |
mov eax,ebp |
call write_process_memory |
add edx,esi |
sub edx,4 ;move to beginning of place for our message |
mov eax,[second_base_address+0x3010] |
mov eax,[eax+0x4] ;eax - our PID |
mov [esp+8],eax |
mov eax,ebp |
call write_process_memory ;write PID |
mov ebx,esp ;address of size of message |
mov eax,ebp |
add edx,4 |
call write_process_memory ;write size of message |
add edx,4 |
pop ecx ;ecx - size of message |
pop eax |
call trans_address |
mov ebx,eax ;ebx - linear address of message |
add esp,4 ;pop temporary variable |
mov eax,ebp |
call write_process_memory ;write message |
sti |
;awake other process |
shl ebp,8 |
mov eax,ebp |
or [eax+0x800A8],dword 0x40 |
cmp dword [check_idle_semaphore],20 |
jge .ipc_no_cis |
mov dword [check_idle_semaphore],5 |
.ipc_no_cis: |
mov dword [esp+36],0 |
ret |
.no_ipc_send: |
mov dword [esp+36],-1 |
ret |
.no_pid: |
sti |
mov dword [esp+36],4 |
ret |
.no_ipc_area: |
sti |
mov dword [esp+36],1 |
ret |
.ipc_blocked: |
sti |
add esp,12 |
mov dword [esp+36],2 |
ret |
.buffer_overflow: |
sti |
add esp,12 |
mov dword [esp+36],3 |
ret |
;----------------------------------------------------------------------------- |
trans_address: |
;Input |
; eax - application address |
;Output |
; eax - linear address for kernel |
add eax,std_application_base_address |
ret |
;----------------------------------------------------------------------------- |
new_start_application_hd: |
;eax - file name (kernel address) |
;ebx - file name length |
;ecx - work area (kernel address) |
;ebp - parameters |
pushad |
mov esi,new_process_loading |
call sys_msg_board_str ;write message to message board |
;lock application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
push ebp |
push ebx |
push eax |
push ecx |
call find_new_process_place ;find new process slot |
sti |
test eax,eax |
jz .failed |
;write application name |
mov eax,[esp+4] |
.find_last_byte: |
cmp byte [eax],0 |
jz .find_last_byte_end |
inc eax |
jmp .find_last_byte |
.find_last_byte_end: |
lea esi,[eax-11] ;last 11 bytes = application name |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
cld |
rep movsb ;copy name to extended information about process |
;read header |
mov eax,[esp+4] ;file name |
mov esi,[esp] ;work area |
mov ecx,1 ;read from first block |
mov edx,1 ;read 1 block |
call read_hd_file |
test eax,eax |
jnz .cleanfailed |
mov esi,[esp] |
;check menuet signature |
cmp [esi+1024+0],dword 'MENU' ;read_hd_file function write file to +1024 offset |
jnz .cleanfailed |
cmp [esi+1024+4],word 'ET' |
jnz .cleanfailed |
add esi,1024 |
mov edi,0x90000 |
mov ecx,512/4 |
cld |
rep movsd ;copy first block to 0x90000 address for get_app_params function |
call get_app_params |
test esi,esi |
jz .cleanfailed |
mov eax,[new_process_place] |
call create_app_cr3_table ;create page directory |
test eax,eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address |
mov ebx,std_application_base_address |
mov ecx,[app_mem] |
add ecx,4096-1 |
shr ecx,12 |
mov edx,eax ;edx - linear address of page directory |
call mem_alloc_specified_region ;allocate memory for application |
test eax,eax |
jz .cleanfailed_mem |
add edx,(std_application_base_address shr 20) |
mov eax,[edx] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
push edx ;save pointer to first page table |
mov edx,eax |
;read file |
mov ecx,1 |
xor ebp,ebp |
.loop1: |
;[esp] - pointer to current page directory entry |
;edx - pointer to current page table |
;ebp - offset in page |
;ecx - current cluster |
push edx |
mov eax,[esp+12] ;file name |
mov ebx,[esp+16] ;file name length |
mov esi,[esp+8] ;work area |
mov edx,1 ;number of blocks to read |
push ecx |
push ebp |
cli |
call read_hd_file |
sti |
pop ebp |
test eax,eax |
jnz .endloop1 ;check io errors |
mov esi,[esp+8+4] ;work area |
add esi,1024 |
mov eax,[esp+4] ;current page table |
mov eax,[eax] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address;calculate linear page address |
lea edi,[eax+ebp] ;add page offset |
mov ecx,512/4 |
cld |
rep movsd ;copy data |
pop ecx |
inc ecx ;next block |
mov eax,[app_i_end] ;todo: precalculate ([app_i_end]+4095)/4096 |
add eax,512-1 |
shr eax,9 ;calculate application image size |
cmp ecx,eax |
jg .endloop11 |
pop edx |
add ebp,512 ;new offset |
test ebp,4096 |
jz .loop1 |
xor ebp,ebp |
add edx,4 ;go to next page |
test edx,(4096-1) |
jnz .loop1 |
add dword [esp],4 ;go to next directory entry |
mov eax,[esp] |
mov eax,[eax] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov edx,eax |
jmp .loop1 |
.endloop1: |
add esp,4 ;pop ecx |
.endloop11: |
add esp,4+4 ;pop edx, pop edx |
;add_app_parameters |
add esp,12 ;now pointer to parameters is on the top of the stack |
call new_start_application_fl.add_app_parameters ;start process |
mov [esp+28],eax |
popad |
ret |
.cleanfailed_mem: |
mov esi,start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: ;clean process name |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
mov eax,' ' |
cld |
rep stosb |
.failed: |
add esp,16 |
popad |
mov eax,-1 |
mov [application_table_status],0 |
sti |
ret |
end if |
/kernel/trunk/core/physmem.inc |
---|
0,0 → 1,218 |
virtual at 0 |
physical_mem_block: |
.start rd 1 |
.size rd 1 |
.flags rd 1 ;0-free, pid-used. |
.sizeof: |
end virtual |
max_physical_mem_blocks = 24 |
uglobal |
num_physical_mem_blocks rd 1 |
physical_mem_blocks rd 3*max_physical_mem_blocks |
endg |
Init_Physical_Memory_Manager: |
pushad |
mov edi,physical_mem_blocks |
mov ecx,3*max_physical_mem_blocks |
xor eax,eax |
cld |
rep stosd |
mov dword [num_physical_mem_blocks],2 |
mov [physical_mem_blocks+physical_mem_block.start],0x60000 |
mov [physical_mem_blocks+physical_mem_block.size],0x20000 ;128Kb |
mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.start],0x780000 |
mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.size],0x80000 ;512Kb |
popad |
ret |
Insert_Block: |
;input: |
; eax - handle |
;output: |
; none |
push eax ecx esi edi |
sub eax,[num_physical_mem_blocks] |
neg eax |
mov edi,physical_mem_block.sizeof |
imul eax,edi |
shr eax,2 |
mov ecx,eax |
mov esi,[num_physical_mem_blocks] |
imul esi,edi |
add esi,physical_mem_blocks |
lea edi,[esi+physical_mem_block.sizeof] |
std |
rep movsd |
pop edi esi ecx eax |
ret |
Delete_Block: |
;input: |
; eax - handle |
;output: |
; none |
pushad |
mov edi,eax |
sub eax,[num_physical_mem_blocks] |
neg eax |
dec eax |
mov esi,physical_mem_block.sizeof |
imul eax,esi |
imul edi,esi |
add edi,physical_mem_blocks |
lea esi,[edi+physical_mem_block.sizeof] |
mov ecx,eax |
shr ecx,2 |
cld |
rep movsd |
popad |
ret |
Allocate_Physical_Block: |
;input: |
; eax - size |
;output: |
; eax - address or 0 if not enough memory. |
pushad |
cmp [num_physical_mem_blocks],max_physical_mem_blocks |
jge .error |
mov ebx,eax |
xor eax,eax |
mov esi,physical_mem_blocks |
.loop: |
cmp dword [esi+physical_mem_block.flags],0 |
jnz .next |
cmp [esi+physical_mem_block.size],ebx |
jg .addblock |
jz .noaddblock |
.next: |
inc eax |
add esi,physical_mem_block.sizeof |
cmp eax,[num_physical_mem_blocks] |
jl .loop |
.error: |
popad |
xor eax,eax |
ret |
.noaddblock: |
mov eax,[esi+physical_mem_block.start] |
mov [esp+28],eax |
mov eax,[0x3010] |
mov eax,[eax+0x4] |
mov [esi+physical_mem_block.flags],eax |
popad |
ret |
.addblock: |
call Insert_Block |
inc dword [num_physical_mem_blocks] |
mov eax,[esi+physical_mem_block.start] |
mov [esp+28],eax |
mov ecx,[0x3010] |
mov ecx,[ecx+0x4] |
mov [esi+physical_mem_block.flags],ecx |
mov ecx,[esi+physical_mem_block.size] |
mov [esi+physical_mem_block.size],ebx |
sub ecx,ebx |
mov [esi+physical_mem_block.sizeof+physical_mem_block.size],ecx |
add ebx,[esi+physical_mem_block.start] |
mov [esi+physical_mem_block.sizeof+physical_mem_block.start],ebx |
mov dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0 |
popad |
ret |
Free_Physical_Block: |
;input: |
; eax - address |
;output: |
; none |
pushad |
test eax,eax |
jz .ret |
mov ebx,eax |
xor eax,eax |
mov esi,physical_mem_blocks |
.loop: |
cmp ebx,[esi+physical_mem_block.start] |
jz .endloop |
inc eax |
add esi,physical_mem_block.sizeof |
cmp eax,[num_physical_mem_blocks] |
jl .loop |
jmp .ret |
.endloop: |
mov dword [esi+physical_mem_block.flags],0 |
test eax,eax |
jz .no_union_previous |
cmp dword [esi-physical_mem_block.sizeof+physical_mem_block.flags],0 |
jnz .no_union_previous |
mov ebx,[esi-physical_mem_block.sizeof+physical_mem_block.start] |
add ebx,[esi-physical_mem_block.sizeof+physical_mem_block.size] |
cmp ebx,[esi+physical_mem_block.start] |
jnz .no_union_previous |
mov ebx,[esi+physical_mem_block.size] |
add [esi-physical_mem_block.sizeof+physical_mem_block.size],ebx |
call Delete_Block |
dec eax |
dec [num_physical_mem_blocks] |
.no_union_previous: |
inc eax |
cmp eax,[num_physical_mem_blocks] |
jge .no_union_next |
cmp dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0 |
jnz .no_union_next |
mov ebx,[esi+physical_mem_block.start] |
add ebx,[esi+physical_mem_block.size] |
cmp ebx,[esi+physical_mem_block.sizeof+physical_mem_block.start] |
jnz .no_union_next |
mov ebx,[esi+physical_mem_block.sizeof+physical_mem_block.size] |
add [esi+physical_mem_block.size],ebx |
call Delete_Block |
dec [num_physical_mem_blocks] |
.no_union_next: |
.ret: |
popad |
ret |
sys_allocate_physical_block: |
;eax - subfunction number |
mov eax,ebx |
call Allocate_Physical_Block |
mov [esp+36],eax |
ret |
sys_free_physical_block: |
;eax - subfunction number |
mov eax,ebx |
call Free_Physical_Block |
ret |
sys_set_buffer: |
add ecx,std_application_base_address |
isys_set_buffer: ;for using in kernel |
;eax - subfunction number |
;ebx - physical address |
;ecx - buffer start |
;edx - buffer size |
lea edi,[ebx+second_base_address] |
mov esi,ecx |
mov ecx,edx |
rep movsb |
ret |
sys_get_buffer: |
add ecx,std_application_base_address |
isys_get_buffer: ;for using in kernel |
;eax - subfunction number |
;ebx - physical address |
;ecx - buffer start |
;edx - buffer size |
mov edi,ecx |
lea esi,[ebx+second_base_address] |
mov ecx,edx |
rep movsb |
ret |
sys_internal_services: |
cmp eax,4 |
jle sys_sheduler |
cmp eax,5 |
jz sys_allocate_physical_block |
cmp eax,6 |
jz sys_free_physical_block |
cmp eax,7 |
jz sys_set_buffer |
cmp eax,8 |
jz sys_get_buffer |
ret |
/kernel/trunk/core/sched.inc |
---|
0,0 → 1,286 |
label next_usage_update dword at 0xB008 |
label timer_ticks dword at 0xFDF0 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; IRQ0 HANDLER (TIMER INTERRUPT) ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
irq0: |
cmp [error_interrupt],-1 |
je no_error_in_previous_process |
mov edi,[error_interrupt] |
shl edi, 3 |
mov [edi+tss0i_l +5], word 01010000b *256 +11101001b |
mov edi,[error_interrupt] |
shl edi,7 |
add edi,0x290000 |
mov esi,[error_interrupt_entry] |
mov [edi+l.eip-tss_sceleton],esi |
mov [edi+l.eflags-tss_sceleton],dword 0x11002 |
mov [0xffff],byte 0 |
mov [error_interrupt],-1 |
no_error_in_previous_process: |
mov edi,[0x3000] |
shl edi, 3 |
; fields of TSS descriptor: |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
inc dword [timer_ticks] |
mov eax, [timer_ticks] |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
call playNote ; <<<--- INSERT THIS LINE !!!!!!!!!! |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
cmp eax,[next_usage_update] |
jb .nocounter |
add eax,100 |
mov [next_usage_update],eax |
call updatecputimes |
.nocounter: |
mov edi, [0x3010] |
mov ebx, [edi+0x18] ; time stamp counter add |
call _rdtsc |
sub eax, ebx |
add eax, [edi+0x14] ; counter sum |
mov [edi+0x14], eax |
mov ebx,[0x3000] |
cmp [0xffff], byte 1 ;1 |
je do_not_change_task ;je |
.waiting_for_termination: |
.waiting_for_reuse: |
.waiting_on_queue: |
add edi,0x20 |
inc ebx |
mov al, byte [edi+0xA] |
cmp al, 3 |
je .waiting_for_termination |
cmp al, 4 |
je .waiting_for_termination |
cmp al, 9 |
je .waiting_for_reuse |
cmp al, 16 |
je .waiting_on_queue |
cmp al, 17 |
je .waiting_on_queue |
cmp ebx,[0x3004] |
jbe nsched0 |
mov ebx,1 |
mov edi,0x3020 |
nsched0: |
mov [0x3000],ebx |
mov [0x3010],edi |
do_not_change_task: |
mov edx,[0x3000] |
lea edx,[tss0sys+8*edx] |
;mov [8*0x40+idts+8+0], word 0 |
mov [8*0x40+idts+8+2],dx |
;mov [8*0x40+idts+8+4],word 11100101b*256 |
;mov [8*0x40+idts+8+6], word 0 |
call _rdtsc |
mov [edi+0x18],eax |
cmp [0xffff],byte 0 |
je nodecffff |
dec byte [0xffff] |
nodecffff: |
shl ebx, 3 |
xor eax, eax |
add ebx, tss0 |
mov word [0xB004], bx ; selector ;mov [tss_s],bx |
mov dword [0xB000], eax ; offset |
mov al,0x20 ; send End Of Interrupt signal |
mov dx,0x20 |
out dx,al |
.switch: |
jmp pword [0xB000] |
inc [context_counter] ;noname & halyavin |
jmp irq0 |
iglobal |
context_counter dd 0 ;noname & halyavin |
endg |
align 4 |
change_task: |
mov [0xffff],byte 2 |
dec dword [timer_ticks] ; because irq0 will increase it |
int 0x20 ; irq0 handler |
ret |
align 4 |
updatecputimes: |
mov eax,[idleuse] |
mov [idleusesec],eax |
mov [idleuse],dword 0 |
mov ecx, [0x3004] |
mov edi, 0x3020 |
.newupdate: |
mov ebx,[edi+0x14] |
mov [edi+0x1c],ebx |
mov [edi+0x14],dword 0 |
add edi,0x20 |
dec ecx |
jnz .newupdate |
ret |
; |
; Wait queue is 16 bytes |
; dd return code +12 |
; dd pointer to process +8 |
; dd prev +4 |
; dd next +0 |
; |
; eax - pointer to pointer to the wait queue |
; return: |
; ecx - return code |
sleep_on_queue: |
sub esp,16 ; reserve space for wait node |
mov ecx,esp ; ecx=this_node, [eax]=queue |
pusha |
mov ebx,[0x3010] ; get pointer to the current process |
mov [ecx+8],ebx |
pushf |
cli ; adding element to the wait queue must be atomic |
mov edi,[eax] ; edi=queue |
and edi,edi ; check if queue is empty |
jz .is_empty |
; add element at the end of wait queue |
mov edx,[edi+4] ; get pointer to prev edx=queue->prev |
mov [ecx+4],edx ; this_node->prev=queue->prev |
mov [ecx+0],edi ; this_node->next=queue |
mov [edx+0],ecx ; this_node->prev->next=this_node |
mov [edi+4],ecx ; queue->prev=this_node |
jmp .added_ok |
.is_empty: |
; set this element as first in the queue |
mov [ecx+0],ecx ; this_node->next=this_node |
mov [ecx+4],ecx ; this_node->prev=this_node |
mov [eax],ecx ; [queue]=this_node |
.added_ok: |
popf ; we can safely restore interrupts |
mov [ebx+0xa],byte 17 ; set current task state as sleeping |
call change_task ; schedule new thread |
; someone has called wake_up_queue |
pushf ; disable interrupts |
cli |
mov edx,[ecx+0] ; edx=this_node->next |
mov esi,[ecx+4] ; esi=this_node->prev |
; check if we need to remove this node from head |
cmp [eax],ecx |
jne .no_head |
cmp [ecx+0],ecx ; check if queue is empty |
jne .not_empty |
mov [eax],dword 0 |
jmp .no_head |
.not_empty: |
mov [eax],edx |
; remove our node from the queue (this must be atomic) |
.no_head: |
mov [edx+4],esi ; this_node->next->prev=this_node->prev |
mov [esi+0],edx ; this_node->prev->next=this_node->next |
popf |
popa |
add esp,12 |
pop ecx |
ret |
; eax - pointer to the wait queue |
; ebx - wake up all (1=yes, 0=no) |
; ecx - return code |
; return: |
; ebx - number of processes woken |
wake_up_queue: |
and eax,eax |
jnz .nz |
ret |
.nz: |
push eax |
push ebx |
push ecx |
push edx |
push esi |
pushf |
cli |
xor ebx,ebx |
mov edx,eax |
.wake_loop: |
mov [edx+12],ecx |
mov esi,[edx+8] |
mov byte [esi+0xa],0 |
inc ebx |
mov edx,[edx+0] |
cmp edx,eax |
jne .wake_loop |
and ebx,ebx |
jz .wake_up_1 |
.return_it: |
popf |
pop esi |
pop edx |
pop ecx |
add esp,4 |
pop eax |
ret |
.wake_up_1: |
mov [eax+12],ecx |
mov ecx,[eax+8] |
mov byte [ecx+0xa],0 |
jmp .return_it |
/kernel/trunk/core/sync.inc |
---|
0,0 → 1,111 |
if ~defined sync_inc |
sync_inc_fix: |
sync_inc fix sync_inc_fix |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;Synhronization for MenuetOS. ;; |
;;Author: Halyavin Andrey, halyavin@land.ru ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;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 [0x3010+second_base_address] |
mov eax,[eax+0x4] |
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,[0x3010+second_base_address] |
mov eax,[eax+0x4] |
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,[0x3000+second_base_address] |
mov eax,[eax+0x4] |
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 |
/kernel/trunk/core/sys32.inc |
---|
0,0 → 1,2301 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; MenuetOS process management, protected ring3 ;; |
;; ;; |
;; Distributed under GPL. See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
; GDT TABLE |
gdts: |
dw gdte-$-1 |
dd gdts |
dw 0 |
int_code_l: |
os_code_l: |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10011010b |
db 0x00 |
int_data_l: |
os_data_l: |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10010010b |
db 0x00 |
graph_data_l: |
dw 0x3ff |
dw 0x0000 |
db 0x00 |
dw 11010000b *256 +11110010b |
db 0x00 |
tss0_l: |
times (max_processes+10) dd 0,0 |
tss0i_l: |
times 0x41 dq 0 ;(256+10) dd 0,0 |
app_code_l: |
times (max_processes+10) dd 0,0 |
app_data_l: |
times (max_processes+10) dd 0,0 |
tss0sys_l: |
times (max_processes+10) dd 0,0 |
gdte: |
; <IP 05.02.2005> |
idtreg: |
dw 8*0x41-1 |
dd idts+8 |
label idts at 0xB100-8 |
;idte = idts + 8 + 0x60 |
; </IP> ; old code below: |
;align 32 |
;idts: |
; dw idte-$-1 |
; dd idts+8 |
; dw 0 |
; times 0x62 dd 0,0 |
;idte: |
build_process_gdt_tss_pointer: |
mov ecx,tss_data |
mov edi,0 |
setgdtl2: |
mov [edi+gdts+ tss0 +0], word tss_step |
mov [edi+gdts+ tss0 +2], cx |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+ tss0 +4], al |
mov [edi+gdts+ tss0 +7], ah |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
add ecx,tss_step |
add edi,8 |
cmp edi,8*(max_processes+5) |
jbe setgdtl2 |
ret |
;build_process_gdt_gate_pointer: |
; mov edi,0 |
; mov dx,tss0 |
; setidtl1: |
; mov ecx,[esi] |
; mov [edi+gdts+ tss0t +0], word 0 |
; mov [edi+gdts+ tss0t +2], dx |
; mov [edi+gdts+ tss0t +4], word 11100101b*256 |
; mov [edi+gdts+ tss0t +6], word 0 |
; add dx,8 |
; add edi,8 |
; cmp edi,8*(max_processes+5) |
; jb setidtl1 |
; ret |
build_interrupt_table: |
mov [l.eflags],dword 0x11002 |
mov [l.ss0], int_data |
;mov [l.ss1], ring1_data |
;mov [l.ss2], ring2_data |
mov [l.esp0], 0x52000 |
mov [l.esp1], 0x53000 |
mov [l.esp2], 0x54000 |
mov eax,cr3 |
mov [l.cr3],eax |
mov [l.cs],int_code |
mov [l.ss],int_data |
mov [l.ds],int_data |
mov [l.es],int_data |
mov [l.fs],int_data |
mov [l.gs],int_data |
mov eax,sys_int |
mov [l.esp],0x720000 |
mov edi,0x290000 |
newint: |
push edi |
mov ebx,[eax] |
mov [l.eip],ebx |
mov esi,tss_sceleton |
mov ecx,120/4 |
cld |
rep movsd |
pop edi |
add edi,128 |
add [l.esp],1024 |
add eax,4 |
cmp eax,sys_int+4*0x40 ;0x60 |
jbe newint ;jb |
;; |
mov esi,boot_sched_3_2 |
call boot_log |
mov ecx,0x290000 |
mov edi,0 |
setgdtl2i: |
mov [edi+gdts+ tss0i +0], word 128 |
mov [edi+gdts+ tss0i +2], cx |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+ tss0i +4], al |
mov [edi+gdts+ tss0i +7], ah |
mov [edi+gdts+ tss0i +5], word 01010000b *256 +11101001b |
add ecx,128 |
add edi,8 |
cmp edi,8*0x40 ;0x60 |
jbe setgdtl2i |
;; |
mov esi,boot_sched_3_3 |
call boot_log |
mov edi,0 |
mov edx,tss0i |
setidtl2: |
mov [edi+idts+ 8 +0], word 0 |
mov [edi+idts+ 8 +2], dx |
mov [edi+idts+ 8 +4], word 10000101b*256 ; task gate DPL=0 |
; cmp edi,0x40*8 |
; jne no_sw_int |
; mov [edi+idts+ 8 +4], word 11100101b*256 ; task gate DPL=3 |
; no_sw_int: |
mov [edi+idts+ 8 +6], word 0 |
add edx,8 |
add edi,8 |
cmp edi,8*0x40 ;0x60 |
jbe setidtl2 ;jb |
; <Ivan Poddubny 06.02.2005> |
; THIS CODE WON'T WORK ;-( |
; because each process's 0-level stack points to the same area |
; and if task switch occurs and another process is being interrupted |
; a stack overflow happens |
; The only way to solve that problem is to disable interrupts |
; while 0x40-handler is working |
; Then we have to make all entries in the IDT INTERRUPT gates, not TASK |
; mov edi, idts+8 |
; mov esi, sys_int |
; mov ecx, 32 |
; @@: |
; mov eax, [esi] |
; mov [edi], ax ; lower part of offset |
; mov [edi+2], word os_code ; segment selector |
; shr eax, 16 |
; mov [edi+4], word 10001110b shl 8 ; interrupt descriptor |
; mov [edi+6], ax |
; add esi, 4 |
; add edi, 8 |
; dec ecx |
; jnz @b |
; </Ivan Poddubny> |
ret |
build_syscall_interrupt_table: |
mov [l.eflags],dword 0x11002 |
mov [l.ss0], int_data ;code |
;mov [l.ss1], ring1_data ;code |
;mov [l.ss2], ring2_data ;code |
mov [l.esp0], 0x52000 |
mov [l.esp1], 0x53000 |
mov [l.esp2], 0x54000 |
mov eax,cr3 |
mov [l.cr3],eax |
mov [l.cs],int_code |
mov [l.ss],int_data |
mov [l.ds],int_data |
mov [l.es],int_data |
mov [l.fs],int_data |
mov [l.gs],int_data |
mov [l.esp],sysint_stack_data |
mov edi,0x298000 |
newint2: |
push edi |
mov ebx,i40 |
mov [l.eip],ebx |
mov esi,tss_sceleton |
mov ecx,120/4 |
cld |
rep movsd |
pop edi |
add [l.esp],4096 |
add edi,128 |
;add eax,4 |
cmp edi,0x298000+128*(max_processes+5) |
jb newint2 |
;; |
mov ecx,0x298000 |
mov edi,0 |
setgdtl2i2: |
mov [edi+gdts+ tss0sys +0], word 128 |
mov [edi+gdts+ tss0sys +2], cx |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+ tss0sys +4], al |
mov [edi+gdts+ tss0sys +7], ah |
mov [edi+gdts+ tss0sys +5], word 01010000b *256 +11101001b |
add ecx,128 |
add edi,8 |
cmp edi,8*(max_processes+5) |
jbe setgdtl2i2 |
;; |
;mov dx,tss0sys |
mov edi,8*0x40+idts+8 |
mov [edi + 0], word 0 |
mov [edi + 2], word tss0sys ;dx |
mov [edi + 4], word 11100101b*256 |
mov [edi + 6], word 0 |
mov edi,8*0x38+idts+8 |
mov eax, i38 |
mov [edi], ax ; lower part of offset |
mov [edi+2], word os_code ; segment selector |
shr eax, 16 |
mov [edi+4], word 11101110b shl 8 ; 32-bit interrupt gate, DPL 3 |
mov [edi+6], ax |
ret |
align 4 |
i38: |
; load data selectors |
pushfd |
push ds es |
push eax |
mov ax, os_data |
mov ds, ax |
mov es, ax |
pop eax |
pushad |
push edi |
mov edi, eax |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov esi, [esp] |
and edi, 0xFF |
call dword [servetable+edi*4] |
add esp, 4 |
popad |
pop es ds |
popfd |
iret |
iglobal |
sys_int: |
dd s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,sa,sb,sc,sd,se,sf |
dd s10 ,s11 ; ,i_unknown12,i_unknown13 |
; dd i_unknown14,i_unknown15,i_unknown16,i_unknown17 |
; dd i_unknown18,i_unknown19,i_unknown1a,i_unknown1b |
; dd i_unknown1c,i_unknown1d,i_unknown1e,i_unknown1f |
times 14 dd unknown_interrupt |
dd irq0 ,irq1 ,p_irq2 ,p_irq3 ,p_irq4 ,p_irq5,p_irq6 ,p_irq7 |
dd p_irq8,p_irq9,p_irq10,p_irq11,p_irq12,irqD ,p_irq14,p_irq15 |
;dd i_unknown30,i_unknown31,i_unknown32,i_unknown33 |
;dd i_unknown34,i_unknown35,i_unknown36,i_unknown37 |
;dd i_unknown38,i_unknown39,i_unknown3a,i_unknown3b |
;dd i_unknown3c,i_unknown3d,i_unknown3e,i_unknown3f |
times 16 dd unknown_interrupt |
dd i40 |
endg |
uglobal |
tss_sceleton: |
l.back dw 0,0 |
l.esp0 dd 0 |
l.ss0 dw 0,0 |
l.esp1 dd 0 |
l.ss1 dw 0,0 |
l.esp2 dd 0 |
l.ss2 dw 0,0 |
l.cr3 dd 0 |
l.eip dd 0 |
l.eflags dd 0 |
l.eax dd 0 |
l.ecx dd 0 |
l.edx dd 0 |
l.ebx dd 0 |
l.esp dd 0 |
l.ebp dd 0 |
l.esi dd 0 |
l.edi dd 0 |
l.es dw 0,0 |
l.cs dw 0,0 |
l.ss dw 0,0 |
l.ds dw 0,0 |
l.fs dw 0,0 |
l.gs dw 0,0 |
l.ldt dw 0,0 |
l.trap dw 0 |
l.io dw 0 |
endg |
s0: |
cli |
mov [error_interrupt],0x0 |
mov [error_interrupt_entry],dword s0 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s1: |
cli |
mov [error_interrupt],0x1 |
mov [error_interrupt_entry],dword s1 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s2: |
cli |
mov [error_interrupt],0x2 |
mov [error_interrupt_entry],dword s2 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s3: |
cli |
mov [error_interrupt],0x3 |
mov [error_interrupt_entry],dword s3 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s4: |
cli |
mov [error_interrupt],0x4 |
mov [error_interrupt_entry],dword s4 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s5: |
cli |
mov [error_interrupt],0x5 |
mov [error_interrupt_entry],dword s5 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s6: |
cli |
mov [error_interrupt],0x6 |
mov [error_interrupt_entry],dword s6 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
;;;;;;;;;;;;;;;;;;;;;;; |
;; FPU ERROR HANDLER ;; |
;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
s7: |
; <IP 05.02.2004> |
cli |
; </IP> |
mov edi, 7*8 |
mov [edi+gdts+ tss0i +5], word 01010000b *256 +11101001b |
mov edi,[0x3000] |
shl edi, 3 |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
; save a copy of current task's TSS to fpu_tss |
mov esi,[0x3000] |
imul esi,tss_step |
add esi,tss_data |
mov edi,fpu_tss |
mov ecx,120/4 |
cld |
rep movsd |
; get base address of our TSS and... |
mov esi,[0x3000] |
imul esi,tss_step |
add esi,tss_data |
; ...init segments, stack, eip, flags |
mov word [esi+l.cs-tss_sceleton],int_code |
mov word [esi+l.ss-tss_sceleton],int_data |
mov word [esi+l.ds-tss_sceleton],int_data |
mov word [esi+l.es-tss_sceleton],int_data |
mov word [esi+l.fs-tss_sceleton],int_data |
mov word [esi+l.gs-tss_sceleton],int_data |
mov dword [esi+l.esp-tss_sceleton],fpu_stack+4*8 |
mov dword [esi+l.eip-tss_sceleton],fpu_handler |
mov dword [esi+l.eflags-tss_sceleton],0x11002 |
; then execute this task |
mov ebx, [0x3000] |
shl ebx,3 |
add ebx, tss0 ;t |
mov [0xB004], bx |
jmp pword [0xB000] |
jmp s7 |
s8: |
cli |
mov [error_interrupt],0x8 |
mov [error_interrupt_entry],dword s8 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s9: |
cli |
mov [error_interrupt],0x9 |
mov [error_interrupt_entry],dword s9 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sa: |
cli |
mov [error_interrupt],0xa |
mov [error_interrupt_entry],dword sa |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sb: |
cli |
mov [error_interrupt],0xb |
mov [error_interrupt_entry],dword sb |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sc: |
cli |
mov [error_interrupt],0xc |
mov [error_interrupt_entry],dword sc |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sd: |
cli |
mov [error_interrupt],0xd |
mov [error_interrupt_entry],dword sd |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
se: |
cli |
mov [error_interrupt],0xe |
mov [error_interrupt_entry],dword se |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sf: |
cli |
mov [error_interrupt],0xf |
mov [error_interrupt_entry],dword sf |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s10: |
cli |
mov [error_interrupt],0x10 |
mov [error_interrupt_entry],dword s10 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s11: |
cli |
mov [error_interrupt],0x11 |
mov [error_interrupt_entry],dword s11 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
writehex: |
pusha |
mov ecx,eax |
mov ax,word [printerrorat] |
shl eax,16 |
mov ax,[esp+32+4] |
sub ax,60 |
mov edx,1 |
mov esi,8 |
mov ebx,0xffffff |
whl1: |
push ecx |
and ecx,0xf |
add ecx,hexletters |
mov edi,1 |
mov cl,[ecx] |
mov edi,[write_error_to] |
mov [edi],cl |
dec [write_error_to] |
pop ecx |
shr ecx,4 |
sub eax,6*65536 |
dec esi |
jnz whl1 |
popa |
ret |
iglobal |
hexletters db '0123456789ABCDEF' |
error_interrupt dd -1 |
error_interrupt_entry dd -1 |
printerrorat dd 300 |
process_error db 'K : Process - forced terminate INT: 00000000',13,10,0 |
process_pid db 'K : Process - forced terminate PID: 00000000',13,10,0 |
process_eip db 'K : Process - forced terminate EIP: 00000000',13,10,0 |
system_error db 'K : Kernel error',13,10,0 |
endg |
uglobal |
write_error_to dd 0x0 |
endg |
show_error_parameters: |
mov [write_error_to],process_pid+43 |
mov eax,[0x3000] |
shl eax, 5 |
mov eax,[0x3000+4+eax] |
call writehex |
mov [write_error_to],process_error+43 |
mov eax,[error_interrupt] |
call writehex |
mov eax,[0x3000] |
shl eax,8 |
cmp [0x80000+eax+0xB0],dword 0 |
jnz .system_error |
mov eax,[0x3000] |
imul eax,tss_step |
mov eax,[eax+tss_data+l.eip-tss_sceleton] |
.out_eip: |
mov [write_error_to],process_eip+43 |
call writehex |
mov esi,process_error |
call sys_msg_board_str |
mov esi,process_pid |
call sys_msg_board_str |
mov esi,process_eip |
call sys_msg_board_str |
ret |
.system_error: |
mov esi,system_error |
call sys_msg_board_str |
mov eax,[0x3000] |
shl eax,7 |
mov eax,[eax+0x298000+l.eip-tss_sceleton] |
jmp .out_eip |
irq5: |
call restore_caller |
mov dx,word [sb16] |
add dx,0xe |
in al,dx |
; mov byte [SB16_Status],0 |
mov [check_idle_semaphore],5 |
mov al,0x20 |
out 0x20,al |
call return_to_caller |
jmp irq5 |
irqD: |
call restore_caller |
mov dx,0xf0 |
mov al,0 |
out dx,al |
mov dx,0xa0 |
mov al,0x20 |
out dx,al |
mov dx,0x20 |
out dx,al |
mov ds,cx |
mov es,cx |
mov fs,cx |
call return_to_caller |
jmp irqD |
p_irq2: |
call restore_caller |
mov edi,2 ; 1 |
call irqhandler ; 2/5 |
call return_to_caller |
jmp p_irq2 |
p_irq3: |
call restore_caller |
mov edi,3 |
call irqhandler |
call return_to_caller |
jmp p_irq3 |
p_irq4: |
call restore_caller |
mov edi,4 |
call irqhandler |
call return_to_caller |
jmp p_irq4 |
p_irq5: |
call restore_caller |
mov edi,5 |
call irqhandler |
call return_to_caller |
jmp p_irq5 |
p_irq6: |
call restore_caller |
call fdc_irq |
mov edi,6 |
call irqhandler |
call return_to_caller |
jmp p_irq6 |
p_irq7: |
call restore_caller |
mov edi,7 |
call irqhandler |
call return_to_caller |
jmp p_irq7 |
p_irq8: |
call restore_caller |
mov edi,8 |
call irqhandler |
call return_to_caller |
jmp p_irq8 |
p_irq9: |
call restore_caller |
mov edi,9 |
call irqhandler |
call return_to_caller |
jmp p_irq9 |
p_irq10: |
call restore_caller |
mov edi,10 |
call irqhandler |
call return_to_caller |
jmp p_irq10 |
p_irq11: |
call restore_caller |
mov edi,11 |
call irqhandler |
call return_to_caller |
jmp p_irq11 |
p_irq12: |
call restore_caller |
mov edi,12 |
call irqhandler |
call return_to_caller |
jmp p_irq12 |
p_irq13: |
call restore_caller |
mov edi,13 |
call irqhandler |
call return_to_caller |
jmp p_irq13 |
p_irq14: |
call restore_caller |
mov edi,14 |
call irqhandler |
call return_to_caller |
jmp p_irq14 |
p_irq15: |
call restore_caller |
mov edi,15 |
call irqhandler |
call return_to_caller |
jmp p_irq15 |
align 4 |
restore_caller: |
mov edi,[0x3000] |
shl edi, 3 |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
ret |
align 4 |
return_to_caller: |
mov ebx,[0x3000] |
shl bx,3 |
add bx,tss0;t |
mov [tss_irq12],bx |
db 0xea |
dd 0 |
tss_irq12 dw tss0;t |
ret |
uglobal |
irqh dd 0x0 |
endg |
irqhandler: |
push edi |
mov esi,edi ; 1 |
shl esi,6 ; 1 |
add esi,irq00read ; 1 |
shl edi,12 ; 1 |
add edi,0x2E0000 |
mov [check_idle_semaphore],5 |
irqnewread: |
mov dx,[esi] ; 2+ |
cmp dx,0 ; 1 |
jz irqover |
cmp [esi+3],byte 1 ; 2 ; byte read |
jne noirqbyte ; 4-11 |
in al,dx |
mov edx,[edi] |
cmp edx,4000 |
je irqfull |
mov ebx,edi |
add ebx,0x10 |
add ebx,edx |
mov [ebx],al |
inc edx |
mov [edi],edx |
add esi,4 |
jmp irqnewread |
noirqbyte: |
cmp [esi+3],byte 2 ; word read |
jne noirqword |
in ax,dx |
mov edx,[edi] |
cmp edx,4000 |
je irqfull |
mov ebx,edi |
add ebx,0x10 |
add ebx,edx |
mov [ebx],ax |
add edx,2 |
mov [edi],edx |
add esi,4 |
jmp irqnewread |
noirqword: |
irqfull: |
irqover: |
mov al,0x20 ; ready for next irq |
out 0x20,al |
pop ebx |
cmp ebx,7 |
jbe noa0 |
out 0xa0,al |
noa0: |
ret |
; this code should never get control! |
; applications can use only 0x40 interrupt |
unknown_interrupt: |
@@: call change_task |
jmp @b |
compare_to_thread: |
push ebx |
mov eax,edx |
shl eax, 3 |
add eax,gdts+ app_code-3 |
mov ebx,[eax] |
cmp ebx,[old_code_0] |
jne ctt0 |
mov ebx,[eax+4] |
cmp ebx,[old_code_1] |
jne ctt0 |
pop ebx |
mov eax,1 |
ret |
ctt0: |
pop ebx |
mov eax,0 |
ret |
check_for_thread_mem: |
pusha |
mov ecx,[0x3004] |
cftm0: |
mov eax,ecx |
shl eax, 8 |
add eax,gdts+ app_code-3 |
mov ebx,[eax] |
cmp ebx,[old_code_0] |
jne cftm1 |
mov ebx,[eax+4] |
cmp ebx,[old_code_1] |
jne cftm1 |
mov eax,ecx ; new code segments |
shl eax, 3 ;imul eax,8 |
add eax,gdts+ app_code-3 |
mov ebx,[new_code_0] |
mov [eax],ebx |
mov ebx,[new_code_1] |
mov [eax+4],ebx |
mov eax,ecx ; new data segments |
shl eax, 3 |
add eax,gdts+ app_data-3 |
mov ebx,[new_data_0] |
mov [eax],ebx |
mov ebx,[new_data_1] |
mov [eax+4],ebx |
cmp [new_pos],0 ; new memory position segments |
je no_new_postition_for_thread |
mov eax,ecx |
shl eax, 5 |
add eax,0x3000 |
mov ebx,[new_pos] |
mov [eax+0x10],ebx |
no_new_postition_for_thread: |
mov eax,ecx ; new amount of memory |
shl eax, 8 |
add eax,0x80000 |
mov ebx,[new_amount] |
mov [eax+0x8C],ebx |
cftm1: |
dec ecx |
jnz cftm0 |
popa |
ret |
save_for_thread_check: |
; save for thread check |
pusha |
mov esi,[0x3000] |
;imul esi,8 |
shl esi, 3 |
add esi,gdts+ app_code-3 +0 |
mov edi,old_code_0 |
mov ecx,8 |
cld |
rep movsb |
popa |
ret |
save_new_position_for_threads: |
; new code segment for thread check |
pusha |
mov esi,[0x3000] |
;imul esi,8 |
shl esi, 3 |
add esi,gdts+ app_code-3 +0 |
mov edi,new_code_0 |
mov ecx,8 |
cld |
rep movsb |
popa |
; new data segment for thread check |
pusha |
mov esi,[0x3000] |
;imul esi,8 |
shl esi, 3 |
add esi,gdts+ app_data-3 +0 |
mov edi,new_data_0 |
mov ecx,8 |
cld |
rep movsb |
popa |
ret |
set_application_table_status: |
push eax |
mov eax,[0x3000] |
;imul eax,32 |
shl eax, 5 |
add eax,0x3000+4 |
mov eax,[eax] |
mov [application_table_status],eax |
pop eax |
ret |
clear_application_table_status: |
push eax |
mov eax,[0x3000] |
;imul eax,32 |
shl eax, 5 |
add eax,0x3000+4 |
mov eax,[eax] |
cmp eax,[application_table_status] |
jne apptsl1 |
mov [application_table_status],0 |
apptsl1: |
pop eax |
ret |
uglobal |
old_code_0 dd 0x0 |
old_code_1 dd 0x0 |
; |
new_code_0 dd 0x0 |
new_code_1 dd 0x0 |
new_data_0 dd 0x0 |
new_data_1 dd 0x0 |
new_pos dd 0x0 |
new_amount dd 0x0 |
endg |
sys_resize_app_memory: |
; eax = 1 - resize |
; ebx = new amount of memory |
cmp eax,1 |
jne no_application_mem_resize |
mov eax,[0x3010] |
cmp dword [eax+0x10],std_application_base_address |
jz new_mem_resize ;resize for new type of processes |
add ebx,4095 |
shr ebx,12 |
shl ebx,12 |
mov ebp,ebx |
; wait for process table to be free |
rsm0: |
cli |
cmp [application_table_status],0 |
je rsm1 |
sti |
call change_task |
jmp rsm0 |
rsm1: |
call set_application_table_status |
sti |
cmp ebx,0 ; other than zero |
je mem_resize_unsuccess |
call save_for_thread_check |
; find a free place |
mov esi,[0xfe84] ; application memory start |
mov edi,ebp |
add edi,esi |
dec edi |
rfgdt: |
mov edx,2 |
rfindgdtl1: |
call compare_to_thread |
cmp eax,1 |
je rfindfl3 |
mov ecx,edx |
shl ecx,3 |
; eax run base -> ebx limit |
mov al,[ecx+gdts+ app_code-3 +4] |
mov ah,[ecx+gdts+ app_code-3 +7] |
shl eax,16 |
mov ax,[ecx+gdts+ app_code-3 +2] |
;!!mem |
cmp eax,std_application_base_address |
jz rfindfl3 |
;!!mem |
movzx ebx,word [ecx+gdts+ app_code-3 +0] |
shl ebx,12 |
add ebx,eax |
cmp eax,edi |
jg rfindfl3 |
cmp ebx,esi |
jb rfindfl3 |
add esi,4096 |
add edi,4096 |
cmp edi,[0xfe8c] ; < c_memory |
jbe rfgdt |
jmp rfind_free_ret_2 ;; not enough memory |
rfindfl3: |
inc edx |
cmp edx,[0x3004] |
jbe rfindgdtl1 |
rfindfl1: |
rthread_c: |
mov ecx,[0x3000] |
shl ecx,3 |
inc edi |
sub edi,esi |
add edi,4095 |
shr edi,12 |
dec edi |
; code |
mov eax,esi |
mov ebx,edi |
mov [ecx+gdts+ app_code-3 +2], ax ; base 0:15 |
shr eax,16 |
mov [ecx+gdts+ app_code-3 +4], al ; base 23:16 |
mov [ecx+gdts+ app_code-3 +7], ah ; base 31:24 |
mov [ecx+gdts+ app_code-3 +0], bx ; limit |
; data |
mov eax,esi |
mov [ecx+gdts+ app_data-3 +2], ax ; base 0:15 |
shr eax,16 |
mov [ecx+gdts+ app_data-3 +4], al ; base 23:16 |
mov [ecx+gdts+ app_data-3 +7], ah ; base 31:24 |
movzx edx,word [ecx+gdts+ app_code-3 +0] ; save limit |
mov [ecx+gdts+ app_data-3 +0], bx ; limit |
and ebx,0xffff |
cmp ebx,edx ; copy smaller from memory sizes |
jge noedxebxxchg |
mov edx,ebx |
noedxebxxchg: |
movzx ecx,dx |
shl ecx,12 |
add ecx,4096 |
mov edi,esi |
mov eax,[0x3010] |
mov esi,[eax+0x10] |
mov [eax+0x10],edi ; new memory position |
mov eax,[0x3000] ; new memory size |
shl eax,8 |
add eax,0x80000 |
mov [eax+0x8c],ebp |
mov [new_pos],edi ; new position for threads |
mov [new_amount],ebp ; new amount of mem for threads |
cmp esi,edi |
je no_app_move |
cld |
rep movsb ; move the app image to the new position |
no_app_move: |
call save_new_position_for_threads |
call check_for_thread_mem |
mov [application_table_status],0 |
mov [esp+36],dword 0 ; eax <- 0 ; successfull |
ret |
rfind_free_ret_2: |
mem_resize_unsuccess: |
mov [application_table_status],0 |
mov [esp+36],dword 1 ; eax <- 1 ; unsuccessfull |
ret |
no_application_mem_resize: |
ret |
align 4 |
find_free_mem: |
push eax |
push ebx |
push ecx |
push edx |
push edi |
call find_free_process_slot |
mov eax,[new_process_place] |
cmp eax,max_processes |
jg find_free_ret_2 |
cmp [thread_create],1 |
je thread_c |
mov esi,[0xfe84] |
add edi,esi |
dec edi |
mov eax,2 |
cmp dword [0x3004],1 |
je findf4 |
fgdt: |
mov edx,2 |
findgdtl1: |
mov ecx,edx |
shl ecx,3 |
; eax run base -> ebx limit |
mov al,[ecx+gdts+ app_code-3 +4] |
mov ah,[ecx+gdts+ app_code-3 +7] |
shl eax,16 |
mov ax,[ecx+gdts+ app_code-3 +2] |
;!!mem |
cmp eax,std_application_base_address |
jz findfl3 |
;!!mem |
movzx ebx,word [ecx+gdts+ app_code-3 +0] |
shl ebx,12 |
add ebx,eax |
cmp eax,edi |
jg findfl3 |
cmp ebx,esi |
jb findfl3 |
add esi,4096 |
add edi,4096 |
cmp edi,[0xfe8c] ; < c_memory |
jbe fgdt |
jmp find_free_ret_2 |
findfl3: |
inc edx |
cmp edx,[check_processes] |
jbe findgdtl1 |
findfl1: |
thread_c: |
mov eax,[new_process_place] |
findf4: |
mov [first_gdt_search],eax |
mov [gdt_place],eax |
mov ecx,eax |
shl ecx,3 |
inc edi |
sub edi,esi |
add edi,4095 |
shr edi,12 |
dec edi |
; code |
mov eax,esi |
mov ebx,edi |
mov [ecx+gdts+ app_code-3 +2], ax ; base 0:15 |
shr eax,16 |
mov [ecx+gdts+ app_code-3 +4], al ; base 23:16 |
mov [ecx+gdts+ app_code-3 +7], ah ; base 31:24 |
mov [ecx+gdts+ app_code-3 +0], bx ; limit |
mov [ecx+gdts+ app_code-3 +5], word 11010000b *256 +11111010b |
; data |
mov eax,esi |
mov [ecx+gdts+ app_data-3 +2], ax ; base 0:15 |
shr eax,16 |
mov [ecx+gdts+ app_data-3 +4], al ; base 23:16 |
mov [ecx+gdts+ app_data-3 +7], ah ; base 31:24 |
mov [ecx+gdts+ app_data-3 +0], bx ; limit |
mov [ecx+gdts+ app_data-3 +5], word 11010000b *256 +11110010b |
push esi |
mov esi,process_loading |
call sys_msg_board_str |
pop esi |
find_free_ret: |
pop edi |
pop edx |
pop ecx |
pop ebx |
pop eax |
ret |
find_free_ret_2: |
cmp [dec3004],0 |
je no3004inc |
dec dword [0x3004] |
no3004inc: |
pop edi |
pop edx |
pop ecx |
pop ebx |
pop eax |
mov esi,0 |
ret |
get_app_params: |
push eax |
cmp [0x90000+6],word '00' |
jne no_00_header |
mov eax,[0x90000+12] |
mov [app_start],eax |
mov eax,[0x90000+16] |
mov [app_i_end],eax |
mov eax,[0x90000+20] |
mov [app_mem],eax |
shr eax,1 |
sub eax,0x10 |
mov [app_esp],eax |
mov eax,[0x90000+24] |
mov [app_i_param],eax |
mov [app_i_icon],dword 0 |
pop eax |
mov esi,1 |
ret |
no_00_header: |
cmp [0x90000+6],word '01' |
jne no_01_header |
mov eax,[0x90000+12] |
mov [app_start],eax |
mov eax,[0x90000+16] |
mov [app_i_end],eax |
mov eax,[0x90000+20] |
mov [app_mem],eax |
mov eax,[0x90000+24] |
mov [app_esp],eax |
mov eax,[0x90000+28] |
mov [app_i_param],eax |
mov eax,[0x90000+32] |
mov [app_i_icon],eax |
pop eax |
mov esi,1 |
ret |
no_01_header: |
pop eax |
mov esi,0 |
ret |
start_application_fl: |
jmp new_start_application_fl |
;************************************************************************ |
start_application_floppy: |
jmp new_start_application_floppy |
;******************************************************************** |
start_application_hd: |
jmp new_start_application_hd |
uglobal |
threadstring dd 0x0 |
new_process_place dd 0x0 |
check_processes dd 0x0 |
dec3004 db 0x0 |
app_start dd 0x0 |
app_i_end dd 0x0 |
app_mem dd 0x0 |
app_esp dd 0x0 |
app_i_param dd 0x0 |
app_i_icon dd 0x0 |
app_mem_pos dd 0x0 |
thread_create dd 0x0 |
gdt_place dd 0x0 |
endg |
iglobal |
hd_app_string db 'HDAPP ' |
process_loading db 'K : Process - loading ',13,10,0 |
process_running db 'K : Process - done',13,10,0 |
first_gdt_search dd 0x2 |
endg |
sys_threads: |
; eax=1 create thread |
; |
; ebx=thread start |
; ecx=thread stack value |
; |
; on return : eax = pid |
jmp new_sys_threads |
cli |
cmp [application_table_status],0 |
je stth9 |
sti |
call change_task |
jmp sys_threads |
stth9: |
call set_application_table_status |
sti |
cmp eax,1 |
jne no_sys_thread_create |
cli |
mov eax,[0x3010] |
mov eax,[eax+0x10] |
mov [app_mem_pos],eax |
mov [app_i_param],0 |
mov [app_i_icon],0 |
mov [app_start],ebx |
mov [app_esp],ecx |
mov ebx,[0x3000] |
shl ebx,8 |
add ebx,0x80000 |
mov [threadstring],ebx |
mov ebx,[ebx+0x8c] |
mov [app_mem],ebx |
mov esi,[app_mem_pos] |
mov edi,[app_mem] |
add edi,esi |
dec edi |
mov [thread_create],1 |
call find_free_mem |
cmp esi,0 |
jne th_cr1 |
mov [application_table_status],0 |
mov eax,1 ; no free memory |
sti |
ret |
th_cr1: |
push dword 0 |
push dword [threadstring] |
jmp add_app_parameters |
no_sys_thread_create: |
mov eax,-1 |
mov [application_table_status],0 |
ret |
find_free_process_slot: |
pusha |
mov ebx,[0x3004] |
mov [check_processes],ebx |
inc ebx |
mov [new_process_place],ebx |
mov ebx,2 |
newfps: |
mov eax,ebx |
;imul eax,0x20 |
shl eax, 5 |
add eax,0x3000+0xa |
cmp [eax],byte 9 |
je ffpl |
inc ebx |
cmp ebx,[0x3004] |
jbe newfps |
;mov [dec3004],0 |
mov [dec3004],1 |
shl ebx,5 |
mov [0x3000+0xa+ebx],byte 9 |
inc dword [0x3004] |
popa |
ret |
ffpl: |
;mov [dec3004],1 |
;dec dword [0x3004] |
mov [dec3004],0 |
mov [new_process_place],ebx |
popa |
ret |
add_app_parameters: |
; returns: eax = pid or -1 if unsuccesfull |
cmp [app_i_param],dword 0 ; parameter |
jz no_app_params |
xor eax, eax |
mov edi,[app_i_param] |
add edi,[app_mem_pos] |
mov ecx,256/4 |
cld |
rep stosd |
mov esi,[esp+4] |
test esi, esi |
jz no_app_params |
mov eax,[app_i_param] |
add eax,[app_mem_pos] |
mov edi,eax |
mov ecx,256 |
cld |
app_new_param: |
cmp [esi],byte 0 |
jz no_app_params |
movsb |
loop app_new_param |
no_app_params: |
;inc dword [0x3004] ; increase number of processes |
mov ebx,[new_process_place] |
mov edi,ebx ; clear 0x80000 (256 bytes) |
shl edi,8 |
add edi,0x80000 |
mov ecx,256 / 4 |
mov eax,0 |
cld |
rep stosd |
shl ebx,5 ; * 32 +0x3000 |
add ebx,0x3000 |
mov al,byte [new_process_place] ; screen id ? |
mov [ebx+0xe],al |
mov [ebx],dword 1+2+4 ; report events: windowdraw, key, button |
inc dword [process_number] ; process id number |
mov eax,[process_number] |
mov [ebx+4],eax |
mov ecx,ebx ; set draw limits |
add ecx,draw_data-0x3000 |
mov [ecx+0],dword 0 |
mov [ecx+4],dword 0 |
mov eax,[0xfe00] |
mov [ecx+8],eax |
mov eax,[0xfe04] |
mov [ecx+12],eax |
mov eax,[app_mem_pos] ; position in memory |
mov [ebx+0x10],eax |
; TSS |
xor ebx,ebx |
cmp [thread_create],ebx |
jnz clone_cr3_table |
mov eax,[new_process_place] |
call create_app_cr3_table |
jmp set_cr3 |
clone_cr3_table: |
; mov eax,[new_process_place] |
; mov ebx,[0x3000] |
; call addreference_app_cr3_table |
mov eax,[0x3000] |
call get_cr3_table |
set_cr3: |
add eax,8+16 |
mov [l.cr3],eax |
mov eax,[app_start] |
mov [l.eip],eax |
mov eax,[app_esp] |
mov [l.esp],eax |
mov ebx,[new_process_place] ; gdt's |
shl ebx,3 |
mov ax,app_code |
add ax,bx |
mov [l.cs],ax |
mov ax,app_data |
add ax,bx |
mov [l.ss],ax |
mov [l.ds],ax |
mov [l.es],ax |
mov [l.fs],ax |
mov ax,graph_data |
mov [l.gs],ax |
mov [l.io],word 128 |
mov [l.eflags],dword 0x11202 |
mov [l.ss0], os_data |
;mov [l.ss1], ring1_data |
;mov [l.ss2], ring2_data |
; [Ivan 07.03.2005] |
mov [l.esp0], 0x8000 ;0x55000 ; used by i38 handler |
; [/Ivan 07.03.2005] |
mov [l.esp1], 0x56000 |
mov [l.esp2], 0x57000 |
mov eax,tss_sceleton ; move tss to tss_data+ |
mov ebx,[new_process_place] |
imul ebx,tss_step |
add ebx,tss_data |
mov ecx,120 |
call memmove |
; Add IO access table |
or eax, -1 |
mov edi, [new_process_place] |
imul edi, tss_step |
add edi, tss_data + 128 |
mov ecx, 2048 ; for 2048 * 4 * 8 bits = 65536 ports |
cld |
rep stosd |
; make sure gdt is pointing to the process |
; and not to i40 handler |
mov ecx,ebx |
mov edi,[new_process_place] |
; imul edi,8 |
shl edi, 3 |
mov [edi+gdts+ tss0 +0], word tss_step ; limit 0:15 |
mov [edi+gdts+ tss0 +2], cx ; base 0:15 |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+ tss0 +4], al ; base 23:16 |
mov [edi+gdts+ tss0 +7], ah ; base 31:24 |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
pop eax |
pop ebx |
mov ebx,[new_process_place] ; save name of the process |
shl ebx,8 |
add ebx,0x80000 |
mov ecx,11 |
call memmove |
mov ebx,[new_process_place] ; save image size |
shl ebx,8 |
add ebx,0x80000+0x8C |
mov eax,[app_mem] |
mov [ebx],eax |
mov [0xf400],byte 0 ; empty keyboard buffer |
mov [0xf500],byte 0 ; empty button buffer |
mov [application_table_status],0 |
mov eax,[process_number] |
mov ebx,[new_process_place] |
shl ebx, 5 ;imul ebx,0x20 |
mov [0x3000+ebx+0xa],byte 0 |
mov edi,[new_process_place] |
shl edi,5 |
add edi,window_data |
mov ebx,[new_process_place] |
movzx esi, word [0xC000 + ebx*2] |
lea esi, [0xC400 + esi*2] |
call windowactivate |
sti |
push esi |
mov esi,process_running |
call sys_msg_board_str |
pop esi |
ret |
iglobal |
process_terminating db 'K : Process - terminating',13,10,0 |
process_terminated db 'K : Process - done',13,10,0 |
endg |
terminate: ; terminate application |
push esi |
mov esi,process_terminating |
call sys_msg_board_str |
pop esi |
;start memory manager code |
; mov eax,esi |
; call MEM_Heap_Clean |
;end memory manager code |
cli |
cmp [application_table_status],0 |
je term9 |
sti |
call change_task |
jmp terminate |
term9: |
call set_application_table_status |
mov eax,esi |
call dispose_app_cr3_table |
mov [first_gdt_search],0x2 ; start gdt search from beginning |
cmp [prev_user_of_fpu],esi ; if user fpu last -> fpu user = 1 |
jne fpu_ok_1 |
mov [prev_user_of_fpu],1 |
fpu_ok_1: |
mov [0xf400],byte 0 ; empty keyboard buffer |
mov [0xf500],byte 0 ; empty button buffer |
mov ecx,esi ; clear memory reserv. |
shl ecx,3 |
mov [ecx+gdts+ app_code-3 +0],dword 0 |
mov [ecx+gdts+ app_code-3 +4],dword 0 |
mov [ecx+gdts+ app_data-3 +0],dword 0 |
mov [ecx+gdts+ app_data-3 +4],dword 0 |
mov edi, esi |
; shl edi, 5 |
; add edi, 0x3000 |
; cmp [edi+0xa],byte 3 ; if normal terminate then clear int40 handler |
; jne nocl40 |
; mov edi,esi ; free the used interrupt 0x40 handler |
; shl edi, 8 ;imul edi,256 |
; mov eax,[edi+0x80000+0xb0] |
; cmp eax,0 ; is application using a systemcall interrupt ? |
; je nocl40 |
mov [usedi40+eax],byte 0 |
; mov edi,8 |
; imul edi,eax |
mov edi, eax |
shl edi, 3 |
mov [edi+tss0sys_l +5], word 01010000b *256 +11101001b |
; mov edi,128 |
; imul edi,eax |
mov edi, eax |
shl edi, 7 |
mov [edi+0x298000+l.eip-tss_sceleton],dword i40 |
mov [edi+0x298000+l.eflags-tss_sceleton],dword 0x11002 |
mov ebx,eax |
shl ebx, 12 ;imul ebx,4096 |
add ebx,sysint_stack_data |
mov [edi+0x298000+l.esp-tss_sceleton],ebx |
nocl40: |
mov ecx,esi ; remove buttons |
bnewba2: |
mov edi,[0xfe88] |
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 ax,[esi+0] |
mov word [dlx],ax |
mov bx,[esi+8] |
add ax,bx |
mov word [dlxe],ax |
mov ax,[esi+4] |
mov word [dly],ax |
mov bx,[esi+12] |
add ax,bx |
mov word [dlye],ax |
mov [esi+0],word 0 |
mov [esi+8],word 5 |
mov ax,[0xFE04] |
mov [esi+4],ax |
mov [esi+12],word 5 |
xor eax, eax |
mov [esi+16],eax;dword 0 |
mov [esi+20],eax;dword 0 |
mov [esi+24],eax;dword 0 |
mov [esi+28],eax;dword 0 |
popa |
pusha |
mov edi,esi |
shl edi,5 |
add edi,window_data |
mov ecx,32/4 |
xor eax, eax |
; cld |
rep stosd |
mov eax,[0xFE04] ; set window to start from maxy+1 |
add eax,2 |
mov edi,esi |
shl edi,5 |
add edi,window_data |
mov [edi+4],eax |
popa |
pusha |
mov edi,esi |
shl edi,5 |
add edi,draw_data |
mov ecx,32/4 |
xor eax, eax |
; cld |
rep stosd |
popa |
pusha ; at 0x80000+ |
mov edi,esi |
shl edi,8 |
add edi,0x80000 |
mov ecx,256/4 |
xor eax, eax |
; cld |
rep stosd |
popa |
pusha ; name to spaces |
mov edi,esi |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
mov eax,' ' |
; cld |
rep stosb |
popa |
pusha ; C000 --> C400 |
mov eax, 0xc000 |
mov esi, 0 |
nlc40: |
add eax, 2 |
inc esi |
cmp esi, [0x3004] |
jae nlc41 |
movzx ecx, word [eax] |
mov [0xC400 + ecx*2], si |
jmp nlc40 |
nlc41: |
; ivan 08.12.2004 begin |
;mov ebx, [0x3004] |
;dec ebx |
;lea esi, [0xC400 + ebx*2] |
;call windowactivate |
; ivan 08.12.2004 end |
popa |
pusha ; remove hd1 reservation |
mov edx,esi |
shl edx, 5 ;imul edx,0x20 |
add edx,0x3000 |
mov edx,[edx+4] |
cmp [hd1_status],edx |
jne no_hd1_s_remove |
mov [hd1_status],0 |
no_hd1_s_remove: |
popa |
pusha ; remove all irq reservations |
mov edx,esi |
shl edx, 5 ;imul edx,0x20 |
add edx,0x3000 |
mov edx,[edx+4] |
mov edi,irq_owner |
mov ecx,16 |
newirqfree: |
cmp [edi],edx |
jne nofreeirq |
mov [edi],dword 0 |
nofreeirq: |
add edi,4 |
loop newirqfree |
popa |
pusha ; remove all port reservations |
mov edx,esi |
shl edx, 5 ;imul edx,0x20 |
add edx,0x3000 |
mov edx,[edx+4] |
rmpr0: |
mov esi,[0x2d0000] |
cmp esi,0 |
je rmpr9 |
rmpr3: |
mov edi,esi |
shl edi,4 |
add edi,0x2d0000 |
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 [0x2d0000] |
jmp rmpr0 |
rmpr9: |
popa |
mov edi,esi ; do not run this process slot |
shl edi, 5 ;imul edi,0x20 |
; add edi,0x3000 |
mov [edi+0x300A],byte 9 |
; call systest |
sti ; .. and life goes on |
; movzx eax,word [dlx] |
; movzx ebx,word [dly] |
; movzx ecx,word [dlxe] |
; movzx edx,word [dlye] |
call calculatescreen |
xor eax, eax |
xor esi, esi |
call redrawscreen |
mov [0xfff4],byte 0 ; no mouse background |
mov [0xfff5],byte 0 ; draw mouse |
mov [application_table_status],0 |
mov esi,process_terminated |
call sys_msg_board_str |
;* start code - fix error redraw for terminate (2) - Mario79 |
; cmp [draw_present],1 |
; je no_draw_background_temp |
; mov [0xfff0],byte 1 |
;no_draw_background_temp: |
; mov [draw_present],0 |
ret |
;draw_present db 0 |
;* end code - fix error redraw for terminate (2) - Mario79 |
iglobal |
boot_sched_1 db 'Building gdt tss pointer',0 |
;boot_sched_2 db 'Building gdt gate pointer',0 |
boot_sched_3 db 'Building interrupt table - TSS',0 |
boot_sched_3_2 db 'Building interrupt table - GDT',0 |
boot_sched_3_3 db 'Building interrupt table - IDT',0 |
boot_sched_4 db 'Building syscall interrupt table',0 |
endg |
build_scheduler: |
; { Ivan 06.03.2005 |
mov edi, usedi40 |
mov ecx, 256/4 |
xor eax, eax |
rep stosd |
; } Ivan 06.03.2005 |
mov esi,boot_sched_1 |
call boot_log |
call build_process_gdt_tss_pointer |
; mov esi,boot_sched_2 |
; call boot_log |
; call build_process_gdt_gate_pointer |
mov esi,boot_sched_3 |
call boot_log |
call build_interrupt_table |
mov esi,boot_sched_4 |
call boot_log |
call build_syscall_interrupt_table |
ret |
/kernel/trunk/core/syscall.inc |
---|
0,0 → 1,238 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSTEM CALL ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
i40: |
cli |
mov edi,[0x3000] |
mov eax,edi |
shl edi, 3 |
;clear busy flag in application's TSS |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
;save GDT TSS entry |
mov edx,[edi+tss0_l] |
mov [reg1+eax*4],edx |
mov edx,[edi+tss0_l+4] |
mov [reg2+eax*4],edx |
;and then write there i40's descriptor |
mov edx,[tss0sys_l+edi] |
mov [edi+tss0_l],edx |
mov edx,[tss0sys_l+edi+4] |
mov [edi+tss0_l+4],edx |
shl edi,5 |
mov [edi+0x80000+0xB0],eax ; used i40 handler |
; for syscall trace function |
call save_registers |
mov esi, [0x3000] |
imul esi, tss_step |
add esi, tss_data |
; esi holds address of TSS of interupted program |
; load first 3 registers |
mov eax,[esi+l.eax-tss_sceleton] |
mov ebx,[esi+l.ebx-tss_sceleton] |
mov ecx,[esi+l.ecx-tss_sceleton] |
; save current registers |
; stack may be modified by a system function to return some value to caller! |
pushad |
; load all registers from TSS of the application, in crossed order (why?) |
mov edi,[esi+l.eax-tss_sceleton] |
mov eax,[esi+l.ebx-tss_sceleton] |
mov ebx,[esi+l.ecx-tss_sceleton] |
mov ecx,[esi+l.edx-tss_sceleton] |
mov edx,[esi+l.esi-tss_sceleton] |
mov esi,[esi+l.edi-tss_sceleton] |
; enable interupts - a task switch or an IRQ _CAN_ interrupt i40 handler |
sti |
; eax doesn't need to be saved, but... |
push eax |
and edi,0xff |
call dword [servetable+edi*4] |
pop eax |
cli |
; return saved and probably even changed regs |
popad |
; <Ivan 05.03.2005> esi already loaded - look above "pusha" |
;mov esi,[0x3000] |
;imul esi,tss_step |
;add esi,tss_data |
; </Ivan 05.03.2005> |
; modify 3 program's registers (in its TSS) |
mov [esi+l.eax-tss_sceleton], eax |
mov [esi+l.ebx-tss_sceleton], ebx |
mov [esi+l.ecx-tss_sceleton], ecx |
; calculate app's TSS address |
mov ebx, [0x3000] |
shl ebx, 3 |
add ebx, tss0_l |
mov ecx, [0x3000] |
; restore saved TSS descriptor |
mov eax, [reg1+ecx*4] |
mov [ebx], eax |
mov eax, [reg2+ecx*4] |
mov [ebx+4], eax |
xor eax, eax |
mov edi, [0x3000] ; no syscall interrupt in use anymore |
shl edi, 8 |
mov [edi+0x80000+0xB0],eax |
; clear busy flag in TSS of this handler |
mov edi, [0x3000] |
shl edi, 3 |
mov [edi+tss0sys_l +5], word 01010000b *256 +11101001b |
add edi,tss0 |
mov [0xB004], di |
jmp pword [0xB000] |
jmp i40 |
label reg1 dword at 0x6000 |
label reg2 dword at 0x6400 |
label usedi40 byte at 0x6800 |
uglobal |
schd dd 0x0 |
endg |
align 4 |
save_registers: |
mov esi,[0x3000] |
imul esi,tss_step |
add esi,tss_data |
mov eax,[esi+l.eax-tss_sceleton] |
mov ebx,[esi+l.ebx-tss_sceleton] |
mov ecx,[esi+l.ecx-tss_sceleton] |
mov edx,[esi+l.edx-tss_sceleton] |
mov edi,[esi+l.edi-tss_sceleton] |
mov ebp,[esi+l.ebp-tss_sceleton] |
mov esi,[esi+l.esi-tss_sceleton] |
push eax ecx esi edi |
mov esi,[0x3010] |
mov eax,[esi+0x4] |
mov esi,esp |
inc [save_syscall_count] |
mov edi,[save_syscall_count] |
and edi,0xF |
shl edi,6 |
add edi,save_syscall_data+32 |
mov [edi-32],eax |
mov ecx,32 / 4 |
cld |
rep movsd |
pop edi esi ecx eax |
ret |
uglobal |
save_syscall_count dd 0x0 |
endg |
label save_syscall_data dword at 0x5000 |
iglobal |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; SYSTEM FUNCTIONS TABLE ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
servetable: |
dd sys_drawwindow ; 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 sys_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 syscall_system ; 18-Shutdown,KillApp,WindowActivate |
dd syscall_startapp ; 19-StartApp |
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 sys_sb16 ; 25-SetSb16 |
dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,. |
dd sys_wss ; 27-SetWssMainVol and SetWssCdVol |
dd sys_sb16II ; 28-SetSb16 |
dd sys_date ; 29-GetDate |
dd syscall_readhd ; 30-ReadHd |
dd syscall_starthdapp ; 31-StartHdApp |
dd syscall_delramdiskfile ; 32-DelRamdiskFile |
dd syscall_writeramdiskfile; 33-WriteRamdiskFile |
dd read_floppy_file ; 34-ReadFloppyDrive |
dd syscall_getpixel ; 35-GetPixel |
dd syscall_readstring ; 36-ReadString (not yet ready) |
dd readmousepos ; 37-GetMousePosition_ScreenRelative,. |
dd syscall_drawline ; 38-DrawLine |
dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,. |
dd set_app_param ; 40-WantEvents |
dd syscall_getirqowner ; 41-GetIrqOwner |
dd get_irq_data ; 42-ReadIrqData |
dd sys_outport ; 43-SendDeviceData |
dd sys_programirq ; 44-ProgramIrqs |
dd reserve_free_irq ; 45-ReserveIrq and FreeIrq |
dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea |
dd display_number ; 47-WriteNum |
dd display_settings ; 48-SetRedrawType and SetButtonType |
dd syscall_appints ; 49-AppInts |
dd random_shaped_window ; 50-Window shape & scale |
dd syscall_threads ; 51-Threads |
dd stack_driver_stat ; 52-Stack driver status |
dd socket ; 53-Socket interface |
dd user_events ; 54-User events |
dd sound_interface ; 55-Sound interface |
dd write_to_hd ; 56-Write a file to hd |
dd delete_from_hd ; 57-Delete a file from hd |
dd file_system ; 58-Common file system interface |
dd sys_trace ; 59-System call trace |
dd new_sys_ipc ; 60-Inter Process Communication |
dd sys_gs ; 61-Direct graphics access |
dd sys_pci ; 62-PCI functions |
dd sys_msg_board ; 63-System message board |
dd sys_resize_app_memory ; 64-Resize application memory usage |
dd undefined_syscall ; 65-UTF |
dd sys_process_def ; 66-Process definitions - keyboard |
dd sys_window_move ; 67-Window move or resize |
dd sys_internal_services ; 68-Some internal services |
times 255 - ( ($-servetable) /4 ) dd undefined_syscall |
dd sys_end ; -1-end application |
endg |
/kernel/trunk/detect/commouse.inc |
---|
0,0 → 1,121 |
;************************************************** |
;* ÏÎÈÑÊ ÌÛØÈ ÏÎ ÏÎÑËÅÄÎÂÀÒÅËÜÍÛÌ ÏÎÐÒÀÌ * |
;* Ïðîöåäóðà ïîäãîòàâëèâàåò ãëîáàëüíûå ïåðåìåííûå * |
;* COMPortNum è COMPortBaseAddr äëÿ ïîäïðîãðàììû * |
;* óñòàíîâêè îáðàáîò÷èêà ïðåðûâàíèÿ * |
;************************************************** |
; Àâòîð èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷. |
; Àäàïòàöèÿ è äîðàáîòêà Mario79 |
MSMouseSearch: |
pusha |
; Çàïðåòèòü ïðåðûâàíèå COM1 è COM2 |
cli |
in AL,21h ;ïðî÷èòàòü ìàñêó ïðåðûâàíèé |
or AL,18h ;çàïðåòèòü IRQ3 è IRQ4 |
out 21h,AL ;çàìåíèòü ìàñêó |
sti |
; ÏÎÈÑÊ ÌÛØÈ ×ÅÐÅÇ COM-ÏÎÐÒÛ |
MouseSearch: |
; Óñòàíàâëèâàåì ñêîðîñòü |
; ïðèåìà/ïåðåäà÷è 1200 áîä |
mov DX,[COMPortBaseAddr] |
add DX,3 |
in AL,DX |
or AL,80h ;óñòàíîâèòü áèò DLAB |
out DX,AL |
mov DX,[COMPortBaseAddr] |
mov AL,60h ;1200 áîä |
out DX,AL |
inc DX |
mov AL,0 |
out DX,AL |
; Óñòàíîâèòü äëèíó ñëîâà 7 áèò, 1 ñòîïîâûé áèò, |
; ÷åòíîñòü íå êîíòðîëèðîâàòü |
mov DX,[COMPortBaseAddr] |
add DX,3 |
mov AL,00000010b |
out DX,AL |
; Çàïðåòèòü âñå ïðåðûâàíèÿ |
mov DX,[COMPortBaseAddr] |
inc DX |
mov AL,0 |
out DX,AL |
; Ïðîâåðèòü, ÷òî óñòðîéñòâî ïîäêëþ÷åíî è ÿâëÿåòñÿ |
; ìûøüþ òèïà MSMouse |
; Îòêëþ÷èòü ïèòàíèå ìûøè è ïðåðûâàíèÿ |
mov DX,[COMPortBaseAddr] |
add DX,4 ;ðåãèñòð óïðàâëåíèÿ ìîäåìîì |
mov AL,0 ;ñáðîñèòü DTR, RTS è OUT2 |
out DX,AL |
; Îæèäàòü 5 "òèêîâ" (0,2 ñ) |
mov ecx,0xffff |
dT_1: |
dec ecx |
cmp ecx,0 |
jne dT_1 |
mov ecx,0xffff |
; Âêëþ÷èòü ïèòàíèå ìûøè |
mov AL,11b ;óñòàíîâèòü DTR è RTS |
out DX,AL |
; Î÷èñòèòü ðåãèñòð äàííûõ |
mov DX,[COMPortBaseAddr] |
in AL,DX |
; Öèêë îïðîñà ïîðòà |
WaitData: |
; Îæèäàòü åùå 10 "òèêîâ" |
dec ecx |
cmp ecx,0 |
je NoMouse |
; Ïðîâåðèòü íàëè÷èå èäåíòèôèêàöèîííîãî áàéòà |
mov DX,[COMPortBaseAddr] |
add DX,5 |
in AL,DX |
test AL,1 ;Äàííûå ãîòîâû? |
jz WaitData |
; Ââåñòè äàííûå |
mov DX,[COMPortBaseAddr] |
in AL,DX |
; Óñòðîéñòâî ÿâëÿåòñÿ ìûøüþ? |
cmp AL,'M' |
je EndDetect |
NoMouse: |
inc [COMPortNum] |
cmp [COMPortNum],1 |
ja EndDetect |
sub [COMPortBaseAddr],100h |
jmp MouseSearch |
iglobal |
COMPortBaseAddr dw 3F8h |
COMPortNum dw 0 |
endg |
iglobal |
boot_setmouse_type db 'No COM mouse, set PS2',0 |
db 'Detected - COM1 mouse',0 |
db 'Detected - COM2 mouse',0 |
endg |
EndDetect: |
cmp [COMPortNum],0 ;íîìåð ïîðòà ìåíüøå 0? |
jl ComMouseNotFound ;ìûøü íå íàéäåíà |
cmp [COMPortNum],1 ;íîìåð ïîðòà áîëüøå 1? |
ja ComMouseNotFound ;ìûøü íå íàéäåíà |
mov ax,[COMPortNum] |
add al,2 |
jmp set_detecting_mouse |
ComMouseNotFound: |
mov al,1 |
set_detecting_mouse: |
mov [0xF604],al |
dec al |
movzx eax,al |
imul eax,22 |
mov esi,boot_setmouse_type |
add esi,eax |
call boot_log |
popa |
/kernel/trunk/detect/dev_fd.inc |
---|
0,0 → 1,20 |
;*************************************************** |
; ïðåäâàðèòåëüíàÿ î÷èñòêà îáëàñòè òàáëèöû |
; ïîèñê è çàíåñåíèå â òàáëèöó ïðèâîäîâ FDD |
; àâòîð Mario79 |
;*************************************************** |
xor eax,eax |
mov edi,0x40000 |
mov ecx,16384 |
cld |
rep stosd |
mov al,0x10 |
out 0x70,al |
mov cx,0xff |
wait_cmos: |
dec cx |
cmp cx,0 |
jne wait_cmos |
in al,0x71 |
mov [0x40000],al |
/kernel/trunk/detect/dev_hdcd.inc |
---|
0,0 → 1,374 |
;****************************************************** |
; ïîèñê ïðèâîäîâ HDD è CD |
; àâòîð èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷. |
; àäàïòàöèÿ è äîðàáîòêà Mario79 |
;****************************************************** |
;**************************************************** |
;* ÏÎÈÑÊ HDD è CD * |
;**************************************************** |
FindHDD: |
mov [ChannelNumber],1 |
mov [DiskNumber],0 |
call FindHDD_3 |
; mov ax,[Sector512+176] |
; mov [0x40006],ax |
; mov ax,[Sector512+126] |
; mov [0x40008],ax |
; mov ax,[Sector512+128] |
; mov [0x40008],ax |
mov [DiskNumber],1 |
call FindHDD_3 |
; mov al,[Sector512+176] |
; mov [0x40007],al |
inc [ChannelNumber] |
mov [DiskNumber],0 |
call FindHDD_3 |
; mov al,[Sector512+176] |
; mov [0x40008],al |
mov [DiskNumber],1 |
call FindHDD_1 |
; mov al,[Sector512+176] |
; mov [0x40009],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 [0x40001] |
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 [0x40001] |
inc byte [0x40001] |
FindHDD_2_2: |
ret |
FindHDD_3: |
call FindHDD_1 |
shl byte [0x40001],2 |
ret |
; Àäðåñ ñ÷èòûâàåìîãî ñåêòîðà â ðåæèìå LBA |
SectorAddress DD ? |
;************************************************* |
;* ×ÒÅÍÈÅ ÈÄÅÍÒÈÔÈÊÀÒÎÐÀ ÆÅÑÒÊÎÃÎ ÄÈÑÊÀ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* 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 |
je @@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 ;ïðèíÿòü áëîê äàííûõ |
jmp @@End |
; Çàïèñàòü êîä îøèáêè |
@@Error1: |
mov [DevErrorCode],1 |
jmp @@End |
@@Error6: |
mov [DevErrorCode],6 |
@@End: ret |
; Ñòàíäàðòíûå áàçîâûå àäðåñà êàíàëîâ 1 è 2 |
StandardATABases DW 1F0h, 170h |
; Íîìåð êàíàëà |
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 DB ? |
;**************************************************** |
;* ÏÎÑËÀÒÜ ÊÎÌÀÍÄÓ ÇÀÄÀÍÍÎÌÓ ÄÈÑÊÓ * |
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå * |
;* ïåðåìåííûå: * |
;* 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 |
je @@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 |
jmp @@End_2 |
; Çàïèñàòü êîä îøèáêè |
@@Err1: mov [DevErrorCode],1 |
jmp @@End_2 |
@@Err2: mov [DevErrorCode],2 |
jmp @@End_2 |
@@Err3: mov [DevErrorCode],3 |
jmp @@End_2 |
@@Err4: mov [DevErrorCode],4 |
jmp @@End_2 |
@@Err5: mov [DevErrorCode],5 |
; Çàâåðøåíèå ðàáîòû ïðîãðàììû |
@@End_2: |
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 |
je @@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 |
jmp @@End_1 |
; Çàïèñàòü êîä îøèáêè |
@@Error1_1: |
mov [DevErrorCode],1 |
jmp @@End_1 |
@@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,0xffff |
@@WaitHDReady_1: |
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ |
dec ecx |
cmp ecx,0 |
je @@Err1_2 ;îøèáêà òàéì-àóòà |
; Ïðî÷èòàòü ðåãèñòð ñîñòîÿíèÿ |
in AL,DX |
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY |
test AL,80h |
jnz @@WaitHDReady_1 |
; Ñáðîñèòü ïðèçíàê îøèáêè |
mov [DevErrorCode],0 |
jmp @@End_3 |
; Îáðàáîòêà îøèáîê |
@@Err1_2: mov [DevErrorCode],1 |
jmp @@End_3 |
@@Err3_2: mov [DevErrorCode],3 |
jmp @@End_3 |
@@Err4_2: mov [DevErrorCode],4 |
; Çàïèñàòü êîä îøèáêè |
@@End_3: |
ret |
EndFindHDD: |
/kernel/trunk/detect/disks.inc |
---|
0,0 → 1,4 |
include 'dev_fd.inc' |
include 'dev_hdcd.inc' |
include 'sear_par.inc' |
/kernel/trunk/detect/sear_par.inc |
---|
0,0 → 1,116 |
;**************************************************** |
; ïîèñê ëîãè÷åñêèõ äèñêîâ íà îáíàðóæåííûõ HDD |
; è çàíåñåíèå äàííûõ â îáëàñòü òàáëèöû |
; àâòîð Mario79 |
;**************************************************** |
mov [transfer_adress],0x4000a |
search_partitions_ide0: |
test [0x40001],byte 0x40 |
jz search_partitions_ide1 |
mov [hdbase],0x1f0 |
mov [hdid],0x0 |
mov [hdpos],1 |
mov [fat32part],1 |
search_partitions_ide0_1: |
call set_FAT32_variables |
cmp [problem_partition],0 |
jne search_partitions_ide1 |
inc byte [0x40002] |
call partition_data_transfer |
add [transfer_adress],100 |
inc [fat32part] |
jmp search_partitions_ide0_1 |
search_partitions_ide1: |
test [0x40001],byte 0x10 |
jz search_partitions_ide2 |
mov [hdbase],0x1f0 |
mov [hdid],0x10 |
mov [hdpos],2 |
mov [fat32part],1 |
search_partitions_ide1_1: |
call set_FAT32_variables |
cmp [problem_partition],0 |
jne search_partitions_ide2 |
inc byte [0x40003] |
call partition_data_transfer |
add [transfer_adress],100 |
inc [fat32part] |
jmp search_partitions_ide1_1 |
search_partitions_ide2: |
test [0x40001],byte 0x4 |
jz search_partitions_ide3 |
mov [hdbase],0x170 |
mov [hdid],0x0 |
mov [hdpos],3 |
mov [fat32part],1 |
search_partitions_ide2_1: |
call set_FAT32_variables |
cmp [problem_partition],0 |
jne search_partitions_ide3 |
inc byte [0x40004] |
call partition_data_transfer |
add [transfer_adress],100 |
inc [fat32part] |
jmp search_partitions_ide2_1 |
search_partitions_ide3: |
test [0x40001],byte 0x1 |
jz end_search_partitions_ide |
mov [hdbase],0x170 |
mov [hdid],0x10 |
mov [hdpos],4 |
mov [fat32part],1 |
search_partitions_ide3_1: |
call set_FAT32_variables |
cmp [problem_partition],0 |
jne end_search_partitions_ide |
inc byte [0x40005] |
call partition_data_transfer |
add [transfer_adress],100 |
inc [fat32part] |
jmp search_partitions_ide3_1 |
partition_data_transfer: |
mov edi,[transfer_adress] |
mov esi,PARTITION_START |
xor ecx,ecx |
mov cx,69 ;100 |
rep movsb |
ret |
transfer_adress dd 0 |
partition_data_transfer_1: |
cli |
mov edi,PARTITION_START |
mov esi,[transfer_adress] |
xor ecx,ecx |
mov cx,69 ;100 |
rep movsb |
sti |
ret |
end_search_partitions_ide: |
;PARTITION_START dd 0x3f |
;PARTITION_END dd 0 |
;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 |
; |
;fat_type db 0 ; 0=none, 16=fat16, 32=fat32 |
/kernel/trunk/fs/fat12.inc |
---|
0,0 → 1,1084 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; FAT12.INC ;; |
;; (C) 2005 Mario79, License: GPL ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
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,[0x3000] |
shl eax,5 |
mov eax,[eax+0x3000+4] |
mov [flp_status],eax |
pop eax |
sti |
ret |
floppy_free_space: |
;--------------------------------------------- |
; |
; returns free space in edi |
; |
;--------------------------------------------- |
push eax ebx ecx |
call read_flp_fat |
cmp [FDC_Status],0 |
jne fdc_status_error_2 |
mov eax,0x282000 |
xor edi,edi |
mov ecx,2847 ;1448000/512 |
rdfs1_1: |
mov ebx,[eax] |
and ebx,4095 |
cmp ebx,0 |
jne rdfs2_1 |
add edi,512 |
rdfs2_1: |
add eax,2 |
loop rdfs1_1 |
fdc_status_error_2: |
pop ecx ebx eax |
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 |
cmp esi,0 ; return ramdisk root |
jne fr_noroot_1 |
cmp ebx,224/16 |
jbe fr_do_1 |
mov eax,5 |
mov ebx,0 |
mov [flp_status],0 |
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,0x8000 |
add esi,ebx |
shl ecx,9 |
cld |
rep movsb |
mov eax,0 ; ok read |
mov ebx,0 |
mov [flp_status],0 |
ret |
fdc_status_error_1: |
mov [flp_status],0 |
mov eax,10 |
mov ebx,-1 |
ret |
fr_noroot_1: |
sub esp,32 |
call expand_filename |
frfloppy_1: |
cmp ebx,0 |
jne frfl5_1 |
mov ebx,1 |
frfl5_1: |
cmp ecx,0 |
jne 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,0xD000 |
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 |
cmp dl,0 |
jne l.21_1 |
dec dh |
cmp dh,0 |
jne l.20_1 |
fdc_status_error_3: |
mov eax,5 ; file not found ? |
mov 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,0x282000 |
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 |
mov eax,0 |
mov [flp_status],0 |
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,0x8000 |
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,0x8000 |
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,0x8000 |
mov edi,0x282000 |
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,0x282000+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,0xD000+39 |
mov ecx,15 |
cld |
rep cmpsb |
je same_label |
mov [root_read],0 |
mov [flp_fat],0 |
same_label: |
mov esi,0xD000+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,0x8000 |
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,0x8000 |
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,0x282000 |
mov edi,0x8000 |
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,0x8000+0x1200 ;4274 bytes - all used FAT |
jb fcnew2_1 |
mov esi,0x8000 ; duplicate fat chain |
mov edi,0x8000+0x1200 |
mov ecx,0x1200/4 |
cld |
rep movsd |
popad |
ret |
floppy_filedelete: |
;-------------------------------------------- |
; |
; filedelete - sys floppy |
; in: |
; eax - filename 11 chars - for root directory |
; edi pointer to path /fd/1/...... - for all files in nested directories |
; |
; out: |
; eax - 0 = successful, 1 = file not found, 10 = access denied |
; |
;-------------------------------------------- |
mov [path_pointer_flp],edi |
mov [save_flag],0 |
mov ebp,1 ; file not found as default |
filedelete_newtry_1: |
sub esp,32 |
call expand_filename |
push eax ebx ecx edx esi edi |
call read_flp_fat |
cmp [FDC_Status],0 |
jne frnoreadd_1 |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],1 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
call SeekTrack |
mov dh,14 |
l.20_2: |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne fdc_status_error_4 |
mov dl,16 |
mov edi,0xD000 |
inc [FDD_Sector] |
l.21_2: |
mov esi,eax ;Name of file we want |
mov ecx,11 |
cld |
rep cmpsb ;Found the file? |
je fifoundd_1 ;Yes |
add ecx,21 |
add edi, ecx ;Advance to next entry |
dec dl |
cmp dl,0 |
jne l.21_2 |
dec dh |
cmp dh,0 |
jne l.20_2 |
jmp frnoreadd_1 |
fdc_status_error_4: |
pop edi esi edx ecx ebx eax |
add esp,32 |
jmp fdc_status_error_1 |
fifoundd_1: |
mov eax,[path_pointer_flp] |
cmp [eax+36],byte 0 |
je fifoundd_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 frnoreadd_1_1 |
mov edi,ebx |
add edi,11 |
jmp fifoundd_2_1 |
fifoundd_2: |
dec [FDD_Sector] |
fifoundd_2_1: |
mov [edi-11],byte 0xE5 ;mark filename deleted |
add edi,0xf |
mov eax,[edi] |
and eax,65535 |
mov edi,eax ;edi = cluster |
frnewd_1: |
shl edi,1 ;find next cluster from FAT |
add edi,0x282000 |
mov eax,[edi] |
mov [edi],word 0x0 ;clear fat chain cluster |
and eax,4095 |
mov edi,eax |
cmp edi,dword 4095 ;last cluster ? |
jz frnoreadd2_1 |
jmp frnewd_1 |
frnoreadd2_1: |
call WriteSectWithRetr |
cmp [FDC_Status],0 |
jne fdc_status_error_4 |
call save_flp_fat |
cmp [FDC_Status],0 |
jne fdc_status_error_4 |
; pop edi esi edx ecx ebx eax |
; add esp,32 |
mov ebp,0 ; file found |
; jmp filedelete_newtry_1 |
jmp frnoreadd_1 |
frnoreadd_1_1: |
cmp [FDC_Status],0 |
jne fdc_status_error_4 |
frnoreadd_1: |
pop edi esi edx ecx ebx eax |
add esp,32 |
mov eax,ebp |
ret |
floppy_filesave: |
;---------------------------------------------------------- |
; |
; filesave - sys floppy |
; |
; eax ; pointer to file name 11 chars - for root directory |
; ebx ; buffer |
; ecx ; count to write in bytes |
; edx ; 0 create new , 1 append |
; edi pointer to path /fd/1/...... - for all files in nested directories |
; |
; output : eax = 0 - ok |
; 5 - file not found / directory not found |
; 8 - disk full |
; 10 - access denied |
;----------------------------------------------------------- |
mov [path_pointer_flp],edi |
sub esp,32 |
call expand_filename |
cmp edx,0 |
jnz fsdel_1 |
pusha |
call floppy_filedelete |
cmp [FDC_Status],0 |
jne fdc_status_error_6 |
popa |
mov [save_flag],1 |
fsdel_1: |
call floppy_free_space |
cmp [FDC_Status],0 |
jne fdc_status_error_6 |
cmp ecx,edi |
jb rd_do_save_1 |
add esp,32 |
mov eax,8 ; not enough free space |
mov [flp_status],0 |
ret |
fdc_status_error_6: |
popa |
add esp,32 |
jmp fdc_status_error_1 |
rd_do_save_1: |
push eax ebx ecx edx esi edi |
call read_flp_fat |
cmp [FDC_Status],0 |
jne fdc_status_error_7 |
push eax |
mov eax,[path_pointer_flp] |
cmp [eax+36],byte 0 |
jne fifoundds_2 |
pop eax |
mov [save_root_flag],1 |
call read_flp_root |
cmp [FDC_Status],0 |
jne fdc_status_error_7 |
mov edi,0x8000 ;Point at directory |
mov edx,224 +1 |
; find an empty spot for filename in the root dir |
l20ds_1: |
sub edx,1 |
cmp edx,0 |
jnz l21ds_1 |
jmp frnoreadds_1 |
l21ds_1: |
cmp [edi],byte 0xE5 |
jz fifoundds_1 |
cmp [edi],byte 0x0 |
jz fifoundds_1 |
add edi,32 ; Advance to next entry |
jmp l20ds_1 |
fifoundds_2: |
pop eax |
mov [save_root_flag],0 |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],1 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
call SeekTrack |
mov dh,14 |
l.20_3: |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne fdc_status_error_7 |
mov dl,16 |
mov edi,0xD000 |
inc [FDD_Sector] |
l.21_3: |
mov esi,eax ;Name of file we want |
mov ecx,11 |
cld |
rep cmpsb ;Found the file? |
je fifoundds_3 ;Yes |
add ecx,21 |
add edi, ecx ;Advance to next entry |
dec dl |
cmp dl,0 |
jne l.21_3 |
dec dh |
cmp dh,0 |
jne l.20_3 |
fdc_status_error_8: |
pop edi esi edx ecx ebx eax |
mov eax,5 ; file not found ? |
mov ebx,-1 |
add esp,32 |
mov [flp_status],0 |
ret |
fifoundds_3: |
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_7_1 |
found_directory_for_writing_flp: |
call analyze_directory_to_write_flp |
jc fdc_status_error_7_1 |
mov edi,ebx |
fifoundds_1: |
push edi ; move the filename to root dir |
mov esi,[esp+4+20] |
cmp [save_root_flag],0 |
jne fifoundds_4 |
mov esi,[pointer_file_name_flp] |
fifoundds_4: |
mov ecx,11 |
cld |
rep movsb |
pop edi |
mov edx,edi |
add edx,11+0xf ; edx <- cluster save position |
mov ebx,[esp+12] ; save file size |
mov [edi+28],ebx |
mov [edi+11],byte 0x20 ; attribute |
call get_date_for_file ; from FAT32.INC |
mov [edi+24],ax ; date |
mov [edi+18],ax ; date |
call get_time_for_file ; from FAT32.INC |
mov [edi+22],ax ; time |
xor ax,ax |
mov [edi+20],ax |
mov ebx,1 ; first cluster |
cmp [save_root_flag],0 |
jne frnewds_1 |
call frnewds_2 |
pusha |
call WriteSectWithRetr |
popa |
cmp [FDC_Status],0 |
jne fdc_status_error_7 |
jmp frnewds_3 |
frnewds_1: |
call frnewds_2 |
frnewds_3: |
pusha ; move save to floppy cluster |
add ebx,31 |
mov eax,ebx |
mov esi,[esp+32+16] |
call take_data_from_application_1 |
call save_chs_sector |
cmp [FDC_Status],0 |
jne fdc_status_error_7 |
popa |
mov eax,[esp+12] |
cmp eax,512 |
jb flnsa_1 |
sub eax,512 |
mov [esp+12],eax |
mov eax,[esp+16] |
add eax,512 |
mov [esp+16],eax |
jmp frnewds_1 |
frnewds_2: |
add ebx,1 |
mov edi,ebx ; find free cluster in FAT |
shl edi,1 |
add edi,0x282000 |
mov eax,[edi] |
and eax,4095 |
cmp eax,0x0 |
jnz frnewds_2 |
mov [edx],bx ; save next cluster pos. to prev cl. |
mov edx,edi ; next save pos abs mem add |
ret |
flnsa_1: |
mov [edi],word 4095 ; mark end of file - last cluster |
cmp [save_root_flag],1 |
jne flnsa_2 |
call save_flp_root |
cmp [FDC_Status],0 |
jne fdc_status_error_7 |
flnsa_2: |
call save_flp_fat |
cmp [FDC_Status],0 |
jne fdc_status_error_7 |
frnoreadds_1: |
pop edi esi edx ecx ebx eax |
add esp,32 |
mov eax,0 |
mov [flp_status],0 |
ret |
fdc_status_error_7_1: |
cmp [FDC_Status],0 |
je fdc_status_error_8 |
fdc_status_error_7: |
pop edi esi edx ecx ebx eax |
add esp,32 |
jmp fdc_status_error_1 |
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 |
cmp edx,0 |
je 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,0xD000 |
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,0x282000 |
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 |
analyze_directory_to_write_flp: |
;-------------------------------- |
; input : EAX = first cluster of the directory |
; output : IF CARRY=0 EAX = sector where the file is found |
; EBX = pointer in buffer |
; [buffer .. buffer+511] |
; ECX,EDX,EDI,EDI not changed |
; IF CARRY=1 |
;-------------------------------- |
push ecx |
push edx |
push esi |
adr561: |
mov [clust_tmp_flp],eax |
add eax,31 |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status],0 |
jne error_found_file_analyze1 |
mov ecx,512/32 |
mov ebx,0xD000 |
adr1_analyze1: |
cmp byte [ebx],0x00 |
je found_file_analyze1 |
cmp byte [ebx],0xe5 |
je found_file_analyze1 |
avanti: |
add ebx,32 |
loop adr1_analyze1 |
mov eax,[clust_tmp_flp] |
shl eax,1 ;find next cluster from FAT |
add eax,0x282000 |
mov eax,[eax] |
and eax,4095 |
cmp eax,0x0ff8 |
jb adr561 |
call get_free_FAT ;this block of code add a new cluster |
;for the directory because the directory |
;is full |
mov [edi],word 0x0fff |
mov eax,[clust_tmp_flp] |
shl eax,1 ;find next cluster from FAT |
add eax,0x282000 |
sub edi,0x282000 |
mov [eax],di |
pusha |
mov ecx,512/4 |
xor eax,eax |
mov edi,0xD000 |
cld |
rep stosd |
popa |
mov eax,edi |
add eax,31 |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status],0 |
jne error_found_file_analyze1 |
mov ebx,0xD000 |
found_file_analyze1: |
pop esi |
pop edx |
pop ecx |
clc ;file found |
ret |
error_found_file_analyze1: |
pop esi |
pop edx |
pop ecx |
stc |
ret |
get_free_FAT_flp: |
;------------------------------------------ |
; input : EAX = # cluster for start the searching |
; output : EAX = # first cluster found free |
;------------------------------------------- |
push ebx |
mov ebx,1 |
check_new_flp: |
add ebx,1 |
mov edi,ebx ; find free cluster in FAT |
shl edi,1 |
add edi,0x282000 |
mov eax,[edi] |
and eax,4095 |
cmp eax,0x0 |
jnz check_new_flp |
pop ebx |
ret |
/kernel/trunk/fs/fat32.inc |
---|
0,0 → 1,2827 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; FAT32.INC ;; |
;; ;; |
;; FAT16/32 functions for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
cache_max equ 1919 ; max. is 1919*512+0x610000=0x6ffe00 |
ERROR_DISK_BASE equ 1 |
ERROR_UNSUPPORTED_FS equ 2 |
ERROR_UNKNOWN_FS equ 3 |
ERROR_PARTITION equ 4 |
ERROR_FILE_NOT_FOUND equ 5 |
ERROR_END_OF_FILE equ 6 |
ERROR_MEMORY_POINTER equ 7 |
ERROR_DISK_FULL equ 8 |
ERROR_FAT_TABLE equ 9 |
ERROR_ACCESS_DENIED equ 10 |
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] |
align 4 |
;****************************************************** |
; Please do not change this place - variables in text |
; Mario79 |
; START place |
;****************************************************** |
PARTITION_START dd 0x3f |
PARTITION_END dd 0 |
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 |
fat_type db 0 ; 0=none, 16=fat16, 32=fat32 |
;*************************************************************************** |
; End place |
; Mario79 |
;*************************************************************************** |
cluster dd 0 ; used by file_write,makedir,append |
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 |
sector_tmp dd 0 ; used by rename,append,file_write |
entry_pos dd 0 ; used by rename,append,file_write |
old_filesize dd 0 ; used by append |
new_filepos dd 0 ; used by append |
bytes2write dd 0 ; used by append |
cache_search_start dd 0 ; used by find_empty_slot |
fat_in_cache dd -1 |
fat_cache: times 512 db 0 |
uglobal |
Sector512: ; label for dev_hdcd.inc |
buffer: times 512 db 0 |
deltree_buffer: times 512 db 0 |
endg |
iglobal |
NewDirEntry1 db ". ",0x10 |
times 20 db 0 |
NewDirEntry2 db ".. ",0x10 |
times 20 db 0 |
endg |
uglobal |
dir_entry: times 32 db 0 |
startpath: times 255 db 0 |
fat16_root db 0 ; flag for fat16 rootdir |
f_del db 0 ; 1=overwrite fat entry |
fat_change db 0 ; 1=fat has changed |
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 |
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 |
reserve_hd1: |
cli |
cmp [hd1_status],0 |
je reserve_ok1 |
sti |
call change_task |
jmp reserve_hd1 |
reserve_ok1: |
push eax |
mov eax,[0x3000] |
shl eax,5 |
mov eax,[eax+0x3000+4] |
mov [hd1_status],eax |
pop eax |
sti |
ret |
clear_hd_cache: |
push eax ecx edi |
mov edi,0x600000 |
mov ecx,16384 |
xor eax,eax |
cld |
rep stosd ; clear hd cache with 0 |
mov [cache_search_start],eax |
mov [fat_in_cache],-1 |
mov [fat_change],0 |
pop edi ecx eax |
ret |
problem_partition db 0 ; used for partitions search |
; Partition chain used: |
; MBR ; PARTITION2 ; PARTITION3 ; PARTITION4 |
;========================================================== |
; fat16/32 +-- fat16/32 +-- fat16/32 +-- fat16/32 +-- |
; extended --+ extended --+ extended --+ extended --+ |
; 0 0 0 0 |
; 0 0 0 0 |
; Notes: |
; - extended partition need to be in second entry on table |
; - it will skip over removed partitions |
set_FAT32_variables: |
mov [0xfe10],dword 0 ; entries in hd cache |
mov [problem_partition],0 |
call reserve_hd1 |
call clear_hd_cache |
cmp dword [hdpos],0 |
je problem_hd |
pushad |
xor ecx,ecx ; partition count |
mov edx,-1 ; flag for partition |
xor eax,eax ; read MBR |
xor ebp,ebp ; extended partition start |
new_partition: |
test ebp,ebp ; is there extended partition? |
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 word [ebx+0x1fe],0xaa55 ; is it valid boot sector? |
jnz end_partition_chain |
cmp dword [ebx+0x1be+0xc],0 ; skip over empty partition |
jz next_partition |
push eax ecx |
mov edi,partition_types |
mov ecx,partition_types_end-partition_types |
mov al,[ebx+0x1be+4] ; get partition type |
cld |
repne scasb ; is partition type ok? |
pop ecx eax |
jnz next_partition ; no. skip over |
inc ecx |
cmp ecx,[fat32part] ; is it wanted partition? |
jnz next_partition ; no |
mov edx,eax ; start sector |
add edx,[ebx+0x1be+8] ; add relative start |
next_partition: |
push ecx |
mov edi,extended_types |
mov ecx,extended_types_end-extended_types |
mov al,[ebx+0x1be+4+16] ; get second partition type |
cld |
repne scasb ; is it extended partition? |
pop ecx |
jnz end_partition_chain ; no. end chain |
mov eax,[ebx+0x1be+8+16] ; get start of extended partition |
test eax,eax ; is there extended partition? |
jnz new_partition ; 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_fat_dec_count: ; bootsector is missing or another problem |
dec [partition_count] ; remove it from partition_count |
problem_partition_or_fat: |
popad |
problem_hd: |
mov [fat_type],0 |
mov [hd1_status],0 ; free |
mov [problem_partition],1 |
ret |
hd_and_partition_ok: |
mov eax,edx |
mov [PARTITION_START],eax |
mov [hd_setup],1 |
mov ebx,buffer |
call hd_read ; read boot sector of partition |
mov [hd_setup],0 |
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 |
mov [SECTORS_PER_CLUSTER],eax |
movzx ecx,word [ebx+0xb] ; bytes per sector |
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 |
; 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 |
popad |
mov [fatRESERVED],0x0FFFFFF6 |
mov [fatBAD],0x0FFFFFF7 |
mov [fatEND],0x0FFFFFF8 |
mov [fatMASK],0x0FFFFFFF |
mov [fat_type],32 ; Fat32 |
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 [fat_type],16 ; Fat16 |
mov [hd1_status],0 ; free |
ret |
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 [fat_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 |
sfc_no_change: |
mov [fat_in_cache],eax ; save fat sector |
call hd_read |
sfc_in_cache: |
cmp [fat_type],16 |
jne sfc_test32 |
cmp [f_del],1 ; overwrite previous value? |
je sfc_set16 ; yes |
cmp word [ebx+esi],0 ; is cluster free? |
je sfc_set16 ; yes |
mov dword [8*0x100000],0xffffff |
mov edx,[ebx+esi] ; get old value |
jmp sfc_nonzero |
sfc_set16: |
xchg [ebx+esi],dx ; save new value and get old value |
jmp sfc_write |
sfc_test32: |
mov eax,[fatMASK] |
cmp [f_del],1 ; overwrite previous value? |
je sfc_set32 ; yes |
test eax,[ebx+esi] ; is cluster free? |
je sfc_set32 ; yes |
mov dword [8*0x100000],0xffffff |
mov edx,[ebx+esi] ; get old value |
jmp sfc_nonzero |
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 [fat_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 |
gfc_no_change: |
mov [fat_in_cache],eax |
call hd_read |
gfc_in_cache: |
mov eax,[ebx+esi] |
and eax,[fatMASK] |
pop esi ebx |
ret |
get_free_FAT: |
;----------------------------------------------------------- |
; input : EAX = # cluster for start the searching |
; 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 |
gff_test: |
cmp eax,[LAST_CLUSTER] ; if above last cluster start at cluster 2 |
jbe gff_in_range |
mov eax,2 |
gff_in_range: |
push eax |
call get_FAT ; get cluster state |
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: |
pop ecx ; yes. disk is full |
stc |
ret |
gff_found: |
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 |
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 [fat_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 |
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 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 |
analyze_directory_to_write: |
;----------------------------------------------------------- |
; input : EAX = first cluster of the directory |
; output : IF CARRY=0 EAX = sector where the empty pos is found |
; EBX = pointer in buffer |
; [buffer .. buffer+511] |
; ECX,EDX,ESI,EDI not changed |
; IF CARRY=1 disk full or fat corrupted |
; Note : if cluster=0 it's changed to read rootdir |
;----------------------------------------------------------- |
push ecx edx edi |
adw_new_cluster: |
mov [cluster_tmp],eax |
mov [fat16_root],0 |
cmp eax,[LAST_CLUSTER] |
ja adw_not_found ; too big cluster number, something is wrong |
cmp eax,2 |
jnb adw_data_cluster |
mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir |
cmp [fat_type],16 |
jne adw_data_cluster |
mov eax,[ROOT_START] |
mov edx,[ROOT_SECTORS] |
mov [fat16_root],1 ; flag for fat16 rootdir |
jmp adw_new_sector |
adw_data_cluster: |
sub eax,2 |
mov edx,[SECTORS_PER_CLUSTER] |
imul eax,edx |
add eax,[DATA_START] |
adw_new_sector: |
mov ebx,buffer |
call hd_read |
mov ecx,512/32 ; count of dir entrys per sector = 16 |
adw_analyze: |
cmp byte [ebx],0x00 ; is free entry? |
je adw_found ; yes |
cmp byte [ebx],0xe5 ; is deleted entry? |
je adw_found ; yes |
add ebx,32 ; position of next dir entry |
dec ecx |
jnz adw_analyze |
inc eax ; next sector |
dec edx |
jne adw_new_sector |
cmp [fat16_root],1 ; end of fat16 rootdir |
je adw_not_found |
mov eax,[cluster_tmp] |
call get_FAT ; get next cluster |
cmp eax,2 ; incorrect fat chain? |
jb adw_not_found ; yes |
cmp eax,[fatRESERVED] ; is it end of directory? |
jb adw_new_cluster ; no. analyse it |
mov eax,2 ; this block of code add a new cluster |
call get_free_FAT ; for the directory because the directory |
jc adw_not_found ; is full |
mov edx,[fatEND] ; new end for directory |
call set_FAT |
push eax ; save new cluster |
mov edx,eax |
mov eax,[cluster_tmp] ; change last cluster to point new cluster |
mov [f_del],1 |
call set_FAT |
mov [f_del],0 |
mov ecx,-1 ; remove 1 cluster from free disk space |
call add_disk_free_space |
mov ecx,512/4 |
xor eax,eax |
mov edi,buffer |
cld |
rep stosd ; clear new directory cluster |
pop eax |
sub eax,2 |
mov ecx,[SECTORS_PER_CLUSTER] |
imul eax,ecx |
add eax,[DATA_START] |
mov ebx,buffer |
push eax ; save sector number |
adw_set_empty_directory: |
call hd_write |
inc eax ; next sector |
dec ecx |
jnz adw_set_empty_directory |
pop eax |
adw_found: |
pop edi edx ecx |
clc ; free space found |
ret |
adw_not_found: |
pop edi edx ecx |
stc ; free space not 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 [fat_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 |
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 |
set_data_cluster: |
;----------------------------------------------------------- |
; input : EAX = cluster |
; EBX = pointer to buffer |
; output : if CARRY=0 ok |
; if CARRY=1 cluster out of range |
;----------------------------------------------------------- |
push eax ebx edx |
cmp eax,[LAST_CLUSTER] |
ja sdc_error ; too big cluster number, something is wrong |
sub eax,2 |
jb sdc_error ; don't allow rootdir write |
mov edx,[SECTORS_PER_CLUSTER] |
imul eax,edx |
add eax,[DATA_START] |
sdc_write: |
call hd_write |
add ebx,512 ; update pointer |
inc eax |
dec edx |
jnz sdc_write |
pop edx ebx eax |
clc |
ret |
sdc_error: |
pop edx ebx 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 |
makedir: |
;----------------------------------------------------- |
; input : eax = directory name |
; edx = path |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 8 - disk full |
; 10 - access denied |
; Note : can only make one directory at time |
;----------------------------------------------------- |
cmp [fat_type],0 |
jnz make_dir_fat_ok |
mov eax,ERROR_UNKNOWN_FS |
ret |
make_dir_fat_ok: |
; call reserve_hd1 |
pushad |
mov ebx,edx |
call get_cluster_of_a_path |
jnc make_dir_found_path |
make_dir_path_not_found: |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
make_dir_disk_full: |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
mov eax,ERROR_DISK_FULL |
ret |
make_dir_already_exist: |
mov eax,[cluster] ; directory cluster |
xor edx,edx ; free |
mov [f_del],1 |
call set_FAT |
mov [f_del],0 |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
mov eax,ERROR_ACCESS_DENIED |
ret |
make_dir_found_path: |
cmp eax,[ROOT_CLUSTER] |
jnz make_dir_not_root |
xor eax,eax |
make_dir_not_root: |
mov ecx,eax ; directorys start cluster |
mov word [NewDirEntry2+26],cx ; 16 bits low of cluster |
shr ecx,16 |
mov word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16) |
push eax ; save parent directory cluster |
mov eax,2 |
call get_free_FAT |
mov [cluster],eax ; first free cluster |
pop eax |
jc make_dir_disk_full |
push eax |
mov eax,[cluster] ; directory cluster |
mov edx,[fatEND] ; end for directory |
call set_FAT |
pop eax |
mov ebx,PUSHAD_EAX ; dir name |
push eax |
call analyze_directory ; check if directory already exist |
pop eax |
jnc make_dir_already_exist ; need to free allocated cluster! |
call analyze_directory_to_write |
jc make_dir_already_exist ; need to free allocated cluster! |
mov esi,PUSHAD_EAX ; dir name |
mov edi,ebx ; pointer in buffer |
mov ecx,11 |
cld |
rep movsb |
mov dword [ebx+28],0 ; dir size is always 0 |
mov ecx,[cluster] |
mov [ebx+26],cx ; 16 bits low of cluster |
mov word [NewDirEntry1+26],cx |
shr ecx,16 |
mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16) |
mov word [NewDirEntry1+20],cx |
mov byte [ebx+11],0x10 ; attribute = directory |
call set_current_time_for_entry |
mov ecx,[ebx+22] |
mov dword [NewDirEntry1+22],ecx |
mov dword [NewDirEntry2+22],ecx |
mov ebx,buffer ; save the directory name,length,cluster |
call hd_write |
mov ecx,512/4 |
xor eax,eax |
mov edi,buffer |
cld |
rep stosd ; clear new directory cluster |
mov eax,[cluster] ; new directory cluster |
sub eax,2 |
mov edx,[SECTORS_PER_CLUSTER] |
imul eax,edx |
add eax,[DATA_START] |
mov ebx,buffer |
add eax,edx ; start from last sector |
dir_set_empty_directory: |
dec eax ; next sector |
cmp edx,1 ; is first directory sector? |
jnz not_first_sector ; no. write empty sector |
mov esi,NewDirEntry1 |
mov edi,buffer |
mov ecx,64/4 |
cld |
rep movsd ; copy 2 first directory entrys "." and ".." |
not_first_sector: |
call hd_write |
dec edx |
jnz dir_set_empty_directory |
mov ecx,-1 ; remove 1 cluster from free disk space |
call add_disk_free_space |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
xor eax,eax |
ret |
removedir: |
;----------------------------------------------------- |
; input : eax = file/directory name |
; edx = path |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 10 - access denied |
;----------------------------------------------------- |
cmp [fat_type],0 |
jnz remove_dir_fat_ok |
mov eax,ERROR_UNKNOWN_FS |
ret |
remove_dir_fat_ok: |
; call reserve_hd1 |
push edi |
mov edi,1 ; allow directory remove |
call file_delete |
pop edi |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
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 [fat_type],32 ; free disk space only used by fat32 |
jne add_dfs_no |
push eax ebx |
mov eax,[ADR_FSINFO] |
mov ebx,buffer |
call hd_read |
cmp dword [ebx+0x1fc],0xaa550000 ; check sector id |
jne add_not_fs |
add [ebx+0x1e8],ecx |
call hd_write |
add_not_fs: |
pop ebx eax |
add_dfs_no: |
ret |
file_append: |
;----------------------------------------------------- |
; input : eax = file name |
; edx = path |
; ecx = pointer to buffer |
; ebx = bytes to write (0 = truncate file) |
; esi = start position (-1 = end of file) |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 6 - end of file |
; 8 - disk full |
; 9 - fat table corrupted |
; 10 - access denied |
; ebx = bytes written |
;----------------------------------------------------- |
cmp [fat_type],0 |
jnz append_fat_ok |
mov eax,ERROR_UNKNOWN_FS |
ret |
append_fat_ok: |
; call reserve_hd1 |
pushad |
mov ebx,edx |
call get_cluster_of_a_path |
jc append_not_found |
mov ebx,PUSHAD_EAX ; file name |
call analyze_directory |
jc append_not_found |
mov [sector_tmp],eax |
mov [entry_pos],ebx |
test byte [ebx+11],0x10 ; is it directory? |
jnz append_access ; yes |
mov ecx,[ebx+28] ; file size |
mov edi,PUSHAD_ESI ; write position |
cmp edi,-1 ; -1 = eof |
jnz append_inside_file |
mov edi,ecx ; file size |
append_inside_file: |
cmp edi,ecx ; start above old file size? |
ja append_eof ; yes |
mov [old_filesize],ecx |
mov [new_filepos],edi |
mov ecx,PUSHAD_EBX ; bytes to write |
test ecx,ecx ; truncate? |
jz append_truncate ; yes |
mov [bytes2write],ecx ; bytes to write |
mov esi,PUSHAD_ECX ; pointer to buffer |
mov eax,[ebx+20-2] ; FAT entry |
mov ax,[ebx+26] |
and eax,[fatMASK] |
jnz append_find_pos ; first cluster <> 0 |
mov eax,2 |
call get_free_FAT |
jc append_disk_full |
mov ecx,eax ; set files first cluster |
mov [ebx+26],cx ; 16 bits low of cluster |
shr ecx,16 |
mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16) |
mov edx,[fatEND] ; new end for cluster chain |
call set_FAT |
push eax ; save first cluster |
mov eax,[sector_tmp] |
mov ebx,buffer |
call hd_write ; write new file entry back to disk |
pop eax |
append_remove_free: |
mov ecx,-1 ; remove 1 cluster from free disk space |
call add_disk_free_space ; Note: uses buffer |
append_found_cluster: |
mov [cluster],eax |
sub eax,2 |
mov ecx,[SECTORS_PER_CLUSTER] |
imul eax,ecx |
add eax,[DATA_START] |
xor edi,edi |
append_new_sector: |
push ecx |
mov ecx,[bytes2write] ; bytes left in buffer |
mov ebx,512 |
sub ebx,edi ; bytes left in sector |
cmp ecx,ebx |
jb append_bytes_ok |
mov ecx,ebx |
append_bytes_ok: |
cmp ecx,512 ; overwrite full sector? |
jz append_full_sector ; yes |
mov ebx,buffer ; overwrite part of sector |
call hd_read ; read old sector |
append_full_sector: |
sub [bytes2write],ecx |
add [new_filepos],ecx |
add edi,buffer |
cld |
rep movsb |
pop ecx |
mov ebx,buffer |
call hd_write |
cmp [bytes2write],0 ; is all done? |
jz append_done |
xor edi,edi |
inc eax |
dec ecx |
jnz append_new_sector |
mov eax,[cluster] |
call get_FAT |
cmp eax,2 |
jb append_fat |
cmp eax,[LAST_CLUSTER] |
jbe append_found_cluster |
append_alloc_cluster: |
mov eax,2 ; ToDo: use temp array to keep track |
call get_free_FAT ; of last free cluster |
jc append_disk_full |
push eax ; save new cluster |
mov edx,[fatEND] ; new end for cluster chain |
call set_FAT |
mov edx,eax |
mov eax,[cluster] |
mov [f_del],1 |
call set_FAT ; update previous cluster |
mov [f_del],0 |
pop eax |
jmp append_remove_free |
append_find_pos: |
call find_filepos |
mov [cluster],ebx |
jnc append_new_sector |
test edi,edi |
jz append_alloc_cluster |
append_fat: |
mov eax,ERROR_FAT_TABLE |
jmp append_ret_code |
append_disk_full: |
mov eax,ERROR_DISK_FULL |
jmp append_ret_code |
append_done: |
xor eax,eax |
append_ret_code: |
mov PUSHAD_EAX,eax ; return code |
mov eax,[sector_tmp] ; update directory entry |
mov ebx,buffer |
call hd_read |
mov ebx,[entry_pos] |
mov ecx,[new_filepos] |
cmp ecx,[old_filesize] ; is file pos above old size? |
jbe append_size_ok ; no |
mov [ebx+28],ecx ; new file size |
append_size_ok: |
call set_current_time_for_entry |
mov ebx,buffer |
call hd_write ; write new file entry back to disk |
sub ecx,PUSHAD_ESI ; start position |
mov PUSHAD_EBX,ecx ; bytes written |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
ret |
append_eof: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_END_OF_FILE |
ret |
append_not_found: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
append_access: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_ACCESS_DENIED |
ret |
append_truncate: |
mov edx,[ebx+20-2] ; FAT entry |
mov dx,[ebx+26] |
and edx,[fatMASK] |
mov [ebx+28],edi ; set new file size |
test edi,edi ; 0 length file? |
jnz truncate_save_size ; no |
mov [ebx+20],di ; FAT entry = 0 |
mov [ebx+26],di |
truncate_save_size: |
call set_current_time_for_entry |
mov ebx,buffer |
call hd_write |
mov eax,edx ; first cluster |
test edi,edi ; 0 length file? |
jz truncate_clear_chain |
imul esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes |
truncate_new_cluster: |
cmp eax,2 ; incorrect fat chain? |
jb truncate_eof ; yes |
cmp eax,[fatRESERVED] ; is it end of file? |
jnb truncate_eof ; yes |
sub edi,esi |
jbe truncate_pos_found |
call get_FAT ; get next cluster |
jmp truncate_new_cluster |
truncate_pos_found: |
mov edx,[fatEND] ; new end for cluster chain |
mov [f_del],1 |
call set_FAT |
mov [f_del],0 |
mov eax,edx ; clear rest of chain |
truncate_clear_chain: |
call clear_cluster_chain |
truncate_eof: |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
xor ebx,ebx |
xor eax,eax |
ret |
find_filepos: |
;----------------------------------------------------- |
; input : eax = first cluster |
; edi = bytes to skip over (start position) |
; output : if CARRY=0 file position found |
; if CARRY=1 end of file found |
; eax = current file sector |
; ebx = last cluster |
; ecx = sector count in last cluster |
; edi = bytes to skip over (sector position) |
;----------------------------------------------------- |
push esi |
mov ecx,[SECTORS_PER_CLUSTER] |
imul esi,ecx,512 ; esi = cluster size in bytes |
mov ebx,eax |
filepos_new_cluster: |
cmp eax,2 ; incorrect fat chain? |
jb filepos_eof ; yes |
cmp eax,[fatRESERVED] ; is it end of file? |
jnb filepos_eof ; yes |
mov ebx,eax |
cmp edi,esi ; skip over full cluster? |
jb filepos_cluster_ok ; no |
sub edi,esi |
call get_FAT ; get next cluster |
jmp filepos_new_cluster |
filepos_cluster_ok: |
sub eax,2 |
imul eax,ecx |
add eax,[DATA_START] |
filepos_new_sector: |
cmp edi,512 ; skip over full sector? |
jb filepos_sector_ok ; no |
sub edi,512 |
inc eax |
dec ecx |
jnz filepos_new_sector |
filepos_eof: |
pop esi |
stc |
ret |
filepos_sector_ok: |
pop esi |
clc |
ret |
file_write: |
;-------------------------------------------------------------------------- |
; INPUT : user-reg register-in-this meaning symbol-in-this-routine |
; |
; EAX EDI system call to write / |
; EBX EAX (PAR0) pointer to file-name PAR0 |
; EDX ECX (PAR1) pointer to buffer PAR1 |
; ECX EBX (PAR2) file size PAR2 |
; ESI EDX (PAR3) pointer to path PAR3 |
; |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 8 - disk full |
; 10 - access denied |
;-------------------------------------------------------------------------- |
cmp [fat_type],0 |
jnz fat_ok_for_writing |
mov eax,ERROR_UNKNOWN_FS |
ret |
fat_ok_for_writing: |
; call reserve_hd1 |
pushad |
xor edi,edi ; don't allow directory remove |
call file_delete ; try to delete the file first |
test eax,eax |
jz old_deleted ; deleted ok |
cmp eax,ERROR_FILE_NOT_FOUND |
jnz exit_write_access ; it exist but can't delete |
old_deleted: |
mov ebx,PUSHAD_EDX |
call get_cluster_of_a_path |
jnc found_directory_for_writing |
exit_writing_with_error: |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
exit_writing_disk_full_clear: |
mov eax,[sector_tmp] |
mov ebx,buffer |
call hd_read ; read directory sector |
mov edx,[entry_pos] |
mov byte [edx],0xe5 ; mark as deleted |
call hd_write |
mov eax,[edx+20-2] ; FAT entry |
mov ax,[edx+26] |
and eax,[fatMASK] |
call clear_cluster_chain |
exit_writing_disk_full: |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
mov eax,ERROR_DISK_FULL |
ret |
exit_write_access: |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
mov eax,ERROR_ACCESS_DENIED |
ret |
found_directory_for_writing: |
call analyze_directory_to_write |
jc exit_writing_disk_full |
mov [sector_tmp],eax |
mov [entry_pos],ebx |
push eax ; save directory sector |
mov eax,2 |
call get_free_FAT |
mov [cluster],eax ; first free cluster |
pop eax |
jc exit_writing_disk_full |
mov esi,PUSHAD_EAX ; file name |
mov edi,ebx ; pointer in buffer |
mov ecx,11 |
cld |
rep movsb |
mov esi,PUSHAD_EBX ; file size (bytes left) |
mov [ebx+28],esi ; file size |
mov ecx,[cluster] |
mov [ebx+26],cx ; 16 bits low of cluster |
shr ecx,16 |
mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16) |
mov byte [ebx+11],0x20 ; attribute = archive |
call set_current_time_for_entry |
mov ebx,buffer ; save the directory name,length,cluster |
call hd_write |
imul edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes |
xor ecx,ecx ; cluster count |
mov ebx,PUSHAD_ECX ; ebx = buffer |
hd_new_block_write: |
mov eax,[cluster] ; eax = block |
call set_data_cluster |
sub esi,edi ; sub wrote bytes |
jbe file_saved_OK ; end if all done |
add ebx,edi ; update buffer position |
inc eax |
call get_free_FAT ; next free in FAT |
jc exit_writing_disk_full_clear |
mov edx,eax |
xchg eax,[cluster] ; get old cluster and save new cluster |
call set_FAT ; add it in cluster chain |
dec ecx ; update cluster count |
jmp hd_new_block_write |
file_saved_OK: |
mov edx,[fatEND] ; new end for cluster chain |
call set_FAT |
dec ecx ; update cluster count |
call add_disk_free_space ; remove clusters from free disk space |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
xor eax,eax |
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 |
; ebx = size of file/directory |
;-------------------------------------------------------------------------- |
cmp [fat_type],0 |
jnz fat_ok_for_reading |
xor ebx,ebx |
mov eax,ERROR_UNKNOWN_FS |
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 |
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 |
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 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: |
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: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_FILE_NOT_FOUND |
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 [fat_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 |
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 |
file_delete: |
;----------------------------------------------------- |
; input : eax = file/directory name |
; edx = path |
; edi = 1 - allow directory remove else don't remove directory |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 10 - access denied |
;----------------------------------------------------- |
cmp [fat_type],0 |
jnz file_del_fat_ok |
mov eax,ERROR_UNKNOWN_FS |
ret |
file_del_fat_ok: |
pushad |
mov ebx,edx |
call get_cluster_of_a_path |
jc file_to_delete_not_found |
mov ebx,PUSHAD_EAX ; file/directory name |
call analyze_directory |
jc file_to_delete_not_found |
test byte [ebx+11],0x10 ; is it directory? |
jz delete_notdir ; no. it's file |
cmp edi,1 ; allow directory remove |
jnz delete_no_access ; no |
push eax ; save directory sector |
mov eax,[ebx+20-2] ; first cluster of file |
mov ax,[ebx+26] ; 0 length files start cluster = 0 |
and eax,[fatMASK] |
xor ebp,ebp ; counter for directory deepnes |
call clear_directory |
pop eax |
jc delete_no_access |
push ebx ; save directory pointer in buffer |
mov ebx,buffer |
call hd_read ; read directory sector |
pop ebx |
delete_notdir: |
call delete_entry_name |
mov eax,ecx ; first cluster of file |
call clear_cluster_chain |
popad |
xor eax,eax |
ret |
delete_no_access: |
popad |
mov eax,ERROR_ACCESS_DENIED |
ret |
file_to_delete_not_found: |
popad |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
clear_cluster_chain: |
;----------------------------------------------------- |
; input : eax = first cluster |
;----------------------------------------------------- |
push eax ecx edx |
xor ecx,ecx ; cluster count |
mov [f_del],1 ; delete on |
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 |
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 |
mov [f_del],0 |
pop edx ecx eax |
ret |
clear_directory: |
;----------------------------------------------------- |
; input : eax = directory cluster |
; ebp = directory deepnes |
; Note : use recursive call |
;----------------------------------------------------- |
pushad |
inc ebp |
cmp ebp,64 ; if over 63 directory deep |
jnb clear_error ; something must be wrong |
clear_new_cluster: |
cmp eax,[LAST_CLUSTER] |
ja clear_end |
cmp eax,[ROOT_CLUSTER] ; don't remove root cluster |
jz clear_end |
mov esi,eax ; esi = current directory cluster |
sub eax,2 |
jb clear_end |
mov ecx,[SECTORS_PER_CLUSTER] |
imul eax,ecx |
add eax,[DATA_START] |
clear_new_sector: |
mov edi,eax ; edi = current directory sector |
mov ebx,deltree_buffer |
call hd_read |
mov edx,512/32 ; count of dir entrys per sector = 16 |
clear_analyze: |
mov al,[ebx+11] ; file attribute |
and al,0xf |
cmp al,0xf |
je clear_long_filename |
cmp byte [ebx],'.' ; parent or current directory |
je clear_next_entry |
cmp byte [ebx],0xe5 ; deleted |
je clear_next_entry |
cmp byte [ebx],0 ; empty |
je clear_write_last |
;je clear_next_entry |
mov eax,[ebx+20-2] ; first cluster of entry |
mov ax,[ebx+26] |
and eax,[fatMASK] |
test byte [ebx+11],0x10 ; is it directory? |
jz clear_file ; no |
push eax ebx |
mov eax,edi |
mov ebx,deltree_buffer ; save buffer over recursive call |
call hd_write ; write directory sector to disk |
pop ebx eax |
call clear_directory ; recursive call !!! |
jc clear_error ; exit if error found |
push eax ebx |
mov eax,edi |
mov ebx,deltree_buffer |
call hd_read ; read directory sector again |
pop ebx eax |
clear_file: |
call clear_cluster_chain |
clear_long_filename: |
mov byte [ebx],0xe5 |
clear_next_entry: |
add ebx,32 ; position of next dir entry |
dec edx |
jnz clear_analyze |
mov eax,edi |
mov ebx,deltree_buffer |
call hd_write ; write directory sector to disk |
inc eax ; next sector |
dec ecx |
jnz clear_new_sector |
mov eax,esi |
call get_FAT ; get next cluster |
jmp clear_new_cluster ; clear it |
clear_write_last: |
mov eax,edi |
mov ebx,deltree_buffer |
call hd_write ; write directory sector to disk |
clear_end: |
popad |
clc |
ret |
clear_error: |
popad |
stc |
ret |
delete_entry_name: |
;----------------------------------------------------- |
; input : eax = directory sector |
; ebx = directory pointer in buffer |
; longname_sec = 2 previous directory sectors |
; output : ecx = first cluster |
; change : eax,ebx,edx |
;----------------------------------------------------- |
mov byte [ebx],0xe5 |
mov ecx,[ebx+20-2] ; first cluster of file |
mov cx,[ebx+26] ; 0 length files start cluster = 0 |
and ecx,[fatMASK] |
delete_empty: |
sub ebx,32 |
cmp ebx,buffer |
jnb delete_test_long |
mov ebx,buffer |
call hd_write ; write directory sector back |
xor eax,eax |
xchg eax,[longname_sec2] |
xchg eax,[longname_sec1] |
test eax,eax ; is there previous directory sector? |
jz delete_name_end ; no |
mov ebx,buffer |
call hd_read ; read previous sector |
mov ebx,buffer+0x1e0 ; start from last entry |
delete_test_long: |
mov dh,[ebx+11] ; file attribute |
and dh,0xf |
cmp dh,0xf |
jne delete_write_buffer |
cmp byte [ebx],0x40 ; end of long dir entry? |
mov byte [ebx],0xe5 |
jb delete_empty |
delete_write_buffer: |
mov ebx,buffer |
call hd_write ; write directory sector back |
delete_name_end: |
ret |
rename: |
;----------------------------------------------------------- |
; input : eax = source directory name |
; edx = source path |
; ebx = dest directory name |
; edi = dest path |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 8 - disk full |
; 10 - access denied |
;----------------------------------------------------------- |
cmp [fat_type],0 |
jnz fat_ok_for_rename |
mov eax,ERROR_UNKNOWN_FS |
ret |
fat_ok_for_rename: |
; call reserve_hd1 |
pushad |
mov ebx,edx ; source path |
call get_cluster_of_a_path |
jc rename_entry_not_found |
mov ebx,PUSHAD_EAX ; source directory name |
call analyze_directory |
jc rename_entry_not_found |
mov [sector_tmp],eax ; save source sector |
mov [entry_pos],ebx |
mov esi,ebx |
mov edi,dir_entry |
mov ecx,32/4 |
cld |
rep movsd ; save entry |
mov ebx,PUSHAD_EDI ; dest path |
call get_cluster_of_a_path |
jc rename_entry_not_found |
mov edx,eax ; save dest directory cluster |
mov ebx,PUSHAD_EBX ; dest directory name |
push [longname_sec1] |
push [longname_sec2] |
call analyze_directory ; check if entry already exist |
pop [longname_sec2] |
pop [longname_sec1] |
jnc rename_entry_already_exist |
mov eax,edx |
call analyze_directory_to_write |
jc rename_disk_full |
mov esi,dir_entry |
mov edi,ebx |
mov ecx,32/4 |
cld |
rep movsd ; copy entry |
mov esi,PUSHAD_EBX ; dest directory name |
mov edi,ebx |
mov ecx,11 |
rep movsb ; copy name |
mov ebx,buffer ; save the directory name,length,cluster |
call hd_write |
test byte [dir_entry+11],0x10 ; is it directory? |
jz rename_not_dir ; no |
mov eax,[dir_entry+20-2] ; FAT entry |
mov ax,[dir_entry+26] |
and eax,[fatMASK] |
call change_2dot_cluster |
rename_not_dir: |
mov eax,[sector_tmp] |
mov ebx,buffer |
call hd_read ; read source directory sector |
mov ebx,[entry_pos] |
call delete_entry_name |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
xor eax,eax |
ret |
rename_entry_not_found: |
popad |
mov [hd1_status],0 |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
rename_entry_already_exist: |
popad |
mov [hd1_status],0 |
mov eax,ERROR_ACCESS_DENIED |
ret |
rename_disk_full: |
popad |
mov [hd1_status],0 |
mov eax,ERROR_DISK_FULL |
ret |
change_2dot_cluster: |
;----------------------------------------------------------- |
; input : eax = directory cluster |
; edx = value to save |
; change : eax,ebx,edx |
;----------------------------------------------------------- |
cmp eax,[LAST_CLUSTER] |
ja not_2dot ; too big cluster number, something is wrong |
sub eax,2 |
jb not_2dot |
imul eax,[SECTORS_PER_CLUSTER] |
add eax,[DATA_START] |
mov ebx,buffer |
call hd_read |
cmp dword [ebx+32],'.. ' |
jnz not_2dot |
cmp edx,[ROOT_CLUSTER] ; is rootdir cluster? |
jne not_2dot_root |
xor edx,edx ; yes. set it zero |
not_2dot_root: |
mov [ebx+32+26],dx ; 16 bits low of cluster |
shr edx,16 |
mov [ebx+32+20],dx ; 16 bits high of cluster (=0 fat16) |
call hd_write |
not_2dot: |
ret |
get_filesize: |
;----------------------------------------------------------- |
; input : eax = file name |
; edx = path |
; edi = if 0 - read rootdir else normal dir/file size |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; ebx = file size |
;----------------------------------------------------------- |
cmp [fat_type],0 |
jnz get_filesize_fat_ok |
xor ebx,ebx |
mov eax,ERROR_UNKNOWN_FS |
ret |
get_filesize_fat_ok: |
; call reserve_hd1 |
pushad |
xor eax,eax |
test edi,edi ; is read rootdir? |
je get_filesize_dirsize ; yes |
get_filesize_no_root: |
mov ebx,edx |
call get_cluster_of_a_path |
jc get_filesize_not_found |
mov ebx,PUSHAD_EAX ; file name |
call analyze_directory |
jc get_filesize_not_found |
mov eax,[ebx+28] ; file size |
test byte [ebx+11],0x10 ; is it directory? |
jz get_filesize_set_size ; no |
mov eax,[ebx+20-2] ; FAT entry |
mov ax,[ebx+26] |
and eax,[fatMASK] |
get_filesize_dirsize: |
call get_dir_size |
get_filesize_set_size: |
mov PUSHAD_EBX,eax |
popad |
mov [hd1_status],0 |
xor eax,eax |
ret |
get_filesize_not_found: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
get_fileattr: |
;----------------------------------------------------------- |
; input : eax = file name |
; edx = path |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; ebx = file attribute |
;----------------------------------------------------------- |
cmp [fat_type],0 |
jnz get_fileattr_fat_ok |
xor ebx,ebx |
mov eax,ERROR_UNKNOWN_FS |
ret |
get_fileattr_fat_ok: |
; call reserve_hd1 |
pushad |
mov ebx,edx |
call get_cluster_of_a_path |
jc get_fileattr_not_found |
mov ebx,PUSHAD_EAX ; file name |
call analyze_directory |
jc get_fileattr_not_found |
movzx eax,byte [ebx+11] ; file attribute |
mov PUSHAD_EBX,eax |
popad |
mov [hd1_status],0 |
xor eax,eax |
ret |
get_fileattr_not_found: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
get_filedate: |
;----------------------------------------------------------- |
; input : eax = file name |
; edx = path |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; ebx = file date/time |
; bits 31..25 = year-1980 |
; bits 24..21 = month |
; bits 20..16 = day |
; bits 15..11 = hour |
; bits 10..5 = minute |
; bits 4..0 = second/2 |
;----------------------------------------------------------- |
cmp [fat_type],0 |
jnz get_filedate_fat_ok |
xor ebx,ebx |
mov eax,ERROR_UNKNOWN_FS |
ret |
get_filedate_fat_ok: |
; call reserve_hd1 |
pushad |
mov ebx,edx |
call get_cluster_of_a_path |
jc get_filedate_not_found |
mov ebx,PUSHAD_EAX ; file name |
call analyze_directory |
jc get_filedate_not_found |
mov eax,[ebx+22] ; file date/time |
mov PUSHAD_EBX,eax |
popad |
mov [hd1_status],0 |
xor eax,eax |
ret |
get_filedate_not_found: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
get_hd_info: |
;----------------------------------------------------------- |
; output : eax = 0 - ok |
; 3 - unknown FS |
; edx = cluster size in bytes |
; ebx = total clusters on disk |
; ecx = free clusters on disk |
;----------------------------------------------------------- |
cmp [fat_type],0 |
jnz 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 |
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 |
update_disk: |
;----------------------------------------------------------- |
; write changed fat and cache to disk |
;----------------------------------------------------------- |
cmp [fat_change],0 ; is fat changed? |
je upd_no_change |
call write_fat_sector |
upd_no_change: |
call write_cache |
ret |
;************************************************************************** |
; |
; 0x600008 - first entry in cache list |
; |
; +0 - lba sector |
; +4 - state of cache sector |
; 0 = empty |
; 1 = used for read ( same as in hd ) |
; 2 = used for write ( differs from hd ) |
; |
; +65536 - cache entries |
; |
;************************************************************************** |
hd_read: |
;----------------------------------------------------------- |
; input : eax = block to read |
; ebx = destination |
;----------------------------------------------------------- |
push ecx esi edi ; scan cache |
mov ecx,cache_max ; entries in cache |
mov esi,0x600000+8 |
mov edi,1 |
hdreadcache: |
cmp dword [esi+4],0 ; empty |
je nohdcache |
cmp [esi],eax ; correct sector |
je yeshdcache |
nohdcache: |
add esi,8 |
inc edi |
dec ecx |
jnz hdreadcache |
call find_empty_slot ; ret in edi |
call wait_for_hd_idle |
push eax edx |
cli |
xor eax,eax |
mov edx,[hdbase] |
inc edx |
out dx,al ; ATAFeatures ðåãèñòð "îñîáåííîñòåé" |
inc edx |
inc eax |
out dx,al ; ATASectorCount ñ÷åò÷èê ñåêòîðîâ |
inc edx |
mov eax,[esp+4] |
out dx,al ; ATASectorNumber ðåãèñòð íîìåðà ñåêòîðà |
shr eax,8 |
inc edx |
out dx,al ; ATACylinder íîìåð öèëèíäðà (ìëàäøèé áàéò) |
shr eax,8 |
inc edx |
out dx,al ; íîìåð öèëèíäðà (ñòàðøèé áàéò) |
shr eax,8 |
inc edx |
and al,1+2+4+8 |
add al,byte [hdid] |
add al,128+64+32 |
out dx,al ; íîìåð ãîëîâêè/íîìåð äèñêà |
inc edx |
mov al,20h |
out dx,al ; ATACommand ðåãèñòð êîìàíä |
sti |
call wait_for_sector_buffer |
cmp [hd_error],0 |
jne hd_read_error |
cli |
push edi |
shl edi,9 |
add edi,0x600000+65536 |
mov ecx,256 |
mov edx,[hdbase] |
cld |
rep insw |
pop edi |
sti |
pop edx eax |
blok_read_2: |
lea esi,[edi*8+0x600000] |
mov [esi],eax ; sector number |
mov dword [esi+4],1 ; hd read - mark as same as in hd |
yeshdcache: |
mov esi,edi |
shl esi,9 |
add esi,0x600000+65536 |
mov edi,ebx |
mov ecx,512/4 |
cld |
rep movsd ; move data |
; blok_read_2: |
pop edi esi ecx |
ret |
hd_write: |
;----------------------------------------------------------- |
; input : eax = block |
; ebx = pointer to memory |
;----------------------------------------------------------- |
push ecx esi edi |
; check if the cache already has the sector and overwrite it |
mov ecx,cache_max |
mov esi,0x600000+8 |
mov edi,1 |
hdwritecache: |
cmp dword [esi+4],0 ; if cache slot is empty |
je not_in_cache_write |
cmp [esi],eax ; if the slot has the sector |
je yes_in_cache_write |
not_in_cache_write: |
add esi,8 |
inc edi |
dec ecx |
jnz hdwritecache |
; sector not found in cache |
; write the block to a new location |
call find_empty_slot ; ret in edi |
lea esi,[edi*8+0x600000] |
mov [esi],eax ; sector number |
yes_in_cache_write: |
mov dword [esi+4],2 ; write - differs from hd |
shl edi,9 |
add edi,0x600000+65536 |
mov esi,ebx |
mov ecx,512/4 |
cld |
rep movsd ; move data |
pop edi esi ecx |
ret |
write_cache: |
;----------------------------------------------------------- |
; write all changed sectors to disk |
;----------------------------------------------------------- |
push eax ecx edx esi edi |
; write difference ( 2 ) from cache to hd |
mov ecx,cache_max |
mov esi,0x600000+8 |
mov edi,1 |
write_cache_more: |
cmp dword [esi+4],2 ; if cache slot is not different |
jne does_not_need_writing |
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 |
call wait_for_hd_idle |
cli |
xor eax,eax |
mov edx,[hdbase] |
inc edx |
out dx,al |
inc edx |
inc eax |
out dx,al |
inc edx |
mov eax,[esi] ; eax = sector to write |
out dx,al |
shr eax,8 |
inc edx |
out dx,al |
shr eax,8 |
inc edx |
out dx,al |
shr eax,8 |
inc edx |
and al,1+2+4+8 |
add al,byte [hdid] |
add al,128+64+32 |
out dx,al |
inc edx |
mov al,30h |
out dx,al |
sti |
call wait_for_sector_buffer |
cmp [hd_error],0 |
jne hd_write_error |
push ecx esi |
cli |
mov esi,edi |
shl esi,9 |
add esi,0x600000+65536 ; esi = from memory position |
mov ecx,256 |
mov edx,[hdbase] |
cld |
rep outsw |
sti |
pop esi ecx |
danger: |
does_not_need_writing: |
add esi,8 |
inc edi |
dec ecx |
jnz write_cache_more |
pop edi esi edx ecx eax |
ret |
find_empty_slot: |
;----------------------------------------------------------- |
; find empty or read slot, flush cache if next 10% is used by write |
; output : edi = cache slot |
;----------------------------------------------------------- |
push ecx esi |
search_again: |
mov ecx,cache_max*10/100 |
mov edi,[cache_search_start] |
search_for_empty: |
inc edi |
cmp edi,cache_max |
jbe inside_cache |
mov edi,1 |
inside_cache: |
cmp dword [edi*8+0x600000+4],2 ; get cache slot info |
jb found_slot ; it's empty or read |
dec ecx |
jnz search_for_empty |
call write_cache ; no empty slots found, write all |
jmp search_again ; and start again |
found_slot: |
mov [cache_search_start],edi |
pop esi ecx |
ret |
save_hd_wait_timeout: |
push eax |
mov eax,[timer_ticks];[0xfdf0] |
add eax,300 ; 3 sec timeout |
mov [hd_wait_timeout],eax |
pop eax |
ret |
check_hd_wait_timeout: |
push eax |
mov eax,[hd_wait_timeout] |
cmp [timer_ticks], eax ;[0xfdf0],eax |
jg hd_timeout_error |
pop eax |
ret |
iglobal |
hd_timeout_str db 'K : FS - HD timeout',13,10,0 |
hd_read_str db 'K : FS - HD read error',13,10,0 |
hd_write_str db 'K : FS - HD write error',13,10,0 |
endg |
hd_timeout_error: |
call clear_hd_cache |
call clear_application_table_status |
mov esi,hd_timeout_str |
call sys_msg_board_str |
jmp $ |
hd_read_error: |
call clear_hd_cache |
call clear_application_table_status |
mov esi,hd_read_str |
call sys_msg_board_str |
jmp $ |
hd_write_error: |
call clear_hd_cache |
call clear_application_table_status |
mov esi,hd_write_str |
call sys_msg_board_str |
jmp $ |
wait_for_hd_idle: |
push eax edx |
call save_hd_wait_timeout |
mov edx,[hdbase] |
add edx,0x7 |
wfhil1: |
call check_hd_wait_timeout |
in al,dx |
test al,128 |
jnz wfhil1 |
pop edx eax |
ret |
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 |
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 |
read_hd_file: |
;----------------------------------------------------------------- |
; |
; Converting old reading function for hd-application start. |
; |
; IN: |
; |
; eax - pointer to file (0 = read only first sector of drive: eg 'label') |
; 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) |
; |
; For new read function |
; |
; EAX (PAR0) pointer to file-name |
; ECX (PAR1) pointer to buffer |
; EBX (PAR2) vt file blocks to read |
; EDX (PAR3) pointer to path |
; ESI vt first 512 block to read |
; EDI if 0 - return root |
;-------------------------------------------------------------------------- |
push ecx esi edi |
mov esi,eax |
mov edi,startpath |
mov ecx,250 |
cld |
rep movsb |
pop edi esi ecx |
mov eax,startpath |
mov [eax+ebx-12],byte 0 |
push eax ebx ecx edx esi |
pop ecx ; pointer to buffer |
add ecx,1024 |
pop ebx ; number of blocks to read |
pop esi ; first block to read |
dec esi |
pop eax ; file length |
pop edx ; pointer to path |
mov edi,12 |
lea eax,[eax+edx-12+1] |
call file_read |
ret |
/kernel/trunk/fs/fs.inc |
---|
0,0 → 1,1095 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; System service for filesystem call ;; |
;; (C) 2004 Ville Turjanmaa, License: GPL ;; |
;; ;; |
;; 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
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 /HardDisk/First 30 |
; eax = 1 ; write file /RamDisk/First 33 /HardDisk/First 56 |
; eax = 2 ; delete file /RamDisk/First 32 /HardDisk/First 57 |
; eax = 3 ; append to a file /RamDisk/First ?? /HardDisk/First ?? |
; eax = 4 ; makedir |
; eax = 5 ; rename file/directory |
; eax = 8 ; lba read |
; eax = 12 ; get_filesize |
; eax = 13 ; get_fileattr |
; eax = 14 ; get_filedate |
; eax = 15 ; get_disk_info |
; eax = 16 ; start application |
; |
; OUT: |
; |
; eax = 0 : read ok |
; eax = 1 : no fd base and/or partition defined |
; eax = 2 : yet unsupported 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 |
; |
; ebx = size |
; Extract parameters |
mov edi,[0x3010] |
add eax,[edi+0x10] ; abs start of info block |
cmp dword [eax+0],12 ; Get file size |
je fs_read |
cmp dword [eax+0],13 ; Get file attribute |
je fs_read |
cmp dword [eax+0],14 ; Get file date/time |
je fs_read |
cmp dword [eax+0],15 ; GET_DISK_INFO |
je fs_info |
cmp dword [eax+0],16 ; RUN - dont care about read&write blocks |
je fs_read |
cmp dword [eax+0],5 ; RENAME - dont care about read&write blocks |
je fs_read |
cmp dword [eax+0],4 ; MAKEDIR - dont care about read&write blocks |
je fs_read |
cmp dword [eax+0],2 ; DELETE - dont care about read&write blocks |
je fs_read |
cmp dword [0x3000],1 ; no memory checks for kernel requests |
jz no_checks_for_kernel |
;iglobal |
; buffer_failed db 'Buffer check failed',13,10,0 |
;endg |
mov edx,eax |
cmp dword [eax+0],1 |
jz .check_for_write_op |
cmp dword [eax+0],3 |
jnz .usual_check |
.check_for_write_op: |
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 '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 |
jmp area_in_app_mem |
; mov ebx,[0x3000] ; pointer in application memory ? |
; shl ebx,8 |
; mov ebx,[ebx+0x80000+0x8c] |
; mov ebp,ebx ; save for checking at stack save |
; sub ebp,[eax+12] |
; shr ebp,9 |
; sub ebx,512 ; need atleast one block |
; cmp ebx,[eax+12] |
; ja area_in_app_mem |
; mov eax,7 |
; mov dword [esp+36],7 |
; ret |
area_in_app_mem: |
mov eax,edx |
no_checks_for_kernel: |
cmp dword [eax+0],3 ; APPEND - allow write 0 bytes (truncate) |
je fs_read |
cmp dword [eax+8],0 ; read or write 0 blocks/bytes ? |
jne fs_read |
mov dword [esp+36],0 |
ret |
fs_read: |
mov ebx,[eax+20] ; program wants root directory ? |
test bl,bl |
je fs_getroot |
test bh,bh |
jne fs_noroot |
fs_getroot: |
mov edx,[edi+0x10] |
mov esi,dir0 |
mov edi,[eax+12] |
add edi,edx |
mov ecx,11 |
cld |
rep movsb |
mov eax,0x10 |
stosb |
add edi,32-11-1 |
mov ecx,11 |
rep movsb |
stosb |
mov dword [esp+36],0 ; ok read |
mov dword [esp+24],32*2 ; size of root |
ret |
fs_info: ;start of code - Mihasik |
mov edi,eax |
push edi |
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: |
mov ebx,[eax+0] |
push ebx ; read/write/delete/.../makedir/rename/lba/run |
mov ebx,[eax+4] |
push ebx ; 512 block number to read |
mov ebx,[eax+8] |
; cmp dword [eax+0],0 ; if read, check that the data stays at |
; jne ret_size_fine ; application memory |
; cmp ebx,ebp |
; jbe ret_size_fine |
; mov ebx,ebp |
; ret_size_fine: |
push ebx ; bytes to write/append or 512 blocks to read |
mov ebx,[eax+12] |
add ebx,[edi+0x10] |
push ebx ; abs start of return/save area |
lea esi,[eax+20] ; abs start of dir + filename |
mov edi,[edi+0x10] ; abs start of work area |
add edi,[eax+16] |
call expand_pathz |
push edi ; dir start |
push ebx ; name of file start |
mov ebx,[dir0+11] ; /RAMDISK |
mov eax,[edi+1] |
cmp eax,'RD ' |
je fs_yesramdisk |
cmp eax,ebx |
jne fs_noramdisk |
fs_yesramdisk: |
cmp byte [edi+1+11],0 |
je fs_give_dir1 |
mov ebx,[dir1] ; /FIRST |
mov eax,[edi+1+12] |
cmp eax,'1 ' |
je fs_yesramdisk_first |
cmp eax,ebx |
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: |
cmp dword [esp+20],1 ; WRITE |
jne fs_noramdisk_write |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
mov ebx,[esp+8] ; buffer |
mov ecx,[esp+12] ; count to write |
mov edx,0 ; create new |
call filesave |
; eax=0 ok - eax=1 not enough free space |
jmp file_system_return |
fs_noramdisk_write: |
cmp dword [esp+20],16 ; START APPLICATION |
jne fs_noramdisk_start_application |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
xor ebx,ebx ; parameters to pass |
cmp dword [esp+12],0 |
je no_fl_start_param |
mov ebx,[0x3010] |
mov ebx,[ebx+0x10] |
add ebx,[esp+12] |
no_fl_start_param: |
call start_application_fl |
jmp file_system_return |
fs_noramdisk_start_application: ;there's new code - Mihasik |
cmp dword [esp+20],2 ;DELETE |
jne fs_noramdisk_delete |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
call filedelete |
jmp file_system_return |
fs_noramdisk_delete: |
cmp dword [esp+20],12 ;GET TIME,DATE,SIZE AND ATTRS |
jb fs_noramdisk_getinfo |
cmp dword [esp+20],14 |
ja fs_noramdisk_getinfo |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
mov ebx,[esp+20] |
mov ecx,[esp+0] |
sub ecx,eax |
add ecx,12+1 ; file name length |
call rd_getfileinfo |
jmp file_system_return |
fs_noramdisk_getinfo: ;End of code - Mihasik |
fs_noramdisk: |
;******************************************************************** |
mov ebx,[dir0+22] ; /FLOPPYDISK |
mov eax,[edi+1] |
cmp eax,'FD ' |
je fs_yesflpdisk |
cmp eax,ebx |
jne fs_noflpdisk |
fs_yesflpdisk: |
call reserve_flp |
cmp byte [edi+1+11],0 |
je fs_give_dir1 |
mov ebx,[dir1] ; /FIRST |
mov eax,[edi+1+12] |
cmp eax,'1 ' |
je fs_yesflpdisk_first |
cmp eax,ebx |
je fs_yesflpdisk_first |
mov ebx,[dir1+11] ; /SECOND |
cmp eax,'2 ' |
je fs_yesflpdisk_second |
cmp eax,ebx |
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: |
cmp dword [esp+20],1 ; WRITE |
jne fs_noflpdisk_write |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
mov ebx,[esp+8] ; buffer |
mov ecx,[esp+12] ; count to write |
mov edx,0 ; create new |
call floppy_filesave |
; eax=0 ok - eax=1 not enough free space |
jmp file_system_return |
fs_noflpdisk_write: |
cmp dword [esp+20],2 ; DELETE |
jne fs_noflpdisk_delete |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
call floppy_filedelete |
mov [flp_status],0 |
jmp file_system_return |
fs_noflpdisk_delete: |
cmp dword [esp+20],16 ; START APPLICATION |
jne fs_noflpdisk_start_application |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
xor ebx,ebx ; parameters to pass |
cmp dword [esp+12],0 |
je no_flp_start_param |
mov ebx,[0x3010] |
mov ebx,[ebx+0x10] |
add ebx,[esp+12] |
no_flp_start_param: |
call start_application_floppy |
jmp file_system_return |
fs_noflpdisk_start_application: |
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 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 [0xfe10],dword 0 ; entries in hd cache |
mov ecx,[hdpos] |
xor eax,eax |
mov edx,0x40002 |
search_partition_array: |
mov bl,[edx] |
movzx ebx,bl |
add eax,ebx |
inc edx |
loop search_partition_array |
sub eax,ebx |
add eax,[fat32part] |
dec eax |
xor edx,edx |
imul eax,100 |
add eax,0x4000a |
mov [transfer_adress],eax |
call partition_data_transfer_1 |
ret |
old_path_harddisk: |
mov ebx,[dir0] ; /HARDDISK |
mov eax,[edi+1] |
cmp eax,'HD ' |
je fs_yesharddisk |
cmp eax,ebx |
jne fs_noharddisk |
fs_yesharddisk: |
call reserve_hd1 |
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 |
fs_for_new_semantic: |
call choice_necessity_partition |
fs_yesharddisk_all: |
mov eax,1 |
cmp [hdpos],0 ; is hd base set? |
jz file_system_return ; no |
cmp [fat32part],0 ; is partition set? |
jz file_system_return ; no |
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],'/' |
jmp file_system_return |
fs_noharddisk_read: |
cmp dword [esp+20],1 ; WRITE |
jne fs_noharddisk_write |
mov eax,[esp+0] ; /fname |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov ebx,[esp+12] ; count to write |
mov ecx,[esp+8] ; buffer |
mov edx,[esp+4] |
add edx,12*2 ; path start |
call file_write |
mov edi,[esp+0] |
mov byte [edi],'/' |
; eax=0 ok - eax=1 not enough free space |
jmp file_system_return |
fs_noharddisk_write: |
cmp dword [esp+20],2 ; DELETE |
jne fs_noharddisk_delete |
mov eax,[esp+0] ; /dirname or /filename |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov edx,[esp+4] |
add edx,12*2 ; path start |
call removedir |
mov edi,[esp+0] |
mov byte [edi],'/' |
jmp file_system_return |
fs_noharddisk_delete: |
cmp dword [esp+20],3 ; APPEND |
jne fs_noharddisk_append |
mov eax,[esp+0] ; /dirname or /filename |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov edx,[esp+4] |
add edx,12*2 ; path start |
mov ecx,[esp+8] ; buffer |
mov ebx,[esp+12] ; count to write |
mov esi,[esp+16] ; bytes to skip over |
call file_append |
mov edi,[esp+0] |
mov byte [edi],'/' |
jmp file_system_return |
fs_noharddisk_append: |
cmp dword [esp+20],4 ; MAKEDIR |
jne fs_noharddisk_makedir |
mov eax,[esp+0] ; /dirname |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov edx,[esp+4] |
add edx,12*2 ; path start |
call makedir |
mov edi,[esp+0] |
mov byte [edi],'/' |
jmp file_system_return |
fs_noharddisk_makedir: |
cmp dword [esp+20],5 ; RENAME |
jne fs_noharddisk_rename |
mov edi,[esp+0] ; start of source file name |
add edi,12+1 ; continue after name |
call expand_pathz ; convert destination name |
mov edx,[dir0] ; /HARDDISK |
mov eax,[edi+1] |
cmp eax,'HD ' |
je fs_rename_test1 |
cmp eax,edx |
jne fs_rename_error |
fs_rename_test1: |
mov edx,[dir1] ; /FIRST |
mov eax,[edi+1+12] |
cmp eax,'1 ' |
je fs_rename_start |
cmp eax,edx |
jne fs_rename_error |
fs_rename_start: |
mov byte [ebx],0 ; path to asciiz |
inc ebx ; filename start |
add edi,12*2 ; path start |
cmp byte [ebx],0 |
je fs_rename_error |
cmp byte [ebx],32 |
je fs_rename_error |
mov eax,[esp+0] ; /filename |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov edx,[esp+4] |
add edx,12*2 ; path start |
call rename |
mov edi,[esp+0] |
mov byte [edi],'/' |
jmp file_system_return |
fs_rename_error: |
mov eax,4 ; partition not defined at hd |
jmp file_system_return |
fs_noharddisk_rename: |
cmp dword [esp+20],12 ; get FILESIZE |
jne fs_noharddisk_get_filesize |
mov eax,[esp+0] ; /fname |
lea edi,[eax+12] |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov edx,[esp+4] |
add edx,12*2 ; path start |
sub edi,edx ; path length |
call get_filesize |
mov edi,[esp+0] |
mov byte [edi],'/' |
jmp file_system_return |
fs_noharddisk_get_filesize: |
cmp dword [esp+20],13 ; get FILEATTR |
jne fs_noharddisk_get_fileattr |
mov eax,[esp+0] ; /dirname |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov edx,[esp+4] |
add edx,12*2 ; path start |
call get_fileattr |
mov edi,[esp+0] |
mov byte [edi],'/' |
jmp file_system_return |
fs_noharddisk_get_fileattr: |
cmp dword [esp+20],14 ; get FILEDATE |
jne fs_noharddisk_get_filedate |
mov eax,[esp+0] ; /dirname |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov edx,[esp+4] |
add edx,12*2 ; path start |
call get_filedate |
mov edi,[esp+0] |
mov byte [edi],'/' |
jmp file_system_return |
fs_noharddisk_get_filedate: |
cmp dword [esp+20],16 ; START APPLICATION |
jne fs_noharddisk_start_application |
mov eax,[esp+4] ; fname |
add eax,12*2 |
mov ebx,[esp+0] ; length |
sub ebx,eax |
add ebx,12 |
mov ecx,[esp+4] ; work area |
add ecx,512 |
xor ebp,ebp ; parameters to pass |
cmp dword [esp+12],0 |
je no_hd_start_param |
mov ebp,[0x3010] |
mov ebp,[ebp+0x10] |
add ebp,[esp+12] |
no_hd_start_param: |
call start_application_hd |
jmp file_system_return |
fs_noharddisk_start_application: |
fs_noharddisk: |
file_system_return: |
add esp,24 |
mov [esp+36],eax |
mov [esp+24],ebx |
ret |
fs_give_dir1: |
mov eax,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 |
mov 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,0x100000 |
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] |
call wait_for_hd_idle |
; 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 |
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 [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 err |
mov bx,cx |
shl cx,1 |
jc err |
shl cx,1 |
jc err |
add cx,bx |
jc err |
cbw |
add cx,ax |
jc err |
i3: |
inc edi |
jmp i1 |
i_exit: |
mov ax,cx |
clc |
i4: |
movzx eax,ax |
pop edi |
pop dx |
pop cx |
pop bx |
ret |
err: |
stc |
jmp i4 |
partition_string: dd 0 |
db 32 |
/kernel/trunk/fs/fs_phys.inc |
---|
0,0 → 1,111 |
hd_phys_read: |
;eax - sector number |
;ebx - destination |
pushad |
call wait_for_hd_idle |
popad |
push edx |
push eax |
cli |
xor eax,eax |
mov edx,[hdbase] |
inc edx |
out dx,al |
inc edx |
inc eax |
out dx,al |
inc edx |
;write sector number. |
mov eax,[esp] |
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] ;+0 or +16 |
or al,32+64+128 |
out dx,al |
inc edx |
mov al,0x20 |
out dx,al |
sti |
call wait_for_sector_buffer |
cmp [hd_error],0 |
jnz hd_read_error |
cli |
push edi |
mov edi,ebx |
mov ecx,256 |
mov edx,[hdbase] |
cld |
rep insw |
pop edi |
sti |
pop edx |
pop eax |
ret |
hd_phys_write: |
;eax - sector number |
;ebx - destination |
cmp eax,[partition_start] |
jb .ret |
cmp eax,[partition_end] |
ja .ret |
pushad |
call wait_for_hd_idle |
popad |
push edx |
push eax |
cli |
xor eax,eax |
mov edx,[hdbase] |
inc edx |
out dx,al |
inc edx |
inc eax |
out dx,al |
;write sector number |
inc edx |
mov eax,[esp] |
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] ;+0 or +16 |
or al,32+64+128 |
out dx,al |
inc edx |
mov al,0x30 |
out dx,al |
sti |
call wait_for_sector_buffer |
cmp [hd_error],0 |
jnz hd_write_error |
cli |
push esi |
mov esi,ebx |
mov ecx,256 |
mov edx,[hdbase] |
cld |
rep outsw |
pop esi |
sti |
pop edx |
pop eax |
.ret: |
ret |
/kernel/trunk/gui/button.inc |
---|
0,0 → 1,551 |
max_buttons=4095 |
dececx: |
push eax |
push edx |
push ecx |
mov edx,1 |
dececl: |
movzx eax,byte [esp+edx] |
cmp eax,0x20 |
jge @f |
mov [esp+edx],byte 0x20 |
@@: |
sub [esp+edx],byte 0x20 |
add edx,1 |
cmp edx,4 |
jbe dececl |
pop ecx |
pop edx |
pop eax |
ret |
drawbuttonframes: |
push esi |
push edi |
push eax |
push ebx |
push ecx |
push edx |
shr eax,16 |
shr ebx,16 |
mov edx,[0x3010] |
add eax,[edx-twdw] |
add ebx,[edx-twdw+4] |
mov cx,ax |
mov dx,bx |
shl eax,16 |
shl ebx,16 |
mov ax,cx |
mov bx,dx |
add ax,word [esp+12] |
mov esi,ebx |
mov edi,0 |
mov ecx,[esp+0] |
add ecx,0x202020 |
call [draw_line] |
movzx edx,word [esp+8] |
add ebx,edx |
shl edx,16 |
add ebx,edx |
mov ecx,[esp+0] |
call dececx |
call [draw_line] |
mov ebx,esi |
push edx |
mov edx,eax |
shr edx,16 |
mov ax,dx |
mov edx,ebx |
shr edx,16 |
mov bx,dx |
mov dx,[esp+8+4] |
add bx,dx |
pop edx |
mov edi,0 |
mov ecx,[esp+0] |
add ecx,0x202020 |
call [draw_line] |
mov esi,edx |
mov dx,[esp+12] |
add ax,dx |
shl edx,16 |
add eax,edx |
add ebx,1*65536 |
mov edx,esi |
mov ecx,[esp+0] |
call dececx |
call [draw_line] |
pop edx |
pop ecx |
pop ebx |
pop eax |
pop edi |
pop esi |
ret |
button_dececx: |
cmp [buttontype],dword 1 |
jne .finish |
; je bdece |
; ret |
; bdece: |
push eax |
mov eax,0x01 |
cmp edi,20 |
jg @f |
mov eax,0x02 |
@@: |
test ecx,0xff |
jz @f |
sub ecx,eax |
@@: |
shl eax,8 |
test ecx,0xff00 |
jz @f |
sub ecx,eax |
@@: |
shl eax,8 |
test ecx,0xff0000 |
jz @f |
sub ecx,eax |
@@: |
pop eax |
.finish: |
ret |
sys_button: |
test ecx,0x80000000 |
jnz remove_button |
push esi |
push edi |
push eax |
push ebx |
push ecx |
push edx |
test ecx,0x40000000 |
jnz button_no_draw |
pushad ; button body |
push ebx |
shr eax,16 |
shr ebx,16 |
mov edx,[0x3010] |
mov esi,[edx-twdw] |
mov edi,[edx-twdw+4] |
add eax,esi |
add ebx,edi |
mov cx,ax |
mov dx,bx |
shl eax,16 |
shl ebx,16 |
mov ax,cx |
mov bx,dx |
movzx ecx,word [4+32+esp+12] |
add eax,ecx |
mov ecx,[4+32+esp+0] |
cmp [buttontype],dword 0 |
je @f |
add ecx,0x141414 |
@@: |
movzx edi,word [esp] |
; <Ivan Poddubny 15.08.2004> |
pop edx |
and edx, 0xFFFF |
;;cli |
.newline: |
call button_dececx |
push edi |
xor edi, edi |
call [draw_line] |
pop edi |
add ebx,1*65536+1 ; [ y start | y end ] |
dec edx |
jnz .newline |
;;sti |
;; pop ebx |
; </Ivan Poddubny 15.08.2004> |
popad |
call drawbuttonframes |
button_no_draw: |
and ecx,0xffff |
mov edi,[0x3010] |
sub edi,twdw |
mov edi,[0xfe88] |
movzx eax,word [edi] |
cmp eax,max_buttons |
jge noaddbutt |
inc eax |
mov [edi],ax |
shl eax,4 |
add eax,edi |
mov bx,[0x3000] |
mov [eax],bx |
add eax,2 ; save button id number |
mov ebx,[esp+4] |
mov [eax],bx ; bits 0-15 |
shr ebx,16 |
mov [eax-2+0xc],bx; bits 16-31 |
add eax,2 ; x start |
mov bx,[esp+12+2] |
mov [eax],bx |
add eax,2 ; x size |
mov bx,[esp+12+0] |
mov [eax],bx |
add eax,2 ; y start |
mov bx,[esp+8+2] |
mov [eax],bx |
add eax,2 ; y size |
mov bx,[esp+8+0] |
mov [eax],bx |
noaddbutt: |
pop edx |
pop ecx |
pop ebx |
pop eax |
pop edi |
pop esi |
ret |
remove_button: |
and ecx,0x7fffffff |
rnewba2: |
mov edi,[0xfe88] |
mov eax,edi |
movzx ebx,word [edi] |
inc bx |
rnewba: |
dec bx |
jz rnmba |
add eax,0x10 |
mov dx,[0x3000] |
cmp dx,[eax] |
jnz rnewba |
cmp cx,[eax+2] |
jnz rnewba |
pushad |
mov ecx,ebx |
inc ecx |
shl ecx,4 |
mov ebx,eax |
add eax,0x10 |
call memmove |
dec dword [edi] |
popad |
jmp rnewba2 |
rnmba: |
ret |
find_pressed_button_frames: |
pushad |
movzx ebx,word [eax+0] |
shl ebx,5 |
add ebx,window_data |
movzx ecx,word [ebx+0] ; window x start |
movzx edx,word [eax+4] ; button x start |
add ecx,edx |
push ecx |
mov dx,[eax+6] ; button x size |
add cx,dx |
mov esi,ecx |
inc esi |
mov cx,[ebx+4] ; window y start |
mov dx,[eax+8] ; button y start |
add ecx,edx |
mov ebx,ecx |
mov dx,[eax+10] ; button y size |
add dx,cx |
inc dx |
pop eax |
; eax x beginning |
; ebx y beginning |
; esi x end |
; edx y end |
; ecx color |
mov [pressed_button_eax],eax |
mov [pressed_button_ebx],ebx |
mov [pressed_button_ecx],ecx |
mov [pressed_button_edx],edx |
mov [pressed_button_esi],esi |
popad |
ret |
uglobal |
pressed_button_eax dd 0 |
pressed_button_ebx dd 0 |
pressed_button_ecx dd 0 |
pressed_button_edx dd 0 |
pressed_button_esi dd 0 |
endg |
; negative button image |
negativebutton: |
; If requested, do not display button |
; boarder on press. |
test ebx,0x20000000 |
jz draw_negative_button |
ret |
draw_negative_button: |
pushad |
mov eax,[pressed_button_eax] |
mov ebx,[pressed_button_ebx] |
mov ecx,[pressed_button_ecx] |
mov edx,[pressed_button_edx] |
mov esi,[pressed_button_esi] |
mov ecx,0x01000000 |
dec edx |
push edx |
inc edx |
dec esi |
push esi |
inc esi |
push eax |
push ebx |
push ecx |
push edx |
push edi |
call [disable_mouse] |
bdbnewline: |
mov edi,1 ; force |
cmp eax,[esp+16] |
jz bneg |
cmp eax,[esp+20] |
jz bneg |
cmp ebx,[esp+12] |
jz bneg |
cmp ebx,[esp+24] |
jnz nbneg |
; jz bneg |
; jmp nbneg |
bneg: |
;;;call [disable_mouse] |
call [putpixel] |
nbneg: |
inc eax |
cmp eax,esi |
jnz bdbnewline |
mov eax,[esp+16] |
inc ebx |
cmp ebx,edx |
jnz bdbnewline |
add esp,28 |
popad |
ret |
; check buttons |
; 0000 word process number |
; 0002 word button id number : bits 0-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 |
; |
; button table in 0x10 increments |
; |
; first at 0x10 |
checkbuttons: |
cmp [0xfb40],byte 0 ; mouse buttons pressed |
jnz @f |
ret |
@@: |
pushad |
xor esi, esi |
mov edi, [0xfe88] |
movzx edx, word [edi] |
test edx, edx |
jne @f |
popad |
ret |
@@: |
push esi |
inc edx |
push edx |
buttonnewcheck: |
pop edx |
pop esi |
inc esi |
cmp edx,esi |
jge bch |
popad ; no button pressed |
ret |
bch: |
push esi |
push edx |
mov eax,esi |
shl eax,4 |
add eax,edi |
; check that button is at top of windowing stack |
movzx ebx,word [eax] |
movzx ecx,word [0xC000 + ebx * 2] |
cmp ecx,[0x3004] |
jne buttonnewcheck |
; check that button start is inside window x/y end |
movzx ebx,word [eax+0] |
shl ebx,5 |
; add ebx,window_data |
; mov ecx,[window_data+ebx+8] ; window end X |
movzx edx,word [eax+4] ; button start X |
cmp edx, [window_data+ebx+8] ;ecx |
jge buttonnewcheck |
; mov ecx,[window_data+ebx+12] ; window end Y |
movzx edx, word [eax+8] ; button start Y |
cmp edx, [window_data+ebx+12] ;ecx |
jge buttonnewcheck |
; check coordinates |
; mouse x >= button x ? |
movzx ebx,word [eax+0] |
shl ebx,5 |
add ebx,window_data |
movzx ecx,word [ebx+0] ; window x start |
movzx edx,word [eax+4] ; button x start |
add edx,ecx |
mov cx,[0xfb0a] |
cmp edx,ecx |
jg buttonnewcheck |
movzx ebx,word [eax+6] ; button x size |
add edx,ebx |
cmp ecx,edx |
jg buttonnewcheck |
; mouse y >= button y ? |
movzx ebx,word [eax+0] |
shl ebx,5 |
add ebx,window_data |
movzx ecx,word [ebx+4] ; window y start |
movzx edx,word [eax+8] ; button y start |
add edx,ecx |
mov cx,[0xfb0c] |
cmp edx,ecx |
jg buttonnewcheck |
movzx ebx,word [eax+10] ; button y size |
add edx,ebx |
cmp ecx,edx |
jg buttonnewcheck |
; mouse on button |
pop edx |
pop esi |
mov bx,[eax+0xc] ; button id : bits 16-31 |
shl ebx,16 |
mov bx,[eax+2] ; button id : bits 00-16 |
push ebx |
mov [0xfb44],byte 1 ; no mouse down checks |
call find_pressed_button_frames |
call negativebutton |
pushad |
cbwaitmouseup: |
call checkidle |
call check_mouse_data |
call [draw_pointer] |
pushad |
call stack_handler |
popad |
cmp [0xfb40],byte 0 ; mouse buttons pressed ? |
jnz cbwaitmouseup |
popad |
call negativebutton |
mov [0xfff4],byte 0 ; no mouse background |
mov [0xfff5],byte 0 ; draw mouse |
mov [0xf500],byte 1 |
pop ebx |
mov [0xf501],ebx |
mov [0xfb44],byte 0 ; mouse down checks |
popad |
ret |
/kernel/trunk/gui/event.inc |
---|
0,0 → 1,188 |
sys_getevent: |
call get_event_for_app |
mov [esp+36],eax |
ret |
align 4 |
sys_wait_event_timeout: |
mov ebx,[timer_ticks];[0xfdf0] |
add ebx,eax |
cmp ebx,[timer_ticks];[0xfdf0] |
jna .swfet2 |
.swfet1: |
call get_event_for_app |
test eax,eax |
jne .eventoccur_time |
call change_task |
cmp ebx,[timer_ticks];[0xfdf0] |
jg .swfet1 |
.swfet2: |
xor eax,eax |
.eventoccur_time: |
mov [esp+36],eax |
ret |
align 4 |
sys_waitforevent: |
call get_event_for_app |
test eax,eax |
jne eventoccur |
newwait: |
call change_task |
call get_event_for_app |
test eax,eax |
je newwait |
eventoccur: |
mov [esp+36],eax |
ret |
get_event_for_app: |
pushad |
mov edi,[0x3010] ; WINDOW REDRAW |
test [edi],dword 1 |
jz no_eventoccur1 |
mov edi,[0x3010] |
cmp [edi-twdw+31],byte 0 |
je no_eventoccur1 |
popad |
mov eax,1 |
ret |
no_eventoccur1: |
mov edi,[0x3010] ; KEY IN BUFFER |
test [edi],dword 2 |
jz no_eventoccur2 |
mov ecx, [0x3000] |
movzx edx,word [0xC000+ecx*2] |
mov eax, [0x3004] |
cmp eax,edx |
jne no_eventoccur2 |
cmp [0xf400],byte 0 |
je no_eventoccur2 |
popad |
mov eax,2 |
ret |
no_eventoccur2: |
mov edi,[0x3010] ; BUTTON IN BUFFER |
test [edi],dword 4 |
jz no_eventoccur3 |
mov ecx, [0x3000] |
movzx edx, word [0xC000+ecx*2] |
mov eax, [0x3004] |
cmp eax,edx |
jnz no_eventoccur3 |
cmp [0xf500],byte 0 |
je no_eventoccur3 |
popad |
mov eax,[0xf501] |
cmp eax,65535 |
je no_event_1 |
mov eax,3 |
ret |
no_event_1: |
mov [window_minimize],1 |
mov [0xf500],byte 0 |
xor eax, eax |
ret |
no_eventoccur3: |
mov edi,[0x3010] ; DESKTOP BACKGROUND REDRAW |
test [edi],dword 16 |
jz no_eventoccur5 |
cmp [0xfff0],byte 2 |
jnz no_eventoccur5 |
popad |
mov eax,5 |
ret |
no_eventoccur5: |
mov edi,[0x3010] ; mouse event |
test [edi],dword 00100000b |
jz no_mouse_event |
mov edi,[0x3000] |
shl edi,8 |
test [edi+0x80000+0xA8],dword 00100000b |
jz no_mouse_event |
and [edi+0x80000+0xA8],dword 0xffffffff-00100000b |
popad |
mov eax,6 |
ret |
no_mouse_event: |
mov edi,[0x3010] ; IPC |
test [edi],dword 01000000b |
jz no_ipc |
mov edi,[0x3000] |
shl edi,8 |
test [edi+0x80000+0xA8],dword 01000000b |
jz no_ipc |
and [edi+0x80000+0xA8],dword 0xffffffff-01000000b |
popad |
mov eax,7 |
ret |
no_ipc: |
mov edi,[0x3010] ; STACK |
test [edi],dword 10000000b |
jz no_stack_event |
mov edi,[0x3000] |
shl edi,8 |
test [edi+0x80000+0xA8],dword 10000000b |
jz no_stack_event |
and [edi+0x80000+0xA8],dword 0xffffffff-10000000b |
popad |
mov eax,7 |
ret |
no_stack_event: |
mov esi,0x2e0000 ; IRQ'S AND DATA |
mov ebx,0x00010000 |
xor ecx, ecx |
irq_event_test: |
mov edi,[0x3010] |
test [edi],ebx |
jz no_irq_event |
mov edi,ecx |
shl edi,2 |
add edi,irq_owner |
mov edx,[edi] |
mov eax,[0x3010] |
mov eax,[eax+0x4] |
cmp edx,eax |
jne no_irq_event |
cmp [esi],dword 0 |
jz no_irq_event |
mov eax,ecx |
add eax,16 |
mov [esp+28],eax |
popad |
ret |
no_irq_event: |
add esi,0x1000 |
shl ebx,1 |
inc ecx |
cmp ecx,16 |
jb irq_event_test |
popad |
xor eax, eax |
ret |
/kernel/trunk/gui/font.inc |
---|
0,0 → 1,225 |
align 4 |
dtext: |
; eax x & y |
; ebx font ( 0xX0000000 ) & color ( 0x00RRGGBB ) |
; ecx start of text |
; edx length |
; edi 1 force |
test ebx,0x10000000 |
jnz dtext2 |
pushad |
mov esi, edx |
and esi, 0xff |
test esi, esi ; zero length ? |
jnz @f |
popad |
ret |
@@: |
align 4 |
.letnew: |
push eax ecx edx |
movzx ebx,ax |
shr eax,16 |
movzx edx,byte [ecx] |
mov ecx,[esp+3*4+32-16] |
call drawletter |
pop edx ecx eax |
add eax,6*65536 |
inc ecx |
dec edx |
jnz .letnew |
popad |
ret |
align 4 |
drawletter: |
; eax x |
; ebx y |
; ecx color |
; edx letter |
; esi shl size |
; edi force |
pushad |
call [disable_mouse] |
xor eax, eax |
xor ebx, ebx ; 0x37000+eax+ebx*8 |
inc esi |
align 4 |
chc: |
push eax |
push ebx |
mov edx,ebx |
shl edx,3 |
add edx,eax |
add edx,0x37000+8 |
mov ecx,[esp+32-12+8] |
imul ecx,8*10 |
add edx,ecx |
cmp [edx],byte 'o' |
jnz .nopix |
mov eax,[esp+4] |
mov ebx,[esp+0] |
add eax,[esp+32+2*4-4] |
add ebx,[esp+32+2*4-16] |
mov ecx,[esp+32+2*4-8] |
;;;call [disable_mouse] |
call [putpixel] |
.nopix: |
pop ebx |
pop eax |
inc eax |
cmp eax,5 ; ebp |
jne chc |
xor eax, eax |
inc ebx |
cmp ebx,9 ; ebp |
jne chc |
popad |
ret |
dtext2: |
; eax x & y |
; ebx color |
; ecx start of text |
; edx length |
; edi 1 force |
pushad |
mov esi,edx |
and esi,0xff |
test esi,esi ; zero length ? |
jnz @f |
popad |
ret |
@@: |
align 4 |
letnew2: |
push eax |
push ecx |
push edx |
movzx ebx,ax |
shr eax,16 |
movzx edx,byte [ecx] |
mov ecx,[esp+3*4+32-16] |
call drawletter2 |
pop edx |
pop ecx |
pop eax |
push edx |
movzx edx,byte [ecx] |
imul edx,10*10 |
add edx,0x30000 |
cmp [edx+6],byte ' ' |
jne nocharadd8 |
add eax,8*65536 |
jmp charaddok |
nocharadd8: |
movzx edx,byte [edx+6] |
sub edx,47 |
shl edx,16 |
add eax,edx |
charaddok: |
pop edx |
inc ecx |
dec edx |
jnz letnew2 |
popad |
ret |
align 4 |
drawletter2: |
; eax x |
; ebx y |
; ecx color |
; edx letter |
; esi shl size |
; edi force |
pushad |
call [disable_mouse] |
xor eax, eax |
xor ebx, ebx ; +eax+ebx*8 |
inc esi |
align 4 |
chc2: |
push eax |
push ebx |
; cmp esi,1 |
; je noldiv |
; xor edx,edx |
; div esi |
; push eax |
; xor edx,edx |
; mov eax,ebx |
; div esi |
; mov ebx,eax |
; pop eax |
; noldiv: |
mov edx,ebx |
;shl edx,3 |
imul edx,10 |
add edx,eax |
add edx,0x30000+8+2 |
mov ecx,[esp+32-12+8] |
;shl ecx,6 |
imul ecx,10*10 |
add edx,ecx |
cmp [edx],byte 'o' |
jnz nopix2 |
mov eax,[esp+4] |
mov ebx,[esp+0] |
add eax,[esp+32+2*4-4] |
add ebx,[esp+32+2*4-16] |
mov ecx,[esp+32+2*4-8] |
;;;call [disable_mouse] |
call [putpixel] |
nopix2: |
pop ebx |
pop eax |
;mov ebp,7 |
;imul ebp,esi |
inc eax |
cmp eax,7 ;ebp |
jnz chc2 |
xor eax, eax |
;mov ebp,9 |
;imul ebp,esi |
inc ebx |
cmp ebx,9 ; ebp |
jnz chc2 |
popad |
ret |
/kernel/trunk/gui/mouse.inc |
---|
0,0 → 1,243 |
;mouseunder: |
; times 16*24 dd 0 |
label mouseunder dword at 0x6900 |
iglobal |
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 |
/kernel/trunk/gui/skincode.inc |
---|
0,0 → 1,388 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; WINDOW SKIN for MenuetOS ;; |
;; ;; |
;; entryway@bkg.lt ;; |
;; ;; |
;; Bugfixes & upgrades by ;; |
;; Samuel Rodriguez Perez ;; |
;; Xeoda@ciberirmandade.org ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include "SKINDATA.INC" |
virtual at 0 |
bmp_header: |
.type rw 1 ; "BM" signature |
.filesize rd 1 ; size of the file |
.reserved rd 1 ; zero |
.offbits rd 1 ; pointer to image data |
;---------------- |
.headsize rd 1 ; usually 40 bytes for image header |
.width rd 1 |
.height rd 1 |
.planes rw 1 ; usually 1 |
.bitcount rw 1 ; currently 24 bits/pixel (0x18) |
.compress rd 1 ; zero |
.sizeimage rd 1 ; x*y*(bitcount/8) |
.unused rd 4 ; these bits aren't used by MeOS |
bmp_data: |
end virtual |
virtual at 0x778000 |
_bmp_bpl dd ? ; bytes per line |
_bmp_dpl dd ? ; dwords per line |
_bmp_zb dd ? ; bytes filled by zeroes at the end of a scanline |
align 32 |
raw_data: |
end virtual |
bmp2raw: |
; esi = to bmp data (source) |
; edi = to raw data (destination) |
cmp [esi+bmp_header.type],'BM' ; check if bmp file is really loaded |
jne .finish |
mov edx,esi |
mov eax,[edx+bmp_header.width] |
imul eax,3 |
push eax |
test eax,11b |
jz @f |
add eax,4 |
@@: |
shr eax,2 |
mov [_bmp_dpl],eax |
shl eax,2 |
mov [_bmp_bpl],eax |
pop ebx |
sub eax,ebx |
mov [_bmp_zb],eax |
add esi,bmp_data |
mov eax,[_bmp_bpl] |
imul eax,[edx+bmp_header.height] |
add esi,eax |
mov ebx,[edx+bmp_header.height] ; ebx = y |
cld |
.y_begin: |
sub esi,[_bmp_bpl] |
push esi |
mov ecx,[_bmp_dpl] |
rep movsd |
pop esi |
sub edi,[_bmp_zb] |
dec ebx |
jne .y_begin |
.finish: |
ret |
; BMP support by Ivan Poddubny |
; 1) load LEFT.BMP |
; a) _skinleftw = bmp_width |
; b) _skinleft = 0 |
; c) _refleft = 0x778000 |
; d) convert |
; 2) load BASE.BMP |
; a) _skinbasew = bmp_width |
; b) _skinbase = _skinleftw |
; c) _refbase = _refleft+sizeof(left_raw_converted) |
; d) convert |
; 3) load OPER.BMP |
; a) _skinoper = minus width from bmp file |
; b) _skinoperw = width from bmp file |
; c) _refoper = _refbase+sizeof(oper_raw_converted) |
; d) convert |
; 4) set height |
load_bmp_file: |
; eax = pointer to filename |
mov ebx, 1 |
or ecx, -1 |
mov edx, 0x90000 |
mov esi, 12 |
call fileread |
ret |
load_default_skin: |
pushad |
mov eax, _fileleft |
call load_bmp_file |
mov eax, [0x90000+bmp_header.width] |
mov [_skinleftw], eax |
mov [_skinleft], 0 |
mov edi, raw_data |
mov [_refleft], edi |
mov esi, 0x90000 |
call bmp2raw |
mov eax, [_bmp_bpl] |
imul eax, [0x90000+bmp_header.height] |
push eax |
mov eax, _filebase |
call load_bmp_file |
mov eax, [0x90000+bmp_header.width] |
mov [_skinbasew], eax |
mov eax, [_skinleftw] |
mov [_skinbase], eax |
pop eax |
add eax, [_refleft] |
; align to 32-byte boundary |
test eax, 11111b |
jz @f |
shr eax, 5 |
inc eax |
shl eax, 5 |
@@: |
; save base address |
mov [_refbase], eax |
; convert |
mov edi, eax |
mov esi, 0x90000 |
call bmp2raw |
mov eax, [_bmp_bpl] |
imul eax, [0x90000+bmp_header.height] |
push eax |
mov eax, _fileoper |
call load_bmp_file |
mov eax, [0x90000+bmp_header.width] |
mov [_skinoperw], eax |
neg eax |
mov [_skinoper], eax |
pop eax |
add eax, [_refbase] |
; align to 32-byte boundary |
test eax, 11111b |
jz @f |
shr eax, 5 |
inc eax |
shl eax, 5 |
@@: |
mov [_refoper], eax |
mov edi, eax |
mov esi, 0x90000 |
call bmp2raw |
; mov eax, [0x90000+bmp_header.height] |
; imul eax, [0x90000+bmp_header.width] |
; imul eax, 3 |
; add eax, raw_data ; now eax points to the last line of image |
; mov ecx, [eax] |
; mov [_coloroutborder], ecx |
; mov [_colorborder], ecx |
; sub eax, 2*3 |
; mov ecx, [eax] |
; mov [_colorframe], ecx |
mov eax, [0x90000+bmp_header.height] |
mov [_skinh], eax |
popad |
ret |
drawwindow_IV: |
pusha |
push edx |
mov edi,[esp] ; RECTANGLE |
mov eax,[edi+0] |
shl eax,16 |
mov ax,[edi+0] |
add ax,[edi+8] |
mov ebx,[edi+4] |
shl ebx,16 |
mov bx,[edi+4] |
add bx,[edi+12] |
; mov esi,[edi+24] |
; shr esi,1 |
; and esi,0x007f7f7f |
mov esi,[_coloroutborder] |
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,[_colorframe] ;[edi+24] |
call draw_rectangle |
dec ecx |
jnz _dw3l |
mov esi,[_colorborder] |
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 |
mov esi,[esp] |
mov eax,[esi+8] ; window width |
mov edx,[_skinleft] |
shl edx,16 |
mov ecx,[_skinleftw] |
shl ecx,16 |
add ecx,[_skinh] |
mov ebx,[_refleft] |
call sys_putimage |
mov esi,[esp] |
mov eax,[esi+8] |
sub eax,[_skinleftw] |
sub eax,[_skinoperw] |
cmp eax,[_skinbase] |
jng non_base |
xor edx,edx |
mov ebx,[_skinbasew] |
div ebx |
inc eax |
mov ebx,[_refbase] |
mov ecx,[_skinbasew] |
shl ecx,16 |
add ecx,[_skinh] |
mov edx,[_skinbase] |
sub edx,[_skinbasew] |
shl edx,16 |
baseskinloop: |
shr edx,16 |
add edx,[_skinbasew] |
shl edx,16 |
push eax ebx ecx edx |
call sys_putimage |
pop edx ecx ebx eax |
dec eax |
jnz baseskinloop |
non_base: |
mov esi,[esp] |
mov edx,[esi+8] |
sub edx,[_skinoperw] |
inc edx |
shl edx,16 |
mov ebx,[_refoper] |
mov ecx,[_skinoperw] |
shl ecx,16 |
add ecx,[_skinh] |
call sys_putimage |
mov esi,[esp] |
mov edx,[esi+04] ; WORK AREA |
add edx,21+5 |
mov ebx,[esi+04] |
add ebx,[esi+12] |
cmp edx,ebx |
jg _noinside2 |
mov eax,5 |
mov ebx,[_skinh] |
mov ecx,[esi+8] |
mov edx,[esi+12] |
sub ecx,4 |
sub edx,4 |
mov edi,[esi+16] |
call [drawbar] |
_noinside2: |
mov edi,[0xfe88] |
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,[0x3000] |
mov [eax],bx |
add eax,2 ; save button id number |
mov bx,1 |
mov [eax],bx |
add eax,2 ; x start |
mov ebx,[esp] |
mov ebx,[ebx+8] |
cmp [_buttonCx],0 |
jg _bCx_at_right |
mov ebx,[_buttonCw] ; ebx will be 0 in next instruction |
_bCx_at_right: |
sub ebx,[_buttonCw] |
sub ebx,[_buttonCx] |
mov [eax],bx |
add eax,2 ; x size |
mov ebx,[_buttonCw] |
mov [eax],bx |
add eax,2 ; y start |
mov ebx,[_buttonCy] |
mov [eax],bx |
add eax,2 ; y size |
mov ebx,[_buttonCh] |
mov [eax],bx |
;* minimize button |
mov edi,[0xfe88] |
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,[0x3000] |
mov [eax],bx |
add eax,2 ; save button id number |
mov bx,65535 ;999 |
mov [eax],bx |
add eax,2 ; x start |
mov ebx,[esp] |
mov ebx,[ebx+8] |
cmp [_buttonMx],0 |
jg _bMx_at_right |
mov ebx,[_buttonMw] ; ebx will be 0 in next instruction |
_bMx_at_right: |
sub ebx,[_buttonMw] |
sub ebx,[_buttonMx] |
mov [eax],bx |
add eax,2 ; x size |
mov ebx,[_buttonMw] |
mov [eax],bx |
add eax,2 ; y start |
mov ebx,[_buttonMy] |
mov [eax],bx |
add eax,2 ; y size |
mov ebx,[_buttonMh] |
mov [eax],bx |
;* minimize button |
no_skin_add_button: |
add esp,4 |
popa |
ret |
/kernel/trunk/gui/skindata.inc |
---|
0,0 → 1,44 |
; |
; WINDOW SKIN for MenuetOS |
; ivan-yar@bk.ru |
; |
iglobal |
_skinh dd 22 |
_skinleftw dd 10 |
_skinbase dd 10 |
_skinbasew dd 8 |
_skinoper dd -39 ;-21 |
_skinoperw dd 39 ;21 |
_buttonCx dd 5 ; close |
_buttonCy dd 2 |
_buttonCw dd 15 |
_buttonCh dd 17 |
_buttonMx dd 23 ; minimize |
_buttonMy dd 2 |
_buttonMw dd 15 |
_buttonMh dd 17 |
_colorframe dd 0x3a6cb6 ;0x586E93 |
_colorborder dd 0x00081D |
_coloroutborder dd 0x00081D |
_fileleft db 'LEFT.BMP ' |
_filebase db 'BASE.BMP ' |
_fileoper db 'OPER.BMP ' |
endg |
uglobal |
_refoper dd 0 |
_refbase dd 0 |
_refleft dd 0 |
_skinleft dd 0 |
_skinwinw dd 0 |
endg |
/kernel/trunk/gui/window.inc |
---|
0,0 → 1,1613 |
setwindowdefaults: |
pushad |
xor eax,eax |
mov ecx,0xc000 |
@@: |
inc eax |
add ecx,2 |
mov [ecx+0x000],ax ; process no |
mov [ecx+0x400],ax ; positions in stack |
cmp ecx,0xc400-2 ; the more high, the more surface |
jnz @b |
popad |
ret |
; eax = cx |
; ebx = cy |
; ecx = ex |
; edx = ey |
; èäåÿ: ïåðåáðàòü âñå îêíà, íà÷èíàÿ ñ ñàìîãî íèæíåãî, |
; è äëÿ êàæäîãî âûçâàòü setscreen |
align 4 |
calculatescreen: |
pushad |
cli |
mov esi, 1 |
xor eax, eax |
xor ebx, ebx |
mov ecx, [0xFE00] |
mov edx, [0xFE04] |
call setscreen |
mov ebp, [0x3004] ; number of processes |
cmp ebp, 1 |
jbe .finish |
align 4 |
.new_wnd: |
movzx edi, word [0xC400 + esi * 2] |
shl edi, 5 |
add edi, window_data |
mov eax, [edi+0] |
mov ebx, [edi+4] |
mov ecx, [edi+8] |
test ecx, ecx |
jz .not_wnd |
add ecx, eax |
mov edx, [edi+12] |
add edx, ebx |
push esi |
movzx esi, word [0xC400 + esi * 2] |
call setscreen |
pop esi |
.not_wnd: |
inc esi |
dec ebp |
jnz .new_wnd |
.finish: |
sti |
popad |
ret |
virtual at esp |
ff_xsz dd ? |
ff_ysz dd ? |
ff_scale dd ? |
end virtual |
align 4 |
; ðåçåðâèðóåò ìåñòî ïîä îêíî çàäàííîãî ïðîöåññà |
setscreen: |
; eax x start |
; ebx y start |
; ecx x end |
; edx y end |
; esi process number |
pushad |
mov edi, esi ;;;word [esi*2+0xc400] |
shl edi, 8 |
add edi, 0x80000+0x80 ; address of random shaped window area |
cmp [edi], dword 0 |
jne .free_form |
; get x&y size |
sub ecx, eax |
sub edx, ebx |
inc ecx |
inc edx |
; get WinMap start |
mov edi, [0xFE00] ; screen_sx |
inc edi |
imul edi, ebx |
add edi, eax |
add edi, WinMapAddress |
.new_y: |
push ecx ; sx |
push edx |
mov edx, esi |
align 4 |
.new_x: |
mov byte [edi], dl |
inc edi |
dec ecx |
jnz .new_x |
pop edx |
pop ecx |
add edi, [0xFE00] |
inc edi |
sub edi, ecx |
dec edx |
jnz .new_y |
popad |
ret |
.read_byte: |
;eax - address |
;esi - slot |
push eax |
push ebx |
push ecx |
push edx |
mov edx,eax |
mov eax,esi |
lea ebx,[esp+12] |
mov ecx,1 |
call read_process_memory |
pop edx |
pop ecx |
pop ebx |
pop eax |
ret |
.free_form: |
; for (y=0; y <= x_size; y++) |
; for (x=0; x <= x_size; x++) |
; if (shape[coord(x,y,scale)]==1) |
; set_pixel(x, y, process_number); |
sub ecx, eax |
sub edx, ebx |
inc ecx |
inc edx |
push dword [edi+4] ; push scale first -> for loop |
; get WinMap start -> ebp |
push eax |
mov eax, [0xFE00] ; screen_sx |
inc eax |
imul eax, ebx ;ebx |
add eax, [esp] ;eax |
add eax, WinMapAddress |
mov ebp, eax |
mov edi, [edi] |
; mov eax, esi |
; shl eax, 5 |
; add edi, [eax+0x3000+0x10] |
pop eax |
; eax = x_start |
; ebx = y_start |
; ecx = x_size |
; edx = y_size |
; esi = process_number |
; edi = &shape |
; [scale] |
push edx ecx ;ebx eax |
xor ebx, ebx |
align 4 |
.ff_new_y: |
xor edx, edx |
align 4 |
.ff_new_x: |
; -- body -- |
mov ecx, [ff_scale] |
mov eax, [ff_xsz] |
shr eax, cl |
push ebx edx |
shr ebx, cl |
shr edx, cl |
imul eax, ebx |
add eax, edx |
pop edx ebx |
add eax, edi ;[ff_shape] |
call .read_byte |
; cmp byte [eax], 1 |
; jne @f |
test al,al |
jz @f |
mov eax, esi ; [ff_proc] |
mov [ebp], al |
@@: |
; -- end body -- |
inc ebp |
inc edx |
cmp edx, [ff_xsz] |
jb .ff_new_x |
sub ebp, [ff_xsz] |
add ebp, [0xFE00] ; screen.x |
inc ebp |
inc ebx |
cmp ebx, [ff_ysz] |
jb .ff_new_y |
pop ecx edx ; eax ebx first |
add esp, 4 |
popad |
ret |
display_settings: |
; eax = 0 ; DISPLAY redraw |
; ebx = 0 ; all |
; |
; eax = 1 ; BUTTON type |
; ebx = 0 ; flat |
; ebx = 1 ; 3D |
; eax = 2 ; set WINDOW colours |
; ebx = pointer to table |
; ecx = number of bytes define |
; eax = 3 ; get WINDOW colours |
; ebx = pointer to table |
; ecx = number of bytes wanted |
; eax = 4 ; get skin height |
; input : nothing |
; output : eax = skin height in pixel |
pushad |
test eax, eax ; redraw display |
jnz dspl0 |
test ebx, ebx |
jnz dspl0 |
cmp [windowtypechanged],dword 1 |
jne dspl00 |
mov [windowtypechanged],dword 0 |
mov [dlx],dword 0 |
mov [dly],dword 0 |
mov eax,[0xfe00] |
mov [dlxe],eax |
mov eax,[0xfe04] |
mov [dlye],eax |
mov eax,window_data |
call redrawscreen |
dspl00: |
popad |
ret |
dspl0: |
cmp eax,1 ; button type |
jne dspl1 |
and ebx,1 |
cmp ebx,[buttontype] |
je dspl9 |
mov [buttontype],ebx |
mov [windowtypechanged],dword 1 |
dspl9: |
popad |
ret |
dspl1: |
cmp eax,2 ; set common window colours |
jne no_com_colours |
mov [windowtypechanged],dword 1 |
mov esi,[0x3010] |
add esi,0x10 |
add ebx,[esi] |
mov esi,ebx |
mov edi,common_colours |
and ecx,127 |
cld |
rep movsb |
popad |
ret |
no_com_colours: |
cmp eax,3 ; get common window colours |
jne no_get_com |
mov esi,[0x3010] |
add esi,0x10 |
add ebx,[esi] |
mov edi,ebx |
mov esi,common_colours |
and ecx,127 |
cld |
rep movsb |
popad |
ret |
no_get_com: |
cmp eax,4 ; get skin height |
jne no_skin_height |
popad |
mov eax,[_skinh] |
mov [esp+36],eax |
ret |
no_skin_height: |
popad |
ret |
uglobal |
common_colours: |
times 128 db 0x0 |
endg |
check_window_move_request: |
pushad |
mov edi,[window_move_pr] ; requestor process base |
cmp edi,0 |
je window_move_return |
shl edi,5 |
add edi,window_data |
push dword [edi+0] ; save old coordinates |
push dword [edi+4] |
push dword [edi+8] |
push dword [edi+12] |
mov eax,[window_move_eax] |
mov ebx,[window_move_ebx] |
mov ecx,[window_move_ecx] |
mov edx,[window_move_edx] |
cmp eax,-1 ; set new position and size |
je no_x_reposition |
mov [edi+0],eax |
no_x_reposition: |
cmp ebx,-1 |
je no_y_reposition |
mov [edi+4],ebx |
no_y_reposition: |
cmp ecx,-1 |
je no_x_resizing |
mov [edi+8],ecx |
no_x_resizing: |
cmp edx,-1 |
je no_y_resizing |
mov [edi+12],edx |
no_y_resizing: |
call check_window_position |
pushad ; save for window fullscreen/resize |
mov esi,edi |
sub edi,window_data |
shr edi,5 |
shl edi,8 |
add edi,0x80000+0x90 |
mov ecx,4 |
cld |
rep movsd |
popad |
pushad ; calculcate screen at new position |
mov eax,[edi+00] |
mov ebx,[edi+04] |
mov ecx,[edi+8] |
mov edx,[edi+12] |
add ecx,eax |
add edx,ebx |
call calculatescreen |
popad |
pop edx ; calculcate screen at old position |
pop ecx |
pop ebx |
pop eax |
add ecx,eax |
add edx,ebx |
mov [dlx],eax ; save for drawlimits |
mov [dly],ebx |
mov [dlxe],ecx |
mov [dlye],edx |
call calculatescreen |
mov [edi+31],byte 1 ; flag the process as redraw |
mov eax,edi ; redraw screen at old position |
xor esi,esi |
call redrawscreen |
mov [0xfff5],byte 0 ; mouse pointer |
mov [0xfff4],byte 0 ; no mouse under |
mov [0xfb44],byte 0 ; react to mouse up/down |
mov ecx,10 ; wait 1/10 second |
wmrl3: |
call check_mouse_data |
call [draw_pointer] |
mov eax,1 |
call delay_hs |
loop wmrl3 |
mov [window_move_pr],0 |
window_move_return: |
popad |
ret |
check_window_position: |
pushad ; window inside screen ? |
movzx eax,word [edi+0] |
movzx ebx,word [edi+4] |
movzx ecx,word [edi+8] |
movzx edx,word [edi+12] |
mov esi,ecx ; check x pos |
add esi,eax |
cmp esi,[0xfe00] |
jbe x_pos_ok |
mov [edi+0],dword 0 |
xor eax, eax |
x_pos_ok: |
mov esi,edx ; check y pos |
add esi,ebx |
cmp esi,[0xfe04] |
jbe y_pos_ok |
mov [edi+4],dword 0 |
mov ebx,0 |
y_pos_ok: |
mov esi,ecx ; check x size |
add esi,eax |
cmp esi,[0xfe00] |
jbe x_size_ok |
mov ecx,[0xfe00] |
mov [edi+8],ecx |
x_size_ok: |
mov esi,edx ; check y size |
add esi,ebx |
cmp esi,[0xfe04] |
jbe y_size_ok |
mov edx,[0xfe04] |
mov [edi+12],edx |
y_size_ok: |
popad |
ret |
uglobal |
new_window_starting dd 0 |
endg |
sys_window_mouse: |
push eax |
mov eax,[timer_ticks] ;[0xfdf0] |
cmp [new_window_starting],eax |
jb swml1 |
mov [0xfff4],byte 0 ; no mouse background |
mov [0xfff5],byte 0 ; draw mouse |
mov [new_window_starting],eax |
swml1: |
pop eax |
ret |
drawwindow_I: |
pushad |
mov esi,[edx+24] ; rectangle |
mov eax,[edx+0] |
shl eax,16 |
add eax,[edx+0] |
add eax,[edx+8] |
mov ebx,[edx+04] |
shl ebx,16 |
add ebx,[edx+4] |
add ebx,[edx+12] |
call draw_rectangle |
mov ecx,[edx+20] ; grab bar |
push ecx |
mov esi,edx |
mov edx,[esi+04] |
add edx,1 |
mov ebx,[esi+04] |
add ebx,25 |
mov eax,[esi+04] |
add eax,[esi+12] |
cmp ebx,eax |
jb wdsizeok |
mov ebx,eax |
wdsizeok: |
push ebx |
drwi: |
mov ebx,edx |
shl ebx,16 |
add ebx,edx |
mov eax,[esi+00] |
inc eax |
shl eax,16 |
add eax,[esi+00] |
add eax,[esi+8] |
sub eax,1 |
push edx |
mov edx,0x80000000 |
mov ecx,[esi+20] |
and ecx,edx |
cmp ecx,edx |
jnz nofa |
mov ecx,[esi+20] |
sub ecx,0x00040404 |
mov [esi+20],ecx |
and ecx,0x00ffffff |
jmp faj |
nofa: |
mov ecx,[esi+20] |
and ecx,0x00ffffff |
faj: |
pop edx |
mov edi,0 |
call [draw_line] |
inc edx |
cmp edx,[esp] |
jb drwi |
add esp,4 |
pop ecx |
mov [esi+20],ecx |
mov edx,[esi+04] ; inside work area |
add edx,21+5 |
mov ebx,[esi+04] |
add ebx,[esi+12] |
cmp edx,ebx |
jg noinside |
mov eax,1 |
mov ebx,21 |
mov ecx,[esi+8] |
mov edx,[esi+12] |
mov edi,[esi+16] |
call [drawbar] |
noinside: |
popad |
ret |
draw_rectangle: |
r_eax equ [esp+28] ; x start |
r_ax equ [esp+30] ; x end |
r_ebx equ [esp+16] ; y start |
r_bx equ [esp+18] ; y end |
;esi ; color |
pushad |
mov ecx,esi ; yb,xb -> yb,xe |
;<<< 14.11.2004 Ivan Poddubny <faster and smaller> |
; mov eax,r_eax |
; shl eax,16 |
; mov ax,r_ax |
mov eax, r_eax |
rol eax, 16 |
;>>> 14.11.2004 Ivan Poddubny <faster and smaller> |
mov ebx,r_ebx |
shl ebx,16 |
mov bx,r_ebx |
xor edi, edi |
call [draw_line] |
mov ebx,r_bx ; ye,xb -> ye,xe |
shl ebx,16 |
mov bx,r_bx |
call [draw_line] |
mov ecx,esi ; ya,xa -> ye,xa |
mov eax,r_eax |
shl eax,16 |
mov ax,r_eax |
mov ebx,r_ebx |
shl ebx,16 |
mov bx,r_bx |
mov edi,0 |
call [draw_line] |
mov eax,r_ax ; ya,xe -> ye,xe |
shl eax,16 |
mov ax,r_ax |
call [draw_line] |
popad |
ret |
drawwindow_III: |
pushad |
mov edi,edx ; RECTANGLE |
mov eax,[edi+0] |
shl eax,16 |
mov ax,[edi+0] |
add ax,[edi+8] |
mov ebx,[edi+4] |
shl ebx,16 |
mov bx,[edi+4] |
add bx,[edi+12] |
mov esi,[edi+24] |
shr esi,1 |
and esi,0x007f7f7f |
push esi |
call draw_rectangle |
mov ecx,3 |
dw3l: |
add eax,1*65536-1 |
add ebx,1*65536-1 |
mov esi,[edi+24] |
call draw_rectangle |
dec ecx |
jnz dw3l |
pop esi |
add eax,1*65536-1 |
add ebx,1*65536-1 |
call draw_rectangle |
mov ecx,[edx+20] ; GRAB BAR |
push ecx |
mov esi,edx |
mov edx,[esi+04] |
add edx,4 |
mov ebx,[esi+04] |
add ebx,20 |
mov eax,[esi+04] |
add eax,[esi+12] |
cmp ebx,eax |
jb wdsizeok2 |
mov ebx,eax |
wdsizeok2: |
push ebx |
drwi2: |
mov ebx,edx |
shl ebx,16 |
add ebx,edx |
mov eax,[esi+00] |
shl eax,16 |
add eax,[esi+00] |
add eax,[esi+8] |
add eax,4*65536-4 |
mov ecx,[esi+20] |
test ecx,0x40000000 |
jz nofa3 |
add ecx,0x040404 |
nofa3: |
test ecx,0x80000000 |
jz nofa2 |
sub ecx,0x040404 |
nofa2: |
mov [esi+20],ecx |
and ecx,0xffffff |
xor edi, edi |
call [draw_line] |
inc edx |
cmp edx,[esp] |
jb drwi2 |
add esp,4 |
pop ecx |
mov [esi+20],ecx |
mov edx,[esi+04] ; WORK AREA |
add edx,21+5 |
mov ebx,[esi+04] |
add ebx,[esi+12] |
cmp edx,ebx |
jg noinside2 |
mov eax,5 |
mov ebx,20 |
mov ecx,[esi+8] |
mov edx,[esi+12] |
sub ecx,4 |
sub edx,4 |
mov edi,[esi+16] |
call [drawbar] |
noinside2: |
popad |
ret |
; activate window |
align 4 |
windowactivate: |
; esi = abs mem position in stack 0xC400+ |
pushad |
push esi |
movzx eax, word [esi] ; ax <- process no |
movzx eax, word [0xC000+eax*2] ; ax <- position in window stack |
xor esi, esi ; drop others |
waloop: |
cmp esi, dword [0x3004] |
jae wacont |
inc esi |
lea edi, [0xC000 + esi*2] |
mov bx, [edi] ; position of the current process |
cmp bx, ax |
jbe @f |
dec bx ; upper? => drop! |
mov [edi], bx |
@@: |
jmp waloop |
wacont: |
; set to no 1 |
pop esi ; esi = pointer at 0xC400 |
movzx eax, word [esi] |
mov bx, [0x3004] ; number of processes |
mov [0xC000+eax*2], bx ; this is the last (and the upper) |
;* start code - get active process (4) - Mario79 |
mov [active_process],eax |
;* end code - get active process (4) - Mario79 |
; update on screen -window stack |
xor esi, esi |
waloop2: |
mov edi, [0x3004] |
cmp esi, edi |
jae wacont2 |
inc esi |
movzx ebx, word [esi*2 + 0xC000] |
mov [ebx*2 + 0xC400], si |
jmp waloop2 |
wacont2: |
mov [0xf400], byte 0 ; empty keyboard buffer |
mov [0xf500], byte 0 ; empty button buffer |
popad |
ret |
; check if window is necessary to draw |
checkwindowdraw: |
; edi = position in window_data+ |
mov esi, edi |
sub esi, window_data |
shr esi, 5 |
; esi = process number |
; <IP 15.08.2004> |
movzx eax, word [0xC000 + esi * 2] ; get value of the curr process |
lea esi, [0xC400 + eax * 2] ; get address of this process at 0xC400 |
; </IP 15.08.2004> |
push esi |
.new_check: |
pop esi |
add esi, 2 |
push esi |
mov eax, [0x3004] |
lea eax, word [0xC400 + eax * 2] ; number of the upper window |
cmp esi, eax |
ja .all_wnds_to_top |
movzx eax, word [esi] |
shl eax, 5 |
add eax, window_data |
mov esi, eax |
mov ebx, [edi+4] |
mov edx, [edi+12] |
add edx, ebx |
mov ecx, [esi+4] ; y check |
cmp ecx, edx |
jae .new_check |
mov eax, [esi+12] |
add ecx, eax |
cmp ebx, ecx |
ja .new_check |
mov eax, [edi+0] |
mov ecx, [edi+8] |
add ecx, eax |
mov edx, [esi+0] ; x check |
cmp edx, ecx |
jae .new_check |
mov ecx, [esi+8] |
add edx, ecx |
cmp eax, edx |
ja .new_check |
pop esi |
mov ecx,1 ; overlap some window |
ret |
.all_wnds_to_top: |
pop esi |
xor ecx, ecx ; passed all windows to top |
ret |
waredraw: ; if redraw necessary at activate |
pushad |
call checkwindowdraw ; draw window on activation ? |
test ecx, ecx |
jz .do_not_draw |
popad |
mov [0xfb44], byte 1 ; do draw mouse |
call windowactivate |
; update screen info |
pushad |
mov edi, [0x3004] ; the last process (number) |
movzx esi, word [0xC400 + edi * 2] |
shl esi, 5 |
add esi, window_data |
; coordinates of the upper window |
mov eax, [esi+00] ; cx |
mov ebx, [esi+04] ; cy |
mov ecx, [esi+08] ; sx |
mov edx, [esi+12] ; sy |
add ecx, eax ; ecx = x_end |
add edx, ebx ; edx = y_end |
mov edi, [0x3004] |
movzx esi, word [0xC400 + edi * 2] |
shl esi, 5 |
movzx esi, byte [esi + 0x3000 + 0xE] |
call setscreen ;;;calculatescreen ; setscreen |
popad |
cmp [0xff01], dword 1 ; if > 1 then activate process |
jbe .not_activate |
;;; mov eax, 10 ; wait for putimages to finish |
;;; call delay_hs |
mov [edi+31],byte 1 ; redraw flag for app |
mov [0xfb44],byte 0 ; mouse down checks |
ret |
.not_activate: |
; mov eax,5 ; wait for putimages to finish |
; call delay_hs |
mov [edi+31],byte 1 ; redraw flag for app |
mov ecx, 25 ;100 |
.waitflagdown: |
dec ecx |
jz .nowait |
mov eax, 2 |
call delay_hs |
cmp [edi+31], byte 0 ; wait flag to drop |
jnz .waitflagdown |
.nowait: |
; mov ecx,10 |
; .wait: |
; mov eax,1 ; wait for draw to finish |
; call delay_hs |
; loop .wait |
mov [0xfb44],byte 0 |
ret |
.do_not_draw: |
popad |
call windowactivate |
mov [0xfb44],byte 0 ; mouse down checks |
mov [0xfff4],byte 0 ; no mouse background |
mov [0xfff5],byte 0 ; draw mouse |
ret |
iglobal |
window_moving db 'K : Window - move/resize',13,10,0 |
window_moved db 'K : Window - done',13,10,0 |
endg |
; check window touch |
align 4 |
checkwindows: |
pushad |
cmp [0xff01],dword 1 ; activate request from app ? |
jbe .no_activate_request |
mov edi,[0xff01] ; process number |
shl edi,5 |
add edi,window_data |
mov ebx,[0xff01] |
movzx esi, word [0xC000 + ebx * 2] |
lea esi, [0xC400 + esi * 2] |
call waredraw |
;* start code - get active process (2) - Mario79 |
mov eax,[0xff01] |
mov [active_process],eax |
;* end code - get active process (2) - Mario79 |
mov [0xff01],dword 0 ; activated |
popad |
ret |
.no_activate_request: |
cmp [0xfb40],byte 0 ; mouse buttons pressed ? |
jne .mouse_buttons_pressed |
; cmp [window_minimize],2 |
; jne .no_activate_request_1 |
cmp [window_minimize],0 |
je .no_activate_request_2 |
cmp [window_minimize],1 |
je .mouse_buttons_pressed |
mov esi,[0x3004] |
movzx edi, word [0xC400 + esi * 2] |
shl edi, 5 |
add edi, window_data |
cmp [edi+12],dword 0 |
je .mouse_buttons_pressed |
; jne .no_activate_request_2 |
; .no_activate_request_1: |
; cmp [window_minimize],1 |
; jge .mouse_buttons_pressed |
; jmp .mouse_buttons_pressed |
.no_activate_request_2: |
mov [window_minimize],0 |
popad |
ret |
.mouse_buttons_pressed: |
mov esi,[0x3004] |
inc esi |
cwloop: |
cmp esi,2 |
jb .exit |
.temp_window_minimize_1: |
dec esi |
movzx edi, word [0xC400 + esi * 2] ; ebx |
shl edi, 5 |
add edi, window_data |
; mov edi, ebx |
mov ecx, [edi+0] |
mov edx, [edi+4] |
mov eax,ecx |
mov ebx,edx |
cmp [window_minimize],1 |
jge .window_minimize_no_check_mouse |
movzx eax, word [0xfb0a] |
movzx ebx, word [0xfb0c] |
cmp ecx, eax |
jae cwloop |
cmp edx, ebx |
jae cwloop |
add ecx, [edi+8] |
add edx, [edi+12] |
cmp eax, ecx |
jae cwloop |
cmp ebx, edx |
jae cwloop |
.window_minimize_no_check_mouse: |
pushad |
mov eax, esi |
mov ebx, [0x3004] |
cmp eax, ebx ; is this window active? |
jz .move_resize_window |
; eax = position in windowing stack |
; redraw must ? |
lea esi, [0xC400 + esi * 2] |
call waredraw |
add esp, 32 |
.exit: |
popad |
ret |
.move_resize_window: ; MOVE OR RESIZE WINDOW |
popad |
; Check for user enabled fixed window |
mov edx, [edi+0x14] |
and edx, 0x0f000000 |
cmp edx, 0x01000000 |
jne .window_move_enabled_for_user |
popad |
ret |
.window_move_enabled_for_user: |
mov [do_resize_from_corner],byte 0 ; resize for skinned window |
mov edx, [edi+0x10] |
and edx, 0x0f000000 |
cmp edx, 0x02000000 |
jb .no_resize_2 ; not type 2 wnd |
mov edx, [edi+4] |
add edx, [edi+12] |
sub edx, 6 ; edx = y_end - 6 |
cmp ebx, edx ; ebx = mouse_y |
jb .no_resize_2 |
mov [do_resize_from_corner],byte 1 |
jmp .continue |
.no_resize_2: |
;// mike.dld [ |
mov dl,[edi+0x10+3] |
and dl,0x0F |
cmp dl,0x03 |
jne @f |
mov edx, [edi+4] ; check if touch on bar |
add edx, [_skinh] |
cmp ebx, edx |
jae .exit |
jmp .continue |
@@: |
;// mike.dld ] |
mov edx, [edi+4] ; check if touch on bar |
add edx, 21 |
cmp ebx, edx |
jae .exit |
.continue: |
push esi |
mov esi, window_moving |
call sys_msg_board_str |
pop esi |
mov ecx, [timer_ticks] ;[0xfdf0] ; double-click ? |
mov edx, ecx |
sub edx, [latest_window_touch] |
mov [latest_window_touch], ecx |
mov [latest_window_touch_delta], edx |
mov cl, [0xfb40] ; save for shade check |
mov [do_resize], cl |
cmp [window_minimize],0 |
je no_emulation_righ_button |
mov [do_resize], byte 2 |
no_emulation_righ_button: |
mov ecx, [edi+0] |
mov edx, [edi+4] |
push eax ecx edx |
mov [dlx], ecx ; save for drawlimits |
mov [dly], edx |
mov eax, [edi+8] |
add ecx, eax |
mov eax, [edi+12] |
add edx, eax |
mov [dlxe], ecx |
mov [dlye], edx |
pop edx ecx eax |
sub eax, ecx |
sub ebx, edx |
mov esi, [0xfb0a] |
mov [0xf300], esi |
pushad ; wait for putimages to finish |
; mov eax,5 |
; call delay_hs |
mov eax,[edi+0] |
mov [npx],eax |
mov eax,[edi+4] |
mov [npy],eax |
popad |
push eax ; save old coordinates |
mov ax,[edi+00] |
mov word [oldc+00],ax |
mov ax,[edi+04] |
mov word [oldc+04],ax |
mov ax,[edi+8] |
mov word [oldc+8],ax |
mov word [npxe],ax |
mov ax,[edi+12] |
mov word [oldc+12],ax |
mov word [npye],ax |
pop eax |
call drawwindowframes |
mov [reposition],0 |
mov [0xfb44],byte 1 ; no reaction to mouse up/down |
; move window |
newchm: |
mov [0xfff5],byte 1 |
call checkidle |
call checkEgaCga |
mov [0xfff4],byte 0 |
call check_mouse_data |
call [draw_pointer] |
pushad |
call stack_handler |
popad |
mov esi,[0xf300] |
cmp esi,[0xfb0a] |
je cwb |
mov cx,[0xfb0a] |
mov dx,[0xfb0c] |
sub cx,ax |
sub dx,bx |
push ax |
push bx |
call drawwindowframes |
mov ax,[0xfe00] |
mov bx,[0xfe04] |
cmp [do_resize_from_corner],1 |
je no_new_position |
mov word [npx],word 0 ; x repos ? |
cmp ax,cx |
jb noreposx |
mov [reposition],1 |
sub ax,word [npxe] |
mov word [npx],ax |
cmp ax,cx |
jb noreposx |
mov word [npx],cx |
noreposx: |
mov word [npy],word 0 ; y repos ? |
cmp bx,dx |
jb noreposy |
mov [reposition],1 |
sub bx,word [npye] |
mov word [npy],bx |
cmp bx,dx |
jb noreposy |
mov word [npy],dx |
noreposy: |
no_new_position: |
cmp [do_resize_from_corner],0 ; resize from right corner |
je norepos_size |
pushad |
mov edx,edi |
sub edx,window_data |
shr edx,5 |
shl edx,8 |
add edx,0x80000 ; process base at 0x80000+ |
movzx eax,word [0xfb0a] |
cmp eax,[edi+0] |
jb nnepx |
sub eax,[edi+0] |
cmp eax,[edx+0x90+8] |
jge nnepx2 |
mov eax,[edx+0x90+8] |
nnepx2: |
mov [npxe],eax |
nnepx: |
movzx eax,word [0xfb0c] |
cmp eax,[edi+4] |
jb nnepy |
sub eax,[edi+4] |
cmp eax,23 ; [edx+0x90+12] |
jge nnepy2 |
mov eax,23 ; [edx+0x90+12] |
nnepy2: |
mov [npye],eax |
nnepy: |
mov [reposition],1 |
popad |
norepos_size: |
pop bx |
pop ax |
call drawwindowframes |
mov esi,[0xfb0a] |
mov [0xf300],esi |
cwb: |
cmp [0xfb40],byte 0 |
jne newchm |
; new position done |
call drawwindowframes |
mov [0xfff5],byte 1 |
mov eax,[npx] |
mov [edi+0],eax |
mov eax,[npy] |
mov [edi+4],eax |
mov eax,[npxe] |
mov [edi+8],eax |
mov eax,[npye] |
mov [edi+12],eax |
cmp [reposition],1 ; save new X and Y start |
jne no_xy_save |
; <IP 28.08.2004> |
push esi edi ecx |
mov esi,edi |
sub edi,window_data |
shr edi,5 |
shl edi,8 |
add edi,0x80000+0x90 |
mov ecx,2 |
cld |
rep movsd |
pop ecx edi esi |
; </IP 28.08.2004> |
no_xy_save: |
pushad ; WINDOW SHADE/FULLSCREEN |
cmp [reposition],1 |
je no_window_sizing |
mov edx,edi |
sub edx,window_data |
shr edx,5 |
shl edx,8 |
add edx,0x80000 ; process base at 0x80000+ |
cmp [do_resize],2 ; window shade ? |
jb no_window_shade |
mov [reposition],1 |
cmp [window_minimize],1 |
jge for_window_minimize |
cmp [edi+12],dword 23 |
jle window_shade_up |
jmp for_window_shade |
for_window_minimize: |
cmp [edi+12],dword 0 |
je window_shade_up |
for_window_shade: |
cmp [window_minimize],0 |
je no_window_minimize |
cmp [window_minimize],2 |
je window_minimize_no_shade_full ;window_shade_up |
mov [edi+8],dword 0 ;66 |
mov [edi+12],dword 0 ;279 ; on |
jmp no_window_shade |
no_window_minimize: |
mov [edi+12],dword 23 ; on |
jmp no_window_shade |
window_shade_up: |
cmp [window_minimize],1 |
jge window_minimize_no_shade_full |
mov eax,[edi+0] |
add eax,[edi+4] |
test eax, eax |
je shade_full |
push edi |
lea esi, [edx + 0x90] |
mov ecx,4 |
cld |
rep movsd |
pop edi |
window_minimize_no_shade_full: |
; mov eax,[edx+0x90] ; off |
; mov [edi+0],eax |
; mov eax,[edx+0x94] ; off |
; mov [edi+4],eax |
; mov eax,[edx+0x98] ; off |
; mov [edi+8],eax |
; mov eax,[edx+0x9C] ; off |
; mov [edi+12],eax |
push edi |
lea esi, [edx + 0x90] |
mov ecx,4 |
cld |
rep movsd |
pop edi |
jmp no_window_shade |
shade_full: |
; mov eax,[0xfe00] |
; mov [edi+8],eax |
mov eax,[0xfe04] |
sub eax,19 |
mov [edi+12],eax |
no_window_shade: |
cmp [do_resize],1 ; fullscreen/restore ? |
jne no_fullscreen_restore |
cmp [latest_window_touch_delta],dword 50 |
jg no_fullscreen_restore |
mov [reposition],1 |
mov eax,[edi+12] |
add eax,19 |
cmp eax,[0xfe04] |
je restore_from_fullscreen |
mov [edi+0],dword 0 ; set fullscreen |
mov [edi+4],dword 0 |
mov eax,[0xfe00] |
mov [edi+8],eax |
mov eax,[0xfe04] |
sub eax,19 |
mov [edi+12],eax |
jmp no_fullscreen_restore |
restore_from_fullscreen: |
push edi ; restore |
; mov esi,edx |
; add esi,0x90 |
lea esi, [edx + 0x90] |
mov ecx,4 |
cld |
rep movsd |
pop edi |
no_fullscreen_restore: |
mov eax,[edi+4] ; check Y inside screen |
add eax,[edi+12] |
cmp eax,[0xfe04] |
jbe no_window_sizing |
mov eax,[edi+0] ; check X inside screen |
add eax,[edi+8] |
cmp eax,[0xfe00] |
jbe no_window_sizing |
mov eax,[0xfe00] |
sub eax,[edi+8] |
mov [edi+0],eax |
mov eax,[0xfe04] |
sub eax,[edi+12] |
mov [edi+4],eax |
no_window_sizing: |
popad |
cmp [reposition],0 |
je retwm |
pushad |
mov eax,[edi+00] |
mov ebx,[edi+04] |
mov ecx,[edi+8] |
mov edx,[edi+12] |
add ecx,eax |
add edx,ebx |
mov edi,[0x3004] |
shl edi,1 |
add edi,0xc400 |
movzx esi,byte [edi] |
shl esi,5 |
add esi,0x3000+0xe |
movzx esi,byte [esi] |
sub edi,draw_data |
shr edi,5 |
shl edi,8 |
add edi,0x80000+0x80 |
;cmp [edi],dword 0 |
;jne no_rect_shaped_move |
call setscreen |
jmp move_calculated |
no_rect_shaped_move: |
call calculatescreen |
move_calculated: |
popad |
mov [edi+31],byte 1 ; mark first as redraw |
mov [0xfff5],byte 1 ; no mouse |
push eax ebx ecx edx |
mov eax,[oldc+00] |
mov ebx,[oldc+04] |
mov ecx,[oldc+8] |
mov edx,[oldc+12] |
add ecx,eax |
add edx,ebx |
call calculatescreen |
pop edx ecx ebx eax |
mov eax,edi |
call redrawscreen |
mov ecx,100 ; wait to avoid mouse residuals |
waitre2: |
call check_mouse_data |
mov [0xfff5],byte 1 |
call checkidle |
cmp [edi+31],byte 0 |
jz retwm |
loop waitre2 |
retwm: |
mov [0xfff5],byte 0 ; mouse pointer |
mov [0xfff4],byte 0 ; no mouse under |
mov [0xfb44],byte 0 ; react to mouse up/down |
mov esi,window_moved |
call sys_msg_board_str |
popad |
mov [window_minimize],0 |
; sti |
ret |
;temp_mouse_1 dw 0 |
;temp_mouse_2 dw 0 |
uglobal |
add_window_data dd 0 |
do_resize_from_corner db 0x0 |
reposition db 0x0 |
latest_window_touch dd 0x0 |
latest_window_touch_delta dd 0x0 |
do_resize db 0x0 |
oldc dd 0x0,0x0,0x0,0x0 |
dlx dd 0x0 |
dly dd 0x0 |
dlxe dd 0x0 |
dlye dd 0x0 |
npx dd 0x0 |
npy dd 0x0 |
npxe dd 0x0 |
npye dd 0x0 |
mpx dd 0x0 |
mpy dd 0x0 |
endg |
; draw negative window frames |
drawwindowframes: |
pushad |
mov eax,[npx] |
shl eax,16 |
add eax,[npx] |
add eax,[npxe] |
add eax,65536*1-1 |
mov ebx,[npy] |
shl ebx,16 |
add ebx,[npy] |
mov ecx,0x01000000 |
push edi |
mov edi,1 |
call [draw_line] |
pop edi |
mov eax,[npx] |
shl eax,16 |
add eax,[npx] |
add eax,[npxe] |
add eax,65536*1-1 |
mov ebx,[npy] |
add ebx,[npye] |
shl ebx,16 |
add ebx,[npy] |
add ebx,[npye] |
mov ecx,0x01000000 |
push edi |
mov edi,1 |
call [draw_line] |
pop edi |
mov eax,[npx] |
shl eax,16 |
add eax,[npx] |
mov ebx,[npy] |
shl ebx,16 |
add ebx,[npy] |
add ebx,[npye] |
mov ecx,0x01000000 |
push edi |
mov edi,1 |
call [draw_line] |
pop edi |
mov eax,[npx] |
add eax,[npxe] |
shl eax,16 |
add eax,[npx] |
add eax,[npxe] |
mov ebx,[npy] |
shl ebx,16 |
add ebx,[npy] |
add ebx,[npye] |
mov ecx,0x01000000 |
push edi |
mov edi,1 |
call [draw_line] |
mov edi,[0x3000] |
shl edi,5 |
add edi,window_data |
mov [edi+30],byte 1 |
pop edi |
popad |
ret |
random_shaped_window: |
; |
; eax = 0 giving address of data area |
; ebx address |
; ebx = 1 shape area scale |
; ebx 2^ebx scale |
test eax, eax |
jne rsw_no_address |
mov eax,[0x3000] |
shl eax,8 |
mov [eax+0x80000+0x80],ebx |
rsw_no_address: |
cmp eax,1 |
jne rsw_no_scale |
mov eax,[0x3000] |
shl eax,8 |
mov [eax+0x80000+0x84],bl |
rsw_no_scale: |
ret |
/kernel/trunk/hid/keyboard.inc |
---|
0,0 → 1,223 |
;// mike.dld [ |
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 |
endg |
align 4 |
irq1: |
call restore_caller |
movzx eax,word[0x3004] ; top window process |
movzx eax,word[0xC400+eax*2] |
shl eax,8 |
mov al,[0x800B4+eax] |
mov [keyboard_mode],al |
in al,0x60 |
mov [keyboard_data],al |
mov ch,al |
cmp al,0xE0 |
je @f |
cmp al,0xE1 |
jne .normal_code |
@@: mov [ext_code],al |
jmp .no_key.end |
.normal_code: |
mov cl,[ext_code] |
mov [ext_code],0 |
and al,0x7F |
@@: cmp al,0x2A |
jne @f |
cmp cl,0xE0 |
je .no_key.end |
mov eax,VKEY_LSHIFT |
jmp .no_key |
@@: cmp al,0x36 |
jne @f |
cmp cl,0xE0 |
je .no_key.end |
mov eax,VKEY_RSHIFT |
jmp .no_key |
@@: cmp al,0x38 |
jne @f |
cmp cl,0xE0 |
je .alt.r |
mov eax,VKEY_LALT |
jmp .no_key |
.alt.r: |
mov eax,VKEY_RALT |
jmp .no_key |
@@: cmp al,0x1D |
jne @f |
cmp cl,0 |
jne .ctrl.r |
mov eax,VKEY_LCONTROL |
jmp .no_key |
.ctrl.r: |
cmp cl,0xE1 |
jne .ctrl.r.2 |
mov [ext_code],cl |
jmp .no_key.end |
.ctrl.r.2: |
mov eax,VKEY_RCONTROL |
jmp .no_key |
@@: cmp al,0x3A |
jne @f |
mov bl,4 |
mov eax,VKEY_CAPSLOCK |
jmp .no_key.xor |
@@: cmp al,0x45 |
jne @f |
cmp cl,0 |
jne .no_key.end |
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 |
@@: |
test ch,0x80 |
jnz .no_key.end |
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 bl,134+48 |
jne .noctrlaltdel |
mov [ctrl_alt_del],1 |
jmp .no_key.end |
.noctrlaltdel: |
test dl,VKEY_CONTROL ; ctrl on ? |
jz @f |
sub bl,0x60 |
@@: test dl,VKEY_SHIFT ; shift on ? |
jz @f |
mov bl,[keymap_shift+eax] |
@@: test dl,VKEY_ALT ; alt on ? |
jz @f |
mov bl,[keymap_alt+eax] |
; alt mouse ? |
xor edx,edx |
cmp bl,178 |
jnz .no_alt.up |
mov edx,5*65536 |
jmp .mouse.change |
.no_alt.up: |
cmp bl,177 |
jnz .no_alt.down |
mov edx,251*65536 |
jmp .mouse.change |
.no_alt.down: |
cmp bl,176 |
jnz .no_alt.left |
mov edx,251*256 |
jmp .mouse.change |
.no_alt.left: |
cmp bl,179 |
jnz .no_alt.right |
mov edx,5*256 |
jmp .mouse.change |
.no_alt.right: |
cmp bl,' ' |
jne @f |
xor [altmouseb],1 |
.mouse.change: |
mov byte[0xF604],1; ps2 data |
mov byte[0xFB00],0; ps2 chunk count |
mov word[0x2E0000+4096*12],3; mouse data count |
mov dl,[altmouseb] |
mov [0x2E0000+4096*12+0x10],edx |
mov bl,0 |
@@: |
cmp [keyboard_mode],0 ; return from keymap |
jne .no_key.end |
mov [keyboard_mode_sys],0 |
cmp bl,0 |
je .no_key.end |
movzx eax,byte[0xF400] |
cmp al,120 |
jae .no_key.end |
inc al |
mov [0xF400],al |
mov [0xF400+eax],bl |
jmp .no_key.end |
.no_key: |
test ch,0x80 |
jz .no_key.down |
not eax |
and [kb_state],eax |
jmp .no_key.end |
.no_key.xor: |
test ch,0x80 |
jnz .no_key.end |
xor [kb_state],eax |
xor [kb_lights],bl |
call set_lights |
jmp .no_key.end |
.no_key.down: |
or [kb_state],eax |
.no_key.end: |
cmp [keyboard_mode],1 ; return scancode |
jne .no_scancode |
mov [keyboard_mode_sys],1 |
movzx eax,byte[0xF400] |
cmp al,120 |
jae .no_scancode |
inc al |
mov [0xF400],al |
mov [0xF400+eax],ch |
.no_scancode: |
.exit.irq1: |
mov [check_idle_semaphore],5 |
mov al,0x20 ; ready for next irq |
out 0x20,al |
call return_to_caller |
jmp irq1 |
set_lights: |
mov al,0xED |
call kb_write |
mov al,[kb_lights] |
call kb_write |
ret |
;// mike.dld ] |
/kernel/trunk/hid/set_dtc.inc |
---|
0,0 → 1,191 |
;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: |
mov ecx,eax |
cli |
mov al,0x0d |
out 0x70,al |
in al,0x71 |
bt ax,7 |
jnc bat_low |
cmp ecx,2 ;day of week |
jne nosetweek |
test ebx,ebx ;test day of week |
je wrongtime |
cmp ebx,7 |
ja wrongtime |
mov dx,0x70 |
call startstopclk |
dec edx |
mov al,6 |
out dx,al |
inc edx |
mov al,bl |
out dx,al |
jmp endsettime |
nosetweek: ;set date |
cmp ecx,1 |
jne nosetdate |
cmp bl,0x99 ;test year |
ja wrongtime |
shl ebx,4 |
cmp bl,0x90 |
ja wrongtime |
cmp bh,0x99 ;test month |
ja wrongtime |
shr ebx,4 |
test bh,bh |
je wrongtime |
cmp bh,0x12 |
ja wrongtime |
shl ebx,8 |
bswap ebx ;ebx=00YYMMDD |
test bl,bl ;test day |
je wrongtime |
shl ebx,4 |
cmp bl,0x90 |
ja wrongtime |
shr ebx,4 |
cmp bh,2 ;February |
jne testday |
cmp bl,0x29 |
ja wrongtime |
jmp setdate |
testday: |
cmp bh,8 |
jb testday1 ;Aug-Dec |
bt bx,8 |
jnc days31 |
jmp days30 |
testday1: |
bt bx,8 ;Jan-Jul ex.Feb |
jnc days30 |
days31: |
cmp bl,0x31 |
ja wrongtime |
jmp setdate |
days30: |
cmp bl,0x30 |
ja wrongtime |
setdate: |
mov dx,0x70 |
call startstopclk |
dec edx |
mov al,7 ;set days |
out dx,al |
inc edx |
mov al,bl |
out dx,al |
dec edx |
mov al,8 ;set months |
out dx,al |
inc edx |
mov al,bh |
out dx,al |
dec edx |
mov al,9 ;set years |
out dx,al |
inc edx |
shr ebx,8 |
mov al,bh |
out dx,al |
jmp endsettime |
nosetdate: ;set time or alarm-clock |
cmp ecx,3 |
ja wrongtime |
cmp bl,0x23 |
ja wrongtime |
cmp bh,0x59 |
ja wrongtime |
shl ebx,4 |
cmp bl,0x90 |
ja wrongtime |
cmp bh,0x92 |
ja wrongtime |
shl ebx,4 |
bswap ebx ;00HHMMSS |
cmp bl,0x59 |
ja wrongtime |
shl ebx,4 |
cmp bl,0x90 |
ja wrongtime |
shr ebx,4 |
mov dx,0x70 |
call startstopclk |
dec edx |
cmp ecx,3 |
je setalarm |
xor eax,eax ;al=0-set seconds |
out dx,al |
inc edx |
mov al,bl |
out dx,al |
dec edx |
mov al,2 ;set minutes |
out dx,al |
inc edx |
mov al,bh |
out dx,al |
dec edx |
mov al,4 ;set hours |
out dx,al |
inc edx |
shr ebx,8 |
mov al,bh |
out dx,al |
jmp endsettime |
setalarm: |
mov al,1 ;set seconds for al. |
out dx,al |
inc edx |
mov al,bl |
out dx,al |
dec edx |
mov al,3 ;set minutes for al. |
out dx,al |
inc edx |
mov al,bh |
out dx,al |
dec edx |
mov al,5 ;set hours for al. |
out dx,al |
inc edx |
shr ebx,8 |
mov al,bh |
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 |
mov [esp+36],dword 0 |
ret |
bat_low: |
sti |
mov [esp+36],dword 2 |
ret |
wrongtime: |
sti |
mov [esp+36],dword 1 |
ret |
startstopclk: |
mov al,0x0b |
out dx,al |
inc dx |
in al,dx |
btc ax,7 |
out dx,al |
ret |
/kernel/trunk/kernel.asm |
---|
0,0 → 1,5730 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; |
;; Kolibri OS - based on source code Menuet OS, but not 100% compatible. |
;; |
;; See file COPYING or GNU.TXT for details with these additional details: |
;; - All code written in 32 bit x86 assembly language |
;; - No external code (eg. bios) at process execution time |
;; |
;; |
;; Compile with last version FASM |
;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include "KGLOBALS.INC" |
include "lang.inc" |
WinMapAddress equ 0x460000 |
display_data = 0x460000 |
max_processes equ 255 |
window_data equ 0x0000 |
tss_data equ 0xD20000 |
;tss_step equ (128+2048) ; tss & i/o - 16384 ports, * 256=557056 |
tss_step equ (128+8192) ; tss & i/o - 65535 ports, * 256=557056*4 |
draw_data equ 0xC00000 |
sysint_stack_data equ 0xC03000 |
twdw equ (0x3000-window_data) |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; |
;; 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 0x10000 |
macro diff16 title,l2 |
{ |
local s,d,l1 |
s = l2 |
display title,': 0x' |
repeat 8 |
d = 48 + s shr ((8-%) shl 2) and $0F |
if d > 57 |
d = d + 65-57-1 |
end if |
display d |
end repeat |
display 13,10 |
} |
jmp start_of_code |
; mike.dld { |
db 0 |
dd servetable-0x10000 |
draw_line dd __sys_draw_line |
disable_mouse dd __sys_disable_mouse |
draw_pointer dd __sys_draw_pointer |
drawbar dd __sys_drawbar |
putpixel dd __sys_putpixel |
; } mike.dld |
version db 'Kolibri OS version 0.5.0.0 ',13,10,13,10,0 |
;dd endofcode-0x10000 |
;db 'Boot02' |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
include "boot/preboot.inc" |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
preboot_lfb db 0 |
preboot_bootlog db 0 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 16 BIT INCLUDED FILES ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
include "KERNEL16.INC" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SWITCH TO 32 BIT PROTECTED MODE ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
os_data equ os_data_l-gdts ; GDTs |
os_code equ os_code_l-gdts |
int_code equ int_code_l-gdts |
int_data equ int_data_l-gdts |
tss0sys equ tss0sys_l-gdts |
graph_data equ 3+graph_data_l-gdts |
tss0 equ tss0_l-gdts |
tss0i equ tss0i_l-gdts |
app_code equ 3+app_code_l-gdts |
app_data equ 3+app_data_l-gdts |
; CR0 Flags - Protected mode and Paging |
mov ecx,0x00000001 |
;and ebx,65535 |
;cmp ebx,00100000000000000b ; lfb -> paging |
;jb no_paging |
;mov ax,0x0000 |
;mov es,ax |
;mov al,[es:0x901E] |
;cmp al,1 |
;je no_paging |
;or ecx, 0x80000000 |
;no_paging: |
; Enabling 32 bit protected mode |
sidt [cs:old_ints_h-0x10000] |
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 |
lgdt [cs:gdts-0x10000] ; Load GDT |
mov eax, cr0 ; Turn on paging // protected mode |
or eax, ecx |
and eax, 10011111b *65536*256 + 0xffffff ; caching enabled |
mov cr0, eax |
jmp byte $+2 |
mov ax,os_data ; Selector for os |
mov ds,ax |
mov es,ax |
mov fs,ax |
mov gs,ax |
mov ss,ax |
mov esp,0x30000 ; Set stack |
jmp pword os_code:B32 ; jmp to enable 32 bit mode |
use32 |
iglobal |
boot_memdetect db 'Determining amount of memory',0 |
boot_fonts db 'Fonts loaded',0 |
boot_tss db 'Setting TSSs',0 |
boot_cpuid db 'Reading CPUIDs',0 |
boot_devices db 'Detecting devices',0 |
boot_timer db 'Setting timer',0 |
boot_irqs db 'Reprogramming IRQs',0 |
boot_setmouse db 'Setting mouse',0 |
boot_windefs db 'Setting window defaults',0 |
boot_bgr db 'Calculating background',0 |
boot_resirqports db 'Reserving IRQs & ports',0 |
boot_setrports db 'Setting addresses for IRQs',0 |
boot_setostask db 'Setting OS task',0 |
boot_allirqs db 'Unmasking all IRQs',0 |
boot_tsc db 'Reading TSC',0 |
boot_pal_ega db 'Setting EGA/CGA 320x200 palette',0 |
boot_pal_vga db 'Setting VGA 640x480 palette',0 |
boot_mtrr db 'Setting MTRR',0 |
boot_tasking db 'All set - press ESC to start',0 |
endg |
iglobal |
boot_y dd 10 |
endg |
boot_log: |
pushad |
mov edx,esi |
.bll3: inc edx |
cmp [edx],byte 0 |
jne .bll3 |
sub edx,esi |
mov eax,10*65536 |
mov ax,word [boot_y] |
add [boot_y],dword 10 |
mov ebx,0xffffff |
mov ecx,esi |
mov edi,1 |
call dtext |
mov [novesachecksum],1000 |
call checkEgaCga |
cmp [preboot_blogesc],byte 1 |
je .bll2 |
cmp esi,boot_tasking |
jne .bll2 |
; begin ealex 04.08.05 |
; in al,0x61 |
; and al,01111111b |
; out 0x61,al |
; end ealex 04.08.05 |
.bll1: in al,0x60 ; wait for ESC key press |
cmp al,129 |
jne .bll1 |
.bll2: popad |
ret |
uglobal |
cpuid_0 dd 0,0,0,0 |
cpuid_1 dd 0,0,0,0 |
cpuid_2 dd 0,0,0,0 |
cpuid_3 dd 0,0,0,0 |
endg |
iglobal |
firstapp db 'LAUNCHER ' |
char db 'CHAR MT ' |
char2 db 'CHAR2 MT ' |
bootpath db '/KOLIBRI ' |
bootpath2 db 0 |
vmode db 'VMODE MDR' |
vrr_m db 'VRR_M ' |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 32 BIT ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
B32: |
; CLEAR 0x280000-0xF00000 |
xor eax,eax |
mov edi,0x280000 |
mov ecx,(0x100000*0xF-0x280000) / 4 |
cld |
rep stosd |
; CLEAR 0x80000-0x90000 |
; xor eax,eax |
mov edi,0x80000 |
mov ecx,(0x90000-0x80000)/4 |
; cld |
rep stosd |
; CLEAR KERNEL UNDEFINED GLOBALS |
mov edi, endofcode |
mov ecx, (uglobals_size/4)+4 |
rep stosd |
; SAVE & CLEAR 0-0xffff |
mov esi,0x0000 |
mov edi,0x2F0000 |
mov ecx,0x10000 / 4 |
cld |
rep movsd |
xor eax,eax |
mov edi,0 |
mov ecx,0x10000 / 4 |
cld |
rep stosd |
; SAVE REAL MODE VARIABLES |
; movzx eax,byte [0x2f0000+0x9010] ; mouse port |
; mov [0xF604],byte 1 ;al |
mov al,[0x2f0000+0x9000] ; bpp |
mov [0xFBF1],al |
movzx eax,word [0x2f0000+0x900A] ; X max |
dec eax |
mov [0xfe00],eax |
movzx eax,word [0x2f0000+0x900C] ; Y max |
dec eax |
mov [0xfe04],eax |
movzx eax,word [0x2f0000+0x9008] ; screen mode |
mov [0xFE0C],eax |
mov eax,[0x2f0000+0x9014] ; Vesa 1.2 bnk sw add |
mov [0xE030],eax |
mov [0xfe08],word 640*4 ; Bytes PerScanLine |
cmp [0xFE0C],word 0x13 ; 320x200 |
je @f |
cmp [0xFE0C],word 0x12 ; VGA 640x480 |
je @f |
mov ax,[0x2f0000+0x9001] ; for other modes |
mov [0xfe08],ax |
@@: |
; GRAPHICS ADDRESSES |
;mov eax,0x100000*8 ; LFB address |
;cmp [0xfe0c],word 0x13 |
;je no_d_lfb |
;cmp [0xfe0c],word 0x12 |
;je no_d_lfb |
;cmp [0x2f0000+0x901e],byte 1 |
;jne no_d_lfb |
mov byte [0x2f0000+0x901e],0x0 |
mov eax,[0x2f0000+0x9018] |
;no_d_lfb: |
mov [0xfe80],eax |
cmp [0xfe0c],word 0100000000000000b |
jge setvesa20 |
cmp [0xfe0c],word 0x13 |
je v20ga32 |
mov [0xe020],dword Vesa12_putpixel24 ; Vesa 1.2 |
mov [0xe024],dword Vesa12_getpixel24 |
cmp [0xfbf1],byte 24 |
jz ga24 |
mov [0xe020],dword Vesa12_putpixel32 |
mov [0xe024],dword Vesa12_getpixel32 |
ga24: |
jmp v20ga24 |
setvesa20: |
mov [0xe020],dword Vesa20_putpixel24 ; Vesa 2.0 |
mov [0xe024],dword Vesa20_getpixel24 |
cmp [0xfbf1],byte 24 |
jz v20ga24 |
v20ga32: |
mov [0xe020],dword Vesa20_putpixel32 |
mov [0xe024],dword Vesa20_getpixel32 |
v20ga24: |
cmp [0xfe0c],word 0x12 ; 16 C VGA 640x480 |
jne no_mode_0x12 |
mov [0xe020],dword VGA_putpixel |
mov [0xe024],dword Vesa20_getpixel32 |
no_mode_0x12: |
; MEMORY MODEL |
; mov [0xfe84],dword 0x100000*16 ; apps mem base address |
; movzx ecx,byte [0x2f0000+0x9030] |
; dec ecx |
; mov eax,16*0x100000 ; memory-16 |
; shl eax,cl |
; mov [0xfe8c],eax ; memory for use |
; cmp eax,16*0x100000 |
; jne no16mb |
; mov [0xfe84],dword 0xD80000 ; !!! 10 !!! |
; no16mb: |
; init: |
; 1) 0xFE84 - applications base |
; 2) 0xFE8C - total amount of memory |
xor edi, edi |
m_GMS_loop: |
add edi, 0x400000 |
mov eax, dword [edi] |
mov dword [edi], 'TEST' |
wbinvd |
cmp dword [edi], 'TEST' |
jne m_GMS_exit |
cmp dword [0], 'TEST' |
je m_GMS_exit |
mov dword [es:edi], eax |
jmp m_GMS_loop |
m_GMS_exit: |
mov [edi], eax |
; now edi contains the EXACT amount of memory |
mov eax, 0x100000*16 |
cmp edi, eax ;0x100000*16 |
jb $ ; less than 16 Mb |
mov dword [0xFE84], eax ;0x100000*16 |
cmp edi, eax ;0x100000*16 |
jne @f |
mov dword [0xFE84], 0xD80000 ; =0x100000*13.5 |
@@: |
mov dword [0xFE8C], edi |
;!!!!!!!!!!!!!!!!!!!!!!!!!! |
include 'detect/disks.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!!!! |
; CHECK EXTRA REGION |
; ENABLE PAGING |
mov eax,cr0 |
or eax,0x80000000 |
mov cr0,eax |
jmp $+2 |
mov dword [0xfe80],0x800000 |
;Set base of graphic segment to linear address of LFB |
mov eax,[0xfe80] ; set for gs |
mov [graph_data_l+2],ax |
shr eax,16 |
mov [graph_data_l+4],al |
mov [graph_data_l+7],ah |
; READ RAMDISK IMAGE FROM HD |
;!!!!!!!!!!!!!!!!!!!!!!! |
include 'boot/rdload.inc' |
;!!!!!!!!!!!!!!!!!!!!!!! |
; mov [dma_hdd],1 |
; CALCULATE FAT CHAIN FOR RAMDISK |
call calculatefatchain |
; LOAD VMODE DRIVER |
;!!!!!!!!!!!!!!!!!!!!!!! |
include 'vmodeld.inc' |
;!!!!!!!!!!!!!!!!!!!!!!! |
; LOAD FONTS I and II |
mov [0x3000],dword 1 |
mov [0x3004],dword 1 |
mov [0x3010],dword 0x3020 |
mov eax,char |
mov esi,12 |
xor ebx,ebx |
mov ecx,26000 |
mov edx,0x37000 |
call fileread |
mov eax,char2 |
mov esi,12 |
xor ebx,ebx |
mov ecx,26000 |
mov edx,0x30000 |
call fileread |
mov esi,boot_fonts |
call boot_log |
; PRINT AMOUNT OF MEMORY |
mov esi, boot_memdetect |
call boot_log |
movzx ecx, word [boot_y] |
or ecx, (10+29*6) shl 16 ; "Determining amount of memory" |
sub ecx, 10 |
mov edx, 0xFFFFFF |
mov ebx, [0xFE8C] |
shr ebx, 20 |
mov edi, 1 |
mov eax, 0x00040000 |
call display_number |
; CHECK EXTENDED REGION |
; mov dword [0x80000000],0x12345678 |
; cmp dword [0x80000000],0x12345678 |
; jz extended_region_found |
; mov esi,boot_ext_region |
; call boot_log |
; jmp $ |
;extended_region_found: |
call MEM_Init |
;add 0x800000-0xc00000 area |
cmp word [0xfe0c],0x13 |
jle .less_memory |
mov eax,0x80000000 ;linear address |
mov ebx,0x400000 shr 12 ;size in pages (4Mb) |
mov ecx,0x800000 ;physical address |
jmp .end_first_block |
.less_memory: |
mov eax,0x80180000 ;linear address |
mov ebx,0x280000 shr 12 ;size in pages (2.5Mb) |
mov ecx,0x980000 ;physical address |
.end_first_block: |
call MEM_Add_Heap ;nobody can lock mutex yet |
call create_general_page_table |
;add 0x1000000(0xd80000)-end_of_memory area |
mov eax,second_base_address |
mov ebx,[0xfe8c] |
mov ecx,[0xfe84] |
sub ebx,ecx |
shr ebx,12 |
add eax,ecx |
call MEM_Add_Heap |
;init physical memory manager. |
call Init_Physical_Memory_Manager |
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f |
mov esi,boot_irqs |
call boot_log |
call rerouteirqs |
mov esi,boot_tss |
call boot_log |
; BUILD SCHEDULER |
call build_scheduler ; sys32.inc |
; LOAD IDT |
; <IP 05.02.2005> |
lidt [cs:idtreg] ;[cs:idts] |
; </IP> |
; READ CPUID RESULT |
mov esi,boot_cpuid |
call boot_log |
pushfd ; get current flags |
pop eax |
mov ecx,eax |
xor eax,0x00200000 ; attempt to toggle ID bit |
push eax |
popfd |
pushfd ; get new EFLAGS |
pop eax |
push ecx ; restore original flags |
popfd |
and eax,0x00200000 ; if we couldn't toggle ID, |
and ecx,0x00200000 ; then this is i486 |
cmp eax,ecx |
jz nopentium |
; It's Pentium or later. Use CPUID |
mov edi,cpuid_0 |
mov esi,0 |
cpuid_new_read: |
mov eax,esi |
cpuid |
call cpuid_save |
add edi,4*4 |
cmp esi,3 |
jge cpuid_done |
cmp esi,[cpuid_0] |
jge cpuid_done |
inc esi |
jmp cpuid_new_read |
cpuid_save: |
mov [edi+00],eax |
mov [edi+04],ebx |
mov [edi+8],ecx |
mov [edi+12],edx |
ret |
cpuid_done: |
nopentium: |
; CR4 flags - enable fxsave / fxrstore |
; |
; finit |
; mov eax,1 |
; cpuid |
; test edx,1000000h |
; jz fail_fpu |
; mov eax,cr4 |
; or eax,200h ; Enable fxsave/fxstor |
; mov cr4,eax |
; fail_fpu: |
; DETECT DEVICES |
mov esi,boot_devices |
call boot_log |
call detect_devices |
; TIMER SET TO 1/100 S |
mov esi,boot_timer |
call boot_log |
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 |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
;include 'detect/commouse.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
; SET MOUSE |
mov esi,boot_setmouse |
call boot_log |
call setmouse |
; SET PRELIMINARY WINDOW STACK AND POSITIONS |
mov esi,boot_windefs |
call boot_log |
call setwindowdefaults |
; SET BACKGROUND DEFAULTS |
mov esi,boot_bgr |
call boot_log |
call calculatebackground |
; RESERVE SYSTEM IRQ'S JA PORT'S |
mov esi,boot_resirqports |
call boot_log |
call reserve_irqs_ports |
; SET PORTS FOR IRQ HANDLERS |
mov esi,boot_setrports |
call boot_log |
call setirqreadports |
; SET UP OS TASK |
mov esi,boot_setostask |
call boot_log |
; name for OS/IDLE process |
mov [0x80000+256+0],dword 'OS/I' |
mov [0x80000+256+4],dword 'DLE ' |
; task list |
mov [0x3004],dword 2 ; number of processes |
mov [0x3000],dword 0 ; process count - start with os task |
mov [0x3020+0xE],byte 1 ; on screen number |
mov [0x3020+0x4],dword 1 ; process id number |
; set default flags & stacks |
mov [l.eflags],dword 0x11202 ; sti and resume |
mov [l.ss0], os_data |
;mov [l.ss1], ring1_data |
;mov [l.ss2], ring2_data |
mov [l.esp0], 0x52000 |
mov [l.esp1], 0x53000 |
mov [l.esp2], 0x54000 |
; osloop - TSS |
mov eax,cr3 |
mov [l.cr3],eax |
mov [l.eip],osloop |
; <Ivan Poddubny 14/03/2004> |
mov [l.esp],0x30000 ;0x2ffff |
; </Ivan Poddubny 14/03/2004> |
mov [l.cs],os_code |
mov [l.ss],os_data |
mov [l.ds],os_data |
mov [l.es],os_data |
mov [l.fs],os_data |
mov [l.gs],os_data |
; move tss to tss_data+tss_step |
mov esi,tss_sceleton |
mov edi,tss_data+tss_step |
mov ecx,120/4 |
cld |
rep movsd |
mov ax,tss0 |
ltr ax |
; READ TSC / SECOND |
mov esi,boot_tsc |
call boot_log |
call _rdtsc |
mov ecx,eax |
mov esi,250 ; wait 1/4 a second |
call delay_ms |
call _rdtsc |
sub eax,ecx |
shl eax,2 |
mov [0xf600],eax ; save tsc / sec |
; SET VARIABLES |
call set_variables |
; STACK AND FDC |
call stack_init |
call fdc_init |
; PALETTE FOR 320x200 and 640x480 16 col |
cmp [0xfe0c],word 0x12 |
jne no_pal_vga |
mov esi,boot_pal_vga |
call boot_log |
call paletteVGA |
no_pal_vga: |
cmp [0xfe0c],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 |
; MTRR'S |
call enable_mtrr |
; LOAD FIRST APPLICATION |
mov [0x3000],dword 1 ;1 |
mov [0x3004],dword 1 ;1 |
cli |
mov al,[0x2f0000+0x9030] |
cmp al,1 |
jne no_load_vrr_m |
mov eax,vrr_m |
call start_application_fl |
cmp eax,2 ; if no vrr_m app found |
je first_app_found |
no_load_vrr_m: |
mov eax,firstapp |
call start_application_fl |
cmp eax,2 ; if no first app found - halt |
je first_app_found |
mov eax, 0xDEADBEEF |
hlt ;jmp $ |
first_app_found: |
cli |
mov [0x3004],dword 2 |
mov [0x3000],dword 1 |
; START MULTITASKING |
mov esi,boot_tasking |
call boot_log |
mov [0xe000],byte 1 ; multitasking enabled |
mov al, 0xf6 ; Ñáðîñ êëàâèàòóðû, ðàçðåøèòü ñêàíèðîâàíèå |
call kb_write |
mov ecx,0 |
wait_loop_1: ; variant 2 |
; ÷èòàåì ïîðò ñîñòîÿíèÿ ïðîöåññîðà 8042 |
in al,64h |
and al,00000010b ; ôëàã ãîòîâíîñòè |
; îæèäàåì ãîòîâíîñòü ïðîöåññîðà 8042 |
loopnz wait_loop_1 |
; SET KEYBOARD PARAMETERS |
; mov al, 0xED ; svetodiody - 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, 00100010b ; 24 500 ;00100100b ; 20 500 |
call kb_write |
call kb_read |
;// mike.dld [ |
call set_lights |
;// mike.dld ] |
; UNMASK ALL IRQ'S |
mov esi,boot_allirqs |
call boot_log |
cli ;guarantee forbidance of interrupts. |
mov al,0 ; unmask all irq's |
out 0xA1,al |
out 0x21,al |
mov ecx,32 |
ready_for_irqs: |
mov al,0x20 ; ready for irqs |
out 0x20,al |
out 0xa0,al |
loop ready_for_irqs ; flush the queue |
; mov [dma_hdd],1 |
sti |
jmp $ ; wait here for timer to take control |
; Fly :) |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; ; |
; MAIN OS LOOP ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
osloop: |
call check_mouse_data |
call [draw_pointer] |
call checkbuttons |
call main_loop_sys_getkey |
call checkwindows |
call check_window_move_request |
call checkmisc |
call checkEgaCga |
call stack_handler |
call checkidle |
call check_fdd_motor_status |
jmp osloop |
;temp_pointers: |
; rd 32 |
; seed dd 0x12345678 |
checkidle: |
pushad |
cmp [check_idle_semaphore],0 |
jne no_idle_state |
call change_task |
mov eax,[idlemem] |
mov ebx,[timer_ticks] ;[0xfdf0] |
cmp eax,ebx |
jnz idle_exit |
call _rdtsc |
mov ecx,eax |
idle_loop: |
hlt |
cmp [check_idle_semaphore],0 |
jne idle_loop_exit |
mov eax,[timer_ticks] ;[0xfdf0] |
cmp ebx,eax |
jz idle_loop |
idle_loop_exit: |
mov [idlemem],eax |
call _rdtsc |
sub eax,ecx |
mov ebx,[idleuse] |
add ebx,eax |
mov [idleuse],ebx |
popad |
ret |
idle_exit: |
mov ebx,[timer_ticks] ;[0xfdf0] |
mov [idlemem],ebx |
call change_task |
popad |
ret |
no_idle_state: |
dec [check_idle_semaphore] |
mov ebx,[timer_ticks] ;[0xfdf0] |
mov [idlemem],ebx |
call change_task |
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 ; |
; ; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
enable_mtrr: |
pushad |
cmp [0x2f0000+0x901c],byte 2 |
je no_mtrr |
mov eax,[0xFE0C] ; if no LFB then no MTRR |
test eax,0100000000000000b |
jz no_mtrr |
mov edx,[cpuid_1+3*4] ; edx - MTRR's supported ? |
test edx,1000000000000b |
jz no_mtrr |
call find_empty_mtrr |
cmp ecx,0 |
jz no_mtrr |
mov esi,boot_mtrr ; 'setting mtrr' |
call boot_log |
mov edx,0x0 ; LFB , +8 M , write combine |
mov eax,[0x2f9018] |
or eax,1 |
wrmsr |
inc ecx |
mov edx,0xf |
mov eax,0xff800800 |
wrmsr |
mov ecx,0x2ff ; enable mtrr's |
rdmsr |
or eax,100000000000b ; set |
wrmsr |
no_mtrr: |
popad |
ret |
find_empty_mtrr: ; 8 pairs checked |
mov ecx,0x201-2 |
mtrr_find: |
add ecx,2 |
cmp ecx,0x200+8*2 |
jge no_free_mtrr |
rdmsr |
test eax,0x0800 |
jnz mtrr_find |
dec ecx |
ret |
no_free_mtrr: |
mov ecx,0 |
ret |
reserve_irqs_ports: |
pushad |
mov [irq_owner+4*0],byte 1 ; timer |
mov [irq_owner+4*1],byte 1 ; keyboard |
mov [irq_owner+4*5],byte 1 ; sound blaster |
mov [irq_owner+4*6],byte 1 ; floppy diskette |
mov [irq_owner+4*13],byte 1 ; math co-pros |
mov [irq_owner+4*14],byte 1 ; ide I |
mov [irq_owner+4*15],byte 1 ; ide II |
movzx eax,byte [0xf604] ; mouse irq |
dec eax |
add eax,mouseirqtable |
movzx eax,byte [eax] |
shl eax,2 |
mov [irq_owner+eax],byte 1 |
; RESERVE PORTS |
mov edi,1 ; 0x00-0xff |
mov [0x2d0000],edi |
shl edi,4 |
mov [0x2d0000+edi+0],dword 1 |
mov [0x2d0000+edi+4],dword 0x0 |
mov [0x2d0000+edi+8],dword 0xff |
cmp [0xf604],byte 2 ; com1 mouse -> 0x3f0-0x3ff |
jne ripl1 |
inc dword [0x2d0000] |
mov edi,[0x2d0000] |
shl edi,4 |
mov [0x2d0000+edi+0],dword 1 |
mov [0x2d0000+edi+4],dword 0x3f0 |
mov [0x2d0000+edi+8],dword 0x3ff |
ripl1: |
cmp [0xf604],byte 3 ; com2 mouse -> 0x2f0-0x2ff |
jne ripl2 |
inc dword [0x2d0000] |
mov edi,[0x2d0000] |
shl edi,4 |
mov [0x2d0000+edi+0],dword 1 |
mov [0x2d0000+edi+4],dword 0x2f0 |
mov [0x2d0000+edi+8],dword 0x2ff |
ripl2: |
popad |
ret |
iglobal |
mouseirqtable db 12 ; ps2 |
db 4 ; com1 |
db 3 ; com2 |
endg |
setirqreadports: |
mov [irq12read+0],dword 0x60 + 0x01000000 ; read port 0x60 , byte |
mov [irq12read+4],dword 0 ; end of port list |
mov [irq04read+0],dword 0x3f8 + 0x01000000 ; read port 0x3f8 , byte |
mov [irq04read+4],dword 0 ; end of port list |
mov [irq03read+0],dword 0x2f8 + 0x01000000 ; read port 0x2f8 , byte |
mov [irq03read+4],dword 0 ; end of port list |
ret |
iglobal |
process_number dd 0x1 |
endg |
uglobal |
novesachecksum dd 0x0 |
endg |
checkEgaCga: |
cmp [0xfe0c],dword 0x13 |
je cnvl |
ret |
cnvl: |
pushad |
mov ecx,[0xfb0a] |
cmp ecx,[novesachecksum] |
jne novesal |
popad |
ret |
novesal: |
mov [novesachecksum],ecx |
mov ecx,0 |
movzx eax,word [0xfb0c] |
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 [0xfb0a] |
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,[0xfe80] |
add esi,ecx |
mov edi,0xa0000 |
mov edx,200 |
mov ecx,320 |
cld |
m13pix: |
lodsd |
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 |
stosb |
loop m13pix |
mov ecx,320 |
add esi,4*(640-320) |
dec edx |
jnz m13pix |
popad |
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 |
set_variables: |
mov ecx,0x100 ; flush port 0x60 |
.fl60: in al,0x60 |
loop .fl60 |
mov [0xfcff],byte 0 ; mouse buffer |
mov [0xf400],byte 0 ; keyboard buffer |
mov [0xf500],byte 0 ; button buffer |
; mov [0xfb0a],dword 100*65536+100 ; mouse x/y |
push eax |
mov ax,[0x2f0000+0x900c] |
shr ax,1 |
shl eax,16 |
mov ax,[0x2f0000+0x900A] |
shr ax,1 |
mov [0xfb0a],eax |
pop eax |
mov byte [SB16_Status],0 ; Minazzi Paolo |
mov [display_data-12],dword 1 ; tiled background |
mov [0xfe88],dword 0x2C0000 ; address of button list |
;!! IP 04.02.2005: |
mov [next_usage_update], 100 |
mov byte [0xFFFF], 0 ; change task if possible |
ret |
;* mouse centered - start code- Mario79 |
mouse_centered: |
push eax |
mov eax,[0xFE00] |
shr eax,1 |
mov [0xFB0A],ax |
mov eax,[0xFE04] |
shr eax,1 |
mov [0xFB0C],ax |
pop eax |
ret |
;* mouse centered - end code- Mario79 |
align 4 |
sys_outport: |
mov edi,ebx ; separate flag for read / write |
and ebx,65535 |
mov ecx,[0x2d0000] |
test ecx,ecx |
jne sopl8 |
mov [esp+36],dword 1 |
ret |
sopl8: |
mov edx,[0x3010] |
mov edx,[edx+0x4] |
and ebx,65535 |
cld |
sopl1: |
mov esi,ecx |
shl esi,4 |
add esi,0x2d0000 |
cmp edx,[esi+0] |
jne sopl2 |
cmp ebx,[esi+4] |
jb sopl2 |
cmp ebx,[esi+8] |
jg sopl2 |
jmp sopl3 |
sopl2: |
dec ecx |
jnz sopl1 |
mov [esp+36],dword 1 |
ret |
sopl3: |
test edi,0x80000000 ; read ? |
jnz sopl4 |
mov dx,bx ; write |
out dx,al |
mov [esp+36],dword 0 |
ret |
sopl4: |
mov dx,bx ; read |
in al,dx |
and eax,0xff |
mov [esp+36],dword 0 |
mov [esp+24],eax |
ret |
align 4 |
sys_sb16: |
cmp word [sb16],word 0 |
jnz sb16l1 |
mov [esp+36],dword 1 |
ret |
sb16l1: |
mov [esp+36],dword 0 |
cmp eax,1 ; set volume - main |
jnz sb16l2 |
mov dx,word [sb16] |
add dx,4 |
mov al,0x22 |
out dx,al |
mov esi,1 |
call delay_ms |
mov eax,ebx |
inc edx |
out dx,al |
ret |
sb16l2: |
cmp eax,2 ; set volume - cd |
jnz sb16l3 |
mov dx,word [sb16] |
add dx,4 |
mov al,0x28 |
out dx,al |
mov esi,1 |
call delay_ms |
mov eax,ebx |
add edx,1 |
out dx,al |
ret |
sb16l3: |
mov [esp+36],dword 2 |
ret |
align 4 |
sys_sb16II: |
cmp word [sb16],word 0 |
jnz IIsb16l1 |
mov [esp+36],dword 1 |
ret |
IIsb16l1: |
cmp eax,1 ; set volume - main |
jnz IIsb16l2 |
; L |
mov dx,word [sb16] |
add dx,4 |
mov al,0x30 |
out dx,al |
mov eax,ebx |
inc edx |
out dx,al |
; R |
mov dx,word [sb16] |
add dx,4 |
mov al,0x31 |
out dx,al |
mov eax,ebx |
inc edx |
out dx,al |
mov [esp+36],dword 0 |
ret |
IIsb16l2: |
cmp eax,2 ; set volume - cd |
jnz IIsb16l3 |
; L |
mov dx,word [sb16] |
add dx,4 |
mov al,0x36 |
out dx,al |
mov eax,ebx |
inc edx |
out dx,al |
; R |
mov dx,word [sb16] |
add dx,4 |
mov al,0x37 |
out dx,al |
mov eax,ebx |
inc edx |
out dx,al |
mov [esp+36],dword 0 |
ret |
IIsb16l3: |
mov [esp+36],dword 2 |
ret |
align 4 |
sys_wss: |
cmp word [wss],word 0 |
jnz wssl1 |
mov [esp+36],dword 1 |
ret |
wssl1: |
cmp eax,1 ; set volume - main |
jnz wssl2 |
mov [esp+36],dword 0 |
ret |
wssl2: |
cmp eax,2 ; set volume - cd |
jnz wssl3 |
; L |
mov dx,word [wss] |
add dx,4 |
mov al,0x2 |
out dx,al |
mov esi,1 |
call delay_ms |
mov eax,ebx |
inc edx |
out dx,al |
; R |
mov dx,word [wss] |
add dx,4 |
mov al,0x3 |
out dx,al |
mov esi,1 |
call delay_ms |
mov eax,ebx |
inc edx |
out dx,al |
mov [esp+36],dword 0 |
ret |
wssl3: |
mov [esp+36],dword 2 |
ret |
display_number: |
; 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 |
cmp eax,0xffff ; length > 0 ? |
jge cont_displ |
ret |
cont_displ: |
cmp eax,60*0x10000 ; length <= 60 ? |
jbe cont_displ2 |
ret |
cont_displ2: |
pushad |
cmp al,1 ; ecx is a pointer ? |
jne displnl1 |
mov edi,[0x3010] |
mov edi,[edi+0x10] |
mov ebx,[edi+ebx] |
displnl1: |
sub esp,64 |
cmp ah,0 ; DECIMAL |
jne no_display_desnum |
shr eax,16 |
and eax,0x2f |
push eax |
;mov edi,[0x3010] |
;mov edi,[edi+0x10] |
mov edi,esp |
add edi,4+64 |
mov ecx,eax |
mov eax,ebx |
mov ebx,10 |
d_desnum: |
xor edx,edx |
div ebx |
add dl,48 |
mov [edi],dl |
dec edi |
loop d_desnum |
pop eax |
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,0x2f |
push eax |
;mov edi,[0x3010] |
;mov edi,[edi+0x10] |
mov edi,esp |
add edi,4+64 |
mov ecx,eax |
mov eax,ebx |
mov ebx,16 |
d_hexnum: |
xor edx,edx |
div ebx |
add edx,hexletters |
mov dl,[edx] |
mov [edi],dl |
dec edi |
loop d_hexnum |
pop eax |
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,0x2f |
push eax |
;mov edi,[0x3010] |
;mov edi,[edi+0x10] |
mov edi,esp |
add edi,4+64 |
mov ecx,eax |
mov eax,ebx |
mov ebx,2 |
d_binnum: |
xor edx,edx |
div ebx |
add dl,48 |
mov [edi],dl |
dec edi |
loop d_binnum |
pop eax |
call draw_num_text |
add esp,64 |
popad |
ret |
no_display_binnum: |
add esp,64 |
popad |
ret |
draw_num_text: |
; dtext |
; |
; eax x & y |
; ebx color |
; ecx start of text |
; edx length |
; edi 1 force |
mov edx,eax |
mov ecx,65 |
sub ecx,eax |
add ecx,esp |
add ecx,4 |
mov eax,[esp+64+32-8+4] |
mov ebx,[esp+64+32-12+4] |
push edx ; add window start x & y |
push ebx |
mov edx,[0x3010] |
mov ebx,[edx-twdw] |
shl ebx,16 |
add ebx,[edx-twdw+4] |
add eax,ebx |
pop ebx |
pop edx |
mov edi,0 |
call dtext |
ret |
read_string: |
; eax read_area |
; ebx color of letter |
; ecx color of background |
; edx number of letters to read |
; esi [x start]*65536 + [y_start] |
ret |
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 |
; 4=sb16 base , base io address |
; 5=system language, 1eng 2fi 3ger 4rus |
; 6=wss base , base io address |
; 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 |
mov [esp+36],dword 0 |
cmp eax,1 ; MIDI |
jnz nsyse1 |
cmp ebx,0x100 |
jb nsyse1 |
mov edx,65535 |
cmp edx,ebx |
jb nsyse1 |
mov [midi_base],bx |
mov word [mididp],bx |
inc bx |
mov word [midisp],bx |
ret |
midi_base dw 0 |
nsyse1: |
cmp eax,2 ; KEYBOARD |
jnz nsyse2 |
cmp ebx,1 |
jnz kbnobase |
mov edi,[0x3010] |
add ecx,[edi+0x10] |
mov eax,ecx |
mov ebx,keymap |
mov ecx,128 |
call memmove |
ret |
kbnobase: |
cmp ebx,2 |
jnz kbnoshift |
mov edi,[0x3010] |
add ecx,[edi+0x10] |
mov eax,ecx |
mov ebx,keymap_shift |
mov ecx,128 |
call memmove |
ret |
kbnoshift: |
cmp ebx,3 |
jne kbnoalt |
mov edi,[0x3010] |
add ecx,[edi+0x10] |
mov eax,ecx |
mov ebx,keymap_alt |
mov ecx,128 |
call memmove |
ret |
kbnoalt: |
cmp ebx,9 |
jnz kbnocountry |
mov word [keyboard],cx |
ret |
kbnocountry: |
mov [esp+36],dword 1 |
ret |
nsyse2: |
cmp eax,3 ; CD |
jnz nsyse3 |
mov [cd_base],bl |
cmp ebx,1 |
jnz noprma |
mov [cdbase],0x1f0 |
mov [cdid],0xa0 |
noprma: |
cmp ebx,2 |
jnz noprsl |
mov [cdbase],0x1f0 |
mov [cdid],0xb0 |
noprsl: |
cmp ebx,3 |
jnz nosema |
mov [cdbase],0x170 |
mov [cdid],0xa0 |
nosema: |
cmp ebx,4 |
jnz nosesl |
mov [cdbase],0x170 |
mov [cdid],0xb0 |
nosesl: |
ret |
cd_base db 0 |
nsyse3: |
cmp eax,4 ; SB |
jnz nsyse4 |
cmp ebx,0x100 |
jb nsyse4 |
mov edx,65535 |
cmp edx,ebx |
jb nsyse4 |
mov word [sb16],bx |
ret |
nsyse4: |
cmp eax,5 ; SYSTEM LANGUAGE |
jnz nsyse5 |
mov [syslang],ebx |
ret |
nsyse5: |
cmp eax,6 ; WSS |
jnz nsyse6 |
cmp ebx,0x100 |
jb nsyse6 |
mov [wss],ebx |
ret |
wss_temp dd 0 |
nsyse6: |
cmp eax,7 ; HD BASE |
jne nsyse7 |
mov [hd_base],bl |
cmp ebx,1 |
jnz noprmahd |
mov [hdbase],0x1f0 |
mov [hdid],0x0 |
mov [hdpos],1 |
; call set_FAT32_variables |
noprmahd: |
cmp ebx,2 |
jnz noprslhd |
mov [hdbase],0x1f0 |
mov [hdid],0x10 |
mov [hdpos],2 |
; call set_FAT32_variables |
noprslhd: |
cmp ebx,3 |
jnz nosemahd |
mov [hdbase],0x170 |
mov [hdid],0x0 |
mov [hdpos],3 |
; call set_FAT32_variables |
nosemahd: |
cmp ebx,4 |
jnz noseslhd |
mov [hdbase],0x170 |
mov [hdid],0x10 |
mov [hdpos],4 |
; call set_FAT32_variables |
noseslhd: |
mov [0xfe10],dword 0 |
call reserve_hd1 |
call clear_hd_cache |
mov [hd1_status],0 ; free |
ret |
hd_base db 0 |
nsyse7: |
cmp eax,8 ; HD PARTITION |
jne nsyse8 |
mov [fat32part],ebx |
; call set_FAT32_variables |
call reserve_hd1 |
call clear_hd_cache |
pusha |
call choice_necessity_partition_1 |
popa |
mov [hd1_status],0 ; free |
ret |
nsyse8: |
cmp eax,10 ; SOUND DMA CHANNEL |
jne no_set_sound_dma |
mov [sound_dma],ebx |
ret |
no_set_sound_dma: |
cmp eax,11 ; ENABLE LBA READ |
jne no_set_lba_read |
and ebx,1 |
mov [lba_read_enabled],ebx |
ret |
no_set_lba_read: |
cmp eax,12 ; ENABLE PCI ACCESS |
jne no_set_pci_access |
and ebx,1 |
mov [pci_access_enabled],ebx |
ret |
no_set_pci_access: |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
include 'vmodeint.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
mov [esp+36],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 |
; 4=sb16 base , base io address |
; 5=system language, 1eng 2fi 3ger 4rus |
; 6=wss base |
; 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 |
jne ngsyse1 |
movzx eax,[midi_base] |
mov [esp+36],eax |
ret |
ngsyse1: |
cmp eax,2 |
jne ngsyse2 |
cmp ebx,1 |
jnz kbnobaseret |
mov edi,[0x3010] |
add ecx,[edi+0x10] |
mov ebx,ecx |
mov eax,keymap |
mov ecx,128 |
call memmove |
ret |
kbnobaseret: |
cmp ebx,2 |
jnz kbnoshiftret |
mov edi,[0x3010] |
add ecx,[edi+0x10] |
mov ebx,ecx |
mov eax,keymap_shift |
mov ecx,128 |
call memmove |
ret |
kbnoshiftret: |
cmp ebx,3 |
jne kbnoaltret |
mov edi,[0x3010] |
add ecx,[edi+0x10] |
mov ebx,ecx |
mov eax,keymap_alt |
mov ecx,128 |
call memmove |
ret |
kbnoaltret: |
cmp ebx,9 |
jnz ngsyse2 |
movzx eax,word [keyboard] |
mov [esp+36],eax |
ret |
ngsyse2: |
cmp eax,3 |
jnz ngsyse3 |
movzx eax,[cd_base] |
mov [esp+36],eax |
ret |
ngsyse3: |
cmp eax,4 |
jne ngsyse4 |
mov eax,[sb16] |
mov [esp+36],eax |
ret |
ngsyse4: |
cmp eax,5 |
jnz ngsyse5 |
mov eax,[syslang] |
mov [esp+36],eax |
ret |
ngsyse5: |
cmp eax,6 |
jnz ngsyse6 |
mov eax,[wss] |
mov [esp+36],eax |
ret |
ngsyse6: |
cmp eax,7 |
jnz ngsyse7 |
movzx eax,[hd_base] |
mov [esp+36],eax |
ret |
ngsyse7: |
cmp eax,8 |
jnz ngsyse8 |
mov eax,[fat32part] |
mov [esp+36],eax |
ret |
ngsyse8: |
cmp eax,9 |
jne ngsyse9 |
mov eax,[timer_ticks] ;[0xfdf0] |
mov [esp+36],eax |
ret |
ngsyse9: |
cmp eax,10 |
jnz ngsyse10 |
mov eax,[sound_dma] |
mov [esp+36],eax |
ret |
ngsyse10: |
cmp eax,11 |
jnz ngsyse11 |
mov eax,[lba_read_enabled] |
mov [esp+36],eax |
ret |
ngsyse11: |
cmp eax,12 |
jnz ngsyse12 |
mov eax,[pci_access_enabled] |
mov [esp+36],eax |
ret |
ngsyse12: |
mov [esp+36],dword 1 |
ret |
align 4 |
readmousepos: |
; eax=0 screen relative |
; eax=1 window relative |
; eax=2 buttons pressed |
test eax,eax |
jnz nosr |
mov eax,[0xfb0a] |
shl eax,16 |
mov ax,[0xfb0c] |
mov [esp+36],eax |
ret |
nosr: |
cmp eax,1 |
jnz nowr |
mov eax,[0xfb0a] |
shl eax,16 |
mov ax,[0xfb0c] |
mov esi,[0x3010] |
sub esi,twdw |
mov bx,[esi] |
shl ebx,16 |
mov bx,[esi+4] |
sub eax,ebx |
mov [esp+36],eax |
ret |
nowr: |
cmp eax,2 |
jnz nomb |
movzx eax,byte [0xfb40] |
nomb: |
mov [esp+36],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 |
setuart: |
su1: |
call is_output |
cmp al,0 |
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 |
cmp al,0 |
jnz su2 |
call get_mpu_in |
cmp al,0xfe |
jnz su2 |
su3: |
call is_output |
cmp al,0 |
jnz su3 |
mov dx,word [midisp] |
mov al,0x3f |
out dx,al |
ret |
align 4 |
sys_midi: |
cmp [mididp],0 |
jnz sm0 |
mov [esp+36],dword 1 |
ret |
sm0: |
cmp eax,1 |
mov [esp+36],dword 0 |
jnz smn1 |
call setuart |
ret |
smn1: |
cmp eax,2 |
jnz smn2 |
sm10: |
call get_mpu_in |
call is_output |
test al,al |
jnz sm10 |
mov al,bl |
call put_mpu_out |
ret |
smn2: |
ret |
detect_devices: |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
include 'detect/commouse.inc' |
;include 'detect/dev_fd.inc' |
;include 'detect/dev_hdcd.inc' |
;include 'detect/sear_par.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
ret |
sys_end: |
mov eax,[0x3010] |
add eax,0xa |
mov [eax],byte 3 ; terminate this program |
waitterm: ; wait here for termination |
mov eax,5 |
call delay_hs |
jmp waitterm |
sys_system: |
cmp eax,1 ; BOOT |
jnz nosystemboot |
mov [0x2f0000+0x9030],byte 0 |
for_shutdown_parameter: |
mov eax,[0x3004] |
add eax,2 |
mov [shutdown_processes],eax |
mov [0xFF00],al |
xor eax, eax |
ret |
uglobal |
shutdown_processes: dd 0x0 |
endg |
nosystemboot: |
cmp eax,2 ; TERMINATE |
jnz noprocessterminate |
cmp ebx,2 |
jb noprocessterminate |
mov edx,[0x3004] |
cmp ebx,edx |
jg noprocessterminate |
mov eax,[0x3004] |
shl ebx,5 |
mov edx,[ebx+0x3000+4] |
add ebx,0x3000+0xa |
;call MEM_Heap_Lock ;guarantee that process isn't working with heap |
mov [ebx],byte 3 ; clear possible i40's |
;call MEM_Heap_UnLock |
cmp edx,[application_table_status] ; clear app table stat |
jne noatsc |
mov [application_table_status],0 |
noatsc: |
ret |
noprocessterminate: |
cmp eax,3 ; ACTIVATE WINDOW |
jnz nowindowactivate |
cmp ebx,2 |
jb nowindowactivate |
cmp ebx,[0x3004] |
ja nowindowactivate |
; edi = position at window_data+ |
mov edi, ebx ; edi = process number |
;shl ebx, 1 |
;add ebx, 0xc000 |
;mov esi, [ebx] ; esi = window stack value |
;and esi, 0xffff ; word |
movzx esi, word [0xC000 + ebx*2] |
mov edx, [0x3004] ; edx = number of processes |
cmp esi, edx |
jz nowindowactivate ; continue if window_stack_value != number_of_processes |
; i.e. if window is not already active |
;* start code - get active process (1) - Mario79 |
mov [window_minimize],2 |
mov [active_process],edi |
;* end code - get active process (1) - Mario79 |
mov [0xff01],edi ; activate |
xor eax, eax |
ret |
nowindowactivate: |
cmp eax,4 ; GET IDLETIME |
jnz nogetidletime |
mov eax,[idleusesec] |
ret |
nogetidletime: |
cmp eax,5 ; GET TSC/SEC |
jnz nogettscsec |
mov eax,[0xf600] |
ret |
nogettscsec: |
; SAVE ramdisk to /hd/1/menuet.img |
;!!!!!!!!!!!!!!!!!!!!!!!! |
include 'blkdev/rdsave.inc' |
;!!!!!!!!!!!!!!!!!!!!!!!! |
;* start code - get active process (2) - Mario79 |
cmp eax,7 |
jnz nogetactiveprocess |
mov eax,[active_process] |
ret |
nogetactiveprocess: |
cmp eax,8 |
jnz nosoundflag |
cmp ebx,1 |
jne nogetsoundflag |
movzx eax,byte [sound_flag] ; get sound_flag |
ret |
nogetsoundflag: |
cmp ebx,2 |
jnz nosoundflag |
inc byte [sound_flag] ; set sound_flag |
and byte [sound_flag],1 ; |
ret |
nosoundflag: |
cmp eax,9 ; system shutdown with param |
jnz noshutdownsystem |
cmp ebx,1 |
jl exit_for_anyone |
cmp ebx,4 |
jg exit_for_anyone |
mov [0x2f0000+0x9030],bl |
jmp for_shutdown_parameter |
noshutdownsystem: |
cmp eax,10 ; minimize window |
jnz nominimizewindow |
mov [window_minimize],1 |
exit_for_anyone: |
ret |
nominimizewindow: |
cmp eax,11 ; get disk info table |
jnz nogetdiskinfo |
cmp ebx,1 |
jnz full_table |
small_table: |
call for_all_tables |
mov cx,10 |
cld |
rep movsb |
ret |
for_all_tables: |
mov edi,[3010h] |
mov edi,[edi+10h] |
add edi,ecx |
mov esi,0x40000 |
xor ecx,ecx |
ret |
full_table: |
cmp ebx,2 |
jnz exit_for_anyone |
call for_all_tables |
mov cx,16384 |
cld |
rep movsd |
ret |
nogetdiskinfo: |
cmp eax,12 ; get all key pressed with ALT |
jnz nogetkey |
mov eax,[last_key_press] |
mov al,[keyboard_mode_sys] |
mov [esp+36],eax |
mov [last_key_press],0 |
.finish: |
ret |
nogetkey: |
cmp eax,13 ; get kernel ID and version |
jnz nogetkernel_id |
mov edi,[3010h] |
mov edi,[edi+10h] |
add edi,ebx |
mov esi,version_inf |
mov ecx,version_end-version_inf |
cld |
rep movsb |
ret |
nogetkernel_id: |
cmp eax,14 ; sys wait retrace |
jnz nosys_wait_retrace |
;wait retrace functions |
sys_wait_retrace: |
mov edx,0x3da |
WaitRetrace_loop: |
in al,dx |
test al,1000b |
jz WaitRetrace_loop |
mov [esp+36],dword 0 |
ret |
nosys_wait_retrace: |
cmp eax,15 ; mouse centered |
jnz no_mouse_centered |
call mouse_centered |
mov [esp+36],dword 0 |
ret |
no_mouse_centered: |
;* end code - get active process (2) - Mario79 |
ret |
window_minimize db 0 |
sound_flag db 0 |
last_key_press dd 0 |
keyboard_mode_sys db 0 |
iglobal |
version_inf: |
db 0,5,0,0 ; version 0.5.0.0 |
db UID_KOLIBRI |
db 'Kolibri',0 |
version_end: |
endg |
UID_NONE=0 |
UID_MENUETOS=1 ;official |
UID_KOLIBRI=2 ;russian |
main_loop_sys_getkey: |
cmp [0xf400],byte 0 |
je .finish |
movzx eax,byte [0xf401] |
shl eax,8 |
mov [last_key_press],eax |
.finish: |
ret |
sys_cachetodiskette: |
pushad |
cmp eax,1 |
jne no_write_all_of_ramdisk |
call fdc_writeramdisk |
popad |
ret |
no_write_all_of_ramdisk: |
cmp eax,2 |
jne no_write_part_of_ramdisk |
call fdc_commitflush |
popad |
ret |
no_write_part_of_ramdisk: |
cmp eax,3 |
jne no_set_fdc |
call fdc_set |
popad |
ret |
no_set_fdc: |
cmp eax,4 |
jne no_get_fdc |
popad |
call fdc_get |
mov [esp+36],ecx |
ret |
no_get_fdc: |
popad |
ret |
uglobal |
; bgrchanged dd 0x0 |
endg |
sys_background: |
cmp eax,1 ; BACKGROUND SIZE |
jnz nosb1 |
cmp ebx,0 |
je sbgrr |
cmp ecx,0 |
je sbgrr |
mov [display_data-8],ebx |
mov [display_data-4],ecx |
; mov [bgrchanged],1 |
sbgrr: |
ret |
nosb1: |
cmp eax,2 ; SET PIXEL |
jnz nosb2 |
mov edx,0x160000-16 |
cmp edx,ebx |
jbe nosb2 |
mov edx,[ebx] |
and edx,0xFF000000 ;255*256*256*256 |
and ecx,0x00FFFFFF ;255*256*256+255*256+255 |
add edx,ecx |
mov [ebx+0x300000],edx |
; mov [bgrchanged],1 |
ret |
nosb2: |
cmp eax,3 ; DRAW BACKGROUND |
jnz nosb3 |
draw_background_temp: |
; cmp [bgrchanged],1 ;0 |
; je nosb31 |
;draw_background_temp: |
; mov [bgrchanged],1 ;0 |
mov [0xfff0],byte 1 |
nosb31: |
ret |
nosb3: |
cmp eax,4 ; TILED / STRETCHED |
jnz nosb4 |
cmp ebx,[display_data-12] |
je nosb41 |
mov [display_data-12],ebx |
; mov [bgrchanged],1 |
nosb41: |
ret |
nosb4: |
cmp eax,5 ; BLOCK MOVE TO BGR |
jnz nosb5 |
; bughere |
mov edi, [0x3010] |
add ebx, [edi+0x10] |
; mov esi, ebx |
; mov edi, ecx |
mov eax, ebx |
mov ebx, ecx |
add ecx, edx |
cmp ecx, 0x160000-16 |
ja .fin |
; add edi, 0x300000 |
add ebx, 0x300000 |
mov ecx, edx |
cmp ecx, 0x160000-16 |
ja .fin |
; mov [bgrchanged],1 |
; cld |
; rep movsb |
call memmove |
.fin: |
ret |
nosb5: |
ret |
align 4 |
sys_getbackground: |
cmp eax,1 ; SIZE |
jnz nogb1 |
mov eax,[display_data-8] |
shl eax,16 |
mov ax,[display_data-4] |
mov [esp+36],eax |
ret |
nogb1: |
cmp eax,2 ; PIXEL |
jnz nogb2 |
mov edx,0x160000-16 |
cmp edx,ebx |
jbe nogb2 |
mov eax, [ebx+0x300000] |
and eax, 0xFFFFFF |
mov [esp+36],eax |
ret |
nogb2: |
cmp eax,4 ; TILED / STRETCHED |
jnz nogb4 |
mov eax,[display_data-12] |
nogb4: |
mov [esp+36],eax |
ret |
align 4 |
sys_getkey: |
mov [esp+36],dword 1 |
mov ebx, [0x3000] ; TOP OF WINDOW STACK |
movzx ecx,word [0xC000 + ebx * 2] |
mov edx,[0x3004] |
cmp ecx,edx |
jne .finish |
cmp [0xf400],byte 0 |
je .finish |
movzx eax,byte [0xf401] |
shl eax,8 |
push eax |
dec byte [0xf400] |
and byte [0xf400],127 |
movzx ecx,byte [0xf400] |
add ecx,2 |
; mov esi,0xf402 |
; mov edi,0xf401 |
; cld |
; rep movsb |
mov eax, 0xF402 |
mov ebx, 0xF401 |
call memmove |
pop eax |
mov [last_key_press],eax |
mov eax,[kb_state] |
and al,110000b |
cmp al,100000b |
je .yes_win_key |
cmp al,10000b |
je .yes_win_key |
mov eax,[last_key_press] |
jmp .no_win_key |
; cmp ah,232 |
; je .yes_win_key |
; cmp ah,233 |
; jne .no_win_key |
.yes_win_key: |
mov eax,1 |
.no_win_key: |
mov [esp+36],eax |
.finish: |
ret |
align 4 |
sys_getbutton: |
mov ebx, [0x3000] ; TOP OF WINDOW STACK |
mov [esp+36],dword 1 |
movzx ecx, word [0xC000 + ebx * 2] |
mov edx, [0x3004] ; less than 256 processes |
cmp ecx,edx |
jne .exit |
movzx eax,byte [0xf500] |
test eax,eax |
jz .exit |
mov eax,[0xf501] |
shl eax,8 |
mov [0xf500],byte 0 |
mov [esp+36],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 |
; |
mov edi,[0x3010] ; eax = return area |
add edi,0x10 |
add eax,[edi] |
cmp ebx,-1 ; who am I ? |
jne no_who_am_i |
mov ebx,[0x3000] |
no_who_am_i: |
push eax ; return area |
push ebx ; process number |
push ebx |
push ebx |
push eax |
; return memory usage |
xor edx,edx |
mov eax,0x20 |
mul ebx |
add eax,0x3000+0x1c |
mov ebx,eax |
pop eax |
mov ecx,[ebx] |
mov [eax],ecx |
pop ebx |
; mov ebx,[esp] |
; shl ebx,1 |
; add ebx,0xc000 |
mov cx, [0xC000 + ebx * 2] |
mov [eax+4],cx |
; mov ebx,[esp] |
; shl ebx,1 |
; add ebx,0xc400 |
mov cx, [0xC400 + ebx * 2] |
mov [eax+6],cx |
; pop ebx |
push eax |
mov eax,ebx |
shl eax,8 |
add eax,0x80000 |
pop ebx |
add ebx,10 |
mov ecx,11 |
call memmove |
; memory usage |
xor eax,eax |
mov edx,0x100000*16 |
pop ecx ; get gdt of tss |
cmp ecx,1 |
je os_mem |
shl ecx,8 |
mov edx,[0x80000+ecx+0x8c] |
mov eax,std_application_base_address |
;add ecx,0x80000+0x88 |
;mov ecx,[ecx] |
; shl ecx,3 |
; eax run base -> edx used memory |
; mov al,[ecx+gdts+ app_code-3 +4] ; base 23:16 |
; mov ah,[ecx+gdts+ app_code-3 +7] ; base 31:24 |
; shl eax,16 |
; mov ax,[ecx+gdts+ app_code-3 +2] ; base 0:15 |
; movzx edx,word [ecx+gdts+ app_code-3 +0] |
; shl edx,12 |
os_mem: |
dec edx |
mov [ebx+12],eax |
mov [ebx+16],edx |
; PID (+30) |
mov eax,[esp] |
shl eax,5 |
add eax,0x3000+0x4 |
mov eax,[eax] |
mov [ebx+20],eax |
; window position and size |
mov esi,[esp] |
shl esi,5 |
add esi,window_data |
mov edi,[esp+4] |
add edi,34 |
mov ecx,4*4 |
cld |
rep movsb |
; Process state (+50) |
mov eax,[esp] |
shl eax,5 |
add eax,0x3000+0xa |
mov eax,[eax] |
mov [ebx+40],ax |
pop ebx |
pop eax |
; return number of processes |
mov eax,[0x3004] |
mov [esp+36],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+36],ecx |
ret |
align 4 |
sys_date: |
cli |
mov al,6 ; day of week |
out 0x70,al |
in al,0x71 |
mov ch,al |
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+36],ecx |
ret |
; redraw status |
sys_redrawstat: |
cmp eax,1 |
jne no_widgets_away |
; buttons away |
mov ecx,[0x3000] |
sys_newba2: |
mov edi,[0xfe88] |
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 eax,2 |
jnz srl1 |
mov edx,[0x3010] ; return whole screen draw area for this app |
add edx,draw_data-0x3000 |
mov [edx+0],dword 0 |
mov [edx+4],dword 0 |
mov eax,[0xfe00] |
mov [edx+8],eax |
mov eax,[0xfe04] |
mov [edx+12],eax |
mov edi,[0x3010] |
sub edi,twdw |
mov [edi+30],byte 1 ; no new position & buttons from app |
call sys_window_mouse |
ret |
srl1: |
ret |
sys_drawwindow: |
mov edi,ecx |
shr edi,16+8 |
and edi,15 |
cmp edi,0 ; type I - original style |
jne nosyswI |
call sys_set_window |
call drawwindow_I |
ret |
nosyswI: |
cmp edi,1 ; type II - only reserve area, no draw |
jne nosyswII |
call sys_set_window |
call sys_window_mouse |
ret |
nosyswII: |
cmp edi,2 ; type III - new style |
jne nosyswIII |
call sys_set_window |
call drawwindow_III |
ret |
nosyswIII: |
cmp edi,3 ; type IV - skinned window |
jne nosyswIV |
call sys_set_window |
call drawwindow_IV |
ret |
nosyswIV: |
ret |
sys_set_window: |
mov edi,[0x3000] |
shl edi,5 |
add edi,window_data |
; colors |
mov [edi+16],ecx |
mov [edi+20],edx |
mov [edi+24],esi |
; check flag (?) |
cmp [edi+30],byte 1 |
jz newd |
push eax |
mov eax,[timer_ticks] ;[0xfdf0] |
add eax,100 |
mov [new_window_starting],eax |
pop eax |
mov [edi+8],ax |
mov [edi+12],bx |
shr eax,16 |
shr ebx,16 |
mov [edi+00],ax |
mov [edi+04],bx |
call check_window_position |
push ecx esi edi ; save for window fullscreen/resize |
mov esi,edi |
sub edi,window_data |
shr edi,5 |
shl edi,8 |
add edi,0x80000+0x90 |
mov ecx,4 |
cld |
rep movsd |
pop edi esi ecx |
push eax ebx ecx edx |
;;; mov eax, 1 |
;;; call delay_hs |
movzx eax, word [edi+00] |
movzx ebx, word [edi+04] |
movzx ecx, word [edi+8] |
movzx edx, word [edi+12] |
add ecx, eax |
add edx, ebx |
call calculatescreen |
pop edx ecx ebx eax |
mov [0xf400],byte 0 ; empty keyboard buffer |
mov [0xf500],byte 0 ; empty button buffer |
newd: |
mov [edi+31],byte 0 ; no redraw |
mov edx,edi |
ret |
sys_window_move: |
cmp [window_move_pr],0 |
je mwrl1 |
mov [esp+36],dword 1 ; return queue error |
ret |
mwrl1: |
mov edi,[0x3000] ; requestor process base |
mov [window_move_pr],edi |
mov [window_move_eax],eax |
mov [window_move_ebx],ebx |
mov [window_move_ecx],ecx |
mov [window_move_edx],edx |
mov [esp+36],dword 0 ; return success |
ret |
type_background_1: |
cmp [0xfff0],byte 0 ; background update ? |
jz temp_nobackgr |
mov [0xfff0],byte 2 |
call change_task |
mov [draw_data+32+0],dword 0 |
mov [draw_data+32+4],dword 0 |
mov eax,[0xfe00] |
mov ebx,[0xfe04] |
mov [draw_data+32+8],eax |
mov [draw_data+32+12],ebx |
call drawbackground |
mov [0xfff0],byte 0 |
mov [0xfff4],byte 0 |
temp_nobackgr: |
ret |
uglobal |
window_move_pr dd 0x0 |
window_move_eax dd 0x0 |
window_move_ebx dd 0x0 |
window_move_ecx dd 0x0 |
window_move_edx dd 0x0 |
endg |
;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. |
;--------------------------------------------------------------------------------------------- |
sys_sheduler: ;noname & halyavin |
cmp eax,0 |
je shed_counter |
cmp eax,2 |
je perf_control |
cmp eax,3 |
je rdmsr_instr |
cmp eax,4 |
je wrmsr_instr |
cmp eax,1 |
jne not_supported |
call change_task ;delay,0 |
ret |
shed_counter: |
mov eax,[context_counter] |
mov [esp+36],eax |
not_supported: |
ret |
perf_control: |
inc eax ;now eax=3 |
cmp ebx,eax |
je cache_disable |
dec eax |
cmp ebx,eax |
je cache_enable |
dec eax |
cmp ebx,eax |
je is_cache_enabled |
dec eax |
cmp ebx,eax |
je modify_pce |
ret |
rdmsr_instr: |
;now counter in ecx |
;(edx:eax) esi:edi => edx:esi |
mov eax,esi |
rdmsr |
mov [esp+36],eax |
mov [esp+24],edx ;ret in ebx? |
ret |
wrmsr_instr: |
;now counter in ecx |
;(edx:eax) esi:edi => edx:esi |
mov eax,esi |
wrmsr |
mov [esp+36],eax |
mov [esp+24],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+36],ebx |
cache_disabled: |
mov dword [esp+36],eax ;0 |
ret |
modify_pce: |
mov eax,cr4 |
; mov ebx,0 |
; or bx,100000000b ;pce |
; xor eax,ebx ;invert pce |
btr eax,8 ;pce=cr4[8] |
mov cr4,eax |
mov [esp+36],eax |
ret |
;--------------------------------------------------------------------------------------------- |
; check pixel limits |
;cplimit: |
; push edi |
; cmp byte [0xe000], 1 ; Multitasking enabled? |
; jnz .ret0 |
; mov edi,[0x3010] |
; add edi, draw_data-0x3000 |
; mov ecx, 1 |
; cmp [edi+0], eax ; xs |
; ja .ret1 |
; cmp [edi+4], ebx ; ys |
; ja .ret1 |
; cmp eax, [edi+8] ; xe |
; ja .ret1 |
; cmp ebx, [edi+12] ; ye |
; ja .ret1 |
;.ret0: |
; xor ecx, ecx |
;.ret1: |
; pop edi |
; ret |
; check if pixel is allowed to be drawn |
checkpixel: |
push eax |
push ebx |
push edx |
; mov ecx,[0x3000] ; process count |
; shl ecx, 6 ; *64 |
; add ecx,0xc000 ; +window_stack |
; mov dx,word [ecx] ; window_stack_value |
; cmp dx, word [0x3004] ; is this window active right now?! |
; jz .ret0 |
; call cplimit |
; test ecx, ecx |
; jnz .ret1 |
mov edx,[0xfe00] ; screen x size |
inc edx |
imul edx, ebx |
mov dl, [eax+edx+display_data] ; lea eax, [...] |
;;; mov dl,[eax] |
mov eax,[0x3000] |
shl eax,5 |
add eax,0x3000+0xe |
mov ecx, 1 |
cmp byte [eax], dl |
jnz .ret1 |
.ret0: |
xor ecx, ecx |
.ret1: |
pop edx |
pop ebx |
pop eax |
ret |
uglobal |
mouse_active db 0 |
endg |
iglobal |
cpustring db 'CPU ' |
endg |
align 4 |
; check misc |
checkmisc: |
cmp [ctrl_alt_del], 1 |
jne nocpustart |
mov eax, cpustring |
call start_application_fl |
mov [ctrl_alt_del], 0 |
nocpustart: |
cmp [mouse_active], 1 |
jne mouse_not_active |
mov [mouse_active], 0 |
xor edi, edi |
mov ecx, [0x3004] |
set_mouse_event: |
add edi, 256 |
or [edi+0x80000+0xA8], dword 00100000b |
loop set_mouse_event |
mouse_not_active: |
cmp [0xfff0],byte 0 ; background update ? |
jz nobackgr |
mov [0xfff0],byte 2 |
call change_task |
mov [draw_data+32+0],dword 0 |
mov [draw_data+32+4],dword 0 |
mov eax,[0xfe00] |
mov ebx,[0xfe04] |
mov [draw_data+32+8],eax |
mov [draw_data+32+12],ebx |
call drawbackground |
mov [0xfff0],byte 0 |
mov [0xfff4],byte 0 |
nobackgr: |
; system shutdown request |
cmp [0xFF00],byte 0 |
je noshutdown |
mov edx,[shutdown_processes] |
sub dl,2 |
cmp [0xff00],dl |
jne no_mark_system_shutdown |
mov edx,0x3040 |
movzx ecx,byte [0xff00] |
add ecx,5 |
markz: |
mov [edx+0xa],byte 3 |
add edx,0x20 |
loop markz |
no_mark_system_shutdown: |
call [disable_mouse] |
dec byte [0xff00] |
cmp [0xff00],byte 0 |
je system_shutdown |
noshutdown: |
mov eax,[0x3004] ; termination |
mov ebx,0x3020+0xa |
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 eax,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+0] |
mov ebx,[edi+4] |
mov ecx,[edi+8] |
mov edx,[edi+12] |
add ecx,eax |
add edx,ebx |
mov ecx,[dlye] ; ecx = area y end ebx = window y start |
cmp ecx,ebx |
jb ricino |
mov ecx,[dlxe] ; ecx = area x end eax = window x start |
cmp ecx,eax |
jb ricino |
mov eax,[edi+0] |
mov ebx,[edi+4] |
mov ecx,[edi+8] |
mov edx,[edi+12] |
add ecx,eax |
add edx,ebx |
mov eax,[dly] ; eax = area y start edx = window y end |
cmp edx,eax |
jb ricino |
mov eax,[dlx] ; eax = area x start ecx = window x end |
cmp ecx,eax |
jb ricino |
bgli: |
cmp edi,esi |
jz ricino |
mov eax,edi |
add eax,draw_data-window_data |
mov ebx,[dlx] ; set limits |
mov [eax+0],ebx |
mov ebx,[dly] |
mov [eax+4],ebx |
mov ebx,[dlxe] |
mov [eax+8],ebx |
mov ebx,[dlye] |
mov [eax+12],ebx |
sub eax,draw_data-window_data |
cmp ecx,1 |
jne nobgrd |
cmp esi,1 |
je newdw8 |
call drawbackground |
newdw8: |
nobgrd: |
mov [eax+31],byte 1 ; mark as redraw |
ricino: |
not_this_task: |
pop ecx |
cmp ecx,[0x3004] |
jle newdw2 |
; jg newdw3 |
; jmp newdw2 |
; newdw3: |
pop eax |
popad |
ret |
; 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 |
check_mouse_data: |
pushad |
cmp [0xF604],byte 1 |
jne no_ps2_mouse |
mov [mousecount],dword 0x2e0000+12*4096 |
mov [mousedata],dword 0x2e0000+12*4096+0x10 |
jmp uusicheckmouse |
no_ps2_mouse: |
cmp [0xF604],byte 2 |
jne no_com1_mouse |
mov [mousecount],dword 0x2e0000+4*4096 |
mov [mousedata],dword 0x2e0000+4*4096+0x10 |
jmp uusicheckmouse |
no_com1_mouse: |
mov [mousecount],dword 0x2e0000+3*4096 |
mov [mousedata],dword 0x2e0000+3*4096+0x10 |
uusicheckmouse: |
mov ebx,[mousecount] ; anything at buffer for mouse |
cmp dword [ebx], 0 ; !!! |
jz checkmouseret |
; first byte of comX or ps2 ? |
cmp [0xF604],byte 1 |
je ps2mousefirst |
; ****************************************** |
; *********** COMX mouse driver ************ |
; ****************************************** |
com1mousefirst: |
mov edi,[mousedata] |
mov dl,byte [edi] ; first com1 ? |
test dl,64 |
jz @f |
mov [0xfb00],byte 0 ; zero mouse block count |
@@: |
xor ebx,ebx |
mov bl,[0xfb00] |
inc bl |
mov [0xfb00],bl |
mov eax,0xfb00 |
add eax,ebx |
mov edi,[mousedata] |
mov dl,byte [edi] |
mov [eax],byte dl |
cmp bl,3 ; three ? |
jnz decm |
; buttons |
;* change right and left button by places - start code - Mario79 |
mov al,[0xfb01] |
mov ah,al |
shr al,3 |
and al,2 |
shr ah,5 |
and ah,1 |
add al,ah |
;* change right and left button by places - end code - Mario79 |
mov [0xfb40],al |
; com1 mouse |
; x |
mov dl,[0xfb01] ; x high bits |
movzx eax,dl |
and al,3 |
shl al,6 |
mov dl,byte[0xfb02] ; x low bits |
add al,dl |
mov [0xfb21],byte al |
movzx ebx,word[0xfb0a] |
mov al,byte [0xfb01] ; + or - ? |
test al,2 |
jz x_add |
x_sub: ; x- |
sub bx,255 |
sub bx,255 |
x_add: ; x+ |
movzx eax,byte [0xfb21] |
add bx,ax |
add bx,ax |
push ebx |
mov [0xfb00],byte 0 |
; y |
my_event: |
mov dl,[0xfb01] ; y high bits |
movzx eax,dl |
and al,12 |
shl al,4 |
mov dl,byte[0xfb03] ; y low bits |
add al,dl |
mov [0xfb22],byte al |
movzx ebx,word[0xfb0c] |
mov al,byte [0xfb01] ; + or - ? |
test al,8 |
je y_add |
y_sub: ; y- |
sub bx,255 |
sub bx,255 |
y_add: ; y+ |
movzx eax,byte [0xfb22] |
add bx,ax |
add bx,ax |
push ebx |
mov [0xfb00],byte 0 |
jmp mdraw |
; end of com1 mouse |
; ****************************************** |
; ******** PS2 MOUSE DRIVER ************** |
; ****************************************** |
ps2mousefirst: |
movzx edx,byte [0x2E0000+4096*12+0x10] ; first ps2 ? |
cmp edx,40 |
jne @f |
mov [0xfb00],byte 0 ; zero mouse block count |
@@: |
movzx ebx,byte [0xfb00] |
add ebx,1 |
mov [0xfb00],bl |
mov eax,0xfb00 |
add eax,ebx |
mov dl,byte [0x2E0000+4096*12+0x10] |
mov [eax],byte dl |
cmp bl,3 ; full packet of three bytes ? |
jnz decm |
; jz ps2mouse |
; jmp decm |
; ps2mouse: |
mov [0xfb00],byte 0 ; zero mouse block count |
; buttons |
movzx eax,byte [0xfb01] |
and eax,3 |
mov [0xfb40],al |
; x |
movzx eax,word [0xfb0a] |
movzx edx,byte [0xfb02] |
cmp edx,128 |
jb ps2xp |
shl edx,1 |
add eax,edx |
cmp eax,512 |
jge ps2xsok |
xor eax, eax |
jmp ps2xready |
ps2xsok: |
sub eax,512 |
jmp ps2xready |
ps2xp: |
shl edx,1 |
add eax,edx |
jmp ps2xready |
ps2xready: |
push eax |
; y |
movzx eax,word [0xfb0c] |
movzx edx,byte [0xfb03] |
cmp edx,128 |
jb ps2yp |
add eax,512 |
shl edx,1 |
sub eax,edx |
jmp ps2yready |
ps2yp: |
shl edx,1 |
cmp edx,eax |
jb ps201 |
mov edx,eax |
ps201: |
sub eax,edx |
jmp ps2yready |
ps2yready: |
push eax |
;jmp mdraw |
; end of ps2 mouse |
; **************************** |
; ***** CHECK FOR LIMITS ***** |
; **************************** |
mdraw: |
cmp [0xfb44],byte 0 |
jne mousedraw4 |
cmp [0xfb40],byte 0 |
je mousedraw4 |
mov [0xfff5],byte 1 |
mousedraw4: |
pop ebx |
pop eax |
mov [mouse_active],1 |
; mov dx,0 ; smaller than zero |
xor dx,dx |
cmp bx,dx |
jge mnb11 |
; mov bx,0 |
xor bx,bx |
mnb11: |
mov [0xfb0c],word bx |
; mov dx,0 |
xor dx,dx |
cmp ax,dx |
jge mnb22 |
; mov ax,0 |
xor ax,ax |
mnb22: |
mov [0xfb0a],word ax |
mov edx,[0xfe04] ; bigger than maximum |
cmp ebx,edx |
jb mnb1 |
mov bx,[0xfe04] |
mnb1: |
mov [0xfb0c],word bx |
mov edx,[0xfe00] |
cmp eax,edx |
jb mnb2 |
mov ax,[0xfe00] |
mnb2: |
mov [0xfb0a],word ax |
; **** NEXT DATA BYTE FROM MOUSE BUFFER **** |
decm: |
mov edi,[mousecount] ; decrease counter |
dec dword [edi] |
mov esi,[mousedata] |
mov edi,esi |
inc esi |
; mov ecx,250 |
mov ecx,[mousecount] |
mov ecx,[ecx] |
cld |
rep movsb |
jmp uusicheckmouse |
checkmouseret: |
cmp [0xfb44],byte 0 |
jne cmret |
cmp [0xfb40],byte 0 |
je cmret |
mov [0xfff4],byte 0 |
mov [0xfff5],byte 0 |
cmret: |
popad |
ret |
draw_mouse_under: |
; return old picture |
; cli |
pushad |
xor ecx,ecx |
xor edx,edx |
;cli ; !!!**** |
align 4 |
mres: |
movzx eax,word [0xfb4a] |
movzx ebx,word [0xfb4c] |
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 |
;;;push edi |
mov edi,1 ;force |
call [putpixel] |
;;;pop edi |
pop edx |
pop ecx |
inc ecx |
cmp ecx, 16 |
jnz mres |
xor ecx, ecx |
inc edx |
cmp edx, 24 |
jnz mres |
;sti ; !!!**** |
popad |
; sti |
ret |
save_draw_mouse: |
; save & draw |
; cli |
mov [0xfb4a],ax |
mov [0xfb4c],bx |
push eax |
push ebx |
mov ecx,0 |
mov edx,0 |
;cli ; !!!**** |
drm: |
push eax |
push ebx |
push ecx |
push edx |
; helloworld |
push eax ebx ecx |
add eax,ecx ; save picture under mouse |
add ebx,edx |
push ecx |
call getpixel |
mov [0xfb30],ecx |
pop ecx |
mov eax,edx |
shl eax,6 |
shl ecx,2 |
add eax,ecx |
add eax,mouseunder |
mov ebx,[0xfb30] |
mov [eax],ebx |
pop ecx ebx eax |
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,[0xf200] ; we have our str address |
mov esi, edi |
add esi, 16*24*3 |
push ecx |
mov ecx, [0xfb30] |
call combine_colors |
mov [0xfb10], 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 edi |
mov ecx, [0xfb10] |
mov edi, 1 |
call [putpixel] |
pop edi ecx |
mnext: |
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 |
pop ebx |
pop eax |
; sti ; !!!**** |
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] |
movzx eax, byte [edi+0] |
movzx ebx, byte [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] |
movzx eax, byte [edi+1] |
movzx ebx, byte [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] |
movzx eax, byte [edi+2] |
movzx ebx, byte [esi+2] |
mul ebx |
shr eax, 8 |
add ecx, eax |
pop eax |
pop edx |
pop ebx |
pop eax |
ret |
__sys_disable_mouse: |
pushad |
cmp [0x3000],dword 1 |
je disable_m |
mov edx,[0x3000] |
shl edx,5 |
add edx,window_data |
movzx eax, word [0xfb0a] |
movzx ebx, word [0xfb0c] |
mov ecx,[0xfe00] |
inc ecx |
imul ecx,ebx |
add ecx,eax |
add ecx, display_data |
movzx eax, byte [edx+twdw+0xe] |
movzx ebx, byte [ecx] |
cmp eax,ebx |
je yes_mouse_disable |
movzx ebx, byte [ecx+16] |
cmp eax,ebx |
je yes_mouse_disable |
mov ebx,[0xfe00] |
inc ebx |
imul ebx,10 |
add ecx,ebx |
movzx ebx, byte [ecx] |
cmp eax,ebx |
je yes_mouse_disable |
mov ebx,[0xfe00] |
inc ebx |
imul ebx,10 |
add ecx,ebx |
movzx ebx, byte [ecx] |
cmp eax,ebx |
je yes_mouse_disable |
movzx ebx, byte [ecx+16] |
cmp eax,ebx |
je yes_mouse_disable |
jmp no_mouse_disable |
yes_mouse_disable: |
mov edx,[0x3000] |
shl edx,5 |
add edx,window_data |
movzx eax, word [0xfb0a] |
movzx ebx, word [0xfb0c] |
mov ecx,[edx+0] ; mouse inside the area ? |
add eax,14 |
cmp eax,ecx |
jb no_mouse_disable |
sub eax,14 |
add ecx,[edx+8] |
cmp eax,ecx |
jg no_mouse_disable |
mov ecx,[edx+4] |
add ebx,20 |
cmp ebx,ecx |
jb no_mouse_disable |
sub ebx,20 |
add ecx,[edx+12] |
cmp ebx,ecx |
jg no_mouse_disable |
disable_m: |
cmp dword [0xf204],dword 0 |
jne @f |
call draw_mouse_under |
@@: |
mov [0xf204],dword 1 |
no_mouse_disable: |
popad |
ret |
__sys_draw_pointer: |
cli |
pushad |
cmp dword [0xf204],dword 0 ; mouse visible ? |
je chms00 |
dec dword [0xf204] |
cmp [0xf204],dword 0 |
jnz nodmu2 |
movzx ebx,word [0xfb0c] |
movzx eax,word [0xfb0a] |
call save_draw_mouse |
popad |
sti |
ret |
nodmu2: |
popad |
sti |
ret |
chms00: |
; popad |
; pushad |
; cmp [0xf204],dword 0 |
; jne nodmp |
movzx ecx,word [0xfb4a] |
movzx edx,word [0xfb4c] |
movzx ebx,word [0xfb0c] |
movzx eax,word [0xfb0a] |
cmp eax,ecx |
jne redrawmouse |
cmp ebx,edx |
jne redrawmouse |
jmp nodmp |
redrawmouse: |
call draw_mouse_under |
redrawmouse_1: |
call save_draw_mouse |
nodmp: |
popad |
sti |
ret |
calculatebackground: ; background |
; all black |
mov [display_data-8],dword 4 ; size x |
mov [display_data-4],dword 2 ; size y |
mov edi, 0x300000 ; set background to black |
xor eax, eax |
mov ecx, 0x0fff00 / 4 |
cld |
rep stosd |
mov edi,display_data ; set os to use all pixels |
mov eax,0x01010101 |
mov ecx,0x1fff00 / 4 |
rep stosd |
mov byte [0xFFF0], 0 ; do not draw background! |
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: |
push edi |
mov edi,[0x3010] |
mov [edi],eax |
pop edi |
ret |
delay_hs: ; delay in 1/100 secs |
push eax |
push ecx |
push edx |
mov edx,[timer_ticks];[0xfdf0] |
add edx,eax |
newtic: |
mov ecx,[timer_ticks];[0xfdf0] |
cmp edx,ecx |
jbe zerodelay |
call change_task |
jmp newtic |
zerodelay: |
pop edx |
pop ecx |
pop eax |
ret |
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 |
; calculate fat chain |
calculatefatchain: |
pushad |
mov esi,0x100000+512 |
mov edi,0x280000 |
fcnew: |
xor eax,eax |
xor ebx,ebx |
xor ecx,ecx |
xor edx,edx |
mov al,[esi+0] ; 1 |
mov bl,[esi+1] |
and ebx,15 |
shl ebx,8 |
add eax,ebx |
mov [edi],ax |
add edi,2 |
xor eax,eax |
xor ebx,ebx |
xor ecx,ecx |
xor edx,edx |
mov bl,[esi+1] ; 2 |
mov cl,[esi+2] |
shr ebx,4 |
shl ecx,4 |
add ecx,ebx |
mov [edi],cx |
add edi,2 |
add esi,3 |
cmp edi,0x280000+4100*4 |
jnz fcnew |
popad |
ret |
restorefatchain: ; restore fat chain |
pushad |
mov esi,0x280000 |
mov edi,0x100000+512 |
fcnew2: |
cld |
xor eax,eax |
xor ebx,ebx |
xor ecx,ecx ; esi XXXXxxxxxxxx yyyyyyyyYYYY |
xor edx,edx |
mov ax,[esi] ; edi xxxxxxxx YYYYXXXX yyyyyyyy |
mov bx,ax |
shr bx,8 |
and ebx,15 |
mov [edi+0],al ; 1 -> 1 & 2 |
mov [edi+1],bl |
add esi,2 |
xor eax,eax |
xor ebx,ebx |
xor ecx,ecx |
xor edx,edx |
mov bx,[esi] |
mov cx,bx |
shr ecx,4 |
mov [edi+2],cl |
and ebx,15 |
shl ebx,4 |
mov edx,[edi+1] |
add edx,ebx |
mov [edi+1],dl ; 2 -> 2 & 3 |
add esi,2 |
add edi,3 |
cmp edi,0x100000+512+0x1200 |
jb fcnew2 |
mov esi,0x100000+512 ; duplicate fat chain |
mov edi,0x100000+512+0x1200 |
mov ecx,0x1200/4 |
cld |
rep movsd |
popad |
ret |
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,[0x3010] |
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 |
sys_programirq: |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
mov edx,ebx |
shl edx,2 |
add edx,irq_owner |
mov edx,[edx] |
mov edi,[0x3010] |
mov edi,[edi+0x4] |
cmp edx,edi |
je spril1 |
mov [esp+36],dword 1 |
ret |
spril1: |
mov esi,eax |
shl ebx,6 |
add ebx,irq00read |
mov edi,ebx |
mov ecx,16 |
cld |
rep movsd |
mov [esp+36],dword 0 |
ret |
align 4 |
get_irq_data: |
mov edx,eax ; check for correct owner |
shl edx,2 |
add edx,irq_owner |
mov edx,[edx] |
mov edi,[0x3010] |
mov edi,[edi+0x4] |
cmp edx,edi |
je gidril1 |
mov [esp+36],eax |
mov [esp+32],dword 2 |
mov [esp+24],ebx |
ret |
gidril1: |
mov ebx,eax |
shl ebx,12 |
add ebx,0x2e0000 |
mov eax,[ebx] |
mov ecx,1 |
test eax,eax |
jz gid1 |
dec eax |
mov esi,ebx |
mov [ebx],eax |
movzx ebx,byte [ebx+0x10] |
add esi,0x10 |
mov edi,esi |
inc esi |
mov ecx,4000 / 4 |
cld |
rep movsd |
xor ecx,ecx |
gid1: |
mov [esp+36],eax |
mov [esp+32],ecx |
mov [esp+24],ebx |
ret |
set_io_access_rights: |
pushad |
mov edi,[0x3000] |
imul edi,tss_step |
add edi,tss_data+128 |
; add edi,128 |
mov ecx,eax |
and ecx,7 ; offset in byte |
shr eax,3 ; number of byte |
add edi,eax |
mov ebx,1 |
shl ebx,cl |
cmp ebp,0 ; enable access - ebp = 0 |
jne siar1 |
not ebx |
and [edi],byte bl |
popad |
ret |
siar1: |
or [edi],byte bl ; disable access - ebp = 1 |
popad |
ret |
r_f_port_area: |
test eax, eax |
jnz free_port_area |
; je r_port_area |
; jmp free_port_area |
; r_port_area: |
pushad |
cmp ebx,ecx ; beginning > end ? |
jg rpal1 |
mov esi,[0x2d0000] |
cmp esi,0 ; no reserved areas ? |
je rpal2 |
cmp esi,255 ; max reserved |
jge rpal1 |
rpal3: |
mov edi,esi |
shl edi,4 |
add edi,0x2d0000 |
cmp ebx,[edi+8] |
jg rpal4 |
cmp ecx,[edi+4] |
jae rpal1 |
; jb rpal4 |
; jmp rpal1 |
rpal4: |
dec esi |
jnz rpal3 |
jmp rpal2 |
rpal1: |
popad |
mov eax,1 |
ret |
rpal2: |
popad |
; enable port access at port IO map |
cli |
pushad ; start enable io map |
cmp ecx,65536 ;16384 |
jae no_unmask_io ; jge |
mov eax,ebx |
new_port_access: |
pushad |
mov ebp,0 ; enable - eax = port |
call set_io_access_rights |
popad |
inc eax |
cmp eax,ecx |
jbe new_port_access |
no_unmask_io: |
popad ; end enable io map |
sti |
mov edi,[0x2d0000] |
add edi,1 |
mov [0x2d0000],edi |
shl edi,4 |
add edi,0x2d0000 |
mov esi,[0x3010] |
mov esi,[esi+0x4] |
mov [edi],esi |
mov [edi+4],ebx |
mov [edi+8],ecx |
xor eax, eax |
ret |
free_port_area: |
pushad |
mov esi,[0x2d0000] ; no reserved areas ? |
cmp esi,0 |
je frpal2 |
mov edx,[0x3010] |
mov edx,[edx+4] |
frpal3: |
mov edi,esi |
shl edi,4 |
add edi,0x2d0000 |
cmp edx,[edi] |
jne frpal4 |
cmp ebx,[edi+4] |
jne frpal4 |
cmp ecx,[edi+8] |
jne frpal4 |
jmp frpal1 |
frpal4: |
dec esi |
jnz frpal3 |
frpal2: |
popad |
mov eax,1 |
ret |
frpal1: |
mov ecx,256 |
sub ecx,esi |
shl ecx,4 |
mov esi,edi |
add esi,16 |
cld |
rep movsb |
dec dword [0x2d0000] |
popad |
; disable port access at port IO map |
pushad ; start disable io map |
cmp ecx,65536 ;16384 |
jge no_mask_io |
mov eax,ebx |
new_port_access_disable: |
pushad |
mov ebp,1 ; disable - eax = port |
call set_io_access_rights |
popad |
inc eax |
cmp eax,ecx |
jbe new_port_access_disable |
no_mask_io: |
popad ; end disable io map |
xor eax, eax |
ret |
reserve_free_irq: |
cmp eax,0 |
jz reserve_irq |
mov edi,ebx |
shl edi,2 |
add edi,irq_owner |
mov edx,[edi] |
mov eax,[0x3010] |
mov eax,[eax+0x4] |
mov ecx,1 |
cmp edx,eax |
jne fril1 |
mov [edi],dword 0 |
mov ecx,0 |
fril1: |
mov [esp+36],ecx ; return in eax |
ret |
reserve_irq: |
mov edi,ebx |
shl edi,2 |
add edi,irq_owner |
mov edx,[edi] |
mov ecx,1 |
cmp edx,0 |
jne ril1 |
mov edx,[0x3010] |
mov edx,[edx+0x4] |
mov [edi],edx |
mov ecx,0 |
ril1: |
mov [esp+36],ecx ; return in eax |
ret |
drawbackground: |
cmp [0xfe0c],word 0x12 |
jne dbrv12 |
cmp [display_data-12],dword 1 |
jne bgrstr12 |
call vga_drawbackground_tiled |
ret |
bgrstr12: |
call vga_drawbackground_stretch |
ret |
dbrv12: |
cmp [0xfe0c],word 0100000000000000b |
jge dbrv20 |
cmp [0xfe0c],word 0x13 |
je dbrv20 |
call vesa12_drawbackground |
ret |
dbrv20: |
cmp [display_data-12],dword 1 |
jne bgrstr |
call vesa20_drawbackground_tiled |
ret |
bgrstr: |
call vesa20_drawbackground_stretch |
ret |
sys_putimage: |
cmp [0xfe0c],word 0x12 |
jne spiv20 |
call vga_putimage |
ret |
spiv20: |
cmp [0xfe0c],word 0100000000000000b |
jge piv20 |
cmp [0xfe0c],word 0x13 |
je piv20 |
call vesa12_putimage |
ret |
piv20: |
call vesa20_putimage |
ret |
; eax x beginning |
; ebx y beginning |
; ecx x end |
; edx y end |
; edi color |
__sys_drawbar: |
cmp [0xfe0c],word 0x12 |
jne sdbv20 |
call vga_drawbar |
ret |
sdbv20: |
cmp [0xfe0c],word 0100000000000000b |
jge dbv20 |
cmp [0xfe0c],word 0x13 |
je dbv20 |
call vesa12_drawbar |
ret |
dbv20: |
call vesa20_drawbar |
ret |
kb_read: |
push ecx edx |
mov ecx,0xffff |
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,0xffff |
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,0xffff |
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,0xffff |
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,0xffff |
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,0xffff |
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,0xffff |
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 [0xf200],dword mousepointer |
cli |
mov bl,0xa8 ; enable mouse cmd |
call kb_cmd |
call kb_read ; read status |
mov bl,0x20 ; get command byte |
call kb_cmd |
call kb_read |
or al,3 ; enable interrupt |
mov bl,0x60 ; write command |
push eax |
call kb_cmd |
pop eax |
call kb_write |
mov bl,0xd4 ; for mouse |
call kb_cmd |
mov al,0xf4 ; enable mouse device |
call kb_write |
call kb_read ; read status return |
; com1 mouse enable |
mov bx,0x3f8 ; combase |
mov dx,bx |
add dx,3 |
mov al,0x80 |
out dx,al |
mov dx,bx |
add dx,1 |
mov al,0 |
out dx,al |
mov dx,bx |
add dx,0 |
mov al,0x30*2 ; 0x30 / 4 |
out dx,al |
mov dx,bx |
add dx,3 |
mov al,2 ; 3 |
out dx,al |
mov dx,bx |
add dx,4 |
mov al,0xb |
out dx,al |
mov dx,bx |
add dx,1 |
mov al,1 |
out dx,al |
; com2 mouse enable |
mov bx,0x2f8 ; combase |
mov dx,bx |
add dx,3 |
mov al,0x80 |
out dx,al |
mov dx,bx |
add dx,1 |
mov al,0 |
out dx,al |
mov dx,bx |
add dx,0 |
mov al,0x30*2 |
out dx,al |
mov dx,bx |
add dx,3 |
mov al,2 |
out dx,al |
mov dx,bx |
add dx,4 |
mov al,0xb |
out dx,al |
mov dx,bx |
add dx,1 |
mov al,1 |
out dx,al |
ret |
_rdtsc: |
mov edx,[cpuid_1+3*4] |
test edx,00010000b |
jz ret_rdtsc |
rdtsc |
ret |
ret_rdtsc: |
mov edx,0xffffffff |
mov eax,0xffffffff |
ret |
rerouteirqs: |
cli |
mov al,0x11 ; icw4, edge triggered |
out 0x20,al |
call pic_delay |
out 0xA0,al |
call pic_delay |
mov al,0x20 ; generate 0x20 + |
out 0x21,al |
call pic_delay |
mov al,0x28 ; generate 0x28 + |
out 0xA1,al |
call pic_delay |
mov al,0x04 ; slave at irq2 |
out 0x21,al |
call pic_delay |
mov al,0x02 ; at irq9 |
out 0xA1,al |
call pic_delay |
mov al,0x01 ; 8086 mode |
out 0x21,al |
call pic_delay |
out 0xA1,al |
call pic_delay |
mov al,255 ; mask all irq's |
out 0xA1,al |
call pic_delay |
out 0x21,al |
call pic_delay |
mov ecx,0x1000 |
cld |
picl1: call pic_delay |
loop picl1 |
mov al,255 ; mask all irq's |
out 0xA1,al |
call pic_delay |
out 0x21,al |
call pic_delay |
cli |
ret |
pic_delay: |
jmp pdl1 |
pdl1: ret |
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 |
uglobal |
msg_board_data: times 512 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 |
mov [msg_board_data+ecx],bl |
inc ecx |
and ecx, 511 |
mov [msg_board_count], ecx |
mov [check_idle_semaphore], 5 |
ret |
smbl1: |
cmp eax, 2 |
jne smbl2 |
test ecx, ecx |
jz smbl21 |
; mov edi, msg_board_data |
; mov esi, msg_board_data+1 |
; movzx eax, byte [edi] |
mov eax, msg_board_data+1 |
mov ebx, msg_board_data |
movzx edx, byte [ebx] |
call memmove |
; push ecx |
; shr ecx, 2 |
; cld |
; rep movsd |
; pop ecx |
; and ecx, 3 |
; rep movsb |
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 |
sys_trace: |
test eax, eax ; get event data |
jnz no_get_sys_events |
mov esi,save_syscall_data ; data |
mov edi,[0x3010] |
mov edi,[edi+0x10] |
add edi,ebx |
cld |
rep movsb |
mov [esp+24],dword 0 |
mov eax,[save_syscall_count] ; count |
mov [esp+36],eax |
ret |
no_get_sys_events: |
ret |
sys_process_def: |
cmp eax,1 ; set keyboard mode |
jne no_set_keyboard_setup |
mov edi,[0x3000] |
shl edi,8 |
add edi,0x80000+0xB4 |
mov [edi],bl |
ret |
no_set_keyboard_setup: |
cmp eax,2 ; get keyboard mode |
jne no_get_keyboard_setup |
mov edi,[0x3000] |
shl edi,8 |
add edi,0x80000+0xB4 |
movzx eax, byte [edi] |
mov [esp+36],eax |
ret |
no_get_keyboard_setup: |
cmp eax,3 ; get keyboard ctrl, alt, shift |
jne no_get_keyboard_cas |
; 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 |
;// mike.dld [ |
mov eax, [kb_state] |
;// mike.dld ] |
mov [esp+36],eax |
ret |
no_get_keyboard_cas: |
ret |
sys_ipc: |
cmp eax,1 ; DEFINE IPC MEMORY |
jne no_ipc_def |
mov edi,[0x3000] |
shl edi,8 |
add edi,0x80000 |
mov [edi+0xA0],ebx |
mov [edi+0xA4],ecx |
mov [esp+36],dword 0 |
ret |
no_ipc_def: |
cmp eax,2 ; SEND IPC MESSAGE |
jne no_ipc_send |
mov esi,1 |
mov edi,0x3020 |
ipcs1: |
cmp [edi+4],ebx |
je ipcs2 |
add edi,0x20 |
inc esi |
cmp esi,[0x3004] |
jbe ipcs1 |
mov [esp+36],dword 4 |
ret |
ipcs2: |
cli |
push esi |
mov eax,esi |
shl eax,8 |
mov ebx,[eax+0x80000+0xa0] |
test ebx,ebx ; ipc area not defined ? |
je ipc_err1 |
add ebx,[eax+0x80000+0xa4] |
mov eax,esi |
shl eax,5 |
add ebx,[eax+0x3000+0x10] ; ebx <- max data position |
mov eax,esi ; to |
shl esi,8 |
add esi,0x80000 |
mov edi,[esi+0xa0] |
shl eax,5 |
add eax,0x3000 |
add edi,[eax+0x10] |
cmp [edi],byte 0 ; overrun ? |
jne ipc_err2 |
mov ebp,edi |
add edi,[edi+4] |
add edi,8 |
mov esi,ecx ; from |
mov eax,[0x3010] |
mov eax,[eax+0x10] |
add esi,eax |
mov ecx,edx ; size |
mov eax,edi |
add eax,ecx |
cmp eax,ebx |
jge ipc_err3 ; not enough room ? |
push ecx |
mov eax,[0x3010] |
mov eax,[eax+4] |
mov [edi-8],eax |
mov [edi-4],ecx |
cld |
rep movsb |
pop ecx |
add ecx,8 |
mov edi,ebp ; increase memory position |
add dword [edi+4],ecx |
mov edi,[esp] |
shl edi,8 |
or dword [edi+0x80000+0xA8],dword 01000000b ; ipc message |
cmp [check_idle_semaphore],dword 20 |
jge ipc_no_cis |
mov [check_idle_semaphore],5 |
ipc_no_cis: |
xor eax, eax |
ipc_err: |
add esp,4 |
mov [esp+36],eax |
sti |
ret |
ipc_err1: |
add esp,4 |
mov [esp+36],dword 1 |
sti |
ret |
ipc_err2: |
add esp,4 |
mov [esp+36],dword 2 |
sti |
ret |
ipc_err3: |
add esp,4 |
mov [esp+36],dword 3 |
sti |
ret |
no_ipc_send: |
mov [esp+36],dword -1 |
ret |
align 4 |
sys_gs: ; direct screen access |
cmp eax,1 ; resolution |
jne no_gs1 |
mov eax,[0xfe00] |
shl eax,16 |
mov ax,[0xfe04] |
add eax,0x00010001 |
mov [esp+36],eax |
ret |
no_gs1: |
cmp eax,2 ; bits per pixel |
jne no_gs2 |
movzx eax,byte [0xfbf1] |
mov [esp+36],eax |
ret |
no_gs2: |
cmp eax,3 ; bytes per scanline |
jne no_gs3 |
mov eax,[0xfe08] |
mov [esp+36],eax |
ret |
no_gs3: |
mov [esp+36],dword -1 |
ret |
align 4 ; PCI functions |
sys_pci: |
call pci_api |
mov [esp+36],eax |
ret |
align 4 ; system functions |
syscall_setpixel: ; SetPixel |
mov edx,[0x3010] |
add eax,[edx-twdw] |
add ebx,[edx-twdw+4] |
xor edi,edi ; no force |
call [disable_mouse] |
jmp [putpixel] |
align 4 |
syscall_writetext: ; WriteText |
mov edi,[0x3010] |
mov ebp,[edi-twdw] |
shl ebp,16 |
add ebp,[edi-twdw+4] |
add edi,0x10 |
add ecx,[edi] |
add eax,ebp |
xor edi,edi |
jmp dtext |
align 4 |
syscall_openramdiskfile: ; OpenRamdiskFile |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
add edx,[edi] |
mov esi,12 |
call fileread |
mov [esp+36],ebx |
ret |
align 4 |
syscall_putimage: ; PutImage |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
mov edx,ecx |
mov ecx,ebx |
mov ebx,eax |
call sys_putimage |
mov [esp+36],eax |
ret |
align 4 |
syscall_drawrect: ; DrawRect |
mov edi,ecx |
test ax,ax |
je drectr |
test bx,bx |
je drectr |
movzx ecx,ax |
shr eax,16 |
movzx edx,bx |
shr ebx,16 |
add ecx,eax |
add edx,ebx |
jmp [drawbar] |
drectr: |
ret |
align 4 |
syscall_getscreensize: ; GetScreenSize |
movzx eax,word[0xfe00] |
shl eax,16 |
mov ax,[0xfe04] |
mov [esp+36],eax |
ret |
align 4 |
syscall_system: ; System |
call sys_system |
mov [esp+36],eax |
ret |
align 4 |
syscall_startapp: ; StartApp |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
test ebx,ebx |
jz noapppar |
add ebx,[edi] |
noapppar: |
; call start_application_fl |
call new_start_application_fl |
mov [esp+36],eax |
ret |
align 4 |
syscall_cdaudio: ; CD |
call sys_cd_audio |
mov [esp+36],eax |
ret |
align 4 |
syscall_readhd: ; ReadHd |
mov edi,[0x3010] |
add edi,0x10 |
add esi,[edi] |
add eax,[edi] |
call read_hd_file |
mov [esp+36],eax |
mov [esp+24],ebx |
ret |
align 4 |
syscall_starthdapp: ; StartHdApp |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
add ecx,[edi] |
mov ebp,0 |
call start_application_hd |
mov [esp+36],eax |
ret |
align 4 |
syscall_delramdiskfile: ; DelRamdiskFile |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
call filedelete |
mov [esp+36],eax |
ret |
align 4 |
syscall_writeramdiskfile: ; WriteRamdiskFile |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
add ebx,[edi] |
call filesave |
mov [esp+36],eax |
ret |
align 4 |
syscall_getpixel: ; GetPixel |
mov ecx,[0xfe00] |
inc ecx |
xor edx,edx |
div ecx |
mov ebx,edx |
xchg eax,ebx |
call dword [0xe024] |
mov [esp+36],ecx |
ret |
align 4 |
syscall_readstring: ; ReadString |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
call read_string |
mov [esp+36],eax |
ret |
align 4 |
syscall_drawline: ; DrawLine |
mov edi,[0x3010] |
movzx edx,word[edi-twdw] |
mov ebp,edx |
shl edx,16 |
add ebp,edx |
movzx edx,word[edi-twdw+4] |
add eax,ebp |
mov ebp,edx |
shl edx,16 |
xor edi,edi |
add edx,ebp |
add ebx,edx |
jmp [draw_line] |
align 4 |
syscall_getirqowner: ; GetIrqOwner |
shl eax,2 |
add eax,irq_owner |
mov eax,[eax] |
mov [esp+36],eax |
ret |
align 4 |
syscall_reserveportarea: ; ReservePortArea and FreePortArea |
call r_f_port_area |
mov [esp+36],eax |
ret |
align 4 |
syscall_appints: ; AppInts |
test eax,eax |
jnz unknown_app_int_fn |
mov edi,[0x3010] |
mov [edi+draw_data-0x3000+0x1c],ebx |
ret |
unknown_app_int_fn: |
mov [esp+36],dword -1 |
ret |
align 4 |
syscall_threads: ; CreateThreads |
call sys_threads |
mov [esp+36],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+36],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 |
user_events: ; User event times |
mov eax,0x12345678 |
mov [esp+36],eax |
ret |
align 4 |
read_from_hd: ; Read from hd - fn not in use |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
add ecx,[edi] |
add edx,[edi] |
call file_read |
mov [esp+36],eax |
mov [esp+24],ebx |
ret |
align 4 |
write_to_hd: ; Write a file to hd |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
add ecx,[edi] |
add edx,[edi] |
call file_write |
ret |
align 4 |
delete_from_hd: ; Delete a file from hd |
mov edi,[0x3010] |
add edi,0x10 |
add eax,[edi] |
add ecx,[edi] |
call file_delete |
ret |
align 4 |
undefined_syscall: ; Undefined system call |
mov [esp+36],dword -1 |
ret |
;clear_busy_flag_at_caller: |
; push edi |
; mov edi,[0x3000] ; restore processes tss pointer in gdt, busyfl? |
; imul edi,8 |
; mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
; pop edi |
; ret |
keymap: |
db '6',27 |
db '1234567890-=',8,9 |
db 'qwertyuiop[]',13 |
db '~asdfghjkl;',39,96,0,'\zxcvbnm,./',0,'45 ' |
db '@234567890123',180,178,184,'6',176,'7' |
db 179,'8',181,177,183,185,182 |
db 'AB<D',255,'FGHIJKLMNOPQRSTUVWXYZ' |
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
keymap_shift: |
db '6',27 |
db '!@#$%^&*()_+',8,9 |
db 'QWERTYUIOP{}',13 |
db '~ASDFGHJKL:"~',0,'|ZXCVBNM<>?',0,'45 ' |
db '@234567890123',180,178,184,'6',176,'7' |
db 179,'8',181,177,183,185,182 |
db 'AB>D',255,'FGHIJKLMNOPQRSTUVWXYZ' |
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
keymap_alt: |
db ' ',27 |
db ' @ $ {[]}\ ',8,9 |
db ' ',13 |
db ' ',0,' ',0,'4',0,' ' |
db ' ',180,178,184,'6',176,'7' |
db 179,'8',181,177,183,185,182 |
db 'ABCD',255,'FGHIJKLMNOPQRSTUVWXYZ' |
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
; device irq owners |
uglobal |
irq_owner: ; process id |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
dd 0x0 |
endg |
; on irq read ports |
uglobal |
irq00read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq01read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq02read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq03read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq04read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq05read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq06read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq07read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq08read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq09read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq10read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq11read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq12read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq13read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq14read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
irq15read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
endg |
; status |
uglobal |
hd1_status dd 0x0 ; 0 - free : other - pid |
application_table_status dd 0x0 ; 0 - free : other - pid |
endg |
; device addresses |
uglobal |
mididp dd 0x0 |
midisp dd 0x0 |
cdbase dd 0x0 |
cdid dd 0x0 |
hdbase dd 0x0 ; for boot 0x1f0 |
hdid dd 0x0 |
hdpos dd 0x0 ; for boot 0x1 |
fat32part dd 0x0 ; for boot 0x1 |
;part2_ld dd 0x0 |
;* start code - get process (3) - Mario79 |
active_process dd 0 |
;* end code - get active process (3) - Mario79 |
wraw_bacground_select db 0 |
lba_read_enabled dd 0x0 ; 0 = disabled , 1 = enabled |
pci_access_enabled dd 0x0 ; 0 = disabled , 1 = enabled |
sb16 dd 0x0 |
wss dd 0x0 |
buttontype dd 0x0 |
windowtypechanged dd 0x0 |
endg |
iglobal |
keyboard dd 0x1 |
sound_dma dd 0x1 |
syslang dd 0x1 |
endg |
IncludeIGlobals |
endofcode: |
IncludeUGlobals |
uglobals_size = $ - endofcode |
diff16 "end of kernel code",$ |
/kernel/trunk/kernel16.inc |
---|
0,0 → 1,31 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; KERNEL16.INC ;; |
;; ;; |
;; Included 16 bit kernel files for MenuetOS ;; |
;; ;; |
;; This file is kept separate as it will be easier to ;; |
;; maintain and compile with an automated SETUP program ;; |
;; in the future. ;; |
;; ;; |
;; Copyright Ville Turjanmaa, see file COPYING for details. ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;% +include |
;!!! |
if lang eq en |
include "boot/booteng.inc" ; english system boot messages |
else |
include "boot/bootru.inc" ; russian system boot messages |
;!!! |
end if |
include "boot/ru.inc" ; Russian font |
include "boot/bootcode.inc" ; 16 bit system boot code |
include "bus/pci/pci16.inc" |
;% -include |
/kernel/trunk/kernel32.inc |
---|
0,0 → 1,105 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; KERNEL32.INC ;; |
;; ;; |
;; Included 32 bit kernel files for MenuetOS ;; |
;; ;; |
;; This file is kept separate as it will be easier to ;; |
;; maintain and compile with an automated SETUP program ;; |
;; in the future. ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; structure definition helper |
macro struct name, [arg] |
{ |
common |
name@struct fix name |
struc name arg { |
} |
macro struct_helper name |
{ |
virtual at 0 |
name name |
sizeof.#name = $ - name |
name equ sizeof.#name |
end virtual |
} |
ends fix } struct_helper name@struct |
; Core functions |
include "core/sync.inc" |
include "core/sys32.inc" ; process management |
include "core/sched.inc" ; process scheduling |
include "core/fpu.inc" ; FPU handler |
include "core/syscall.inc" ; system call |
include "core/mem.inc" ; high-level memory management |
include "core/newproce.inc" ;new process management |
include "core/physmem.inc" ; access to physical memory for applications |
include "core/sync.inc" ; macros for synhronization objects |
; GUI stuff |
include "gui/window.inc" |
include "gui/event.inc" |
include "gui/font.inc" |
include "gui/button.inc" |
; shutdown |
include "boot/shutdown.inc" ; shutdown or restart |
; file system |
include "fs/fs.inc" ; syscall |
include "fs/fat32.inc" ; read / write for fat32 filesystem |
include "fs/fat12.inc" ; read / write for fat12 filesystem |
include "blkdev/rd.inc" ; ramdisk read /write |
; sound |
include "sound/sb16.inc" ; playback for Sound Blaster 16 |
include "sound/playnote.inc" ; player Note for Speaker PC |
; display |
include "video/vesa12.inc" ; Vesa 1.2 functions |
include "video/vesa20.inc" ; Vesa 2.0 functions |
include "video/vga.inc" ; VGA 16 color functions |
; Network Interface & TCPIP Stack |
include "network/stack.inc" |
; Mouse pointer |
include "gui/mouse.inc" |
; Window skinning |
include "gui/skincode.inc" |
; Pci functions |
include "bus/pci/pci32.inc" |
; Floppy drive controller |
include "blkdev/fdc.inc" |
include "blkdev/flp_drv.inc" |
; CD drive controller |
include "blkdev/cdrom.inc" |
; Character devices |
include "hid/keyboard.inc" |
; setting date,time,clock and alarm-clock |
include "hid/set_dtc.inc" |
;% -include |
/kernel/trunk/kglobals.inc |
---|
0,0 → 1,50 |
;------------------------------------------------------------------ |
; use "iglobal" for inserting initialized global data definitions. |
;------------------------------------------------------------------ |
macro iglobal { |
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 { } |
endg fix } ; Use endg for ending iglobal and uglobal blocks. |
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 |
/kernel/trunk/memmap.inc |
---|
0,0 → 1,239 |
; |
; 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:9020 8bytes pci data |
; 0:9030 byte VRR start enabled 1, 2-no |
; 0:9031 word IDEContrRegsBaseAddr |
; |
; |
; Runtime: |
; |
; 0000 -> 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 word 0, state 3=zombie, 4=terminate |
; 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 |
; |
; -> delete -> 5000 -> AFFF free |
; |
;!!! |
; 5000 -> 5FFF save_syscall_data - syscall trace |
; 6000 -> 63FF reg1 array - for i40 (first parts of saved TSS descriptor) |
; 6400 -> 67FF reg2 array - same thing, second part |
; 6800 -> 68FF used i40 (1 if used, 0 if free), first element not used |
; 6900 -> 6EFF saved picture under mouse pointer |
; |
; 6F00 -> 7FFF i38 stack (4,25Kb) |
; |
; 8000 -> A3FF used FLOPPY driver |
; |
; A400 -> AFFF free |
; |
; B000 -> B005 jump address for irq0 (task switch) |
; B008 -> B00B count of ticks remaining to updating CPU usage info |
; |
; B060 -> B07F fpu error handler's stack |
; B080 -> B0FF fpu_tss -> temporary TSS for FPU context switching |
; B100 -> B2FF IDT |
; B300 -> BAFF tasknum array - for i40 handler |
; BB00 -> BEFF free |
;!!! |
; BF00 -> BFFF bytes, 1 if process running/memory in use |
; 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 |
; E000 byte multitasking started |
; E004 dword save for boot mem 0x24 |
; E010 dword pm bank switch address |
; E014 dword window multiplier |
; E020 dword putpixel address |
; E024 dword getpixel address |
; E030 dword Vesa 1.2 pm bank switch address |
; F000 dword hd partition 1 start |
; F004 dword root start at partition 1 |
; F008 dword root start at hd |
; F100 byte 1=only os draw on screen |
; F200 dword mousepicture -pointer |
; F204 dword mouse appearance counter |
; F300 dword x & y temp for windowmove |
; 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 mouse port: 1 ps2, 2 com1, 3 com2 |
; FB00 -> FB0F mouse memory 00 chunk count - FB0A-B x - FB0C-D y |
; 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 |
; FBF0 byte multiplied window |
; FBF1 byte bits per pixel |
; FC00 -> FCFE com1/ps2 buffer |
; FCFF com1/ps2 buffer count starting from FC00 |
; FDF0 -> FDF3 timer tick inc every 1/100 sec 4 bytes |
; FE00 dword screen x size |
; FE04 dword screen y size |
; FE08 dword screen y multiplier |
; FE0C dword screen mode |
; FE10 dword entries in hd cache |
; 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 |
; FF00 byte 1 = system shutdown request |
; FF01 dword if >1 then activate process |
; FFF0 byte 1 = redraw background request from app |
; FFF1 byte 1 = diskette int occur |
; 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. |
; |
; 10000 -> 1FFFF 32 bit os |
; 20000 -> 2FFFF 32 bit stack |
; 30000 -> 36FFF basic text font II |
; 37000 -> 3BFFF basic text font I |
; 40000 -> 4FFFF data of retrieved disks and partitions (Mario79) |
; 50000 -> 500FF TSS of scheduler |
; 51000 -> 54000 esp0,esp1,esp2 |
; 5F000 -> 5FFFF schedulers stack |
; 60000 -> 7FFFF paging tables |
; 80000 -> 8FFFF additional app info, in 256 byte steps - 256 entries |
; |
; 00 11db name of app running |
; 10 108db floating point unit save area |
; 7f byte 0= no fpu saved , 1= fpu saved to 0x10 -> restore |
; 80 dword address of random shaped window area |
; 84 byte shape area scale |
; 88 dword used GDT of TSS |
; 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,.. |
; |
; B0 dword int40 handler in use ; 0 if not in use |
; B4 byte keyboard mode: 0 = keymap, 1 = scancodes |
; |
; 90000 -> 9FFFF tmp |
; A0000 -> AFFFF screen access area |
; B0000 -> FFFFF bios rest in peace -area |
; 100000 -> 27FFFF diskette image |
; 280000 -> 281FFF ramdisk fat |
; 282000 -> 283FFF floppy fat |
; |
; 284000 -> 28FFFF free |
; |
; 290000 -> 297FFF TSS's of interrupts |
; 298000 -> 29FFFF TSS's of SYSTEM interrupts - 256 entries |
; 2A0000 -> 2B00ff wav device data |
; 2C0000 -> 2C3fff button info |
; |
; 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 |
; |
; 2D0000 -> 2DFFFF reserved port area |
; |
; 0000 dword no of port areas reserved |
; 0010 dword process id |
; dword start port |
; dword end port |
; dword 0 |
; |
; 2E0000 -> 2EFFFF irq data area |
; 2F0000 -> 2FFFFF low memory save |
; |
; 300000 -> 45FFFF background image, max 1 M |
; |
; 460000 -> 5FFFFF display info |
; |
; 600000 -> 6FFFFF hd cache |
; |
; 700000 -> 71ffff tcp memory (128 kb) |
; 720000 -> 75ffff interrupt stacks (256 kpl * 1024) |
; |
; 760000 -> 76ffff !vrr driver |
; 770000 -> 777fff tcp memory ( 32 kb) |
; |
; 778000 -> 77ffff window skinning ( 32 kb) |
; 780000 -> 7fffff free |
; |
; 800000 -> BFFFFF mapped to LFB |
; |
; C00000 -> DFFFFF * Application information |
; |
; C00000 -> C01FFF draw_data - 256 entries |
; |
; 00 dword draw limit - x start |
; 04 dword draw limit - y start |
; 08 dword draw limit - x end |
; 0C dword draw limit - y end |
; 1C dword app int vector |
; |
; C03000 -> D11fff sysint_stack_data |
; - system interrupt stacks |
; - 256 entries * 4096 step |
; |
; D20000 -> DA8000 TSS and IO map for (2048*8)=16384 ports |
; (128+2048)*256 = 557956 = 0x88000 |
; |
; 1000000 -> 3FFFFFF for applications |
; |
/kernel/trunk/network/eth_drv/3c59x.inc |
---|
0,0 → 1,2380 |
;; 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 |
{ |
if defined E3C59X_LINUX |
sub reg, [virt_addr] |
add reg, [dma_addr] |
end if |
} |
macro dma_to_virt reg |
{ |
if defined E3C59X_LINUX |
sub reg, [dma_addr] |
add reg, [virt_addr] |
end if |
} |
macro zero_to_virt reg |
{ |
if defined E3C59X_LINUX |
add reg, [virt_addr] |
end if |
} |
macro virt_to_zero reg |
{ |
if defined E3C59X_LINUX |
sub reg, [virt_addr] |
end if |
} |
macro zero_to_dma reg |
{ |
if defined E3C59X_LINUX |
add reg, [dma_addr] |
end if |
} |
macro dma_to_zero reg |
{ |
if defined E3C59X_LINUX |
sub reg, [dma_addr] |
end if |
} |
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, 2000 |
.tx_reset_loop: |
in ax, dx |
test ah, 10000b ; check CmdInProgress |
jz .tx_enable |
dec ecx |
jns .tx_reset_loop |
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 |
/kernel/trunk/network/eth_drv/ethernet.inc |
---|
0,0 → 1,1681 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; ETHERNET.INC ;; |
;; ;; |
;; Ethernet network layer for Menuet OS ;; |
;; ;; |
;; Version 0.4 22 September 2003 ;; |
;; ;; |
;; 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************** |
; Interface |
; ethernet_driver called by stack_handler in stack.inc |
; eth_probe called by app_stack_handler in stack.inc |
; |
;******************************************************************** |
; 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 "rtl8029.inc" |
include "i8255x.inc" |
include "rtl8139.inc" |
include "3c59x.inc" |
include "sis900.inc" |
include "pcnet32.inc" |
; DEBUGGING_STATE enables or disables output of received and transmitted |
; data over the serial port |
DEBUGGING_ENABLED equ 1 |
DEBUGGING_DISABLED equ 0 |
DEBUGGING_STATE equ DEBUGGING_DISABLED |
; 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 20 ; Size of each PCICARDS entry |
iglobal |
PCICards: |
dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit |
dd 0x12111113, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit |
dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit |
dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit |
dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit |
dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit |
; following card is untested |
dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit |
dd 0,0,0,0,0 ; end of list marker, do not remove |
endg |
; 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 |
ETHER_IP equ 0x0008 ; Reversed from 0800 for intel |
ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel |
ETHER_RARP equ 0x3580 |
ARP_REQ_OPCODE equ 0x0100 |
ARP_REP_OPCODE equ 0x0200 |
uglobal |
arp_rx_count: dd 0 |
ip_rx_count: dd 0 |
dumped_rx_count: dd 0 |
ip_tx_count: dd 0 |
node_addr: db 0,0,0,0,0,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 |
; These hold the destination Host identity for ARP responses |
remote_ip_add: dd 0 |
remote_hw_add: db 0, 0, 0, 0, 0, 0 |
endg |
iglobal |
broadcast_add: db 0xff,0xff,0xff,0xff,0xff,0xff |
subnet_mask: dd 0x00ffffff |
endg |
uglobal |
; This is used by getMACfromIP |
MACAddress: db 0,0,0,0,0,0 |
gateway_ip: db 0, 0, 0, 0 |
dns_ip: dd 0 |
endg |
; The follow is the ARP Table. |
; This table must be manually updated and the kernel recompilied if |
; changes are made to it. |
; ARP_TABLE_SIZE defines the size of the table |
; ARP_TABLE_ENTRIES defines the number of entries in the table |
; Each entry is 10 bytes: 4 Byte IP address, 6 byte MAC Address, |
; 2 bytes status, 2 bytes TTL ( in seconds ) |
; Empty entries are filled with zeros |
; 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 permanent 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 |
ARP_NO_ENTRY equ 0 |
ARP_VALID_MAPPING equ 1 |
ARP_AWAITING_RESPONSE equ 2 |
ARP_RESPONSE_TIMEOUT equ 3 |
ARP_ENTRY_SIZE equ 14 ; Number of bytes per entry |
ARP_TABLE_SIZE equ 20 ; Size of table |
ARP_TABLE_ENTRIES equ 0 ; Inital, hardcoded entries |
uglobal |
ARPTable: |
times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE db 0 |
endg |
iglobal |
NumARP: db ARP_TABLE_ENTRIES |
endg |
;*************************************************************************** |
; 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 erx_exit |
if DEBUGGING_STATE = DEBUGGING_ENABLED |
pusha |
mov eax, 0 ;Indicate that this is a received packet |
mov cx, [eth_rx_data_len] |
mov esi, Ether_buffer |
cmp word [esi + 12], ETHER_IP |
jnz erxd_done |
; cmp byte [esi + 14 + 9], 0x06 ; TCP |
; jnz erxd_done |
call eth_dump |
erxd_done: |
popa |
end if |
; Check the protocol. Call appropriate handler |
mov eax, Ether_buffer |
add eax, 12 ; The address of the protocol word |
mov ax, [eax] |
cmp ax, ETHER_ARP |
je erx_001 ; It is ARP |
cmp ax, ETHER_IP |
je erx_002 ; It's IP |
; inc dword [dumped_rx_count] |
jmp erx_exit ; If not IP or ARP, ignore |
erx_001: |
mov eax, [arp_rx_count] |
inc eax |
mov [arp_rx_count], eax |
; At this point, the packet is still in the Ether_buffer |
call arp_handler |
jmp erx_exit |
erx_002: |
mov eax, [ip_rx_count] |
inc eax |
mov [ip_rx_count], eax |
; Check to see if the MAC address is in our arp table |
; refresh the arp ttl if so |
mov esi, Ether_buffer |
add esi, 6 |
call refreshARP |
call ether_IP_handler |
jmp erx_exit |
erx_exit: |
ret |
;*************************************************************************** |
; 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 |
; |
;*************************************************************************** |
eth_tx: |
; Look for a buffer to tx |
mov eax, NET1OUT_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je eth_exit ; Exit if no buffer available |
push eax |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
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 ) |
mov [MACAddress], dword 0xffffffff |
mov [MACAddress + 4], word 0xffff |
cmp edx, 0xffffffff |
je etx_send ; If it is broadcast, just send |
call getMACfromIP ; Get the MAC address. |
cmp eax, ARP_VALID_MAPPING |
jz etx_send |
; No valid entry. Are we waiting for a response? |
cmp eax, ARP_AWAITING_RESPONSE |
jne etx_001 |
; Re-queue the packet, and exit |
pop ebx |
mov eax, NET1OUT_QUEUE |
call queue |
jmp etx_exit |
etx_001: |
; HAs the request been sent, but timed out? |
cmp eax, ARP_RESPONSE_TIMEOUT |
jne etx_002 |
pop eax |
call freeBuff |
jmp etx_exit |
etx_002: |
; There is no entry. Re queue the request, and ask ARP to send a request |
; IP address is in edx |
push edx |
call arp_request |
pop ebx |
; Add an entry in the ARP table, awaiting response |
cmp byte [NumARP], ARP_TABLE_SIZE |
je etx_003 ; We cannot add a new entry in the table |
inc byte [NumARP] |
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
sub eax, ARP_ENTRY_SIZE |
mov [eax + ARPTable], ebx |
xor ebx, ebx |
mov [eax + ARPTable + 4], ebx |
mov [eax + ARPTable + 8], bx |
; set the status field up - awaiting response |
mov cl, 0x00 |
mov [eax + ARPTable + 10], cl |
mov cl, 0x02 |
mov [eax + ARPTable + 11], cl |
; Initialise the time to live field - 10s |
mov cx, 0x000A |
mov [eax + ARPTable + 12], cx |
etx_003: |
pop ebx ; Get the buffer back |
mov eax, NET1OUT_QUEUE |
call queue |
jmp etx_exit |
etx_send: |
xor ecx, ecx |
mov ch, [ebx+2] |
mov cl, [ebx+3] ; ; Size of IP packet to send |
mov esi, ebx |
mov edi, MACAddress |
if DEBUGGING_STATE = DEBUGGING_ENABLED |
pusha |
mov cx, 42 |
mov eax, 1 ; Indicate that this is a tx packet |
call eth_dump |
popa |
end if |
mov bx, ETHER_IP |
call dword [drvr_transmit] ; Call the drivers transmit function |
; OK, we have sent a packet, so increment the count |
inc dword [ip_tx_count] |
; And finally, return the buffer to the free queue |
pop eax |
call freeBuff |
etx_exit: |
ret |
;*************************************************************************** |
; 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 |
; |
;*************************************************************************** |
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, Ether_buffer + 14 |
; Now store it all away |
mov ecx, IPBUFFSIZE / 4 ; Copy all of the available |
; data across - worse case |
cld |
rep movsd |
; And finally, place the buffer in the IPRX queue |
pop ebx |
mov eax, IPIN_QUEUE |
call queue |
eiph00x: |
ret |
;*************************************************************************** |
; |
; ARP CODE FOLLOWS |
; |
; The ARP code is used by ethernet drivers to translate an destination |
; IP address into an ethernet hardware address. Functions to broadcast |
; requests and handle response are (or will be) here. |
; The IP layer has no knowledge of ARP, as this is a network interface |
; issue |
; |
;*************************************************************************** |
;*************************************************************************** |
; Function |
; arp_timer |
; |
; Description |
; Called every 1s |
; It is responsible for removing expired routes |
; All registers may be destroyed |
; |
;*************************************************************************** |
arp_timer: |
; loop through all the ARP entries, decrementing each one |
; that doesn't have a TTL of 0xFFFF |
movzx eax, byte [NumARP] |
arp_001: |
cmp eax, 0 |
je arp_003 |
push eax |
dec eax |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
cmp word [ eax + ARPTable + 12], 0xFFFF |
je arp_002 |
cmp word [ eax + ARPTable + 12], 0 |
je arp_002 |
dec word [eax + ARPTable + 12] |
arp_002: |
pop eax |
dec eax |
jmp arp_001 |
; Now, look for entries with a TTL of 0 |
; Valid entries and response timeout entries get removed |
; awaiting response gets converted into a response timeout, with a |
; short life time - this allows queued packets to be flushed |
arp_003: |
movzx edx, byte [NumARP] |
cmp edx, 0 |
je arp_exit |
; EDX holds the # of entries to search through |
mov eax, 0 |
arp_005: |
cmp word [ eax + ARPTable + 12], 0 |
jne arp_004 |
; If it's status code is 0001 or 0003, delete the entry |
cmp word [eax + ARPTable + 10], 0x0100 |
je arp_007 |
cmp word [eax + ARPTable + 10], 0x0300 |
je arp_007 |
; The only other valid code is 0002 - indicating a |
; timeout while waiting for a response. Change the |
; entry to response timed out |
mov [eax + ARPTable + 10], word 0x0300 |
mov [eax + ARPTable + 12], word 0x000A |
jmp arp_004 |
arp_007: |
; Delete this entry |
mov edi, ARPTable |
add edi, eax |
mov esi, edi |
add esi, ARP_ENTRY_SIZE |
mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE |
sub ecx, eax |
rep movsb |
dec byte [NumARP] |
jmp arp_006 |
arp_004: |
add eax, ARP_ENTRY_SIZE |
arp_006: |
dec edx |
cmp edx, 0 |
jne arp_005 |
arp_exit: |
ret |
;*************************************************************************** |
; Function |
; arp_request |
; |
; Description |
; Sends an ARP request on the ethernet |
; The requested IP address is in edx |
; All registers may be destroyed |
; |
;*************************************************************************** |
arp_request: |
mov ebx, Ether_buffer |
mov ax, 0x0100 |
mov [ebx], ax |
add ebx, 2 |
mov ax, 0x0008 |
mov [ebx], ax |
add ebx, 2 |
mov ax, 0x0406 |
mov [ebx], ax |
add ebx, 2 |
mov ax, 0x0100 |
mov [ebx], ax |
add ebx, 2 |
mov ecx, node_addr |
mov eax, [ecx] |
mov [ebx], eax |
add ecx, 4 |
add ebx, 4 |
mov ax, [ecx] |
mov [ebx], ax |
add ebx, 2 |
mov eax, [stack_ip] |
mov [ebx], eax |
add ebx, 4 |
xor eax, eax |
mov [ebx], eax |
add ebx, 4 |
mov [ebx], ax |
add ebx, 2 |
mov [ebx], edx |
; Now, send it! |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
mov edi, broadcast_add |
;if DEBUGGING_STATE = DEBUGGING_ENABLED |
; pusha |
; mov eax, 1 ; Indicate that this is a tx packet |
; mov ecx, 28 |
; mov esi, Ether_buffer |
; call eth_dump |
; popa |
;end if |
mov bx, ETHER_ARP |
mov ecx, 28 |
mov esi, Ether_buffer |
call dword [drvr_transmit] ; Call the drivers transmit function |
ret |
;*************************************************************************** |
; 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 |
mov ebx, Ether_buffer |
mov edx, ebx |
add edx, 20 |
mov ax, [edx] |
cmp ax, ARP_REQ_OPCODE ; Is this a request packet? |
jne arph_resp ; No - so test for response |
mov edx, ebx |
add edx, 38 |
mov eax, [edx] |
cmp eax, [stack_ip] ; Is it looking for my IP address? |
jne arph_exit ; No - so quit now |
; OK, it is a request for my MAC address. Build the frame and send it |
; Save the important data from the original packet |
; remote MAC address first |
mov ecx, remote_hw_add |
mov edx, ebx |
add edx, 22 ; edx points to Source h/w address |
mov eax, [edx] |
mov [ecx], eax |
add edx, 4 |
add ecx, 4 |
mov ax, [edx] |
mov [ecx],ax |
; and also the remote IP address |
add edx, 2 |
mov eax,[edx] |
mov [remote_ip_add], eax |
; So now we can reuse the packet. ebx still holds the address of |
; the header + packet |
; We dont need the header ( first 14 bytes ) |
mov edx, ebx |
add edx, 20 |
mov ax, ARP_REP_OPCODE |
mov [edx], ax |
add edx, 2 |
mov ecx, node_addr |
mov eax, [ecx] |
mov [edx], eax |
add ecx, 4 |
add edx, 4 |
mov ax, [ecx] |
mov [edx], ax |
add edx, 2 |
mov eax, [stack_ip] |
mov [edx], eax |
add edx, 4 |
mov ecx, remote_hw_add |
mov eax, [ecx] |
mov [edx], eax |
add ecx, 4 |
add edx, 4 |
mov ax, [ecx] |
mov [edx], ax |
add edx, 2 |
mov eax, [remote_ip_add] |
mov [edx], eax |
; Now, send it! |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
mov edi, remote_hw_add |
;if DEBUGGING_STATE = DEBUGGING_ENABLED |
; pusha |
; mov eax, 1 ; Indicate that this is a tx packet |
; mov ecx, 28 |
; mov esi, Ether_buffer + 14 |
; call eth_dump |
; popa |
;end if |
mov bx, ETHER_ARP |
mov ecx, 28 |
mov esi, Ether_buffer + 14 |
call dword [drvr_transmit] ; Call the drivers transmit function |
jmp arph_exit |
arph_resp: |
cmp ax, ARP_REP_OPCODE ; Is this a replypacket? |
jne arph_resp ; No - so quit |
; This was a reply, probably directed at me. |
; save the remotes MAC & IP |
mov ecx, remote_hw_add |
mov edx, ebx |
add edx, 22 ; edx points to Source h/w address |
mov eax, [edx] |
mov [ecx], eax |
add edx, 4 |
add ecx, 4 |
mov ax, [edx] |
mov [ecx],ax |
; and also the remote IP address |
add edx, 2 |
mov eax,[edx] |
mov [remote_ip_add], eax |
; Now, add an entry in the table for this IP address if it doesn't exist |
push eax |
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
pop edx |
movzx ecx, byte [NumARP] |
cmp ecx, 0 |
je arph_002 |
arph_001: |
sub eax, ARP_ENTRY_SIZE |
cmp [eax + ARPTable], edx |
loopnz arph_001 ; Return back if non match |
jnz arph_002 ; None found, add to end |
mov ecx, [remote_hw_add] |
mov [eax + ARPTable + 4], ecx |
mov cx, [remote_hw_add+4] |
mov [eax + ARPTable + 8], cx |
; specify the type - a valid entry |
mov cl, 0x00 |
mov [eax + ARPTable + 10], cl |
mov cl, 0x01 |
mov [eax + ARPTable + 11], cl |
; Initialise the time to live field - 1 hour |
mov cx, 0x0E10 |
mov [eax + ARPTable + 12], cx |
jmp arph_exit |
arph_002: |
cmp byte [NumARP], ARP_TABLE_SIZE |
je arph_exit |
inc byte [NumARP] |
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
sub eax, ARP_ENTRY_SIZE |
mov ecx, [remote_ip_add] |
mov [eax + ARPTable], ecx |
mov ecx, [remote_hw_add] |
mov [eax + ARPTable + 4], ecx |
mov cx, [remote_hw_add+4] |
mov [eax + ARPTable + 8], cx |
mov cl, 0x00 |
mov [eax + ARPTable + 10], cl |
mov cl, 0x01 |
mov [eax + ARPTable + 11], cl |
; Initialise the time to live field - 1 hour |
mov cx, 0x0E10 |
mov [eax + ARPTable + 12], cx |
arph_exit: |
ret |
; pointer to MAC in esi |
refreshARP: |
mov ebx, [esi] |
mov dx, [esi+4] |
push edx |
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
pop edx |
movzx ecx, byte [NumARP] |
cmp ecx, 0 |
je rf_exit |
rf_001: |
sub eax, ARP_ENTRY_SIZE |
cmp [eax + ARPTable+4], ebx |
je rf_002 |
loop rf_001 |
jmp rf_exit |
rf_002: |
cmp [eax + ARPTable+8], dx |
je rf_gotone |
loop rf_001 |
jmp rf_exit |
rf_gotone: |
; Initialise the time to live field - 1 hour |
mov cx, 0x0E10 |
mov [eax + ARPTable + 12], cx |
rf_exit: |
ret |
;*************************************************************************** |
; Function |
; getMACfromIP |
; |
; Description |
; Takes an IP address in edx and scans the ARP table for |
; a matching entry |
; If a match is found, it's MAC address is stored in MACAddress. |
; Otherwise the value 0 is writen to MACAddress |
; eax holds ARP table entry status code ( ARP_ ) |
; ebx unchanged |
; |
;*************************************************************************** |
getMACfromIP: |
; first, check destination IP to see if it is on 'this' network. |
; The test is: |
; if ( destIP & subnet_mask == stack_ip & subnet_mask ) |
; desitnation is local |
; else |
; destination is remote, so pass to gateway |
mov eax, edx |
and eax, [subnet_mask] |
mov ecx, [stack_ip] |
and ecx, [subnet_mask] |
cmp eax, ecx |
je gm0 |
mov edx, [gateway_ip] |
gm0: |
push edx |
xor eax, eax |
mov [MACAddress], eax |
mov [MACAddress + 4], ax |
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
pop edx |
movzx ecx, byte [NumARP] |
cmp ecx, 0 |
je gm_none |
gm1: |
sub eax, ARP_ENTRY_SIZE |
cmp [eax + ARPTable], edx |
loopnz gm1 ; Return back if non match |
jnz gm_none ; Quit if none found |
; eax holds index |
mov ecx, [eax + ARPTable + 4] |
mov [MACAddress], ecx |
mov cx, [eax + ARPTable + 8] |
mov [MACAddress+4], cx |
; Return the entry status in eax |
mov ch, [eax + ARPTable + 10] |
mov cl, [eax + ARPTable + 11] |
movzx eax, cx |
jmp gm_exit |
gm_none: |
mov eax, ARP_NO_ENTRY |
gm_exit: |
ret |
;*************************************************************************** |
; |
; PCI CODE FOLLOWS |
; |
; the following functions provide access to the PCI interface. |
; These functions are used by scan_bus, and also some ethernet drivers |
; |
;*************************************************************************** |
;*************************************************************************** |
; 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 |
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 |
;*************************************************************************** |
; |
; DEBUGGING CODE FOLLOWS |
; |
; If debugging data output is not required, ALL code & data below may |
; be removed. |
; |
;*************************************************************************** |
if DEBUGGING_STATE = DEBUGGING_ENABLED |
;*************************************************************************** |
; Function |
; eth_dump |
; |
; Description |
; Dumps a tx or rx ethernet packet over the rs232 link |
; This is a debugging routine that seriously slows down the stack. |
; Use with caution. |
; |
; Baud rate is 57600, 8n1 com1 |
; eax : type (0 == rx, 1 == tx ) |
; cx : # of bytes in buffer |
; esi : address of buffer start |
; edi : pointer to MACAddress ( tx only ) |
; |
;*************************************************************************** |
eth_dump: |
pusha |
; Set the port to the desired speed |
mov ebx, 0x3f8 ; combase |
mov edx, ebx |
add edx, 3 ; data format register |
mov al, 0x80 ; enable access to divisor latch |
out dx, al |
mov edx, ebx |
add edx, 1 ; interrupt enable register |
mov al, 0x00 ; No interruts enabled |
out dx, al |
mov edx, ebx |
mov al, 0x20 / 16 ; set baud rate to 57600 0x10 =115200 |
out dx, al |
mov edx, ebx |
add edx, 3 ; data format register |
mov al, 0x03 ; 8 data bits |
out dx, al |
mov edx, ebx |
add edx, 4 ; Modem control register |
mov al, 0x08 ; out2 enabled. No handshaking. |
out dx, al |
mov edx, ebx |
add edx, 1 ; interrupt enable register |
mov al, 0x01 ; Receive data interrupt enabled, |
out dx, al |
popa |
; First, display the type of the buffer. |
; If it is a tx buffer, display the macaddress |
pusha |
cmp eax, 0 |
jne dd001 |
mov bl, 0x0a |
call tx_byted |
mov bl, 0x0d |
call tx_byted |
; Output "RX:" |
mov bl, 'R' |
call tx_byted |
mov bl, 'X' |
call tx_byted |
mov bl, ':' |
call tx_byted |
jmp dump_data |
dd001: |
mov bl, 0x0a |
call tx_byted |
mov bl, 0x0d |
call tx_byted |
; Output TX: xxxxxxxxxxxx |
mov bl, 'T' |
call tx_byted |
mov bl, 'X' |
call tx_byted |
mov bl, ':' |
call tx_byted |
mov bl, ' ' |
call tx_byted |
; Display MAC address |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
dump_data: |
popa |
; OK, we come in here with |
; cx == number of byte to send |
; esi == buffer start |
; |
dd_000: |
mov bl, 0x0a |
call tx_byted |
mov bl, 0x0d |
call tx_byted |
mov eax, 16 ; Number of characters on the line |
mov edi, esi ; Save first byte position for later |
push ecx |
dd_001: |
push eax |
; Print a byte, and a space |
xor eax, eax |
mov al, [esi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
xor eax, eax |
mov al, [esi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
mov bl, ' ' |
call tx_byted |
pop eax |
inc esi |
dec ecx |
cmp ecx, 0 |
je dd_0011 ; Print the ASCII format |
dec eax |
cmp eax, 0 |
je dd_002 ; Print the ASCII format |
jmp dd_001 ; Print rest of line |
dd_0011: |
; First, complete the 16 bytes of data, by printing spaces |
dec eax |
cmp eax, 0 |
je dd_002 |
push eax |
mov bl, ' ' |
call tx_byted |
mov bl, ' ' |
call tx_byted |
mov bl, ' ' |
call tx_byted |
pop eax |
jmp dd_0011 |
dd_002: |
pop ecx |
mov esi, edi ; Go back to the start of the line data |
mov eax, 16 |
outLineAscii: |
push eax |
xor eax, eax |
mov al, [esi] |
mov bl, '.' |
cmp al, 0x1F |
jle outAscii |
cmp al, 0x7e |
jge outAscii |
mov bl, al |
outAscii: |
call tx_byted ; byte in bl eax ebx edx destroyed |
pop eax |
dec ecx |
inc esi |
cmp ecx, 0 |
je dd_003 |
dec eax |
cmp eax, 0 |
je dd_003 |
jmp outLineAscii |
dd_003: |
cmp ecx, 0 |
je dd_004 |
jmp dd_000 |
dd_004: |
ret |
;*************************************************************************** |
; Function |
; tx_byte |
; |
; Description |
; Send a byte in bl out of the com port 1 |
; destroys eax, edx |
; |
;*************************************************************************** |
tx_byted: |
push ebx ; Save the byte |
mov ebx, 0x3f8 ; get the com port address |
; Wait for transmit buffer to empty. This could take 1ms @ 9600baud |
mov edx, ebx |
add edx, 5 |
wait_txd: |
in al, dx ; read uart serialisation status |
and al, 0x40 |
cmp al, 0 |
jz wait_txd ; loop until free |
mov edx, ebx |
pop eax ; restore the byte to send |
out dx, al |
ret |
iglobal |
; This is used for translating hex to ASCII for display or output |
hexchars db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' |
endg |
end if |
/kernel/trunk/network/eth_drv/i8255x.inc |
---|
0,0 → 1,739 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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 ;; |
;; ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************** |
; 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_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; No inputs |
; All registers destroyed |
; |
;*************************************************************************** |
I8255x_reset: |
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: |
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 |
mov [rxfd_link], eax |
mov eax, Ether_buffer |
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 |
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 |
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 |
mov [confcmd_link], eax |
mov ax, 1 |
mov [txfd_command], ax ; CmdIASetup |
mov ax, 0 |
mov [txfd_status], ax |
mov eax, confcmd |
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 |
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_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 |
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 |
mov [txfd_tx_desc_addr], eax |
mov eax, hdr |
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 |
mov [txfd_tx_buf_addr1], eax |
mov eax, ecx |
mov [txfd_tx_buf_size1], eax |
mov eax, txfd |
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 |
/kernel/trunk/network/eth_drv/pcnet32.inc |
---|
0,0 → 1,814 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; PCNET32.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 1.0 31 July 2004 ;; |
;; ;; |
;; 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;macro PutStr X |
;{ |
; local .__xyz1 |
; local .__xyz2 |
; push esi |
; mov esi,.__xyz1 |
; call sys_msg_board_str |
; push eax |
; mov eax,1 |
; call delay_hs |
; pop eax |
; jmp .__xyz2 |
;.__xyz1: |
; db X |
; db 13,10,0 |
;.__xyz2: |
; pop esi |
;} |
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 |
.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 dword [pcnet32_private.rx_ring],pcnet32_rx_ring |
mov dword [pcnet32_private.tx_ring],pcnet32_tx_ring |
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 |
; PutStr "ASEL, enable auto-negotiation" |
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 |
and eax,0xffff |
call dword [pcnet32_access.write_csr] |
mov eax,pcnet32_private |
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: |
; PutStr "hardware reset" |
xor ebx,ebx |
mov eax,0x0002 |
call dword [pcnet32_access.write_csr] |
xor ebx,ebx |
call dword [pcnet32_access.read_csr] |
; PutStr "PCNET reset complete" |
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 |
; PutStr "Using WIO" |
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 |
; PutStr "Using DWIO" |
mov esi,pcnet32_dwio |
jmp .L1 |
.no_dev: |
; PutStr "PCNET32 not found" |
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 |
; PutStr "PCNET32 chip version OK" |
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 |
; PutStr "Invalid chip rev" |
jmp .no_dev |
.L2: |
; PutStr "PCnet/PCI 79C970" |
jmp .L10 |
.L3: |
; PutStr "PCnet/PCI 79C970" |
jmp .L10 |
.L4: |
; PutStr "PCnet/PCI II 79C970A" |
mov [pcnet32_private.fdx],1 |
jmp .L10 |
.L5: |
; PutStr "PCnet/FAST 79C971" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
mov [pcnet32_private.fset],1 |
mov [pcnet32_private.ltint],1 |
jmp .L10 |
.L6: |
; PutStr "PCnet/FAST+ 79C972" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
mov [pcnet32_private.fset],1 |
jmp .L10 |
.L7: |
; PutStr "PCnet/FAST III 79C973" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
jmp .L10 |
.L8: |
; PutStr "PCnet/Home 79C978" |
mov [pcnet32_private.fdx],1 |
mov ebx,49 |
call dword [pcnet32_access.read_bcr] |
call dword [pcnet32_access.write_bcr] |
jmp .L10 |
.L9: |
; PutStr "PCnet/FAST III 79C975" |
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 |
; PutStr "MAC read" |
call pcnet32_adjust_pci_device |
; PutStr "PCI done" |
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 dword [pcnet32_private.rx_ring],pcnet32_rx_ring |
mov dword [pcnet32_private.tx_ring],pcnet32_tx_ring |
; PutStr "Switching to 32" |
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 eax,eax |
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 |
; PutStr "PCNETRX" |
mov ecx,[ebx+pcnet32_rx_head.msg_length] |
and ecx,0xfff |
sub ecx,4 |
mov [eth_rx_data_len],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 |
; PutStr "PCNETTX" |
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 |
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: |
; PutStr "PCNET: Send timeout" |
.L3: |
mov dword [edi+pcnet32_tx_head.base],0 |
pop ecx |
pop ebx |
pop esi |
pop edi |
ret |
/kernel/trunk/network/eth_drv/rtl8029.inc |
---|
0,0 → 1,955 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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! ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************** |
; 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 |
/kernel/trunk/network/eth_drv/rtl8139.inc |
---|
0,0 → 1,595 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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 ;; |
;; ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
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 ax, RTL8139_RX_CONFIG |
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND |
out dx, ax |
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144 |
mov ax, (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, ax |
; 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 |
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 |
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 |
test ax, 0x1fff ; or no size given |
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 |
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 |
/kernel/trunk/network/eth_drv/sis900.inc |
---|
0,0 → 1,1148 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************** |
; 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 ;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 ; 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 ; |
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 ; |
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 |
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], ebx |
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 |
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 |
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 |
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 |
/kernel/trunk/network/ip.inc |
---|
0,0 → 1,202 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************* |
; Interface |
; |
; ip_rx processes all packets received by the network layer |
; It calls the appropriate protocol handler |
; |
; |
; |
;******************************************************************* |
;*************************************************************************** |
; Function |
; ip_rx |
; |
; Description |
; Handles received IP packets |
; This is a kernel function, called by stack_handler |
; |
;*************************************************************************** |
ip_rx: |
; Look for a buffer to tx |
mov eax, IPIN_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je ipr_exit ; Exit if no buffer available |
push eax |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov edx, eax ; Save the address in edx for use by future processes |
; Validate the IP checksum |
mov ebx, edx |
mov ah, [ebx + 10] |
mov al, [ebx + 11] ; Get the checksum in intel format |
mov [ebx + 10], word 0 ; clear checksum field - need to when |
; recalculating checksum |
; this needs two data pointers and two size #. |
; 2nd pointer can be of length 0 |
mov ebx, edx |
mov [checkAdd1], ebx |
mov [checkSize1], word 20 |
mov [checkAdd2], dword 0 |
mov [checkSize2], word 0 |
call checksum ; Recalculate IP checksum |
cmp ax, [checkResult] |
jnz ipr_dump |
; If the IP address is 255.255.255.255, accept it |
; - it is a broadcast packet, which we need for dhcp |
mov eax, [edx + 16] |
cmp eax, 0xffffffff |
je ipr_p0 |
; Validate the IP address, if it isn't broadcast |
cmp eax, [stack_ip] |
jnz ipr_dump |
ipr_p0: |
mov al, [edx] |
and al, 0x0f |
cmp al, 0x05 |
jnz ipr_dump |
cmp [edx+8], byte 0 |
jz ipr_dump |
mov ax, [edx + 6] |
and ax, 0xFFBF |
cmp ax, 0 |
jnz ipr_dump |
; Check the protocol, and call the appropriate handler |
; Each handler will re-use or free the queue buffer as appropriate |
mov al, [edx + 9] |
cmp al , PROTOCOL_ICMP |
jnz ipr_p1 |
pop eax |
call icmp_rx |
jmp ipr_exit |
ipr_p1: |
cmp al , PROTOCOL_TCP |
jnz ipr_p2 |
pop eax |
call tcp_rx |
jmp ipr_exit |
ipr_p2: |
cmp al , PROTOCOL_UDP |
jnz ipr_dump |
pop eax |
call udp_rx |
jmp ipr_exit |
ipr_dump: |
; No protocol handler available, so |
; silently dump the packet, freeing up the queue buffer |
; inc dword [dumped_rx_count] |
pop eax |
call freeBuff |
ipr_exit: |
ret |
;*************************************************************************** |
; Function |
; icmp_rx |
; |
; Description |
; ICMP protocol handler |
; This is a kernel function, called by ip_rx |
; edx contains the address of the buffer in use. |
; This buffer must be reused or marked as empty afterwards |
; |
;*************************************************************************** |
icmp_rx: |
cmp [edx + 20], byte 8 ; Is this an echo request? discard if not |
jz icmp_echo |
call freeBuff |
jmp icmp_exit |
icmp_echo: |
push eax |
mov [edx + 10], word 0 ; I think this was already done by IP rx |
; swap the source and destination addresses |
mov ecx, [edx + 16] |
mov eax, [edx + 12] |
mov [edx + 16], eax |
mov [edx + 12], ecx |
; recaluculate the IP header checksum |
mov ebx, edx |
mov [checkAdd1], ebx |
mov [checkSize1], word 20 |
mov [checkAdd2], dword 0 |
mov [checkSize2], word 0 |
call checksum |
mov ax, [checkResult] |
mov [edx + 10], ah |
mov [edx + 11], al ; ?? correct byte order? |
mov [edx + 20], byte 0 ; change the request to a response |
mov [edx + 22], word 0 ; clear ICMP checksum prior to re-calc |
; Calculate the length of the ICMP data ( IP payload) |
mov ah, [edx + 2] |
mov al, [edx + 3] |
sub ax, 20 |
mov [checkSize1], ax |
mov ebx, edx |
add ebx, 20 |
mov [checkAdd1], ebx |
mov [checkAdd2], dword 0 |
mov [checkSize2], word 0 |
call checksum |
mov ax, [checkResult] |
mov [edx + 22], ah |
mov [edx + 23], al |
; Queue packet for transmission |
pop ebx |
mov eax, NET1OUT_QUEUE |
call queue |
icmp_exit: |
ret |
/kernel/trunk/network/queue.inc |
---|
0,0 → 1,214 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; QUEUE.INC ;; |
;; ;; |
;; Buffer queue management for Menuet OS TCP/IP Stack ;; |
;; ;; |
;; Version 0.3 29 August 2002 ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************* |
; 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 |
;*************************************************************************** |
freeBuff: |
push ebx |
push ecx |
mov ebx, EMPTY_QUEUE |
shl ebx, 1 |
add ebx, queues |
cli ; Ensure that another process does not interfer |
movzx ecx, word [ebx] |
mov [ebx], ax |
shl eax, 1 |
add eax, queueList |
mov [eax], 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 |
;*************************************************************************** |
queue: |
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 |
; |
;*************************************************************************** |
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 |
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 |
/kernel/trunk/network/stack.inc |
---|
0,0 → 1,1784 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; STACK.INC ;; |
;; ;; |
;; TCP/IP stack for Menuet OS ;; |
;; ;; |
;; Version 0.7 4th July 2004 ;; |
;; ;; |
;; 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 ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************* |
; Interface |
; The interfaces defined in ETHERNET.INC plus: |
; stack_init |
; stack_handler |
; app_stack_handler |
; app_socket_handler |
; checksum |
; |
;******************************************************************* |
; |
; IP Packet after reception - Normal IP packet format |
; |
; 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 |
; |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
;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 | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Data | |
; +-+-+-.......... -+ |
; 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 |
; |
; 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 | |
; +-+-+-.......... -+ |
; |
; |
; Socket Descriptor + Buffer |
; |
; 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 |
; |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Status ( of this buffer ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Application Process ID | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Local IP Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Local IP Port | Unused ( set to 0 ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Remote IP Address | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; | Remote IP Port | Unused ( set to 0 ) | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 24| Rx Data Count INTEL format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 28| TCB STATE INTEL format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 32| TCB Timer (seconds) INTEL format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 36| ISS (Inital Sequence # used by this connection ) INET format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 40| IRS ( Inital Receive Sequence # ) INET format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 44| SND.UNA Seq # of unack'ed sent packets INET format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 48| SND.NXT Next send seq # to use INET format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 52| SND.WND Send window INET format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 56| RCV.NXT Next expected receive sequence # INET format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 60| RCV.WND Receive window INET format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 64| SEG.LEN Segment length INTEL format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 68| SEG.WND Segment window INTEL format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 72| Retransmit queue # NOW WINDOW SIZE TIMER INTEL format| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 76| RX Data | |
; +-+-+-.......... -+ |
; IP protocol numbers |
PROTOCOL_ICMP equ 1 |
PROTOCOL_TCP equ 6 |
PROTOCOL_UDP equ 17 |
; TIPBUFF 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 |
SOCK_EMPTY equ 0 ; socket not in use |
SOCK_OPEN equ 1 ; open issued, but no data sent |
; TCP opening modes |
SOCKET_PASSIVE equ 0 |
SOCKET_ACTIVE equ 1 |
; 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_TIME_WAIT equ 10 |
TCB_CLOSED equ 11 |
TWOMSL equ 10 ; # of secs to wait before closing socket |
; socket buffers |
SOCKETBUFFSIZE equ 4096 ; state + config + buffer. |
SOCKETHEADERSIZE equ 76 ; thus 4096 - SOCKETHEADERSIZE bytes data |
NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 |
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 |
TCP_RETRIES equ 5 ; Number of times to resend a packet |
TCP_TIMEOUT equ 10 ; resend if not replied to in x hs |
; 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 |
slip_active equ stack_data + 8 ; no longer used |
; 1 byte. 0 == inactive, 1 = active |
ethernet_active equ stack_data + 9 |
unused equ stack_data + 10 |
; word. Buffer number, -1 if none |
rx_buff_ptr equ stack_data + 12 |
; dword. Buffer number, -1 if none |
tx_buff_ptr equ stack_data + 16 |
; byte. |
slip_rx_state equ stack_data + 20 ; no longer used |
; byte |
slip_tx_state equ stack_data + 21 ; no longer used |
; dword. Index into data |
rx_data_ptr equ stack_data + 22 |
; dword. Index into data |
tx_data_ptr equ stack_data + 26 |
; word. Count of bytes to send |
tx_msg_len equ stack_data + 30 |
; 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 sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) |
; 1560 byte buffer for rx / tx ethernet packets |
Ether_buffer equ Next_free2 |
Next_free3 equ Ether_buffer + 1560 |
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 |
;*************************************************************************** |
; 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: |
xor eax,eax |
mov edi,stack_data_start |
mov ecx,0x20000 / 4 ; Assume that we have 128KB of data |
cld |
rep stosd |
; Initialise TCP resend queue data structures |
mov eax, 0xFFFFFFFF |
mov edi, resendQ |
mov ecx, NUMRESENDENTRIES ; 1 dword per entry |
cld |
rep stosd |
mov eax, 0xFFFFFFFF |
mov [rx_buff_ptr], eax |
mov [tx_buff_ptr], eax |
; Put in some defaults : slip, 0x3f8, 4, ip=192.168.1.22 |
; Saves me entering them each boot up when debugging |
mov eax, 0x03f80401 |
mov [stack_config], eax |
mov eax, 0xc801a8c0 |
mov [stack_ip], eax |
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 |
; |
;*************************************************************************** |
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 |
call arp_timer |
call tcp_tcb_handler |
sh_exit: |
ret |
;*************************************************************************** |
; Function |
; is_localport_unused |
; |
; Description |
; scans through all the active sockets , looking to see if the |
; port number specified in bx is in use as a localport number. |
; This is useful when you want a to generate a unique local port |
; number. |
; On return, eax = 1 for free, 0 for in use |
; |
;*************************************************************************** |
is_localport_unused: |
mov al, bh |
mov ah, bl |
mov bx, ax |
mov edx, SOCKETBUFFSIZE * NUM_SOCKETS |
mov ecx, NUM_SOCKETS |
mov eax, 0 ; Assume the return value is 'in use' |
ilu1: |
sub edx, SOCKETBUFFSIZE |
cmp [edx + sockets + 12], bx |
loopnz ilu1 ; Return back if the socket is occupied |
jz ilu_exit |
inc eax ; return port not in use |
ilu_exit: |
ret |
;*************************************************************************** |
; Function |
; get_free_socket |
; |
; Description |
; |
;*************************************************************************** |
get_free_socket: |
push ecx |
mov eax, SOCKETBUFFSIZE * NUM_SOCKETS |
mov ecx, NUM_SOCKETS |
gfs1: |
sub eax, SOCKETBUFFSIZE |
cmp [eax + sockets], dword SOCK_EMPTY |
loopnz gfs1 ; Return back if the socket is occupied |
mov eax, ecx |
pop ecx |
jz gfs_exit |
mov eax, 0xFFFFFFFF |
gfs_exit: |
ret |
;*************************************************************************** |
; 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 |
xor edx, edx ; edx is the accumulative checksum |
xor ebx, ebx |
mov cx, [checkSize1] |
shr cx, 1 |
jz cs1_1 |
mov eax, [checkAdd1] |
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 |
shr cx, 1 |
jz cs2_1 |
mov eax, [checkAdd2] |
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 fn 52 |
; It provides application access to the network interface layer |
; |
;*************************************************************************** |
app_stack_handler: |
cmp eax, 0 |
jnz not0 |
; Read the configuartion word |
mov eax, [stack_config] |
ret |
not0: |
cmp eax, 1 |
jnz not1 |
; read the IP address |
mov eax, [stack_ip] |
ret |
not1: |
cmp eax, 2 |
jnz not2 |
; write the configuration word |
mov [stack_config], ebx |
; <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 bl, 0x7f |
cmp bl, 3 |
je ash_eth_enable |
; Ethernet isn't enabled, so make sure that the card is disabled |
mov [ethernet_active], byte 0 |
ret |
ash_eth_enable: |
; Probe for the card. This will reset it and enable the interface |
; if found |
call eth_probe |
cmp eax, 0 |
je ash_eth_done ; Abort if no hardware found |
mov [ethernet_active], byte 1 |
ash_eth_done: |
ret |
not2: |
cmp eax, 3 |
jnz not3 |
; write the IP Address |
mov [stack_ip], ebx |
ret |
not3: |
cmp eax, 4 |
jnz not4 |
; Enabled the slip driver on the comm port |
; slip removed |
ret |
not4: |
cmp eax, 5 |
jnz not5 |
; Disable the slip driver on the comm port |
; slip removed |
not5: |
cmp eax, 6 |
jnz not6 |
; Insert an IP packet into the stacks received packet queue |
call stack_insert_packet |
ret |
not6: |
cmp eax, 7 |
jnz not7 |
; Test for any packets queued for transmission over the network |
not7: |
cmp eax, 8 |
jnz not8 |
call stack_get_packet |
; Extract a packet queued for transmission by the network |
ret |
not8: |
cmp eax, 9 |
jnz not9 |
; read the gateway IP address |
mov eax, [gateway_ip] |
ret |
not9: |
cmp eax, 10 |
jnz not10 |
; read the subnet mask |
mov eax, [subnet_mask] |
ret |
not10: |
cmp eax, 11 |
jnz not11 |
; write the gateway IP Address |
mov [gateway_ip], ebx |
ret |
not11: |
cmp eax, 12 |
jnz not12 |
; write the subnet mask |
mov [subnet_mask], ebx |
not12: |
cmp eax, 13 |
jnz not13 |
; read the dns |
mov eax, [dns_ip] |
ret |
not13: |
cmp eax, 14 |
jnz stack_driver_end |
; write the dns IP Address |
mov [dns_ip], ebx |
ret |
stack_driver_end: |
ret |
;*************************************************************************** |
; Function |
; app_socket_handler |
; |
; Description |
; This is an application service, called by int 0x40 |
; It provides application access to stack socket services |
; such as opening sockets |
; |
;*************************************************************************** |
app_socket_handler: |
cmp eax, 0 |
jnz nots0 |
call socket_open |
ret |
nots0: |
cmp eax, 1 |
jnz nots1 |
call socket_close |
ret |
nots1: |
cmp eax, 2 |
jnz nots2 |
call socket_poll |
ret |
nots2: |
cmp eax, 3 |
jnz nots3 |
call socket_read |
ret |
nots3: |
cmp eax, 4 |
jnz nots4 |
call socket_write |
ret |
nots4: |
cmp eax, 5 |
jnz nots5 |
call socket_open_tcp |
ret |
nots5: |
cmp eax, 6 |
jnz nots6 |
call socket_status |
ret |
nots6: |
cmp eax, 7 |
jnz nots7 |
call socket_write_tcp |
ret |
nots7: |
cmp eax, 8 |
jnz nots8 |
call socket_close_tcp |
ret |
nots8: |
cmp eax, 9 |
jnz nots9 |
call is_localport_unused |
ret |
nots9: |
cmp eax, 254 |
jnz notdump |
ret |
notdump: |
cmp eax, 255 |
jnz notsdebug |
; This sub function allows access to debugging information on the stack |
; ebx 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 ) |
call stack_internal_status |
ret |
notsdebug: |
; Invalid Option |
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 |
; |
;*************************************************************************** |
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,[0x3010] |
add edi,0x10 |
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,[0x3010] |
add edi,0x10 |
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 |
;*************************************************************************** |
; Function |
; socket_open |
; |
; Description |
; find a free socket |
; local port in ebx |
; remote port in ecx |
; remote ip in edx |
; return socket # in eax, -1 if none available |
; |
;*************************************************************************** |
socket_open: |
call get_free_socket |
cmp eax, 0xFFFFFFFF |
jz so_exit |
; ax holds the socket number that is free. Get real address |
push eax |
shl eax, 12 |
add eax, sockets |
mov [eax], dword SOCK_OPEN |
mov [eax + 12], byte bh ; Local port ( LS 16 bits ) |
mov [eax + 13], byte bl ; Local port ( LS 16 bits ) |
mov ebx, [stack_ip] |
mov [eax + 8], ebx ; Local IP |
mov [eax + 20], ch ; Remote Port ( LS 16 bits ) |
mov [eax + 21], cl ; Remote Port ( LS 16 bits ) |
mov [eax + 16], edx ; Remote IP ( in Internet order ) |
mov [eax + 24], dword 0 ; recieved data count |
mov esi, [0x3010] |
mov ebx, [esi+0x4] |
mov [eax + 4], ebx ; save the process ID |
pop eax ; Get the socket number back, so we can return it |
so_exit: |
ret |
;*************************************************************************** |
; Function |
; socket_open_tcp |
; |
; Description |
; Opens a TCP socket in PASSIVE or ACTIVE mode |
; find a free socket |
; local port in ebx ( intel format ) |
; remote port in ecx ( intel format ) |
; remote ip in edx ( in Internet byte order ) |
; Socket open mode in esi ( SOCKET_PASSIVE or SOCKET_ACTIVE ) |
; return socket # in eax, -1 if none available |
; |
;*************************************************************************** |
socket_open_tcp: |
call get_free_socket |
cmp eax, 0xFFFFFFFF |
jz so_exit |
; ax holds the socket number that is free. Get real address |
push eax |
shl eax, 12 |
add eax, sockets |
mov [sktAddr], eax |
mov [eax], dword SOCK_OPEN |
; TODO - check this works! |
mov [eax + 72], dword 0 ; Reset the window timer. |
mov [eax + 12], byte bh ; Local port ( LS 16 bits ) |
mov [eax + 13], byte bl ; Local port ( LS 16 bits ) |
mov ebx, [stack_ip] |
mov [eax + 8], ebx ; Local IP |
mov [eax + 20], ch ; Remote Port ( LS 16 bits ) |
mov [eax + 21], cl ; Remote Port ( LS 16 bits ) |
mov [eax + 16], edx ; Remote IP ( in Internet order ) |
mov [eax + 24], dword 0 ; recieved data count |
; Now fill in TCB state |
mov ebx, TCB_LISTEN |
cmp esi, SOCKET_PASSIVE |
jz sot_001 |
mov ebx, TCB_SYN_SENT |
sot_001: |
mov [eax + 28], ebx ; Indicate the state of the TCB |
mov esi, [0x3010] |
mov ecx, [esi+0x4] |
mov [eax + 4], ecx ; save the process ID |
cmp ebx, TCB_LISTEN |
je sot_done |
; 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 sot_done |
push eax |
mov bl, 0x02 ; SYN |
mov ecx, 0 |
call buildTCPPacket |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [ sktAddr ] |
mov ecx, [ ecx + 16 ] |
cmp edx, ecx |
jne sot_notlocal |
mov eax, IPIN_QUEUE |
sot_notlocal: |
; Send it. |
pop ebx |
call queue |
mov esi, [sktAddr] |
; increment SND.NXT in socket |
add esi, 48 |
call inc_inet_esi |
sot_done: |
pop eax ; Get the socket number back, so we can return it |
sot_exit: |
ret |
;*************************************************************************** |
; Function |
; socket_close |
; |
; Description |
; socket # in ebx |
; returns 0 for ok, -1 for socket not open (fail) |
; |
;*************************************************************************** |
socket_close: |
shl ebx, 12 |
add ebx, sockets |
mov eax, 0xFFFFFFFF ; assume this operation will fail.. |
cmp [ebx], dword SOCK_EMPTY |
jz sc_exit |
; Clear the socket varaibles |
xor eax, eax |
mov edi,ebx |
mov ecx,SOCKETHEADERSIZE |
cld |
rep stosb |
sc_exit: |
ret |
;*************************************************************************** |
; Function |
; socket_close_tcp |
; |
; Description |
; socket # in ebx |
; returns 0 for ok, -1 for socket not open (fail) |
; |
;*************************************************************************** |
socket_close_tcp: |
; first, remove any resend entries |
pusha |
mov esi, resendQ |
mov ecx, 0 |
sct001: |
cmp ecx, NUMRESENDENTRIES |
je sct003 ; None left |
cmp [esi], bl |
je sct002 ; found one |
inc ecx |
add esi, 4 |
jmp sct001 |
sct002: |
dec dword [arp_rx_count] ; ************ TEST ONLY! |
mov [esi], byte 0xFF |
jmp sct001 |
sct003: |
popa |
shl ebx, 12 |
add ebx, sockets |
mov [sktAddr], ebx |
mov eax, 0xFFFFFFFF ; assume this operation will fail.. |
cmp [ebx], dword SOCK_EMPTY |
jz sct_exit |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je stl_exit |
push eax |
mov bl, 0x11 ; FIN + ACK |
mov ecx, 0 |
mov esi, 0 |
call buildTCPPacket |
mov ebx, [sktAddr] |
; increament SND.NXT in socket |
mov esi, 48 |
add esi, ebx |
call inc_inet_esi |
; Get the socket state |
mov eax, [ebx + 28] |
cmp eax, TCB_LISTEN |
je destroyTCB |
cmp eax, TCB_SYN_SENT |
je destroyTCB |
cmp eax, TCB_SYN_RECEIVED |
je sct_finwait1 |
cmp eax, TCB_ESTABLISHED |
je sct_finwait1 |
; assume CLOSE WAIT |
; Send a fin, then enter last-ack state |
mov eax, TCB_LAST_ACK |
mov [ebx + 28], eax |
xor eax, eax |
jmp sct_send |
sct_finwait1: |
; Send a fin, then enter finwait2 state |
mov eax, TCB_FIN_WAIT_1 |
mov [ebx + 28], eax |
xor eax, eax |
sct_send: |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [ sktAddr ] |
mov ecx, [ ecx + 16 ] |
cmp edx, ecx |
jne sct_notlocal |
mov eax, IPIN_QUEUE |
sct_notlocal: |
; Send it. |
pop ebx |
call queue |
jmp sct_exit |
destroyTCB: |
pop eax |
; Clear the socket varaibles |
xor eax, eax |
mov edi,ebx |
mov ecx,SOCKETHEADERSIZE |
cld |
rep stosb |
sct_exit: |
ret |
;*************************************************************************** |
; Function |
; socket_poll |
; |
; Description |
; socket # in ebx |
; returns count in eax. |
; |
;*************************************************************************** |
socket_poll: |
shl ebx, 12 |
add ebx, sockets |
mov eax, [ebx + 24] |
ret |
;*************************************************************************** |
; Function |
; socket_status |
; |
; Description |
; socket # in ebx |
; returns TCB state in eax. |
; |
;*************************************************************************** |
socket_status: |
shl ebx, 12 |
add ebx, sockets |
mov eax, [ebx + 28] |
ret |
;*************************************************************************** |
; Function |
; socket_read |
; |
; Description |
; socket # in ebx |
; returns # of bytes remaining in eax, data in bl |
; |
;*************************************************************************** |
socket_read: |
shl ebx, 12 |
add ebx, sockets |
mov eax, [ebx + 24] ; get count of bytes |
mov ecx,1 |
test eax, eax |
jz sr2 |
dec eax |
mov esi, ebx ; esi is address of socket |
mov [ebx + 24], eax ; store new count |
movzx ebx, byte [ebx + SOCKETHEADERSIZE] ; get the byte |
add esi, SOCKETHEADERSIZE |
mov edi, esi |
inc esi |
mov ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4 |
cld |
rep movsd |
xor ecx, ecx |
sr1: |
jmp sor_exit |
sr2: |
xor bl, bl |
sor_exit: |
ret |
;*************************************************************************** |
; Function |
; socket_write |
; |
; Description |
; socket in ebx |
; # of bytes to write in ecx |
; pointer to data in edx |
; returns 0 in eax ok, -1 == failed ( invalid socket, or |
; could not queue IP packet ) |
; |
;*************************************************************************** |
socket_write: |
; First, find the address of the socket descriptor |
shl ebx, 12 |
add ebx, sockets ; ebx = address of actual socket |
mov eax, 0xFFFFFFFF |
; If the socket is invalid, return with an error code |
cmp [ebx], dword SOCK_EMPTY |
je sw_exit |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je sw_exit |
; 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 + 8] |
mov [edx + 12], eax ; source IP |
mov eax, [ebx + 16] |
mov [edx + 16], eax ; Destination IP |
mov al, 0x45 |
mov [edx], al ; Version, IHL |
xor al, al |
mov [edx + 1], al ; Type of service |
pop eax ; Get the UDP data length |
push eax |
add eax, 20 + 8 ; add IP header and UDP header lengths |
mov [edx + 2], ah |
mov [edx + 3], al |
xor al, al |
mov [edx + 4], al |
mov [edx + 5], al |
mov al, 0x40 |
mov [edx + 6], al |
xor al, al |
mov [edx + 7], al |
mov al, 0x20 |
mov [edx + 8], al |
mov al, 17 |
mov [edx + 9], al |
; Checksum left unfilled |
xor ax, ax |
mov [edx + 10], ax |
; Fill in the UDP header ( some data is in the socket descriptor) |
mov ax, [ebx + 12] |
mov [edx + 20], ax |
mov ax, [ebx + 20] |
mov [edx + 20 + 2], ax |
pop eax |
push eax |
add eax, 8 |
mov [edx + 20 + 4], ah |
mov [edx + 20 + 5], al |
; Checksum left unfilled |
xor ax, ax |
mov [edx + 20 + 6], 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,[0x3010] |
add edi,0x10 |
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 + 12] |
mov [pseudoHeader], eax |
mov eax, [edx + 16] |
mov [pseudoHeader+4], eax |
mov ax, 0x1100 ; 0 + protocol |
mov [pseudoHeader+8], ax |
add ebx, 8 |
mov eax, ebx |
mov [pseudoHeader+10], ah |
mov [pseudoHeader+11], al |
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') |
cmp ax, 0 |
jne sw_001 |
mov ax, 0xffff |
sw_001: |
mov [edx + 20 + 6], ah |
mov [edx + 20 + 7], al |
; Fill in the IP header checksum |
mov eax, edx |
mov [checkAdd1], eax |
mov [checkSize1], word 20 |
mov [checkAdd2], dword 0 |
mov [checkSize2], word 0 |
call checksum |
mov ax, [checkResult] |
mov [edx + 10], ah |
mov [edx + 11], al |
; 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 + 16] |
mov edx, [stack_ip] |
cmp edx, ecx |
jne sw_notlocal |
mov eax, IPIN_QUEUE |
sw_notlocal: |
; Send it. |
call queue |
xor eax, eax |
sw_exit: |
ret |
;*************************************************************************** |
; Function |
; socket_write_tcp |
; |
; Description |
; socket in ebx |
; # of bytes to write in ecx |
; pointer to data in edx |
; returns 0 in eax ok, -1 == failed ( invalid socket, or |
; could not queue IP packet ) |
; |
;*************************************************************************** |
socket_write_tcp: |
; First, find the address of the socket descriptor |
shl ebx, 12 |
add ebx, sockets ; ebx = address of actual socket |
mov [sktAddr], ebx |
mov eax, 0xFFFFFFFF |
; If the socket is invalid, return with an error code |
cmp [ebx], dword SOCK_EMPTY |
je swt_exit |
; If the sockets window timer is nonzero, do not queue packet |
; TODO - done |
cmp [ebx + 72], dword 0 |
jne swt_exit |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je swt_exit |
push eax |
mov bl, 0x10 ; ACK |
; Get the address of the callers data |
mov edi,[0x3010] |
add edi,0x10 |
add edx,[edi] |
mov esi, edx |
pop eax |
push eax |
push ecx |
call buildTCPPacket |
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, [ sktAddr ] |
mov ecx, [ ecx + 16 ] |
cmp edx, ecx |
jne swt_notlocal |
mov eax, IPIN_QUEUE |
swt_notlocal: |
pop ecx |
push ebx ; save ipbuffer number |
call queue |
mov esi, [sktAddr] |
; increament SND.NXT in socket |
; Amount to increment by is in ecx |
add esi, 48 |
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 |
swt003: |
cmp ecx, NUMRESENDENTRIES |
je swt001 ; None found |
cmp [esi], byte 0xFF |
je swt002 ; found one |
inc ecx |
add esi, 4 |
jmp swt003 |
swt002: |
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 |
mov eax, [sktAddr] |
sub eax, sockets |
shr eax, 12 ; get skt # |
mov [esi], al |
mov [esi + 1], byte TCP_RETRIES |
mov [esi + 2], word TCP_TIMEOUT |
inc ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
mov edi, resendBuffer - IPBUFFSIZE |
swt002a: |
add edi, IPBUFFSIZE |
loop swt002a |
; 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 |
inc dword [arp_rx_count] ; ************ TEST ONLY! |
swt001: |
xor eax, eax |
swt_exit: |
ret |
; Below, the main network layer source code is included |
; |
include "queue.inc" |
include "ip.inc" |
include "tcp.inc" |
include "udp.inc" |
include "eth_drv/ethernet.inc" |
/kernel/trunk/network/tcp.inc |
---|
0,0 → 1,1243 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; TCP.INC ;; |
;; ;; |
;; TCP Processes for Menuet OS TCP/IP stack ;; |
;; ;; |
;; Version 0.6 4th July 2004 ;; |
;; ;; |
;; 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 ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************* |
; 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 |
; |
;******************************************************************* |
;*************************************************************************** |
; Function |
; tcp_tcb_handler |
; |
; Description |
; Handles sockets in the timewait state, closing them |
; when the TCB timer expires |
; |
;*************************************************************************** |
tcp_tcb_handler: |
; scan through all the sockets, decrementing active timers |
mov eax, SOCKETBUFFSIZE * NUM_SOCKETS |
mov ecx, NUM_SOCKETS |
tth1: |
sub eax, SOCKETBUFFSIZE |
cmp [eax + sockets + 32], dword 0 |
jne tth2 |
tth1a: |
cmp [eax + sockets + 72], dword 0 |
jne tth4 |
loop tth1 |
ret |
tth2: |
; decrement it, delete socket if TCB timer = 0 & socket in timewait state |
pusha |
dec dword [eax + sockets + 32] |
cmp [eax + sockets + 32], dword 0 |
jne tth3 |
cmp [eax + sockets + 28], dword TCB_TIME_WAIT |
jne tth3 |
; OK, delete socket |
mov edi, eax |
add edi, sockets |
xor eax, eax |
mov ecx, SOCKETHEADERSIZE |
cld |
rep stosb |
tth3: |
popa |
jmp tth1a |
loop tth1 |
ret |
; TODO - prove it works! |
tth4: |
dec dword [eax + sockets + 72] |
loop tth1 |
ret |
tth_exit: |
ret |
;*************************************************************************** |
; Function |
; tcp_tx_handler |
; |
; Description |
; Handles queued TCP data |
; This is a kernel function, called by stack_handler |
; |
;*************************************************************************** |
tcp_tx_handler: |
; 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 |
tth001: |
cmp ecx, NUMRESENDENTRIES |
je tth003 ; None left |
cmp [esi], byte 0xFF |
jne tth002 ; found one |
inc ecx |
add esi, 4 |
jmp tth001 |
tth002: |
; we have one. decrement it's timer by 1 |
dec word [esi+2] |
mov ax, [esi+2] |
cmp ax, 0 |
je tth002a |
inc ecx |
add esi, 4 |
jmp tth001 ; Timer not zero, so move on |
tth002a: |
mov bl, 0xff |
; 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] |
mov al, [esi+1] |
cmp al, 0 |
jne tth004 |
; retries now 0, so delete from queue |
xchg [esi], bl |
tth004: |
; resend packet |
pusha |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
jne tth004z |
; TODO - try again in 10ms. |
cmp bl, 0xff |
jne tth004za |
mov [esi], bl |
tth004za: |
; Mark it to expire in 10ms - 1 tick |
mov [esi+1], byte 1 |
mov [esi+2], word 1 |
jmp tth005 |
tth004z: |
; we have a buffer # in ax |
push eax |
push ecx |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
; we have the buffer address in eax |
mov edi, eax |
pop ecx |
; get resend data address |
inc ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
mov esi, resendBuffer - IPBUFFSIZE |
tth004a: |
add esi, IPBUFFSIZE |
loop tth004a |
; we have resend buffer location in esi |
mov ecx, IPBUFFSIZE |
; copy data across |
cld |
rep movsb |
; queue packet |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [ edi + 16 ] |
cmp edx, ecx |
jne tth004b |
mov eax, IPIN_QUEUE |
tth004b: |
pop ebx |
call queue |
tth005: |
popa |
inc ecx |
add esi, 4 |
jmp tth001 |
tth003: |
ret |
;*************************************************************************** |
; 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 |
; |
;*************************************************************************** |
tcp_rx: |
; 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 eax, SOCKETBUFFSIZE * NUM_SOCKETS |
mov ecx, NUM_SOCKETS |
ss1: |
sub eax, SOCKETBUFFSIZE |
movzx ebx, word [edx + 22] ; get the dest. port from the TCP hdr |
cmp [eax + sockets + 12], bx ; compare with socket's local port |
jnz nxttst1 ; different - try next socket |
movzx ebx, word [edx + 20] ; get the source port from the TCP hdr |
cmp [eax + sockets + 20], bx ; compare with socket's remote port |
jnz nxttst1 ; different - try next socket |
mov ebx, [edx + 12] ; get the source IP Addr from the IP hdr |
cmp [eax + sockets + 16], ebx ; compare with socket's remote IP |
jnz nxttst1 ; different - try next socket |
; We have a complete match - use this socket |
jmp tcprx_001 |
nxttst1: |
loop ss1 ; Return back if no match |
; 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 eax, SOCKETBUFFSIZE * NUM_SOCKETS |
mov ecx, NUM_SOCKETS |
ss2: |
sub eax, SOCKETBUFFSIZE |
movzx ebx, word [edx + 22] ; get the dest. port from the TCP hdr |
cmp [eax + sockets + 12], bx ; compare with socket's local port |
jnz nxttst2 ; different - try next socket |
mov ebx, [edx + 12] ; get the source IP Addr from the IP hdr |
cmp [eax + sockets + 16], ebx ; compare with socket's remote IP |
jnz nxttst2 ; different - try next socket |
mov ebx, 0 |
cmp [eax + sockets + 20], bx ; only match a remote socket of 0 |
jnz nxttst2 ; different - try next socket |
; We have a complete match - use this socket |
jmp tcprx_001 |
nxttst2: |
loop ss2 ; Return back if no match |
; 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 eax, SOCKETBUFFSIZE * NUM_SOCKETS |
mov ecx, NUM_SOCKETS |
ss3: |
sub eax, SOCKETBUFFSIZE |
movzx ebx, word [edx + 22] ; get destination port from the TCP hdr |
cmp [eax + sockets + 12], bx ; compare with socket's local port |
jnz nxttst3 ; different - try next socket |
mov ebx, 0 |
cmp [eax + sockets + 20], bx ; only match a remote socket of 0 |
jnz nxttst3 ; different - try next socket |
mov ebx, 0 |
cmp [eax + sockets + 16], ebx ; only match a socket remote IP of 0 |
jnz nxttst3 ; different - try next socket |
; We have a complete match - use this socket |
jmp tcprx_001 |
nxttst3: |
loop ss3 ; Return back if no match |
; If we got here, we need to reject the packet |
inc dword [dumped_rx_count] |
jmp tcprx_exit |
tcprx_001: |
; We have a valid socket/TCB, so call the TCB State Machine for that skt. |
; socket is pointed to by [eax + sockets] |
; IP packet is pointed to by [edx] |
; IP buffer number is on stack ( it will be popped at the end) |
call tcpStateMachine |
tcprx_exit: |
pop eax |
call freeBuff |
ret |
;*************************************************************************** |
; 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 |
; |
;*************************************************************************** |
buildTCPPacket: |
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 + 33], bl ; TCP flags |
mov ebx, [sktAddr] |
; 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 + 8] |
mov [edx + 12], eax ; source IP |
mov eax, [ebx + 16] |
mov [edx + 16], eax ; Destination IP |
mov al, 0x45 |
mov [edx], al ; Version, IHL |
xor al, al |
mov [edx + 1], al ; Type of service |
pop eax ; Get the TCP data length |
push eax |
add eax, 20 + 20 ; add IP header and TCP header lengths |
mov [edx + 2], ah |
mov [edx + 3], al |
xor al, al |
mov [edx + 4], al |
mov [edx + 5], al |
mov al, 0x40 |
mov [edx + 6], al |
xor al, al |
mov [edx + 7], al |
mov al, 0x20 |
mov [edx + 8], al |
mov al, 6 ; TCP protocol |
mov [edx + 9], al |
; Checksum left unfilled |
xor ax, ax |
mov [edx + 10], ax |
; Fill in the TCP header ( some data is in the socket descriptor) |
mov ax, [ebx + 12] |
mov [edx + 20], ax ; Local Port |
mov ax, [ebx + 20] |
mov [edx + 20 + 2], ax ; desitination Port |
; Checksum left unfilled |
xor ax, ax |
mov [edx + 20 + 16], ax |
; sequence number |
mov eax, [ebx + 48] |
mov [edx + 20 + 4], eax |
; ack number |
mov eax, [ebx + 56] |
mov [edx + 20 + 8], eax |
; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) |
; 768 bytes seems better |
mov ax, 0x0003 |
mov [edx + 20 + 14], ax |
; Urgent pointer (0) |
mov ax, 0 |
mov [edx + 20 + 18], ax |
; data offset ( 0x50 ) |
mov al, 0x50 |
mov [edx + 20 + 12], al |
pop ecx ; count of bytes to send |
mov ebx, ecx ; need the length later |
cmp ebx, 0 |
jz btp_001 |
mov edi, edx |
add edi, 40 |
cld |
rep movsb ; copy the data across |
btp_001: |
; we have edx as IPbuffer ptr. |
; Fill in the TCP checksum |
; First, fill in pseudoheader |
mov eax, [edx + 12] |
mov [pseudoHeader], eax |
mov eax, [edx + 16] |
mov [pseudoHeader+4], eax |
mov ax, 0x0600 ; 0 + protocol |
mov [pseudoHeader+8], ax |
add ebx, 20 |
mov eax, ebx |
mov [pseudoHeader+10], ah |
mov [pseudoHeader+11], al |
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 |
call checksum |
; store it in the TCP checksum ( in the correct order! ) |
mov ax, [checkResult] |
mov [edx + 20 + 16], ah |
mov [edx + 20 + 17], al |
; Fill in the IP header checksum |
mov eax, edx |
mov [checkAdd1], eax |
mov [checkSize1], word 20 |
mov [checkAdd2], dword 0 |
mov [checkSize2], word 0 |
call checksum |
mov ax, [checkResult] |
mov [edx + 10], ah |
mov [edx + 11], al |
ret |
; Increments the 32 bit value pointed to by esi in internet order |
inc_inet_esi: |
push eax |
add esi, 3 |
mov al, byte[esi] |
inc al |
mov byte[esi], al |
cmp al, 0 |
jnz iie_exit |
dec esi |
mov al, byte[esi] |
inc al |
mov byte[esi], al |
cmp al, 0 |
jnz iie_exit |
dec esi |
mov al, byte[esi] |
inc al |
mov byte[esi], al |
cmp al, 0 |
jnz iie_exit |
dec esi |
mov al, byte[esi] |
inc al |
mov byte[esi], al |
iie_exit: |
pop eax |
ret |
; Increments the 32 bit value pointed to by esi in internet order |
; by the value in ecx |
add_inet_esi: |
push eax |
mov al, [esi] |
shl eax, 8 |
inc esi |
mov al, [esi] |
shl eax, 8 |
inc esi |
mov al, [esi] |
shl eax, 8 |
inc esi |
mov al, [esi] |
add eax, ecx |
mov [esi], al |
dec esi |
shr eax, 8 |
mov [esi], al |
dec esi |
shr eax, 8 |
mov [esi], al |
dec esi |
shr eax, 8 |
mov [esi], al |
pop eax |
ret |
iglobal |
TCBStateHandler: |
dd stateTCB_LISTEN |
dd stateTCB_SYN_SENT |
dd stateTCB_SYN_RECEIVED |
dd stateTCB_ESTABLISHED |
dd stateTCB_FIN_WAIT_1 |
dd stateTCB_FIN_WAIT_2 |
dd stateTCB_CLOSE_WAIT |
dd stateTCB_CLOSING |
dd stateTCB_LAST_ACK |
dd stateTCB_TIME_WAIT |
dd 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 [eax + sockets] |
; |
; The IP buffer will be released by the caller |
;*************************************************************************** |
tcpStateMachine: |
mov ebx, sockets |
add ebx, eax |
mov [sktAddr], ebx |
; as a packet has been received, update the TCB timer |
mov ecx, TWOMSL |
mov [ebx + 32], ecx |
; If the received packet has an ACK bit set, |
; remove any packets in the resend queue that this |
; received packet acknowledges |
pusha |
mov cl, [edx + 33] |
and cl, 0x10 |
cmp cl, 0x10 |
jne tsm001 ; No ACK, so no data yet |
; get skt number in al |
shr eax, 12 |
; The ack number is in [edx + 28], inet format |
; skt in al |
mov esi, resendQ |
mov ecx, 0 |
t001: |
cmp ecx, NUMRESENDENTRIES |
je t003 ; None left |
cmp [esi], al |
je t002 ; found one |
inc ecx |
add esi, 4 |
jmp t001 |
t002: ; Can we delete this buffer? |
; If yes, goto t004. No, goto t001 |
; Get packet data address |
push ecx |
inc ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
mov edi, resendBuffer - IPBUFFSIZE |
t002a: |
add edi, IPBUFFSIZE |
loop t002a |
; we have dest buffer location in edi. incoming packet in edx. |
; Get this packets sequence number |
; preserve al, ecx, esi, edx |
mov cl, [edi + 24] |
shl ecx, 8 |
mov cl, [edi + 25] |
shl ecx, 8 |
mov cl, [edi + 26] |
shl ecx, 8 |
mov cl, [edi + 27] |
movzx ebx, byte [edi + 3] |
mov bh, [edi + 2] |
sub ebx, 40 |
add ecx, ebx ; ecx is now seq# of last byte +1, intel format |
; get recievd ack #, in intel format |
mov bl, [edx + 28] |
shl ebx, 8 |
mov bl, [edx + 29] |
shl ebx, 8 |
mov bl, [edx + 30] |
shl ebx, 8 |
mov bl, [edx + 31] |
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 t004 ; if rx > old, delete old |
inc ecx |
add esi, 4 |
jmp t001 |
t004: |
dec dword [arp_rx_count] ; ************ TEST ONLY! |
mov [esi], byte 0xFF |
inc ecx |
add esi, 4 |
jmp t001 |
t003: |
tsm001: |
popa |
; Call handler for given TCB state |
mov ebx, [eax + sockets+28] |
cmp ebx, TCB_LISTEN |
jb tsm_exit |
cmp ebx, TCB_CLOSED |
ja tsm_exit |
dec ebx |
call dword [TCBStateHandler+ebx*4] |
tsm_exit: |
ret |
stateTCB_LISTEN: |
; 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 |
mov bl, [edx + 33] |
and bl, 0x02 |
cmp bl, 0x02 |
jnz stl_exit |
; We have a SYN. update the socket with this IP packets details, |
; And send a response |
mov ebx, [edx + 12] ; IP source address |
mov [eax + sockets + 16], ebx |
mov bx, [edx + 20] ; IP source port |
mov [eax + sockets + 20], bx |
mov ebx, [edx + 24] ; IRS |
mov [eax + sockets + 40], ebx |
mov [eax + sockets + 56], ebx |
mov esi, sockets |
add esi, eax |
add esi, 56 |
call inc_inet_esi ; RCV.NXT |
mov ebx, [eax + sockets + 36] ; ISS |
mov [eax + sockets + 48], ebx ; SND.NXT |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je stl_exit |
push eax |
mov bl, 0x12 ; SYN + ACK |
mov ecx, 0 |
mov esi, 0 |
call buildTCPPacket |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [ sktAddr ] |
mov ecx, [ ecx + 16 ] |
cmp edx, ecx |
jne stl_notlocal |
mov eax, IPIN_QUEUE |
stl_notlocal: |
; Send it. |
pop ebx |
call queue |
mov ebx, TCB_SYN_RECEIVED |
mov esi, [sktAddr] |
mov [esi + 28], ebx |
; increament SND.NXT in socket |
add esi, 48 |
call inc_inet_esi |
stl_exit: |
ret |
stateTCB_SYN_SENT: |
; We are awaiting an ACK to our SYN, with a SYM |
; Look at control flags - expecting an ACK |
mov bl, [edx + 33] |
and bl, 0x12 |
cmp bl, 0x12 |
jnz stss_exit |
mov ebx, TCB_ESTABLISHED |
mov esi, [sktAddr] |
mov [esi + 28], ebx |
; Store the recv.nxt field |
mov eax, [edx + 24] |
; Update our recv.nxt field |
mov esi, [sktAddr] |
add esi, 56 |
mov [esi], eax |
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 |
je stss_exit |
push eax |
mov bl, 0x10 ; ACK |
mov ecx, 0 |
mov esi, 0 |
call buildTCPPacket |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [ sktAddr ] |
mov ecx, [ ecx + 16 ] |
cmp edx, ecx |
jne stss_notlocal |
mov eax, IPIN_QUEUE |
stss_notlocal: |
; Send it. |
pop ebx |
call queue |
stss_exit: |
ret |
stateTCB_SYN_RECEIVED: |
; In this case, we are expecting an ACK packet |
; For now, if the packet is an ACK, process it, |
; If not, ignore it |
; Look at control flags - expecting an ACK |
mov bl, [edx + 33] |
and bl, 0x10 |
cmp bl, 0x10 |
jnz stsr_exit |
mov ebx, TCB_ESTABLISHED |
mov esi, [sktAddr] |
mov [esi + 28], ebx |
stsr_exit: |
ret |
stateTCB_ESTABLISHED: |
; Here we are expecting data, or a request to close |
; OR both... |
; Did we receive a FIN or RST? |
mov bl, [edx + 33] |
and bl, 0x05 |
cmp bl, 0 |
je ste_chkack |
; It was a fin or reset. |
; Remove resend entries from the queue - I dont want to send any more data |
pusha |
mov ebx, [sktAddr] |
sub ebx, sockets |
shr ebx, 12 ; get skt # |
mov esi, resendQ |
mov ecx, 0 |
ste001: |
cmp ecx, NUMRESENDENTRIES |
je ste003 ; None left |
cmp [esi], bl |
je ste002 ; found one |
inc ecx |
add esi, 4 |
jmp ste001 |
ste002: |
dec dword [arp_rx_count] ; ************ TEST ONLY! |
mov [esi], byte 0xFF |
jmp ste001 |
ste003: |
popa |
; was it a reset? |
mov bl, [edx + 33] |
and bl, 0x04 |
cmp bl, 0x04 |
jne ste003a |
mov esi, [sktAddr] |
mov ebx, TCB_CLOSED |
mov [esi + 28], ebx |
jmp ste_exit |
ste003a: |
; Send an ACK to that fin, and enter closewait state |
mov esi, [sktAddr] |
mov ebx, TCB_CLOSE_WAIT |
mov [esi + 28], ebx |
add esi, 56 |
mov eax, [esi] ; save original |
call inc_inet_esi |
;; jmp ste_ack - NO, there may be data |
ste_chkack: |
; Check that we received an ACK |
mov bl, [edx + 33] |
and bl, 0x10 |
cmp bl, 0x10 |
jnz ste_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 ch, [edx + 34] |
mov cl, [edx + 35] |
cmp cx, 1024 |
ja ste004 |
mov ecx, [sktAddr] |
mov [ecx+72], dword 1 |
ste004: |
; OK, here is the deal |
; My recv.nct field holds the seq of the expected next rec byte |
; if the recevied sequence number is not equal to this, do not |
; increment the recv.nxt field, do not copy data - just send a |
; repeat ack. |
; recv.nxt is in dword [edx+24], in inext format |
; recv seq is in [sktAddr]+56, in inet format |
; just do a comparision |
mov ecx, [sktAddr] |
add ecx, 56 |
cmp [ecx - 56 + 28], dword TCB_CLOSE_WAIT |
mov ecx, [ecx] |
jne stenofin |
mov ecx, eax |
stenofin: |
cmp ecx, [edx+24] |
jne ste_ack |
; Read the data bytes, store in socket buffer |
xor ecx, ecx |
mov ch, [edx + 2] |
mov cl, [edx + 3] |
sub ecx, 40 ; Discard 40 bytes of header |
cmp ecx, 0 |
jnz ste_data ; Read data, if any |
; If we had received a fin, we need to ACK it. |
mov esi, [sktAddr] |
mov ebx, [esi + 28] |
cmp ebx, TCB_CLOSE_WAIT |
jz ste_ack |
jnz ste_exit |
ste_data: |
push ecx |
mov esi, [sktAddr] |
add [esi + 24], ecx ; increment the count of bytes in buffer |
mov eax, [esi + 4] ; get socket owner PID |
push eax |
mov eax, [esi + 24] ; get # of bytes already in buffer |
; point to the location to store the data |
add esi, eax |
sub esi, ecx |
add esi, SOCKETHEADERSIZE |
add edx, 40 ; edx now points to the data |
mov edi, esi |
mov esi, edx |
cld |
rep movsb ; copy the data across |
; flag an event to the application |
pop eax |
mov ecx,1 |
mov esi,0x3020+0x4 |
news: |
cmp [esi],eax |
je foundPID1 |
inc ecx |
add esi,0x20 |
cmp ecx,[0x3004] |
jbe news |
foundPID1: |
shl ecx,8 |
or dword [ecx+0x80000+0xA8],dword 10000000b ; stack event |
pop ecx |
; Update our recv.nxt field |
mov esi, [sktAddr] |
add esi, 56 |
call add_inet_esi |
ste_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 ste_exit |
push eax |
mov bl, 0x10 ; ACK |
mov ecx, 0 |
mov esi, 0 |
call buildTCPPacket |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [ sktAddr ] |
mov ecx, [ ecx + 16 ] |
cmp edx, ecx |
jne ste_notlocal |
mov eax, IPIN_QUEUE |
ste_notlocal: |
; Send it. |
pop ebx |
call queue |
ste_exit: |
ret |
stateTCB_FIN_WAIT_1: |
; We can either receive an ACK of a fin, or a fin |
mov bl, [edx + 33] |
and bl, 0x10 |
cmp bl, 0x10 |
jnz stfw1_001 |
; It was an ACK |
mov esi, [sktAddr] |
mov ebx, TCB_FIN_WAIT_2 |
mov [esi + 28], ebx |
jmp stfw1_exit |
stfw1_001: |
; It must be a fin then |
mov esi, [sktAddr] |
mov ebx, TCB_CLOSING |
mov [esi + 28], ebx |
add esi, 56 |
call inc_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je stfw1_exit |
push eax |
mov bl, 0x10 ; ACK |
mov ecx, 0 |
mov esi, 0 |
call buildTCPPacket |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [ sktAddr ] |
mov ecx, [ ecx + 16 ] |
cmp edx, ecx |
jne stfw1_notlocal |
mov eax, IPIN_QUEUE |
stfw1_notlocal: |
; Send it. |
pop ebx |
call queue |
stfw1_exit: |
ret |
stateTCB_FIN_WAIT_2: |
mov esi, [sktAddr] |
; Get data length |
xor ecx, ecx |
mov ch, [edx+2] |
mov cl, [edx+3] |
sub ecx, 40 |
mov bl, [edx + 33] |
and bl, 0x01 |
cmp bl, 0x01 |
jne stfw2001 |
; Change state, as we have a fin |
mov ebx, TCB_TIME_WAIT |
mov [esi + 28], ebx |
inc ecx ; FIN is part of the sequence space |
stfw2001: |
add esi, 56 |
call add_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je stfw2_exit |
push eax |
mov bl, 0x10 ; ACK |
mov ecx, 0 |
mov esi, 0 |
call buildTCPPacket |
mov eax, NET1OUT_QUEUE |
mov edx, [stack_ip] |
mov ecx, [ sktAddr ] |
mov ecx, [ ecx + 16 ] |
cmp edx, ecx |
jne stfw2_notlocal |
mov eax, IPIN_QUEUE |
stfw2_notlocal: |
; Send it. |
pop ebx |
call queue |
; Only delete the socket if we received the FIN |
mov bl, [edx + 33] |
and bl, 0x01 |
cmp bl, 0x01 |
jne stfw2_exit |
; mov edi, [sktAddr] |
; delete the socket. Should really wait for 2MSL |
; xor eax, eax |
; mov ecx,SOCKETHEADERSIZE |
; cld |
; rep stosb |
stfw2_exit: |
ret |
stateTCB_CLOSE_WAIT: |
; Intentionally left empty |
; socket_close_tcp handles this |
ret |
stateTCB_CLOSING: |
; We can either receive an ACK of a fin, or a fin |
mov bl, [edx + 33] |
and bl, 0x10 |
cmp bl, 0x10 |
jnz stc_exit |
; It was an ACK |
mov edi, [sktAddr] |
; delete the socket |
xor eax, eax |
mov ecx,SOCKETHEADERSIZE |
cld |
rep stosb |
stc_exit: |
ret |
stateTCB_LAST_ACK: |
; Look at control flags - expecting an ACK |
mov bl, [edx + 33] |
and bl, 0x10 |
cmp bl, 0x10 |
jnz stla_exit |
mov edi, [sktAddr] |
; delete the socket |
xor eax, eax |
mov ecx,SOCKETHEADERSIZE |
cld |
rep stosb |
stla_exit: |
ret |
stateTCB_TIME_WAIT: |
ret |
stateTCB_CLOSED: |
ret |
/kernel/trunk/network/udp.inc |
---|
0,0 → 1,137 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; UDP.INC ;; |
;; ;; |
;; UDP 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;******************************************************************* |
; Interface |
; |
; udp_rx Handles received IP packets with the UDP protocol |
; |
;******************************************************************* |
;*************************************************************************** |
; Function |
; udp_rx |
; |
; Description |
; UDP protocol handler |
; This is a kernel function, called by ip_rx |
; IP buffer address given in edx |
; Free up (or re-use) IP buffer when finished |
; |
;*************************************************************************** |
udp_rx: |
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 |
movzx ebx, word [edx + 22] ; get the local port from |
; the IP packet's UDP header |
mov eax, SOCKETBUFFSIZE * NUM_SOCKETS |
mov ecx, NUM_SOCKETS |
fs1: |
sub eax, SOCKETBUFFSIZE |
cmp [eax + sockets + 12], bx ; bx will hold the 'wrong' value, |
; but the comparision is correct |
loopnz fs1 ; Return back if no match |
jz fs_done |
; No match, so exit |
jmp udprx_001 |
fs_done: |
; 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 |
mov ebx, [eax + sockets + 16] |
cmp ebx, 0xffffffff |
je udprx_002 |
mov ebx, [edx + 12] ; get the Source address from the IP packet |
cmp [eax + sockets + 16], ebx |
jne udprx_001 ; Quit if the source IP is not valid |
udprx_002: |
; 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 |
movzx ebx, word [edx + 20] ; get the UDP source port |
; ( was 69, now new ) |
mov [eax + sockets + 20], bx |
; 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, byte [edx + 3] ; total length of IP packet. Subtract |
mov ch, byte [edx + 2] ; 20 + 8 gives data length |
sub ecx, 28 |
mov ebx, eax |
add ebx, sockets ; ebx = address of actual socket |
mov eax, [ebx+ 4] ; get socket owner PID |
push eax |
mov eax, [ebx + 24] ; get # of bytes already in buffer |
add [ebx + 24], ecx ; increment the count of bytes in buffer |
; point to the location to store the data |
add ebx, eax |
add ebx, SOCKETHEADERSIZE |
; ebx = location for first byte, ecx has count, |
; edx points to data |
add edx, 28 ; edx now points to the data |
mov edi, ebx |
mov esi, edx |
cld |
rep movsb ; copy the data across |
; flag an event to the application |
pop eax |
mov ecx,1 |
mov esi,0x3020+0x4 |
newsearch: |
cmp [esi],eax |
je foundPID |
inc ecx |
add esi,0x20 |
cmp ecx,[0x3004] |
jbe newsearch |
foundPID: |
shl ecx,8 |
or dword [ecx+0x80000+0xA8],dword 10000000b ; stack event |
mov [check_idle_semaphore],200 |
udprx_001: |
pop eax |
call freeBuff ; Discard the packet |
ret |
/kernel/trunk/sound/playnote.inc |
---|
0,0 → 1,135 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
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 |
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 ebx |
push ecx |
push edx |
mov eax,[pidProcessNote] |
call pid_to_slot |
test eax,eax |
jz .failed |
lea ebx,[esp+12] |
mov ecx,1 |
mov edx,[memAdrNote] |
inc [memAdrNote] |
call read_process_memory |
.failed: |
pop edx |
pop ecx |
pop ebx |
pop eax |
ret |
;------------------- END CODE ------------------- |
/kernel/trunk/sound/sb16.inc |
---|
0,0 → 1,350 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SB16.INC ;; |
;; ;; |
;; Sound Blaster 16 functions for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;; - 11.07.2002 8 bit stereo mode - Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
SB16_load_music equ 0xc0000000 |
SB16_play_music equ 0xc0000001 |
DMAPage equ 0x2A |
Rate equ 44100 |
SB16Buffer equ 0x2A0000 |
SB16_Status equ SB16Buffer+65536 |
iglobal |
sound_data_format dd 0x1 |
sound_data_length dd 65536 |
sound_data_freq dd 44100 |
endg |
sound_interface: |
cmp eax,0 ; Load data |
jne no_SB16_load_music |
mov edi,[0x3010] |
add edi,0x10 |
add ebx,[edi] |
call code_SB16_load_music |
ret |
no_SB16_load_music: |
cmp eax,1 ; Play data |
jne no_SB16_play_music |
call code_SB16_play_music |
ret |
no_SB16_play_music: |
cmp eax,2 ; Set data formats |
jne no_SB16_data_format |
cmp ebx,0 ; ebx=0 play format |
jne no_sound_format |
mov [sound_data_format],ecx ; 1=8b mono, 2=8b stereo |
ret |
no_sound_format: |
cmp ebx,1 ; ebx=1 data length |
jne no_sound_length |
mov [sound_data_length],ecx ; |
ret |
no_sound_length: |
cmp ebx,2 ; ebx=2 sound data frequency |
jne no_sound_freq |
mov [sound_data_freq],ecx |
ret |
no_sound_freq: |
ret |
no_SB16_data_format: |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
cmp eax, edi ; 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 eax, [0x3010] |
; mov eax, [eax+0x10] ; address application im memory |
; add eax, edx ; add offset Delay-Note string |
; mov [memAdrNote], eax |
mov [memAdrNote],edx |
mov eax,[0x3010] |
mov eax,[eax+4] |
mov [pidProcessNote],eax |
xor eax, eax ; Ok! EAX = 0 |
retFunc55: |
mov [esp+36], eax ; return value EAX for application |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
ret |
code_SB16_play_music: |
cmp [sound_data_format],1 |
jne no_sound_8bm |
call sb_play_8b_mono |
ret |
no_sound_8bm: |
cmp [sound_data_format],2 |
jne no_sound_8bs |
call sb_play_8b_stereo |
ret |
no_sound_8bs: |
ret |
Blaster_command: |
push eax |
push ecx |
push edx |
mov dx,word [sb16] |
add dx,0xc |
mov cx,1000 |
bcl1: |
in al,dx |
and al,128 |
jz bcl2 |
loop bcl1 |
bcl2: |
mov al,[esp+8] |
mov dx,[esp+0] |
add dx,word [sb16] |
out dx,al |
pop edx |
pop ecx |
pop eax |
ret |
sb_play_8b_stereo: |
pusha |
call sb_set_dma |
call sb_set_stereo |
mov dx,0xc |
mov al,0xa8 |
call Blaster_command |
mov al,0x40 |
call Blaster_command |
mov al,245 |
call Blaster_command |
mov al,0x48 |
call Blaster_command |
mov al,0xff |
call Blaster_command |
call Blaster_command |
mov al,0x91 |
call Blaster_command |
popa |
ret |
sb_set_stereo: |
push eax |
push edx |
call sb_wait |
mov dx,word [sb16] |
add dx,0x4 |
mov al,0xe |
out dx,al |
inc dx |
in al,dx |
and al,253 |
or al,2 ; stereo |
out dx,al |
pop edx |
pop eax |
ret |
code_SB16_load_music: |
cmp byte [SB16_Status],1 |
je nol |
mov edi,SB16Buffer |
mov esi,ebx |
mov ecx,65536/4 |
cld |
rep movsd |
nol: ret |
iglobal |
dma_table db 0x87,0x83,0x81,0x82 |
endg |
;-------------------------------- |
; program dma |
;-------------------------------- |
sb_set_dma: |
pusha |
mov eax,[sound_dma] |
add eax,4 |
out 0xa,al |
mov al,0 |
out 0xc,al |
mov eax,[sound_dma] |
add eax,0x48 |
out 0xb,al |
mov edx,[sound_dma] |
shl edx,1 |
mov al,0 |
out dx,al |
mov al,0 |
out dx,al |
mov edx,[sound_dma] |
add edx,dma_table |
movzx edx,byte [edx] |
mov al,DMAPage |
out dx,al |
mov edx,[sound_dma] |
shl edx,1 |
inc edx |
mov eax,[sound_data_length] |
dec eax |
and eax,0xff |
; mov al,(DataLength-1) and 0xff |
out dx,al |
mov eax,[sound_data_length] |
dec eax |
shr eax,8 |
; mov al,(DataLength-1) shr 8 |
out dx,al |
mov eax,[sound_dma] ; DMA |
out 0xa,al |
popa |
ret |
sb_play_8b_mono: |
call sb_set_dma |
cmp byte [SB16_Status],1 |
jne contsb16 |
jmp retserve |
contsb16: |
mov dx,word [sb16] |
add dx,4 |
mov ecx,[sound_dma] |
mov ax,0x01 |
shl ax,cl |
shl ax,8 |
add ax,0x81 |
out dx,ax |
mov ax,0f280h ;enable irq5 |
out dx,ax |
adr1_SB: mov dx,word [sb16] |
add dx,0ch |
in al,dx |
and al,080h |
jnz adr1_SB |
call sb_set_stereo |
mov al,0d1h |
out dx,al |
mov dx,word [sb16] |
add dx,0ch |
call sb_wait |
mov al,40h ; Rate |
out dx,al |
call sb_wait |
mov al,256-1000000/Rate |
out dx,al |
call sb_wait |
mov al,14h ; Datalength |
out dx,al |
call sb_wait |
mov eax,[sound_data_length] |
dec eax |
and eax,0xff |
;mov al,(DataLength-1) and 0xff |
out dx,al |
call sb_wait |
mov eax,[sound_data_length] |
dec eax |
shr eax,8 |
;mov al,(DataLength-1) shr 8 |
out dx,al |
retserve: |
ret |
sb_wait: in al,dx ;wait |
and al,080h |
jnz sb_wait |
ret |
;**************************************** |
; END CODE SB16 by Minazzi Paolo |
;*************************************** |
/kernel/trunk/video/vesa12.inc |
---|
0,0 → 1,973 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; VESA12.INC ;; |
;; ;; |
;; Vesa 1.2 functions for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Ville Turjanmaa ;; |
;; ;; |
;; quickcode@mail.ru - bankswitch for S3 cards ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; 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 modified by kmeaw |
set_bank: |
cli |
cmp al,[0xfff2] |
je retsb |
mov [0xfff2],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: |
sti |
ret |
;Set bank function for Intel 810/815 chipsets |
; *****Modified by Protopopius, Russia.***** |
; ********* http://menuetos.hut.ru ************** |
; ************************************************ |
; |
;set_bank: |
;cli |
;cmp al,[0xfff2] |
;je retsb |
;mov [0xfff2],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: |
;sti |
;ret |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} |
;set_bank: |
; cli |
; cmp al,[0xfff2] |
; je retsb |
; mov [0xfff2],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: |
; ret |
vesa12_drawbackground: |
call [disable_mouse] |
push eax |
push ebx |
push ecx |
push edx |
xor edx,edx |
mov eax,dword[WinMapAddress-8] |
mov ebx,dword[WinMapAddress-4] |
mul ebx |
mov ebx,3 |
mul ebx |
mov [imax],eax |
mov eax,[draw_data+32+0] |
mov ebx,[draw_data+32+4] |
mov edi,0 ;no force |
v12dp3: |
push eax |
push ebx |
mov esi,0x300000 |
cmp [WinMapAddress-12],dword 1 ; tiled background |
jne no_vesa12_tiled_bgr |
push edx |
xor edx,edx |
mov ecx,[WinMapAddress-8] |
div ecx |
mov eax,edx |
push eax |
mov eax,ebx |
xor edx,edx |
mov ecx,[WinMapAddress-4] |
div ecx |
mov ebx,edx |
pop eax |
pop edx |
no_vesa12_tiled_bgr: |
cmp [WinMapAddress-12],dword 2 ; stretched background |
jne no_vesa12_stretched_bgr |
push edx |
imul eax,dword [WinMapAddress-8] |
xor edx,edx |
mov ecx,[0xfe00] |
inc ecx |
div ecx |
push eax |
mov eax,ebx |
imul eax,dword [WinMapAddress-4] |
xor edx,edx |
mov ecx,[0xfe04] |
inc ecx |
div ecx |
mov ebx,eax |
pop eax |
pop edx |
no_vesa12_stretched_bgr: |
push eax |
mov eax,ebx |
xor edx,edx |
mov ebx,[WinMapAddress-8] |
add ebx,[WinMapAddress-8] |
add ebx,[WinMapAddress-8] |
mul ebx |
mov esi,eax |
pop eax |
add esi,eax |
add esi,eax |
add esi,eax |
add esi,0x300000 |
pop ebx |
pop eax |
v12di4: |
mov ecx,[esi] |
pusha |
mov esi,eax |
mov edi,ebx |
mov eax,[0xfe00] |
add eax,1 |
mul ebx |
add eax,esi |
add eax,WinMapAddress |
cmp [eax],byte 1 |
jnz v12nbgp |
mov eax,[0xfe08] |
mov ebx,edi |
mul ebx |
add eax,esi |
add eax,esi |
add eax,esi |
cmp [0xFBF1],byte 24 |
jz v12bgl3 |
add eax,esi |
v12bgl3: |
push ebx |
push eax |
sub eax,[0xfe80] |
shr eax,16 |
call set_bank |
pop eax |
and eax,65535 |
add eax,0xa0000 |
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+8] |
jg v12nodp31 |
jmp v12dp3 |
v12nodp31: |
mov eax,[draw_data+32+0] |
inc ebx |
cmp ebx,[draw_data+32+12] |
jg v12dp4 |
jmp v12dp3 |
v12dp4: |
pop edx |
pop ecx |
pop ebx |
pop eax |
ret |
vesa12_drawbar: |
call [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,[0x3010] |
add eax,[ecx-twdw] |
add ebx,[ecx-twdw+4] |
push eax |
mov eax,ebx ; y |
mov ebx,[0xfe08] |
mul ebx |
pop ecx |
add eax,ecx ; x |
add eax,ecx |
add eax,ecx |
cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? - x start |
jz dbpi2412 |
add eax,ecx |
dbpi2412: |
add eax,[0xfe80] |
mov edi,eax |
; x size |
mov eax,[esp+4] ; [esp+6] |
mov ecx,eax |
add ecx,eax |
add ecx,eax |
cmp [0xfbf1],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,[0x3010] |
mov ecx,[eax+draw_data-0x3000+0] |
cmp ecx,0 |
jnz dbcblimitlset12 |
mov ecx,[eax+draw_data-0x3000+4] |
cmp ecx,0 |
jnz dbcblimitlset12 |
mov ecx,[eax+draw_data-0x3000+8] |
cmp ecx,[0xfe00] |
jnz dbcblimitlset12 |
mov ecx,[eax+draw_data-0x3000+12] |
cmp ecx,[0xfe04] |
jnz dbcblimitlset12 |
pop ecx |
pop eax |
push dword 0 |
jmp dbcblimitlno12 |
dbcblimitlset12: |
pop ecx |
pop eax |
push dword 1 |
dbcblimitlno12: |
cmp [0xfbf1],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,[0xfe80] |
mov ebx,3 |
div ebx |
add eax,WinMapAddress |
mov ebx,[0x3010] |
movzx ebx,byte[ebx+0xe] |
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,[0xfe80] |
shr eax,16 |
call set_bank |
and edi,0xffff |
add edi,0xa0000 |
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,[0xfe08] |
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,[0xfe80] |
shr eax,2 |
add eax,WinMapAddress |
mov ebx,[0x3010] |
movzx ebx,byte[ebx+0xe] |
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,[0xfe80] |
shr eax,16 |
call set_bank |
and edi,0xffff |
add edi,0xa0000 |
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,[0xfe08] |
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,[0xfe08] |
mul ebx |
add edi,eax |
mov eax,edi |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,0xa0000 |
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,[0xfe08] |
mul ebx |
add edi,eax |
mov eax,edi |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,0xa0000 |
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,[0xfe08] |
mul ebx |
add edi,eax |
mov eax,edi |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,0xa0000 |
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,[0xfe08] |
xor edx,edx |
mul ebx |
add edi,eax |
mov eax,edi |
shr eax,16 |
call set_bank |
and edi,65535 |
add edi,0xa0000 |
mov ecx,[edi] |
and ecx,255*256*256+255*256+255 |
sti |
ret |
vesa12_putimage: |
; mov ebx,image |
; mov ecx,320*65536+240 |
; mov edx,20*65536+20 |
call [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,[0x3010] |
add eax,[ecx-twdw] |
add ebx,[ecx-twdw+4] |
push eax |
mov eax,ebx ; y |
mov ebx,[0xfe08] |
mul ebx |
pop ecx |
add eax,ecx ; x |
add eax,ecx |
add eax,ecx |
cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? - x start |
jz pi2412 |
add eax,ecx |
pi2412: |
add eax,[0xfe80] |
mov edi,eax |
; x size |
movzx eax,word [esp+6] |
mov ecx,eax |
add ecx,eax |
add ecx,eax |
cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? - x size |
jz pi24312 |
add ecx,eax |
pi24312: |
mov esi,[esp+8] |
movzx ebx,word [esp+4] |
; check limits while draw ? |
push eax |
push ecx |
mov eax,[0x3010] |
mov ecx,[eax+draw_data-0x3000+0] |
cmp ecx,0 |
jnz dbcblimitlset212 |
mov ecx,[eax+draw_data-0x3000+4] |
cmp ecx,0 |
jnz dbcblimitlset212 |
mov ecx,[eax+draw_data-0x3000+8] |
cmp ecx,[0xfe00] |
jnz dbcblimitlset212 |
mov ecx,[eax+draw_data-0x3000+12] |
cmp ecx,[0xfe04] |
jnz dbcblimitlset212 |
pop ecx |
pop eax |
push dword 0 |
jmp dbcblimitlno212 |
dbcblimitlset212: |
pop ecx |
pop eax |
push dword 1 |
dbcblimitlno212: |
cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? |
jz pi24bit12 |
jmp pi32bit12 |
pi24bit12: |
cld |
push eax |
push ebx |
push edx |
xor edx,edx |
mov eax,ecx |
mov ebx,3 |
div ebx |
mov ecx,eax |
pop edx |
pop ebx |
pop eax |
newpi12: |
push edi |
push esi |
push ecx |
push ebx |
xor edx,edx |
mov eax,edi |
sub eax,[0xfe80] |
mov ebx,3 |
div ebx |
add eax,WinMapAddress |
mov ebx,[0x3010] |
mov bl,[ebx+0xe] |
mov bh,[esp+4*4] |
np2412: |
cmp bl,[eax] |
jnz imp24no12 |
mov edx,[esi] |
cmp bh,0 |
jz imp24yes12 |
; call dbcplimit |
; jnz imp24no12 |
imp24yes12: |
push eax |
push edi |
mov eax,edi |
sub eax,[0xfe80] |
shr eax,16 |
call set_bank |
and edi,0xffff |
add edi,0xa0000 |
mov [edi],edx |
shr edx,2 |
mov [edi+2],dl |
sti |
pop edi |
pop eax |
imp24no12: |
inc eax |
add esi,3 |
add edi,3 |
dec ecx |
jnz np2412 |
np24d12: |
pop ebx |
pop ecx |
pop esi |
pop edi |
add edi,[0xfe08] |
xor eax,eax |
mov ax,[esp+4+2+4] |
lea eax,[eax+eax*2] |
add esi,eax |
dec ebx |
jz nonewpi12 |
jmp newpi12 |
nonewpi12: |
add esp,7*4 |
mov eax,0 |
ret |
pi32bit12: |
cld |
shr ecx,2 |
newpi3212: |
push edi |
push esi |
push ecx |
push ebx |
mov eax,edi |
sub eax,[0xfe80] |
shr eax,2 |
add eax,WinMapAddress |
mov ebx,[0x3010] |
mov bl,[ebx+0xe] |
mov bh,[esp+4*4] |
np3212: |
cmp bl,[eax] |
jnz imp32no12 |
mov edx,[esi] |
cmp bh,0 |
jz imp32yes12 |
; call dbcplimit |
; jnz imp32no12 |
imp32yes12: |
push eax |
push edi |
mov eax,edi |
sub eax,[0xfe80] |
shr eax,16 |
call set_bank |
and edi,0xffff |
add edi,0xa0000 |
mov [edi],edx |
sti |
pop edi |
pop eax |
imp32no12: |
inc eax |
add esi,3 |
add edi,4 |
dec ecx |
jnz np3212 |
np32d12: |
pop ebx |
pop ecx |
pop esi |
pop edi |
add edi,[0xfe08] |
movzx eax,word [esp+4+2+4] |
lea eax,[eax+eax*2] |
add esi,eax |
dec ebx |
jz nonewpi3212 |
jmp newpi3212 |
nonewpi3212: |
add esp,7*4 |
mov eax,0 |
ret |
vesa12_read_screen_pixel: |
and eax,0x3FFFFF |
cmp [0xfbf1],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,0xa0000 |
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,0xa0000 |
mov eax,[edi] |
and eax,0x00ffffff |
ret |
/kernel/trunk/video/vesa20.inc |
---|
0,0 → 1,1107 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; If you're planning to write your own video driver I suggest |
; you replace the VESA12.INC file and see those instructions. |
ScreenWidth equ 0xfe00 |
ScreenHeight equ 0xfe04 |
BytesPerScanLine equ 0xfe08 |
LFBAddress equ 0xfe80 |
ScreenBPP equ 0xfbf1 |
WinMapAddress equ 0x460000 |
;************************************************* |
; getpixel |
; |
; in: |
; eax = x coordinate |
; ebx = y coordinate |
; |
; ret: |
; ecx = 00 RR GG BB |
getpixel: |
push eax ebx edx edi |
call dword [0xe024] |
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) |
add edi, [LFBAddress] ; ebx = where pixel is in memory |
mov ecx, [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) |
add edi, [LFBAddress] ; ebx = where pixel is in memory |
mov ecx, [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 ? |
.source_bpp dd ? |
.winmap_newline dd ? |
.screen_newline dd ? |
.stack_data = 4*13 |
end virtual |
align 4 |
; ebx = pointer |
; ecx = size [x|y] |
; edx = coordinates [x|y] |
vesa20_putimage: |
pushad |
call [disable_mouse] |
sub esp, putimg.stack_data |
mov [putimg.source_bpp], 3 |
; test ebx, 0x80000000 |
; jz @f |
; inc [putimg.source_bpp] |
; @@: |
; and ebx, 0x7FFFFFFF |
; 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, [0x3010] |
mov ebx, [eax-twdw + 0] |
add ebx, [putimg.image_cx] |
mov [putimg.abs_cx], ebx |
mov ebx, [eax-twdw + 4] |
add ebx, [putimg.image_cy] |
mov [putimg.abs_cy], ebx |
; real_sx = MIN(wnd_sx-image_cx, image_sx); |
mov ebx, [eax-twdw + 8] ; ebx = wnd_sx |
sub ebx, [putimg.image_cx] |
ja @f |
add esp, putimg.stack_data |
popad |
xor eax, eax |
inc eax |
ret |
@@: |
cmp ebx, [putimg.image_sx] |
jbe .end_x |
mov ebx, [putimg.image_sx] |
dec ebx |
.end_x: |
inc ebx |
mov [putimg.real_sx], ebx |
; init real_sy |
mov ebx, [eax-twdw + 12] ; ebx = wnd_sy |
sub ebx, [putimg.image_cy] |
ja @f |
add esp, putimg.stack_data |
popad |
xor eax, eax |
inc eax |
ret |
@@: |
cmp ebx, [putimg.image_sy] |
jbe .end_y |
mov ebx, [putimg.image_sy] |
dec ebx |
.end_y: |
inc ebx |
mov [putimg.real_sy], ebx |
; line increment |
mov eax, [putimg.image_sx] |
sub eax, [putimg.real_sx] |
;; imul eax, [putimg.source_bpp] |
lea eax, [eax + eax * 2] |
mov [putimg.line_increment], eax |
; winmap new line increment |
mov eax, [ScreenWidth] |
inc eax |
sub eax, [putimg.real_sx] |
mov [putimg.winmap_newline], eax |
; screen new line increment |
mov eax, [BytesPerScanLine] |
mov ecx, [putimg.real_sx] |
movzx ebx, byte [ScreenBPP] |
shr ebx, 3 |
imul ecx, ebx |
sub eax, ecx |
mov [putimg.screen_newline], eax |
; pointer to image |
mov ecx, [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 |
add edx, [LFBAddress] |
; pointer to pixel map |
mov eax, [putimg.abs_cy] |
imul eax, [ScreenWidth] |
add eax, [putimg.abs_cy] |
add eax, [putimg.abs_cx] |
add eax, WinMapAddress |
xchg eax, ebp |
; get process number |
mov eax, [0x3010] |
mov bl, [eax+0xE] |
cmp byte [ScreenBPP], 32 |
je put_image_end_32 |
;put_image_end_24: |
;cli ; !!!!!!!!!!!!!!!!!!!!!! |
mov edi, [putimg.real_sy] |
align 4 |
.new_line: |
mov esi, [putimg.real_sx] |
; push ebp edx |
align 4 |
.new_x: |
cmp [ebp], bl |
jne .skip |
mov eax, [ecx] ; ecx = RRBBGGRR |
mov [edx], ax |
shr eax, 16 |
mov [edx+2], al |
.skip: |
add ecx, 3 ;[putimg.source_bpp] |
add edx, 3 |
inc ebp |
dec esi |
jnz .new_x |
; pop edx ebp |
add ecx, [putimg.line_increment] |
add edx, [putimg.screen_newline] ;[BytesPerScanLine] |
add ebp, [putimg.winmap_newline] ;[ScreenWidth] |
;inc ebp |
dec edi |
jnz .new_line |
.finish: |
add esp, putimg.stack_data |
popad |
xor eax, eax |
;sti ; !!!!!!!!!!!!!!!!!!!!! |
ret |
put_image_end_32: |
mov edi, [putimg.real_sy] |
align 4 |
.new_line: |
mov esi, [putimg.real_sx] |
; push ebp edx |
align 4 |
.new_x: |
cmp [ebp], bl |
jne .skip |
mov eax, [ecx] ; ecx = RRBBGGRR |
mov [edx], eax |
.skip: |
add ecx, [putimg.source_bpp] |
add edx, 4 |
inc ebp |
dec esi |
jnz .new_x |
; pop edx ebp |
add ecx, [putimg.line_increment] |
add edx, [putimg.screen_newline] ;[BytesPerScanLine] |
add ebp, [putimg.winmap_newline] ;[ScreenWidth] |
;inc ebp |
dec edi |
jnz .new_line |
.finish: |
add esp, putimg.stack_data |
popad |
xor eax, eax |
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 |
test edi,1 ; force ? |
jnz .forced |
; not forced: |
call checkpixel |
test ecx,ecx |
jnz .exit |
.forced: |
cmp [ScreenWidth], eax |
jb .exit |
cmp [ScreenHeight], ebx |
jb .exit |
.ok: |
; check if negation |
test ecx,0x01000000 |
jz .noneg |
call getpixel |
not ecx |
mov [esp+32-8],ecx |
.noneg: |
; OK to set pixel |
call dword [0xe020] ; 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] |
add edi, [LFBAddress] |
add edi, ebx ; ebx = where to put pixel in memory |
mov [edi], ax |
shr eax, 16 |
mov [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 |
add edi, [LFBAddress] ; ebx = where to put pixel in memory |
mov [edi], eax |
ret |
;************************************************* |
;align 4 |
calculate_edi: |
mov edi, ebx |
imul edi, [ScreenWidth] |
add edi, ebx |
add edi, eax |
ret |
;************************************************* |
; DRAWLINE |
align 4 |
__sys_draw_line: |
call [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 |
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 [disable_mouse] |
sub esp, drbar.stack_data |
mov [drbar.color], edi |
sub edx, ebx |
sub ecx, eax |
mov [drbar.bar_sy], edx |
mov [drbar.bar_sx], ecx |
mov [drbar.bar_cx], eax |
mov [drbar.bar_cy], ebx |
mov edi, [0x3010] |
add eax, [edi-twdw + 0] ; win_cx |
add ebx, [edi-twdw + 4] ; 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 + 8] ; ebx = wnd_sx |
sub ebx, [drbar.bar_cx] |
ja @f |
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 + 12] ; ebx = wnd_sy |
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, [ScreenWidth] |
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 |
add edx, [LFBAddress] |
; pointer to pixel map |
mov eax, [drbar.abs_cy] |
imul eax, [ScreenWidth] |
add eax, [drbar.abs_cy] |
add eax, [drbar.abs_cx] |
add eax, WinMapAddress |
xchg eax, ebp |
; get process number |
mov eax, [0x3010] |
mov bl, [eax+0xE] |
cmp byte [ScreenBPP], 24 |
jne draw_bar_end_32 |
draw_bar_end_24: |
;cli ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
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 [edx], bh |
mov [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 |
;sti ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
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 [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 |
xor eax, eax |
ret |
;voodoodbcplimit: |
; ebp:=(y+Ywin)*(ScreenXSize+1)+(x+Xwin)+AddrBuffer |
; pusha |
; xor edx,edx |
; mov eax,ebp |
; mov ebx,[ScreenWidth] ; Screen_X_size |
; inc ebx ; +1 |
; sub eax,WinMapAddress ; -AddrBuffer |
; div ebx ; |
; mov ebx,eax ; ebx:=Y |
; mov eax,edx ; eax:=X |
; call cplimit |
; test ecx,ecx |
; jne dbcpl12 |
; popa |
; clc |
; ret |
; dbcpl12: |
; popa |
; stc |
; ret |
;dbcplimit: |
; pusha |
; xor edx,edx |
; mov ebx,[ScreenWidth] |
; inc ebx |
; sub eax,WinMapAddress |
; div ebx |
; mov ebx,eax |
; mov eax,edx |
; call cplimit |
; test ecx,ecx |
; jne dbcpl1 |
; popa |
; clc |
; ret |
; dbcpl1: |
; popa |
; stc |
; ret |
;--------------vbe voodoo ------------------------------------------------ |
vesa20_drawbackground_tiled: |
call [disable_mouse] |
push ebp |
push eax |
push ebx |
push ecx |
push edx |
mov edx,dword [WinMapAddress-8] ; B |
add edx,dword [WinMapAddress-8] ; +B |
add edx,dword [WinMapAddress-8] ; +B |
push edx |
mov ebp,[draw_data+32+0] ; x start:=(x+Xwin) |
mov ebx,[draw_data+32+4] ; y start:=(y+Ywin) |
mov eax,[BytesPerScanLine] |
mul ebx |
xchg ebp, eax ; BytesPerScanLine*(Ywin+y) |
add ebp, eax ; +X |
add ebp, eax ; +X |
add ebp, eax ; +X |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
add ebp,eax ; +X |
@@: |
add ebp,[LFBAddress] ; +LFB |
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB |
call calculate_edi |
dp3: ; MAIN LOOP |
cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1) |
; je ybgp |
; |
; jmp nbgp |
; |
; ybgp: |
jne nbgp |
push eax |
push ebx |
mov ecx,dword [WinMapAddress-8] ; B |
xor edx,edx ; edx:=0 |
div ecx ; Xstart/B |
; eax=Int(qn) edx:=Rem |
lea esi,[edx+edx*2] ; esi:=edx*3 |
mov ecx,dword [WinMapAddress-4] ; ecx:=H |
mov eax,[esp+0] ; eax:=Ystart |
xor edx,edx ; |
div ecx ; Ystart/H |
mov eax,edx ; eax:=Rem |
xor edx,edx ; |
mov ebx,[esp+8] ; ebx:=B*3 |
mul ebx ; |
add esi,eax ; |
mov eax,[esi+0x300000] |
and eax,0xffffff |
xchg edi, ebp |
stosw |
shr eax,16 |
stosb |
xchg ebp, edi ; ebp+=3 |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
inc ebp ; +1 |
@@: |
pop ebx |
pop eax |
jmp hook1 |
nbgp: |
add ebp,3 ; +3 |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
inc ebp ; +1 |
@@: |
hook1: |
inc edi ; ptrBuffer++ |
add esi,3 ; ptrImage+=3 |
inc eax |
cmp eax,[draw_data+32+8] ; X > xend? |
; jg nodp3 |
; jmp dp3 |
; |
; nodp3: |
jle dp3 |
mov ebp,[draw_data+32+0] |
inc ebx |
mov eax,[BytesPerScanLine] |
mul ebx |
xchg ebp, eax ; BytesPerScanLine*(Ywin+y) |
add ebp, eax ; +X |
add ebp, eax ; +X=X*2 |
add ebp, eax ; +X=X*3 |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
add ebp,eax ; +X=X*4 |
@@: |
add ebp,[LFBAddress] ; +LFB |
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB |
call calculate_edi |
cmp ebx,[draw_data+32+12] |
; jg dp4 |
; |
; jmp dp3 |
; |
; dp4: |
jle dp3 |
add esp,4 |
pop edx |
pop ecx |
pop ebx |
pop eax |
pop ebp |
ret |
; ---------- |
vesa20_drawbackground_stretch: |
call [disable_mouse] |
push ebp |
push eax |
push ebx |
push ecx |
push edx |
mov edx,dword [WinMapAddress-8] ; B |
add edx,dword [WinMapAddress-8] ; +B |
add edx,dword [WinMapAddress-8] ; +B |
push edx |
mov ebp,[draw_data+32+0] ; x start:=(x+Xwin) |
mov ebx,[draw_data+32+4] ; y start:=(y+Ywin) |
mov eax,[BytesPerScanLine] |
mul ebx |
xchg ebp, eax ; BytesPerScanLine*(Ywin+y) |
add ebp, eax ; +X |
add ebp, eax ; +X |
add ebp, eax ; +X |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
add ebp,eax ; +X |
@@: |
add ebp,[LFBAddress] ; +LFB |
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB |
call calculate_edi |
sdp3: ; MAIN LOOP |
cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1) |
jne snbgp |
push eax |
push ebx |
mov eax,dword [WinMapAddress-8] |
imul eax, [esp+4] ;4 |
xor edx,edx |
mov ebx,[ScreenWidth] |
div ebx |
lea esi,[eax+eax*2] |
mov eax,dword [WinMapAddress-4] |
imul eax, [esp+0] ;0 |
xor edx,edx |
mov ebx,[ScreenHeight] |
div ebx |
imul eax, [esp+8] ;8 |
add esi,eax |
mov eax,[esi+0x300000] |
and eax,0xffffff |
xchg edi, ebp |
stosw |
shr eax,16 |
stosb |
xchg ebp, edi ; ebp+=3 |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
inc ebp ; +1 |
@@: |
pop ebx |
pop eax |
jmp shook1 |
snbgp: |
add ebp,3 ; +3 |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
inc ebp ; +1 |
@@: |
shook1: |
inc edi ; ptrBuffer++ |
add esi,3 ; ptrImage+=3 |
inc eax |
cmp eax,[draw_data+32+8] ; X > xend? |
jle sdp3 |
mov ebp,[draw_data+32+0] |
inc ebx |
mov eax,[BytesPerScanLine] |
mul ebx |
xchg ebp, eax ; BytesPerScanLine*(Ywin+y) |
add ebp, eax ; +X |
add ebp, eax ; +X=X*2 |
add ebp, eax ; +X=X*3 |
cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size |
jz @f |
add ebp,eax ; +X=X*4 |
@@: |
add ebp,[LFBAddress] ; +LFB |
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB |
call calculate_edi |
cmp ebx,[draw_data+32+12] |
jle sdp3 |
add esp,4 |
pop edx |
pop ecx |
pop ebx |
pop eax |
pop ebp |
ret |
/kernel/trunk/video/vga.inc |
---|
0,0 → 1,781 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; VGA.INC ;; |
;; ;; |
;; 640x480 mode 0x12 VGA functions for MenuetOS ;; |
;; ;; |
;; Paul Butcher, paul.butcher@asa.co.uk ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
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 |
ret |
vga_putimage: |
push ebp ; |
push esi ; |
push edi ; |
push eax ; |
push ebx ; +8 [ptrImage] |
push ecx ; +4 [BH] |
push edx ; +0 [xy] |
movzx eax,word [esp+2] ; eax:=x |
movzx ebx,word [esp+0] ; ebx:=y |
mov ecx,[0x3010] ; |
add eax,[ecx-twdw] ; eax+=Xwin |
add ebx,[ecx-twdw+4] ; ebx+=Ywin |
mov ecx,ebx ; ecx = y+Ywin |
mov edx,eax ; edx = x+Xwin |
imul ebx, 640*4 ; (y+Ywin)*BytesPerScanLine |
shl eax,2 ; (x+Xwin)*BytesPerPixel |
add eax,ebx ; |
mov edi,eax ; store copy |
add eax,[0xfe80] ; +AddrLFB |
;entry point in LFB >> EAX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrLFB |
shr edi,5 ; change from 4 to 1/8 BytesPerPixel |
add edi,0xa0000 ; + VGABasePtr |
;VGA start address >> EDI:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrVGA |
mov ebx, [0xfe00] ; ScreenXSize |
inc ebx ; +1 |
imul ebx,ecx ; *(y+Ywin) |
mov ebp, ebx ; |
add ebp, edx ; +(x+Xwin) |
add ebp, WinMapAddress ; ebp:=(y+Ywin)*(ScreenXSize+1)+(x+Xwin)+AddrBuffer |
mov esi,[esp+8] ; esi:=AddrImg |
movzx ecx,word [esp+6] ; ecx:=B |
movzx ebx,word [esp+4] ; ebx:=H |
; check limits while draw ? |
push ecx ; B |
push eax ; LFB address |
mov eax,[0x3010] |
mov ecx,[eax+draw_data-0x3000+0] |
cmp ecx,0 |
jnz dbcblimitlset_vga |
mov ecx,[eax+draw_data-0x3000+4] |
cmp ecx,0 |
jnz dbcblimitlset_vga |
mov ecx,[eax+draw_data-0x3000+8] |
cmp ecx,[0xfe00] ; ecx <> Screen X size |
jnz dbcblimitlset_vga |
mov ecx,[eax+draw_data-0x3000+12] |
cmp ecx,[0xfe04] ; ecx <> Screen Y size |
jnz dbcblimitlset_vga |
pop eax ; LFB address |
pop ecx ; B |
push dword 0 |
jmp pimvga |
dbcblimitlset_vga: |
pop eax ; LFB address |
pop ecx ; B |
push dword 1 |
pimvga: |
push edi |
push esi |
push eax ; LFB address |
push ecx ; B |
push ebx ; H |
push edx ; x+Xwin |
mov ebx,[0x3010] |
mov bl,[ebx+0xe] |
mov bh,[esp+6*4] |
cld |
npvga: |
cmp bl,[ds:ebp] |
jnz impvgano |
; cmp bh,0 |
; jz impvgayes |
; call voodoodbcplimit |
; jnz impvgano |
; impvgayes: |
push eax ; LFB address |
push ebx ; app no. |
push ecx ; B |
push edx ; x+Xwin |
mov edx,[esi] ; color |
mov [eax],dx |
shr edx,16 |
mov [eax+2],dl |
mov eax,[esi] ; color |
mov ecx,[esp] ; x+Xwin |
and ecx,0x07 ; modulo 8 |
call setvgapixel ; eax=color, ecx=x%8, edi=VGA address |
pop edx |
pop ecx |
pop ebx |
pop eax |
impvgano: |
add esi,3 ; esi+=3 ptrImage+=3 |
add eax,4 ; eax+=4 LFBaddr +=4 |
inc ebp |
inc edx ; x+Xwin+n |
test edx,0x07 ; test modulo 8 |
jnz impvgacont |
inc edi |
impvgacont: |
dec ecx ; B-- |
jnz npvga |
pop edx |
pop ebx |
pop ecx |
pop eax |
pop esi |
pop edi |
add edi,640/8 ; add one VGA line |
add eax,640*4 ; add one LFB line |
sub ebp, ecx ; -B |
add ebp, [0xfe00] ; |
inc ebp ; ptrBuffer:=ptrBuffer-B+Screen_Xsize+1 |
push ecx |
lea ecx,[ecx+ecx*2] ; |
add esi,ecx ; ptrImage:=ptrImage+B*3 |
pop ecx |
dec ebx ; H-- |
jnz near pimvga |
add esp,4 ; jump saved limit byte |
pop edx |
pop ecx |
pop ebx |
pop eax |
pop edi |
pop esi |
pop ebp |
ret |
VGA_putpixel: |
; eax = x |
; ebx = y |
mov ecx,eax |
mov eax, [esp+32-8+4] ; color |
imul ebx, 640*4 ; y*BytesPerLine (Vesa2.0 32) |
lea edx, [ebx+ecx*4] ; + x*BytesPerPixel (Vesa2.0 32) |
mov edi,edx |
add edi, [0xfe80] ; + LFB address |
mov [edi], eax ; write to LFB for Vesa2.0 |
shr edx,5 ; change BytesPerPixel to 1/8 |
mov edi,edx |
add edi, 0x0a0000 ; address of pixel in VGA area |
and ecx,0x07 ; bit no. (modulo 8) |
setvgapixel: |
; edi = address, eax = 24bit colour, ecx = bit no. (modulo 8) |
push eax |
mov ebx,eax ; color |
;mov al,0x08 |
;mov dx,0x03ce |
;out dx,al ; select GDC bit mask register |
inc cl |
mov ax, 0x100 |
shr ax,cl |
mov dx,0x03cf |
out dx,al ; set bit mask for pixel |
mov dl,0 |
mov eax,ebx |
and eax,0x000000ff ; blue |
cmp eax,85 |
jle p13green |
or dl,0x01 |
cmp eax,170 |
jle p13green |
or dl,0x08 |
p13green: |
and ebx,0x0000ff00 ; green |
cmp ebx,85*256 |
jle p13red |
or dl,0x02 |
cmp ebx,170*256 |
jle p13red |
or dl,0x08 |
p13red: |
pop ebx |
and ebx,0x00ff0000 ; red |
cmp ebx,85*256*256 |
jle p13cont |
or dl,0x04 |
cmp ebx,170*256*256 |
jle p13cont |
or dl,0x08 |
p13cont: |
mov al,[edi] ; dummy read |
mov [edi],dl |
ret |
vga_drawbar: |
sub edx,ebx ; edx:=Yend-Ystart=H |
sub ecx,eax ; ecx:=Xend-Xstat=B |
push ebp ; +24 |
push esi ; +20 |
push edi ; +16 |
push eax ; +12 |
push ebx ; +8 |
push ecx ; +4 |
push edx ; +0 |
mov ecx,[0x3010] ; |
add eax,[ecx-twdw] ; eax:=Xwin+x |
add ebx,[ecx-twdw+4] ; ebx:=Ywin+y |
mov ecx, eax ; ecx:=(x+Xwin) |
mov edx, ebx ; edx:=(y+Ywin) |
imul ebx, 640/8 ; |
mov edi, ebx ; edi:=BytesPerScanLine*(y+Ywin) |
shr eax, 3 ; |
add edi, eax ; + (x+Xwin)*BytesPerPixel |
add edi,0xa0000 ; + VGAbaseaddress |
mov eax, [0xfe00] ; ScreenXSize |
inc eax ; +1 |
imul eax,edx ; *(y+Ywin) |
mov ebp, eax ; |
add ebp, ecx ; +(x+Win) |
add ebp, WinMapAddress ; +AddrBuffer |
mov eax, [0xfe08] ; BytesPerScanLine - LFB |
mul edx ; *(y+Ywin) |
mov esi,eax |
add esi,ecx |
add esi,ecx |
add esi,ecx |
add esi,ecx ; + 4*(x+Xwin) |
add esi,[0xfe80] ; +AddrLFB |
; edi:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel + AddrVGA |
; esi:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel + AddrLFB |
; ebp:=(y+Ywin)*(ScreenXSize+1)+(x+Xwin)+AddrBuffer |
; x size |
mov eax,[esp+4] ; B [esp+4] |
mov ebx,[esp+0] ; H |
mov edx,[esp+16] ; color |
test edx,0x80000000 |
jz nodbglvga |
; no color glide for VGA - set to half glide |
shr ebx,1 ; H/2 |
sub edx,ebx |
mov [esp+16],edx |
mov ebx,[esp+0] ; reset to H |
nodbglvga: |
; check limits ? |
push eax |
push ecx |
mov eax,[0x3010] |
mov ecx,[eax+draw_data-0x3000+0] |
cmp ecx,0 |
jnz dbcblimitlset_vga2 |
mov ecx,[eax+draw_data-0x3000+4] |
cmp ecx,0 |
jnz dbcblimitlset_vga2 |
mov ecx,[eax+draw_data-0x3000+8] |
cmp ecx,[0xfe00] |
jnz dbcblimitlset_vga2 |
mov ecx,[eax+draw_data-0x3000+12] |
cmp ecx,[0xfe04] |
jnz dbcblimitlset_vga2 |
pop ecx |
pop eax |
push dword 0 |
jmp dbnewpivga |
dbcblimitlset_vga2: |
pop ecx ; x+Xwin |
pop eax ; B |
push dword 1 |
dbnewpivga: |
push eax; B |
push ebx ; H |
push edi |
push esi |
push ecx ; x+Xwin |
mov ebx,[0x3010] |
movzx ebx,byte[ebx+0xe] |
cld |
dbnpvga: |
mov dl,[ds:ebp] |
cmp dl,bl |
jnz dbimpvgano |
; mov edx,[esp+5*4] ; check limit? |
; cmp edx,0 |
; jz dbimpvgayes |
; call voodoodbcplimit |
; jnz dbimpvgano |
; dbimpvgayes: |
push eax ; B |
push ebx |
push ecx ; x+Xwin |
mov eax,[esp+12+20+16+4] ; color |
mov ebx,eax |
mov [esi],bx ; write LFB pixel |
shr ebx,16 |
mov [esi+2],bl |
and ecx,0x07 ; modulo 8 |
call setvgapixel ; eax=color, ecx=x%8, edi=VGA address |
pop ecx |
pop ebx |
pop eax |
dbimpvgano: |
add esi,4 ; ptrLFB+=4 |
inc ebp ; address buffer |
inc ecx ; x posn++ |
test ecx,0x07 ; test modulo 8 |
jnz dbvgacont |
inc edi ; VGA screen ptr++ |
dbvgacont: |
dec eax ; B-- NB ecx in Vesa20 fn? |
jnz dbnpvga |
dbnpvgad: |
pop ecx |
pop esi |
pop edi |
pop ebx |
pop eax |
add esi,[0xfe08] ; ptrLFB+=BytesPerScanLine |
add edi,640/8 ; ptrScreen+=BytesPerScanLine |
add ebp,[0xfe00] ; |
sub ebp, eax ; was ecx in vesa20 fn? |
inc ebp ; ptrBuffer:=ptrBuffer-B+BytesPerLine+1 |
dec ebx ; H-- |
jz nodbnewpivga ; H<>0 |
jmp dbnewpivga |
nodbnewpivga: |
add esp,7*4 ; NB includes limit check flag |
;pop ebx |
;pop eax |
;pop edi |
;pop esi |
pop ebp |
;pop edx |
;pop ecx |
ret |
vga_drawbackground_tiled: |
push ebp |
push eax |
push ebx |
push ecx |
push edx |
mov edx,dword [0x400000-8] ; B |
add edx,dword [WinMapAddress-8] ; +B |
add edx,dword [WinMapAddress-8] ; +B |
push edx |
mov eax,[draw_data+32+0] ; x start:=(x+Xwin) |
mov ebx,[draw_data+32+4] ; y start:=(y+Ywin) |
mov ecx,eax |
mov edx,ebx |
imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine |
shl ecx,2 ; (x+Xwin)*BytesPerPixel |
add ecx,edx ; |
mov ebp,ecx ; store copy |
add ecx,[0xfe80] ; +AddrLFB |
;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr |
shr ebp,5 ; change from 4 to 1/8 BytesPerPixel |
add ebp,0xa0000 ; + VGABasePtr |
;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrV |
call calculate_edi |
dp3vga: ; MAIN LOOP |
cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1) |
je ybgpvga |
jmp nbgpvga |
ybgpvga: |
push eax ; x |
push ebx ; y |
push ecx ; LFB address |
mov ecx,dword [WinMapAddress-8] ; B |
xor edx,edx ; edx:=0 |
div ecx ; Xstart/B |
; eax=Int(qn) edx:=Rem |
lea esi,[edx+edx*2] ; esi:=edx*3 |
mov ecx,dword [WinMapAddress-4] ; ecx:=H |
mov eax,[esp+4] ; eax:=Ystart |
xor edx,edx ; |
div ecx ; Ystart/H |
mov eax,edx ; eax:=Rem |
xor edx,edx ; |
mov ebx,[esp+12] ; ebx:=B*3 |
mul ebx ; |
add esi,eax ; |
mov eax,[esi+0x300000] ; color |
and eax,0xffffff |
mov ecx, [esp] ; LFB address |
mov ebx,eax ; copy color |
mov [ecx],bx |
shr ebx,16 |
mov [ecx+2],bl |
xchg edi, ebp |
mov ecx,[esp+8] ; x position |
and ecx,0x07 ; x modulo 8 |
call setvgapixel ; eax=color, ecx=x%8, edi=VGA address |
xchg ebp, edi |
pop ecx |
pop ebx |
pop eax |
nbgpvga: |
inc eax ; x++ |
cmp eax,[draw_data+32+8] ; X > xend? |
jg nodp3vga |
test eax,0x07 ; x test modulo 8 |
jnz hook1vga |
inc ebp ; VGA address++ |
hook1vga: |
add ecx,4 ; LFB address += 4 |
inc edi ; ptrBuffer++ |
add esi,3 ; ptrImage+=3 |
jmp dp3vga |
nodp3vga: |
mov eax,[draw_data+32+0] ; x+Xwin |
inc ebx ; y position |
mov ecx,eax |
mov edx,ebx |
imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine |
shl ecx,2 ; (x+Xwin)*BytesPerPixel |
add ecx,edx ; |
mov ebp,ecx ; store copy |
add ecx,[0xfe80] ; +AddrLFB |
;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr |
shr ebp,5 ; change from 4 to 1/8 BytesPerPixel |
add ebp,0xa0000 ; + VGABasePtr |
;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrV |
call calculate_edi |
cmp ebx,[draw_data+32+12] ; Y > yend |
jg dp4vga |
jmp dp3vga |
dp4vga: |
add esp,4 |
pop edx |
pop ecx |
pop ebx |
pop eax |
pop ebp |
ret |
; ---------- |
vga_drawbackground_stretch: |
push ebp |
push eax |
push ebx |
push ecx |
push edx |
mov edx,dword [WinMapAddress-8] ; B |
add edx,dword [WinMapAddress-8] ; +B |
add edx,dword [WinMapAddress-8] ; +B |
push edx |
mov eax,[draw_data+32+0] ; x start:=(x+Xwin) |
mov ebx,[draw_data+32+4] ; y start:=(y+Ywin) |
mov ecx,eax |
mov edx,ebx |
imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine |
shl ecx,2 ; (x+Xwin)*BytesPerPixel |
add ecx,edx ; |
mov ebp,ecx ; store copy |
add ecx,[0xfe80] ; +AddrLFB |
;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr |
shr ebp,5 ; change from 4 to 1/8 BytesPerPixel |
add ebp,0xa0000 ; + VGABasePtr |
;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrV |
call calculate_edi |
sdp3vga: ; MAIN LOOP |
cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1) |
je sybgpvga |
jmp snbgpvga |
sybgpvga: |
push eax ; x |
push ebx ; y |
push ecx ; LFB address |
mov eax,dword [WinMapAddress-8] ; B |
xor edx,edx |
mov ebx,[esp+8] ; Xstart |
mul ebx ; B*Xstart |
xor edx,edx |
mov ebx,[0xfe00] ; x screen width |
div ebx ; B*Xstart/xwidth |
lea esi,[eax+eax*2] ; *3 |
mov eax,dword [WinMapAddress-4] ; H |
xor edx,edx |
mov ebx,[esp+4] ; Ystart |
mul ebx ; H*Ystart |
xor edx,edx |
mov ebx,[0xfe04] ; y screen height |
div ebx ; H*Ystart/yheight |
xor edx,edx |
mov ebx,[esp+12] ; B*3 |
mul ebx ; |
add esi,eax |
mov eax,[esi+0x300000] ; color |
and eax,0xffffff |
mov ecx, [esp] ; LFB address |
mov ebx,eax ; copy color |
mov [ecx],bx |
shr ebx,16 |
mov [ecx+2],bl |
xchg edi, ebp |
mov ecx,[esp+8] ; x position |
and ecx,0x07 ; x modulo 8 |
call setvgapixel ; eax=color, ecx=x%8, edi=VGA address |
xchg ebp, edi ; ebp+=3 |
pop ecx |
pop ebx |
pop eax |
snbgpvga: |
inc eax ; x++ |
cmp eax,[draw_data+32+8] ; X > xend? |
jg snodp3vga |
test eax,0x07 ; x test modulo 8 |
jnz shook1vga |
inc ebp ; VGA address++ |
shook1vga: |
add ecx,4 ; LFB address += 4 |
inc edi ; ptrBuffer++ |
add esi,3 ; ptrImage+=3 |
jmp sdp3vga |
snodp3vga: |
mov eax,[draw_data+32+0] ; x+Xwin |
inc ebx ; y position |
mov ecx,eax |
mov edx,ebx |
imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine |
shl ecx,2 ; (x+Xwin)*BytesPerPixel |
add ecx,edx ; |
mov ebp,ecx ; store copy |
add ecx,[0xfe80] ; +AddrLFB |
;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr |
shr ebp,5 ; change from 4 to 1/8 BytesPerPixel |
add ebp,0xa0000 ; + VGABasePtr |
;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+A |
call calculate_edi |
cmp ebx,[draw_data+32+12] ; Y > yend |
jg sdp4vga |
jmp sdp3vga |
sdp4vga: |
add esp,4 |
pop edx |
pop ecx |
pop ebx |
pop eax |
pop ebp |
ret |
/kernel/trunk/vmodeint.inc |
---|
0,0 → 1,20 |
; |
; Call of videomode driver's functions |
; |
; (Add in System function 21 (and/or 26) as a subfunction 13) |
; |
; Author: Trans |
; Date: 19.07.2003 |
; |
; Include in MeOS kernel and compile with FASM |
; |
cmp eax,13 ; CALL VIDEOMODE DRIVER FUNCTIONS |
jne .no_vmode_drv_access |
or eax,-1 ; If driver is absent then eax does not change |
call 0x760100 ; Entry point of video driver |
mov [esp+36],eax |
mov [esp+24],ebx |
mov [esp+32],ecx |
; mov [esp+28],edx |
ret |
.no_vmode_drv_access: |
/kernel/trunk/vmodeld.inc |
---|
0,0 → 1,27 |
; |
; Load of videomode driver in memory |
; |
; (driver is located at 0x760000-0x768000 - 32kb) // if this area not occuped anything |
; |
; Author: Trans |
; Date: 19.07.2003 |
; |
; Include in MeOS kernel and compile with FASM |
; |
;vmode db 'VMODE MDR' ; MDR - Menuet Driver |
; must be located after fonts filenames in kernel.asm |
; LOAD VIDEOMODE DRIVER |
; If vmode.mdr file not found |
or eax,-1 ; Driver ID = -1 (not present in system) |
mov [0x760000],eax ; |
mov [0x760100],byte 0xC3 ; Instruction RETN - driver loop |
mov eax,vmode ; File name of driver |
mov esi,12 |
mov ebx,0 |
mov ecx,26000 |
mov edx,0x760000 ; Memory position of driver |
call fileread |
/kernel/trunk |
---|
Property changes: |
Added: svn:ignore |
+*.mnt |
+lang.inc |
+*.bat |
+out.txt |
+scin* |